Merge pull request #4576 from fufesou/fix/win_mouse_input_touchpad
fix, win mouse, touchpad scroll
This commit is contained in:
		
						commit
						858cf2f5b5
					
				| @ -1,5 +1,6 @@ | ||||
| import 'dart:async'; | ||||
| import 'dart:convert'; | ||||
| import 'dart:io'; | ||||
| import 'dart:math'; | ||||
| import 'dart:ui' as ui; | ||||
| 
 | ||||
| @ -45,12 +46,11 @@ class InputModel { | ||||
|   var command = false; | ||||
| 
 | ||||
|   // trackpad | ||||
|   final _trackpadSpeed = 0.06; | ||||
|   var _trackpadLastDelta = Offset.zero; | ||||
|   var _trackpadScrollUnsent = Offset.zero; | ||||
|   var _stopFling = true; | ||||
|   var _fling = false; | ||||
|   Timer? _flingTimer; | ||||
|   final _flingBaseDelay = 10; | ||||
|   final _flingBaseDelay = 30; | ||||
| 
 | ||||
|   // mouse | ||||
|   final isPhysicalMouse = false.obs; | ||||
| @ -327,63 +327,39 @@ class InputModel { | ||||
|   // https://docs.flutter.dev/release/breaking-changes/trackpad-gestures | ||||
|   // TODO(support zoom in/out) | ||||
|   void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent e) { | ||||
|     var delta = e.panDelta; | ||||
|     final delta = e.panDelta; | ||||
|     _trackpadLastDelta = delta; | ||||
|     _trackpadScrollUnsent += (delta * _trackpadSpeed); | ||||
|     var x = _trackpadScrollUnsent.dx.truncate(); | ||||
|     var y = _trackpadScrollUnsent.dy.truncate(); | ||||
|     _trackpadScrollUnsent -= Offset(x.toDouble(), y.toDouble()); | ||||
|     var x = delta.dx.toInt(); | ||||
|     var y = delta.dy.toInt(); | ||||
|     if (x != 0 || y != 0) { | ||||
|       bind.sessionSendMouse( | ||||
|           id: id, msg: '{"type": "trackpad", "x": "$x", "y": "$y"}'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void _scheduleFling(double x, double y, int delay) { | ||||
|     if ((x == 0 && y == 0) || _stopFling) { | ||||
|       _fling = false; | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     _flingTimer = Timer(Duration(milliseconds: delay), () { | ||||
|       if (_stopFling) { | ||||
|         _fling = false; | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       final d = 0.93; | ||||
|       final d = 0.97; | ||||
|       x *= d; | ||||
|       y *= d; | ||||
|       final dx0 = x * _trackpadSpeed; | ||||
|       final dy0 = y * _trackpadSpeed; | ||||
| 
 | ||||
|       // Try set delta (x,y) and delay. | ||||
|       var dx = dx0.truncate(); | ||||
|       var dy = dy0.truncate(); | ||||
|       var dx = x.toInt(); | ||||
|       var dy = y.toInt(); | ||||
|       var delay = _flingBaseDelay; | ||||
| 
 | ||||
|       setMinDelta(double v) { | ||||
|         double minThr = _trackpadSpeed * 2; | ||||
|         return v > minThr ? 1 : (v < -minThr ? -1 : 0); | ||||
|       } | ||||
| 
 | ||||
|       // Try set min delta (x,y), and increase delay. | ||||
|       if (dx == 0 && dy == 0) { | ||||
|         final thr = 25; | ||||
|         var vx = thr; | ||||
|         var vy = thr; | ||||
|         if (dx0 != 0) { | ||||
|           vx = 1.0 ~/ dx0.abs(); | ||||
|         } | ||||
|         if (dy0 != 0) { | ||||
|           vy = 1.0 ~/ dy0.abs(); | ||||
|         } | ||||
|         if (vx < vy) { | ||||
|           delay *= (vx < thr ? vx : thr); | ||||
|           dx = setMinDelta(dx0); | ||||
|         } else if (vy < thr) { | ||||
|           delay *= (vy < thr ? vy : thr); | ||||
|           dy = setMinDelta(dy0); | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       if (dx == 0 && dy == 0) { | ||||
|         _fling = false; | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
| @ -393,13 +369,28 @@ class InputModel { | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   void waitLastFlingDone() { | ||||
|     if (_fling) { | ||||
|       _stopFling = true; | ||||
|     } | ||||
|     for (var i = 0; i < 5; i++) { | ||||
|       if (!_fling) { | ||||
|         break; | ||||
|       } | ||||
|       sleep(Duration(milliseconds: 10)); | ||||
|     } | ||||
|     _flingTimer?.cancel(); | ||||
|   } | ||||
| 
 | ||||
|   void onPointerPanZoomEnd(PointerPanZoomEndEvent e) { | ||||
|     waitLastFlingDone(); | ||||
|     _stopFling = false; | ||||
|     _trackpadScrollUnsent = Offset.zero; | ||||
| 
 | ||||
|     // 2.0 is an experience value | ||||
|     double minFlingValue = 2.0; | ||||
|     if (_trackpadLastDelta.dx.abs() > minFlingValue || | ||||
|         _trackpadLastDelta.dy.abs() > minFlingValue) { | ||||
|       _fling = true; | ||||
|       _scheduleFling( | ||||
|           _trackpadLastDelta.dx, _trackpadLastDelta.dy, _flingBaseDelay); | ||||
|     } | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| use enigo::{Enigo, MouseButton, MouseControllable}; | ||||
| use winapi::um::winuser::WHEEL_DELTA; | ||||
| use std::thread; | ||||
| use std::time::Duration; | ||||
| 
 | ||||
| @ -25,16 +26,16 @@ fn main() { | ||||
| 
 | ||||
|     #[cfg(not(target_os = "macos"))] | ||||
|     { | ||||
|         enigo.mouse_scroll_x(2); | ||||
|         enigo.mouse_scroll_x(2 * WHEEL_DELTA as i32); | ||||
|         thread::sleep(wait_time); | ||||
| 
 | ||||
|         enigo.mouse_scroll_x(-2); | ||||
|         enigo.mouse_scroll_x(-2 * WHEEL_DELTA as i32); | ||||
|         thread::sleep(wait_time); | ||||
| 
 | ||||
|         enigo.mouse_scroll_y(2); | ||||
|         enigo.mouse_scroll_y(2 * WHEEL_DELTA as i32); | ||||
|         thread::sleep(wait_time); | ||||
| 
 | ||||
|         enigo.mouse_scroll_y(-2); | ||||
|         enigo.mouse_scroll_y(-2 * WHEEL_DELTA as i32); | ||||
|         thread::sleep(wait_time); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -21,11 +21,9 @@ static mut LAYOUT: HKL = std::ptr::null_mut(); | ||||
| pub const ENIGO_INPUT_EXTRA_VALUE: ULONG_PTR = 100; | ||||
| 
 | ||||
| fn mouse_event(flags: u32, data: u32, dx: i32, dy: i32) -> DWORD { | ||||
|     let mut input: INPUT = unsafe { std::mem::MaybeUninit::zeroed().assume_init() }; | ||||
|     input.type_ = INPUT_MOUSE; | ||||
|     let mut u = INPUT_u::default(); | ||||
|     unsafe { | ||||
|         let dst_ptr = (&mut input.u as *mut _) as *mut u8; | ||||
|         let m = MOUSEINPUT { | ||||
|         *u.mi_mut() = MOUSEINPUT { | ||||
|             dx, | ||||
|             dy, | ||||
|             mouseData: data, | ||||
| @ -33,9 +31,11 @@ fn mouse_event(flags: u32, data: u32, dx: i32, dy: i32) -> DWORD { | ||||
|             time: 0, | ||||
|             dwExtraInfo: ENIGO_INPUT_EXTRA_VALUE, | ||||
|         }; | ||||
|         let src_ptr = (&m as *const _) as *const u8; | ||||
|         std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, size_of::<MOUSEINPUT>()); | ||||
|     } | ||||
|     let mut input = INPUT { | ||||
|         type_: INPUT_MOUSE, | ||||
|         u, | ||||
|     }; | ||||
|     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) } | ||||
| } | ||||
| 
 | ||||
| @ -154,8 +154,8 @@ impl MouseControllable for Enigo { | ||||
|                 } | ||||
|             }, | ||||
|             match button { | ||||
|                 MouseButton::Back => XBUTTON1 as _, | ||||
|                 MouseButton::Forward => XBUTTON2 as _, | ||||
|                 MouseButton::Back => XBUTTON1 as u32 * WHEEL_DELTA as u32, | ||||
|                 MouseButton::Forward => XBUTTON2 as u32 * WHEEL_DELTA as u32, | ||||
|                 _ => 0, | ||||
|             }, | ||||
|             0, | ||||
| @ -199,11 +199,11 @@ impl MouseControllable for Enigo { | ||||
|     } | ||||
| 
 | ||||
|     fn mouse_scroll_x(&mut self, length: i32) { | ||||
|         mouse_event(MOUSEEVENTF_HWHEEL, unsafe { transmute(length * 120) }, 0, 0); | ||||
|         mouse_event(MOUSEEVENTF_HWHEEL, length as _, 0, 0); | ||||
|     } | ||||
| 
 | ||||
|     fn mouse_scroll_y(&mut self, length: i32) { | ||||
|         mouse_event(MOUSEEVENTF_WHEEL, unsafe { transmute(length * 120) }, 0, 0); | ||||
|         mouse_event(MOUSEEVENTF_WHEEL, length as _, 0, 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -6,6 +6,10 @@ use crate::{ | ||||
|     common::make_fd_to_json, | ||||
|     flutter::{self, SESSIONS}, | ||||
|     flutter::{session_add, session_start_}, | ||||
|     server::input_service::{ | ||||
|         MOUSE_BUTTON_BACK, MOUSE_BUTTON_FORWARD, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, | ||||
|         MOUSE_BUTTON_WHEEL, MOUSE_TYPE_DOWN, MOUSE_TYPE_TRACKPAD, MOUSE_TYPE_UP, MOUSE_TYPE_WHEEL, | ||||
|     }, | ||||
|     ui_interface::{self, *}, | ||||
| }; | ||||
| use flutter_rust_bridge::{StreamSink, SyncReturn}; | ||||
| @ -1054,20 +1058,20 @@ pub fn session_send_mouse(id: String, msg: String) { | ||||
|         let mut mask = 0; | ||||
|         if let Some(_type) = m.get("type") { | ||||
|             mask = match _type.as_str() { | ||||
|                 "down" => 1, | ||||
|                 "up" => 2, | ||||
|                 "wheel" => 3, | ||||
|                 "trackpad" => 4, | ||||
|                 "down" => MOUSE_TYPE_DOWN, | ||||
|                 "up" => MOUSE_TYPE_UP, | ||||
|                 "wheel" => MOUSE_TYPE_WHEEL, | ||||
|                 "trackpad" => MOUSE_TYPE_TRACKPAD, | ||||
|                 _ => 0, | ||||
|             }; | ||||
|         } | ||||
|         if let Some(buttons) = m.get("buttons") { | ||||
|             mask |= match buttons.as_str() { | ||||
|                 "left" => 0x01, | ||||
|                 "right" => 0x02, | ||||
|                 "wheel" => 0x04, | ||||
|                 "back" => 0x08, | ||||
|                 "forward" => 0x10, | ||||
|                 "left" => MOUSE_BUTTON_LEFT, | ||||
|                 "right" => MOUSE_BUTTON_RIGHT, | ||||
|                 "wheel" => MOUSE_BUTTON_WHEEL, | ||||
|                 "back" => MOUSE_BUTTON_BACK, | ||||
|                 "forward" => MOUSE_BUTTON_FORWARD, | ||||
|                 _ => 0, | ||||
|             } << 3; | ||||
|         } | ||||
|  | ||||
| @ -17,9 +17,22 @@ use std::{ | ||||
|     thread, | ||||
|     time::{self, Duration, Instant}, | ||||
| }; | ||||
| use winapi::um::winuser::WHEEL_DELTA; | ||||
| 
 | ||||
| const INVALID_CURSOR_POS: i32 = i32::MIN; | ||||
| 
 | ||||
| pub const MOUSE_TYPE_MOVE: i32 = 0; | ||||
| pub const MOUSE_TYPE_DOWN: i32 = 1; | ||||
| pub const MOUSE_TYPE_UP: i32 = 2; | ||||
| pub const MOUSE_TYPE_WHEEL: i32 = 3; | ||||
| pub const MOUSE_TYPE_TRACKPAD: i32 = 4; | ||||
| 
 | ||||
| pub const MOUSE_BUTTON_LEFT: i32 = 0x01; | ||||
| pub const MOUSE_BUTTON_RIGHT: i32 = 0x02; | ||||
| pub const MOUSE_BUTTON_WHEEL: i32 = 0x04; | ||||
| pub const MOUSE_BUTTON_BACK: i32 = 0x08; | ||||
| pub const MOUSE_BUTTON_FORWARD: i32 = 0x10; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| struct StateCursor { | ||||
|     hcursor: u64, | ||||
| @ -777,7 +790,7 @@ pub fn handle_mouse_(evt: &MouseEvent, conn: i32) { | ||||
|         } | ||||
|     } | ||||
|     match evt_type { | ||||
|         0 => { | ||||
|         MOUSE_TYPE_MOVE => { | ||||
|             en.mouse_move_to(evt.x, evt.y); | ||||
|             *LATEST_PEER_INPUT_CURSOR.lock().unwrap() = Input { | ||||
|                 conn, | ||||
| @ -786,43 +799,43 @@ pub fn handle_mouse_(evt: &MouseEvent, conn: i32) { | ||||
|                 y: evt.y, | ||||
|             }; | ||||
|         } | ||||
|         1 => match buttons { | ||||
|             0x01 => { | ||||
|         MOUSE_TYPE_DOWN => match buttons { | ||||
|             MOUSE_BUTTON_LEFT => { | ||||
|                 allow_err!(en.mouse_down(MouseButton::Left)); | ||||
|             } | ||||
|             0x02 => { | ||||
|             MOUSE_BUTTON_RIGHT => { | ||||
|                 allow_err!(en.mouse_down(MouseButton::Right)); | ||||
|             } | ||||
|             0x04 => { | ||||
|             MOUSE_BUTTON_WHEEL => { | ||||
|                 allow_err!(en.mouse_down(MouseButton::Middle)); | ||||
|             } | ||||
|             0x08 => { | ||||
|             MOUSE_BUTTON_BACK => { | ||||
|                 allow_err!(en.mouse_down(MouseButton::Back)); | ||||
|             } | ||||
|             0x10 => { | ||||
|             MOUSE_BUTTON_FORWARD => { | ||||
|                 allow_err!(en.mouse_down(MouseButton::Forward)); | ||||
|             } | ||||
|             _ => {} | ||||
|         }, | ||||
|         2 => match buttons { | ||||
|             0x01 => { | ||||
|         MOUSE_TYPE_UP => match buttons { | ||||
|             MOUSE_BUTTON_LEFT => { | ||||
|                 en.mouse_up(MouseButton::Left); | ||||
|             } | ||||
|             0x02 => { | ||||
|             MOUSE_BUTTON_RIGHT => { | ||||
|                 en.mouse_up(MouseButton::Right); | ||||
|             } | ||||
|             0x04 => { | ||||
|             MOUSE_BUTTON_WHEEL => { | ||||
|                 en.mouse_up(MouseButton::Middle); | ||||
|             } | ||||
|             0x08 => { | ||||
|             MOUSE_BUTTON_BACK => { | ||||
|                 en.mouse_up(MouseButton::Back); | ||||
|             } | ||||
|             0x10 => { | ||||
|             MOUSE_BUTTON_FORWARD => { | ||||
|                 en.mouse_up(MouseButton::Forward); | ||||
|             } | ||||
|             _ => {} | ||||
|         }, | ||||
|         3 | 4 => { | ||||
|         MOUSE_TYPE_WHEEL | MOUSE_TYPE_TRACKPAD => { | ||||
|             #[allow(unused_mut)] | ||||
|             let mut x = evt.x; | ||||
|             #[allow(unused_mut)] | ||||
| @ -857,14 +870,20 @@ pub fn handle_mouse_(evt: &MouseEvent, conn: i32) { | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             #[cfg(windows)] | ||||
|             if evt_type == MOUSE_TYPE_WHEEL { | ||||
|                 x *= WHEEL_DELTA as i32; | ||||
|                 y *= WHEEL_DELTA as i32; | ||||
|             } | ||||
| 
 | ||||
|             #[cfg(not(target_os = "macos"))] | ||||
|             { | ||||
|                 if x != 0 { | ||||
|                     en.mouse_scroll_x(x); | ||||
|                 } | ||||
|                 if y != 0 { | ||||
|                     en.mouse_scroll_y(y); | ||||
|                 } | ||||
|                 if x != 0 { | ||||
|                     en.mouse_scroll_x(x); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         _ => {} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user