From 1ea364c83051e9453c6f0eca47f6f1e3b1a38933 Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Fri, 30 May 2025 20:15:52 -0300 Subject: [PATCH 1/9] Add gschema --- data/display.gschema.xml | 15 +++++++++++++++ data/meson.build | 6 ++++++ meson.build | 2 ++ 3 files changed, 23 insertions(+) create mode 100644 data/display.gschema.xml diff --git a/data/display.gschema.xml b/data/display.gschema.xml new file mode 100644 index 00000000..405b702b --- /dev/null +++ b/data/display.gschema.xml @@ -0,0 +1,15 @@ + + + + + {} + Preferred display layouts + + Stores user-defined display layout profiles. + Each profile contains a unique identifier and a list of monitors, with their respective position (x, y) and other properties such as transformation (e.g., rotation). + This allows the system to restore or suggest preferred monitor arrangements and settings when displays are connected or configurations change. + + + + + \ No newline at end of file diff --git a/data/meson.build b/data/meson.build index bb32ce31..592d77a7 100644 --- a/data/meson.build +++ b/data/meson.build @@ -11,3 +11,9 @@ gresource = gnome.compile_resources( 'gresource', 'display.gresource.xml' ) + +install_data( + 'display.gschema.xml', + install_dir: datadir / 'glib-2.0' / 'schemas', + rename: 'io.elementary.settings.display.gschema.xml' +) \ No newline at end of file diff --git a/meson.build b/meson.build index cd420ed8..352622fe 100644 --- a/meson.build +++ b/meson.build @@ -30,3 +30,5 @@ config_file = configure_file( subdir('data') subdir('src') subdir('po') + +gnome.post_install(glib_compile_schemas: true) \ No newline at end of file From 762da1f86f7f5d8c53cf6a141dddcda2688578f0 Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Fri, 30 May 2025 20:16:32 -0300 Subject: [PATCH 2/9] Implement MonitorLayoutManager --- src/Objects/MonitorLayoutManager.vala | 172 ++++++++++++++++++++++++++ src/Objects/MonitorLayoutProfile.vala | 48 +++++++ src/meson.build | 2 + 3 files changed, 222 insertions(+) create mode 100644 src/Objects/MonitorLayoutManager.vala create mode 100644 src/Objects/MonitorLayoutProfile.vala diff --git a/src/Objects/MonitorLayoutManager.vala b/src/Objects/MonitorLayoutManager.vala new file mode 100644 index 00000000..a701a7f7 --- /dev/null +++ b/src/Objects/MonitorLayoutManager.vala @@ -0,0 +1,172 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * SPDX-FileCopyrightText: 2025 elementary, Inc. + * + * Authored by: Leonardo Lemos + */ + +public class Display.MonitorLayoutManager : GLib.Object { + private Settings settings; + + private const string PREFERRED_MONITOR_LAYOUTS_KEY = "preferred-display-layouts"; + + public MonitorLayoutManager () { + Object (); + } + + construct { + settings = new Settings ("io.elementary.settings.display"); + } + + public void arrange_monitors (Gee.LinkedList virtual_monitors) { + if (virtual_monitors.size == 1) { + // If there's only one monitor, no need to arrange + return; + } + + var layout_key = get_layout_key (virtual_monitors); + var layout = find_match_layout (layout_key); + var is_cloned = is_virtual_monitors_cloned (virtual_monitors); + var has_update = false; + + + if (layout != null) { + foreach (var virtual_monitor in virtual_monitors) { + var monitor_layout = layout.find_position_by_id (virtual_monitor.monitors[0].hash.to_string ()); + + if (monitor_layout != null) { + if ((virtual_monitor.x != monitor_layout.x || virtual_monitor.y != monitor_layout.y) && !is_cloned) { + has_update = true; + break; + } + + virtual_monitor.x = monitor_layout.x; + virtual_monitor.y = monitor_layout.y; + } + } + } else { + // If no layout found, we save the current layout to use later + save_layout (virtual_monitors); + } + + if (has_update) { + save_layout (virtual_monitors); + } + } + + public void save_layout (Gee.LinkedList virtual_monitors) { + var key = get_layout_key (virtual_monitors); + var layout_variant = build_layout_variant (virtual_monitors); + + var layouts = settings.get_value (PREFERRED_MONITOR_LAYOUTS_KEY); + + add_or_update_layout (layouts, key, layout_variant); + + } + + public MonitorLayoutProfile? find_match_layout (string key) { + // Layouts format is 'a{sa{sv}}' + var layouts = settings.get_value (PREFERRED_MONITOR_LAYOUTS_KEY); + + if (layouts == null || layouts.n_children () == 0) { + return null; // No layouts saved + } + + for (var i = 0; i < layouts.n_children (); i++) { + var layout = layouts.get_child_value (i); + var layout_key = layout.get_child_value (0).get_string (); + var monitors = layout.get_child_value (1); + + if (layout_key != key) { + continue; + } + + var virtual_monitor_layout = new MonitorLayoutProfile (layout_key); + + // Process the monitors in the layout + for (var j = 0; j < monitors.n_children (); j++) { + var monitor = monitors.get_child_value (j); + var monitor_props = monitor.get_child_value (1); + + warning (monitor_props.get_child_value (0).get_type ().dup_string ()); + warning (monitor_props.get_child_value (0).get_child_value (1).get_child_value (0).get_type ().dup_string ()); + + + virtual_monitor_layout.add_position ( + monitor.get_child_value (0).get_string (), // id + monitor_props.get_child_value (0).get_child_value (1).get_child_value (0).get_int32 (), // x position + monitor_props.get_child_value (1).get_child_value (1).get_child_value (0).get_int32 () // y position + ); + } + + return virtual_monitor_layout; + } + + return null; + } + + private string get_layout_key (Gee.LinkedList virtual_monitors) { + // Generate a unique key based on the virtual monitors' monitors hashes + var key = new StringBuilder (); + + foreach (var virtual_monitor in virtual_monitors) { + foreach (var monitor in virtual_monitor.monitors) { + key.append (monitor.hash.to_string ()); + } + } + + return key.str.hash ().to_string (); + } + + private GLib.Variant build_layout_variant (Gee.LinkedList virtual_monitors) { + var dict_builder = new VariantBuilder(VariantType.DICTIONARY); + + foreach (var monitor in virtual_monitors) { + var props_builder = new VariantBuilder(VariantType.DICTIONARY); + var key = monitor.monitors.get(0).hash.to_string(); + + props_builder.add_value (new Variant.dict_entry ("x", new Variant.variant(new Variant.int32 (monitor.x)))); + props_builder.add_value (new Variant.dict_entry ("y", new Variant.variant(new Variant.int32 (monitor.y)))); + + dict_builder.add_value (new Variant.dict_entry (key, props_builder)); + } + + return dict_builder.end (); + } + + private void add_or_update_layout (GLib.Variant layouts, string key, GLib.Variant layout_variant) { + var layout_builder = new VariantBuilder(VariantType.DICTIONARY); + bool found = false; + + for (var i = 0; i < layouts.n_children (); i++) { + var layout = layouts.get_child_value (i); + var layout_key = layout.get_child_value (0).get_string (); + + if (layout_key == key) { + // Update existing layout + layout_builder.add_value (new Variant.dict_entry (key, layout_variant)); + found = true; + } else { + // Keep existing layout + layout_builder.add_value (new Variant.dict_entry (layout_key, layout)); + } + } + + if (!found) { + // Add new layout + layout_builder.add_value (new Variant.dict_entry (key, layout_variant)); + } + + settings.set_value(PREFERRED_MONITOR_LAYOUTS_KEY, layout_builder.end ()); + } + + private bool is_virtual_monitors_cloned (Gee.LinkedList virtual_monitors) { + foreach (var monitor in virtual_monitors) { + if (monitor.x != 0 || monitor.y != 0) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/Objects/MonitorLayoutProfile.vala b/src/Objects/MonitorLayoutProfile.vala new file mode 100644 index 00000000..543f0f8b --- /dev/null +++ b/src/Objects/MonitorLayoutProfile.vala @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * SPDX-FileCopyrightText: 2025 elementary, Inc. + * + * Authored by: Leonardo Lemos + */ + +public class Display.MonitorLayoutProfile : GLib.Object { + public class MonitorPosition : GLib.Object { + public string id { get; set; } + public int x { get; set; } + public int y { get; set; } + + public MonitorPosition (string id, int x, int y) { + Object (id: id, x: x, y: y); + } + } + + public string id { get; set; } + private List _positions; + + public unowned List positions { + get { + return _positions; + } + } + + public MonitorLayoutProfile (string id) { + Object (id: id); + } + + construct { + _positions = new List (); + } + + public void add_position (string id, int x, int y) { + _positions.append (new MonitorPosition (id, x, y)); + } + + public MonitorPosition? find_position_by_id (string id) { + foreach (var position in _positions) { + if (position.id == id) { + return position; + } + } + return null; + } +} \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 94aa9310..6de3dd7f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,6 +10,8 @@ plug_files = files( 'Objects/MonitorMode.vala', 'Objects/MonitorManager.vala', 'Objects/Monitor.vala', + 'Objects/MonitorLayoutManager.vala', + 'Objects/MonitorLayoutProfile.vala', 'Views/NightLightView.vala', 'Views/DisplaysView.vala', 'Views' / 'FiltersView.vala', From dd6c098b31b28c48c47e0d67779a0ad238405d05 Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Fri, 30 May 2025 20:16:52 -0300 Subject: [PATCH 3/9] Use MonitorLayoutManager --- src/Objects/MonitorManager.vala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Objects/MonitorManager.vala b/src/Objects/MonitorManager.vala index 7e04b0e4..98f9e21d 100644 --- a/src/Objects/MonitorManager.vala +++ b/src/Objects/MonitorManager.vala @@ -48,6 +48,7 @@ public class Display.MonitorManager : GLib.Object { private MutterDisplayConfigInterface iface; private uint current_serial; + private MonitorLayoutManager layout_manager; private static MonitorManager monitor_manager; public static unowned MonitorManager get_default () { @@ -65,6 +66,7 @@ public class Display.MonitorManager : GLib.Object { construct { monitors = new Gee.LinkedList (); virtual_monitors = new Gee.LinkedList (); + layout_manager = new MonitorLayoutManager (); try { iface = Bus.get_proxy_sync (BusType.SESSION, "org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig"); iface.monitors_changed.connect (get_monitor_config); @@ -83,6 +85,8 @@ public class Display.MonitorManager : GLib.Object { critical (e.message); } + var monitor_number = virtual_monitors.size; + // Clear all monitors and virtual monitors before re-adding them if needed monitors.clear (); virtual_monitors.clear (); @@ -239,6 +243,16 @@ public class Display.MonitorManager : GLib.Object { virtual_monitor.scale = virtual_monitors[0].scale; add_virtual_monitor (virtual_monitor); } + + + } + + if (monitor_number != virtual_monitors.size) { + notify_property ("virtual-monitor-number"); + } + + if (virtual_monitors.size >= 2) { + layout_manager.arrange_monitors (virtual_monitors); } } @@ -402,6 +416,8 @@ public class Display.MonitorManager : GLib.Object { virtual_monitors.clear (); virtual_monitors.add_all (new_virtual_monitors); + layout_manager.arrange_monitors (virtual_monitors); + notify_property ("virtual-monitor-number"); notify_property ("is-mirrored"); } From b2c0ff18210ff07e041cc844d6ae9812a990d92f Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Fri, 30 May 2025 20:27:00 -0300 Subject: [PATCH 4/9] Fix build --- src/Objects/MonitorLayoutManager.vala | 4 ++-- src/Objects/MonitorLayoutProfile.vala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Objects/MonitorLayoutManager.vala b/src/Objects/MonitorLayoutManager.vala index a701a7f7..93834265 100644 --- a/src/Objects/MonitorLayoutManager.vala +++ b/src/Objects/MonitorLayoutManager.vala @@ -2,7 +2,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later * SPDX-FileCopyrightText: 2025 elementary, Inc. * - * Authored by: Leonardo Lemos + * Authored by: Leonardo Lemos */ public class Display.MonitorLayoutManager : GLib.Object { @@ -128,7 +128,7 @@ public class Display.MonitorLayoutManager : GLib.Object { props_builder.add_value (new Variant.dict_entry ("x", new Variant.variant(new Variant.int32 (monitor.x)))); props_builder.add_value (new Variant.dict_entry ("y", new Variant.variant(new Variant.int32 (monitor.y)))); - dict_builder.add_value (new Variant.dict_entry (key, props_builder)); + dict_builder.add_value (new Variant.dict_entry (key, props_builder.end ())); } return dict_builder.end (); diff --git a/src/Objects/MonitorLayoutProfile.vala b/src/Objects/MonitorLayoutProfile.vala index 543f0f8b..7791ac22 100644 --- a/src/Objects/MonitorLayoutProfile.vala +++ b/src/Objects/MonitorLayoutProfile.vala @@ -2,7 +2,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later * SPDX-FileCopyrightText: 2025 elementary, Inc. * - * Authored by: Leonardo Lemos + * Authored by: Leonardo Lemos */ public class Display.MonitorLayoutProfile : GLib.Object { From 441b2800fcb9bad09eeba90c8f9d02161c6d217e Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Sat, 31 May 2025 18:28:45 -0300 Subject: [PATCH 5/9] Notify monitor number change only once --- src/Objects/MonitorManager.vala | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Objects/MonitorManager.vala b/src/Objects/MonitorManager.vala index 98f9e21d..1708e980 100644 --- a/src/Objects/MonitorManager.vala +++ b/src/Objects/MonitorManager.vala @@ -221,7 +221,7 @@ public class Display.MonitorManager : GLib.Object { virtual_monitor.scale = mutter_logical_monitor.scale; virtual_monitor.transform = mutter_logical_monitor.transform; virtual_monitor.primary = mutter_logical_monitor.primary; - add_virtual_monitor (virtual_monitor); + virtual_monitors.add (virtual_monitor); } // Look for any monitors that aren't part of a virtual monitor (hence disabled) @@ -241,19 +241,15 @@ public class Display.MonitorManager : GLib.Object { virtual_monitor.primary = false; virtual_monitor.monitors.add (monitor); virtual_monitor.scale = virtual_monitors[0].scale; - add_virtual_monitor (virtual_monitor); + virtual_monitors.add (virtual_monitor); } - - } if (monitor_number != virtual_monitors.size) { notify_property ("virtual-monitor-number"); } - if (virtual_monitors.size >= 2) { - layout_manager.arrange_monitors (virtual_monitors); - } + layout_manager.arrange_monitors (virtual_monitors); } public void set_monitor_config () throws Error { @@ -422,11 +418,6 @@ public class Display.MonitorManager : GLib.Object { notify_property ("is-mirrored"); } - private void add_virtual_monitor (Display.VirtualMonitor virtual_monitor) { - virtual_monitors.add (virtual_monitor); - notify_property ("virtual-monitor-number"); - } - private VirtualMonitor? get_virtual_monitor_by_id (string id) { foreach (var vm in virtual_monitors) { if (vm.id == id) { From 12a1a02dba3365eb968f19a42d99190f6408cf85 Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Sat, 31 May 2025 18:29:04 -0300 Subject: [PATCH 6/9] Show display label only once --- src/Widgets/DisplaysOverlay.vala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Widgets/DisplaysOverlay.vala b/src/Widgets/DisplaysOverlay.vala index d76bb41c..b429c468 100644 --- a/src/Widgets/DisplaysOverlay.vala +++ b/src/Widgets/DisplaysOverlay.vala @@ -199,6 +199,7 @@ public class Display.DisplaysOverlay : Gtk.Box { add_output (virtual_monitor); } + show_windows (); change_active_displays_sensitivity (); calculate_ratio (); scanning = false; @@ -351,10 +352,6 @@ public class Display.DisplaysOverlay : Gtk.Box { check_configuration_change (); calculate_ratio (); }); - - if (!monitor_manager.is_mirrored && virtual_monitor.is_active) { - show_windows (); - } } private void set_as_primary (Display.VirtualMonitor new_primary) { From f8605150ac38418143789b08041eb3708094fe34 Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Sat, 31 May 2025 19:18:13 -0300 Subject: [PATCH 7/9] Rescan Displays only if monitors changed --- src/Objects/MonitorManager.vala | 21 ++++++++++++++------- src/Widgets/DisplaysOverlay.vala | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Objects/MonitorManager.vala b/src/Objects/MonitorManager.vala index 1708e980..7947f1bd 100644 --- a/src/Objects/MonitorManager.vala +++ b/src/Objects/MonitorManager.vala @@ -46,6 +46,8 @@ public class Display.MonitorManager : GLib.Object { } } + public signal void monitors_changed (); + private MutterDisplayConfigInterface iface; private uint current_serial; private MonitorLayoutManager layout_manager; @@ -68,8 +70,14 @@ public class Display.MonitorManager : GLib.Object { virtual_monitors = new Gee.LinkedList (); layout_manager = new MonitorLayoutManager (); try { - iface = Bus.get_proxy_sync (BusType.SESSION, "org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig"); - iface.monitors_changed.connect (get_monitor_config); + iface = Bus.get_proxy_sync ( + BusType.SESSION, + "org.gnome.Mutter.DisplayConfig", + "/org/gnome/Mutter/DisplayConfig"); + iface.monitors_changed.connect (() => { + get_monitor_config (); + monitors_changed (); + }); } catch (Error e) { critical (e.message); } @@ -80,7 +88,10 @@ public class Display.MonitorManager : GLib.Object { MutterReadLogicalMonitor[] mutter_logical_monitors; GLib.HashTable properties; try { - iface.get_current_state (out current_serial, out mutter_monitors, out mutter_logical_monitors, out properties); + iface.get_current_state (out current_serial, + out mutter_monitors, + out mutter_logical_monitors, + out properties); } catch (Error e) { critical (e.message); } @@ -245,10 +256,6 @@ public class Display.MonitorManager : GLib.Object { } } - if (monitor_number != virtual_monitors.size) { - notify_property ("virtual-monitor-number"); - } - layout_manager.arrange_monitors (virtual_monitors); } diff --git a/src/Widgets/DisplaysOverlay.vala b/src/Widgets/DisplaysOverlay.vala index b429c468..f1657964 100644 --- a/src/Widgets/DisplaysOverlay.vala +++ b/src/Widgets/DisplaysOverlay.vala @@ -87,7 +87,7 @@ public class Display.DisplaysOverlay : Gtk.Box { add_controller (drag_gesture); monitor_manager = Display.MonitorManager.get_default (); - monitor_manager.notify["virtual-monitor-number"].connect (() => rescan_displays ()); + monitor_manager.monitors_changed.connect (() => rescan_displays ()); rescan_displays (); overlay.get_child_position.connect (get_child_position); From 671246144b7be3c346f41ad98e7d55e80d95b15c Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Sat, 31 May 2025 19:18:40 -0300 Subject: [PATCH 8/9] Add display transformation saving --- src/Objects/MonitorLayoutManager.vala | 86 +++++++++++++++++---------- src/Objects/MonitorLayoutProfile.vala | 11 ++-- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/Objects/MonitorLayoutManager.vala b/src/Objects/MonitorLayoutManager.vala index 93834265..547c986b 100644 --- a/src/Objects/MonitorLayoutManager.vala +++ b/src/Objects/MonitorLayoutManager.vala @@ -9,7 +9,7 @@ public class Display.MonitorLayoutManager : GLib.Object { private Settings settings; private const string PREFERRED_MONITOR_LAYOUTS_KEY = "preferred-display-layouts"; - + public MonitorLayoutManager () { Object (); } @@ -23,25 +23,29 @@ public class Display.MonitorLayoutManager : GLib.Object { // If there's only one monitor, no need to arrange return; } - + var layout_key = get_layout_key (virtual_monitors); var layout = find_match_layout (layout_key); var is_cloned = is_virtual_monitors_cloned (virtual_monitors); var has_update = false; - if (layout != null) { foreach (var virtual_monitor in virtual_monitors) { - var monitor_layout = layout.find_position_by_id (virtual_monitor.monitors[0].hash.to_string ()); - - if (monitor_layout != null) { - if ((virtual_monitor.x != monitor_layout.x || virtual_monitor.y != monitor_layout.y) && !is_cloned) { + var monitor_position = layout + .find_position_by_id (virtual_monitor.monitors[0].hash.to_string ()); + + if (monitor_position != null) { + if ((virtual_monitor.x != monitor_position.x + || virtual_monitor.y != monitor_position.y + || virtual_monitor.transform != monitor_position.transform) + && !is_cloned) { has_update = true; break; } - virtual_monitor.x = monitor_layout.x; - virtual_monitor.y = monitor_layout.y; + virtual_monitor.x = monitor_position.x; + virtual_monitor.y = monitor_position.y; + virtual_monitor.transform = monitor_position.transform; } } } else { @@ -50,6 +54,7 @@ public class Display.MonitorLayoutManager : GLib.Object { } if (has_update) { + // If the layout has been updated, save the new layout save_layout (virtual_monitors); } } @@ -61,11 +66,10 @@ public class Display.MonitorLayoutManager : GLib.Object { var layouts = settings.get_value (PREFERRED_MONITOR_LAYOUTS_KEY); add_or_update_layout (layouts, key, layout_variant); - } public MonitorLayoutProfile? find_match_layout (string key) { - // Layouts format is 'a{sa{sv}}' + // Layouts format are 'a{sa{sa{sv}}}' var layouts = settings.get_value (PREFERRED_MONITOR_LAYOUTS_KEY); if (layouts == null || layouts.n_children () == 0) { @@ -81,25 +85,32 @@ public class Display.MonitorLayoutManager : GLib.Object { continue; } - var virtual_monitor_layout = new MonitorLayoutProfile (layout_key); + var virtual_monitor_position = new MonitorLayoutProfile (layout_key); // Process the monitors in the layout for (var j = 0; j < monitors.n_children (); j++) { var monitor = monitors.get_child_value (j); var monitor_props = monitor.get_child_value (1); - warning (monitor_props.get_child_value (0).get_type ().dup_string ()); - warning (monitor_props.get_child_value (0).get_child_value (1).get_child_value (0).get_type ().dup_string ()); - - - virtual_monitor_layout.add_position ( - monitor.get_child_value (0).get_string (), // id - monitor_props.get_child_value (0).get_child_value (1).get_child_value (0).get_int32 (), // x position - monitor_props.get_child_value (1).get_child_value (1).get_child_value (0).get_int32 () // y position - ); + virtual_monitor_position.add_position ( + monitor.get_child_value (0) + .get_string (), // id + monitor_props.get_child_value (0) + .get_child_value (1) + .get_child_value (0) + .get_int32 (), // x position + monitor_props.get_child_value (1) + .get_child_value (1) + .get_child_value (0) + .get_int32 (), // y position + monitor_props.get_child_value (2) + .get_child_value (1) + .get_child_value (0) + .get_int32 () // transform + ); } - return virtual_monitor_layout; + return virtual_monitor_position; } return null; @@ -119,23 +130,32 @@ public class Display.MonitorLayoutManager : GLib.Object { } private GLib.Variant build_layout_variant (Gee.LinkedList virtual_monitors) { - var dict_builder = new VariantBuilder(VariantType.DICTIONARY); + var dict_builder = new VariantBuilder (VariantType.DICTIONARY); foreach (var monitor in virtual_monitors) { - var props_builder = new VariantBuilder(VariantType.DICTIONARY); - var key = monitor.monitors.get(0).hash.to_string(); - - props_builder.add_value (new Variant.dict_entry ("x", new Variant.variant(new Variant.int32 (monitor.x)))); - props_builder.add_value (new Variant.dict_entry ("y", new Variant.variant(new Variant.int32 (monitor.y)))); - - dict_builder.add_value (new Variant.dict_entry (key, props_builder.end ())); + var props_builder = new VariantBuilder (VariantType.DICTIONARY); + var key = monitor.monitors.get (0).hash.to_string (); + + var coordinate_x_variant = new Variant.variant (new Variant.int32 (monitor.x)); + var coordinate_y_variant = new Variant.variant (new Variant.int32 (monitor.y)); + var transform_variant = new Variant.variant (new Variant.int32 (monitor.transform)); + + props_builder.add_value (new Variant.dict_entry ("x", coordinate_x_variant)); + props_builder.add_value (new Variant.dict_entry ("y", coordinate_y_variant)); + props_builder.add_value (new Variant.dict_entry ("transform", transform_variant)); + + var props_variant = props_builder.end (); + + warning (props_variant.print (true)); + + dict_builder.add_value (new Variant.dict_entry (key, props_variant)); } return dict_builder.end (); } private void add_or_update_layout (GLib.Variant layouts, string key, GLib.Variant layout_variant) { - var layout_builder = new VariantBuilder(VariantType.DICTIONARY); + var layout_builder = new VariantBuilder (VariantType.DICTIONARY); bool found = false; for (var i = 0; i < layouts.n_children (); i++) { @@ -157,7 +177,7 @@ public class Display.MonitorLayoutManager : GLib.Object { layout_builder.add_value (new Variant.dict_entry (key, layout_variant)); } - settings.set_value(PREFERRED_MONITOR_LAYOUTS_KEY, layout_builder.end ()); + settings.set_value (PREFERRED_MONITOR_LAYOUTS_KEY, layout_builder.end ()); } private bool is_virtual_monitors_cloned (Gee.LinkedList virtual_monitors) { @@ -169,4 +189,4 @@ public class Display.MonitorLayoutManager : GLib.Object { return true; } -} \ No newline at end of file +} diff --git a/src/Objects/MonitorLayoutProfile.vala b/src/Objects/MonitorLayoutProfile.vala index 7791ac22..1c8822c4 100644 --- a/src/Objects/MonitorLayoutProfile.vala +++ b/src/Objects/MonitorLayoutProfile.vala @@ -10,9 +10,10 @@ public class Display.MonitorLayoutProfile : GLib.Object { public string id { get; set; } public int x { get; set; } public int y { get; set; } + public DisplayTransform transform { get; set; } - public MonitorPosition (string id, int x, int y) { - Object (id: id, x: x, y: y); + public MonitorPosition (string id, int x, int y, DisplayTransform transform) { + Object (id: id, x: x, y: y, transform: transform); } } @@ -33,8 +34,8 @@ public class Display.MonitorLayoutProfile : GLib.Object { _positions = new List (); } - public void add_position (string id, int x, int y) { - _positions.append (new MonitorPosition (id, x, y)); + public void add_position (string id, int x, int y, DisplayTransform transform) { + _positions.append (new MonitorPosition (id, x, y, transform)); } public MonitorPosition? find_position_by_id (string id) { @@ -45,4 +46,4 @@ public class Display.MonitorLayoutProfile : GLib.Object { } return null; } -} \ No newline at end of file +} From 756c165047d587d79e1a05f12f9642dc86872820 Mon Sep 17 00:00:00 2001 From: Leonardo Lemos Date: Sun, 1 Jun 2025 19:11:36 -0300 Subject: [PATCH 9/9] Removed unused variable --- src/Objects/MonitorManager.vala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Objects/MonitorManager.vala b/src/Objects/MonitorManager.vala index 7947f1bd..de91eac5 100644 --- a/src/Objects/MonitorManager.vala +++ b/src/Objects/MonitorManager.vala @@ -96,8 +96,6 @@ public class Display.MonitorManager : GLib.Object { critical (e.message); } - var monitor_number = virtual_monitors.size; - // Clear all monitors and virtual monitors before re-adding them if needed monitors.clear (); virtual_monitors.clear ();