[feat] cursor mapping in different displays supported

This commit is contained in:
dijunkun
2025-05-15 19:47:08 +08:00
parent 11358e0b60
commit eca4f614c8
10 changed files with 91 additions and 60 deletions

44
src/common/display_info.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-05-15
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _DISPLAY_INFO_H_
#define _DISPLAY_INFO_H_
#include <string>
class DisplayInfo {
public:
DisplayInfo(std::string name, int left, int top, int right, int bottom)
: name(name), left(left), top(top), right(right), bottom(bottom) {
width = right - left;
height = bottom - top;
}
DisplayInfo(void* handle, std::string name, bool is_primary, int left,
int top, int right, int bottom)
: handle(handle),
name(name),
is_primary(is_primary),
left(left),
top(top),
right(right),
bottom(bottom) {
width = right - left;
height = bottom - top;
}
~DisplayInfo() {}
void* handle = nullptr;
std::string name = "";
bool is_primary = false;
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
int width = 0;
int height = 0;
};
#endif

View File

@@ -9,6 +9,8 @@
#include <stdio.h> #include <stdio.h>
#include "display_info.h"
typedef enum { typedef enum {
mouse = 0, mouse = 0,
keyboard, keyboard,

View File

@@ -6,22 +6,26 @@ MouseController::MouseController() {}
MouseController::~MouseController() {} MouseController::~MouseController() {}
int MouseController::Init(int screen_width, int screen_height) { int MouseController::Init(std::vector<DisplayInfo> display_info_list) {
screen_width_ = screen_width; display_info_list_ = display_info_list;
screen_height_ = screen_height;
return 0; return 0;
} }
int MouseController::Destroy() { return 0; } int MouseController::Destroy() { return 0; }
int MouseController::SendMouseCommand(RemoteAction remote_action) { int MouseController::SendMouseCommand(RemoteAction remote_action,
int display_index) {
INPUT ip; INPUT ip;
if (remote_action.type == ControlType::mouse) { if (remote_action.type == ControlType::mouse) {
ip.type = INPUT_MOUSE; ip.type = INPUT_MOUSE;
ip.mi.dx = (LONG)(remote_action.m.x * screen_width_); ip.mi.dx =
ip.mi.dy = (LONG)(remote_action.m.y * screen_height_); (LONG)(remote_action.m.x * display_info_list_[display_index].width) +
display_info_list_[display_index].left;
ip.mi.dy =
(LONG)(remote_action.m.y * display_info_list_[display_index].height) +
display_info_list_[display_index].top;
switch (remote_action.m.flag) { switch (remote_action.m.flag) {
case MouseFlag::left_down: case MouseFlag::left_down:
@@ -58,6 +62,7 @@ int MouseController::SendMouseCommand(RemoteAction remote_action) {
ip.mi.time = 0; ip.mi.time = 0;
SetCursorPos(ip.mi.dx, ip.mi.dy); SetCursorPos(ip.mi.dx, ip.mi.dy);
LOG_ERROR("mouse {}x{}", ip.mi.dx, ip.mi.dy);
if (ip.mi.dwFlags != MOUSEEVENTF_MOVE) { if (ip.mi.dwFlags != MOUSEEVENTF_MOVE) {
SendInput(1, &ip, sizeof(INPUT)); SendInput(1, &ip, sizeof(INPUT));

View File

@@ -7,6 +7,8 @@
#ifndef _MOUSE_CONTROLLER_H_ #ifndef _MOUSE_CONTROLLER_H_
#define _MOUSE_CONTROLLER_H_ #define _MOUSE_CONTROLLER_H_
#include <vector>
#include "device_controller.h" #include "device_controller.h"
class MouseController : public DeviceController { class MouseController : public DeviceController {
@@ -15,13 +17,12 @@ class MouseController : public DeviceController {
virtual ~MouseController(); virtual ~MouseController();
public: public:
virtual int Init(int screen_width, int screen_height); virtual int Init(std::vector<DisplayInfo> display_info_list);
virtual int Destroy(); virtual int Destroy();
virtual int SendMouseCommand(RemoteAction remote_action); virtual int SendMouseCommand(RemoteAction remote_action, int display_index);
private: private:
int screen_width_ = 0; std::vector<DisplayInfo> display_info_list_;
int screen_height_ = 0;
}; };
#endif #endif

View File

@@ -9,35 +9,13 @@
#include <functional> #include <functional>
#include "display_info.h"
class ScreenCapturer { class ScreenCapturer {
public: public:
typedef std::function<void(unsigned char*, int, int, int, int)> typedef std::function<void(unsigned char*, int, int, int, int)>
cb_desktop_data; cb_desktop_data;
class DisplayInfo {
public:
DisplayInfo(std::string name, int left, int top, int right, int bottom)
: name(name), left(left), top(top), right(right), bottom(bottom) {}
DisplayInfo(void* handle, std::string name, bool is_primary, int left,
int top, int right, int bottom)
: handle(handle),
name(name),
is_primary(is_primary),
left(left),
top(top),
right(right),
bottom(bottom) {}
~DisplayInfo() {}
void* handle = nullptr;
std::string name = "";
bool is_primary = false;
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
};
public: public:
virtual ~ScreenCapturer() {} virtual ~ScreenCapturer() {}

View File

@@ -10,7 +10,7 @@
#include "libyuv.h" #include "libyuv.h"
#include "rd_log.h" #include "rd_log.h"
static std::vector<ScreenCapturer::DisplayInfo> gs_display_list; static std::vector<DisplayInfo> gs_display_list;
std::string WideToUtf8(const wchar_t *wideStr) { std::string WideToUtf8(const wchar_t *wideStr) {
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0, int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0,
@@ -37,11 +37,11 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom});
*(HMONITOR *)data = hmonitor; *(HMONITOR *)data = hmonitor;
} else { } else {
gs_display_list.push_back( gs_display_list.push_back(DisplayInfo(
{(void *)hmonitor, WideToUtf8(monitor_info_.szDevice), (void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom));
} }
} }

View File

@@ -369,8 +369,11 @@ int Render::StartMouseController() {
} }
mouse_controller_ = (MouseController*)device_controller_factory_->Create( mouse_controller_ = (MouseController*)device_controller_factory_->Create(
DeviceControllerFactory::Device::Mouse); DeviceControllerFactory::Device::Mouse);
int mouse_controller_init_ret =
mouse_controller_->Init(screen_width_, screen_height_); if (screen_capturer_ && display_info_list_.empty()) {
display_info_list_ = screen_capturer_->GetDisplayInfoList();
}
int mouse_controller_init_ret = mouse_controller_->Init(display_info_list_);
if (0 != mouse_controller_init_ret) { if (0 != mouse_controller_init_ret) {
LOG_INFO("Destroy mouse controller") LOG_INFO("Destroy mouse controller")
mouse_controller_->Destroy(); mouse_controller_->Destroy();
@@ -937,11 +940,11 @@ void Render::MainLoop() {
} }
if (need_to_send_host_info_) { if (need_to_send_host_info_) {
RemoteAction remote_action; if (screen_capturer_ && display_info_list_.empty()) {
if (screen_capturer_) {
display_info_list_ = screen_capturer_->GetDisplayInfoList(); display_info_list_ = screen_capturer_->GetDisplayInfoList();
} }
RemoteAction remote_action;
remote_action.i.display_num = display_info_list_.size(); remote_action.i.display_num = display_info_list_.size();
remote_action.i.display_list = remote_action.i.display_list =
(char**)malloc(remote_action.i.display_num * sizeof(char*)); (char**)malloc(remote_action.i.display_num * sizeof(char*));

View File

@@ -83,7 +83,7 @@ class Render {
int video_height_ = 0; int video_height_ = 0;
int video_width_last_ = 0; int video_width_last_ = 0;
int video_height_last_ = 0; int video_height_last_ = 0;
int selected_display_ = 1; int selected_display_ = 0;
size_t video_size_ = 0; size_t video_size_ = 0;
bool tab_selected_ = false; bool tab_selected_ = false;
bool tab_opened_ = true; bool tab_opened_ = true;
@@ -98,7 +98,7 @@ class Render {
std::string mouse_control_button_label_ = "Mouse Control"; std::string mouse_control_button_label_ = "Mouse Control";
std::string audio_capture_button_label_ = "Audio Capture"; std::string audio_capture_button_label_ = "Audio Capture";
std::string remote_host_name_ = ""; std::string remote_host_name_ = "";
std::vector<ScreenCapturer::DisplayInfo> display_info_list_; std::vector<DisplayInfo> display_info_list_;
SDL_Texture *stream_texture_ = nullptr; SDL_Texture *stream_texture_ = nullptr;
SDL_Rect stream_render_rect_; SDL_Rect stream_render_rect_;
SDL_Rect stream_render_rect_last_; SDL_Rect stream_render_rect_last_;
@@ -316,6 +316,7 @@ class Render {
float about_window_height_ = 150; float about_window_height_ = 150;
int screen_width_ = 1280; int screen_width_ = 1280;
int screen_height_ = 720; int screen_height_ = 720;
int selected_display_ = 0;
std::string connect_button_label_ = "Connect"; std::string connect_button_label_ = "Connect";
char input_password_tmp_[7] = ""; char input_password_tmp_[7] = "";
char input_password_[7] = ""; char input_password_[7] = "";
@@ -398,7 +399,7 @@ class Render {
DeviceControllerFactory *device_controller_factory_ = nullptr; DeviceControllerFactory *device_controller_factory_ = nullptr;
MouseController *mouse_controller_ = nullptr; MouseController *mouse_controller_ = nullptr;
KeyboardCapturer *keyboard_capturer_ = nullptr; KeyboardCapturer *keyboard_capturer_ = nullptr;
std::vector<ScreenCapturer::DisplayInfo> display_info_list_; std::vector<DisplayInfo> display_info_list_;
uint64_t last_frame_time_; uint64_t last_frame_time_;
char client_id_[10] = ""; char client_id_[10] = "";
char client_id_display_[12] = ""; char client_id_display_[12] = "";

View File

@@ -63,13 +63,9 @@ int Render::ProcessMouseEvent(SDL_Event &event) {
last_mouse_event.button.y = event.button.y; last_mouse_event.button.y = event.button.y;
remote_action.m.x = remote_action.m.x =
(float)(event.button.x - props->stream_render_rect_.x + (float)(event.button.x - props->stream_render_rect_.x) / render_width;
props->display_info_list_[props->selected_display_ - 1]
.left) /
render_width;
remote_action.m.y = remote_action.m.y =
(float)(event.button.y - props->stream_render_rect_.y + (float)(event.button.y - props->stream_render_rect_.y) /
props->display_info_list_[props->selected_display_ - 1].top) /
render_height; render_height;
if (SDL_MOUSEBUTTONDOWN == event.type) { if (SDL_MOUSEBUTTONDOWN == event.type) {
@@ -297,10 +293,9 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size,
LOG_INFO("Remote hostname: [{}]", props->remote_host_name_); LOG_INFO("Remote hostname: [{}]", props->remote_host_name_);
for (int i = 0; i < host_info.i.display_num; i++) { for (int i = 0; i < host_info.i.display_num; i++) {
props->display_info_list_.push_back( props->display_info_list_.push_back(DisplayInfo(
{std::string(host_info.i.display_list[i]), host_info.i.left[i], std::string(host_info.i.display_list[i]), host_info.i.left[i],
host_info.i.top[i], host_info.i.right[i], host_info.i.top[i], host_info.i.right[i], host_info.i.bottom[i]));
host_info.i.bottom[i]});
LOG_INFO("Remote display [{}:{}], bound [({}, {}) ({}, {})]", i + 1, LOG_INFO("Remote display [{}:{}], bound [({}, {}) ({}, {})]", i + 1,
props->display_info_list_[i].name, props->display_info_list_[i].name,
props->display_info_list_[i].left, props->display_info_list_[i].left,
@@ -319,7 +314,8 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size,
} else { } else {
// remote // remote
if (ControlType::mouse == remote_action.type && render->mouse_controller_) { if (ControlType::mouse == remote_action.type && render->mouse_controller_) {
render->mouse_controller_->SendMouseCommand(remote_action); render->mouse_controller_->SendMouseCommand(remote_action,
render->selected_display_);
} else if (ControlType::audio_capture == remote_action.type) { } else if (ControlType::audio_capture == remote_action.type) {
if (remote_action.a) { if (remote_action.a) {
render->StartSpeakerCapturer(); render->StartSpeakerCapturer();
@@ -335,6 +331,7 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size,
remote_action.k.flag == KeyFlag::key_down); remote_action.k.flag == KeyFlag::key_down);
} else if (ControlType::display_id == remote_action.type) { } else if (ControlType::display_id == remote_action.type) {
if (render->screen_capturer_) { if (render->screen_capturer_) {
render->selected_display_ = remote_action.d;
render->screen_capturer_->SwitchTo(remote_action.d); render->screen_capturer_->SwitchTo(remote_action.d);
} }
} }

View File

@@ -58,7 +58,7 @@ target("common")
target("screen_capturer") target("screen_capturer")
set_kind("object") set_kind("object")
add_deps("rd_log") add_deps("rd_log", "common")
add_includedirs("src/screen_capturer", {public = true}) add_includedirs("src/screen_capturer", {public = true})
if is_os("windows") then if is_os("windows") then
add_packages("libyuv") add_packages("libyuv")
@@ -92,7 +92,7 @@ target("speaker_capturer")
target("device_controller") target("device_controller")
set_kind("object") set_kind("object")
add_deps("rd_log") add_deps("rd_log", "common")
add_includedirs("src/device_controller", {public = true}) add_includedirs("src/device_controller", {public = true})
if is_os("windows") then if is_os("windows") then
add_files("src/device_controller/mouse/windows/*.cpp", add_files("src/device_controller/mouse/windows/*.cpp",