diff --git a/src/Background/Background.vala b/src/Background/Background.vala
index aaf1084bc..08f45ad66 100644
--- a/src/Background/Background.vala
+++ b/src/Background/Background.vala
@@ -1,288 +1,275 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- public class Background : Object {
- private const double ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
- private const double ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
-
- public signal void changed ();
- public signal void loaded ();
-
- public Meta.Display display { get; construct; }
- public int monitor_index { get; construct; }
- public BackgroundSource background_source { get; construct; }
- public bool is_loaded { get; private set; default = false; }
- public GDesktop.BackgroundStyle style { get; construct; }
- public string? filename { get; construct; }
- public Meta.Background background { get; private set; }
-
- private Animation? animation = null;
- private Gee.HashMap file_watches;
- private Cancellable cancellable;
- private uint update_animation_timeout_id = 0;
-
- private Gnome.WallClock clock;
- private ulong clock_timezone_handler = 0;
-
- public Background (Meta.Display display, int monitor_index, string? filename,
- BackgroundSource background_source, GDesktop.BackgroundStyle style) {
- Object (display: display,
- monitor_index: monitor_index,
- background_source: background_source,
- style: style,
- filename: filename);
- }
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+public class Gala.Background : Object {
+ private const double ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
+ private const double ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
+
+ public signal void changed ();
+ public signal void loaded ();
+
+ public Meta.Display display { get; construct; }
+ public int monitor_index { get; construct; }
+ public BackgroundSource background_source { get; construct; }
+ public bool is_loaded { get; private set; default = false; }
+ public GDesktop.BackgroundStyle style { get; construct; }
+ public string? filename { get; construct; }
+ public Meta.Background background { get; private set; }
+
+ private Animation? animation = null;
+ private Gee.HashMap file_watches;
+ private Cancellable cancellable;
+ private uint update_animation_timeout_id = 0;
+
+ private Gnome.WallClock clock;
+ private ulong clock_timezone_handler = 0;
+
+ public Background (Meta.Display display, int monitor_index, string? filename,
+ BackgroundSource background_source, GDesktop.BackgroundStyle style) {
+ Object (display: display,
+ monitor_index: monitor_index,
+ background_source: background_source,
+ style: style,
+ filename: filename);
+ }
- construct {
- background = new Meta.Background (display);
- background.set_data ("delegate", this);
+ construct {
+ background = new Meta.Background (display);
+ background.set_data ("delegate", this);
- file_watches = new Gee.HashMap ();
- cancellable = new Cancellable ();
+ file_watches = new Gee.HashMap ();
+ cancellable = new Cancellable ();
- background_source.changed.connect (settings_changed);
+ background_source.changed.connect (settings_changed);
- clock = new Gnome.WallClock ();
- clock_timezone_handler = clock.notify["timezone"].connect (() => {
- if (animation != null) {
- load_animation.begin (animation.filename);
- }
- });
+ clock = new Gnome.WallClock ();
+ clock_timezone_handler = clock.notify["timezone"].connect (() => {
+ if (animation != null) {
+ load_animation.begin (animation.filename);
+ }
+ });
- load ();
- }
+ load ();
+ }
- public void destroy () {
- cancellable.cancel ();
- remove_animation_timeout ();
+ public void destroy () {
+ cancellable.cancel ();
+ remove_animation_timeout ();
- var cache = BackgroundCache.get_default ();
+ var cache = BackgroundCache.get_default ();
- foreach (var watch in file_watches.values) {
- cache.disconnect (watch);
- }
+ foreach (var watch in file_watches.values) {
+ cache.disconnect (watch);
+ }
- background_source.changed.disconnect (settings_changed);
+ background_source.changed.disconnect (settings_changed);
- if (clock_timezone_handler != 0) {
- clock.disconnect (clock_timezone_handler);
- }
+ if (clock_timezone_handler != 0) {
+ clock.disconnect (clock_timezone_handler);
}
+ }
- public void update_resolution () {
- if (animation != null) {
- remove_animation_timeout ();
- update_animation ();
- }
+ public void update_resolution () {
+ if (animation != null) {
+ remove_animation_timeout ();
+ update_animation ();
}
+ }
- private void set_loaded () {
- if (is_loaded)
- return;
+ private void set_loaded () {
+ if (is_loaded)
+ return;
- is_loaded = true;
+ is_loaded = true;
- Idle.add (() => {
- loaded ();
- return Source.REMOVE;
- });
- }
+ Idle.add (() => {
+ loaded ();
+ return Source.REMOVE;
+ });
+ }
- private void load_pattern () {
- string color_string;
- var settings = background_source.gnome_background_settings;
+ private void load_pattern () {
+ string color_string;
+ var settings = background_source.gnome_background_settings;
- color_string = settings.get_string ("primary-color");
+ color_string = settings.get_string ("primary-color");
#if HAS_MUTTER47
- var color = Cogl.Color.from_string (color_string);
+ var color = Cogl.Color.from_string (color_string);
#else
- var color = Clutter.Color.from_string (color_string);
+ var color = Clutter.Color.from_string (color_string);
#endif
- if (color == null) {
+ if (color == null) {
#if HAS_MUTTER47
- color = Cogl.Color.from_string ("black");
+ color = Cogl.Color.from_string ("black");
#else
- color = Clutter.Color.from_string ("black");
+ color = Clutter.Color.from_string ("black");
#endif
- }
+ }
- var shading_type = settings.get_enum ("color-shading-type");
+ var shading_type = settings.get_enum ("color-shading-type");
- if (shading_type == GDesktop.BackgroundShading.SOLID) {
- background.set_color (color);
- } else {
- color_string = settings.get_string ("secondary-color");
+ if (shading_type == GDesktop.BackgroundShading.SOLID) {
+ background.set_color (color);
+ } else {
+ color_string = settings.get_string ("secondary-color");
#if HAS_MUTTER47
- var second_color = Cogl.Color.from_string (color_string);
+ var second_color = Cogl.Color.from_string (color_string);
#else
- var second_color = Clutter.Color.from_string (color_string);
+ var second_color = Clutter.Color.from_string (color_string);
#endif
- if (second_color == null) {
+ if (second_color == null) {
#if HAS_MUTTER47
- second_color = Cogl.Color.from_string ("black");
+ second_color = Cogl.Color.from_string ("black");
#else
- second_color = Clutter.Color.from_string ("black");
+ second_color = Clutter.Color.from_string ("black");
#endif
- }
-
- background.set_gradient ((GDesktop.BackgroundShading) shading_type, color, second_color);
}
+
+ background.set_gradient ((GDesktop.BackgroundShading) shading_type, color, second_color);
}
+ }
- private void watch_file (string filename) {
- if (file_watches.has_key (filename))
- return;
+ private void watch_file (string filename) {
+ if (file_watches.has_key (filename))
+ return;
- var cache = BackgroundCache.get_default ();
+ var cache = BackgroundCache.get_default ();
- cache.monitor_file (filename);
+ cache.monitor_file (filename);
- file_watches[filename] = cache.file_changed.connect ((changed_file) => {
- if (changed_file == filename) {
- var image_cache = Meta.BackgroundImageCache.get_default ();
- image_cache.purge (File.new_for_path (changed_file));
- changed ();
- }
- });
- }
-
- private void remove_animation_timeout () {
- if (update_animation_timeout_id != 0) {
- Source.remove (update_animation_timeout_id);
- update_animation_timeout_id = 0;
+ file_watches[filename] = cache.file_changed.connect ((changed_file) => {
+ if (changed_file == filename) {
+ var image_cache = Meta.BackgroundImageCache.get_default ();
+ image_cache.purge (File.new_for_path (changed_file));
+ changed ();
}
+ });
+ }
+
+ private void remove_animation_timeout () {
+ if (update_animation_timeout_id != 0) {
+ Source.remove (update_animation_timeout_id);
+ update_animation_timeout_id = 0;
}
+ }
- private void finish_animation (string[] files) {
- set_loaded ();
+ private void finish_animation (string[] files) {
+ set_loaded ();
- if (files.length > 1)
- background.set_blend (File.new_for_path (files[0]), File.new_for_path (files[1]), animation.transition_progress, style);
- else if (files.length > 0)
- background.set_file (File.new_for_path (files[0]), style);
- else
- background.set_file (null, style);
+ if (files.length > 1)
+ background.set_blend (File.new_for_path (files[0]), File.new_for_path (files[1]), animation.transition_progress, style);
+ else if (files.length > 0)
+ background.set_file (File.new_for_path (files[0]), style);
+ else
+ background.set_file (null, style);
- queue_update_animation ();
- }
+ queue_update_animation ();
+ }
- private void update_animation () {
- update_animation_timeout_id = 0;
+ private void update_animation () {
+ update_animation_timeout_id = 0;
- animation.update (display.get_monitor_geometry (monitor_index));
- var files = animation.key_frame_files;
+ animation.update (display.get_monitor_geometry (monitor_index));
+ var files = animation.key_frame_files;
- var cache = Meta.BackgroundImageCache.get_default ();
- var num_pending_images = files.length;
- for (var i = 0; i < files.length; i++) {
- watch_file (files[i]);
+ var cache = Meta.BackgroundImageCache.get_default ();
+ var num_pending_images = files.length;
+ for (var i = 0; i < files.length; i++) {
+ watch_file (files[i]);
- var image = cache.load (File.new_for_path (files[i]));
+ var image = cache.load (File.new_for_path (files[i]));
- if (image.is_loaded ()) {
- num_pending_images--;
- if (num_pending_images == 0) {
+ if (image.is_loaded ()) {
+ num_pending_images--;
+ if (num_pending_images == 0) {
+ finish_animation (files);
+ }
+ } else {
+ ulong handler = 0;
+ handler = image.loaded.connect (() => {
+ image.disconnect (handler);
+ if (--num_pending_images == 0) {
finish_animation (files);
}
- } else {
- ulong handler = 0;
- handler = image.loaded.connect (() => {
- image.disconnect (handler);
- if (--num_pending_images == 0) {
- finish_animation (files);
- }
- });
- }
+ });
}
}
+ }
- private void queue_update_animation () {
- if (update_animation_timeout_id != 0)
- return;
-
- if (cancellable == null || cancellable.is_cancelled ())
- return;
+ private void queue_update_animation () {
+ if (update_animation_timeout_id != 0)
+ return;
- if (animation.transition_duration == 0)
- return;
+ if (cancellable == null || cancellable.is_cancelled ())
+ return;
- var n_steps = 255.0 / ANIMATION_OPACITY_STEP_INCREMENT;
- var time_per_step = (animation.transition_duration * 1000) / n_steps;
+ if (animation.transition_duration == 0)
+ return;
- var interval = (uint32) Math.fmax (ANIMATION_MIN_WAKEUP_INTERVAL * 1000, time_per_step);
+ var n_steps = 255.0 / ANIMATION_OPACITY_STEP_INCREMENT;
+ var time_per_step = (animation.transition_duration * 1000) / n_steps;
- if (interval > uint32.MAX)
- return;
+ var interval = (uint32) Math.fmax (ANIMATION_MIN_WAKEUP_INTERVAL * 1000, time_per_step);
- update_animation_timeout_id = Timeout.add (interval, () => {
- update_animation_timeout_id = 0;
- update_animation ();
- return Source.REMOVE;
- });
- }
+ if (interval > uint32.MAX)
+ return;
- private async void load_animation (string filename) {
- animation = yield BackgroundCache.get_default ().get_animation (filename);
+ update_animation_timeout_id = Timeout.add (interval, () => {
+ update_animation_timeout_id = 0;
+ update_animation ();
+ return Source.REMOVE;
+ });
+ }
- if (animation == null || cancellable.is_cancelled ()) {
- set_loaded ();
- return;
- }
+ private async void load_animation (string filename) {
+ animation = yield BackgroundCache.get_default ().get_animation (filename);
- update_animation ();
- watch_file (filename);
+ if (animation == null || cancellable.is_cancelled ()) {
+ set_loaded ();
+ return;
}
- private void load_image (string filename) {
- background.set_file (File.new_for_path (filename), style);
- watch_file (filename);
+ update_animation ();
+ watch_file (filename);
+ }
+
+ private void load_image (string filename) {
+ background.set_file (File.new_for_path (filename), style);
+ watch_file (filename);
- var cache = Meta.BackgroundImageCache.get_default ();
- var image = cache.load (File.new_for_path (filename));
- if (image.is_loaded ())
+ var cache = Meta.BackgroundImageCache.get_default ();
+ var image = cache.load (File.new_for_path (filename));
+ if (image.is_loaded ())
+ set_loaded ();
+ else {
+ ulong handler = 0;
+ handler = image.loaded.connect (() => {
set_loaded ();
- else {
- ulong handler = 0;
- handler = image.loaded.connect (() => {
- set_loaded ();
- image.disconnect (handler);
- });
- }
+ image.disconnect (handler);
+ });
}
+ }
- private void load_file (string filename) {
- if (filename.has_suffix (".xml"))
- load_animation.begin (filename);
- else
- load_image (filename);
- }
+ private void load_file (string filename) {
+ if (filename.has_suffix (".xml"))
+ load_animation.begin (filename);
+ else
+ load_image (filename);
+ }
- private void load () {
- load_pattern ();
+ private void load () {
+ load_pattern ();
- if (filename == null)
- set_loaded ();
- else
- load_file (filename);
- }
+ if (filename == null)
+ set_loaded ();
+ else
+ load_file (filename);
+ }
- private void settings_changed () {
- changed ();
- }
+ private void settings_changed () {
+ changed ();
}
}
diff --git a/src/Background/BackgroundCache.vala b/src/Background/BackgroundCache.vala
index 2de0969e3..02025dcb4 100644
--- a/src/Background/BackgroundCache.vala
+++ b/src/Background/BackgroundCache.vala
@@ -1,78 +1,53 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- public class BackgroundCache : Object {
- private static BackgroundCache? instance = null;
-
- public static unowned BackgroundCache get_default () {
- if (instance == null)
- instance = new BackgroundCache ();
-
- return instance;
- }
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
- public signal void file_changed (string filename);
+public class Gala.BackgroundCache : Object {
+ private static BackgroundCache? instance = null;
- private Gee.HashMap file_monitors;
- private BackgroundSource background_source;
+ public static unowned BackgroundCache get_default () {
+ if (instance == null)
+ instance = new BackgroundCache ();
- private Animation animation;
+ return instance;
+ }
- public BackgroundCache () {
- Object ();
- }
+ public signal void file_changed (string filename);
- construct {
- file_monitors = new Gee.HashMap ();
- }
+ private Gee.HashMap file_monitors;
+ private BackgroundSource background_source;
- public void monitor_file (string filename) {
- if (file_monitors.has_key (filename))
- return;
-
- var file = File.new_for_path (filename);
- try {
- var monitor = file.monitor (FileMonitorFlags.NONE, null);
- monitor.changed.connect (() => {
- file_changed (filename);
- });
-
- file_monitors[filename] = monitor;
- } catch (Error e) {
- warning ("Failed to monitor %s: %s", filename, e.message);
- }
- }
+ private Animation animation;
- public async Animation get_animation (string filename) {
- if (animation != null && animation.filename == filename) {
- Idle.add (() => {
- get_animation.callback ();
- return Source.REMOVE;
- });
- yield;
+ public BackgroundCache () {
+ Object ();
+ }
+
+ construct {
+ file_monitors = new Gee.HashMap ();
+ }
- return animation;
- }
+ public void monitor_file (string filename) {
+ if (file_monitors.has_key (filename))
+ return;
- var animation = new Animation (filename);
+ var file = File.new_for_path (filename);
+ try {
+ var monitor = file.monitor (FileMonitorFlags.NONE, null);
+ monitor.changed.connect (() => {
+ file_changed (filename);
+ });
- yield animation.load ();
+ file_monitors[filename] = monitor;
+ } catch (Error e) {
+ warning ("Failed to monitor %s: %s", filename, e.message);
+ }
+ }
+ public async Animation get_animation (string filename) {
+ if (animation != null && animation.filename == filename) {
Idle.add (() => {
get_animation.callback ();
return Source.REMOVE;
@@ -82,20 +57,32 @@ namespace Gala {
return animation;
}
- public BackgroundSource get_background_source (Meta.Display display) {
- if (background_source == null) {
- background_source = new BackgroundSource (display);
- background_source.use_count = 1;
- } else
- background_source.use_count++;
+ var animation = new Animation (filename);
- return background_source;
- }
+ yield animation.load ();
+
+ Idle.add (() => {
+ get_animation.callback ();
+ return Source.REMOVE;
+ });
+ yield;
+
+ return animation;
+ }
+
+ public BackgroundSource get_background_source (Meta.Display display) {
+ if (background_source == null) {
+ background_source = new BackgroundSource (display);
+ background_source.use_count = 1;
+ } else
+ background_source.use_count++;
+
+ return background_source;
+ }
- public void release_background_source () {
- if (--background_source.use_count == 0) {
- background_source.destroy ();
- }
+ public void release_background_source () {
+ if (--background_source.use_count == 0) {
+ background_source.destroy ();
}
}
}
diff --git a/src/Background/BackgroundContainer.vala b/src/Background/BackgroundContainer.vala
index 01aee1fdb..2f824b33f 100644
--- a/src/Background/BackgroundContainer.vala
+++ b/src/Background/BackgroundContainer.vala
@@ -1,80 +1,68 @@
-//
-// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2013 Tom Beckmann
+ * 2013 Rico Tzschichholz
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
-namespace Gala {
- public class BackgroundContainer : Meta.BackgroundGroup {
- public signal void changed ();
- public signal void show_background_menu (int x, int y);
+public class Gala.BackgroundContainer : Meta.BackgroundGroup {
+ public signal void changed ();
+ public signal void show_background_menu (int x, int y);
- public Meta.Display display { get; construct; }
+ public Meta.Display display { get; construct; }
- public BackgroundContainer (Meta.Display display) {
- Object (display: display);
- }
+ public BackgroundContainer (Meta.Display display) {
+ Object (display: display);
+ }
- construct {
- unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
- monitor_manager.monitors_changed.connect (update);
+ construct {
+ unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
+ monitor_manager.monitors_changed.connect (update);
- reactive = true;
- button_release_event.connect ((event) => {
- float x, y;
- event.get_coords (out x, out y);
- if (event.get_button () == Clutter.Button.SECONDARY) {
- show_background_menu ((int)x, (int)y);
- }
- });
+ reactive = true;
+ button_release_event.connect ((event) => {
+ float x, y;
+ event.get_coords (out x, out y);
+ if (event.get_button () == Clutter.Button.SECONDARY) {
+ show_background_menu ((int)x, (int)y);
+ }
+ });
- set_black_background (true);
- update ();
- }
+ set_black_background (true);
+ update ();
+ }
- ~BackgroundContainer () {
- unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
- monitor_manager.monitors_changed.disconnect (update);
- }
+ ~BackgroundContainer () {
+ unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
+ monitor_manager.monitors_changed.disconnect (update);
+ }
- public void set_black_background (bool black) {
+ public void set_black_background (bool black) {
#if HAS_MUTTER47
- set_background_color (black ? Cogl.Color.from_string ("Black") : null);
+ set_background_color (black ? Cogl.Color.from_string ("Black") : null);
#else
- set_background_color (black ? Clutter.Color.from_string ("Black") : null);
+ set_background_color (black ? Clutter.Color.from_string ("Black") : null);
#endif
- }
+ }
- private void update () {
- var reference_child = (get_child_at_index (0) as BackgroundManager);
- if (reference_child != null)
- reference_child.changed.disconnect (background_changed);
+ private void update () {
+ var reference_child = (get_child_at_index (0) as BackgroundManager);
+ if (reference_child != null)
+ reference_child.changed.disconnect (background_changed);
- destroy_all_children ();
+ destroy_all_children ();
- for (var i = 0; i < display.get_n_monitors (); i++) {
- var background = new BackgroundManager (display, i);
+ for (var i = 0; i < display.get_n_monitors (); i++) {
+ var background = new BackgroundManager (display, i);
- add_child (background);
+ add_child (background);
- if (i == 0)
- background.changed.connect (background_changed);
- }
+ if (i == 0)
+ background.changed.connect (background_changed);
}
+ }
- private void background_changed () {
- changed ();
- }
+ private void background_changed () {
+ changed ();
}
}
diff --git a/src/Background/BackgroundSource.vala b/src/Background/BackgroundSource.vala
index 095340567..3c7a69838 100644
--- a/src/Background/BackgroundSource.vala
+++ b/src/Background/BackgroundSource.vala
@@ -1,166 +1,153 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- public class BackgroundSource : Object {
- // list of keys that are actually relevant for us
- private const string[] OPTIONS = {
- "color-shading-type",
- "picture-options",
- "picture-uri",
- "picture-uri-dark",
- "primary-color",
- "secondary-color"
- };
-
- public signal void changed ();
-
- public Meta.Display display { get; construct; }
- public GLib.Settings gnome_background_settings { get; private set; }
-
- internal int use_count { get; set; default = 0; }
-
- private GLib.HashTable backgrounds;
- private uint[] hash_cache;
- private Meta.MonitorManager? monitor_manager;
- private GLib.Settings gala_background_settings;
-
- public bool should_dim {
- get {
- return (
- Drawing.StyleManager.get_instance ().prefers_color_scheme == DARK &&
- gala_background_settings.get_boolean ("dim-wallpaper-in-dark-style")
- );
- }
- }
-
- public BackgroundSource (Meta.Display display) {
- Object (display: display);
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+public class Gala.BackgroundSource : Object {
+ // list of keys that are actually relevant for us
+ private const string[] OPTIONS = {
+ "color-shading-type",
+ "picture-options",
+ "picture-uri",
+ "picture-uri-dark",
+ "primary-color",
+ "secondary-color"
+ };
+
+ public signal void changed ();
+
+ public Meta.Display display { get; construct; }
+ public GLib.Settings gnome_background_settings { get; private set; }
+
+ internal int use_count { get; set; default = 0; }
+
+ private GLib.HashTable backgrounds;
+ private uint[] hash_cache;
+ private Meta.MonitorManager? monitor_manager;
+ private GLib.Settings gala_background_settings;
+
+ public bool should_dim {
+ get {
+ return (
+ Drawing.StyleManager.get_instance ().prefers_color_scheme == DARK &&
+ gala_background_settings.get_boolean ("dim-wallpaper-in-dark-style")
+ );
}
+ }
- construct {
- backgrounds = new GLib.HashTable (GLib.direct_hash, GLib.direct_equal);
- hash_cache = new uint[OPTIONS.length];
+ public BackgroundSource (Meta.Display display) {
+ Object (display: display);
+ }
- monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
- monitor_manager.monitors_changed.connect (monitors_changed);
+ construct {
+ backgrounds = new GLib.HashTable (GLib.direct_hash, GLib.direct_equal);
+ hash_cache = new uint[OPTIONS.length];
- gala_background_settings = new GLib.Settings ("io.elementary.desktop.background");
- gala_background_settings.changed["dim-wallpaper-in-dark-style"].connect (() => changed ());
+ monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
+ monitor_manager.monitors_changed.connect (monitors_changed);
- Drawing.StyleManager.get_instance ().notify["prefers-color-scheme"].connect (() => changed ());
+ gala_background_settings = new GLib.Settings ("io.elementary.desktop.background");
+ gala_background_settings.changed["dim-wallpaper-in-dark-style"].connect (() => changed ());
- gnome_background_settings = new GLib.Settings ("org.gnome.desktop.background");
+ Drawing.StyleManager.get_instance ().notify["prefers-color-scheme"].connect (() => changed ());
- // unfortunately the settings sometimes tend to fire random changes even though
- // nothing actually happened. The code below is used to prevent us from spamming
- // new actors all the time, which lead to some problems in other areas of the code
- for (int i = 0; i < OPTIONS.length; i++) {
- hash_cache[i] = gnome_background_settings.get_value (OPTIONS[i]).hash ();
- }
+ gnome_background_settings = new GLib.Settings ("org.gnome.desktop.background");
- gnome_background_settings.changed.connect ((key) => {
- for (int i = 0; i < OPTIONS.length; i++) {
- if (key == OPTIONS[i]) {
- uint new_hash = gnome_background_settings.get_value (key).hash ();
- if (hash_cache[i] != new_hash) {
- hash_cache[i] = new_hash;
- changed ();
- break;
- }
- }
- }
- });
+ // unfortunately the settings sometimes tend to fire random changes even though
+ // nothing actually happened. The code below is used to prevent us from spamming
+ // new actors all the time, which lead to some problems in other areas of the code
+ for (int i = 0; i < OPTIONS.length; i++) {
+ hash_cache[i] = gnome_background_settings.get_value (OPTIONS[i]).hash ();
}
- private void monitors_changed () {
- var n = display.get_n_monitors ();
- var i = 0;
-
- backgrounds.foreach_remove ((hash, background) => {
- if (i++ < n) {
- background.update_resolution ();
- return false;
- } else {
- background.changed.disconnect (background_changed);
- background.destroy ();
- return true;
+ gnome_background_settings.changed.connect ((key) => {
+ for (int i = 0; i < OPTIONS.length; i++) {
+ if (key == OPTIONS[i]) {
+ uint new_hash = gnome_background_settings.get_value (key).hash ();
+ if (hash_cache[i] != new_hash) {
+ hash_cache[i] = new_hash;
+ changed ();
+ break;
+ }
}
- });
- }
+ }
+ });
+ }
- public Background get_background (int monitor_index) {
- string? filename = null;
+ private void monitors_changed () {
+ var n = display.get_n_monitors ();
+ var i = 0;
- var style = gnome_background_settings.get_enum ("picture-options");
- if (style != GDesktop.BackgroundStyle.NONE) {
- filename = get_background_path ();
+ backgrounds.foreach_remove ((hash, background) => {
+ if (i++ < n) {
+ background.update_resolution ();
+ return false;
+ } else {
+ background.changed.disconnect (background_changed);
+ background.destroy ();
+ return true;
}
+ });
+ }
- // Animated backgrounds are (potentially) per-monitor, since
- // they can have variants that depend on the aspect ratio and
- // size of the monitor; for other backgrounds we can use the
- // same background object for all monitors.
- if (filename == null || !filename.has_suffix (".xml"))
- monitor_index = 0;
-
- var background = backgrounds.lookup (monitor_index);
- if (background == null) {
- background = new Background (display, monitor_index, filename, this, (GDesktop.BackgroundStyle) style);
- background.changed.connect (background_changed);
- backgrounds.insert (monitor_index, background);
- }
+ public Background get_background (int monitor_index) {
+ string? filename = null;
- return background;
+ var style = gnome_background_settings.get_enum ("picture-options");
+ if (style != GDesktop.BackgroundStyle.NONE) {
+ filename = get_background_path ();
}
- private string get_background_path () {
- if (Drawing.StyleManager.get_instance ().prefers_color_scheme == DARK) {
- var uri = gnome_background_settings.get_string ("picture-uri-dark");
- var path = File.new_for_uri (uri).get_path ();
- if (FileUtils.test (path, EXISTS)) {
- return path;
- }
- }
+ // Animated backgrounds are (potentially) per-monitor, since
+ // they can have variants that depend on the aspect ratio and
+ // size of the monitor; for other backgrounds we can use the
+ // same background object for all monitors.
+ if (filename == null || !filename.has_suffix (".xml"))
+ monitor_index = 0;
+
+ var background = backgrounds.lookup (monitor_index);
+ if (background == null) {
+ background = new Background (display, monitor_index, filename, this, (GDesktop.BackgroundStyle) style);
+ background.changed.connect (background_changed);
+ backgrounds.insert (monitor_index, background);
+ }
+
+ return background;
+ }
- var uri = gnome_background_settings.get_string ("picture-uri");
+ private string get_background_path () {
+ if (Drawing.StyleManager.get_instance ().prefers_color_scheme == DARK) {
+ var uri = gnome_background_settings.get_string ("picture-uri-dark");
var path = File.new_for_uri (uri).get_path ();
if (FileUtils.test (path, EXISTS)) {
return path;
}
-
- return uri;
}
- private void background_changed (Background background) {
- background.changed.disconnect (background_changed);
- background.destroy ();
- backgrounds.remove (background.monitor_index);
+ var uri = gnome_background_settings.get_string ("picture-uri");
+ var path = File.new_for_uri (uri).get_path ();
+ if (FileUtils.test (path, EXISTS)) {
+ return path;
}
- public void destroy () {
- monitor_manager.monitors_changed.disconnect (monitors_changed);
- monitor_manager = null;
+ return uri;
+ }
+
+ private void background_changed (Background background) {
+ background.changed.disconnect (background_changed);
+ background.destroy ();
+ backgrounds.remove (background.monitor_index);
+ }
- backgrounds.foreach_remove ((hash, background) => {
- background.changed.disconnect (background_changed);
- background.destroy ();
- return true;
- });
- }
+ public void destroy () {
+ monitor_manager.monitors_changed.disconnect (monitors_changed);
+ monitor_manager = null;
+
+ backgrounds.foreach_remove ((hash, background) => {
+ background.changed.disconnect (background_changed);
+ background.destroy ();
+ return true;
+ });
}
}
diff --git a/src/DBusAccelerator.vala b/src/DBusAccelerator.vala
index 5c496d9ab..493e0118f 100644
--- a/src/DBusAccelerator.vala
+++ b/src/DBusAccelerator.vala
@@ -1,22 +1,12 @@
-//
-// Copyright (C) 2015 Nicolas Bruguier, Corentin Noël
-// 2025 elementary, Inc.
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2015 Nicolas Bruguier
+ * 2015 Corentin Noël
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+[DBus (name="org.gnome.Shell")]
+public class Gala.DBusAccelerator {
[Flags]
public enum ActionMode {
/**
@@ -71,116 +61,113 @@ namespace Gala {
public uint action;
}
- [DBus (name="org.gnome.Shell")]
- public class DBusAccelerator {
- private const string NOTIFICATION_COMPONENT_NAME = "DBusAccelerator";
+ private const string NOTIFICATION_COMPONENT_NAME = "DBusAccelerator";
- public signal void accelerator_activated (uint action, GLib.HashTable parameters);
+ public signal void accelerator_activated (uint action, GLib.HashTable parameters);
- private Meta.Display display;
- private NotificationsManager notifications_manager;
- private GLib.HashTable grabbed_accelerators;
+ private Meta.Display display;
+ private NotificationsManager notifications_manager;
+ private GLib.HashTable grabbed_accelerators;
- public DBusAccelerator (Meta.Display _display, NotificationsManager _notifications_manager) {
- display = _display;
- notifications_manager = _notifications_manager;
- grabbed_accelerators = new HashTable (str_hash, str_equal);
- display.accelerator_activated.connect (on_accelerator_activated);
- }
+ public DBusAccelerator (Meta.Display _display, NotificationsManager _notifications_manager) {
+ display = _display;
+ notifications_manager = _notifications_manager;
+ grabbed_accelerators = new HashTable (str_hash, str_equal);
+ display.accelerator_activated.connect (on_accelerator_activated);
+ }
- private void on_accelerator_activated (uint action, Clutter.InputDevice device, uint timestamp) {
- foreach (unowned GrabbedAccelerator accel in grabbed_accelerators.get_values ()) {
- if (accel.action == action) {
- var parameters = new GLib.HashTable (null, null);
- parameters.set ("timestamp", new Variant.uint32 (timestamp));
- if (device.device_node != null) {
- parameters.set ("device-node", new Variant.string (device.device_node));
- }
+ private void on_accelerator_activated (uint action, Clutter.InputDevice device, uint timestamp) {
+ foreach (unowned GrabbedAccelerator accel in grabbed_accelerators.get_values ()) {
+ if (accel.action == action) {
+ var parameters = new GLib.HashTable (null, null);
+ parameters.set ("timestamp", new Variant.uint32 (timestamp));
+ if (device.device_node != null) {
+ parameters.set ("device-node", new Variant.string (device.device_node));
+ }
- accelerator_activated (action, parameters);
+ accelerator_activated (action, parameters);
- return;
- }
+ return;
}
}
+ }
- public uint grab_accelerator (string accelerator, ActionMode flags, Meta.KeyBindingFlags grab_flags) throws GLib.DBusError, GLib.IOError {
- unowned var found_accel = grabbed_accelerators[accelerator];
- if (found_accel != null) {
- return found_accel.action;
- }
-
- uint action = display.grab_accelerator (accelerator, grab_flags);
- if (action != Meta.KeyBindingFlags.NONE) {
- var accel = new GrabbedAccelerator ();
- accel.action = action;
- accel.name = accelerator;
- accel.flags = flags;
- accel.grab_flags = grab_flags;
- grabbed_accelerators.insert (accel.name, (owned)accel);
- }
+ public uint grab_accelerator (string accelerator, ActionMode flags, Meta.KeyBindingFlags grab_flags) throws GLib.DBusError, GLib.IOError {
+ unowned var found_accel = grabbed_accelerators[accelerator];
+ if (found_accel != null) {
+ return found_accel.action;
+ }
- return action;
+ uint action = display.grab_accelerator (accelerator, grab_flags);
+ if (action != Meta.KeyBindingFlags.NONE) {
+ var accel = new GrabbedAccelerator ();
+ accel.action = action;
+ accel.name = accelerator;
+ accel.flags = flags;
+ accel.grab_flags = grab_flags;
+ grabbed_accelerators.insert (accel.name, (owned)accel);
}
- public uint[] grab_accelerators (Accelerator[] accelerators) throws GLib.DBusError, GLib.IOError {
- uint[] actions = {};
+ return action;
+ }
- foreach (unowned Accelerator accelerator in accelerators) {
- actions += grab_accelerator (accelerator.name, accelerator.flags, accelerator.grab_flags);
- }
+ public uint[] grab_accelerators (Accelerator[] accelerators) throws GLib.DBusError, GLib.IOError {
+ uint[] actions = {};
- return actions;
+ foreach (unowned Accelerator accelerator in accelerators) {
+ actions += grab_accelerator (accelerator.name, accelerator.flags, accelerator.grab_flags);
}
- public bool ungrab_accelerator (uint action) throws GLib.DBusError, GLib.IOError {
- foreach (unowned GrabbedAccelerator accel in grabbed_accelerators.get_values ()) {
- if (accel.action == action) {
- bool ret = display.ungrab_accelerator (action);
- grabbed_accelerators.remove (accel.name);
- return ret;
- }
- }
+ return actions;
+ }
- return false;
+ public bool ungrab_accelerator (uint action) throws GLib.DBusError, GLib.IOError {
+ foreach (unowned GrabbedAccelerator accel in grabbed_accelerators.get_values ()) {
+ if (accel.action == action) {
+ bool ret = display.ungrab_accelerator (action);
+ grabbed_accelerators.remove (accel.name);
+ return ret;
+ }
}
- public bool ungrab_accelerators (uint[] actions) throws GLib.DBusError, GLib.IOError {
- foreach (uint action in actions) {
- ungrab_accelerator (action);
- }
+ return false;
+ }
- return true;
+ public bool ungrab_accelerators (uint[] actions) throws GLib.DBusError, GLib.IOError {
+ foreach (uint action in actions) {
+ ungrab_accelerator (action);
}
- [DBus (name = "ShowOSD")]
- public void show_osd (GLib.HashTable parameters) throws GLib.DBusError, GLib.IOError {
- int32 monitor_index = -1;
- if (parameters.contains ("monitor"))
- monitor_index = parameters["monitor"].get_int32 ();
- string icon = "";
- if (parameters.contains ("icon"))
- icon = parameters["icon"].get_string ();
- string label = "";
- if (parameters.contains ("label"))
- label = parameters["label"].get_string ();
- int32 level = 0;
- if (parameters.contains ("level")) {
- var double_level = parameters["level"].get_double ();
- level = (int)(double_level * 100);
- }
+ return true;
+ }
- var hints = new GLib.HashTable (null, null);
- hints.set ("x-canonical-private-synchronous", new Variant.string ("gala-feedback"));
- hints.set ("value", new Variant.int32 (level));
-
- notifications_manager.send.begin (
- NOTIFICATION_COMPONENT_NAME,
- icon,
- label,
- "",
- hints
- );
+ [DBus (name = "ShowOSD")]
+ public void show_osd (GLib.HashTable parameters) throws GLib.DBusError, GLib.IOError {
+ int32 monitor_index = -1;
+ if (parameters.contains ("monitor"))
+ monitor_index = parameters["monitor"].get_int32 ();
+ string icon = "";
+ if (parameters.contains ("icon"))
+ icon = parameters["icon"].get_string ();
+ string label = "";
+ if (parameters.contains ("label"))
+ label = parameters["label"].get_string ();
+ int32 level = 0;
+ if (parameters.contains ("level")) {
+ var double_level = parameters["level"].get_double ();
+ level = (int)(double_level * 100);
}
+
+ var hints = new GLib.HashTable (null, null);
+ hints.set ("x-canonical-private-synchronous", new Variant.string ("gala-feedback"));
+ hints.set ("value", new Variant.int32 (level));
+
+ notifications_manager.send.begin (
+ NOTIFICATION_COMPONENT_NAME,
+ icon,
+ label,
+ "",
+ hints
+ );
}
}
diff --git a/src/PluginManager.vala b/src/PluginManager.vala
index 0af190e5b..6ad1a6afb 100644
--- a/src/PluginManager.vala
+++ b/src/PluginManager.vala
@@ -1,217 +1,204 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- public delegate PluginInfo RegisterPluginFunction ();
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+public class Gala.PluginManager : Object {
+ private static PluginManager? instance = null;
+ public static unowned PluginManager get_default () {
+ if (instance == null)
+ instance = new PluginManager ();
+
+ return instance;
+ }
- public class PluginManager : Object {
- private static PluginManager? instance = null;
- public static unowned PluginManager get_default () {
- if (instance == null)
- instance = new PluginManager ();
+ public delegate PluginInfo RegisterPluginFunction ();
- return instance;
- }
+ public signal void regions_changed ();
- public signal void regions_changed ();
+ public bool initialized { get; private set; default = false; }
- public bool initialized { get; private set; default = false; }
+ private X.Xrectangle[] _regions = {};
+ public unowned X.Xrectangle[] get_regions () {
+ return _regions;
+ }
- private X.Xrectangle[] _regions = {};
- public unowned X.Xrectangle[] get_regions () {
- return _regions;
- }
+ public string? window_switcher_provider { get; private set; default = null; }
+ public string? window_overview_provider { get; private set; default = null; }
+ public string? workspace_view_provider { get; private set; default = null; }
- public string? window_switcher_provider { get; private set; default = null; }
- public string? window_overview_provider { get; private set; default = null; }
- public string? workspace_view_provider { get; private set; default = null; }
+ private HashTable plugins;
+ private File plugin_dir;
- private HashTable plugins;
- private File plugin_dir;
+ private WindowManager? wm = null;
- private WindowManager? wm = null;
+ private Gee.LinkedList load_later_plugins;
- private Gee.LinkedList load_later_plugins;
+ private PluginManager () {
+ plugins = new HashTable (str_hash, str_equal);
+ load_later_plugins = new Gee.LinkedList ();
- private PluginManager () {
- plugins = new HashTable (str_hash, str_equal);
- load_later_plugins = new Gee.LinkedList ();
+ if (!Module.supported ()) {
+ warning ("Modules are not supported on this platform");
+ return;
+ }
- if (!Module.supported ()) {
- warning ("Modules are not supported on this platform");
- return;
+ plugin_dir = File.new_for_path (Config.PLUGINDIR);
+ if (!plugin_dir.query_exists ())
+ return;
+
+ try {
+ var enumerator = plugin_dir.enumerate_children (FileAttribute.STANDARD_NAME +
+ "," + FileAttribute.STANDARD_CONTENT_TYPE, 0);
+ FileInfo info;
+ while ((info = enumerator.next_file ()) != null) {
+ if (info.get_content_type () == "application/x-sharedlib")
+ load_module (info.get_name ());
}
+ } catch (Error e) {
+ warning (e.message);
+ }
- plugin_dir = File.new_for_path (Config.PLUGINDIR);
- if (!plugin_dir.query_exists ())
- return;
-
- try {
- var enumerator = plugin_dir.enumerate_children (FileAttribute.STANDARD_NAME +
- "," + FileAttribute.STANDARD_CONTENT_TYPE, 0);
- FileInfo info;
- while ((info = enumerator.next_file ()) != null) {
- if (info.get_content_type () == "application/x-sharedlib")
- load_module (info.get_name ());
+ try {
+ plugin_dir.monitor_directory (FileMonitorFlags.NONE, null).changed.connect ((file, other_file, type) => {
+ if (type == FileMonitorEvent.CREATED) {
+ load_module (file.get_basename ());
}
- } catch (Error e) {
- warning (e.message);
- }
-
- try {
- plugin_dir.monitor_directory (FileMonitorFlags.NONE, null).changed.connect ((file, other_file, type) => {
- if (type == FileMonitorEvent.CREATED) {
- load_module (file.get_basename ());
- }
- });
- } catch (Error e) {
- warning (e.message);
- }
+ });
+ } catch (Error e) {
+ warning (e.message);
}
+ }
- private bool load_module (string plugin_name) {
- var path = Module.build_path (plugin_dir.get_path (), plugin_name);
- var module = Module.open (path, ModuleFlags.LOCAL);
- if (module == null) {
- warning (Module.error ());
- return false;
- }
-
- void* function;
- module.symbol ("register_plugin", out function);
- if (function == null) {
- warning ("%s failed to register: register_plugin() function not found", plugin_name);
- return false;
- }
- unowned RegisterPluginFunction register = (RegisterPluginFunction)function;
+ private bool load_module (string plugin_name) {
+ var path = Module.build_path (plugin_dir.get_path (), plugin_name);
+ var module = Module.open (path, ModuleFlags.LOCAL);
+ if (module == null) {
+ warning (Module.error ());
+ return false;
+ }
- var info = register ();
- if (info.plugin_type.is_a (typeof (Plugin)) == false) {
- warning ("%s does not return a class of type Plugin", plugin_name);
- return false;
- }
+ void* function;
+ module.symbol ("register_plugin", out function);
+ if (function == null) {
+ warning ("%s failed to register: register_plugin() function not found", plugin_name);
+ return false;
+ }
+ unowned RegisterPluginFunction register = (RegisterPluginFunction)function;
- if (!check_provides (info.name, info.provides)) {
- return false;
- }
+ var info = register ();
+ if (info.plugin_type.is_a (typeof (Plugin)) == false) {
+ warning ("%s does not return a class of type Plugin", plugin_name);
+ return false;
+ }
- info.module_name = plugin_name;
- module.make_resident ();
+ if (!check_provides (info.name, info.provides)) {
+ return false;
+ }
- if (info.load_priority == LoadPriority.DEFERRED && !initialized) {
- load_later_plugins.add (info);
- } else {
- load_plugin_class (info);
- }
+ info.module_name = plugin_name;
+ module.make_resident ();
- return true;
+ if (info.load_priority == LoadPriority.DEFERRED && !initialized) {
+ load_later_plugins.add (info);
+ } else {
+ load_plugin_class (info);
}
- private void load_plugin_class (PluginInfo info) {
- var plugin = (Plugin)Object.@new (info.plugin_type);
- plugins.set (info.module_name, plugin);
+ return true;
+ }
- debug ("Loaded plugin %s (%s)", info.name, info.module_name);
+ private void load_plugin_class (PluginInfo info) {
+ var plugin = (Plugin)Object.@new (info.plugin_type);
+ plugins.set (info.module_name, plugin);
- if (initialized) {
- initialize_plugin (info.module_name, plugin);
- recalculate_regions ();
- }
- }
+ debug ("Loaded plugin %s (%s)", info.name, info.module_name);
- private void initialize_plugin (string plugin_name, Plugin plugin) {
- plugin.initialize (wm);
- plugin.region_changed.connect (recalculate_regions);
+ if (initialized) {
+ initialize_plugin (info.module_name, plugin);
+ recalculate_regions ();
}
+ }
- private bool check_provides (string name, PluginFunction provides) {
- var message = "Plugins %s and %s both provide %s functionality, using first one only";
- switch (provides) {
- case PluginFunction.WORKSPACE_VIEW:
- if (workspace_view_provider != null) {
- warning (message, workspace_view_provider, name, "workspace view");
- return false;
- }
- workspace_view_provider = name;
- return true;
- case PluginFunction.WINDOW_OVERVIEW:
- if (window_overview_provider != null) {
- warning (message, window_overview_provider, name, "window overview");
- return false;
- }
- window_overview_provider = name;
- return true;
- case PluginFunction.WINDOW_SWITCHER:
- if (window_switcher_provider != null) {
- warning (message, window_switcher_provider, name, "window switcher");
- return false;
- }
- window_switcher_provider = name;
- return true;
- default:
- break;
- }
+ private void initialize_plugin (string plugin_name, Plugin plugin) {
+ plugin.initialize (wm);
+ plugin.region_changed.connect (recalculate_regions);
+ }
- return true;
+ private bool check_provides (string name, PluginFunction provides) {
+ var message = "Plugins %s and %s both provide %s functionality, using first one only";
+ switch (provides) {
+ case PluginFunction.WORKSPACE_VIEW:
+ if (workspace_view_provider != null) {
+ warning (message, workspace_view_provider, name, "workspace view");
+ return false;
+ }
+ workspace_view_provider = name;
+ return true;
+ case PluginFunction.WINDOW_OVERVIEW:
+ if (window_overview_provider != null) {
+ warning (message, window_overview_provider, name, "window overview");
+ return false;
+ }
+ window_overview_provider = name;
+ return true;
+ case PluginFunction.WINDOW_SWITCHER:
+ if (window_switcher_provider != null) {
+ warning (message, window_switcher_provider, name, "window switcher");
+ return false;
+ }
+ window_switcher_provider = name;
+ return true;
+ default:
+ break;
}
- public void initialize (WindowManager _wm) {
- wm = _wm;
+ return true;
+ }
- plugins.@foreach (initialize_plugin);
- recalculate_regions ();
+ public void initialize (WindowManager _wm) {
+ wm = _wm;
- initialized = true;
- }
+ plugins.@foreach (initialize_plugin);
+ recalculate_regions ();
- public void load_waiting_plugins () {
- foreach (var info in load_later_plugins) {
- load_plugin_class (info);
- }
+ initialized = true;
+ }
- load_later_plugins.clear ();
+ public void load_waiting_plugins () {
+ foreach (var info in load_later_plugins) {
+ load_plugin_class (info);
}
- public Plugin? get_plugin (string id) {
- return plugins.lookup (id);
- }
+ load_later_plugins.clear ();
+ }
- /**
- * Iterate over all plugins and grab their regions, update the regions
- * array accordingly and emit the regions_changed signal.
- */
- private void recalculate_regions () {
- X.Xrectangle[] regions = {};
-
- plugins.@foreach ((name, plugin) => {
- foreach (var region in plugin.get_region ()) {
- X.Xrectangle rect = {
- (short) region.x,
- (short) region.y,
- (ushort) region.width,
- (ushort) region.height
- };
-
- regions += rect;
- }
- });
+ public Plugin? get_plugin (string id) {
+ return plugins.lookup (id);
+ }
- this._regions = regions;
- regions_changed ();
- }
+ /**
+ * Iterate over all plugins and grab their regions, update the regions
+ * array accordingly and emit the regions_changed signal.
+ */
+ private void recalculate_regions () {
+ X.Xrectangle[] regions = {};
+
+ plugins.@foreach ((name, plugin) => {
+ foreach (var region in plugin.get_region ()) {
+ X.Xrectangle rect = {
+ (short) region.x,
+ (short) region.y,
+ (ushort) region.width,
+ (ushort) region.height
+ };
+
+ regions += rect;
+ }
+ });
+
+ this._regions = regions;
+ regions_changed ();
}
}
diff --git a/src/SessionManager.vala b/src/SessionManager.vala
index cbfe0a1f3..3184e2ba2 100644
--- a/src/SessionManager.vala
+++ b/src/SessionManager.vala
@@ -1,26 +1,16 @@
-//
-// Copyright (C) 2018 Adam Bieńkowski
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2018 Adam Bieńkowski
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
// Reference code by the Solus Project:
// https://github.com/solus-project/budgie-desktop/blob/master/src/wm/shim.vala
-namespace Gala {
+[DBus (name = "org.gnome.SessionManager.EndSessionDialog")]
+public class Gala.SessionManager : Object {
[DBus (name = "io.elementary.wingpanel.session.EndSessionDialog")]
- public interface WingpanelEndSessionDialog : Object {
+ private interface WingpanelEndSessionDialog : Object {
public signal void confirmed_logout ();
public signal void confirmed_reboot ();
public signal void confirmed_shutdown ();
@@ -30,63 +20,60 @@ namespace Gala {
public abstract void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError;
}
- [DBus (name = "org.gnome.SessionManager.EndSessionDialog")]
- public class SessionManager : Object {
- private static SessionManager? instance;
+ private static SessionManager? instance;
- [DBus (visible = false)]
- public static unowned SessionManager init () {
- if (instance == null) {
- instance = new SessionManager ();
- }
-
- return instance;
+ [DBus (visible = false)]
+ public static unowned SessionManager init () {
+ if (instance == null) {
+ instance = new SessionManager ();
}
- public signal void confirmed_logout ();
- public signal void confirmed_reboot ();
- public signal void confirmed_shutdown ();
- public signal void canceled ();
- public signal void closed ();
+ return instance;
+ }
- private WingpanelEndSessionDialog? proxy = null;
+ public signal void confirmed_logout ();
+ public signal void confirmed_reboot ();
+ public signal void confirmed_shutdown ();
+ public signal void canceled ();
+ public signal void closed ();
- private SessionManager () {
- Bus.watch_name (BusType.SESSION, "io.elementary.wingpanel.session.EndSessionDialog",
- BusNameWatcherFlags.NONE, proxy_appeared, proxy_vanished);
- }
+ private WingpanelEndSessionDialog? proxy = null;
- private void get_proxy_cb (Object? o, AsyncResult? res) {
- try {
- proxy = Bus.get_proxy.end (res);
- } catch (Error e) {
- warning ("Could not connect to io.elementary.wingpanel.session.EndSessionDialog proxy: %s", e.message);
- return;
- }
+ private SessionManager () {
+ Bus.watch_name (BusType.SESSION, "io.elementary.wingpanel.session.EndSessionDialog",
+ BusNameWatcherFlags.NONE, proxy_appeared, proxy_vanished);
+ }
- proxy.confirmed_logout.connect (() => confirmed_logout ());
- proxy.confirmed_reboot.connect (() => confirmed_reboot ());
- proxy.confirmed_shutdown.connect (() => confirmed_shutdown ());
- proxy.canceled.connect (() => canceled ());
- proxy.closed.connect (() => closed ());
+ private void get_proxy_cb (Object? o, AsyncResult? res) {
+ try {
+ proxy = Bus.get_proxy.end (res);
+ } catch (Error e) {
+ warning ("Could not connect to io.elementary.wingpanel.session.EndSessionDialog proxy: %s", e.message);
+ return;
}
- private void proxy_appeared () {
- Bus.get_proxy.begin (BusType.SESSION,
- "io.elementary.wingpanel.session.EndSessionDialog", "/io/elementary/wingpanel/session/EndSessionDialog",
- 0, null, get_proxy_cb);
- }
+ proxy.confirmed_logout.connect (() => confirmed_logout ());
+ proxy.confirmed_reboot.connect (() => confirmed_reboot ());
+ proxy.confirmed_shutdown.connect (() => confirmed_shutdown ());
+ proxy.canceled.connect (() => canceled ());
+ proxy.closed.connect (() => closed ());
+ }
- private void proxy_vanished () {
- proxy = null;
- }
+ private void proxy_appeared () {
+ Bus.get_proxy.begin (BusType.SESSION,
+ "io.elementary.wingpanel.session.EndSessionDialog", "/io/elementary/wingpanel/session/EndSessionDialog",
+ 0, null, get_proxy_cb);
+ }
- public void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError {
- if (proxy == null) {
- throw new DBusError.FAILED ("io.elementary.wingpanel.session.EndSessionDialog DBus interface is not registered.");
- }
+ private void proxy_vanished () {
+ proxy = null;
+ }
- proxy.open (type, timestamp, open_length, inhibiters);
+ public void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError {
+ if (proxy == null) {
+ throw new DBusError.FAILED ("io.elementary.wingpanel.session.EndSessionDialog DBus interface is not registered.");
}
+
+ proxy.open (type, timestamp, open_length, inhibiters);
}
}
diff --git a/src/Widgets/MonitorClone.vala b/src/Widgets/MonitorClone.vala
index 5f6f66e7f..efefd6d9a 100644
--- a/src/Widgets/MonitorClone.vala
+++ b/src/Widgets/MonitorClone.vala
@@ -1,122 +1,109 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- /**
- * More or less utility class to contain a WindowCloneContainer for each
- * non-primary monitor. It's the pendant to the WorkspaceClone which is
- * only placed on the primary monitor. It also draws a wallpaper behind itself
- * as the WindowGroup is hidden while the view is active. Only used when
- * workspaces-only-on-primary is set to true.
- */
- public class MonitorClone : Clutter.Actor {
- public signal void window_selected (Meta.Window window);
-
- public Meta.Display display { get; construct; }
- public int monitor { get; construct; }
- public GestureTracker gesture_tracker { get; construct; }
-
- private WindowCloneContainer window_container;
- private BackgroundManager background;
-
- public MonitorClone (Meta.Display display, int monitor, GestureTracker gesture_tracker) {
- Object (display: display, monitor: monitor, gesture_tracker: gesture_tracker);
- }
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+/**
+ * More or less utility class to contain a WindowCloneContainer for each
+ * non-primary monitor. It's the pendant to the WorkspaceClone which is
+ * only placed on the primary monitor. It also draws a wallpaper behind itself
+ * as the WindowGroup is hidden while the view is active. Only used when
+ * workspaces-only-on-primary is set to true.
+ */
+public class Gala.MonitorClone : Clutter.Actor {
+ public signal void window_selected (Meta.Window window);
+
+ public Meta.Display display { get; construct; }
+ public int monitor { get; construct; }
+ public GestureTracker gesture_tracker { get; construct; }
+
+ private WindowCloneContainer window_container;
+ private BackgroundManager background;
+
+ public MonitorClone (Meta.Display display, int monitor, GestureTracker gesture_tracker) {
+ Object (display: display, monitor: monitor, gesture_tracker: gesture_tracker);
+ }
- construct {
- reactive = true;
+ construct {
+ reactive = true;
- background = new BackgroundManager (display, monitor, false);
+ background = new BackgroundManager (display, monitor, false);
- var scale = display.get_monitor_scale (monitor);
+ var scale = display.get_monitor_scale (monitor);
- window_container = new WindowCloneContainer (display, gesture_tracker, scale);
- window_container.window_selected.connect ((w) => { window_selected (w); });
+ window_container = new WindowCloneContainer (display, gesture_tracker, scale);
+ window_container.window_selected.connect ((w) => { window_selected (w); });
- display.window_entered_monitor.connect (window_entered);
- display.window_left_monitor.connect (window_left);
+ display.window_entered_monitor.connect (window_entered);
+ display.window_left_monitor.connect (window_left);
- unowned GLib.List window_actors = display.get_window_actors ();
- foreach (unowned Meta.WindowActor window_actor in window_actors) {
- if (window_actor.is_destroyed ())
- continue;
+ unowned GLib.List window_actors = display.get_window_actors ();
+ foreach (unowned Meta.WindowActor window_actor in window_actors) {
+ if (window_actor.is_destroyed ())
+ continue;
- unowned Meta.Window window = window_actor.get_meta_window ();
- if (window.get_monitor () == monitor) {
- window_entered (monitor, window);
- }
+ unowned Meta.Window window = window_actor.get_meta_window ();
+ if (window.get_monitor () == monitor) {
+ window_entered (monitor, window);
}
+ }
- add_child (background);
- add_child (window_container);
+ add_child (background);
+ add_child (window_container);
- var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
- add_action (drop);
+ var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
+ add_action (drop);
- update_allocation ();
- }
+ update_allocation ();
+ }
- ~MonitorClone () {
- display.window_entered_monitor.disconnect (window_entered);
- display.window_left_monitor.disconnect (window_left);
- }
+ ~MonitorClone () {
+ display.window_entered_monitor.disconnect (window_entered);
+ display.window_left_monitor.disconnect (window_left);
+ }
- /**
- * Make sure the MonitorClone is at the location of the monitor on the stage
- */
- public void update_allocation () {
- var monitor_geometry = display.get_monitor_geometry (monitor);
+ /**
+ * Make sure the MonitorClone is at the location of the monitor on the stage
+ */
+ public void update_allocation () {
+ var monitor_geometry = display.get_monitor_geometry (monitor);
- set_position (monitor_geometry.x, monitor_geometry.y);
- set_size (monitor_geometry.width, monitor_geometry.height);
- window_container.set_size (monitor_geometry.width, monitor_geometry.height);
+ set_position (monitor_geometry.x, monitor_geometry.y);
+ set_size (monitor_geometry.width, monitor_geometry.height);
+ window_container.set_size (monitor_geometry.width, monitor_geometry.height);
- var scale = display.get_monitor_scale (monitor);
- window_container.monitor_scale = scale;
- }
+ var scale = display.get_monitor_scale (monitor);
+ window_container.monitor_scale = scale;
+ }
- /**
- * Animate the windows from their old location to a tiled layout
- */
- public void open (bool with_gesture = false, bool is_cancel_animation = false) {
- window_container.restack_windows ();
- window_container.open (null, with_gesture, is_cancel_animation);
- }
+ /**
+ * Animate the windows from their old location to a tiled layout
+ */
+ public void open (bool with_gesture = false, bool is_cancel_animation = false) {
+ window_container.restack_windows ();
+ window_container.open (null, with_gesture, is_cancel_animation);
+ }
- /**
- * Animate the windows back to their old location
- */
- public void close (bool with_gesture = false, bool is_cancel_animation = false) {
- window_container.restack_windows ();
- window_container.close (with_gesture);
- }
+ /**
+ * Animate the windows back to their old location
+ */
+ public void close (bool with_gesture = false, bool is_cancel_animation = false) {
+ window_container.restack_windows ();
+ window_container.close (with_gesture);
+ }
- private void window_left (int window_monitor, Meta.Window window) {
- if (window_monitor != monitor)
- return;
+ private void window_left (int window_monitor, Meta.Window window) {
+ if (window_monitor != monitor)
+ return;
- window_container.remove_window (window);
- }
+ window_container.remove_window (window);
+ }
- private void window_entered (int window_monitor, Meta.Window window) {
- if (window_monitor != monitor || window.window_type != Meta.WindowType.NORMAL)
- return;
+ private void window_entered (int window_monitor, Meta.Window window) {
+ if (window_monitor != monitor || window.window_type != Meta.WindowType.NORMAL)
+ return;
- window_container.add_window (window);
- }
+ window_container.add_window (window);
}
}
diff --git a/src/Widgets/SafeWindowClone.vala b/src/Widgets/SafeWindowClone.vala
index 29a46f36d..1f1f2b072 100644
--- a/src/Widgets/SafeWindowClone.vala
+++ b/src/Widgets/SafeWindowClone.vala
@@ -1,66 +1,53 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+/**
+ * A clone for a MetaWindowActor that will guard against the
+ * meta_window_appears_focused crash by disabling painting the clone
+ * as soon as it gets unavailable.
+ */
+public class Gala.SafeWindowClone : Clutter.Clone {
+ public Meta.Window window { get; construct; }
-namespace Gala {
/**
- * A clone for a MetaWindowActor that will guard against the
- * meta_window_appears_focused crash by disabling painting the clone
- * as soon as it gets unavailable.
+ * If set to true, the SafeWindowClone will destroy itself when the connected
+ * window is unmanaged
*/
- public class SafeWindowClone : Clutter.Clone {
- public Meta.Window window { get; construct; }
+ public bool destroy_on_unmanaged { get; construct set; default = false; }
- /**
- * If set to true, the SafeWindowClone will destroy itself when the connected
- * window is unmanaged
- */
- public bool destroy_on_unmanaged { get; construct set; default = false; }
-
- /**
- * Creates a new SafeWindowClone
- *
- * @param window The window to clone from
- * @param destroy_on_unmanaged see destroy_on_unmanaged property
- */
- public SafeWindowClone (Meta.Window window, bool destroy_on_unmanaged = false) {
- var actor = (Meta.WindowActor) window.get_compositor_private ();
+ /**
+ * Creates a new SafeWindowClone
+ *
+ * @param window The window to clone from
+ * @param destroy_on_unmanaged see destroy_on_unmanaged property
+ */
+ public SafeWindowClone (Meta.Window window, bool destroy_on_unmanaged = false) {
+ var actor = (Meta.WindowActor) window.get_compositor_private ();
- Object (window: window,
- source: actor,
- destroy_on_unmanaged: destroy_on_unmanaged);
- }
+ Object (window: window,
+ source: actor,
+ destroy_on_unmanaged: destroy_on_unmanaged);
+ }
- construct {
- if (source != null)
- window.unmanaged.connect (reset_source);
- }
+ construct {
+ if (source != null)
+ window.unmanaged.connect (reset_source);
+ }
- ~SafeWindowClone () {
- window.unmanaged.disconnect (reset_source);
- }
+ ~SafeWindowClone () {
+ window.unmanaged.disconnect (reset_source);
+ }
- private void reset_source () {
- // actually destroying the clone will be handled somewhere else (unless we were
- // requested to destroy it), we just need to make sure the clone doesn't attempt
- // to draw a clone of a window that has been destroyed
- source = null;
+ private void reset_source () {
+ // actually destroying the clone will be handled somewhere else (unless we were
+ // requested to destroy it), we just need to make sure the clone doesn't attempt
+ // to draw a clone of a window that has been destroyed
+ source = null;
- if (destroy_on_unmanaged)
- destroy ();
- }
+ if (destroy_on_unmanaged)
+ destroy ();
}
}
diff --git a/src/Widgets/ScreenShield.vala b/src/Widgets/ScreenShield.vala
index edc94fb0b..06f47988a 100644
--- a/src/Widgets/ScreenShield.vala
+++ b/src/Widgets/ScreenShield.vala
@@ -1,23 +1,11 @@
-//
-// Copyright 2020 elementary, Inc. (https://elementary.io)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2020, 2025 elementary, Inc. (https://elementary.io)
+ */
+
+public class Gala.ScreenShield : Clutter.Actor {
[DBus (name = "org.freedesktop.login1.Manager")]
- interface LoginManager : Object {
+ private interface LoginManager : Object {
public signal void prepare_for_sleep (bool about_to_suspend);
public abstract GLib.ObjectPath get_session (string session_id) throws GLib.Error;
@@ -26,7 +14,7 @@ namespace Gala {
}
[DBus (name = "org.freedesktop.login1.Session")]
- interface LoginSessionManager : Object {
+ private interface LoginSessionManager : Object {
public abstract bool active { get; }
public signal void lock ();
@@ -35,18 +23,18 @@ namespace Gala {
public abstract void set_locked_hint (bool locked) throws GLib.Error;
}
- public struct LoginDisplay {
+ private struct LoginDisplay {
string session;
GLib.ObjectPath objectpath;
}
[DBus (name = "org.freedesktop.login1.User")]
- interface LoginUserManager : Object {
+ private interface LoginUserManager : Object {
public abstract LoginDisplay? display { owned get; }
}
[CCode (type_signature = "u")]
- enum PresenceStatus {
+ private enum PresenceStatus {
AVAILABLE = 0,
INVISIBLE = 1,
BUSY = 2,
@@ -54,379 +42,377 @@ namespace Gala {
}
[DBus (name = "org.gnome.SessionManager.Presence")]
- interface SessionPresence : Object {
+ private interface SessionPresence : Object {
public abstract PresenceStatus status { get; }
public signal void status_changed (PresenceStatus new_status);
}
[DBus (name = "org.freedesktop.DisplayManager.Seat")]
- interface DisplayManagerSeat : Object {
+ private interface DisplayManagerSeat : Object {
public abstract void switch_to_greeter () throws GLib.Error;
}
- public class ScreenShield : Clutter.Actor {
- // Animation length for when computer has been sitting idle and display
- // is about to turn off
- public const uint LONG_ANIMATION_TIME = 3000;
- // Animation length used for manual lock action (i.e. Super+L or GUI action)
- public const uint SHORT_ANIMATION_TIME = 300;
+ // Animation length for when computer has been sitting idle and display
+ // is about to turn off
+ public const uint LONG_ANIMATION_TIME = 3000;
+ // Animation length used for manual lock action (i.e. Super+L or GUI action)
+ public const uint SHORT_ANIMATION_TIME = 300;
- private const string LOCK_ENABLED_KEY = "lock-enabled";
- private const string LOCK_PROHIBITED_KEY = "disable-lock-screen";
- private const string LOCK_ON_SUSPEND_KEY = "lock-on-suspend";
+ private const string LOCK_ENABLED_KEY = "lock-enabled";
+ private const string LOCK_PROHIBITED_KEY = "disable-lock-screen";
+ private const string LOCK_ON_SUSPEND_KEY = "lock-on-suspend";
- public signal void active_changed ();
+ public signal void active_changed ();
- // Screensaver active but not necessarily locked
- public bool active { get; private set; default = false; }
+ // Screensaver active but not necessarily locked
+ public bool active { get; private set; default = false; }
- public bool is_locked { get; private set; default = false; }
- public bool in_greeter { get; private set; default = false; }
- public int64 activation_time { get; private set; default = 0; }
+ public bool is_locked { get; private set; default = false; }
+ public bool in_greeter { get; private set; default = false; }
+ public int64 activation_time { get; private set; default = 0; }
- public WindowManager wm { get; construct; }
+ public WindowManager wm { get; construct; }
- private ModalProxy? modal_proxy;
+ private ModalProxy? modal_proxy;
- private LoginManager? login_manager;
- private LoginUserManager? login_user_manager;
- private LoginSessionManager? login_session;
- private SessionPresence? session_presence;
+ private LoginManager? login_manager;
+ private LoginUserManager? login_user_manager;
+ private LoginSessionManager? login_session;
+ private SessionPresence? session_presence;
- private DisplayManagerSeat? display_manager;
+ private DisplayManagerSeat? display_manager;
- private uint animate_id = 0;
+ private uint animate_id = 0;
- private UnixInputStream? inhibitor;
+ private UnixInputStream? inhibitor;
- private GLib.Settings screensaver_settings;
- private GLib.Settings lockdown_settings;
- private GLib.Settings gala_settings;
+ private GLib.Settings screensaver_settings;
+ private GLib.Settings lockdown_settings;
+ private GLib.Settings gala_settings;
- private bool connected_to_buses = false;
+ private bool connected_to_buses = false;
- public ScreenShield (WindowManager wm) {
- Object (wm: wm);
- }
+ public ScreenShield (WindowManager wm) {
+ Object (wm: wm);
+ }
- construct {
- // We use the lock-enabled key in the GNOME namespace instead of our own
- // because it's also used by gsd-power
- screensaver_settings = new GLib.Settings ("org.gnome.desktop.screensaver");
+ construct {
+ // We use the lock-enabled key in the GNOME namespace instead of our own
+ // because it's also used by gsd-power
+ screensaver_settings = new GLib.Settings ("org.gnome.desktop.screensaver");
- // Vanilla GNOME doesn't have a key that separately enables/disables locking on
- // suspend, so we have a key in our own namespace for this
- gala_settings = new GLib.Settings ("io.elementary.desktop.screensaver");
- lockdown_settings = new GLib.Settings ("org.gnome.desktop.lockdown");
+ // Vanilla GNOME doesn't have a key that separately enables/disables locking on
+ // suspend, so we have a key in our own namespace for this
+ gala_settings = new GLib.Settings ("io.elementary.desktop.screensaver");
+ lockdown_settings = new GLib.Settings ("org.gnome.desktop.lockdown");
- visible = false;
- reactive = true;
+ visible = false;
+ reactive = true;
- // Listen for keypresses or mouse movement
- key_press_event.connect ((event) => {
- on_user_became_active ();
- return Clutter.EVENT_STOP;
- });
+ // Listen for keypresses or mouse movement
+ key_press_event.connect ((event) => {
+ on_user_became_active ();
+ return Clutter.EVENT_STOP;
+ });
- motion_event.connect ((event) => {
- on_user_became_active ();
- return Clutter.EVENT_STOP;
- });
+ motion_event.connect ((event) => {
+ on_user_became_active ();
+ return Clutter.EVENT_STOP;
+ });
#if HAS_MUTTER47
- background_color = Cogl.Color.from_string ("black");
+ background_color = Cogl.Color.from_string ("black");
#else
- background_color = Clutter.Color.from_string ("black");
+ background_color = Clutter.Color.from_string ("black");
#endif
- expand_to_screen_size ();
+ expand_to_screen_size ();
+
+ unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
+ monitor_manager.monitors_changed.connect (expand_to_screen_size);
- unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
- monitor_manager.monitors_changed.connect (expand_to_screen_size);
+ init_dbus_interfaces.begin ();
+ }
- init_dbus_interfaces.begin ();
+ private async void init_dbus_interfaces () {
+ bool success = true;
+
+ try {
+ login_manager = yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1");
+ login_user_manager = yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1/user/self");
+
+ // Listen for sleep/resume events from logind
+ login_manager.prepare_for_sleep.connect (prepare_for_sleep);
+ login_session = get_current_session_manager ();
+ if (login_session != null) {
+ // Listen for lock unlock events from logind
+ login_session.lock.connect (() => @lock (false));
+ login_session.unlock.connect (() => {
+ deactivate (false);
+ in_greeter = false;
+ });
+
+ ((DBusProxy)login_session).g_properties_changed.connect (sync_inhibitor);
+ sync_inhibitor ();
+ }
+ } catch (Error e) {
+ success = false;
+ critical ("Unable to connect to logind bus, screen locking disabled: %s", e.message);
}
- private async void init_dbus_interfaces () {
- bool success = true;
+ try {
+ session_presence = yield Bus.get_proxy (BusType.SESSION, "org.gnome.SessionManager", "/org/gnome/SessionManager/Presence");
+ on_status_changed (session_presence.status);
+ session_presence.status_changed.connect ((status) => on_status_changed (status));
+ } catch (Error e) {
+ success = false;
+ critical ("Unable to connect to session presence bus, screen locking disabled: %s", e.message);
+ }
- try {
- login_manager = yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1");
- login_user_manager = yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1/user/self");
-
- // Listen for sleep/resume events from logind
- login_manager.prepare_for_sleep.connect (prepare_for_sleep);
- login_session = get_current_session_manager ();
- if (login_session != null) {
- // Listen for lock unlock events from logind
- login_session.lock.connect (() => @lock (false));
- login_session.unlock.connect (() => {
- deactivate (false);
- in_greeter = false;
- });
-
- ((DBusProxy)login_session).g_properties_changed.connect (sync_inhibitor);
- sync_inhibitor ();
- }
- } catch (Error e) {
- success = false;
- critical ("Unable to connect to logind bus, screen locking disabled: %s", e.message);
- }
+ string? seat_path = GLib.Environment.get_variable ("XDG_SEAT_PATH");
+ if (seat_path != null) {
try {
- session_presence = yield Bus.get_proxy (BusType.SESSION, "org.gnome.SessionManager", "/org/gnome/SessionManager/Presence");
- on_status_changed (session_presence.status);
- session_presence.status_changed.connect ((status) => on_status_changed (status));
+ display_manager = yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.DisplayManager", seat_path);
} catch (Error e) {
success = false;
- critical ("Unable to connect to session presence bus, screen locking disabled: %s", e.message);
+ critical ("Unable to connect to display manager bus, screen locking disabled");
}
+ } else {
+ success = false;
+ critical ("XDG_SEAT_PATH unset, screen locking disabled");
+ }
+ connected_to_buses = success;
+ }
- string? seat_path = GLib.Environment.get_variable ("XDG_SEAT_PATH");
- if (seat_path != null) {
- try {
- display_manager = yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.DisplayManager", seat_path);
- } catch (Error e) {
- success = false;
- critical ("Unable to connect to display manager bus, screen locking disabled");
- }
- } else {
- success = false;
- critical ("XDG_SEAT_PATH unset, screen locking disabled");
- }
-
- connected_to_buses = success;
- }
+ private void expand_to_screen_size () {
+ int screen_width, screen_height;
+ wm.get_display ().get_size (out screen_width, out screen_height);
+ width = screen_width;
+ height = screen_height;
+ }
- private void expand_to_screen_size () {
- int screen_width, screen_height;
- wm.get_display ().get_size (out screen_width, out screen_height);
- width = screen_width;
- height = screen_height;
+ private void prepare_for_sleep (bool about_to_suspend) {
+ if (!connected_to_buses) {
+ return;
}
- private void prepare_for_sleep (bool about_to_suspend) {
- if (!connected_to_buses) {
- return;
+ if (about_to_suspend) {
+ if (gala_settings.get_boolean (LOCK_ON_SUSPEND_KEY)) {
+ debug ("about to sleep, locking screen");
+ this.@lock (false);
}
+ } else {
+ debug ("resumed from suspend, waking screen");
+ on_user_became_active ();
+ expand_to_screen_size ();
+ }
+ }
- if (about_to_suspend) {
- if (gala_settings.get_boolean (LOCK_ON_SUSPEND_KEY)) {
- debug ("about to sleep, locking screen");
- this.@lock (false);
- }
- } else {
- debug ("resumed from suspend, waking screen");
- on_user_became_active ();
- expand_to_screen_size ();
- }
+ // status becomes idle after interval defined at /org/gnome/desktop/session/idle-delay
+ private void on_status_changed (PresenceStatus status) {
+ if (status != PresenceStatus.IDLE || !connected_to_buses) {
+ return;
}
- // status becomes idle after interval defined at /org/gnome/desktop/session/idle-delay
- private void on_status_changed (PresenceStatus status) {
- if (status != PresenceStatus.IDLE || !connected_to_buses) {
- return;
- }
+ debug ("session became idle, activating screensaver");
- debug ("session became idle, activating screensaver");
+ activate (true);
+ }
- activate (true);
+ // We briefly inhibit sleep so that we can try and lock before sleep occurs if necessary
+ private void sync_inhibitor () {
+ if (!connected_to_buses) {
+ return;
}
- // We briefly inhibit sleep so that we can try and lock before sleep occurs if necessary
- private void sync_inhibitor () {
- if (!connected_to_buses) {
- return;
- }
-
- var lock_enabled = gala_settings.get_boolean (LOCK_ON_SUSPEND_KEY);
- var lock_prohibited = lockdown_settings.get_boolean (LOCK_PROHIBITED_KEY);
-
- var inhibit = login_session != null && login_session.active && !active && lock_enabled && !lock_prohibited;
- if (inhibit) {
- try {
- var new_inhibitor = login_manager.inhibit ("sleep", "Pantheon", "Pantheon needs to lock the screen", "delay");
- if (inhibitor != null) {
- inhibitor.close ();
- inhibitor = null;
- }
+ var lock_enabled = gala_settings.get_boolean (LOCK_ON_SUSPEND_KEY);
+ var lock_prohibited = lockdown_settings.get_boolean (LOCK_PROHIBITED_KEY);
- inhibitor = new_inhibitor;
- } catch (Error e) {
- warning ("Unable to inhibit sleep, may be unable to lock before sleep starts: %s", e.message);
- }
- } else {
+ var inhibit = login_session != null && login_session.active && !active && lock_enabled && !lock_prohibited;
+ if (inhibit) {
+ try {
+ var new_inhibitor = login_manager.inhibit ("sleep", "Pantheon", "Pantheon needs to lock the screen", "delay");
if (inhibitor != null) {
- try {
- inhibitor.close ();
- } catch (Error e) {
- warning ("Unable to remove sleep inhibitor: %s", e.message);
- }
-
+ inhibitor.close ();
inhibitor = null;
}
- }
- }
- private void on_user_became_active () {
- if (!connected_to_buses) {
- return;
+ inhibitor = new_inhibitor;
+ } catch (Error e) {
+ warning ("Unable to inhibit sleep, may be unable to lock before sleep starts: %s", e.message);
}
-
- // User became active in some way, switch to the greeter if we're not there already
- if (is_locked && !in_greeter) {
- debug ("user became active, switching to greeter");
- cancel_animation ();
+ } else {
+ if (inhibitor != null) {
try {
- display_manager.switch_to_greeter ();
- in_greeter = true;
+ inhibitor.close ();
} catch (Error e) {
- critical ("Unable to switch to greeter to unlock: %s", e.message);
+ warning ("Unable to remove sleep inhibitor: %s", e.message);
}
- // Otherwise, we're in screensaver mode, just deactivate
- } else if (!is_locked) {
- debug ("user became active in unlocked session, closing screensaver");
- deactivate (false);
+
+ inhibitor = null;
}
}
+ }
- private LoginSessionManager? get_current_session_manager () throws GLib.Error {
- string? session_id = GLib.Environment.get_variable ("XDG_SESSION_ID");
- if (session_id == null) {
- debug ("Unset XDG_SESSION_ID, asking logind");
- if (login_user_manager == null) {
- return null;
- }
+ private void on_user_became_active () {
+ if (!connected_to_buses) {
+ return;
+ }
- session_id = login_user_manager.display.session;
+ // User became active in some way, switch to the greeter if we're not there already
+ if (is_locked && !in_greeter) {
+ debug ("user became active, switching to greeter");
+ cancel_animation ();
+ try {
+ display_manager.switch_to_greeter ();
+ in_greeter = true;
+ } catch (Error e) {
+ critical ("Unable to switch to greeter to unlock: %s", e.message);
}
+ // Otherwise, we're in screensaver mode, just deactivate
+ } else if (!is_locked) {
+ debug ("user became active in unlocked session, closing screensaver");
+ deactivate (false);
+ }
+ }
- if (session_id == null) {
+ private LoginSessionManager? get_current_session_manager () throws GLib.Error {
+ string? session_id = GLib.Environment.get_variable ("XDG_SESSION_ID");
+ if (session_id == null) {
+ debug ("Unset XDG_SESSION_ID, asking logind");
+ if (login_user_manager == null) {
return null;
}
- var session_path = login_manager.get_session (session_id);
- LoginSessionManager? session = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", session_path);
+ session_id = login_user_manager.display.session;
+ }
- return session;
+ if (session_id == null) {
+ return null;
}
- public void @lock (bool animate) {
- if (is_locked || !connected_to_buses) {
- return;
- }
+ var session_path = login_manager.get_session (session_id);
+ LoginSessionManager? session = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", session_path);
- if (lockdown_settings.get_boolean (LOCK_PROHIBITED_KEY)) {
- debug ("Lock prohibited, ignoring lock request");
- return;
- }
+ return session;
+ }
- is_locked = true;
+ public void @lock (bool animate) {
+ if (is_locked || !connected_to_buses) {
+ return;
+ }
- activate (animate, SHORT_ANIMATION_TIME);
+ if (lockdown_settings.get_boolean (LOCK_PROHIBITED_KEY)) {
+ debug ("Lock prohibited, ignoring lock request");
+ return;
}
- public void activate (bool animate, uint animation_time = LONG_ANIMATION_TIME) {
- if (visible || !connected_to_buses) {
- return;
- }
+ is_locked = true;
- expand_to_screen_size ();
+ activate (animate, SHORT_ANIMATION_TIME);
+ }
- if (activation_time == 0) {
- activation_time = GLib.get_monotonic_time ();
- }
+ public void activate (bool animate, uint animation_time = LONG_ANIMATION_TIME) {
+ if (visible || !connected_to_buses) {
+ return;
+ }
- wm.get_display ().get_cursor_tracker ().set_pointer_visible (false);
- visible = true;
- grab_key_focus ();
- modal_proxy = wm.push_modal (this);
+ expand_to_screen_size ();
- if (AnimationsSettings.get_enable_animations () && animate) {
- animate_and_lock (animation_time);
- } else {
- _set_active (true);
+ if (activation_time == 0) {
+ activation_time = GLib.get_monotonic_time ();
+ }
- opacity = 255;
+ wm.get_display ().get_cursor_tracker ().set_pointer_visible (false);
+ visible = true;
+ grab_key_focus ();
+ modal_proxy = wm.push_modal (this);
- if (screensaver_settings.get_boolean (LOCK_ENABLED_KEY)) {
- @lock (false);
- }
- }
- }
+ if (AnimationsSettings.get_enable_animations () && animate) {
+ animate_and_lock (animation_time);
+ } else {
+ _set_active (true);
- private void animate_and_lock (uint animation_time) {
- opacity = 0;
- save_easing_state ();
- set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
- set_easing_duration (animation_time);
opacity = 255;
- animate_id = Timeout.add (animation_time, () => {
- animate_id = 0;
-
- restore_easing_state ();
+ if (screensaver_settings.get_boolean (LOCK_ENABLED_KEY)) {
+ @lock (false);
+ }
+ }
+ }
- _set_active (true);
+ private void animate_and_lock (uint animation_time) {
+ opacity = 0;
+ save_easing_state ();
+ set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
+ set_easing_duration (animation_time);
+ opacity = 255;
- if (screensaver_settings.get_boolean (LOCK_ENABLED_KEY)) {
- @lock (false);
- }
+ animate_id = Timeout.add (animation_time, () => {
+ animate_id = 0;
- return GLib.Source.REMOVE;
- });
- }
+ restore_easing_state ();
- private void cancel_animation () {
- if (animate_id != 0) {
- GLib.Source.remove (animate_id);
- animate_id = 0;
+ _set_active (true);
- restore_easing_state ();
+ if (screensaver_settings.get_boolean (LOCK_ENABLED_KEY)) {
+ @lock (false);
}
- }
- public void deactivate (bool animate) {
- if (!connected_to_buses) {
- return;
- }
+ return GLib.Source.REMOVE;
+ });
+ }
- cancel_animation ();
+ private void cancel_animation () {
+ if (animate_id != 0) {
+ GLib.Source.remove (animate_id);
+ animate_id = 0;
- is_locked = false;
+ restore_easing_state ();
+ }
+ }
- if (modal_proxy != null) {
- wm.pop_modal (modal_proxy);
- modal_proxy = null;
- }
+ public void deactivate (bool animate) {
+ if (!connected_to_buses) {
+ return;
+ }
- wm.get_display ().get_cursor_tracker ().set_pointer_visible (true);
- visible = false;
+ cancel_animation ();
- activation_time = 0;
- _set_active (false);
+ is_locked = false;
+
+ if (modal_proxy != null) {
+ wm.pop_modal (modal_proxy);
+ modal_proxy = null;
}
- private void _set_active (bool new_active) {
- if (!connected_to_buses) {
- return;
- }
+ wm.get_display ().get_cursor_tracker ().set_pointer_visible (true);
+ visible = false;
- var prev_is_active = active;
- active = new_active;
+ activation_time = 0;
+ _set_active (false);
+ }
- if (prev_is_active != active) {
- active_changed ();
- }
+ private void _set_active (bool new_active) {
+ if (!connected_to_buses) {
+ return;
+ }
- try {
- login_session.set_locked_hint (active);
- } catch (Error e) {
- warning ("Unable to set locked hint on login session: %s", e.message);
- }
+ var prev_is_active = active;
+ active = new_active;
- sync_inhibitor ();
+ if (prev_is_active != active) {
+ active_changed ();
}
+
+ try {
+ login_session.set_locked_hint (active);
+ } catch (Error e) {
+ warning ("Unable to set locked hint on login session: %s", e.message);
+ }
+
+ sync_inhibitor ();
}
}
diff --git a/src/Widgets/SelectionArea.vala b/src/Widgets/SelectionArea.vala
index c3754bd31..161476f60 100644
--- a/src/Widgets/SelectionArea.vala
+++ b/src/Widgets/SelectionArea.vala
@@ -1,176 +1,164 @@
-//
-// Copyright (C) 2017 Santiago León O., Adam Bieńkowski
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- public class SelectionArea : CanvasActor {
- public signal void closed ();
-
- public WindowManager wm { get; construct; }
-
- public bool cancelled { get; private set; }
-
- private ModalProxy? modal_proxy;
- private Graphene.Point start_point;
- private Graphene.Point end_point;
- private bool dragging = false;
- private bool clicked = false;
-
- public SelectionArea (WindowManager wm) {
- Object (wm: wm);
- }
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2017 Santiago León O.
+ * 2017 Adam Bieńkowski
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
- construct {
- start_point.init (0, 0);
- end_point.init (0, 0);
- visible = true;
- reactive = true;
+public class Gala.SelectionArea : CanvasActor {
+ public signal void closed ();
- int screen_width, screen_height;
- wm.get_display ().get_size (out screen_width, out screen_height);
- width = screen_width;
- height = screen_height;
- }
+ public WindowManager wm { get; construct; }
+
+ public bool cancelled { get; private set; }
+
+ private ModalProxy? modal_proxy;
+ private Graphene.Point start_point;
+ private Graphene.Point end_point;
+ private bool dragging = false;
+ private bool clicked = false;
+
+ public SelectionArea (WindowManager wm) {
+ Object (wm: wm);
+ }
+
+ construct {
+ start_point.init (0, 0);
+ end_point.init (0, 0);
+ visible = true;
+ reactive = true;
+
+ int screen_width, screen_height;
+ wm.get_display ().get_size (out screen_width, out screen_height);
+ width = screen_width;
+ height = screen_height;
+ }
#if HAS_MUTTER45
- public override bool key_press_event (Clutter.Event e) {
+ public override bool key_press_event (Clutter.Event e) {
#else
- public override bool key_press_event (Clutter.KeyEvent e) {
+ public override bool key_press_event (Clutter.KeyEvent e) {
#endif
- if (e.get_key_symbol () == Clutter.Key.Escape) {
- close ();
- cancelled = true;
- closed ();
- return true;
- }
-
- return false;
+ if (e.get_key_symbol () == Clutter.Key.Escape) {
+ close ();
+ cancelled = true;
+ closed ();
+ return true;
}
+ return false;
+ }
+
#if HAS_MUTTER45
- public override bool button_press_event (Clutter.Event e) {
+ public override bool button_press_event (Clutter.Event e) {
#else
- public override bool button_press_event (Clutter.ButtonEvent e) {
+ public override bool button_press_event (Clutter.ButtonEvent e) {
#endif
- if (dragging || e.get_button () != Clutter.Button.PRIMARY) {
- return true;
- }
+ if (dragging || e.get_button () != Clutter.Button.PRIMARY) {
+ return true;
+ }
- clicked = true;
+ clicked = true;
- float x, y;
- e.get_coords (out x, out y);
- start_point.init (x, y);
+ float x, y;
+ e.get_coords (out x, out y);
+ start_point.init (x, y);
- return true;
- }
+ return true;
+ }
#if HAS_MUTTER45
- public override bool button_release_event (Clutter.Event e) {
+ public override bool button_release_event (Clutter.Event e) {
#else
- public override bool button_release_event (Clutter.ButtonEvent e) {
+ public override bool button_release_event (Clutter.ButtonEvent e) {
#endif
- if (e.get_button () != Clutter.Button.PRIMARY) {
- return true;
- }
-
- if (!dragging) {
- close ();
- cancelled = true;
- closed ();
- return true;
- }
-
- dragging = false;
- clicked = false;
+ if (e.get_button () != Clutter.Button.PRIMARY) {
+ return true;
+ }
+ if (!dragging) {
close ();
- this.hide ();
- content.invalidate ();
-
+ cancelled = true;
closed ();
return true;
}
-#if HAS_MUTTER45
- public override bool motion_event (Clutter.Event e) {
-#else
- public override bool motion_event (Clutter.MotionEvent e) {
-#endif
- if (!clicked) {
- return true;
- }
+ dragging = false;
+ clicked = false;
- float x, y;
- e.get_coords (out x, out y);
- end_point.init (x, y);
- content.invalidate ();
+ close ();
+ this.hide ();
+ content.invalidate ();
- if (!dragging) {
- dragging = true;
- }
+ closed ();
+ return true;
+ }
+#if HAS_MUTTER45
+ public override bool motion_event (Clutter.Event e) {
+#else
+ public override bool motion_event (Clutter.MotionEvent e) {
+#endif
+ if (!clicked) {
return true;
}
- public void close () {
- wm.get_display ().set_cursor (Meta.Cursor.DEFAULT);
+ float x, y;
+ e.get_coords (out x, out y);
+ end_point.init (x, y);
+ content.invalidate ();
- if (modal_proxy != null) {
- wm.pop_modal (modal_proxy);
- }
+ if (!dragging) {
+ dragging = true;
}
- public void start_selection () {
- wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
- grab_key_focus ();
+ return true;
+ }
- modal_proxy = wm.push_modal (this);
- }
+ public void close () {
+ wm.get_display ().set_cursor (Meta.Cursor.DEFAULT);
- public Graphene.Rect get_selection_rectangle () {
- return Graphene.Rect () {
- origin = start_point,
- size = Graphene.Size.zero ()
- }.expand (end_point);
+ if (modal_proxy != null) {
+ wm.pop_modal (modal_proxy);
}
+ }
- protected override void draw (Cairo.Context ctx, int width, int height) {
- ctx.save ();
+ public void start_selection () {
+ wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
+ grab_key_focus ();
- ctx.set_operator (Cairo.Operator.CLEAR);
- ctx.paint ();
+ modal_proxy = wm.push_modal (this);
+ }
- ctx.restore ();
+ public Graphene.Rect get_selection_rectangle () {
+ return Graphene.Rect () {
+ origin = start_point,
+ size = Graphene.Size.zero ()
+ }.expand (end_point);
+ }
- if (!dragging) {
- return;
- }
+ protected override void draw (Cairo.Context ctx, int width, int height) {
+ ctx.save ();
- ctx.translate (0.5, 0.5);
+ ctx.set_operator (Cairo.Operator.CLEAR);
+ ctx.paint ();
- var rect = get_selection_rectangle ();
- ctx.rectangle (rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
- ctx.set_source_rgba (0.1, 0.1, 0.1, 0.2);
- ctx.fill ();
+ ctx.restore ();
- ctx.rectangle (rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
- ctx.set_source_rgb (0.7, 0.7, 0.7);
- ctx.set_line_width (1.0);
- ctx.stroke ();
+ if (!dragging) {
+ return;
}
+
+ ctx.translate (0.5, 0.5);
+
+ var rect = get_selection_rectangle ();
+ ctx.rectangle (rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+ ctx.set_source_rgba (0.1, 0.1, 0.1, 0.2);
+ ctx.fill ();
+
+ ctx.rectangle (rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+ ctx.set_source_rgb (0.7, 0.7, 0.7);
+ ctx.set_line_width (1.0);
+ ctx.stroke ();
}
}
diff --git a/src/Widgets/WindowCloneContainer.vala b/src/Widgets/WindowCloneContainer.vala
index 4776e492d..6cab571af 100644
--- a/src/Widgets/WindowCloneContainer.vala
+++ b/src/Widgets/WindowCloneContainer.vala
@@ -1,415 +1,402 @@
-//
-// Copyright (C) 2014 Tom Beckmann
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-
-namespace Gala {
- /**
- * Container which controls the layout of a set of WindowClones.
- */
- public class WindowCloneContainer : Clutter.Actor {
- public signal void window_selected (Meta.Window window);
- public signal void requested_close ();
-
- public int padding_top { get; set; default = 12; }
- public int padding_left { get; set; default = 12; }
- public int padding_right { get; set; default = 12; }
- public int padding_bottom { get; set; default = 12; }
-
- public Meta.Display display { get; construct; }
- public GestureTracker gesture_tracker { get; construct; }
- public bool overview_mode { get; construct; }
-
- private float _monitor_scale = 1.0f;
- public float monitor_scale {
- get {
- return _monitor_scale;
- }
- set {
- if (value != _monitor_scale) {
- _monitor_scale = value;
- reallocate ();
- }
+/*
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2014 Tom Beckmann
+ * 2025 elementary, Inc. (https://elementary.io)
+ */
+
+/**
+ * Container which controls the layout of a set of WindowClones.
+ */
+public class Gala.WindowCloneContainer : Clutter.Actor {
+ public signal void window_selected (Meta.Window window);
+ public signal void requested_close ();
+
+ public int padding_top { get; set; default = 12; }
+ public int padding_left { get; set; default = 12; }
+ public int padding_right { get; set; default = 12; }
+ public int padding_bottom { get; set; default = 12; }
+
+ public Meta.Display display { get; construct; }
+ public GestureTracker gesture_tracker { get; construct; }
+ public bool overview_mode { get; construct; }
+
+ private float _monitor_scale = 1.0f;
+ public float monitor_scale {
+ get {
+ return _monitor_scale;
+ }
+ set {
+ if (value != _monitor_scale) {
+ _monitor_scale = value;
+ reallocate ();
}
}
+ }
- private bool opened = false;
+ private bool opened = false;
- /**
- * The window that is currently selected via keyboard shortcuts. It is not
- * necessarily the same as the active window.
- */
- private unowned WindowClone? current_window = null;
+ /**
+ * The window that is currently selected via keyboard shortcuts. It is not
+ * necessarily the same as the active window.
+ */
+ private unowned WindowClone? current_window = null;
+
+ public WindowCloneContainer (Meta.Display display, GestureTracker gesture_tracker, float scale, bool overview_mode = false) {
+ Object (display: display, gesture_tracker: gesture_tracker, monitor_scale: scale, overview_mode: overview_mode);
+ }
- public WindowCloneContainer (Meta.Display display, GestureTracker gesture_tracker, float scale, bool overview_mode = false) {
- Object (display: display, gesture_tracker: gesture_tracker, monitor_scale: scale, overview_mode: overview_mode);
+ private void reallocate () {
+ foreach (unowned var child in get_children ()) {
+ unowned var clone = (WindowClone) child;
+ clone.monitor_scale_factor = monitor_scale;
}
+ }
- private void reallocate () {
- foreach (unowned var child in get_children ()) {
- unowned var clone = (WindowClone) child;
- clone.monitor_scale_factor = monitor_scale;
- }
+ /**
+ * Create a WindowClone for a MetaWindow and add it to the group
+ *
+ * @param window The window for which to create the WindowClone for
+ */
+ public void add_window (Meta.Window window) {
+ var windows = new List ();
+ foreach (unowned var child in get_children ()) {
+ unowned var clone = (WindowClone) child;
+ windows.append (clone.window);
}
+ windows.append (window);
- /**
- * Create a WindowClone for a MetaWindow and add it to the group
- *
- * @param window The window for which to create the WindowClone for
- */
- public void add_window (Meta.Window window) {
- var windows = new List ();
- foreach (unowned var child in get_children ()) {
- unowned var clone = (WindowClone) child;
- windows.append (clone.window);
- }
- windows.append (window);
+ var windows_ordered = InternalUtils.sort_windows (display, windows);
- var windows_ordered = InternalUtils.sort_windows (display, windows);
+ var new_window = new WindowClone (display, window, gesture_tracker, monitor_scale, overview_mode);
- var new_window = new WindowClone (display, window, gesture_tracker, monitor_scale, overview_mode);
+ new_window.selected.connect ((clone) => window_selected (clone.window));
+ new_window.destroy.connect ((_new_window) => {
+ // make sure to release reference if the window is selected
+ if (_new_window == current_window) {
+ select_next_window (Meta.MotionDirection.RIGHT);
+ }
- new_window.selected.connect ((clone) => window_selected (clone.window));
- new_window.destroy.connect ((_new_window) => {
- // make sure to release reference if the window is selected
- if (_new_window == current_window) {
- select_next_window (Meta.MotionDirection.RIGHT);
- }
+ // if window is still selected, reset the selection
+ if (_new_window == current_window) {
+ current_window = null;
+ }
- // if window is still selected, reset the selection
- if (_new_window == current_window) {
- current_window = null;
- }
+ reflow ();
+ });
+ new_window.request_reposition.connect (() => reflow ());
+
+ unowned Meta.Window? target = null;
+ foreach (unowned var w in windows_ordered) {
+ if (w != window) {
+ target = w;
+ continue;
+ }
+ break;
+ }
- reflow ();
- });
- new_window.request_reposition.connect (() => reflow ());
+ // top most or no other children
+ if (target == null) {
+ add_child (new_window);
+ }
- unowned Meta.Window? target = null;
- foreach (unowned var w in windows_ordered) {
- if (w != window) {
- target = w;
- continue;
- }
+ foreach (unowned var child in get_children ()) {
+ unowned var clone = (WindowClone) child;
+ if (target == clone.window) {
+ insert_child_below (new_window, clone);
break;
}
+ }
- // top most or no other children
- if (target == null) {
- add_child (new_window);
- }
+ reflow ();
+ }
- foreach (unowned var child in get_children ()) {
- unowned var clone = (WindowClone) child;
- if (target == clone.window) {
- insert_child_below (new_window, clone);
- break;
- }
+ /**
+ * Find and remove the WindowClone for a MetaWindow
+ */
+ public void remove_window (Meta.Window window) {
+ foreach (unowned var child in get_children ()) {
+ if (((WindowClone) child).window == window) {
+ remove_child (child);
+ reflow ();
+ break;
}
+ }
+ }
- reflow ();
+ /**
+ * Sort the windows z-order by their actual stacking to make intersections
+ * during animations correct.
+ */
+ public void restack_windows () {
+ var children = get_children ();
+
+ var windows = new List ();
+ foreach (unowned Clutter.Actor child in children) {
+ windows.prepend (((WindowClone) child).window);
}
- /**
- * Find and remove the WindowClone for a MetaWindow
- */
- public void remove_window (Meta.Window window) {
- foreach (unowned var child in get_children ()) {
+ var windows_ordered = InternalUtils.sort_windows (display, windows);
+ windows_ordered.reverse ();
+
+ var i = 0;
+ foreach (unowned var window in windows_ordered) {
+ foreach (unowned var child in children) {
if (((WindowClone) child).window == window) {
- remove_child (child);
- reflow ();
+ set_child_at_index (child, i);
+ children.remove (child);
+ i++;
break;
}
}
}
+ }
- /**
- * Sort the windows z-order by their actual stacking to make intersections
- * during animations correct.
- */
- public void restack_windows () {
- var children = get_children ();
-
- var windows = new List ();
- foreach (unowned Clutter.Actor child in children) {
- windows.prepend (((WindowClone) child).window);
- }
-
- var windows_ordered = InternalUtils.sort_windows (display, windows);
- windows_ordered.reverse ();
-
- var i = 0;
- foreach (unowned var window in windows_ordered) {
- foreach (unowned var child in children) {
- if (((WindowClone) child).window == window) {
- set_child_at_index (child, i);
- children.remove (child);
- i++;
- break;
- }
- }
- }
+ /**
+ * Recalculate the tiling positions of the windows and animate them to
+ * the resulting spots.
+ */
+ public void reflow (bool with_gesture = false, bool is_cancel_animation = false, bool opening = false) {
+ if (!opened) {
+ return;
}
- /**
- * Recalculate the tiling positions of the windows and animate them to
- * the resulting spots.
- */
- public void reflow (bool with_gesture = false, bool is_cancel_animation = false, bool opening = false) {
- if (!opened) {
- return;
- }
-
- var windows = new List ();
- foreach (unowned var child in get_children ()) {
- unowned var clone = (WindowClone) child;
- windows.prepend ({ clone.window.get_frame_rect (), clone });
- }
+ var windows = new List ();
+ foreach (unowned var child in get_children ()) {
+ unowned var clone = (WindowClone) child;
+ windows.prepend ({ clone.window.get_frame_rect (), clone });
+ }
- if (windows.is_empty ()) {
- return;
- }
+ if (windows.is_empty ()) {
+ return;
+ }
- // make sure the windows are always in the same order so the algorithm
- // doesn't give us different slots based on stacking order, which can lead
- // to windows flying around weirdly
- windows.sort ((a, b) => {
- var seq_a = ((WindowClone) a.id).window.get_stable_sequence ();
- var seq_b = ((WindowClone) b.id).window.get_stable_sequence ();
- return (int) (seq_b - seq_a);
- });
+ // make sure the windows are always in the same order so the algorithm
+ // doesn't give us different slots based on stacking order, which can lead
+ // to windows flying around weirdly
+ windows.sort ((a, b) => {
+ var seq_a = ((WindowClone) a.id).window.get_stable_sequence ();
+ var seq_b = ((WindowClone) b.id).window.get_stable_sequence ();
+ return (int) (seq_b - seq_a);
+ });
#if HAS_MUTTER45
- Mtk.Rectangle area = {
+ Mtk.Rectangle area = {
#else
- Meta.Rectangle area = {
+ Meta.Rectangle area = {
#endif
- padding_left,
- padding_top,
- (int)width - padding_left - padding_right,
- (int)height - padding_top - padding_bottom
- };
+ padding_left,
+ padding_top,
+ (int)width - padding_left - padding_right,
+ (int)height - padding_top - padding_bottom
+ };
- var window_positions = InternalUtils.calculate_grid_placement (area, windows);
+ var window_positions = InternalUtils.calculate_grid_placement (area, windows);
- foreach (var tilable in window_positions) {
- unowned var clone = (WindowClone) tilable.id;
- clone.take_slot (tilable.rect, opening && !is_cancel_animation, with_gesture);
- }
+ foreach (var tilable in window_positions) {
+ unowned var clone = (WindowClone) tilable.id;
+ clone.take_slot (tilable.rect, opening && !is_cancel_animation, with_gesture);
}
+ }
- /**
- * Collect key events, mainly for redirecting them to the WindowCloneContainers to
- * select the active window.
- */
+ /**
+ * Collect key events, mainly for redirecting them to the WindowCloneContainers to
+ * select the active window.
+ */
#if HAS_MUTTER45
- public override bool key_press_event (Clutter.Event event) {
+ public override bool key_press_event (Clutter.Event event) {
#else
- public override bool key_press_event (Clutter.KeyEvent event) {
+ public override bool key_press_event (Clutter.KeyEvent event) {
#endif
- if (!opened) {
- return Clutter.EVENT_PROPAGATE;
- }
+ if (!opened) {
+ return Clutter.EVENT_PROPAGATE;
+ }
- switch (event.get_key_symbol ()) {
- case Clutter.Key.Escape:
+ switch (event.get_key_symbol ()) {
+ case Clutter.Key.Escape:
+ requested_close ();
+ break;
+ case Clutter.Key.Down:
+ select_next_window (Meta.MotionDirection.DOWN);
+ break;
+ case Clutter.Key.Up:
+ select_next_window (Meta.MotionDirection.UP);
+ break;
+ case Clutter.Key.Left:
+ select_next_window (Meta.MotionDirection.LEFT);
+ break;
+ case Clutter.Key.Right:
+ select_next_window (Meta.MotionDirection.RIGHT);
+ break;
+ case Clutter.Key.Return:
+ case Clutter.Key.KP_Enter:
+ if (!activate_selected_window ()) {
requested_close ();
- break;
- case Clutter.Key.Down:
- select_next_window (Meta.MotionDirection.DOWN);
- break;
- case Clutter.Key.Up:
- select_next_window (Meta.MotionDirection.UP);
- break;
- case Clutter.Key.Left:
- select_next_window (Meta.MotionDirection.LEFT);
- break;
- case Clutter.Key.Right:
- select_next_window (Meta.MotionDirection.RIGHT);
- break;
- case Clutter.Key.Return:
- case Clutter.Key.KP_Enter:
- if (!activate_selected_window ()) {
- requested_close ();
- }
- break;
- }
+ }
+ break;
+ }
- return Clutter.EVENT_STOP;
+ return Clutter.EVENT_STOP;
+ }
+
+ /**
+ * Look for the next window in a direction and make this window the
+ * new current_window. Used for keyboard navigation.
+ *
+ * @param direction The MetaMotionDirection in which to search for windows for.
+ */
+ public void select_next_window (Meta.MotionDirection direction) {
+ if (get_n_children () < 1) {
+ return;
}
- /**
- * Look for the next window in a direction and make this window the
- * new current_window. Used for keyboard navigation.
- *
- * @param direction The MetaMotionDirection in which to search for windows for.
- */
- public void select_next_window (Meta.MotionDirection direction) {
- if (get_n_children () < 1) {
- return;
- }
+ WindowClone? closest = null;
- WindowClone? closest = null;
+ if (current_window == null) {
+ closest = (WindowClone) get_child_at_index (0);
+ } else {
+ var current_rect = current_window.slot;
- if (current_window == null) {
- closest = (WindowClone) get_child_at_index (0);
- } else {
- var current_rect = current_window.slot;
+ foreach (unowned var child in get_children ()) {
+ if (child == current_window) {
+ continue;
+ }
- foreach (unowned var child in get_children ()) {
- if (child == current_window) {
- continue;
- }
+ var window_rect = ((WindowClone) child).slot;
- var window_rect = ((WindowClone) child).slot;
+ if (window_rect == null) {
+ continue;
+ }
- if (window_rect == null) {
+ if (direction == LEFT) {
+ if (window_rect.x > current_rect.x) {
continue;
}
- if (direction == LEFT) {
- if (window_rect.x > current_rect.x) {
- continue;
- }
-
- // test for vertical intersection
- if (window_rect.y + window_rect.height > current_rect.y
- && window_rect.y < current_rect.y + current_rect.height) {
+ // test for vertical intersection
+ if (window_rect.y + window_rect.height > current_rect.y
+ && window_rect.y < current_rect.y + current_rect.height) {
- if (closest == null || closest.slot.x < window_rect.x) {
- closest = (WindowClone) child;
- }
- }
- } else if (direction == RIGHT) {
- if (window_rect.x < current_rect.x) {
- continue;
+ if (closest == null || closest.slot.x < window_rect.x) {
+ closest = (WindowClone) child;
}
+ }
+ } else if (direction == RIGHT) {
+ if (window_rect.x < current_rect.x) {
+ continue;
+ }
- // test for vertical intersection
- if (window_rect.y + window_rect.height > current_rect.y
- && window_rect.y < current_rect.y + current_rect.height) {
+ // test for vertical intersection
+ if (window_rect.y + window_rect.height > current_rect.y
+ && window_rect.y < current_rect.y + current_rect.height) {
- if (closest == null || closest.slot.x > window_rect.x) {
- closest = (WindowClone) child;
- }
- }
- } else if (direction == UP) {
- if (window_rect.y > current_rect.y) {
- continue;
+ if (closest == null || closest.slot.x > window_rect.x) {
+ closest = (WindowClone) child;
}
+ }
+ } else if (direction == UP) {
+ if (window_rect.y > current_rect.y) {
+ continue;
+ }
- // test for horizontal intersection
- if (window_rect.x + window_rect.width > current_rect.x
- && window_rect.x < current_rect.x + current_rect.width) {
+ // test for horizontal intersection
+ if (window_rect.x + window_rect.width > current_rect.x
+ && window_rect.x < current_rect.x + current_rect.width) {
- if (closest == null || closest.slot.y < window_rect.y) {
- closest = (WindowClone) child;
- }
- }
- } else if (direction == DOWN) {
- if (window_rect.y < current_rect.y) {
- continue;
+ if (closest == null || closest.slot.y < window_rect.y) {
+ closest = (WindowClone) child;
}
+ }
+ } else if (direction == DOWN) {
+ if (window_rect.y < current_rect.y) {
+ continue;
+ }
- // test for horizontal intersection
- if (window_rect.x + window_rect.width > current_rect.x
- && window_rect.x < current_rect.x + current_rect.width) {
+ // test for horizontal intersection
+ if (window_rect.x + window_rect.width > current_rect.x
+ && window_rect.x < current_rect.x + current_rect.width) {
- if (closest == null || closest.slot.y > window_rect.y) {
- closest = (WindowClone) child;
- }
+ if (closest == null || closest.slot.y > window_rect.y) {
+ closest = (WindowClone) child;
}
- } else {
- warning ("Invalid direction");
- break;
}
+ } else {
+ warning ("Invalid direction");
+ break;
}
}
+ }
- if (closest == null) {
- if (current_window != null) {
- InternalUtils.bell_notify (display);
- current_window.active = true;
- }
- return;
- }
-
+ if (closest == null) {
if (current_window != null) {
- current_window.active = false;
+ InternalUtils.bell_notify (display);
+ current_window.active = true;
}
+ return;
+ }
- closest.active = true;
- current_window = closest;
+ if (current_window != null) {
+ current_window.active = false;
}
- /**
- * Emit the selected signal for the current_window.
- */
- public bool activate_selected_window () {
- if (current_window != null) {
- window_selected (current_window.window);
- return true;
- }
+ closest.active = true;
+ current_window = closest;
+ }
- return false;
+ /**
+ * Emit the selected signal for the current_window.
+ */
+ public bool activate_selected_window () {
+ if (current_window != null) {
+ window_selected (current_window.window);
+ return true;
}
- /**
- * When opened the WindowClones are animated to a tiled layout
- */
- public void open (Meta.Window? selected_window, bool with_gesture, bool is_cancel_animation) {
- if (opened) {
- return;
- }
+ return false;
+ }
- opened = true;
+ /**
+ * When opened the WindowClones are animated to a tiled layout
+ */
+ public void open (Meta.Window? selected_window, bool with_gesture, bool is_cancel_animation) {
+ if (opened) {
+ return;
+ }
- // hide the highlight when opened
- if (selected_window != null) {
- foreach (var child in get_children ()) {
- unowned var clone = (WindowClone) child;
- if (clone.window == selected_window) {
- current_window = clone;
- break;
- }
- }
+ opened = true;
- if (current_window != null) {
- current_window.active = false;
+ // hide the highlight when opened
+ if (selected_window != null) {
+ foreach (var child in get_children ()) {
+ unowned var clone = (WindowClone) child;
+ if (clone.window == selected_window) {
+ current_window = clone;
+ break;
}
- } else {
- current_window = null;
}
- reflow (with_gesture, is_cancel_animation, true);
+ if (current_window != null) {
+ current_window.active = false;
+ }
+ } else {
+ current_window = null;
}
- /**
- * Calls the transition_to_original_state() function on each child
- * to make them take their original locations again.
- */
- public void close (bool with_gesture = false) {
- if (!opened) {
- return;
- }
+ reflow (with_gesture, is_cancel_animation, true);
+ }
- opened = false;
+ /**
+ * Calls the transition_to_original_state() function on each child
+ * to make them take their original locations again.
+ */
+ public void close (bool with_gesture = false) {
+ if (!opened) {
+ return;
+ }
- foreach (var window in get_children ()) {
- ((WindowClone) window).transition_to_original_state (with_gesture);
- }
+ opened = false;
+
+ foreach (var window in get_children ()) {
+ ((WindowClone) window).transition_to_original_state (with_gesture);
}
}
}