[fix] validate macOS input display state before injecting events

This commit is contained in:
dijunkun
2026-05-28 04:22:14 +08:00
parent 193e4bd5bf
commit 32345f93bf
3 changed files with 100 additions and 74 deletions
@@ -310,6 +310,10 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down,
if (IsFunctionKey(cg_key_code) && !is_down) { if (IsFunctionKey(cg_key_code) && !is_down) {
CGEventRef fn_release_event = CGEventRef fn_release_event =
CGEventCreateKeyboardEvent(NULL, fn_key_code_, false); CGEventCreateKeyboardEvent(NULL, fn_key_code_, false);
if (!fn_release_event) {
LOG_ERROR("CGEventCreateKeyboardEvent failed for fn release");
return -1;
}
CGEventPost(kCGHIDEventTap, fn_release_event); CGEventPost(kCGHIDEventTap, fn_release_event);
CFRelease(fn_release_event); CFRelease(fn_release_event);
} }
@@ -1,6 +1,7 @@
#include "mouse_controller.h" #include "mouse_controller.h"
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
#include <algorithm>
#include "rd_log.h" #include "rd_log.h"
@@ -20,85 +21,101 @@ int MouseController::Destroy() { return 0; }
int MouseController::SendMouseCommand(RemoteAction remote_action, int MouseController::SendMouseCommand(RemoteAction remote_action,
int display_index) { int display_index) {
if (remote_action.type != ControlType::mouse) {
return 0;
}
if (display_index < 0 ||
display_index >= static_cast<int>(display_info_list_.size())) {
LOG_WARN("Mouse command skipped, invalid display_index={}, displays={}",
display_index, display_info_list_.size());
return -1;
}
const DisplayInfo& display_info = display_info_list_[display_index];
if (display_info.width <= 0 || display_info.height <= 0) {
LOG_WARN("Mouse command skipped, invalid display geometry: {}x{}",
display_info.width, display_info.height);
return -1;
}
const float normalized_x = std::clamp(remote_action.m.x, 0.0f, 1.0f);
const float normalized_y = std::clamp(remote_action.m.y, 0.0f, 1.0f);
int mouse_pos_x = int mouse_pos_x =
remote_action.m.x * display_info_list_[display_index].width + normalized_x * display_info.width + display_info.left;
display_info_list_[display_index].left;
int mouse_pos_y = int mouse_pos_y =
remote_action.m.y * display_info_list_[display_index].height + normalized_y * display_info.height + display_info.top;
display_info_list_[display_index].top;
if (remote_action.type == ControlType::mouse) { CGEventRef mouse_event = nullptr;
CGEventRef mouse_event = nullptr; CGEventType mouse_type;
CGEventType mouse_type; CGMouseButton mouse_button;
CGMouseButton mouse_button; CGPoint mouse_point = CGPointMake(mouse_pos_x, mouse_pos_y);
CGPoint mouse_point = CGPointMake(mouse_pos_x, mouse_pos_y);
switch (remote_action.m.flag) { switch (remote_action.m.flag) {
case MouseFlag::left_down: case MouseFlag::left_down:
mouse_type = kCGEventLeftMouseDown; mouse_type = kCGEventLeftMouseDown;
left_dragging_ = true; left_dragging_ = true;
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonLeft); kCGMouseButtonLeft);
break; break;
case MouseFlag::left_up: case MouseFlag::left_up:
mouse_type = kCGEventLeftMouseUp; mouse_type = kCGEventLeftMouseUp;
left_dragging_ = false; left_dragging_ = false;
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonLeft); kCGMouseButtonLeft);
break; break;
case MouseFlag::right_down: case MouseFlag::right_down:
mouse_type = kCGEventRightMouseDown; mouse_type = kCGEventRightMouseDown;
right_dragging_ = true; right_dragging_ = true;
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonRight); kCGMouseButtonRight);
break; break;
case MouseFlag::right_up: case MouseFlag::right_up:
mouse_type = kCGEventRightMouseUp; mouse_type = kCGEventRightMouseUp;
right_dragging_ = false; right_dragging_ = false;
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonRight); kCGMouseButtonRight);
break; break;
case MouseFlag::middle_down: case MouseFlag::middle_down:
mouse_type = kCGEventOtherMouseDown; mouse_type = kCGEventOtherMouseDown;
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonCenter); kCGMouseButtonCenter);
break; break;
case MouseFlag::middle_up: case MouseFlag::middle_up:
mouse_type = kCGEventOtherMouseUp; mouse_type = kCGEventOtherMouseUp;
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonCenter); kCGMouseButtonCenter);
break; break;
case MouseFlag::wheel_vertical: case MouseFlag::wheel_vertical:
mouse_event = CGEventCreateScrollWheelEvent( mouse_event = CGEventCreateScrollWheelEvent(
NULL, kCGScrollEventUnitLine, 2, remote_action.m.s, 0); NULL, kCGScrollEventUnitLine, 2, remote_action.m.s, 0);
break; break;
case MouseFlag::wheel_horizontal: case MouseFlag::wheel_horizontal:
mouse_event = CGEventCreateScrollWheelEvent( mouse_event = CGEventCreateScrollWheelEvent(
NULL, kCGScrollEventUnitLine, 2, 0, remote_action.m.s); NULL, kCGScrollEventUnitLine, 2, 0, remote_action.m.s);
break; break;
default: default:
if (left_dragging_) { if (left_dragging_) {
mouse_type = kCGEventLeftMouseDragged; mouse_type = kCGEventLeftMouseDragged;
mouse_button = kCGMouseButtonLeft; mouse_button = kCGMouseButtonLeft;
} else if (right_dragging_) { } else if (right_dragging_) {
mouse_type = kCGEventRightMouseDragged; mouse_type = kCGEventRightMouseDragged;
mouse_button = kCGMouseButtonRight; mouse_button = kCGMouseButtonRight;
} else { } else {
mouse_type = kCGEventMouseMoved; mouse_type = kCGEventMouseMoved;
mouse_button = kCGMouseButtonLeft; mouse_button = kCGMouseButtonLeft;
} }
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
mouse_button); mouse_button);
break; break;
} }
if (mouse_event) { if (mouse_event) {
CGEventPost(kCGHIDEventTap, mouse_event); CGEventPost(kCGHIDEventTap, mouse_event);
CFRelease(mouse_event); CFRelease(mouse_event);
}
} }
return 0; return 0;
} }
} // namespace crossdesk } // namespace crossdesk
+7 -2
View File
@@ -1196,8 +1196,13 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
remote_action.k.extended); remote_action.k.extended);
} else if (remote_action.type == ControlType::display_id && } else if (remote_action.type == ControlType::display_id &&
render->screen_capturer_) { render->screen_capturer_) {
render->selected_display_ = remote_action.d; const int ret = render->screen_capturer_->SwitchTo(remote_action.d);
render->screen_capturer_->SwitchTo(remote_action.d); if (ret == 0) {
render->selected_display_ = remote_action.d;
} else {
LOG_WARN("Display switch skipped, invalid display_id={}",
remote_action.d);
}
} }
} }
} }