Skip to content

feat: disambiguate same-named monitors with relative position labels - #593

Open
utahcon wants to merge 2 commits into
domferr:v18.0from
utahcon:feat/monitor-position-names
Open

feat: disambiguate same-named monitors with relative position labels#593
utahcon wants to merge 2 commits into
domferr:v18.0from
utahcon:feat/monitor-position-names

Conversation

@utahcon

@utahcon utahcon commented Jul 27, 2026

Copy link
Copy Markdown

Summary

Fixes #81.

When two or more monitors are the same model, the indicator menu shows identical names for all of them, so there is no way to tell which layout row belongs to which monitor. This PR appends a relative position label to the name of any monitor that shares its name with another one, e.g.:

  • DELL U2723QE (left) / DELL U2723QE (right)
  • LG HDR 4K (top) / LG HDR 4K (bottom)
  • ASUS PB278 (top left) / ASUS PB278 (top right) / ASUS PB278 (bottom)

Monitors with unique names are left untouched, so nothing changes for setups that aren't affected by the problem.

Why position labels instead of number suffixes

The discussion in #81 originally converged on appending the monitor's number (e.g. LG Electronics 34" 1, LG Electronics 34" 2). This PR instead implements the relative position labels later suggested by @rloutrel in that thread, for the reason @GuillaumeAmat reported: monitor numbers get reassigned interchangeably every time a monitor is (un)plugged, so a number suffix doesn't reliably tell the user which physical screen a row refers to, while "left"/"right" does. Numbers are still used as a tie-breaker when positions can't disambiguate (e.g. mirrored displays get middle 1 / middle 2).

How it works

  • New src/indicator/monitorNames.ts exposes disambiguateMonitorNames(), which groups monitors by name and computes a position label only for groups with duplicates.
  • Positions are derived by clustering monitor center points into columns and rows. The clustering tolerance is half of the smallest monitor dimension in the group (with a fallback when geometry is unavailable), so slightly misaligned monitors still land in the same row/column.
  • Labels are picked from the cluster ranks: left/middle/right horizontally and top/middle/bottom vertically, combined when the group spans both axes (e.g. top right).
  • If two monitors in a group would still get the same label (mirrored displays, or 4-in-a-row where two are middle), the labels are numbered (middle 1, middle 2) so every entry stays unambiguous.
  • Whole phrases are passed through _() rather than composing translated words, since word order differs between languages.
  • Both name sources go through the same disambiguation: the GNOME 49+ Meta.Monitor.get_display_name() path and the gjs subprocess fallback used on older shells.

Since MetaLogicalMonitor exposes no geometry properties to GJS (only get_monitors() and get_number()), the GNOME 49+ path now reads x/y/width/height from the shell's monitors matched by monitor index instead of the previous (logicalMonitor as any).x access, which silently yielded 0 for every monitor. Related: #142 describes row-to-monitor confusion of a similar nature, though on an older code path — this PR does not claim to fix it.

Test plan

  • npm run lint passes and npm run build succeeds
  • Also verified against the v18.0 branch: no conflicts, the two files touched here lint clean, and the build succeeds — happy to retarget there if you prefer
  • Tested locally on GNOME 50 (Fedora) with same-model monitors: each menu entry shows the monitor name with its position label appended
  • Test on GNOME shell <= 44 (subprocess fallback path — logic is shared, but I couldn't exercise it locally; happy to get help here per CONTRIBUTING.md)
  • Test vertical and 2x2 arrangements on real hardware

@utahcon
utahcon force-pushed the feat/monitor-position-names branch from 0ed4ae6 to 6758a6e Compare July 27, 2026 17:37
@utahcon
utahcon changed the base branch from main to v18.0 July 27, 2026 17:37
utahcon added 2 commits July 27, 2026 11:42
When two or more monitors share the exact same display name, the
indicator menu now appends their relative position to the name, e.g.
"DELL U2720Q (left)" / "DELL U2720Q (right)", "(top)" / "(bottom)"
for stacked monitors, and combined labels like "(top left)" for grids.
Mirrored monitors (no distinct position) fall back to numbering, and
any colliding labels are numbered so names are always unique.

Positions are computed from monitor center points on both the
GNOME 49+ Meta.Monitor path (now enriched with width/height from the
shell's monitors) and the Gdk subprocess fallback. Position phrases
are translated as whole strings so word order can differ per language.
MetaLogicalMonitor exposes no properties to GJS (only get_monitors()
and get_number()), so reading logicalMonitor.x/y always yielded
undefined and every monitor fell back to (0, 0). Same-named monitors
then computed identical center points and were numbered (1)/(2)
instead of getting directional labels like (left)/(right).

Take x and y from the shell's monitor matched by index, alongside the
width and height already sourced there.
@utahcon
utahcon force-pushed the feat/monitor-position-names branch from 6758a6e to 5eab6b4 Compare July 27, 2026 17:43
@utahcon
utahcon changed the base branch from v18.0 to main July 27, 2026 17:43
@domferr
domferr changed the base branch from main to v18.0 August 9, 2026 10:50
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.

[Feature Request] Distinguish between monitors of the same model

1 participant