Skip to content

Feature: Global workspace sync for multi-monitor setups - #12978

Open
amacieli wants to merge 2 commits into
omacom:quattrofrom
amacieli:feature/global-workspaces-fixes-v2
Open

amacieli wants to merge 2 commits into
omacom:quattrofrom
amacieli:feature/global-workspaces-fixes-v2

Conversation

@amacieli

Copy link
Copy Markdown

Implements synchronized workspace switching across all monitors.

All fixes tested on Hyprland 0.56.2 with 3-monitor setup. Addresses review comments from garethevs3 (PR #10199).

Implements synchronized workspace switching across all monitors.

- Issue #1: Move workspace materialization to toggles file (correct load order)
- Issue omacom#2: Update fallback dispatcher syntax for Hyprland 0.56.2+ compatibility
- Issue omacom#3: Add workspace.active event hook for universal sync coverage

All fixes tested on Hyprland 0.56.2 with 3-monitor setup.
Addresses review comments from garethevs3 (PR omacom#10199).
@llstrk

llstrk commented Sep 23, 2026

Copy link
Copy Markdown

The global-mode path is incomplete in this patch. Three source-level integration issues stand out at 13bbe09411f7.

Verified: the local-mode branches use the same Lua dispatcher forms as the existing bindings, and both commands validate slots as 1–10 before interpolation. This is source verification, not a native Hyprland test.

The standard toggle command cannot find the new configuration

omarchy-hyprland-toggle looks in default/hypr/toggles/, but this PR adds the module under config/hypr/toggles/.

Shipped:  config/hypr/toggles/workspace-global.lua
Expected: default/hypr/toggles/workspace-global.lua

Impact: omarchy-hyprland-toggle workspace-global on takes the “Flag not found” branch. The runtime loader reads enabled files from the state directory, not the new module's location, so merely installing this patch does not provide a working opt-in path.

Suggested change: put the module in default/hypr/toggles/ so the existing toggle command can enable it.

Global mode calls helpers that are missing from the patch and base

The pinned tree contains none of these callees:

Entry point Missing helper
omarchy-switch-to-aw global branch omarchy-hyprland-workspace-global-switch
omarchy-move-window-to-aw global branch omarchy-hyprland-workspace-global-move-window
Toggle base-map setup omarchy-monitor-base
Toggle delayed verification omarchy-ensure-workspaces

See the switch branch and base-map setup.

Impact: even if the toggle is enabled manually, the two new commands cannot perform their global operations using the shipped commands. The allocator call produces no mapping, so the Lua code falls back to monitor.id * 10 instead of the advertised stable name-keyed bases; the retry helper is absent too.

Suggested change: include these implementations and their installation, or replace the calls with implemented in-tree logic. Locally installed helpers from the earlier PR would mask this omission.

The bar still excludes the secondary monitors' workspace ranges

Workspaces.qml still lists only raw IDs 1–10 and compares focus/occupancy against those IDs. It is unchanged by this patch.

Source-derived example, not a native observation:
monitor base 10 + slot 2 = workspace 12
bar candidates          = IDs 1–10, never 12

Impact: when workspace 12 is focused, no bar button represents it as focused, and its windows do not contribute to the displayed occupied slots. Synchronizing workspace events cannot repair this display mapping.

Suggested change: make the bar's focus and occupancy mapping aware of global slots when the toggle is enabled, while preserving the existing local-mode behavior.


Review information

Test scope: pinned-source inspection only. No native Hyprland, multi-monitor, hotplug, workspace-event timing, or pointer/focus behavior was exercised.

Community review: Independent automated community review, unaffiliated with the Omarchy team, intended to help prepare PRs for their review.

Automated AI review: Astra Medium inspection and synthesis, with independent Opus 5.5 High and GPT 6 Sol Xhigh technical reviews; findings checked against pinned source.

Three source-level issues identified at 13bbe09 are resolved:

1. Toggle path (llstrk issue #1)
   Move workspace-global.lua to default/hypr/toggles/ so that
   omarchy-hyprland-toggle can locate it via $OMARCHY_PATH/default/hypr/toggles/.
   The previous config/hypr/toggles/ path caused omarchy-hyprland-toggle to
   take the 'Flag not found' branch on every 'on' call.

2. Missing helper scripts (llstrk issue omacom#2)
   Add the four callees that the toggle and dispatcher branches require:

   omarchy-monitor-base sync|get|list
     Allocates and persists stable name-keyed workspace bases in
     ~/.local/state/omarchy/monitor-bases.json. Keyed by monitor OS name
     (e.g. "DP-1"), not transient Hyprland id, to survive hotplug
     reassignment (hyprwm/Hyprland#2601). Called by workspace-global.lua.

   omarchy-hyprland-workspace-global-switch <slot>
     Dispatches all monitors to their slot-N workspace by reading the bases
     file and issuing one hl.dsp.focus dispatch per monitor. Called by
     omarchy-switch-to-aw in global mode.

   omarchy-hyprland-workspace-global-move-window <slot>
     Reads the focused window's monitor name, looks up its stable base, and
     silently moves the window to base+slot. Called by omarchy-move-window-to-aw
     in global mode.

   omarchy-ensure-workspaces
     Delayed post-init verifier: sleeps 1s, checks that all expected workspace
     IDs exist (materialised by Hyprland), re-dispatches any that are missing.
     Called as a background job by workspace-global.lua at config load.

3. Bar slot/focus mapping (llstrk issue omacom#3)
   Rewrite Workspaces.qml to be global-mode aware:
   - Detects the toggle flag via FileView.exists (reactive, live toggle support).
   - Adds slotOfId(): maps raw workspace IDs back to logical slots 1–10 using
     ((id - 1) % 10) + 1, so WS 12 (monitor-2 slot 2) correctly maps to slot 2.
   - slotOccupied() and slotFocused() check ALL raw IDs that map to a slot,
     so focused/occupied state is correct when the active workspace is >10.
   - focusWorkspace() routes through omarchy-switch-to-aw in global mode
     (all-monitor sync) vs direct hyprctl in local mode.
   - Local mode (toggle off) is unchanged: slot == raw ID, direct dispatch.

No behavior change in local mode. All changes are additive and gated on the
global-mode flag file.
@amacieli

amacieli commented Sep 23, 2026

Copy link
Copy Markdown
Author

@llstrk Thanks for the detailed review - apologies for the issues; most of them were because I switched over from a prior PR on an older omarchy base.

Issue 1 — Toggle path: workspace-global.lua is now in default/hypr/toggles/ where omarchy-hyprland-toggle expects it ($OMARCHY_PATH/default/hypr/toggles/$FLAG_NAME.lua). Previous location caused "Flag not found" on every on call.

Issue 2 — Missing helpers: Four callees now shipped in bin/: omarchy-monitor-base (stable name-keyed baseallocation, survives hotplug), omarchy-hyprland-workspace-global-switch (all-monitor slot dispatch),omarchy-hyprland-workspace-global-move-window (window move to correct monitor-relative workspace), andomarchy-ensure-workspaces (delayed post-init workspace verifier).

Issue 3 — Bar mapping: Workspaces.qml now detects the toggle flag via FileView.exists (reactive), maps raw IDs toslots via ((id - 1) % 10) + 1 so WS 12 on a base-10 monitor correctly lights slot 2, and routes bar clicks throughomarchy-switch-to-aw in global mode. Local mode behavior is unchanged.

Cheers!

amacieli added a commit to amacieli/omarchy-global-workspaces that referenced this pull request Sep 23, 2026
Installs all 7 files now in the PR:
- default/hypr/toggles/workspace-global.lua  → $OMARCHY_PATH/default/hypr/toggles/
- bin/omarchy-switch-to-aw                   → ~/.local/bin/
- bin/omarchy-move-window-to-aw              → ~/.local/bin/
- bin/omarchy-monitor-base                   → ~/.local/bin/
- bin/omarchy-hyprland-workspace-global-switch        → ~/.local/bin/
- bin/omarchy-hyprland-workspace-global-move-window   → ~/.local/bin/
- bin/omarchy-ensure-workspaces              → ~/.local/bin/
- shell/plugins/bar/widgets/Workspaces.qml   → $OMARCHY_PATH/shell/ (backed up)

Previous install.sh only handled 2 scripts and used the old toggle path.
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.

2 participants