diff --git a/flutter/lib/common/widgets/remote_input.dart b/flutter/lib/common/widgets/remote_input.dart index 35eaf8a7c..b00cd1fb4 100644 --- a/flutter/lib/common/widgets/remote_input.dart +++ b/flutter/lib/common/widgets/remote_input.dart @@ -6,6 +6,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/models/model.dart'; import 'package:flutter_hbb/models/input_model.dart'; @@ -263,9 +264,9 @@ class _RawTouchGestureDetectorRegionState if (scale != 0) { bind.sessionSendPointer( sessionId: sessionId, - msg: json.encode({ - 'touch': {'scale': scale} - })); + msg: json.encode( + PointerEventToRust(kPointerEventKindTouch, 'scale', scale) + .toJson())); } } else { // mobile @@ -283,9 +284,8 @@ class _RawTouchGestureDetectorRegionState if (isDesktop) { bind.sessionSendPointer( sessionId: sessionId, - msg: json.encode({ - 'touch': {'scale': 0} - })); + msg: json.encode( + PointerEventToRust(kPointerEventKindTouch, 'scale', 0).toJson())); } else { // mobile _scale = 1; diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 5376196e4..f26e83e01 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -54,6 +54,9 @@ const String kTabLabelSettingPage = "Settings"; const String kWindowPrefix = "wm_"; const int kWindowMainId = 0; +const String kPointerEventKindTouch = "touch"; +const String kPointerEventKindMouse = "mouse"; + // the executable name of the portable version const String kEnvPortableExecutable = "RUSTDESK_APPNAME"; diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 18e9d0d2f..9b1ec4437 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -35,6 +35,24 @@ extension ToString on MouseButtons { } } +class PointerEventToRust { + final String kind; + final String type; + final dynamic value; + + PointerEventToRust(this.kind, this.type, this.value); + + Map toJson() { + return { + 'k': kind, + 'v': { + 't': type, + 'v': value, + } + }; + } +} + class InputModel { final WeakReference parent; String keyboardMode = "legacy"; @@ -349,9 +367,9 @@ class InputModel { if (scale != 0) { bind.sessionSendPointer( sessionId: sessionId, - msg: json.encode({ - 'touch': {'scale': scale} - })); + msg: json.encode( + PointerEventToRust(kPointerEventKindTouch, 'scale', scale) + .toJson())); return; } } @@ -379,7 +397,7 @@ class InputModel { } if (x != 0 || y != 0) { if (peerPlatform == kPeerPlatformAndroid) { - handlePointerEvent('touch', 'pan_move', e.delta); + handlePointerEvent('touch', 'pan_update', Offset(x.toDouble(), y.toDouble())); } else { bind.sessionSendMouse( sessionId: sessionId, @@ -447,9 +465,8 @@ class InputModel { bind.sessionSendPointer( sessionId: sessionId, - msg: json.encode({ - 'touch': {'scale': 0} - })); + msg: json.encode( + PointerEventToRust(kPointerEventKindTouch, 'scale', 0).toJson())); waitLastFlingDone(); _stopFling = false; @@ -558,34 +575,40 @@ class InputModel { void handlePointerEvent(String kind, String type, Offset offset) { double x = offset.dx; - double y = max(0.0, offset.dy); + double y = offset.dy; if (_checkPeerControlProtected(x, y)) { return; } // Only touch events are handled for now. So we can just ignore buttons. // to-do: handle mouse events - final isMoveTypes = ['pan', 'pan_start', 'pan_end']; - final pos = handlePointerDevicePos( - x, - y, - isMoveTypes.contains(type), - type, - ); - if (pos == null) { - return; + late final dynamic evtValue; + if (type == 'pan_update') { + evtValue = { + 'x': '${x.toInt()}', + 'y': '${y.toInt()}', + }; + } else { + final isMoveTypes = ['pan_start', 'pan_end']; + final pos = handlePointerDevicePos( + kPointerEventKindTouch, + x, + y, + isMoveTypes.contains(type), + type, + ); + if (pos == null) { + return; + } + evtValue = { + 'x': '${pos.x}', + 'y': '${pos.y}', + }; } - final evt = { - kind: { - type: { - 'x': '${pos.x}', - 'y': '${pos.y}', - } - } - }; + final evt = PointerEventToRust(kind, type, evtValue).toJson(); bind.sessionSendPointer( - sessionId: sessionId, msg: json.encode({modify(evt)})); + sessionId: sessionId, msg: json.encode(modify(evt))); } bool _checkPeerControlProtected(double x, double y) { @@ -639,6 +662,7 @@ class InputModel { evt['type'] = type; final pos = handlePointerDevicePos( + kPointerEventKindMouse, x, y, isMove, @@ -649,8 +673,13 @@ class InputModel { if (pos == null) { return; } - evt['x'] = '${pos.x}'; - evt['y'] = '${pos.y}'; + if (type != '') { + evt['x'] = 0; + evt['y'] = 0; + } else { + evt['x'] = '${pos.x}'; + evt['y'] = '${pos.y}'; + } Map mapButtons = { kPrimaryMouseButton: 'left', @@ -664,6 +693,7 @@ class InputModel { } Point? handlePointerDevicePos( + String kind, double x, double y, bool isMove, @@ -738,18 +768,15 @@ class InputModel { int maxY = (d.y + d.height).toInt() - 1; evtX = trySetNearestRange(evtX, minX, maxX, 5); evtY = trySetNearestRange(evtY, minY, maxY, 5); - if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { - // If left mouse up, no early return. - if (buttons != kPrimaryMouseButton || evtType != 'up') { - return null; + if (kind == kPointerEventKindMouse) { + if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { + // If left mouse up, no early return. + if (!(buttons == kPrimaryMouseButton && evtType == 'up')) { + return null; + } } } - if (evtType != '') { - evtX = 0; - evtY = 0; - } - return Point(evtX, evtY); } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index ef4c9e2ba..cf5d23397 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1177,14 +1177,39 @@ pub fn session_send_pointer(session_id: SessionID, msg: String) { let ctrl = m.get("ctrl").is_some(); let shift = m.get("shift").is_some(); let command = m.get("command").is_some(); - if let Some(touch_event) = m.get("touch") { - if let Some(scale) = touch_event.get("scale") { - if let Some(session) = SESSIONS.read().unwrap().get(&session_id) { - if let Some(scale) = scale.as_i64() { - session.send_touch_scale(scale as _, alt, ctrl, shift, command); - } - } - } + match (m.get("k"), m.get("v")) { + (Some(k), Some(v)) => match k.as_str() { + Some("touch") => match v.as_str() { + Some("scale") => match v.get("v") { + Some(scale) => { + if let Some(scale) = scale.as_i64() { + if let Some(session) = SESSIONS.read().unwrap().get(&session_id) { + session.send_touch_scale(scale as _, alt, ctrl, shift, command); + } + } + } + None => {} + }, + Some(pan_event) => match (v.get("x"), v.get("y")) { + (Some(x), Some(y)) => { + if let Some(x) = x.as_i64() { + if let Some(y) = y.as_i64() { + if let Some(session) = SESSIONS.read().unwrap().get(&session_id) + { + session.send_touch_pan_event( + pan_event, x as _, y as _, alt, ctrl, shift, command, + ); + } + } + } + } + _ => {} + }, + _ => {} + }, + _ => {} + }, + _ => {} } } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 913c831da..972750fc2 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1573,20 +1573,20 @@ impl Connection { pan_start.y, ) } - Some(touch_event::Union::PanUpdate(pan_start)) => { + Some(touch_event::Union::PanUpdate(pan_update)) => { call_main_service_pointer_input( "touch".to_string(), 5, - pan_start.x, - pan_start.y, + pan_update.x, + pan_update.y, ) } - Some(touch_event::Union::PanEnd(pan_start)) => { + Some(touch_event::Union::PanEnd(pan_end)) => { call_main_service_pointer_input( "touch".to_string(), 6, - pan_start.x, - pan_start.y, + pan_end.x, + pan_end.y, ) } _ => Ok(()), diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 7ffcaac6d..23035a550 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -724,6 +724,49 @@ impl Session { send_pointer_device_event(evt, alt, ctrl, shift, command, self); } + pub fn send_touch_pan_event( + &self, + event: &str, + x: i32, + y: i32, + alt: bool, + ctrl: bool, + shift: bool, + command: bool, + ) { + let mut touch_evt = TouchEvent::new(); + match event { + "pan_start" => { + touch_evt.set_pan_start(TouchPanStart { + x, + y, + ..Default::default() + }); + } + "pan_update" => { + touch_evt.set_pan_update(TouchPanUpdate { + x, + y, + ..Default::default() + }); + } + "pan_end" => { + touch_evt.set_pan_end(TouchPanEnd { + x, + y, + ..Default::default() + }); + } + _ => { + log::warn!("unknown touch pan event: {}", event); + return; + } + }; + let mut evt = PointerDeviceEvent::new(); + evt.set_touch_event(touch_evt); + send_pointer_device_event(evt, alt, ctrl, shift, command, self); + } + pub fn send_mouse( &self, mask: i32,