feat(client/windows): invert scroll direction
The Apple client's toggle, wired through the shared session presenter: Settings::invert_scroll -> SessionOpts -> Capture, applied at the single seam where wheel deltas enter (before accumulation, so the fractional remainders stay consistent with what was actually sent). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -158,6 +158,7 @@ pub fn run(target: Option<&str>) -> u8 {
|
|||||||
v => v,
|
v => v,
|
||||||
},
|
},
|
||||||
touch_mode: settings_at_start.touch_mode(),
|
touch_mode: settings_at_start.touch_mode(),
|
||||||
|
invert_scroll: settings_at_start.invert_scroll,
|
||||||
json_status,
|
json_status,
|
||||||
on_connected: Some(Box::new(move |fingerprint: [u8; 32]| {
|
on_connected: Some(Box::new(move |fingerprint: [u8; 32]| {
|
||||||
let fp_hex = trust::hex(&fingerprint);
|
let fp_hex = trust::hex(&fingerprint);
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ mod session_main {
|
|||||||
v => v,
|
v => v,
|
||||||
},
|
},
|
||||||
touch_mode: settings.touch_mode(),
|
touch_mode: settings.touch_mode(),
|
||||||
|
invert_scroll: settings.invert_scroll,
|
||||||
json_status: true,
|
json_status: true,
|
||||||
on_connected: Some(Box::new(|fingerprint: [u8; 32]| {
|
on_connected: Some(Box::new(|fingerprint: [u8; 32]| {
|
||||||
// This host's card carries the accent bar in the desktop client now.
|
// This host's card carries the accent bar in the desktop client now.
|
||||||
|
|||||||
@@ -380,6 +380,10 @@ pub(crate) fn settings_page(
|
|||||||
let touch_combo = setting_combo(ctx, "Touch input", touch_names, touch_i, |s, i| {
|
let touch_combo = setting_combo(ctx, "Touch input", touch_names, touch_i, |s, i| {
|
||||||
s.touch_mode = TOUCH_MODES[i].0.to_string();
|
s.touch_mode = TOUCH_MODES[i].0.to_string();
|
||||||
});
|
});
|
||||||
|
let invert_scroll_toggle =
|
||||||
|
setting_toggle(ctx, "Invert scroll direction", s.invert_scroll, |s, on| {
|
||||||
|
s.invert_scroll = on
|
||||||
|
});
|
||||||
let shortcuts_toggle = setting_toggle(
|
let shortcuts_toggle = setting_toggle(
|
||||||
ctx,
|
ctx,
|
||||||
"Capture system shortcuts (Alt+Tab, Win, \u{2026})",
|
"Capture system shortcuts (Alt+Tab, Win, \u{2026})",
|
||||||
@@ -523,11 +527,17 @@ pub(crate) fn settings_page(
|
|||||||
);
|
);
|
||||||
out.extend(group(
|
out.extend(group(
|
||||||
Some("Keyboard & mouse"),
|
Some("Keyboard & mouse"),
|
||||||
vec![described(
|
vec![
|
||||||
|
described(
|
||||||
shortcuts_toggle,
|
shortcuts_toggle,
|
||||||
"Alt+Tab, the Windows key and friends reach the host while the stream has \
|
"Alt+Tab, the Windows key and friends reach the host while the stream \
|
||||||
input captured. Off, they act on this machine instead.",
|
has input captured. Off, they act on this machine instead.",
|
||||||
)],
|
),
|
||||||
|
described(
|
||||||
|
invert_scroll_toggle,
|
||||||
|
"Reverses the wheel and trackpad scroll direction sent to the host.",
|
||||||
|
),
|
||||||
|
],
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
("Input", out)
|
("Input", out)
|
||||||
|
|||||||
@@ -533,6 +533,10 @@ pub struct Settings {
|
|||||||
/// wait only adds a delay.
|
/// wait only adds a delay.
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
pub auto_wake: bool,
|
pub auto_wake: bool,
|
||||||
|
/// Reverse the wheel/trackpad scroll direction sent to the host (the Apple client's
|
||||||
|
/// "Invert scroll direction"). Default off = the host scrolls the way this machine does.
|
||||||
|
#[serde(default)]
|
||||||
|
pub invert_scroll: bool,
|
||||||
/// Match-window resolution policy (design/midstream-resolution-resize.md D1): the
|
/// Match-window resolution policy (design/midstream-resolution-resize.md D1): the
|
||||||
/// stream mode follows the session window — the connect asks for the window's pixel
|
/// stream mode follows the session window — the connect asks for the window's pixel
|
||||||
/// size and a mid-session resize renegotiates the host's virtual display + encoder
|
/// size and a mid-session resize renegotiates the host's virtual display + encoder
|
||||||
@@ -622,6 +626,7 @@ impl Default for Settings {
|
|||||||
fullscreen_on_stream: true,
|
fullscreen_on_stream: true,
|
||||||
library_enabled: false,
|
library_enabled: false,
|
||||||
auto_wake: true,
|
auto_wake: true,
|
||||||
|
invert_scroll: false,
|
||||||
match_window: false,
|
match_window: false,
|
||||||
last_window_w: 0,
|
last_window_w: 0,
|
||||||
last_window_h: 0,
|
last_window_h: 0,
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ pub struct Capture {
|
|||||||
/// The touchscreen input model for this session, and — for trackpad/pointer — the
|
/// The touchscreen input model for this session, and — for trackpad/pointer — the
|
||||||
/// gesture state machine finger events feed.
|
/// gesture state machine finger events feed.
|
||||||
touch_mode: TouchMode,
|
touch_mode: TouchMode,
|
||||||
|
/// Reverse the scroll direction sent to the host ([`Settings::invert_scroll`]).
|
||||||
|
invert_scroll: bool,
|
||||||
gestures: Gestures,
|
gestures: Gestures,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +70,11 @@ fn send(connector: &NativeClient, kind: InputKind, code: u32, x: i32, y: i32, fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Capture {
|
impl Capture {
|
||||||
pub fn new(connector: Arc<NativeClient>, touch_mode: TouchMode) -> Capture {
|
pub fn new(
|
||||||
|
connector: Arc<NativeClient>,
|
||||||
|
touch_mode: TouchMode,
|
||||||
|
invert_scroll: bool,
|
||||||
|
) -> Capture {
|
||||||
Capture {
|
Capture {
|
||||||
connector,
|
connector,
|
||||||
captured: false,
|
captured: false,
|
||||||
@@ -79,6 +85,7 @@ impl Capture {
|
|||||||
scroll_acc: (0.0, 0.0),
|
scroll_acc: (0.0, 0.0),
|
||||||
touch_slots: HashMap::new(),
|
touch_slots: HashMap::new(),
|
||||||
touch_mode,
|
touch_mode,
|
||||||
|
invert_scroll,
|
||||||
gestures: Gestures::new(touch_mode == TouchMode::Trackpad),
|
gestures: Gestures::new(touch_mode == TouchMode::Trackpad),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,9 +201,10 @@ impl Capture {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.flush_motion(); // scroll happens at the latest cursor position
|
self.flush_motion(); // scroll happens at the latest cursor position
|
||||||
|
let sign = if self.invert_scroll { -1.0 } else { 1.0 };
|
||||||
let (mut ax, mut ay) = self.scroll_acc;
|
let (mut ax, mut ay) = self.scroll_acc;
|
||||||
ay += f64::from(dy) * 120.0;
|
ay += f64::from(dy) * 120.0 * sign;
|
||||||
ax += f64::from(dx) * 120.0;
|
ax += f64::from(dx) * 120.0 * sign;
|
||||||
let vy = ay.trunc() as i32;
|
let vy = ay.trunc() as i32;
|
||||||
if vy != 0 {
|
if vy != 0 {
|
||||||
ay -= f64::from(vy);
|
ay -= f64::from(vy);
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ pub struct SessionOpts {
|
|||||||
/// `Pointer` (absolute cursor), or `Touch` (real multi-touch passthrough). Latched per
|
/// `Pointer` (absolute cursor), or `Touch` (real multi-touch passthrough). Latched per
|
||||||
/// session — a mouse-only client leaves this at the default and never sees a finger.
|
/// session — a mouse-only client leaves this at the default and never sees a finger.
|
||||||
pub touch_mode: TouchMode,
|
pub touch_mode: TouchMode,
|
||||||
|
/// Reverse the scroll direction sent to the host ([`Settings::invert_scroll`]).
|
||||||
|
pub invert_scroll: bool,
|
||||||
/// Emit the `{"ready":true}` stdout line after the first presented frame.
|
/// Emit the `{"ready":true}` stdout line after the first presented frame.
|
||||||
pub json_status: bool,
|
pub json_status: bool,
|
||||||
/// Called once on `Connected` with the host's fingerprint (trust persistence is the
|
/// Called once on `Connected` with the host's fingerprint (trust persistence is the
|
||||||
@@ -811,7 +813,7 @@ fn run_inner(mut opts: SessionOpts, mut mode: ModeCtl) -> Result<Option<Outcome>
|
|||||||
.ok();
|
.ok();
|
||||||
gamepad.attach(c.clone());
|
gamepad.attach(c.clone());
|
||||||
st.clock_offset = Some(c.clock_offset_shared());
|
st.clock_offset = Some(c.clock_offset_shared());
|
||||||
let mut cap = Capture::new(c.clone(), opts.touch_mode);
|
let mut cap = Capture::new(c.clone(), opts.touch_mode, opts.invert_scroll);
|
||||||
cap.engage(); // capture engages when the stream starts (ui_stream parity)
|
cap.engage(); // capture engages when the stream starts (ui_stream parity)
|
||||||
apply_capture(&mut window, &mouse, true);
|
apply_capture(&mut window, &mouse, true);
|
||||||
st.capture = Some(cap);
|
st.capture = Some(cap);
|
||||||
|
|||||||
Reference in New Issue
Block a user