Skip to content

Instantly share code, notes, and snippets.

@liquidev
Last active December 8, 2019 21:07
Show Gist options
  • Select an option

  • Save liquidev/a9691ed6cef5a2c9d2b36982791d1d20 to your computer and use it in GitHub Desktop.

Select an option

Save liquidev/a9691ed6cef5a2c9d2b36982791d1d20 to your computer and use it in GitHub Desktop.
Turn your joypad to a mouse
cc jm.c -lxdo -lSDL2 -lm -o jm -O3
./jm

Only tested with an Xbox 360 Wireless Controller.

Default bindings:

  • Left joystick - move cursor
  • Right joystick - scroll
  • A - left click
  • X - right click
  • B - middle click
  • triggers
    • left - slow down
    • right - speed up
    • the harder you press the stronger the effect
  • Xbox logo - quit the emulator
/* jm - joystick to mouse */
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL2/SDL.h>
#include <xdo.h>
#define DEADZONE_X_MIN -0.2
#define DEADZONE_X_MAX 0.2
#define DEADZONE_Y_MIN -0.2
#define DEADZONE_Y_MAX 0.2
#define SCROLL_UP(x) x < -0.5
#define SCROLL_DOWN(x) x > 0.5
#define SPEED_BASE 10.0
#define SPEED_DEC 8.0
#define SPEED_INC 20.0
#define BUTTON_LMB 0
#define BUTTON_MMB 1
#define BUTTON_RMB 2
#define BUTTON_MODE 5
#define BUTTON_QUIT 8
int main(void) {
xdo_t *xdo;
SDL_Joystick *js;
SDL_Init(SDL_INIT_JOYSTICK);
xdo = xdo_new(NULL);
if (SDL_NumJoysticks() > 0) {
js = SDL_JoystickOpen(0);
}
int end = 0;
int frame = 0;
while (!end) {
SDL_JoystickUpdate();
#ifdef JM_DEBUG
printf("AXES ");
for (int i = 0; i < SDL_JoystickNumAxes(js); ++i) {
double x = (double)SDL_JoystickGetAxis(js, i) / 32768;
printf("[%i: %f] ", i, x);
}
printf(" BUTTONS ");
for (int i = 0; i < SDL_JoystickNumButtons(js); ++i) {
int x = SDL_JoystickGetButton(js, i);
printf("[%i: %i]", i, x);
}
printf("\n");
#endif
/* events */
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP: {
SDL_JoyButtonEvent btn_event = event.jbutton;
int mouse_button = 0;
switch (btn_event.button) {
case BUTTON_LMB: mouse_button = 1; break;
case BUTTON_MMB: mouse_button = 2; break;
case BUTTON_RMB: mouse_button = 3; break;
}
if (mouse_button != 0) {
if (btn_event.state == SDL_PRESSED) {
xdo_mouse_down(xdo, CURRENTWINDOW, mouse_button);
} else {
xdo_mouse_up(xdo, CURRENTWINDOW, mouse_button);
}
}
} break;
}
}
/* mouse movement */
double x0 = (double)SDL_JoystickGetAxis(js, 0) / 32768;
double y0 = (double)SDL_JoystickGetAxis(js, 1) / 32768;
double x1 = (double)SDL_JoystickGetAxis(js, 3) / 32768;
double y1 = (double)SDL_JoystickGetAxis(js, 4) / 32768;
double z0 = ((double)SDL_JoystickGetAxis(js, 2) / 32768 + 1.0) / 2.0;
double z1 = ((double)SDL_JoystickGetAxis(js, 5) / 32768 + 1.0) / 2.0;
double sensitivity = SPEED_BASE - z0 * SPEED_DEC + z1 * SPEED_INC;
if (x0 < DEADZONE_X_MIN || x0 > DEADZONE_X_MAX) {
xdo_move_mouse_relative(xdo, (int)round(x0 * sensitivity), 0);
}
if (y0 < DEADZONE_X_MIN || y0 > DEADZONE_Y_MAX) {
xdo_move_mouse_relative(xdo, 0, (int)round(y0 * sensitivity));
}
// printf("%i %i\n", frame % 10, (int)(y1 * 5));
if ((int)(1 / y1 * 3) != 0) {
if (frame % (int)(1 / y1 * 3) == 1) {
if (SCROLL_UP(y1)) {
xdo_click_window(xdo, CURRENTWINDOW, 4);
}
if (SCROLL_DOWN(y1)) {
xdo_click_window(xdo, CURRENTWINDOW, 5);
}
}
}
/* buttons */
if (SDL_JoystickGetButton(js, BUTTON_QUIT)) {
end = 1;
}
++frame;
usleep(16666);
}
SDL_JoystickClose(js);
SDL_Quit();
xdo_free(xdo);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment