Fixes#9120
Hi-res mouse wheels (like my logitech G502) send scrolls as fractional clicks. On a mac client, fractional events are truncated to zero lines. This fix accumulates those fractional events then emits the entire click 120 units at a time
fix(platform/ei): accumulate smooth scroll into full wheel clicks on server
On Wayland, two-finger smooth scroll events are delivered as per-frame pixel
deltas (e.g. 0.26, 0.53, 1.05 px per event). The previous code quantized
these at the pixel level via `modf()` — any accumulated integer pixel (even
just 1) triggered a wheel event whose value was `pixels * 12`, i.e. 12, 24
or 36 units. Because the deskflow protocol uses 120 units per standard
wheel click, these fractional clicks were silently dropped by the client
compositor and the user saw nothing on the secondary screen until a
very large/fast stroke pushed enough pixels through.
Switch to wheel-click-level accumulation: smooth scroll pixel deltas are
now scaled to fractional wheel-clicks (0.1 per pixel, keeping the 10 px ==
1 click convention) and only dispatched to the client when at least one
full 120-unit click has accumulated. This uses `std::trunc()` (toward
zero) instead of `std::floor()` to avoid spurious clicks on negative
scroll values.
Physical mouse wheels (discrete scroll events, EI_EVENT_SCROLL_DISCRETE)
are unaffected and continue to be forwarded immediately as-is.
- `EiScreen.cpp`: replace `modf()` pixel quantization with fractional
wheel-click accumulation using `std::trunc()`.
- `ScrollRemainder` struct comment: clarify the unit is now fractional
wheel-clicks rather than pixels.
The macOS client mapped every right-hand modifier (Control_R, Shift_R,
Alt_R, Super/Meta_R) to its left-hand virtual key and always emitted the
left device-dependent event flags, so a remote right-side modifier
arrived on the client as the left one. Apps that distinguish the two
(input methods that need Right Shift, hotkeys bound to Right Control,
etc.) never saw the right key.
Map the right-hand KeyIDs to their macOS right virtual keys, teach
isModifier() and setKeyboardModifiers() about them, track which side is
held, and emit the matching NX_DEVICER*KEYMASK device flag. This change
is client-only; the macOS server key map is unchanged.
fixes: #8486
Signed-off-by: rNoz <rnoz.commits@gmail.com>
macOS input methods can expose non-user-selectable keyboard layouts bundled with the input method rather than the user's real selectable keyboard layout. Translating remote key events through those layouts can send IME punctuation semantics to clients instead of the expected ASCII punctuation.
Use the current ASCII-capable keyboard layout when the active input source has no Unicode key layout data and the reported keyboard layout is not directly selectable. Normal selectable keyboard layouts continue to use the existing translation path.
This affects macOS servers forwarding keyboard input to remote clients while an input-method-bundled layout is active.
Remapping the cursor coordinates to the portal edge size makes the mouse
position being relative to the edge size, in a multi-monitor environment
this edge can be in only one of the monitors and the cursor coordinates
got wrong.
This changes uses the full height and the full width of the combined
monitors to set the mouse cursor position, cropped by the portal edge
size.
A BITMAPINFOHEADER with negative biHeight (top-down DIB) caused
std::length_error crash in toIClipboard because 4 * w * h went
negative and wrapped to a huge size_t in string::append.
Fix: use abs(height) for buffer size and SetDIBitsToDevice, and
add null check for CreateDIBSection.
fixes: #9869
TISGetInputSourceProperty returns NULL for an input source that has no
kTISPropertyInputSourceLanguages value, but both loops evaluate
CFArrayGetCount(layoutLanguages) before the "&& layoutLanguages" guard.
The guard is therefore dead and CFArrayGetCount dereferences NULL.
Test the pointer first.
Signed-off-by: rNoz <rnoz.commits@gmail.com>