#16143

Refresh floating workspace exclusions for late personal rules

Openzihaomuwants to merge intofrom

Summary

Fixes #16114 by refreshing floating-workspace exclusions when personal window rules register after saved workspace modes. This implements the change notification suggested in the issue.

The first matching window now stays outside the floating mode's ownership, just like subsequent matching windows. Ending floating mode leaves these windows floating.

Why the first window is affected

The shipped hyprland.lua loads saved workspace modes through default.hypr.toggles before its personal-configuration section. A saved floating mode builds its opening rules from the float patterns currently recorded in o.floating_apps.

A later o.window(..., { float = true }) records a new pattern, but the generated exclusions previously stayed unchanged. The first matching window therefore received the mode's size and opening tag. claim_opened() claimed that window and refreshed the rules, making subsequent matching windows behave correctly. The incorrect ownership also caused the first window to become tiled when floating mode ended.

Fix logic

  1. Track whether o.window() records a float pattern or a class/title-to-tag relationship.
  2. After registering the window rule, notify o.floating_apps_changed when that registry changed.
  3. Set that hook to sync_open_rules() in the workspace-mode module, so exclusions are current before the first matching window opens. Notifying for both float rules and tagging rules handles either registration order.
  4. Clear the previous hook when helpers reload, avoiding calls into the preceding configuration's workspace-mode state.

Unrelated window rules do not trigger a refresh. The fix uses the existing rule-generation path and adds no polling or configuration migration.

Regression coverage

The added regression fails against unchanged production code with a late class float rule did not refresh the first-window exclusion, then passes with this patch.

Five new regression groups cover late class/title rules, either half of a late tag relationship, both tag-related rules registered late in either order, multiple floating workspaces and disabled modes, and avoiding unrelated refreshes or stale callbacks after helpers reload.

Focused validation completed on the submitted sources:

SuitePassing checks
Floating workspaces45
Workspace layout15
Workspace-mode migration2
Total62
OMARCHY_PATH="$PWD" bash test/shell.d/hyprland-floating-workspaces-test.sh
OMARCHY_PATH="$PWD" bash test/shell.d/hyprland-workspace-layout-test.sh
OMARCHY_PATH="$PWD" bash test/shell.d/workspace-layout-mode-migration-test.sh
luac -p default/hypr/helpers.lua
luac -p default/hypr/workspace-modes.lua
bash -n test/shell.d/hyprland-floating-workspaces-test.sh
git diff --check

Native before/after result

Reproduced using the real Omarchy modules in a sandboxed, nested Hyprland 0.56.2 compositor accelerated by a Radeon 8060S on a Ryzen AI Max+ PRO 395. The configuration restores a floating workspace before registering the personal rule. Two matching foot terminals request 100×8 cells, resolving to 600×120 pixels in this fixture; an ordinary terminal checks that workspace mode still manages normal windows.

ObservationUnchanged upstreamWith this patch
First class-matching terminal436×578, incorrectly mode-owned600×120, unclaimed
Second class-matching terminal600×120, unclaimed600×120, unclaimed
First matching terminal when floating mode endsIncorrectly tiledRemains floating at 600×120
Ordinary control terminalMode-owned, then tiled on mode exitMode-owned, then tiled on mode exit

All 16 native comparison assertions passed, including title-rule ownership, mode exit, and completion without configuration errors. Before/after screenshots were also inspected.

Validation scope

The title-only case also stops being claimed and remains floating on mode exit. In this minimal nested configuration, however, its first terminal negotiates 682×850 even with the personal rule registered early on unchanged upstream. The patched late-rule case matches that unaffected early-rule control. This patch corrects stale exclusions and mode ownership; it does not establish a general fix for initial title-based size negotiation.

The comparison uses current upstream modules in an isolated configuration, rather than a full installed Omarchy 4.5 session. Confirmation in the reporter's complete configuration would be useful.

Activity

2
greptile-apps[bot]13h ago

Confidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues were found.

Summary

Updates floating-workspace exclusions as personal window rules are registered, before the first matching window opens.

  • Late personal window rules now update floating-workspace exclusions.

No actionable issues were found. Review checks were based on source inspection and a clean git diff --check; no runtime or visual verification was performed.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Personal window rule] --> B[Update floating-app records]
  B --> C[Register the window rule]
  C --> D{Relevant records changed?}
  D -->|Yes, callback installed| E[Refresh opening rules]
  E --> F[Exclude apps with their own float rules]
  D -->|No| G[No refresh]

Reviews (1) · Last reviewed commit: "Refresh floating workspace exclusions fo..." · Reviewed by Greptile