You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature request: bind workspaces to a monitor by stable identifier (device path / hardware id)
Problem
bind_to_monitor takes a numeric index into GlazeWM's geometrically sorted monitor list (leftmost = 0, see wm-platform/src/dispatcher.rs:470). That index depends purely on how displays are arranged, so it changes from desk to desk and there is no way to express "this workspace belongs on this physical screen".
Concrete case (three monitors at the office, two at home):
arrangement
leftmost (index 0)
index 1
index 2
Office desk
laptop panel
primary 1920x1080
second 1920x1080
Home dock
primary ultrawide
laptop panel
—
With keep_alive: true workspaces bound to index 0, every desk change either puts the workspaces on the wrong screen or (worse) leaves a monitor with no matching binding and no inactive workspace left, in which case GlazeWM aborts at startup:
"No workspace config available to activate workspace"
That abort occurred with nine bound workspaces serving two monitors when a third display was connected. The only workarounds today are per-desk config edits or a convention like "always arrange the main screen leftmost in Windows" — the latter is what I currently do, and it is fragile.
Evidence that the identity data already exists
MonitorDto (wm-common/src/dtos/monitor_dto.rs) already carries device_name, device_path and hardware_id, populated from EnumDisplayDevices in wm-platform/src/platform_impl/windows/display.rs:205-232.
More importantly, the matching logic this feature needs already exists. find_matching_monitor in wm/src/events/handle_display_settings_changed.rs matches a display to an existing monitor by:
its handle,
its device path,
its hardware id (guarded by a uniqueness check, since the hardware id identifies a model, not a unit).
That function's own comment documents the trade-offs: handles and device paths are unique but can change; the hardware id is stable but not guaranteed unique.
Proposal
Add a new optional field to WorkspaceConfig, e.g.:
Backwards compatible: bind_to_monitor keeps working exactly as today; a workspace may use either binding, and the id-based one wins when both are set. Matching reuses the precedence semantics of find_matching_monitor — device_path matches first (unique, changes if the cable moves), hardware_id second (stable, ambiguous if two identical monitors are attached). device_name (\\.\DISPLAY1) is also available and has the same caveat as the numeric index but at least survives re-sorting.
Why this solves the reported crash too
With an id-based binding, the "which monitor am I" question no longer depends on sorting at all — move_bounded_workspaces_to_new_monitor can match monitors by identity. The sorted_displays TODO at dispatcher.rs:470 ("Need to assign workspaces after sorting monitors because of bind_to_monitor") is exactly the coupling this would remove.
Implementation outline (v3.10.1)
wm-common/src/parsed_config.rs:384 — extend WorkspaceConfig with bind_to_monitor_id: Option<MonitorBinding> (#[serde(default)]).
wm/src/commands/monitor/add_monitor.rs:52 — extend the filter in move_bounded_workspaces_to_new_monitor to match by identity, reusing find_matching_monitor's comparison semantics.
wm/src/user_config.rs:313 (workspace_config_for_monitor) and :332 (next_inactive_workspace_config) — same.
wm/src/commands/workspace/activate_workspace.rs:37 — resolve the id to a monitor via monitor.native_properties() instead of monitor.index().
wm/src/commands/workspace/update_workspace_config.rs:37-39 and wm-common/src/app_command.rs:430 — carry the new field through the config merge and the invoke update-workspace-config CLI.
resources/assets/sample-config.yaml — document the field. (bind_to_monitor is currently undocumented there at all.)
No new Win32 code is required; the identity plumbing is complete.
Field shape: second field vs. an untagged enum on bind_to_monitor (integer or string)? A second field is simpler and fully backwards compatible; an untagged enum is more ergonomic but a breaking shape change for anyone deserializing the config.
Feature request: bind workspaces to a monitor by stable identifier (device path / hardware id)
Problem
bind_to_monitortakes a numeric index into GlazeWM's geometrically sorted monitor list (leftmost = 0, seewm-platform/src/dispatcher.rs:470). That index depends purely on how displays are arranged, so it changes from desk to desk and there is no way to express "this workspace belongs on this physical screen".Concrete case (three monitors at the office, two at home):
With
keep_alive: trueworkspaces bound to index 0, every desk change either puts the workspaces on the wrong screen or (worse) leaves a monitor with no matching binding and no inactive workspace left, in which case GlazeWM aborts at startup:That abort occurred with nine bound workspaces serving two monitors when a third display was connected. The only workarounds today are per-desk config edits or a convention like "always arrange the main screen leftmost in Windows" — the latter is what I currently do, and it is fragile.
Evidence that the identity data already exists
MonitorDto(wm-common/src/dtos/monitor_dto.rs) already carriesdevice_name,device_pathandhardware_id, populated fromEnumDisplayDevicesinwm-platform/src/platform_impl/windows/display.rs:205-232.More importantly, the matching logic this feature needs already exists.
find_matching_monitorinwm/src/events/handle_display_settings_changed.rsmatches a display to an existing monitor by:That function's own comment documents the trade-offs: handles and device paths are unique but can change; the hardware id is stable but not guaranteed unique.
Proposal
Add a new optional field to
WorkspaceConfig, e.g.:Backwards compatible:
bind_to_monitorkeeps working exactly as today; a workspace may use either binding, and the id-based one wins when both are set. Matching reuses the precedence semantics offind_matching_monitor—device_pathmatches first (unique, changes if the cable moves),hardware_idsecond (stable, ambiguous if two identical monitors are attached).device_name(\\.\DISPLAY1) is also available and has the same caveat as the numeric index but at least survives re-sorting.Why this solves the reported crash too
With an id-based binding, the "which monitor am I" question no longer depends on sorting at all —
move_bounded_workspaces_to_new_monitorcan match monitors by identity. Thesorted_displaysTODO atdispatcher.rs:470("Need to assign workspaces after sorting monitors because ofbind_to_monitor") is exactly the coupling this would remove.Implementation outline (v3.10.1)
wm-common/src/parsed_config.rs:384— extendWorkspaceConfigwithbind_to_monitor_id: Option<MonitorBinding>(#[serde(default)]).wm/src/commands/monitor/add_monitor.rs:52— extend the filter inmove_bounded_workspaces_to_new_monitorto match by identity, reusingfind_matching_monitor's comparison semantics.wm/src/user_config.rs:313(workspace_config_for_monitor) and:332(next_inactive_workspace_config) — same.wm/src/commands/workspace/activate_workspace.rs:37— resolve the id to a monitor viamonitor.native_properties()instead ofmonitor.index().wm/src/commands/workspace/update_workspace_config.rs:37-39andwm-common/src/app_command.rs:430— carry the new field through the config merge and theinvoke update-workspace-configCLI.resources/assets/sample-config.yaml— document the field. (bind_to_monitoris currently undocumented there at all.)No new Win32 code is required; the identity plumbing is complete.
Related issues
bind_to_monitoronly applies on full restart (still the case for existing workspaces; a config reload never re-binds)Open questions for maintainers
bind_to_monitor(integer or string)? A second field is simpler and fully backwards compatible; an untagged enum is more ergonomic but a breaking shape change for anyone deserializing the config.wm-reload-configre-bind ([Bug] Workspaces should be moved to bound monitor on config reload #649), or stay consistent with the current "startup and monitor add only" semantics?