mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-12-12 02:57:22 +00:00
Merge pull request #5323 from dignow/refact/android_scroll_event
Refact/android scroll event
This commit is contained in:
@@ -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<String, dynamic> toJson() {
|
||||
return {
|
||||
'k': kind,
|
||||
'v': {
|
||||
't': type,
|
||||
'v': value,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class InputModel {
|
||||
final WeakReference<FFI> parent;
|
||||
String keyboardMode = "legacy";
|
||||
@@ -62,11 +80,11 @@ class InputModel {
|
||||
int _lastButtons = 0;
|
||||
Offset lastMousePos = Offset.zero;
|
||||
|
||||
get id => parent.target?.id ?? "";
|
||||
|
||||
late final SessionID sessionId;
|
||||
|
||||
bool get keyboardPerm => parent.target!.ffiModel.keyboard;
|
||||
String get id => parent.target?.id ?? '';
|
||||
String? get peerPlatform => parent.target?.ffiModel.pi.platform;
|
||||
|
||||
InputModel(this.parent) {
|
||||
sessionId = parent.target!.sessionId;
|
||||
@@ -223,14 +241,8 @@ class InputModel {
|
||||
command: command);
|
||||
}
|
||||
|
||||
Map<String, dynamic> getEvent(PointerEvent evt, String type) {
|
||||
Map<String, dynamic> _getMouseEvent(PointerEvent evt, String type) {
|
||||
final Map<String, dynamic> out = {};
|
||||
out['x'] = evt.position.dx;
|
||||
out['y'] = evt.position.dy;
|
||||
if (alt) out['alt'] = 'true';
|
||||
if (shift) out['shift'] = 'true';
|
||||
if (ctrl) out['ctrl'] = 'true';
|
||||
if (command) out['command'] = 'true';
|
||||
|
||||
// Check update event type and set buttons to be sent.
|
||||
int buttons = _lastButtons;
|
||||
@@ -260,7 +272,6 @@ class InputModel {
|
||||
|
||||
out['buttons'] = buttons;
|
||||
out['type'] = type;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -292,7 +303,7 @@ class InputModel {
|
||||
}
|
||||
|
||||
/// Modify the given modifier map [evt] based on current modifier key status.
|
||||
Map<String, String> modify(Map<String, String> evt) {
|
||||
Map<String, dynamic> modify(Map<String, dynamic> evt) {
|
||||
if (ctrl) evt['ctrl'] = 'true';
|
||||
if (shift) evt['shift'] = 'true';
|
||||
if (alt) evt['alt'] = 'true';
|
||||
@@ -334,27 +345,33 @@ class InputModel {
|
||||
isPhysicalMouse.value = true;
|
||||
}
|
||||
if (isPhysicalMouse.value) {
|
||||
handleMouse(getEvent(e, _kMouseEventMove));
|
||||
handleMouse(_getMouseEvent(e, _kMouseEventMove), e.position);
|
||||
}
|
||||
}
|
||||
|
||||
void onPointerPanZoomStart(PointerPanZoomStartEvent e) {
|
||||
_lastScale = 1.0;
|
||||
_stopFling = true;
|
||||
|
||||
if (peerPlatform == kPeerPlatformAndroid) {
|
||||
handlePointerEvent('touch', 'pan_start', e.position);
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.flutter.dev/release/breaking-changes/trackpad-gestures
|
||||
void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent e) {
|
||||
final scale = ((e.scale - _lastScale) * 1000).toInt();
|
||||
_lastScale = e.scale;
|
||||
if (peerPlatform != kPeerPlatformAndroid) {
|
||||
final scale = ((e.scale - _lastScale) * 1000).toInt();
|
||||
_lastScale = e.scale;
|
||||
|
||||
if (scale != 0) {
|
||||
bind.sessionSendPointer(
|
||||
sessionId: sessionId,
|
||||
msg: json.encode({
|
||||
'touch': {'scale': scale}
|
||||
}));
|
||||
return;
|
||||
if (scale != 0) {
|
||||
bind.sessionSendPointer(
|
||||
sessionId: sessionId,
|
||||
msg: json.encode(
|
||||
PointerEventToRust(kPointerEventKindTouch, 'scale', scale)
|
||||
.toJson()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final delta = e.panDelta;
|
||||
@@ -362,7 +379,7 @@ class InputModel {
|
||||
|
||||
var x = delta.dx.toInt();
|
||||
var y = delta.dy.toInt();
|
||||
if (parent.target?.ffiModel.pi.platform == kPeerPlatformLinux) {
|
||||
if (peerPlatform == kPeerPlatformLinux) {
|
||||
_trackpadScrollUnsent += (delta * _trackpadSpeed);
|
||||
x = _trackpadScrollUnsent.dx.truncate();
|
||||
y = _trackpadScrollUnsent.dy.truncate();
|
||||
@@ -378,9 +395,13 @@ class InputModel {
|
||||
}
|
||||
}
|
||||
if (x != 0 || y != 0) {
|
||||
bind.sessionSendMouse(
|
||||
sessionId: sessionId,
|
||||
msg: '{"type": "trackpad", "x": "$x", "y": "$y"}');
|
||||
if (peerPlatform == kPeerPlatformAndroid) {
|
||||
handlePointerEvent('touch', 'pan_update', Offset(x.toDouble(), y.toDouble()));
|
||||
} else {
|
||||
bind.sessionSendMouse(
|
||||
sessionId: sessionId,
|
||||
msg: '{"type": "trackpad", "x": "$x", "y": "$y"}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,11 +457,15 @@ class InputModel {
|
||||
}
|
||||
|
||||
void onPointerPanZoomEnd(PointerPanZoomEndEvent e) {
|
||||
if (peerPlatform == kPeerPlatformAndroid) {
|
||||
handlePointerEvent('touch', 'pan_end', e.position);
|
||||
return;
|
||||
}
|
||||
|
||||
bind.sessionSendPointer(
|
||||
sessionId: sessionId,
|
||||
msg: json.encode({
|
||||
'touch': {'scale': 0}
|
||||
}));
|
||||
msg: json.encode(
|
||||
PointerEventToRust(kPointerEventKindTouch, 'scale', 0).toJson()));
|
||||
|
||||
waitLastFlingDone();
|
||||
_stopFling = false;
|
||||
@@ -465,21 +490,21 @@ class InputModel {
|
||||
}
|
||||
}
|
||||
if (isPhysicalMouse.value) {
|
||||
handleMouse(getEvent(e, _kMouseEventDown));
|
||||
handleMouse(_getMouseEvent(e, _kMouseEventDown), e.position);
|
||||
}
|
||||
}
|
||||
|
||||
void onPointUpImage(PointerUpEvent e) {
|
||||
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
||||
if (isPhysicalMouse.value) {
|
||||
handleMouse(getEvent(e, _kMouseEventUp));
|
||||
handleMouse(_getMouseEvent(e, _kMouseEventUp), e.position);
|
||||
}
|
||||
}
|
||||
|
||||
void onPointMoveImage(PointerMoveEvent e) {
|
||||
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
||||
if (isPhysicalMouse.value) {
|
||||
handleMouse(getEvent(e, _kMouseEventMove));
|
||||
handleMouse(_getMouseEvent(e, _kMouseEventMove), e.position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,19 +529,16 @@ class InputModel {
|
||||
}
|
||||
|
||||
void refreshMousePos() => handleMouse({
|
||||
'x': lastMousePos.dx,
|
||||
'y': lastMousePos.dy,
|
||||
'buttons': 0,
|
||||
'type': _kMouseEventMove,
|
||||
});
|
||||
}, lastMousePos);
|
||||
|
||||
void tryMoveEdgeOnExit(Offset pos) => handleMouse(
|
||||
{
|
||||
'x': pos.dx,
|
||||
'y': pos.dy,
|
||||
'buttons': 0,
|
||||
'type': _kMouseEventMove,
|
||||
},
|
||||
pos,
|
||||
onExit: true,
|
||||
);
|
||||
|
||||
@@ -550,17 +572,49 @@ class InputModel {
|
||||
return Offset(x, y);
|
||||
}
|
||||
|
||||
void handleMouse(
|
||||
Map<String, dynamic> evt, {
|
||||
bool onExit = false,
|
||||
}) {
|
||||
double x = evt['x'];
|
||||
double y = max(0.0, evt['y']);
|
||||
final cursorModel = parent.target!.cursorModel;
|
||||
void handlePointerEvent(String kind, String type, Offset offset) {
|
||||
double x = offset.dx;
|
||||
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
|
||||
|
||||
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 = PointerEventToRust(kind, type, evtValue).toJson();
|
||||
bind.sessionSendPointer(
|
||||
sessionId: sessionId, msg: json.encode(modify(evt)));
|
||||
}
|
||||
|
||||
bool _checkPeerControlProtected(double x, double y) {
|
||||
final cursorModel = parent.target!.cursorModel;
|
||||
if (cursorModel.isPeerControlProtected) {
|
||||
lastMousePos = ui.Offset(x, y);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cursorModel.gotMouseControl) {
|
||||
@@ -571,10 +625,23 @@ class InputModel {
|
||||
cursorModel.gotMouseControl = true;
|
||||
} else {
|
||||
lastMousePos = ui.Offset(x, y);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
lastMousePos = ui.Offset(x, y);
|
||||
return false;
|
||||
}
|
||||
|
||||
void handleMouse(
|
||||
Map<String, dynamic> evt,
|
||||
Offset offset, {
|
||||
bool onExit = false,
|
||||
}) {
|
||||
double x = offset.dx;
|
||||
double y = max(0.0, offset.dy);
|
||||
if (_checkPeerControlProtected(x, y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var type = '';
|
||||
var isMove = false;
|
||||
@@ -592,17 +659,58 @@ class InputModel {
|
||||
return;
|
||||
}
|
||||
evt['type'] = type;
|
||||
|
||||
final pos = handlePointerDevicePos(
|
||||
kPointerEventKindMouse,
|
||||
x,
|
||||
y,
|
||||
isMove,
|
||||
type,
|
||||
onExit: onExit,
|
||||
buttons: evt['buttons'],
|
||||
);
|
||||
if (pos == null) {
|
||||
return;
|
||||
}
|
||||
if (type != '') {
|
||||
evt['x'] = '0';
|
||||
evt['y'] = '0';
|
||||
} else {
|
||||
evt['x'] = '${pos.x}';
|
||||
evt['y'] = '${pos.y}';
|
||||
}
|
||||
|
||||
Map<int, String> mapButtons = {
|
||||
kPrimaryMouseButton: 'left',
|
||||
kSecondaryMouseButton: 'right',
|
||||
kMiddleMouseButton: 'wheel',
|
||||
kBackMouseButton: 'back',
|
||||
kForwardMouseButton: 'forward'
|
||||
};
|
||||
evt['buttons'] = mapButtons[evt['buttons']] ?? '';
|
||||
bind.sessionSendMouse(sessionId: sessionId, msg: json.encode(modify(evt)));
|
||||
}
|
||||
|
||||
Point? handlePointerDevicePos(
|
||||
String kind,
|
||||
double x,
|
||||
double y,
|
||||
bool isMove,
|
||||
String evtType, {
|
||||
bool onExit = false,
|
||||
int buttons = kPrimaryMouseButton,
|
||||
}) {
|
||||
y -= CanvasModel.topToEdge;
|
||||
x -= CanvasModel.leftToEdge;
|
||||
final canvasModel = parent.target!.canvasModel;
|
||||
final nearThr = 3;
|
||||
var nearRight = (canvasModel.size.width - x) < nearThr;
|
||||
var nearBottom = (canvasModel.size.height - y) < nearThr;
|
||||
|
||||
final ffiModel = parent.target!.ffiModel;
|
||||
if (isMove) {
|
||||
canvasModel.moveDesktopMouse(x, y);
|
||||
}
|
||||
|
||||
final nearThr = 3;
|
||||
var nearRight = (canvasModel.size.width - x) < nearThr;
|
||||
var nearBottom = (canvasModel.size.height - y) < nearThr;
|
||||
final d = ffiModel.display;
|
||||
final imageWidth = d.width * canvasModel.scale;
|
||||
final imageHeight = d.height * canvasModel.scale;
|
||||
@@ -650,7 +758,7 @@ class InputModel {
|
||||
} catch (e) {
|
||||
debugPrintStack(
|
||||
label: 'canvasModel.scale value ${canvasModel.scale}, $e');
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
int minX = d.x.toInt();
|
||||
@@ -659,40 +767,16 @@ 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 (evt['buttons'] != kPrimaryMouseButton || type != 'up') {
|
||||
return;
|
||||
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 (type != '') {
|
||||
evtX = 0;
|
||||
evtY = 0;
|
||||
}
|
||||
|
||||
evt['x'] = '$evtX';
|
||||
evt['y'] = '$evtY';
|
||||
var buttons = '';
|
||||
switch (evt['buttons']) {
|
||||
case kPrimaryMouseButton:
|
||||
buttons = 'left';
|
||||
break;
|
||||
case kSecondaryMouseButton:
|
||||
buttons = 'right';
|
||||
break;
|
||||
case kMiddleMouseButton:
|
||||
buttons = 'wheel';
|
||||
break;
|
||||
case kBackMouseButton:
|
||||
buttons = 'back';
|
||||
break;
|
||||
case kForwardMouseButton:
|
||||
buttons = 'forward';
|
||||
break;
|
||||
}
|
||||
evt['buttons'] = buttons;
|
||||
bind.sessionSendMouse(sessionId: sessionId, msg: json.encode(evt));
|
||||
return Point(evtX, evtY);
|
||||
}
|
||||
|
||||
/// Web only
|
||||
|
||||
Reference in New Issue
Block a user