From 4bf92c9e2cdfc0967ee8745fcf26093bbbff967f Mon Sep 17 00:00:00 2001 From: dijunkun Date: Thu, 17 Sep 2026 01:31:54 +0800 Subject: [PATCH] [fix] use reliable transport for mouse input and cursor state --- .../src/gui/application/gui_application.cpp | 10 +++++----- .../desktop/src/gui/application/sdl_events.cpp | 8 ++++---- .../src/gui/runtime/connection_runtime.cpp | 2 +- apps/desktop/src/gui/runtime/gui_runtime.cpp | 2 +- .../Bridge/CrossDeskRTCBridge.mm | 18 ++++++------------ 5 files changed, 17 insertions(+), 23 deletions(-) diff --git a/apps/desktop/src/gui/application/gui_application.cpp b/apps/desktop/src/gui/application/gui_application.cpp index 7c3fdb52..a3f18e8b 100644 --- a/apps/desktop/src/gui/application/gui_application.cpp +++ b/apps/desktop/src/gui/application/gui_application.cpp @@ -2014,7 +2014,7 @@ void GuiApplication::ShareLocalCursorState() { action.type = ControlType::cursor_state; action.cs = outgoing; const std::string message = action.to_json(); - const int result = SendDataFrameToPeer( + const int result = SendReliableDataFrameToPeer( peer_, message.c_str(), message.size(), mouse_label_.c_str(), recipient.remote_id.c_str(), recipient.remote_id.size()); if (result != 0) { @@ -3318,8 +3318,8 @@ void GuiApplication::SendPointerInput(int button, int kind, float x, float y) { std::lock_guard lock(props->remote_cursor_state_mutex_); props->cursor_presentation_.NoteInput(SDL_GetTicks()); } - SendDataFrame(props->peer_, message.c_str(), message.size(), - props->mouse_label_.c_str()); + SendReliableDataFrame(props->peer_, message.c_str(), message.size(), + props->mouse_label_.c_str()); } void GuiApplication::SendScrollInput(float delta_x, float delta_y, float x, @@ -3362,8 +3362,8 @@ void GuiApplication::SendScrollInput(float delta_x, float delta_y, float x, } controlled_remote_id_ = props->remote_id_; const std::string message = action.to_json(); - SendDataFrame(props->peer_, message.c_str(), message.size(), - props->mouse_label_.c_str()); + SendReliableDataFrame(props->peer_, message.c_str(), message.size(), + props->mouse_label_.c_str()); } void GuiApplication::SendKeyInput(const std::string& text, bool pressed, diff --git a/apps/desktop/src/gui/application/sdl_events.cpp b/apps/desktop/src/gui/application/sdl_events.cpp index 604bb6ab..e73061c8 100644 --- a/apps/desktop/src/gui/application/sdl_events.cpp +++ b/apps/desktop/src/gui/application/sdl_events.cpp @@ -366,8 +366,8 @@ int GuiApplication::ProcessMouseEvent(const SDL_Event &event) { } if (props->peer_) { std::string msg = remote_action.to_json(); - SendDataFrame(props->peer_, msg.c_str(), msg.size(), - props->mouse_label_.c_str()); + SendReliableDataFrame(props->peer_, msg.c_str(), msg.size(), + props->mouse_label_.c_str()); } } else if (SDL_EVENT_MOUSE_WHEEL == event.type && last_mouse_event.button.x >= render_rect.x && @@ -412,8 +412,8 @@ int GuiApplication::ProcessMouseEvent(const SDL_Event &event) { } if (props->peer_) { std::string msg = remote_action.to_json(); - SendDataFrame(props->peer_, msg.c_str(), msg.size(), - props->mouse_label_.c_str()); + SendReliableDataFrame(props->peer_, msg.c_str(), msg.size(), + props->mouse_label_.c_str()); } } } diff --git a/apps/desktop/src/gui/runtime/connection_runtime.cpp b/apps/desktop/src/gui/runtime/connection_runtime.cpp index 391fd243..dd4a886f 100644 --- a/apps/desktop/src/gui/runtime/connection_runtime.cpp +++ b/apps/desktop/src/gui/runtime/connection_runtime.cpp @@ -518,7 +518,7 @@ int GuiRuntime::ConnectTo(const std::string& remote_id, const char* password, } AddAudioStream(props->peer_, props->audio_label_.c_str()); AddDataStream(props->peer_, props->data_label_.c_str(), false); - AddDataStream(props->peer_, props->mouse_label_.c_str(), false); + AddDataStream(props->peer_, props->mouse_label_.c_str(), true); AddDataStream(props->peer_, props->keyboard_label_.c_str(), true); AddDataStream(props->peer_, props->control_data_label_.c_str(), true); AddDataStream(props->peer_, props->file_label_.c_str(), true); diff --git a/apps/desktop/src/gui/runtime/gui_runtime.cpp b/apps/desktop/src/gui/runtime/gui_runtime.cpp index 1fb70e4c..2b67a108 100644 --- a/apps/desktop/src/gui/runtime/gui_runtime.cpp +++ b/apps/desktop/src/gui/runtime/gui_runtime.cpp @@ -199,7 +199,7 @@ int GuiRuntime::CreateConnectionPeer() { AddAudioStream(peer_, audio_label_.c_str()); AddDataStream(peer_, data_label_.c_str(), false); - AddDataStream(peer_, mouse_label_.c_str(), false); + AddDataStream(peer_, mouse_label_.c_str(), true); AddDataStream(peer_, keyboard_label_.c_str(), true); AddDataStream(peer_, control_data_label_.c_str(), true); AddDataStream(peer_, file_label_.c_str(), true); diff --git a/apps/ios/CrossDeskMobile/Bridge/CrossDeskRTCBridge.mm b/apps/ios/CrossDeskMobile/Bridge/CrossDeskRTCBridge.mm index c72b0bd3..994580f1 100644 --- a/apps/ios/CrossDeskMobile/Bridge/CrossDeskRTCBridge.mm +++ b/apps/ios/CrossDeskMobile/Bridge/CrossDeskRTCBridge.mm @@ -621,21 +621,15 @@ Params MakeParams(const RTCState &state, const std::string &user_id, y:(float)y action:(CrossDeskPointerAction)action { const std::string message = MouseJSON(x, y, 0, static_cast(action)); - // Movement is latency-sensitive and can be superseded by newer positions. - // Button transitions must not be lost or reordered, otherwise a tap can be - // applied at a stale pointer position or leave a button logically pressed. - // MiniRTC reliability is configured per stream, so transitions use the - // existing reliable control stream while movement stays on the mouse stream. - const BOOL is_movement = action == CrossDeskPointerActionMove; + // Keep movement, button transitions, and scrolling ordered on the reliable + // mouse stream. #if DEBUG - if (!is_movement) { + if (action != CrossDeskPointerActionMove) { NSLog(@"CrossDesk pointer action=%ld normalized=(%.5f, %.5f)", static_cast(action), x, y); } #endif - [self sendMessage:message - reliable:!is_movement - stream:is_movement ? kMouseStream : kControlStream]; + [self sendMessage:message reliable:YES stream:kMouseStream]; } - (void)sendScrollX:(float)x @@ -648,7 +642,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id, const int flag = vertical ? 7 : 8; const int wheel = raw_delta > 0 ? 1 : -1; const std::string message = MouseJSON(x, y, wheel, flag); - [self sendMessage:message reliable:NO stream:kMouseStream]; + [self sendMessage:message reliable:YES stream:kMouseStream]; } - (void)sendWindowsKeyCode:(NSUInteger)keyCode isDown:(BOOL)isDown { @@ -893,7 +887,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id, // display. Remote display receivers are created from the host's SDP. AddAudioStream(_state->controller_peer, kAudioStream); AddDataStream(_state->controller_peer, kDataStream, false); - AddDataStream(_state->controller_peer, kMouseStream, false); + AddDataStream(_state->controller_peer, kMouseStream, true); AddDataStream(_state->controller_peer, kKeyboardStream, true); AddDataStream(_state->controller_peer, kControlStream, true); AddDataStream(_state->controller_peer, kFileStream, true);