mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-02-17 22:11:30 +08:00
* feat: Add relative mouse mode - Add "Relative Mouse Mode" toggle in desktop toolbar and bind to InputModel - Implement relative mouse movement path: Flutter pointer deltas -> `type: move_relative` -> new `MOUSE_TYPE_MOVE_RELATIVE` in Rust - In server input service, simulate relative movement via Enigo and keep latest cursor position in sync - Track pointer-lock center in Flutter (local widget + screen coordinates) and re-center OS cursor after each relative move - Update pointer-lock center on window move/resize/restore/maximize and when remote display geometry changes - Hide local cursor when relative mouse mode is active (both Flutter cursor and OS cursor), restore on leave/disable - On Windows, clip OS cursor to the window rect while in relative mode and release clip when leaving/turning off - Implement platform helpers: `get_cursor_pos`, `set_cursor_pos`, `show_cursor`, `clip_cursor` (no-op clip/hide on Linux for now) - Add keyboard shortcut Ctrl+Alt+Shift+M to toggle relative mode (enabled by default, works on all platforms) - Remove `enable-relative-mouse-shortcut` config option - shortcut is now always available when keyboard permission is granted - Handle window blur/focus/minimize events to properly release/restore cursor constraints - Add MOUSE_TYPE_MASK constant and unit tests for mouse event constants Note: Relative mouse mode state is NOT persisted to config (session-only). Note: On Linux, show_cursor and clip_cursor are no-ops; cursor hiding is handled by Flutter side. Signed-off-by: fufesou <linlong1266@gmail.com> * feat(mouse): relative mouse mode, exit hint Signed-off-by: fufesou <linlong1266@gmail.com> * refact(relative mouse): shortcut Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
59 lines
1.6 KiB
Dart
59 lines
1.6 KiB
Dart
/// A small helper for accumulating fractional mouse deltas and emitting integer deltas.
|
|
///
|
|
/// Relative mouse mode uses integer deltas on the wire, but Flutter pointer deltas
|
|
/// are doubles. This accumulator preserves sub-pixel movement by carrying the
|
|
/// fractional remainder across events.
|
|
class RelativeMouseDelta {
|
|
final int x;
|
|
final int y;
|
|
|
|
const RelativeMouseDelta(this.x, this.y);
|
|
}
|
|
|
|
/// Accumulates fractional mouse deltas and returns integer deltas when available.
|
|
class RelativeMouseAccumulator {
|
|
double _fracX = 0.0;
|
|
double _fracY = 0.0;
|
|
|
|
/// Adds a delta and returns an integer delta when at least one axis reaches a
|
|
/// magnitude of 1px (after truncation towards zero).
|
|
///
|
|
/// If [maxDelta] is > 0, the returned integer delta is clamped to
|
|
/// [-maxDelta, maxDelta] on each axis.
|
|
RelativeMouseDelta? add(
|
|
double dx,
|
|
double dy, {
|
|
required int maxDelta,
|
|
}) {
|
|
// Guard against misuse: negative maxDelta would silently disable clamping.
|
|
assert(maxDelta >= 0, 'maxDelta must be non-negative');
|
|
|
|
_fracX += dx;
|
|
_fracY += dy;
|
|
|
|
int intX = _fracX.truncate();
|
|
int intY = _fracY.truncate();
|
|
|
|
if (intX == 0 && intY == 0) {
|
|
return null;
|
|
}
|
|
|
|
// Clamp before subtracting so excess movement is preserved in the accumulator
|
|
// rather than being permanently discarded during spikes.
|
|
if (maxDelta > 0) {
|
|
intX = intX.clamp(-maxDelta, maxDelta);
|
|
intY = intY.clamp(-maxDelta, maxDelta);
|
|
}
|
|
|
|
_fracX -= intX;
|
|
_fracY -= intY;
|
|
|
|
return RelativeMouseDelta(intX, intY);
|
|
}
|
|
|
|
void reset() {
|
|
_fracX = 0.0;
|
|
_fracY = 0.0;
|
|
}
|
|
}
|