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