Optimise the AVX 2 implementation reducing number of operations per block
and also add an AVX-512 implementation used when the CPU supports it at
runtime.
Mostly comes from detecting the case of runs of ASCII printable
characters and using a special fast path for them. Improves benchmarks
as per benchmark.py by 15-30% for text heavy workloads
surfaceHandleEnter() and surfaceHandleLeave() passed the event's output
argument straight to wl_output_get_user_data(). Wayland delivers object
arguments as NULL when the object was destroyed client-side before the
event was dispatched, even for arguments declared non-nullable, so this
segfaults whenever a wl_output global goes away while a window is open.
Easily reproduced with a hardware KVM or a monitor input switch.
Also fixes two pre-existing problems in surfaceHandleLeave():
- The removal loop stopped at monitorsCount - 1, so it never compared the
last entry, and the trailing unconditional
window->wl.monitors[--window->wl.monitorsCount] = NULL
dropped the last monitor whether or not it was the one that was left.
A leave for a monitor not in the list therefore evicted an unrelated
one.
- That same statement ran even when monitorsCount was 0, writing to
monitors[-1] and leaving the count negative.
Both are replaced with the remove_i_from_array() loop already used for
this array in registryHandleGlobalRemove().
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
resetScrollValuators() runs on every LeaveNotify, clearing the initialized
flag of every scroll valuator. handle_xi_motion_event() then treats the next
XI_Motion event as a baseline sample and discards it.
On setups where the X server emits crossing events with mode NotifyGrab
faster than the wheel is turned, every scroll event lands in that branch and
is swallowed, so scrolling does not work at all. This is easy to hit inside a
VMware guest, where the same physical mouse is exposed as several pointer
devices: --debug-input shows a continuous leave/enter cycle and a single
Scroll event for the whole session.
Fix this in two places:
- Do not reset the baseline for crossing events generated by a grab being
activated/released or by the pointer moving to a child window, since the
pointer did not actually leave.
- Keep the baseline value across a reset so the next event can still compute
a delta from it, and only discard the event when the jump is too large to
be a genuine scroll.
Fixes#9846
main()'s error path after handle_action fails (e.g. malformed
--ssh-connection-data, or a ControlMaster connect failure) was missing the
reset_terminal() call Python's equivalent except-path makes
(kittens/remote_file/main.py pre-shrink: `except Exception: print(reset_terminal(),
...); traceback.print_exc(); show_error(...)`). Without it, the error rendered
over the stale ask-menu screen instead of a clean one. Added reset_terminal()
before show_error(), matching the other four call sites already added for
this kitten.
Verified: launched `kitten remote-file --path /nonexistent --hostname x
--ssh-connection-data 'not-json'` in a disposable kitty instance, selected an
action to trigger the parse failure, and confirmed via `get-text`/`get-text
--extent=all` that only the error message is present -- no ask-menu leftovers.
Adds kittens/remote_file/main.go (ask menu, hostname-mismatch prompt,
save-path prompt with tab completion, edit/open/save actions) on top of the
ControlMaster/ssh helpers from the previous two commits, registers it in
tools/cmd/tool/main.go, and adds remote_file to shell-integration/ssh/kitty's
wrapped_kittens list so both `kitty +kitten remote_file` and ssh-session
invocations exec the Go binary directly. main.py is shrunk to option_text
(kept importable by kitty/cli_stub.py and used for --doc/--help generation),
is_ssh_kitten_sentinel (kept importable by kitty/window.py), and the
handle_result shim boss.py runs in-process to open the returned file.
Also drops the dead `-h` alias on --hostname: Python's CLI layer always
special-cases -h/--help ahead of user options, so it never worked as a
hostname shorthand, but the Go CLI layer hard-errors on the collision; removing
it is a no-op for existing behavior (boss.py only ever passes --hostname) and
unblocks `kitten remote-file --help`. Also adds the same reset_terminal()
calls Python makes between UI phases (ask menu -> action, hostname-mismatch
prompt, overwrite prompt, $EDITOR handoff) so the Go and Python screens match.
Manually verified parity against Python (ask menu, cancel, open/edit/save
download+upload round-trips, hostname-mismatch Y/N, save-path prompt and
overwrite O/A/R/N) using a fake-ssh test double, and confirmed post-wrap that
`kitty +kitten remote_file` execs the Go kitten binary.
On X11 glfw_xkb_compile_keymap() gets its state from
xkb_x11_state_new_from_device(), which seeds it with the server's physical
modifier mask. Every other path into that state goes through
glfw_xkb_update_modifiers(), where the permutation is applied, so after a
keymap reload the state held physical modifiers until the next XkbStateNotify
happened to arrive. Any key pressed in that window was encoded with the
modifier on the keycap: with ctrl held across a reload under
`remap_modifiers ctrl:super`, Ctrl+A reached the child as a literal 0x01.
Keymap reloads are routine - switching layout causes one, and so does any
client asking X for a keysym it must bind to a spare keycode.
Re-apply the permutation to the freshly loaded state, after
glfw_xkb_update_masks() has computed the modifier indices it is expressed in.
On Wayland the new state is empty, so this is a no-op there.