Skip to content

Rebase the Cua Hyprland plugin on Driver 0.32.0 for Hyprland 0.56.2-4 - #772

Merged
spencerbull merged 4 commits into
masterfrom
cua-hyprland-plugin-0.32.0
Oct 4, 2026
Merged

spencerbull merged 4 commits into
masterfrom
cua-hyprland-plugin-0.32.0

Conversation

@spencerbull

@spencerbull spencerbull commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Edge now carries Arch's hyprland 0.56.2-4, and the published cua-hyprland-plugin 0.28.2-2 pins hyprland=0.56.2-3, so omarchy update fails for every edge user with the plugin installed: installing hyprland (0.56.2-4) breaks dependency 'hyprland=0.56.2-3' required by cua-hyprland-plugin. This release, 0.32.0-3, pins -4, and an update takes Hyprland and the plugin together.

-4 is the same 0.56.2 source rebuilt against vulkan-sdk 1.4.363 and glslang, with the same GCC 16.2.1 20260810 and libstdc++. Only the executable and two of its 497 headers differ, so the derivation now also takes the compositor executable and header-inventory hashes, measured from -4 the way the kit's profile_verify.py measures them; the same method reproduces the kit's -3 values exactly. Compiler, runtime, header version, tooling and source identities stay Cua's, the derivation still refuses any other profile change, and at build time the verifier checks the measured values against the installed Hyprland. A new Hyprland release, compiler or libstdc++ still needs a kit from Cua (trycua/cua#4216). The profile is omarchy-hyprland-0562r4-remaps.

The plugin is built from the Driver 0.32.0 source. That gives agent keyboards the user seat's repeat rate and delay instead of repeat_info(0, 0), which crashed single-seat clients such as imv and cut Zed off from the user's input (trycua/cua#4257). Driver 0.31.0 also took the independent agent keymaps and Num Lock handling from #473 upstream, so the old keymap patch is gone. What remains is downstream.patch, applied through the same downstream.py machinery as before, with every resulting file pinned in DOWNSTREAM-PROVENANCE.json. It makes two changes.

Foreground typing. Upstream refuses all foreground typing unless every key the KEY command can press types the US keysym, modifier keys included, which blocks typing under ctrl:swapcaps, compose:ralt, altwin:swap_alt_win or compose:102. The patch replaces that up-front check with one that runs the existing per-chord check over exactly the chords Driver types text with (ASCII on the US main block, with and without Shift, as text_actions in Driver's hyprland_input.rs sends them), with Num Lock off and on. A string is still admitted or refused before its first key, and every other key is left to the per-chord check, so under ctrl:swapcaps plain text types and Ctrl+A is refused. Stock Omarchy options and the us,<layout> plus grp:alts_toggle setup Omarchy writes for non-Latin layouts qualify; Dvorak, Colemak, French, German and US International do not.

Input-method popups. With input enabled, fcitx5 requests an input method for each of the three seats, and when it exits, which Omarchy's omarchy-restart-xcompose does, Hyprland 0.56.2 can be left with an input-method popup that is still mapped although its wl_surface is gone: the popup's surface-destroy handler emits unmap but never clears m_mapped. Tearing down the input method then updates every popup, CInputPopup::updateBox dereferences the missing surface, and Hyprland restarts in safe mode, taking the session with it. The patch hooks CInputPopup::updateBox and CInputPopup::shouldBeRendered through Hyprland's function-hook API so that a popup without a surface is neither placed nor rendered. The hooks are compiled into the module only, installed at load and removed at unload, and hyprctl -j cua:status reports ime_popup_guard: true when both are active. The fault itself is Hyprland's.

cua-driver-bin stays at 0.28.2, which speaks the same input protocol v3 to this source: Driver 0.28.3 through 0.32.0 refuse desktop screenshots on Hyprland when more than one output is active, or when the only output is away from 0,0, where 0.28.2 captures (trycua/cua#4161).

🤖 Generated by Opus 5.5 in Claude Code. Reviewed by Codex XHigh.

Driver 0.31.0 took the independent agent keymaps and Num Lock handling from #473 upstream, so independent-keymaps.patch goes. Upstream also added an up-front check that every key the KEY command can press types the US keysym, modifier keys included, which refuses all foreground typing under ctrl:swapcaps, compose:ralt, altwin:swap_alt_win or compose:102. foreground-remaps.patch makes that check run the per-chord check every key already passes over exactly the chords Driver types text with, with Num Lock off and on, so a string is still admitted or refused before its first key and other remaps are left to the per-chord check.

0.32.0 also gives agent keyboards a real repeat rate, which stops single-seat clients like imv crashing on an agent seat (trycua/cua#4257).

cua-driver-bin stays at 0.28.2, which speaks the same input protocol v3: Driver 0.28.3 through 0.32.0 refuse desktop capture on Hyprland with more than one output or with one away from the origin (trycua/cua#4161).

Co-Authored-By: Codex XHigh <noreply@openai.com>
@spencerbull

Copy link
Copy Markdown
Contributor Author

End-to-end run on omabot workers built from the Omarchy ISO and switched to the edge channel (Hyprland 0.56.2-3, Aquamarine 0.15.1-1, glibc 2.44+r50, GCC 16.2.1), driven by Opus 5.5 in Claude Code. Codex XHigh reviewed the diff in four rounds. Its findings shaped the gate: the upstream remap regression, a text chord the first gate missed, and Num Lock. The last round found nothing.

Build. makepkg -s on an edge worker resolved every exact pin. The patch applied with zero fuzz, the downstream tooling tests passed, and all 20 plugin CTests passed in both check() and package(). In mutation checks, the new equivalence tests fail if the gate drops its Shift pass, its Num Lock pass, or Tab and Return from the text keys.

Upgrade. Starting from the published edge cua-driver-bin 0.28.2-3 and cua-hyprland-plugin 0.28.2-2, with this package served from a local repository ahead of [omarchy], omarchy update -y upgraded only the plugin. The installed consumer check, hyprctl -j cua:status (input protocol 3, keyboard_layout_independent, foreground_numlock_compatible), and disable, remove and reinstall all passed.

#4257. With the published 0.28.2-2 plugin loaded, imv-wayland binds Cua-Agent-2, receives repeat_info(0, 0) and dies with SIGFPE (exit 136). With this package it receives repeat_info(40, 250) and keeps running.

Background input. With the terminal focused, Driver sent Inkscape 1.4.4-6 the rectangle-tool key, a drag, and Ctrl+S through the agent lane. The saved SVG gained a <rect>, focus stayed on the terminal, and the user's pointer never moved (screenshot below).

Foreground typing into the focused terminal, echo ok > file then Return:

Keyboard 0.28.2-2 (published) 0.32.0 unpatched this package
Omarchy default (compose:caps,shift:both_capslock_cancel) types types types
ctrl:swapcaps types refused types
compose:ralt types refused types
compose:caps,altwin:swap_alt_win types refused types
compose:102 not run not run types
us,ru + grp:alts_toggle types types types
us(dvorak) refused refused refused

Under ctrl:swapcaps, a foreground Ctrl+A is refused with foreground_unsupported_layout while the default keymap dispatches it. Omarchy turns Num Lock on by default, and it was on throughout. ctrl:swapcaps and compose:ralt were also set in ~/.config/hypr/input.lua and checked from a fresh boot, with the same results.

Driver. Desktop and window captures with the 0.28.2 driver succeed at scale 1, 1.25 and 1.6, and with two monitors. Driver 0.32.0 refuses the desktop capture with two monitors or a single monitor at 1920,0, with or without this plugin loaded, which is why cua-driver-bin stays where it is.

Foreground commands typed under each keyboard configuration (left); the rectangle Driver drew in Inkscape through the agent lane while the terminal kept focus (right)

@spencerbull

Copy link
Copy Markdown
Contributor Author

Hardware run and a crash investigation, both by Opus 5.5 in Claude Code; no second-opinion review ran on either.

Hardware. CI's artifact for this PR (cua-hyprland-plugin-0.32.0-2, SHA-256 763a54cb…, the file publish uses) was installed over the published 0.28.2-2 on a Dell XPS 16 on edge, with the panel at scale 2 and a 5120×2160 external at 1.6. The installed consumer check, loading into the running compositor, input protocol 3 on both lanes, imv receiving repeat_info(40, 250), and the foreground typing table all matched the worker results. Driver 0.28.2 captured the desktop on that two-monitor layout and Driver 0.32.0 refused it, as on the workers.

Hyprland crash. Partway through that run Hyprland 0.56.2 crashed and restarted in safe mode. Symbolized with Arch's debug info, the fault is in Hyprland's input-method handling: when the input-method client (fcitx5) disconnects, the relay's destroy listener updates every input-method popup and CInputPopup::updateBox faults (InputMethodRelay.cpp:45 → TextInput.cpp:254 → InputMethodRelay.cpp:104 → InputMethodPopup.cpp:108). fcitx5 requests an input method for every wl_seat, so the plugin's two agent seats are part of the setup. 25 rounds of the same keyboard and fcitx5-restart sequence per configuration, on edge workers:

Configuration Hyprland crashes
No plugin 0
Published 0.28.2-2, input enabled 3
This PR, input enabled 3
This PR, loaded with input disabled 0

This PR does not change the exposure: the published plugin crashes at the same rate. It takes input enabled and fcitx5 exiting, which Omarchy does in omarchy-restart-xcompose (Setup → XCompose in the menu, and migration 1788102906). The fault is Hyprland's and is unchanged on its main; a report to Hyprland and a note on trycua/cua#4257, whose plan for agent seats that exist only during an agent session would remove the exposure, are drafted.

spencerbull and others added 3 commits October 3, 2026 16:52
With plugin input enabled, fcitx5 requests an input method for each of the three seats, and when it exits Hyprland 0.56.2 can still hold an input-method popup that is mapped although its wl_surface is gone: the popup's surface-destroy handler emits unmap but never clears m_mapped. Tearing down the input method then updates every popup, CInputPopup::updateBox dereferences the missing surface and Hyprland restarts in safe mode. Omarchy's omarchy-restart-xcompose reaches this in normal use.

The plugin now hooks CInputPopup::updateBox and CInputPopup::shouldBeRendered so a popup whose getSurface() is empty is neither placed nor rendered, reports the guard in cua:status, and removes the hooks on unload. The guard is compiled into the module only, so the mock-based tests are unchanged. foreground-remaps.patch becomes downstream.patch now that it carries both changes.
Arch rebuilt Hyprland 0.56.2 against vulkan-sdk 1.4.363 and glslang. The executable and two headers change, so the plugin's exact compositor pin and hashes would block hyprland upgrades for anyone with it installed, and Cua's kit has no profile for it (trycua/cua#4216). The release, compiler and runtime are unchanged, so the derivation now also takes the re-measured compositor executable and header inventory; the build's verifier checks both against the installed package.
The guard is installed best effort, so the README promises the fix only while it is active, and the activation checklist now asks for ime_popup_guard: true. 'No hooks' meant package-manager hooks, which the plugin's new function hooks made ambiguous.

Co-Authored-By: Codex XHigh <noreply@openai.com>
@spencerbull spencerbull changed the title Rebase the Cua Hyprland plugin on Driver 0.32.0 and keep foreground typing under key remaps Rebase the Cua Hyprland plugin on Driver 0.32.0 for Hyprland 0.56.2-4 Oct 3, 2026
@spencerbull

Copy link
Copy Markdown
Contributor Author

Evidence for the current head (09f4e5b8, package 0.32.0-3), run by Opus 5.5 in Claude Code on omabot workers built from the Omarchy ISO and switched to edge. Codex XHigh reviewed the input-method guard and found no implementation defect; its three README corrections are in 09f4e5b8. It earlier reviewed the Hyprland -4 re-measurement and found nothing.

Update path on the real edge mirror (Hyprland 0.56.2-4 since 2026-10-03 21:30 UTC). A worker with the published cua-driver-bin 0.28.2-3, cua-hyprland-plugin 0.28.2-2 and Hyprland -3 fails omarchy update -y with installing hyprland (0.56.2-4) breaks dependency 'hyprland=0.56.2-3' required by cua-hyprland-plugin, exit 1. With this package served from a local repository ahead of [omarchy], the same command upgraded 17 packages, Hyprland -4 and cua-hyprland-plugin 0.32.0-3 among them, exit 0.

Build. makepkg -s on edge with Hyprland -4: the kit verifier accepted the re-measured compositor and headers, downstream.patch applied with zero fuzz, and all 20 plugin CTests passed in both check() and package(). The guard is compiled into the module only (ime_popup_guard.cpp), so the mock-based tests are unchanged.

Input-method crash. The crash this release guards against is a Hyprland 0.56.2 fault: a core dump shows an input-method popup still marked mapped after its wl_surface was destroyed, and CInputPopup::updateBox dereferencing the missing surface while fcitx5's input method is torn down (InputMethodPopup.cpp:106). The same keyboard and fcitx5-restart sequence, 25 rounds per configuration on edge workers:

Configuration Hyprland crashes
No plugin 0
Published 0.28.2-2, input enabled 3
0.32.0-2 without the guard, input enabled 3
0.32.0-2 loaded, input disabled 0
Guard on Hyprland -3, input enabled 0
This package on Hyprland -4, input enabled 0

After the upgrade, rebooted into Hyprland -4: the installed consumer check, hyprctl -j cua:status with input protocol 3, keyboard_layout_independent, foreground_numlock_compatible and ime_popup_guard: true, imv receiving repeat_info(40, 250) on an agent seat, background key, drag and save into Inkscape 1.4.4-6 with focus and pointer unchanged, foreground typing under Omarchy's default options, ctrl:swapcaps, compose:ralt, altwin:swap_alt_win, compose:102 and us,ru with grp:alts_toggle, Dvorak refused, Ctrl+A refused under ctrl:swapcaps and dispatched otherwise, ctrl:swapcaps and compose:ralt from input.lua at a fresh boot, Driver 0.28.2 captures at scale 1, 1.25, 1.6 and with two monitors, and disable, remove and reinstall all passed, with no Hyprland crash during the run.

CI's artifact. The package this PR's CI built and would publish (cua-hyprland-plugin-0.32.0-3, SHA-256 fefc3c16…, carrying the committed downstream.patch) was installed on an edge worker with Hyprland -4 and passed the same suite, ime_popup_guard: true included, with no Hyprland crash.

@spencerbull

Copy link
Copy Markdown
Contributor Author

Re-tested at head 09f4e5b8 on real hardware, a Dell XPS 16 on Omarchy edge with the maintainer's own configuration (compose:caps, Num Lock on, fcitx5), run by Opus 5.5 in Claude Code. Codex XHigh reviewed the whole diff at this head and found nothing that should block the merge; it independently reconstructed every derived kit digest and the re-measured executable and header hashes, including exactly two changed headers out of 497, and checked the typing gate's 97 chords against Driver 0.28.2's text_actions with 15 keyboard configurations, Num Lock off and on.

The update path. With the published pair installed (hyprland 0.56.2-3, cua-hyprland-plugin 0.28.2-2), a system upgrade against the live edge mirror fails with installing hyprland (0.56.2-4) breaks dependency 'hyprland=0.56.2-3' required by cua-hyprland-plugin, exit 1. With this PR's CI artifact (fefc3c16…, the file publish reuses for this tree) served ahead of [omarchy], the same upgrade run from inside the session succeeds: 14 packages, Hyprland 0.56.2-4 and cua-hyprland-plugin 0.32.0-3 among them, pacman -Qkk clean and the running session unaffected.

Fresh session, following the README's activation section. The running compositor's executable hashes to the re-measured 55da553b…, the consumer check with kit 3c2141dc… passes, and loading reports input protocol 3, both lanes bound, and keyboard_layout_independent, foreground_numlock_compatible and ime_popup_guard all true. In a disposable Inkscape 1.4.4-6 document, with a terminal holding focus throughout, two background keys and a drag drew the rectangle exactly where asked, Ctrl+S saved it, and the reopened SVG shows it. Foreground typing of a line containing every printable ASCII class into the focused terminal arrived byte for byte, and omarchy-restart-xcompose with input enabled left Hyprland running and typing working afterwards.

Two limitations, both pre-existing and unchanged by this PR:

  • Foreground typing that has to move focus to its target stops after two or three keys while fcitx5 is running. fcitx5 re-sends its unchanged keymap each time a window with a text field gains focus (two activelayout>>hl-virtual-keyboard-fcitx5 events per switch), and the plugin's keymap listener treats every keymap event as a desktop transition and closes the action connection. The published 0.28.2-2 fails the same way on this machine (3 of 3), typing into an already focused window works on both, and with fcitx5 stopped the focus-switching case types completely. A follow-up can ignore a re-sent keymap whose text is unchanged.
  • When an application's surface is larger than its tile, Hyprland scales it down and pointer input lands scaled with it (about 0.78× in X for Inkscape in a 781 px tile, which happens on its own when Inkscape reopens at a remembered size), because target_geometry treats the surface as the tile's size. The same code is in 0.28.2.

Ready to merge; it is waiting on a maintainer. Publishing reuses the PR artifact for seven days from the 2026-10-03 build.

🤖 Generated by Opus 5.5 in Claude Code. Reviewed by Codex XHigh.

Inkscape after the background keys and drag, terminal focused

The saved SVG reopened

@spencerbull
spencerbull merged commit a2c3571 into master Oct 4, 2026
6 checks passed
@spencerbull
spencerbull deleted the cua-hyprland-plugin-0.32.0 branch October 4, 2026 03:37
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Publish succeeded → live

Packages: cua-hyprland-plugin (x86_64, PR artifact)

  • edge/x86_64: cua-hyprland-plugin-0.32.0-3-x86_64

Commit a2c3571 · run

@spencerbull

Copy link
Copy Markdown
Contributor Author

Release check for the published package, as the README's Ownership and publication section asks, run by Opus 5.5 in Claude Code. Edge's database lists cua-hyprland-plugin 0.32.0-3 with SHA-256 fefc3c16…, the CI artifact tested above, depending on hyprland=0.56.2-4; publish reused that artifact rather than rebuilding.

On a fresh Omabot worker built from the Omarchy ISO and switched to edge, and on a Dell XPS 16 on edge, the package installed from the edge repository with pacman validating checksum and signature. In a fresh session the consumer check passed, the module loaded with input protocol 3 and ime_popup_guard: true, Inkscape 1.4.4-6 took background keys, a drag and a save with a terminal focused (the rectangle within a pixel of the requested bounds, found in the saved SVG), and an agent drove Chromium, LibreOffice Writer and a terminal through the foreground route. Disabling input and removing the package left nothing behind. The full run is on omacom/omarchy#11342.

🤖 Generated by Opus 5.5 in Claude Code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant