Skip to content

Introduce Monitor Layout Manager#423

Open
leonardo-lemos wants to merge 34 commits into
mainfrom
introduce-layout-manager
Open

Introduce Monitor Layout Manager#423
leonardo-lemos wants to merge 34 commits into
mainfrom
introduce-layout-manager

Conversation

@leonardo-lemos
Copy link
Copy Markdown
Collaborator

@leonardo-lemos leonardo-lemos commented May 30, 2025

Fixes #418
Closes #412
Resolves #424

This PR introduces the MonitorLayoutManager class to persist and restore monitor arrangements when changes occur.

We rely on Mutter's DisplayConfig D-Bus interface to detect monitor changes and retrieve the current monitor layout configuration (i.e., virtual monitors or CRTCs). However, there are some edge cases that cause layout issues:

  • Clone Mode (Mirror Mode): When clone mode is enabled, Settings creates a single virtual monitor encompassing all physical monitors with identical coordinates (x=0, y=0). When clone mode is disabled, Settings has no memory of the previous layout and falls back to overlapping display widgets, since all monitors share the same coordinates.

  • Disabling Monitors: When a monitor is disabled, Mutter still reports its existence but omits its coordinates, as it’s no longer part of the active layout. This results in the disabled monitor’s widget overlapping another widget in the UI.

To address these issues, this PR introduces a GSetting to persist monitor layout data, including each monitor's position and transformation. This allows us to restore previous layouts accurately, even after mode toggles or monitor disable events.

Additionally, this PR modifies when the display overlay updates its widgets — now triggered only when monitor changes are detected, ensuring a more stable and consistent display configuration.

@leonardo-lemos leonardo-lemos marked this pull request as ready for review May 31, 2025 23:12
@danirabbit
Copy link
Copy Markdown
Member

I think @jeremypw has some experience in this codebase?

@jeremypw
Copy link
Copy Markdown
Collaborator

jeremypw commented Jun 6, 2025

Its been quite a while since I looked at this plug but I'll try to test this out this weekend.

Copy link
Copy Markdown

@Marukesu Marukesu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some simplifications suggestions.

Comment thread meson.build
Comment thread src/Objects/MonitorLayoutManager.vala
}

public MonitorLayoutProfile? find_match_layout (string key) {
// Layouts format are 'a{sa{sa{sv}}}'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"a{sa{s(iiu)}}" should be simpler, we don't need the monitor properties be extensible, nor the extra boxing of using variant values.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we want to persist addition properties in future?

Comment thread src/Objects/MonitorLayoutManager.vala Outdated
Comment thread src/Objects/MonitorLayoutManager.vala Outdated
Comment thread src/Objects/MonitorLayoutManager.vala
Comment thread src/Objects/MonitorLayoutManager.vala Outdated
Comment thread src/Objects/MonitorLayoutManager.vala Outdated
Comment thread src/Objects/MonitorLayoutManager.vala
Comment thread src/Objects/MonitorManager.vala
@flodavid
Copy link
Copy Markdown
Contributor

I have the following error:

(io.elementary.settings:37137): GLib-GIO-CRITICAL **: 03:12:23.570: g_settings_set_value: key 'preferred-display-layouts' in 'io.elementary.settings.display' expects type 'a{sa{sa{sv}}}', but a GVariant of type 'a{s{sa{sa{sv}}}}' was given

It is because you are trying to handle multiple layouts, each with its own hash. Hence {s is missing from the gschema type.

I also have the following error:

(io.elementary.settings:37137): GLib-CRITICAL **: 03:12:23.570: g_variant_builder_add_value: assertion '!GVSB(builder)->prev_item_type || g_variant_is_of_type (value, GVSB(builder)->prev_item_type)' failed

Disabled monitor still overlap active ones. And once the mirror mode was activated, I could no longer deactivate it, as an error window alerting of bad configuration appeared and prevented validating.

@jeremypw
Copy link
Copy Markdown
Collaborator

@leonardo-lemos Hi, if you're still interested in pursuing this, I suggest you break out the code cleanups in order to reduce the diff. I think you are going in the right direction - personally I do not have a problem with a separate class to encompass the layout/settings management - the existing manager is complicated enough as it is. If you prefer, I am willing to work on this as this plug needs some attention.

@leonardo-lemos
Copy link
Copy Markdown
Collaborator Author

@leonardo-lemos Hi, if you're still interested in pursuing this, I suggest you break out the code cleanups in order to reduce the diff. I think you are going in the right direction - personally I do not have a problem with a separate class to encompass the layout/settings management - the existing manager is complicated enough as it is. If you prefer, I am willing to work on this as this plug needs some attention.

@jeremypw Would you mind working on this? I have a newborn right now and don't have much time to dedicate to it.

@jeremypw
Copy link
Copy Markdown
Collaborator

@leonardo-lemos Very understandable! I'll see what I can do to progress this.

@jeremypw jeremypw self-assigned this May 27, 2026
@jeremypw jeremypw marked this pull request as draft May 27, 2026 20:14
@jeremypw jeremypw marked this pull request as ready for review May 31, 2026 16:01
@jeremypw
Copy link
Copy Markdown
Collaborator

This basically works although there are some corner cases that need addressing. However, to keep things simple I am proposing for review now with the intention of iterating.

@jeremypw
Copy link
Copy Markdown
Collaborator

A current limitation is that only one layout per monitor set is remembered. It should not be too hard to remember the previous layout too. In future a layout management dialog could allow more layouts to be remembered (and forgotten).

@jeremypw jeremypw marked this pull request as draft May 31, 2026 17:19
@jeremypw
Copy link
Copy Markdown
Collaborator

Convert to draft to fix some issues noticed.

@jeremypw
Copy link
Copy Markdown
Collaborator

jeremypw commented Jun 1, 2026

Some tweaking to the variant dictionary handling was required to get saving and restoring layouts working properly.

@jeremypw
Copy link
Copy Markdown
Collaborator

jeremypw commented Jun 1, 2026

Enabling and disabling the mirror mode now seems to work partially - the layout from settings is restored. A shortcoming is that the primary monitor is not restored (as it is not stored in the setting at present).

@jeremypw
Copy link
Copy Markdown
Collaborator

jeremypw commented Jun 2, 2026

The "primary" and "is-active" properties are now also saved and restored which seems to fix the remaining linked issues. Probably worth another review now.

@jeremypw jeremypw marked this pull request as ready for review June 2, 2026 09:00
@jeremypw jeremypw requested a review from Marukesu June 2, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants