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); } } }