mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 12:15:34 +08:00
Use factory method to create mouse controller on Linux
This commit is contained in:
44
src/device_controller/device_controller.h
Normal file
44
src/device_controller/device_controller.h
Normal file
@@ -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 <stdio.h>
|
||||||
|
|
||||||
|
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
|
||||||
33
src/device_controller/device_controller_factory.h
Normal file
33
src/device_controller/device_controller_factory.h
Normal file
@@ -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
|
||||||
122
src/device_controller/mouse/linux/mouse_controller.cpp
Normal file
122
src/device_controller/mouse/linux/mouse_controller.cpp
Normal file
@@ -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));
|
||||||
|
}
|
||||||
41
src/device_controller/mouse/linux/mouse_controller.h
Normal file
41
src/device_controller/mouse/linux/mouse_controller.h
Normal file
@@ -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 <fcntl.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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
|
||||||
124
src/gui/main.cpp
124
src/gui/main.cpp
@@ -56,6 +56,7 @@ extern "C" {
|
|||||||
#include "screen_capture_avf.h"
|
#include "screen_capture_avf.h"
|
||||||
#endif
|
#endif
|
||||||
#include "../../thirdparty/projectx/src/interface/x.h"
|
#include "../../thirdparty/projectx/src/interface/x.h"
|
||||||
|
#include "device_controller_factory.h"
|
||||||
|
|
||||||
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
|
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
|
||||||
|
|
||||||
@@ -170,6 +171,9 @@ ScreenCaptureX11 *screen_capture = nullptr;
|
|||||||
ScreenCaptureAvf *screen_capture = nullptr;
|
ScreenCaptureAvf *screen_capture = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DeviceControllerFactory *device_controller_factory = nullptr;
|
||||||
|
MouseController *mouse_controller = nullptr;
|
||||||
|
|
||||||
char *nv12_buffer = nullptr;
|
char *nv12_buffer = nullptr;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@@ -186,27 +190,26 @@ static std::atomic<int> mouse_pos_y_last = -65535;
|
|||||||
std::chrono::steady_clock::time_point last_frame_time_;
|
std::chrono::steady_clock::time_point last_frame_time_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum { mouse = 0, keyboard } ControlType;
|
// typedef enum { mouse = 0, keyboard } ControlType;
|
||||||
typedef enum { move = 0, left_down, left_up, right_down, right_up } MouseFlag;
|
// typedef enum { move = 0, left_down, left_up, right_down, right_up }
|
||||||
typedef enum { key_down = 0, key_up } KeyFlag;
|
// MouseFlag; typedef enum { key_down = 0, key_up } KeyFlag; typedef struct {
|
||||||
typedef struct {
|
// size_t x;
|
||||||
size_t x;
|
// size_t y;
|
||||||
size_t y;
|
// MouseFlag flag;
|
||||||
MouseFlag flag;
|
// } Mouse;
|
||||||
} Mouse;
|
|
||||||
|
|
||||||
typedef struct {
|
// typedef struct {
|
||||||
size_t key_value;
|
// size_t key_value;
|
||||||
KeyFlag flag;
|
// KeyFlag flag;
|
||||||
} Key;
|
// } Key;
|
||||||
|
|
||||||
typedef struct {
|
// typedef struct {
|
||||||
ControlType type;
|
// ControlType type;
|
||||||
union {
|
// union {
|
||||||
Mouse m;
|
// Mouse m;
|
||||||
Key k;
|
// Key k;
|
||||||
};
|
// };
|
||||||
} RemoteAction;
|
// } RemoteAction;
|
||||||
|
|
||||||
inline int ProcessMouseKeyEven(SDL_Event &ev) {
|
inline int ProcessMouseKeyEven(SDL_Event &ev) {
|
||||||
float ratio = 1280.0 / window_w;
|
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);
|
CFRelease(mouse_event);
|
||||||
}
|
}
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
if (remote_action.type == ControlType::mouse) {
|
// if (remote_action.type == ControlType::mouse) {
|
||||||
struct input_event event;
|
// struct input_event event;
|
||||||
memset(&event, 0, sizeof(event));
|
// memset(&event, 0, sizeof(event));
|
||||||
gettimeofday(&event.time, NULL);
|
// gettimeofday(&event.time, NULL);
|
||||||
|
|
||||||
if (remote_action.m.flag == MouseFlag::left_down) {
|
// if (remote_action.m.flag == MouseFlag::left_down) {
|
||||||
simulate_key_down(uinput_fd, BTN_LEFT);
|
// simulate_key_down(uinput_fd, BTN_LEFT);
|
||||||
} else if (remote_action.m.flag == MouseFlag::left_up) {
|
// } else if (remote_action.m.flag == MouseFlag::left_up) {
|
||||||
simulate_key_up(uinput_fd, BTN_LEFT);
|
// simulate_key_up(uinput_fd, BTN_LEFT);
|
||||||
} else if (remote_action.m.flag == MouseFlag::right_down) {
|
// } else if (remote_action.m.flag == MouseFlag::right_down) {
|
||||||
simulate_key_down(uinput_fd, BTN_RIGHT);
|
// simulate_key_down(uinput_fd, BTN_RIGHT);
|
||||||
} else if (remote_action.m.flag == MouseFlag::right_up) {
|
// } else if (remote_action.m.flag == MouseFlag::right_up) {
|
||||||
simulate_key_up(uinput_fd, BTN_RIGHT);
|
// simulate_key_up(uinput_fd, BTN_RIGHT);
|
||||||
} else {
|
// } else {
|
||||||
mouseSetPosition(uinput_fd, mouse_pos_x, mouse_pos_y);
|
// mouseSetPosition(uinput_fd, mouse_pos_x, mouse_pos_y);
|
||||||
// simulate_mouse(uinput_fd, rel_x, rel_y);
|
// // simulate_mouse(uinput_fd, rel_x, rel_y);
|
||||||
// simulate_mouse_abs(uinput_fd, 65535, 65535);
|
// // simulate_mouse_abs(uinput_fd, 65535, 65535);
|
||||||
mouse_pos_x_last = mouse_pos_x;
|
// mouse_pos_x_last = mouse_pos_x;
|
||||||
mouse_pos_y_last = mouse_pos_y;
|
// 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, 1); // Report BUTTON A CLICK - PRESS event
|
||||||
// report_key(EV_KEY, KEY_A, 0);
|
// // report_key(EV_KEY, KEY_A, 0);
|
||||||
}
|
// }
|
||||||
|
mouse_controller->SendCommand(remote_action);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1018,35 +1022,10 @@ int main() {
|
|||||||
screen_capture->Start();
|
screen_capture->Start();
|
||||||
|
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
{
|
device_controller_factory = new DeviceControllerFactory();
|
||||||
uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
mouse_controller = (MouseController *)device_controller_factory->Create(
|
||||||
if (uinput_fd < 0) {
|
DeviceControllerFactory::Device::Mouse);
|
||||||
LOG_ERROR("Cannot open device: /dev/uinput");
|
mouse_controller->Init(screen_w, screen_h);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
screen_capture = new ScreenCaptureX11();
|
screen_capture = new ScreenCaptureX11();
|
||||||
|
|
||||||
@@ -1394,10 +1373,7 @@ int main() {
|
|||||||
SDL_CloseAudioDevice(output_dev);
|
SDL_CloseAudioDevice(output_dev);
|
||||||
SDL_CloseAudioDevice(input_dev);
|
SDL_CloseAudioDevice(input_dev);
|
||||||
|
|
||||||
#ifdef __linux__
|
mouse_controller->Destroy();
|
||||||
ioctl(uinput_fd, UI_DEV_DESTROY);
|
|
||||||
close(uinput_fd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ImGui_ImplSDLRenderer2_Shutdown();
|
ImGui_ImplSDLRenderer2_Shutdown();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
|
|||||||
17
xmake.lua
17
xmake.lua
@@ -67,9 +67,24 @@ target("screen_capture")
|
|||||||
add_includedirs("src/screen_capture/linux", {public = true})
|
add_includedirs("src/screen_capture/linux", {public = true})
|
||||||
end
|
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")
|
target("remote_desk")
|
||||||
set_kind("binary")
|
set_kind("binary")
|
||||||
add_deps("log", "screen_capture", "projectx")
|
add_deps("log", "screen_capture", "device_controller", "projectx")
|
||||||
add_files("src/gui/main.cpp")
|
add_files("src/gui/main.cpp")
|
||||||
|
|
||||||
-- after_install(function (target)
|
-- after_install(function (target)
|
||||||
|
|||||||
Reference in New Issue
Block a user