diff --git a/src/device_controller/device_controller.h b/src/device_controller/device_controller.h new file mode 100644 index 0000000..ff9c41f --- /dev/null +++ b/src/device_controller/device_controller.h @@ -0,0 +1,44 @@ +/* + * @Author: DI JUNKUN + * @Date: 2023-12-14 + * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _DEVICE_CONTROLLER_H_ +#define _DEVICE_CONTROLLER_H_ + +#include + +typedef enum { mouse = 0, keyboard } ControlType; +typedef enum { move = 0, left_down, left_up, right_down, right_up } MouseFlag; +typedef enum { key_down = 0, key_up } KeyFlag; +typedef struct { + size_t x; + size_t y; + MouseFlag flag; +} Mouse; + +typedef struct { + size_t key_value; + KeyFlag flag; +} Key; + +typedef struct { + ControlType type; + union { + Mouse m; + Key k; + }; +} RemoteAction; + +class DeviceController { + public: + virtual ~DeviceController() {} + + public: + virtual int Init(int screen_width, int screen_height) = 0; + virtual int Destroy() = 0; + virtual int SendCommand(RemoteAction remote_action) = 0; +}; + +#endif \ No newline at end of file diff --git a/src/device_controller/device_controller_factory.h b/src/device_controller/device_controller_factory.h new file mode 100644 index 0000000..c6e0494 --- /dev/null +++ b/src/device_controller/device_controller_factory.h @@ -0,0 +1,33 @@ +/* + * @Author: DI JUNKUN + * @Date: 2023-12-14 + * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _DEVICE_CONTROLLER_FACTORY_H_ +#define _DEVICE_CONTROLLER_FACTORY_H_ + +#include "device_controller.h" +#include "mouse_controller.h" + +class DeviceControllerFactory { + public: + enum Device { Mouse, Keyboard }; + + public: + virtual ~DeviceControllerFactory() {} + + public: + DeviceController* Create(Device device) { + switch (device) { + case Mouse: + return new MouseController(); + case Keyboard: + return nullptr; + default: + return nullptr; + } + } +}; + +#endif \ No newline at end of file diff --git a/src/device_controller/mouse/linux/mouse_controller.cpp b/src/device_controller/mouse/linux/mouse_controller.cpp new file mode 100644 index 0000000..4c65a1c --- /dev/null +++ b/src/device_controller/mouse/linux/mouse_controller.cpp @@ -0,0 +1,122 @@ +#include "mouse_controller.h" + +#include "log.h" + +MouseController::MouseController() {} + +MouseController::~MouseController() {} + +int MouseController::Init(int screen_width, int screen_height) { + screen_width_ = screen_width; + screen_height_ = screen_height; + + uinput_fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (uinput_fd_ < 0) { + LOG_ERROR("Cannot open device: /dev/uinput"); + } + + ioctl(uinput_fd_, UI_SET_EVBIT, EV_KEY); + ioctl(uinput_fd_, UI_SET_KEYBIT, BTN_RIGHT); + ioctl(uinput_fd_, UI_SET_KEYBIT, BTN_LEFT); + ioctl(uinput_fd_, UI_SET_EVBIT, EV_ABS); + ioctl(uinput_fd_, UI_SET_ABSBIT, ABS_X); + ioctl(uinput_fd_, UI_SET_ABSBIT, ABS_Y); + ioctl(uinput_fd_, UI_SET_EVBIT, EV_REL); + + struct uinput_user_dev uidev; + memset(&uidev, 0, sizeof(uidev)); + snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "VirtualMouse"); + uidev.id.bustype = BUS_USB; + uidev.id.version = 1; + uidev.id.vendor = 0x1; + uidev.id.product = 0x1; + uidev.absmin[ABS_X] = 0; + uidev.absmax[ABS_X] = screen_width_; + uidev.absmin[ABS_Y] = 0; + uidev.absmax[ABS_Y] = screen_height_; + + write(uinput_fd_, &uidev, sizeof(uidev)); + ioctl(uinput_fd_, UI_DEV_CREATE); + return 0; +} + +int MouseController::Destroy() { + ioctl(uinput_fd_, UI_DEV_DESTROY); + close(uinput_fd_); +} + +int MouseController::SendCommand(RemoteAction remote_action) { + int mouse_pos_x = remote_action.m.x * screen_width_ / 1280; + int mouse_pos_y = remote_action.m.y * screen_height_ / 720; + + if (remote_action.type == ControlType::mouse) { + struct input_event event; + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, NULL); + + if (remote_action.m.flag == MouseFlag::left_down) { + SimulateKeyDown(uinput_fd_, BTN_LEFT); + } else if (remote_action.m.flag == MouseFlag::left_up) { + SimulateKeyUp(uinput_fd_, BTN_LEFT); + } else if (remote_action.m.flag == MouseFlag::right_down) { + SimulateKeyDown(uinput_fd_, BTN_RIGHT); + } else if (remote_action.m.flag == MouseFlag::right_up) { + SimulateKeyUp(uinput_fd_, BTN_RIGHT); + } else { + SetMousePosition(uinput_fd_, mouse_pos_x, mouse_pos_y); + } + } + + return 0; +} + +void MouseController::SimulateKeyDown(int fd, int kval) { + struct input_event event; + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, 0); + + event.type = EV_KEY; + event.value = 1; + event.code = kval; + write(fd, &event, sizeof(event)); + + event.type = EV_SYN; + event.value = 0; + event.code = SYN_REPORT; + write(fd, &event, sizeof(event)); +} + +void MouseController::SimulateKeyUp(int fd, int kval) { + struct input_event event; + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, 0); + + event.type = EV_KEY; + event.value = 0; + event.code = kval; + write(fd, &event, sizeof(event)); + + event.type = EV_SYN; + event.value = 0; + event.code = SYN_REPORT; + write(fd, &event, sizeof(event)); +} + +void MouseController::SetMousePosition(int fd, int x, int y) { + struct input_event ev[2], ev_sync; + memset(ev, 0, sizeof(ev)); + memset(&ev_sync, 0, sizeof(ev_sync)); + + ev[0].type = EV_ABS; + ev[0].code = ABS_X; + ev[0].value = x; + ev[1].type = EV_ABS; + ev[1].code = ABS_Y; + ev[1].value = y; + int res_w = write(fd, ev, sizeof(ev)); + + ev_sync.type = EV_SYN; + ev_sync.value = 0; + ev_sync.code = 0; + int res_ev_sync = write(fd, &ev_sync, sizeof(ev_sync)); +} \ No newline at end of file diff --git a/src/device_controller/mouse/linux/mouse_controller.h b/src/device_controller/mouse/linux/mouse_controller.h new file mode 100644 index 0000000..f31fa44 --- /dev/null +++ b/src/device_controller/mouse/linux/mouse_controller.h @@ -0,0 +1,41 @@ +/* + * @Author: DI JUNKUN + * @Date: 2023-12-14 + * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _MOUSE_CONTROLLER_H_ +#define _MOUSE_CONTROLLER_H_ + +#include +#include +#include +#include +#include +#include + +#include "device_controller.h" + +class MouseController : public DeviceController { + public: + MouseController(); + virtual ~MouseController(); + + public: + virtual int Init(int screen_width, int screen_height); + virtual int Destroy(); + virtual int SendCommand(RemoteAction remote_action); + + private: + void SimulateKeyDown(int fd, int kval); + void SimulateKeyUp(int fd, int kval); + void SetMousePosition(int fd, int x, int y); + + private: + int uinput_fd_; + struct uinput_user_dev uinput_dev_; + int screen_width_ = 0; + int screen_height_ = 0; +}; + +#endif \ No newline at end of file diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 9b3fa7b..5d02ab0 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -56,6 +56,7 @@ extern "C" { #include "screen_capture_avf.h" #endif #include "../../thirdparty/projectx/src/interface/x.h" +#include "device_controller_factory.h" #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 @@ -170,6 +171,9 @@ ScreenCaptureX11 *screen_capture = nullptr; ScreenCaptureAvf *screen_capture = nullptr; #endif +DeviceControllerFactory *device_controller_factory = nullptr; +MouseController *mouse_controller = nullptr; + char *nv12_buffer = nullptr; #ifdef __linux__ @@ -186,27 +190,26 @@ static std::atomic mouse_pos_y_last = -65535; std::chrono::steady_clock::time_point last_frame_time_; #endif -typedef enum { mouse = 0, keyboard } ControlType; -typedef enum { move = 0, left_down, left_up, right_down, right_up } MouseFlag; -typedef enum { key_down = 0, key_up } KeyFlag; -typedef struct { - size_t x; - size_t y; - MouseFlag flag; -} Mouse; +// typedef enum { mouse = 0, keyboard } ControlType; +// typedef enum { move = 0, left_down, left_up, right_down, right_up } +// MouseFlag; typedef enum { key_down = 0, key_up } KeyFlag; typedef struct { +// size_t x; +// size_t y; +// MouseFlag flag; +// } Mouse; -typedef struct { - size_t key_value; - KeyFlag flag; -} Key; +// typedef struct { +// size_t key_value; +// KeyFlag flag; +// } Key; -typedef struct { - ControlType type; - union { - Mouse m; - Key k; - }; -} RemoteAction; +// typedef struct { +// ControlType type; +// union { +// Mouse m; +// Key k; +// }; +// } RemoteAction; inline int ProcessMouseKeyEven(SDL_Event &ev) { float ratio = 1280.0 / window_w; @@ -582,30 +585,31 @@ void ServerReceiveDataBuffer(const char *data, size_t size, const char *user_id, CFRelease(mouse_event); } #elif __linux__ - if (remote_action.type == ControlType::mouse) { - struct input_event event; - memset(&event, 0, sizeof(event)); - gettimeofday(&event.time, NULL); + // if (remote_action.type == ControlType::mouse) { + // struct input_event event; + // memset(&event, 0, sizeof(event)); + // gettimeofday(&event.time, NULL); - if (remote_action.m.flag == MouseFlag::left_down) { - simulate_key_down(uinput_fd, BTN_LEFT); - } else if (remote_action.m.flag == MouseFlag::left_up) { - simulate_key_up(uinput_fd, BTN_LEFT); - } else if (remote_action.m.flag == MouseFlag::right_down) { - simulate_key_down(uinput_fd, BTN_RIGHT); - } else if (remote_action.m.flag == MouseFlag::right_up) { - simulate_key_up(uinput_fd, BTN_RIGHT); - } else { - mouseSetPosition(uinput_fd, mouse_pos_x, mouse_pos_y); - // simulate_mouse(uinput_fd, rel_x, rel_y); - // simulate_mouse_abs(uinput_fd, 65535, 65535); - mouse_pos_x_last = mouse_pos_x; - mouse_pos_y_last = mouse_pos_y; - } + // if (remote_action.m.flag == MouseFlag::left_down) { + // simulate_key_down(uinput_fd, BTN_LEFT); + // } else if (remote_action.m.flag == MouseFlag::left_up) { + // simulate_key_up(uinput_fd, BTN_LEFT); + // } else if (remote_action.m.flag == MouseFlag::right_down) { + // simulate_key_down(uinput_fd, BTN_RIGHT); + // } else if (remote_action.m.flag == MouseFlag::right_up) { + // simulate_key_up(uinput_fd, BTN_RIGHT); + // } else { + // mouseSetPosition(uinput_fd, mouse_pos_x, mouse_pos_y); + // // simulate_mouse(uinput_fd, rel_x, rel_y); + // // simulate_mouse_abs(uinput_fd, 65535, 65535); + // mouse_pos_x_last = mouse_pos_x; + // mouse_pos_y_last = mouse_pos_y; + // } - // report_key(EV_KEY, KEY_A, 1); // Report BUTTON A CLICK - PRESS event - // report_key(EV_KEY, KEY_A, 0); - } + // // report_key(EV_KEY, KEY_A, 1); // Report BUTTON A CLICK - PRESS event + // // report_key(EV_KEY, KEY_A, 0); + // } + mouse_controller->SendCommand(remote_action); #endif #endif } @@ -1018,35 +1022,10 @@ int main() { screen_capture->Start(); #elif __linux__ - { - uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); - if (uinput_fd < 0) { - LOG_ERROR("Cannot open device: /dev/uinput"); - } - - ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY); - ioctl(uinput_fd, UI_SET_KEYBIT, BTN_RIGHT); - ioctl(uinput_fd, UI_SET_KEYBIT, BTN_LEFT); - ioctl(uinput_fd, UI_SET_EVBIT, EV_ABS); - ioctl(uinput_fd, UI_SET_ABSBIT, ABS_X); - ioctl(uinput_fd, UI_SET_ABSBIT, ABS_Y); - ioctl(uinput_fd, UI_SET_EVBIT, EV_REL); - - struct uinput_user_dev uidev; - memset(&uidev, 0, sizeof(uidev)); - snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "VirtualMouse"); - uidev.id.bustype = BUS_USB; - uidev.id.version = 1; - uidev.id.vendor = 0x1; - uidev.id.product = 0x1; - uidev.absmin[ABS_X] = 0; - uidev.absmax[ABS_X] = screen_w; - uidev.absmin[ABS_Y] = 0; - uidev.absmax[ABS_Y] = screen_h; - - write(uinput_fd, &uidev, sizeof(uidev)); - ioctl(uinput_fd, UI_DEV_CREATE); - } + device_controller_factory = new DeviceControllerFactory(); + mouse_controller = (MouseController *)device_controller_factory->Create( + DeviceControllerFactory::Device::Mouse); + mouse_controller->Init(screen_w, screen_h); screen_capture = new ScreenCaptureX11(); @@ -1394,10 +1373,7 @@ int main() { SDL_CloseAudioDevice(output_dev); SDL_CloseAudioDevice(input_dev); -#ifdef __linux__ - ioctl(uinput_fd, UI_DEV_DESTROY); - close(uinput_fd); -#endif + mouse_controller->Destroy(); ImGui_ImplSDLRenderer2_Shutdown(); ImGui_ImplSDL2_Shutdown(); diff --git a/xmake.lua b/xmake.lua index 7b83d5e..48fd0e6 100644 --- a/xmake.lua +++ b/xmake.lua @@ -67,9 +67,24 @@ target("screen_capture") add_includedirs("src/screen_capture/linux", {public = true}) end +target("device_controller") + set_kind("object") + add_deps("log") + if is_os("windows") then + -- add_files("src/screen_capture/windows/*.cpp") + -- add_includedirs("src/screen_capture/windows", {public = true}) + elseif is_os("macosx") then + -- add_files("src/screen_capture/macosx/*.cpp") + -- add_includedirs("src/screen_capture/macosx", {public = true}) + elseif is_os("linux") then + add_files("src/device_controller/mouse/linux/*.cpp") + add_includedirs("src/device_controller/mouse/linux", {public = true}) + add_includedirs("src/device_controller", {public = true}) + end + target("remote_desk") set_kind("binary") - add_deps("log", "screen_capture", "projectx") + add_deps("log", "screen_capture", "device_controller", "projectx") add_files("src/gui/main.cpp") -- after_install(function (target)