feat: support track pad scroll on flutter

This commit is contained in:
xxrl 2022-11-20 22:46:27 +08:00
parent edfb22d9c2
commit 13fd55557b
5 changed files with 71 additions and 4 deletions

View File

@ -51,6 +51,9 @@ class RawPointerMouseRegion extends StatelessWidget {
onPointerUp: inputModel.onPointUpImage, onPointerUp: inputModel.onPointUpImage,
onPointerMove: inputModel.onPointMoveImage, onPointerMove: inputModel.onPointMoveImage,
onPointerSignal: inputModel.onPointerSignalImage, onPointerSignal: inputModel.onPointerSignalImage,
onPointerPanZoomStart: inputModel.onPointerPanZoomStart,
onPointerPanZoomUpdate: inputModel.onPointerPanZoomUpdate,
onPointerPanZoomEnd: inputModel.onPointerPanZoomEnd,
child: MouseRegion( child: MouseRegion(
cursor: cursor ?? MouseCursor.defer, cursor: cursor ?? MouseCursor.defer,
onEnter: onEnter, onEnter: onEnter,

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'dart:ui' as ui; import 'dart:ui' as ui;
@ -39,6 +40,10 @@ class InputModel {
var alt = false; var alt = false;
var command = false; var command = false;
// trackpad
var trackpadScrollDistance = Offset.zero;
Timer? _flingTimer;
// mouse // mouse
final isPhysicalMouse = false.obs; final isPhysicalMouse = false.obs;
int _lastMouseDownButtons = 0; int _lastMouseDownButtons = 0;
@ -236,6 +241,7 @@ class InputModel {
if (!enter) { if (!enter) {
resetModifiers(); resetModifiers();
} }
_flingTimer?.cancel();
bind.sessionEnterOrLeave(id: id, enter: enter); bind.sessionEnterOrLeave(id: id, enter: enter);
} }
@ -258,6 +264,57 @@ class InputModel {
} }
} }
int _signOrZero(num x) {
if (x == 0) {
return 0;
} else {
return x > 0 ? 1 : -1;
}
}
void onPointerPanZoomStart(PointerPanZoomStartEvent e) {}
// https://docs.flutter.dev/release/breaking-changes/trackpad-gestures
// TODO(support zoom in/out)
void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent e) {
var delta = e.panDelta;
trackpadScrollDistance += delta;
bind.sessionSendMouse(
id: id,
msg:
'{"type": "trackpad", "x": "${delta.dx.toInt()}", "y": "${delta.dy.toInt()}"}');
}
// Simple simulation for fling.
void _scheduleFling(var x, y, dx, dy) {
if (dx <= 0 && dy <= 0) {
return;
}
_flingTimer = Timer(Duration(milliseconds: 10), () {
bind.sessionSendMouse(
id: id, msg: '{"type": "trackpad", "x": "$x", "y": "$y"}');
dx--;
dy--;
if (dx == 0) {
x = 0;
}
if (dy == 0) {
y = 0;
}
_scheduleFling(x, y, dx, dy);
});
}
void onPointerPanZoomEnd(PointerPanZoomEndEvent e) {
var x = _signOrZero(trackpadScrollDistance.dx);
var y = _signOrZero(trackpadScrollDistance.dy);
var dx = trackpadScrollDistance.dx.abs() ~/ 40;
var dy = trackpadScrollDistance.dy.abs() ~/ 40;
_scheduleFling(x, y, dx, dy);
trackpadScrollDistance = Offset.zero;
}
void onPointDownImage(PointerDownEvent e) { void onPointDownImage(PointerDownEvent e) {
debugPrint("onPointDownImage"); debugPrint("onPointDownImage");
if (e.kind != ui.PointerDeviceKind.mouse) { if (e.kind != ui.PointerDeviceKind.mouse) {

View File

@ -1572,9 +1572,14 @@ pub async fn handle_test_delay(t: TestDelay, peer: &mut Stream) {
} }
} }
/// Whether is track pad scrolling.
#[inline] #[inline]
#[cfg(all(target_os = "macos", not(feature = "flutter")))] #[cfg(all(target_os = "macos"))]
fn check_scroll_on_mac(mask: i32, x: i32, y: i32) -> bool { fn check_scroll_on_mac(mask: i32, x: i32, y: i32) -> bool {
// flutter version we set mask type bit to 4 when track pad scrolling.
if mask & 7 == 4 {
return true;
}
if mask & 3 != 3 { if mask & 3 != 3 {
return false; return false;
} }
@ -1597,7 +1602,7 @@ fn check_scroll_on_mac(mask: i32, x: i32, y: i32) -> bool {
/// ///
/// * `mask` - Mouse event. /// * `mask` - Mouse event.
/// * mask = buttons << 3 | type /// * mask = buttons << 3 | type
/// * type, 1: down, 2: up, 3: wheel /// * type, 1: down, 2: up, 3: wheel, 4: trackpad
/// * buttons, 1: left, 2: right, 4: middle /// * buttons, 1: left, 2: right, 4: middle
/// * `x` - X coordinate. /// * `x` - X coordinate.
/// * `y` - Y coordinate. /// * `y` - Y coordinate.
@ -1636,7 +1641,7 @@ pub fn send_mouse(
if command { if command {
mouse_event.modifiers.push(ControlKey::Meta.into()); mouse_event.modifiers.push(ControlKey::Meta.into());
} }
#[cfg(all(target_os = "macos", not(feature = "flutter")))] #[cfg(all(target_os = "macos"))]
if check_scroll_on_mac(mask, x, y) { if check_scroll_on_mac(mask, x, y) {
mouse_event.modifiers.push(ControlKey::Scroll.into()); mouse_event.modifiers.push(ControlKey::Scroll.into());
} }

View File

@ -156,6 +156,7 @@ pub fn session_reconnect(id: String) {
pub fn session_toggle_option(id: String, value: String) { pub fn session_toggle_option(id: String, value: String) {
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) { if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
log::warn!("toggle option {}", value);
session.toggle_option(value); session.toggle_option(value);
} }
} }
@ -907,6 +908,7 @@ pub fn session_send_mouse(id: String, msg: String) {
"down" => 1, "down" => 1,
"up" => 2, "up" => 2,
"wheel" => 3, "wheel" => 3,
"trackpad" => 4,
_ => 0, _ => 0,
}; };
} }

View File

@ -513,7 +513,7 @@ pub fn handle_mouse_(evt: &MouseEvent) {
} }
_ => {} _ => {}
}, },
3 => { 3 | 4 => {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut x = evt.x; let mut x = evt.x;
#[allow(unused_mut)] #[allow(unused_mut)]