Fix camera movement not working in games when using mouse

This commit is contained in:
loki 2019-12-23 19:39:24 +01:00
parent 29edc88294
commit 63de33e62a
4 changed files with 158 additions and 78 deletions

0
sunshine/move_by_copy.h Executable file → Normal file
View File

View File

@ -19,8 +19,12 @@ using evdev_t = util::safe_ptr<libevdev, libevdev_free>;
using uinput_t = util::safe_ptr<libevdev_uinput, libevdev_uinput_destroy>; using uinput_t = util::safe_ptr<libevdev_uinput, libevdev_uinput_destroy>;
struct input_raw_t { struct input_raw_t {
evdev_t dev; evdev_t gamepad_dev;
uinput_t uinput; uinput_t gamepad_input;
evdev_t mouse_dev;
uinput_t mouse_input;
display_t display; display_t display;
gamepad_state_t gamepad_state; gamepad_state_t gamepad_state;
@ -42,36 +46,49 @@ struct display_attr_t {
}; };
void move_mouse(input_t &input, int deltaX, int deltaY) { void move_mouse(input_t &input, int deltaX, int deltaY) {
auto &disp = *((display_attr_t *) ((input_raw_t*)input.get())->display.get()); auto mouse = ((input_raw_t*)input.get())->mouse_input.get();
XWarpPointer(disp.display, None, None, 0, 0, 0, 0, deltaX, deltaY); if(deltaX) {
XFlush(disp.display); libevdev_uinput_write_event(mouse, EV_REL, REL_X, deltaX);
}
if(deltaY) {
libevdev_uinput_write_event(mouse, EV_REL, REL_Y, deltaY);
}
libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0);
} }
void button_mouse(input_t &input, int button, bool release) { void button_mouse(input_t &input, int button, bool release) {
auto &disp = *((display_attr_t *) ((input_raw_t*)input.get())->display.get()); int btn_type;
int scan;
XTestFakeButtonEvent(disp.display, button, !release, CurrentTime); if(button == 1) {
btn_type = BTN_LEFT;
XFlush(disp.display); scan = 90001;
} }
else if(button == 2) {
void scroll(input_t &input, int distance) { btn_type = BTN_MIDDLE;
auto &disp = *((display_attr_t *) ((input_raw_t*)input.get())->display.get()); scan = 90003;
}
int button = distance > 0 ? 4 : 5; else {
btn_type = BTN_RIGHT;
distance = std::abs(distance / 120); scan = 90002;
while(distance > 0) {
--distance;
XTestFakeButtonEvent(disp.display, button, True, CurrentTime);
XTestFakeButtonEvent(disp.display, button, False, CurrentTime);
XSync(disp.display, 0);
} }
XFlush(disp.display); auto mouse = ((input_raw_t*)input.get())->mouse_input.get();
libevdev_uinput_write_event(mouse, EV_MSC, MSC_SCAN, scan);
libevdev_uinput_write_event(mouse, EV_KEY, btn_type, release ? 0 : 1);
libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0);
}
void scroll(input_t &input, int high_res_distance) {
int distance = high_res_distance / 120;
auto mouse = ((input_raw_t*)input.get())->mouse_input.get();
libevdev_uinput_write_event(mouse, EV_REL, REL_WHEEL, distance);
libevdev_uinput_write_event(mouse, EV_REL, REL_WHEEL_HI_RES, high_res_distance);
libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0);
} }
uint16_t keysym(uint16_t modcode) { uint16_t keysym(uint16_t modcode) {
@ -205,92 +222,140 @@ namespace gp {
// up pressed == -1, down pressed == 1, else 0 // up pressed == -1, down pressed == 1, else 0
void dpad_y(input_t &input, int button_state) { void dpad_y(input_t &input, int button_state) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_HAT0Y, button_state); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_HAT0Y, button_state);
} }
// left pressed == -1, right pressed == 1, else 0 // left pressed == -1, right pressed == 1, else 0
void dpad_x(input_t &input, int button_state) { void dpad_x(input_t &input, int button_state) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_HAT0X, button_state); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_HAT0X, button_state);
} }
void start(input_t &input, int button_down) { void start(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_START, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_START, button_down);
} }
void back(input_t &input, int button_down) { void back(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_SELECT, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_SELECT, button_down);
} }
void left_stick(input_t &input, int button_down) { void left_stick(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_THUMBL, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_THUMBL, button_down);
} }
void right_stick(input_t &input, int button_down) { void right_stick(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_THUMBR, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_THUMBR, button_down);
} }
void left_button(input_t &input, int button_down) { void left_button(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_TL, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_TL, button_down);
} }
void right_button(input_t &input, int button_down) { void right_button(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_TR, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_TR, button_down);
} }
void home(input_t &input, int button_down) { void home(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_MODE, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_MODE, button_down);
} }
void a(input_t &input, int button_down) { void a(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_SOUTH, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_SOUTH, button_down);
} }
void b(input_t &input, int button_down) { void b(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_EAST, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_EAST, button_down);
} }
void x(input_t &input, int button_down) { void x(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_NORTH, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_NORTH, button_down);
} }
void y(input_t &input, int button_down) { void y(input_t &input, int button_down) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_KEY, BTN_WEST, button_down); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_KEY, BTN_WEST, button_down);
} }
void left_trigger(input_t &input, std::uint8_t abs_z) { void left_trigger(input_t &input, std::uint8_t abs_z) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_Z, abs_z); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_Z, abs_z);
} }
void right_trigger(input_t &input, std::uint8_t abs_z) { void right_trigger(input_t &input, std::uint8_t abs_z) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_RZ, abs_z); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_RZ, abs_z);
} }
void left_stick_x(input_t &input, std::int16_t x) { void left_stick_x(input_t &input, std::int16_t x) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_X, x); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_X, x);
} }
void left_stick_y(input_t &input, std::int16_t y) { void left_stick_y(input_t &input, std::int16_t y) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_Y, -y); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_Y, -y);
} }
void right_stick_x(input_t &input, std::int16_t x) { void right_stick_x(input_t &input, std::int16_t x) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_RX, x); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_RX, x);
} }
void right_stick_y(input_t &input, std::int16_t y) { void right_stick_y(input_t &input, std::int16_t y) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_ABS, ABS_RY, -y); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_ABS, ABS_RY, -y);
} }
void sync(input_t &input) { void sync(input_t &input) {
auto &gp = *(input_raw_t*)input.get(); auto &gp = *(input_raw_t*)input.get();
libevdev_uinput_write_event(gp.uinput.get(), EV_SYN, SYN_REPORT, 0); libevdev_uinput_write_event(gp.gamepad_input.get(), EV_SYN, SYN_REPORT, 0);
} }
} }
input_t input() { int mouse(input_raw_t &gp) {
input_t result { new input_raw_t() }; gp.mouse_dev.reset(libevdev_new());
auto &gp = *(input_raw_t*)result.get();
gp.dev.reset(libevdev_new()); libevdev_set_uniq(gp.mouse_dev.get(), "Sunshine Gamepad");
libevdev_set_id_product(gp.mouse_dev.get(), 0x4038);
libevdev_set_id_vendor(gp.mouse_dev.get(), 0x46D);
libevdev_set_id_bustype(gp.mouse_dev.get(), 0x3);
libevdev_set_id_version(gp.mouse_dev.get(), 0x111);
libevdev_set_name(gp.mouse_dev.get(), "Logitech Wireless Mouse PID:4038");
libevdev_enable_event_type(gp.mouse_dev.get(), EV_KEY);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_LEFT, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_RIGHT, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_MIDDLE, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_SIDE, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_EXTRA, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_FORWARD, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_BACK, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, BTN_TASK, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 280, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 281, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 282, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 283, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 284, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 285, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 286, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_KEY, 287, nullptr);
libevdev_enable_event_type(gp.mouse_dev.get(), EV_REL);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_REL, REL_X, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_REL, REL_Y, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_REL, REL_WHEEL, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_REL, REL_WHEEL_HI_RES, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_REL, REL_HWHEEL, nullptr);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_REL, REL_HWHEEL_HI_RES, nullptr);
libevdev_enable_event_type(gp.mouse_dev.get(), EV_MSC);
libevdev_enable_event_code(gp.mouse_dev.get(), EV_MSC, MSC_SCAN, nullptr);
libevdev_uinput *buf;
int err = libevdev_uinput_create_from_device(gp.mouse_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &buf);
gp.mouse_input.reset(buf);
if(err) {
std::cout << "Could not create Sunshine Mouse: "sv << strerror(-err) << std::endl;
return -1;
}
return 0;
}
int gamepad(input_raw_t &gp) {
gp.gamepad_dev.reset(libevdev_new());
input_absinfo stick { input_absinfo stick {
0, 0,
@ -316,42 +381,57 @@ input_t input() {
0 0
}; };
libevdev_set_uniq(gp.dev.get(), "Sunshine Gamepad"); libevdev_set_uniq(gp.gamepad_dev.get(), "Sunshine Gamepad");
libevdev_set_id_product(gp.dev.get(), 0x28E); libevdev_set_id_product(gp.gamepad_dev.get(), 0x28E);
libevdev_set_id_vendor(gp.dev.get(), 0x45E); libevdev_set_id_vendor(gp.gamepad_dev.get(), 0x45E);
libevdev_set_id_bustype(gp.dev.get(), 0x3); libevdev_set_id_bustype(gp.gamepad_dev.get(), 0x3);
libevdev_set_id_version(gp.dev.get(), 0x110); libevdev_set_id_version(gp.gamepad_dev.get(), 0x110);
libevdev_set_name(gp.dev.get(), "Microsoft X-Box 360 pad"); libevdev_set_name(gp.gamepad_dev.get(), "Microsoft X-Box 360 pad");
libevdev_enable_event_type(gp.dev.get(), EV_KEY); libevdev_enable_event_type(gp.gamepad_dev.get(), EV_KEY);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_WEST, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_WEST, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_EAST, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_EAST, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_NORTH, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_NORTH, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_SOUTH, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_SOUTH, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_THUMBL, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_THUMBL, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_THUMBR, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_THUMBR, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_TR, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_TR, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_TL, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_TL, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_SELECT, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_SELECT, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_MODE, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_MODE, nullptr);
libevdev_enable_event_code(gp.dev.get(), EV_KEY, BTN_START, nullptr); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_KEY, BTN_START, nullptr);
libevdev_enable_event_type(gp.dev.get(), EV_ABS); libevdev_enable_event_type(gp.gamepad_dev.get(), EV_ABS);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_HAT0Y, &dpad); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_HAT0Y, &dpad);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_HAT0X, &dpad); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_HAT0X, &dpad);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_Z, &trigger); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_Z, &trigger);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_RZ, &trigger); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_RZ, &trigger);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_X, &stick); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_X, &stick);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_RX, &stick); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_RX, &stick);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_Y, &stick); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_Y, &stick);
libevdev_enable_event_code(gp.dev.get(), EV_ABS, ABS_RY, &stick); libevdev_enable_event_code(gp.gamepad_dev.get(), EV_ABS, ABS_RY, &stick);
libevdev_uinput *buf; libevdev_uinput *buf;
int err = libevdev_uinput_create_from_device(gp.dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &buf); int err = libevdev_uinput_create_from_device(gp.gamepad_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &buf);
gp.uinput.reset(buf); gp.gamepad_input.reset(buf);
if(err) { if(err) {
std::cout << "Could not create Sunshine Gamepad: "sv << strerror(-err) << std::endl; std::cout << "Could not create Sunshine Gamepad: "sv << strerror(-err) << std::endl;
return -1;
}
return 0;
}
input_t input() {
input_t result { new input_raw_t() };
auto &gp = *(input_raw_t*)result.get();
if(gamepad(gp)) {
return nullptr;
}
if(mouse(gp)) {
return nullptr; return nullptr;
} }

0
sunshine/task_pool.h Executable file → Normal file
View File

0
sunshine/thread_pool.h Executable file → Normal file
View File