From 2d8f49a03680d5ed750888c88d9d12d1141afb6d Mon Sep 17 00:00:00 2001 From: lenemter Date: Sat, 3 Feb 2024 20:49:42 +0900 Subject: [PATCH 01/11] Add blurred background --- compositor/Background/Animation.vala | 74 +++++ compositor/Background/Background.vala | 251 +++++++++++++++ compositor/Background/BackgroundCache.vala | 101 ++++++ .../Background/BackgroundContainer.vala | 62 ++++ compositor/Background/BackgroundManager.vala | 152 +++++++++ compositor/Background/BackgroundSource.vala | 147 +++++++++ compositor/Background/BlurEffect.vala | 292 ++++++++++++++++++ compositor/Background/SystemBackground.vala | 36 +++ compositor/SystemBackground.vala | 54 ---- compositor/WindowManager.vala | 19 +- .../BackgroundUtils.vala | 0 .../DBusWingpanelManager.vala} | 10 +- .../WingpanelManager.vala} | 4 +- compositor/meson.build | 17 +- meson.build | 6 +- src/Cards/UserCard.vala | 12 +- src/meson.build | 1 + 17 files changed, 1165 insertions(+), 73 deletions(-) create mode 100644 compositor/Background/Animation.vala create mode 100644 compositor/Background/Background.vala create mode 100644 compositor/Background/BackgroundCache.vala create mode 100644 compositor/Background/BackgroundContainer.vala create mode 100644 compositor/Background/BackgroundManager.vala create mode 100644 compositor/Background/BackgroundSource.vala create mode 100644 compositor/Background/BlurEffect.vala create mode 100644 compositor/Background/SystemBackground.vala delete mode 100644 compositor/SystemBackground.vala rename compositor/{ => WingpanelManager}/BackgroundUtils.vala (100%) rename compositor/{DBusBackgroundManager.vala => WingpanelManager/DBusWingpanelManager.vala} (87%) rename compositor/{BackgroundManager.vala => WingpanelManager/WingpanelManager.vala} (98%) diff --git a/compositor/Background/Animation.vala b/compositor/Background/Animation.vala new file mode 100644 index 000000000..45df5b0c4 --- /dev/null +++ b/compositor/Background/Animation.vala @@ -0,0 +1,74 @@ +// +// 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 GreeterCompositor { + public class Animation : Object { + public string filename { get; construct; } + public string[] key_frame_files { get; private set; default = {}; } + public double transition_progress { get; private set; default = 0.0; } + public double transition_duration { get; private set; default = 0.0; } + public bool loaded { get; private set; default = false; } + + private Gnome.BGSlideShow? show = null; + + public Animation (string filename) { + Object (filename: filename); + } + + public async void load () { + show = new Gnome.BGSlideShow (filename); + + show.load_async (null, (obj, res) => { + loaded = true; + + load.callback (); + }); + + yield; + } + +#if HAS_MUTTER45 + public void update (Mtk.Rectangle monitor) { +#else + public void update (Meta.Rectangle monitor) { +#endif + string[] key_frame_files = {}; + + if (show == null) + return; + + if (show.get_num_slides () < 1) + return; + + double progress, duration; + bool is_fixed; + string file1, file2; + show.get_current_slide (monitor.width, monitor.height, out progress, out duration, out is_fixed, out file1, out file2); + + transition_duration = duration; + transition_progress = progress; + + if (file1 != null) + key_frame_files += file1; + + if (file2 != null) + key_frame_files += file2; + + this.key_frame_files = key_frame_files; + } + } +} diff --git a/compositor/Background/Background.vala b/compositor/Background/Background.vala new file mode 100644 index 000000000..ee9740fd0 --- /dev/null +++ b/compositor/Background/Background.vala @@ -0,0 +1,251 @@ +// +// 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 GreeterCompositor { + 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; + + 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); + + file_watches = new Gee.HashMap (); + cancellable = new Cancellable (); + + background_source.changed.connect (settings_changed); + + load (); + } + + public void destroy () { + cancellable.cancel (); + remove_animation_timeout (); + + var cache = BackgroundCache.get_default (); + + foreach (var watch in file_watches.values) { + cache.disconnect (watch); + } + + background_source.changed.disconnect (settings_changed); + } + + public void update_resolution () { + if (animation != null) { + remove_animation_timeout (); + update_animation (); + } + } + + private void set_loaded () { + if (is_loaded) + return; + + is_loaded = true; + + Idle.add (() => { + loaded (); + return Source.REMOVE; + }); + } + + private void load_pattern () { + string color_string; + var settings = background_source.gnome_background_settings; + + color_string = settings.get_string ("primary-color"); + var color = Clutter.Color.from_string (color_string); + + 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"); + var second_color = Clutter.Color.from_string (color_string); + background.set_gradient ((GDesktop.BackgroundShading) shading_type, color, second_color); + } + } + + private void watch_file (string filename) { + if (file_watches.has_key (filename)) + return; + + var cache = BackgroundCache.get_default (); + + 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; + } + } + + 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); + + queue_update_animation (); + } + + private void update_animation () { + update_animation_timeout_id = 0; + + 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 image = cache.load (File.new_for_path (files[i])); + + 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); + } + }); + } + } + } + + private void queue_update_animation () { + if (update_animation_timeout_id != 0) + return; + + if (cancellable == null || cancellable.is_cancelled ()) + return; + + if (animation.transition_duration == 0) + return; + + var n_steps = 255.0 / ANIMATION_OPACITY_STEP_INCREMENT; + var time_per_step = (animation.transition_duration * 1000) / n_steps; + + var interval = (uint32) Math.fmax (ANIMATION_MIN_WAKEUP_INTERVAL * 1000, time_per_step); + + if (interval > uint32.MAX) + return; + + update_animation_timeout_id = Timeout.add (interval, () => { + update_animation_timeout_id = 0; + update_animation (); + return Source.REMOVE; + }); + } + + private async void load_animation (string filename) { + animation = yield BackgroundCache.get_default ().get_animation (filename); + + if (animation == null || cancellable.is_cancelled ()) { + set_loaded (); + return; + } + + 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 ()) + set_loaded (); + else { + ulong handler = 0; + handler = image.loaded.connect (() => { + set_loaded (); + 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 () { + load_pattern (); + + if (filename == null) + set_loaded (); + else + load_file (filename); + } + + private void settings_changed () { + changed (); + } + } +} diff --git a/compositor/Background/BackgroundCache.vala b/compositor/Background/BackgroundCache.vala new file mode 100644 index 000000000..93134a440 --- /dev/null +++ b/compositor/Background/BackgroundCache.vala @@ -0,0 +1,101 @@ +// +// 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 GreeterCompositor { + public class BackgroundCache : Object { + private static BackgroundCache? instance = null; + + public static unowned BackgroundCache get_default () { + if (instance == null) + instance = new BackgroundCache (); + + return instance; + } + + public signal void file_changed (string filename); + + private Gee.HashMap file_monitors; + private BackgroundSource background_source; + + private Animation animation; + + public BackgroundCache () { + Object (); + } + + construct { + file_monitors = new Gee.HashMap (); + } + + 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); + } + } + + public async Animation get_animation (string filename) { + if (animation != null && animation.filename == filename) { + Idle.add (() => { + get_animation.callback (); + return Source.REMOVE; + }); + yield; + + return animation; + } + + var animation = new Animation (filename); + + 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 (); + } + } + } +} diff --git a/compositor/Background/BackgroundContainer.vala b/compositor/Background/BackgroundContainer.vala new file mode 100644 index 000000000..46691eecf --- /dev/null +++ b/compositor/Background/BackgroundContainer.vala @@ -0,0 +1,62 @@ +// +// 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 . +// + +namespace GreeterCompositor { + public class BackgroundContainer : Meta.BackgroundGroup { + public signal void changed (); + public WindowManager wm { get; construct; } + + public BackgroundContainer (WindowManager wm) { + Object (wm: wm); + } + + construct { + unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); + monitor_manager.monitors_changed.connect (update); + + update (); + } + + ~BackgroundContainer () { + unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); + monitor_manager.monitors_changed.disconnect (update); + } + + 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 (); + + for (var i = 0; i < wm.get_display ().get_n_monitors (); i++) { + var background = new BackgroundManager (wm, i); + background.add_effect (new BlurEffect (background, 18)); + + add_child (background); + + if (i == 0) { + background.changed.connect (background_changed); + } + } + } + + private void background_changed () { + changed (); + } + } +} diff --git a/compositor/Background/BackgroundManager.vala b/compositor/Background/BackgroundManager.vala new file mode 100644 index 000000000..efbcd9c61 --- /dev/null +++ b/compositor/Background/BackgroundManager.vala @@ -0,0 +1,152 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2023 elementary, Inc. (https://elementary.io) + * 2014 Tom Beckmann + */ + +public class GreeterCompositor.BackgroundManager : Meta.BackgroundGroup { + private const double DIM_OPACITY = 0.55; + private const int FADE_ANIMATION_TIME = 1000; + + public signal void changed (); + + public WindowManager wm { get; construct; } + public int monitor_index { get; construct; } + public bool control_position { get; construct; } + + private BackgroundSource background_source; + private Meta.BackgroundActor background_actor; + private Meta.BackgroundActor? new_background_actor = null; + + public BackgroundManager (WindowManager wm, int monitor_index, bool control_position = true) { + Object (wm: wm, monitor_index: monitor_index, control_position: control_position); + } + + construct { + background_source = BackgroundCache.get_default ().get_background_source (wm.get_display ()); + background_actor = create_background_actor (); + + destroy.connect (on_destroy); + } + + private void on_destroy () { + BackgroundCache.get_default ().release_background_source (); + background_source = null; + + if (new_background_actor != null) { + new_background_actor.destroy (); + new_background_actor = null; + } + + if (background_actor != null) { + background_actor.destroy (); + background_actor = null; + } + } + + private void swap_background_actor (bool animate) { + return_if_fail (new_background_actor != null); + + var old_background_actor = background_actor; + background_actor = new_background_actor; + new_background_actor = null; + + if (old_background_actor == null) { + return; + } + + if (animate) { + var transition = new Clutter.PropertyTransition ("opacity"); + transition.set_from_value (255); + transition.set_to_value (0); + transition.duration = FADE_ANIMATION_TIME; + transition.progress_mode = Clutter.AnimationMode.EASE_OUT_QUAD; + transition.remove_on_complete = true; + transition.completed.connect (() => { + old_background_actor.destroy (); + + changed (); + }); + + old_background_actor.add_transition ("fade-out", transition); + } else { + old_background_actor.destroy (); + changed (); + } + } + + private void update_background_actor (bool animate = true) { + if (new_background_actor != null) { + // Skip displaying existing background queued for load + new_background_actor.destroy (); + new_background_actor = null; + } + + new_background_actor = create_background_actor (); + var new_content = (Meta.BackgroundContent)new_background_actor.content; + new_background_actor.visible = background_actor.visible; + + var background = new_content.background.get_data ("delegate"); + + if (background.is_loaded) { + swap_background_actor (animate); + return; + } + + ulong handler = 0; + handler = background.loaded.connect (() => { + background.disconnect (handler); + background.set_data ("background-loaded-handler", 0); + + swap_background_actor (animate); + }); + background.set_data ("background-loaded-handler", handler); + } + + public new void set_size (float width, float height) { + if (width != background_actor.width || height != background_actor.height) { + update_background_actor (false); + } + } + + private Meta.BackgroundActor create_background_actor () { + unowned var display = wm.get_display (); + + var background = background_source.get_background (monitor_index); + var background_actor = new Meta.BackgroundActor (display, monitor_index); + + unowned var content = (Meta.BackgroundContent) background_actor.content; + content.background = background.background; + + insert_child_below (background_actor, null); + + var monitor = display.get_monitor_geometry (monitor_index); + background_actor.set_size (monitor.width, monitor.height); + + if (control_position) { + background_actor.set_position (monitor.x, monitor.y); + } + + ulong changed_handler = 0; + changed_handler = background.changed.connect (() => { + background.disconnect (changed_handler); + changed_handler = 0; + update_background_actor (); + }); + + background_actor.destroy.connect (() => { + if (changed_handler != 0) { + background.disconnect (changed_handler); + changed_handler = 0; + } + + var loaded_handler = background.get_data ("background-loaded-handler"); + if (loaded_handler != 0) { + background.disconnect (loaded_handler); + background.set_data ("background-loaded-handler", 0); + } + }); + + return background_actor; + } +} diff --git a/compositor/Background/BackgroundSource.vala b/compositor/Background/BackgroundSource.vala new file mode 100644 index 000000000..84c00ebfe --- /dev/null +++ b/compositor/Background/BackgroundSource.vala @@ -0,0 +1,147 @@ +// +// 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 GreeterCompositor { + 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 BackgroundSource (Meta.Display display) { + Object (display: display); + } + + construct { + backgrounds = new GLib.HashTable (GLib.direct_hash, GLib.direct_equal); + hash_cache = new uint[OPTIONS.length]; + + monitor_manager = display.get_context ().get_backend ().get_monitor_manager (); + monitor_manager.monitors_changed.connect (monitors_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"); + + // 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.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; + } + } + } + }); + } + + 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; + } + }); + } + + public Background get_background (int monitor_index) { + string? filename = null; + + var style = gnome_background_settings.get_enum ("picture-options"); + if (style != GDesktop.BackgroundStyle.NONE) { + filename = get_background_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; + } + + private string get_background_path () { + 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; + } + + return uri; + } + + private void background_changed (Background background) { + background.changed.disconnect (background_changed); + background.destroy (); + backgrounds.remove (background.monitor_index); + } + + 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/compositor/Background/BlurEffect.vala b/compositor/Background/BlurEffect.vala new file mode 100644 index 000000000..6f254ba95 --- /dev/null +++ b/compositor/Background/BlurEffect.vala @@ -0,0 +1,292 @@ +/* + * Copyright 2023 elementary, Inc. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +public class GreeterCompositor.BlurEffect : Clutter.Effect { + private const float MIN_DOWNSCALE_SIZE = 256.0f; + private const float MAX_RADIUS = 12.0f; + + public new Clutter.Actor actor { get; construct; } + public float radius { get; construct; } + + private bool actor_painted = false; + private bool blur_applied = false; + private int texture_width; + private int texture_height; + private float downscale_factor; + + private Cogl.Framebuffer actor_framebuffer; + private Cogl.Pipeline actor_pipeline; + private Cogl.Texture actor_texture; + + private Cogl.Framebuffer framebuffer; + private Cogl.Pipeline pipeline; + private Cogl.Texture texture; + + public BlurEffect (Clutter.Actor actor, float radius) { + Object (actor: actor, radius: radius); + } + + construct { + unowned var ctx = Clutter.get_default_backend ().get_cogl_context (); + + actor_pipeline = new Cogl.Pipeline (ctx); + actor_pipeline.set_layer_null_texture (0); + actor_pipeline.set_layer_filters (0, Cogl.PipelineFilter.LINEAR, Cogl.PipelineFilter.LINEAR); + actor_pipeline.set_layer_wrap_mode (0, Cogl.PipelineWrapMode.CLAMP_TO_EDGE); + + pipeline = new Cogl.Pipeline (ctx); + pipeline.set_layer_null_texture (0); + pipeline.set_layer_filters (0, Cogl.PipelineFilter.LINEAR, Cogl.PipelineFilter.LINEAR); + pipeline.set_layer_wrap_mode (0, Cogl.PipelineWrapMode.CLAMP_TO_EDGE); + } + + private bool needs_repaint (Clutter.EffectPaintFlags flags) { + var actor_dirty = (flags & Clutter.EffectPaintFlags.ACTOR_DIRTY) != 0; + + return actor_dirty || !blur_applied || !actor_painted; + } + + private Clutter.ActorBox update_actor_box (Clutter.PaintContext paint_context) { + var actor_allocation_box = actor.get_allocation_box (); + Clutter.ActorBox.clamp_to_pixel (ref actor_allocation_box); + + return actor_allocation_box; + } + + private float calculate_downscale_factor (float width, float height, float radius) { + float downscale_factor = 1.0f; + float scaled_width = width; + float scaled_height = height; + float scaled_radius = radius; + + /* This is the algorithm used by Firefox; keep downscaling until either the + * blur radius is lower than the threshold, or the downscaled texture is too + * small. + */ + while ( + scaled_radius > MAX_RADIUS && + scaled_width > MIN_DOWNSCALE_SIZE && + scaled_height > MIN_DOWNSCALE_SIZE + ) { + downscale_factor *= 2.0f; + + scaled_width = width / downscale_factor; + scaled_height = height / downscale_factor; + scaled_radius = radius / downscale_factor; + } + + return downscale_factor; + } + + private void setup_projection_matrix (Cogl.Framebuffer framebuffer, float width, float height) { + Graphene.Matrix projection = {}; + projection.init_translate ({ -width / 2.0f, -height / 2.0f, 0.0f }); + projection.scale (2.0f / width, -2.0f / height, 1.0f); + + framebuffer.set_projection_matrix (projection); + } + + private bool update_general_fbo (int width, int height, float downscale_factor) { + if ( + texture_width == width && + texture_height == height && + this.downscale_factor == downscale_factor && + framebuffer != null + ) { + return true; + } + + unowned var ctx = Clutter.get_default_backend ().get_cogl_context (); + + framebuffer = null; + texture = null; + + var new_width = (int) Math.floorf (width / downscale_factor); + var new_height = (int) Math.floorf (height / downscale_factor); + + var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, new_width, new_height); + + try { + texture = new Cogl.Texture2D.from_data (ctx, new_width, new_height, Cogl.PixelFormat.BGRA_8888_PRE, surface.get_stride (), surface.get_data ()); + } catch (GLib.Error e) { + warning (e.message); + return false; + } + + pipeline.set_layer_texture (0, texture); + + framebuffer = new Cogl.Offscreen.with_texture (texture); + + setup_projection_matrix (framebuffer, new_width, new_height); + + return true; + } + + private bool update_actor_fbo (int width, int height, float downscale_factor) { + if ( + texture_width == width && + texture_height == height && + this.downscale_factor == downscale_factor && + actor_framebuffer != null + ) { + return true; + } + + actor_painted = false; + + unowned var ctx = Clutter.get_default_backend ().get_cogl_context (); + + actor_framebuffer = null; + actor_texture = null; + + var new_width = (int) Math.floorf (width / downscale_factor); + var new_height = (int) Math.floorf (height / downscale_factor); + + var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, new_width, new_height); + + try { + actor_texture = new Cogl.Texture2D.from_data (ctx, new_width, new_height, Cogl.PixelFormat.BGRA_8888_PRE, surface.get_stride (), surface.get_data ()); + } catch (GLib.Error e) { + warning (e.message); + return false; + } + + actor_pipeline.set_layer_texture (0, actor_texture); + + actor_framebuffer = (Cogl.Framebuffer) new Cogl.Offscreen.with_texture (actor_texture); + + setup_projection_matrix (actor_framebuffer, new_width, new_height); + + return true; + } + + private bool update_framebuffers (Clutter.PaintContext paint_context, Clutter.ActorBox actor_box) { + var width = (int) actor_box.get_width (); + var height = (int) actor_box.get_height (); + + var downscale_factor = calculate_downscale_factor (width, height, radius); + + var updated = update_actor_fbo (width, height, downscale_factor) && update_general_fbo (width, height, downscale_factor); + + texture_width = width; + texture_height = height; + this.downscale_factor = downscale_factor; + + return updated; + } + + private Clutter.PaintNode create_blur_nodes (Clutter.PaintNode node) { + float width, height; + actor.get_size (out width, out height); + + var general_node = new Clutter.LayerNode.to_framebuffer (framebuffer, pipeline); + node.add_child (general_node); + general_node.add_rectangle ({ 0.0f, 0.0f, width, height }); + + var blur_node = new Clutter.BlurNode ( + (uint) (texture_width / downscale_factor), + (uint) (texture_height / downscale_factor), + radius / downscale_factor + ); + general_node.add_child (blur_node); + blur_node.add_rectangle ({ + 0.0f, + 0.0f, + texture.get_width (), + texture.get_height () + }); + + blur_applied = true; + + return blur_node; + } + + private void paint_actor_offscreen (Clutter.PaintNode node, Clutter.EffectPaintFlags flags) { + var actor_dirty = (flags & Clutter.EffectPaintFlags.ACTOR_DIRTY) != 0; + + /* The actor offscreen framebuffer is updated already */ + if (actor_dirty || !actor_painted) { + /* Layer node */ + var layer_node = new Clutter.LayerNode.to_framebuffer (actor_framebuffer, actor_pipeline); + node.add_child (layer_node); + layer_node.add_rectangle ({ + 0.0f, + 0.0f, + texture_width / downscale_factor, + texture_height / downscale_factor + }); + + /* Transform node */ + Graphene.Matrix transform = {}; + transform.init_scale ( + 1.0f / downscale_factor, + 1.0f / downscale_factor, + 1.0f + ); + var transform_node = new Clutter.TransformNode (transform); + layer_node.add_child (transform_node); + + /* Actor node */ + add_actor_node (transform_node); + + actor_painted = true; + } else { + Clutter.PaintNode pipeline_node = null; + + pipeline_node = new Clutter.PipelineNode (actor_pipeline); + node.add_child (pipeline_node); + pipeline_node.add_rectangle ({ + 0.0f, + 0.0f, + texture_width / downscale_factor, + texture_height / downscale_factor, + }); + } + } + + private void add_actor_node (Clutter.PaintNode node) { + var actor_node = new Clutter.ActorNode (actor, 255); + node.add_child (actor_node); + } + + private void add_blurred_pipeline (Clutter.PaintNode node) { + Clutter.PaintNode pipeline_node = null; + float width, height; + + /* Use the untransformed actor size here, since the framebuffer itself already + * has the actor transform matrix applied. + */ + actor.get_size (out width, out height); + + pipeline_node = new Clutter.PipelineNode (pipeline); + node.add_child (pipeline_node); + + pipeline_node.add_rectangle ({ 0.0f, 0.0f, width, height }); + } + + public override void paint_node (Clutter.PaintNode node, Clutter.PaintContext paint_context, Clutter.EffectPaintFlags flags) { + if (radius <= 0) { + // fallback to drawing actor + add_actor_node (node); + return; + } + + if (needs_repaint (flags)) { + var actor_box = update_actor_box (paint_context); + + if (!update_framebuffers (paint_context, actor_box)) { + // fallback to drawing actor + add_actor_node (node); + return; + } + + var blur_node = create_blur_nodes (node); + paint_actor_offscreen (blur_node, flags); + } else { + /* Use the cached pipeline if no repaint is needed */ + add_blurred_pipeline (node); + } + } +} diff --git a/compositor/Background/SystemBackground.vala b/compositor/Background/SystemBackground.vala new file mode 100644 index 000000000..6c1a09d0b --- /dev/null +++ b/compositor/Background/SystemBackground.vala @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Tom Beckmann + * Copyright 2023 elementary, Inc. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +public class GreeterCompositor.SystemBackground : GLib.Object { + private const Clutter.Color DEFAULT_BACKGROUND_COLOR = { 0x2e, 0x34, 0x36, 0xff }; + + public Meta.BackgroundActor background_actor { get; construct; } + + private static Meta.Background? system_background = null; + + public SystemBackground (Meta.Display display) { + Object (background_actor: new Meta.BackgroundActor (display, 0)); + } + + construct { + if (system_background == null) { + system_background = new Meta.Background (background_actor.meta_display); + system_background.set_color (DEFAULT_BACKGROUND_COLOR); + } + + ((Meta.BackgroundContent) background_actor.content).background = system_background; + } + + public static void refresh () { + // Meta.Background.refresh_all does not refresh backgrounds with the WALLPAPER style. + // (Last tested with mutter 3.28) + // As a workaround, re-apply the current color again to force the wallpaper texture + // to be rendered from scratch. + if (system_background != null) { + system_background.set_color (DEFAULT_BACKGROUND_COLOR); + } + } +} diff --git a/compositor/SystemBackground.vala b/compositor/SystemBackground.vala deleted file mode 100644 index c3eda2cff..000000000 --- a/compositor/SystemBackground.vala +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2018 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 2 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Authors: Corentin Noël - */ - -public class Greeter.SystemBackground : GLib.Object { - const Clutter.Color DEFAULT_BACKGROUND_COLOR = { 0x2e, 0x34, 0x36, 0xff }; - - static Meta.Background? system_background = null; - - public Meta.BackgroundActor background_actor { get; construct; } - - public signal void loaded (); - - public SystemBackground (Meta.Display display) { - Object (background_actor: new Meta.BackgroundActor (display, 0)); - } - - construct { - if (system_background == null) { - system_background = new Meta.Background (background_actor.meta_display); - var texture_file = GLib.File.new_for_uri ("resource:///io/elementary/desktop/gala/texture.png"); - system_background.set_color (DEFAULT_BACKGROUND_COLOR); - system_background.set_file (texture_file, GDesktop.BackgroundStyle.WALLPAPER); - } - - ((Meta.BackgroundContent)background_actor.content).background = system_background; - } - - public void refresh () { - // Meta.Background.refresh_all does not refresh backgrounds with the WALLPAPER style. - // (Last tested with mutter 3.28) - // As a workaround, re-apply the current color again to force the wallpaper texture - // to be rendered from scratch. - if (system_background != null) - system_background.set_color (DEFAULT_BACKGROUND_COLOR); - } -} diff --git a/compositor/WindowManager.vala b/compositor/WindowManager.vala index 7cbb88fcc..991be1a4f 100644 --- a/compositor/WindowManager.vala +++ b/compositor/WindowManager.vala @@ -42,9 +42,14 @@ namespace GreeterCompositor { */ public Clutter.Actor top_window_group { get; protected set; } + /** + * The background group is a container for the background actors forming the wallpaper + */ + public Meta.BackgroundGroup background_group { get; protected set; } + public PointerLocator pointer_locator { get; private set; } - public Greeter.SystemBackground system_background { get; private set; } + public GreeterCompositor.SystemBackground system_background { get; private set; } Meta.PluginInfo info; @@ -101,12 +106,12 @@ namespace GreeterCompositor { unowned Meta.Display display = get_display (); stage.remove_child (system_background.background_actor); - system_background = new Greeter.SystemBackground (display); + system_background = new SystemBackground (display); system_background.background_actor.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.ALL, 0)); stage.insert_child_below (system_background.background_actor, null); - system_background.refresh (); + SystemBackground.refresh (); } void show_stage () { @@ -114,12 +119,12 @@ namespace GreeterCompositor { MediaFeedback.init (); DBus.init (this); DBusAccelerator.init (this); - DBusBackgroundManager.init (this); + DBusWingpanelManager.init (this); KeyboardManager.init (display); stage = display.get_stage () as Clutter.Stage; - system_background = new Greeter.SystemBackground (display); + system_background = new SystemBackground (display); system_background.background_actor.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.ALL, 0)); stage.insert_child_below (system_background.background_actor, null); @@ -136,6 +141,10 @@ namespace GreeterCompositor { stage.remove_child (top_window_group); ui_group.add_child (top_window_group); + background_group = new BackgroundContainer (this); + window_group.add_child (background_group); + window_group.set_child_below_sibling (background_group, null); + pointer_locator = new PointerLocator (this); ui_group.add_child (pointer_locator); diff --git a/compositor/BackgroundUtils.vala b/compositor/WingpanelManager/BackgroundUtils.vala similarity index 100% rename from compositor/BackgroundUtils.vala rename to compositor/WingpanelManager/BackgroundUtils.vala diff --git a/compositor/DBusBackgroundManager.vala b/compositor/WingpanelManager/DBusWingpanelManager.vala similarity index 87% rename from compositor/DBusBackgroundManager.vala rename to compositor/WingpanelManager/DBusWingpanelManager.vala index bb12d88f5..3d5b226a3 100644 --- a/compositor/DBusBackgroundManager.vala +++ b/compositor/WingpanelManager/DBusWingpanelManager.vala @@ -18,9 +18,9 @@ */ [DBus (name = "org.pantheon.gala.WingpanelInterface")] - public class GreeterCompositor.DBusBackgroundManager : Object { - private BackgroundManager background_manager; - private static DBusBackgroundManager? instance; + public class GreeterCompositor.DBusWingpanelManager : Object { + private WingpanelManager background_manager; + private static DBusWingpanelManager? instance; static WindowManager wm; [DBus (visible = false)] @@ -30,7 +30,7 @@ Bus.own_name (BusType.SESSION, "org.pantheon.gala.WingpanelInterface", BusNameOwnerFlags.NONE, (connection) => { if (instance == null) - instance = new DBusBackgroundManager (); + instance = new DBusWingpanelManager (); try { connection.register_object ("/org/pantheon/gala/WingpanelInterface", instance); @@ -46,7 +46,7 @@ public signal void state_changed (BackgroundState state, uint animation_duration); public void initialize (int monitor, int panel_height) throws GLib.Error { - background_manager = new BackgroundManager (wm, panel_height); + background_manager = new WingpanelManager (wm, panel_height); background_manager.state_changed.connect ((state, animation_duration) => { state_changed (state, animation_duration); }); diff --git a/compositor/BackgroundManager.vala b/compositor/WingpanelManager/WingpanelManager.vala similarity index 98% rename from compositor/BackgroundManager.vala rename to compositor/WingpanelManager/WingpanelManager.vala index 9b1bc6fbf..92b008f15 100644 --- a/compositor/BackgroundManager.vala +++ b/compositor/WingpanelManager/WingpanelManager.vala @@ -25,7 +25,7 @@ public enum BackgroundState { TRANSLUCENT_LIGHT } -public class GreeterCompositor.BackgroundManager : Object { +public class GreeterCompositor.WingpanelManager : Object { private const int MINIMIZE_DURATION = 200; private const int SNAP_DURATION = 250; private const int WALLPAPER_TRANSITION_DURATION = 150; @@ -45,7 +45,7 @@ public class GreeterCompositor.BackgroundManager : Object { private BackgroundUtils.ColorInformation? bk_color_info = null; - public BackgroundManager (WindowManager _wm, int panel_height) { + public WingpanelManager (WindowManager _wm, int panel_height) { wm = _wm; Object (panel_height: panel_height); diff --git a/compositor/meson.build b/compositor/meson.build index 582890698..6008a2c9a 100644 --- a/compositor/meson.build +++ b/compositor/meson.build @@ -65,18 +65,25 @@ mutter_typelib_dir = libmutter_dep.get_variable('typelibdir') # Here is the real Compositor work compositor_files = files( - 'BackgroundManager.vala', - 'BackgroundUtils.vala', + 'Background/Animation.vala', + 'Background/Background.vala', + 'Background/BackgroundCache.vala', + 'Background/BackgroundContainer.vala', + 'Background/BackgroundManager.vala', + 'Background/BackgroundSource.vala', + 'Background/BlurEffect.vala', + 'Background/SystemBackground.vala', + 'WingpanelManager/WingpanelManager.vala', + 'WingpanelManager/DBusWingpanelManager.vala', + 'WingpanelManager/BackgroundUtils.vala', 'DBus.vala', 'DBusAccelerator.vala', - 'DBusBackgroundManager.vala', 'Dialogs.vala', 'KeyboardManager.vala', 'main.vala', 'MaskCorners.vala', 'MediaFeedback.vala', 'PointerLocator.vala', - 'SystemBackground.vala', 'Utils.vala', 'WindowManager.vala' ) @@ -86,7 +93,7 @@ executable( compositor_files, compositor_resources, config_header, - dependencies: [glib_dep, gtk_dep, gee_dep, m_dep, posix_dep, mutter_dep], + dependencies: [glib_dep, gtk_dep, gee_dep, m_dep, posix_dep, mutter_dep, gnome_desktop_dep], vala_args: vala_flags, c_args: compositor_c_args, build_rpath: mutter_typelib_dir, diff --git a/meson.build b/meson.build index 88b12b9c5..a7cea8d5c 100644 --- a/meson.build +++ b/meson.build @@ -31,7 +31,11 @@ config_header = configure_file ( add_project_arguments(['--vapidir', join_paths(meson.current_source_dir(), 'vapi')], language: 'vala') -add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), language:'c') +add_global_arguments( + '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), + '-DGNOME_DESKTOP_USE_UNSTABLE_API', + language:'c' +) greeter_resources = gnome.compile_resources( 'greeter-resources', 'data/greeter.gresource.xml', diff --git a/src/Cards/UserCard.vala b/src/Cards/UserCard.vala index e1c886d57..1424fc437 100644 --- a/src/Cards/UserCard.vala +++ b/src/Cards/UserCard.vala @@ -236,7 +236,7 @@ public class Greeter.UserCard : Greeter.BaseCard { } }); - // This makes all the animations synchonous + // This makes all the animations synchronous form_revealer.size_allocate.connect ((alloc) => { var total_height = form_box.get_allocated_height () + form_box.margin_top + form_box.margin_bottom; reveal_ratio = (double)alloc.height / (double)total_height; @@ -478,6 +478,16 @@ public class Greeter.UserCard : Greeter.BaseCard { var touchscreen_settings = new GLib.Settings ("org.gnome.settings-daemon.peripherals.touchscreen"); touchscreen_settings.set_boolean ("orientation-lock", settings_act.orientation_lock); + + var background_settings = new GLib.Settings ("org.gnome.desktop.background"); + if (lightdm_user.background != null) { + background_settings.set_value ("picture-uri", lightdm_user.background); + } else { + background_settings.reset ("picture-uri"); + } + + background_settings.set_value ("picture-options", settings_act.picture_options); + background_settings.set_value ("primary-color", settings_act.primary_color); } private void set_night_light_settings () { diff --git a/src/meson.build b/src/meson.build index 29aaef3f8..909954288 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,6 +5,7 @@ gtk_dep = dependency('gtk+-3.0') granite_dep = dependency('granite', version: '>= 5.5.0') hdy_dep = dependency('libhandy-1', version: '>= 1.1.90') lightdm_dep = dependency('liblightdm-gobject-1') +gnome_desktop_dep = dependency('gnome-desktop-3.0') m_dep = meson.get_compiler('c').find_library('m') install_path = join_paths(get_option('prefix'), get_option('sbindir')) From f695e1a1207fe25f335b7922b456c8d134fad6d4 Mon Sep 17 00:00:00 2001 From: lenemter Date: Sat, 3 Feb 2024 20:52:14 +0900 Subject: [PATCH 02/11] Fix lint --- compositor/Background/BackgroundManager.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compositor/Background/BackgroundManager.vala b/compositor/Background/BackgroundManager.vala index efbcd9c61..fbe7f0faa 100644 --- a/compositor/Background/BackgroundManager.vala +++ b/compositor/Background/BackgroundManager.vala @@ -119,7 +119,7 @@ public class GreeterCompositor.BackgroundManager : Meta.BackgroundGroup { content.background = background.background; insert_child_below (background_actor, null); - + var monitor = display.get_monitor_geometry (monitor_index); background_actor.set_size (monitor.width, monitor.height); From 474d8d6924b98de32e3712173cd5767421f4eefb Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 14 Feb 2024 18:30:14 +0900 Subject: [PATCH 03/11] Fix wingpanel-interface --- .../WingpanelManager/BackgroundUtils.vala | 6 +++- .../DBusWingpanelManager.vala | 32 +++++++++---------- .../WingpanelManager/WingpanelManager.vala | 5 ++- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/compositor/WingpanelManager/BackgroundUtils.vala b/compositor/WingpanelManager/BackgroundUtils.vala index b527aee2b..d0f84795e 100644 --- a/compositor/WingpanelManager/BackgroundUtils.vala +++ b/compositor/WingpanelManager/BackgroundUtils.vala @@ -48,7 +48,11 @@ namespace BackgroundUtils { public async ColorInformation get_background_color_information (GreeterCompositor.WindowManager wm, int reference_x, int reference_y, int reference_width, int reference_height) throws DBusError { - var background = wm.system_background.background_actor; + var background = wm.background_group.get_child_at_index (wm.get_display ().get_primary_monitor ()); + + if (background == null) { + throw new DBusError.INVALID_ARGS ("Invalid monitor requested: %i".printf (wm.get_display ().get_primary_monitor ())); + } var effect = new DummyOffscreenEffect (); background.add_effect (effect); diff --git a/compositor/WingpanelManager/DBusWingpanelManager.vala b/compositor/WingpanelManager/DBusWingpanelManager.vala index 3d5b226a3..a7326cdc5 100644 --- a/compositor/WingpanelManager/DBusWingpanelManager.vala +++ b/compositor/WingpanelManager/DBusWingpanelManager.vala @@ -17,11 +17,11 @@ * Boston, MA 02110-1301 USA. */ - [DBus (name = "org.pantheon.gala.WingpanelInterface")] - public class GreeterCompositor.DBusWingpanelManager : Object { - private WingpanelManager background_manager; - private static DBusWingpanelManager? instance; - static WindowManager wm; +[DBus (name = "org.pantheon.gala.WingpanelInterface")] +public class GreeterCompositor.DBusWingpanelManager : Object { + private WingpanelManager background_manager; + private static DBusWingpanelManager? instance; + static WindowManager wm; [DBus (visible = false)] public static void init (WindowManager _wm) { @@ -43,19 +43,19 @@ ); } - public signal void state_changed (BackgroundState state, uint animation_duration); + public signal void state_changed (BackgroundState state, uint animation_duration); - public void initialize (int monitor, int panel_height) throws GLib.Error { - background_manager = new WingpanelManager (wm, panel_height); - background_manager.state_changed.connect ((state, animation_duration) => { - state_changed (state, animation_duration); - }); + public void initialize (int monitor, int panel_height) throws GLib.Error { + background_manager = new WingpanelManager (wm, panel_height); + background_manager.state_changed.connect ((state, animation_duration) => { + state_changed (state, animation_duration); + }); } - public bool begin_grab_focused_window (int x, int y, int button, uint time, uint state) throws GLib.Error { - return false; - } + public bool begin_grab_focused_window (int x, int y, int button, uint time, uint state) throws GLib.Error { + return false; + } - public void remember_focused_window () throws GLib.Error {} - public void restore_focused_window () throws GLib.Error {} + public void remember_focused_window () throws GLib.Error {} + public void restore_focused_window () throws GLib.Error {} } diff --git a/compositor/WingpanelManager/WingpanelManager.vala b/compositor/WingpanelManager/WingpanelManager.vala index 92b008f15..5e721d76b 100644 --- a/compositor/WingpanelManager/WingpanelManager.vala +++ b/compositor/WingpanelManager/WingpanelManager.vala @@ -63,11 +63,14 @@ public class GreeterCompositor.WingpanelManager : Object { update_current_workspace (); }); - wm.notify["system-background"].connect (() => { + var signal_id = GLib.Signal.lookup ("changed", wm.background_group.get_type ()); + GLib.Signal.add_emission_hook (signal_id, 0, (ihint, param_values) => { update_bk_color_info.begin ((obj, res) => { update_bk_color_info.end (res); check_for_state_change (WALLPAPER_TRANSITION_DURATION); }); + + return true; }); } From 25c2e94af5eacad10a23117ccf0215f57e445cc2 Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 14 Feb 2024 18:50:30 +0900 Subject: [PATCH 04/11] Code style fixes --- .../WingpanelManager/DBusWingpanelManager.vala | 9 +++++---- compositor/meson.build | 16 ++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compositor/WingpanelManager/DBusWingpanelManager.vala b/compositor/WingpanelManager/DBusWingpanelManager.vala index a7326cdc5..bb75f4ecc 100644 --- a/compositor/WingpanelManager/DBusWingpanelManager.vala +++ b/compositor/WingpanelManager/DBusWingpanelManager.vala @@ -18,10 +18,11 @@ */ [DBus (name = "org.pantheon.gala.WingpanelInterface")] -public class GreeterCompositor.DBusWingpanelManager : Object { - private WingpanelManager background_manager; +public class GreeterCompositor.DBusWingpanelManager : GLib.Object { private static DBusWingpanelManager? instance; - static WindowManager wm; + private static WindowManager wm; + + private WingpanelManager background_manager; [DBus (visible = false)] public static void init (WindowManager _wm) { @@ -58,4 +59,4 @@ public class GreeterCompositor.DBusWingpanelManager : Object { public void remember_focused_window () throws GLib.Error {} public void restore_focused_window () throws GLib.Error {} - } +} diff --git a/compositor/meson.build b/compositor/meson.build index 6008a2c9a..489b47846 100644 --- a/compositor/meson.build +++ b/compositor/meson.build @@ -65,14 +65,14 @@ mutter_typelib_dir = libmutter_dep.get_variable('typelibdir') # Here is the real Compositor work compositor_files = files( - 'Background/Animation.vala', - 'Background/Background.vala', - 'Background/BackgroundCache.vala', - 'Background/BackgroundContainer.vala', - 'Background/BackgroundManager.vala', - 'Background/BackgroundSource.vala', - 'Background/BlurEffect.vala', - 'Background/SystemBackground.vala', + 'Background/Animation.vala', + 'Background/Background.vala', + 'Background/BackgroundCache.vala', + 'Background/BackgroundContainer.vala', + 'Background/BackgroundManager.vala', + 'Background/BackgroundSource.vala', + 'Background/BlurEffect.vala', + 'Background/SystemBackground.vala', 'WingpanelManager/WingpanelManager.vala', 'WingpanelManager/DBusWingpanelManager.vala', 'WingpanelManager/BackgroundUtils.vala', From bdee5b189f8a545113407cb3fd8a9e4b3eb5a3ce Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 14 Feb 2024 19:10:45 +0900 Subject: [PATCH 05/11] Update copyright --- .../WingpanelManager/DBusWingpanelManager.vala | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/compositor/WingpanelManager/DBusWingpanelManager.vala b/compositor/WingpanelManager/DBusWingpanelManager.vala index bb75f4ecc..22c072ef7 100644 --- a/compositor/WingpanelManager/DBusWingpanelManager.vala +++ b/compositor/WingpanelManager/DBusWingpanelManager.vala @@ -1,20 +1,6 @@ /* - * Copyright (c) 2011-2015 Wingpanel Developers (http://launchpad.net/wingpanel) - * - * 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 2 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. + * Copyright 2024 elementary, Inc. (https://elementary.io) + * SPDX-License-Identifier: GPL-2.0-or-later */ [DBus (name = "org.pantheon.gala.WingpanelInterface")] From a8c86639a3c6864315cabbd74831d8d48ca01681 Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 14 Feb 2024 19:15:14 +0900 Subject: [PATCH 06/11] Update copyrights --- compositor/Background/Animation.vala | 21 +++++------------- compositor/Background/Background.vala | 21 +++++------------- compositor/Background/BackgroundCache.vala | 21 +++++------------- .../Background/BackgroundContainer.vala | 22 +++++-------------- compositor/Background/BackgroundSource.vala | 21 +++++------------- 5 files changed, 26 insertions(+), 80 deletions(-) diff --git a/compositor/Background/Animation.vala b/compositor/Background/Animation.vala index 45df5b0c4..fa4c17c08 100644 --- a/compositor/Background/Animation.vala +++ b/compositor/Background/Animation.vala @@ -1,19 +1,8 @@ -// -// 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: 2024 elementary, Inc. (https://elementary.io) + * 2014 Tom Beckmann + */ namespace GreeterCompositor { public class Animation : Object { diff --git a/compositor/Background/Background.vala b/compositor/Background/Background.vala index ee9740fd0..056bec101 100644 --- a/compositor/Background/Background.vala +++ b/compositor/Background/Background.vala @@ -1,19 +1,8 @@ -// -// 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: 2024 elementary, Inc. (https://elementary.io) + * 2014 Tom Beckmann + */ namespace GreeterCompositor { public class Background : Object { diff --git a/compositor/Background/BackgroundCache.vala b/compositor/Background/BackgroundCache.vala index 93134a440..be62ddd30 100644 --- a/compositor/Background/BackgroundCache.vala +++ b/compositor/Background/BackgroundCache.vala @@ -1,19 +1,8 @@ -// -// 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: 2024 elementary, Inc. (https://elementary.io) + * 2014 Tom Beckmann + */ namespace GreeterCompositor { public class BackgroundCache : Object { diff --git a/compositor/Background/BackgroundContainer.vala b/compositor/Background/BackgroundContainer.vala index 46691eecf..d432120e4 100644 --- a/compositor/Background/BackgroundContainer.vala +++ b/compositor/Background/BackgroundContainer.vala @@ -1,19 +1,9 @@ -// -// 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: 2024 elementary, Inc. (https://elementary.io) + * 2013 Tom Beckmann + * 2013 Rico Tzschichholz + */ namespace GreeterCompositor { public class BackgroundContainer : Meta.BackgroundGroup { diff --git a/compositor/Background/BackgroundSource.vala b/compositor/Background/BackgroundSource.vala index 84c00ebfe..5896cfa71 100644 --- a/compositor/Background/BackgroundSource.vala +++ b/compositor/Background/BackgroundSource.vala @@ -1,19 +1,8 @@ -// -// 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: 2024 elementary, Inc. (https://elementary.io) + * 2014 Tom Beckmann + */ namespace GreeterCompositor { public class BackgroundSource : Object { From fda5e2980cab8b69d251a2af2eede1c3e2213f07 Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 14 Feb 2024 19:15:55 +0900 Subject: [PATCH 07/11] Update year --- compositor/Background/BackgroundManager.vala | 2 +- compositor/Background/BlurEffect.vala | 2 +- compositor/Background/SystemBackground.vala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compositor/Background/BackgroundManager.vala b/compositor/Background/BackgroundManager.vala index fbe7f0faa..12588ba96 100644 --- a/compositor/Background/BackgroundManager.vala +++ b/compositor/Background/BackgroundManager.vala @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: GPL-3.0-or-later - * SPDX-FileCopyrightText: 2023 elementary, Inc. (https://elementary.io) + * SPDX-FileCopyrightText: 2023-2024 elementary, Inc. (https://elementary.io) * 2014 Tom Beckmann */ diff --git a/compositor/Background/BlurEffect.vala b/compositor/Background/BlurEffect.vala index 6f254ba95..0c09b8717 100644 --- a/compositor/Background/BlurEffect.vala +++ b/compositor/Background/BlurEffect.vala @@ -1,5 +1,5 @@ /* - * Copyright 2023 elementary, Inc. + * Copyright 2024 elementary, Inc. * SPDX-License-Identifier: GPL-3.0-or-later */ diff --git a/compositor/Background/SystemBackground.vala b/compositor/Background/SystemBackground.vala index 6c1a09d0b..cbad1aba8 100644 --- a/compositor/Background/SystemBackground.vala +++ b/compositor/Background/SystemBackground.vala @@ -1,6 +1,6 @@ /* * Copyright 2014 Tom Beckmann - * Copyright 2023 elementary, Inc. + * Copyright 2023-2024 elementary, Inc. * SPDX-License-Identifier: GPL-3.0-or-later */ From bf741b5d978750bd93a17183ce06374aa4d37065 Mon Sep 17 00:00:00 2001 From: Leo Date: Wed, 14 Feb 2024 21:03:41 +0900 Subject: [PATCH 08/11] wingpanel-interface: implement FocusManager (#706) --- .../DBusWingpanelManager.vala | 14 +- compositor/WingpanelManager/FocusManager.vala | 128 ++++++++++++++++++ compositor/meson.build | 1 + 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 compositor/WingpanelManager/FocusManager.vala diff --git a/compositor/WingpanelManager/DBusWingpanelManager.vala b/compositor/WingpanelManager/DBusWingpanelManager.vala index 22c072ef7..9a41ebcfd 100644 --- a/compositor/WingpanelManager/DBusWingpanelManager.vala +++ b/compositor/WingpanelManager/DBusWingpanelManager.vala @@ -9,6 +9,7 @@ public class GreeterCompositor.DBusWingpanelManager : GLib.Object { private static WindowManager wm; private WingpanelManager background_manager; + private FocusManager focus_manager; [DBus (visible = false)] public static void init (WindowManager _wm) { @@ -37,12 +38,19 @@ public class GreeterCompositor.DBusWingpanelManager : GLib.Object { background_manager.state_changed.connect ((state, animation_duration) => { state_changed (state, animation_duration); }); + + focus_manager = new FocusManager (wm.get_display ()); } public bool begin_grab_focused_window (int x, int y, int button, uint time, uint state) throws GLib.Error { - return false; + return focus_manager.begin_grab_focused_window (x, y, button, time, state); + } + + public void remember_focused_window () throws GLib.Error { + focus_manager.remember_focused_window (); } - public void remember_focused_window () throws GLib.Error {} - public void restore_focused_window () throws GLib.Error {} + public void restore_focused_window () throws GLib.Error { + focus_manager.restore_focused_window (); + } } diff --git a/compositor/WingpanelManager/FocusManager.vala b/compositor/WingpanelManager/FocusManager.vala new file mode 100644 index 000000000..fa69dfea3 --- /dev/null +++ b/compositor/WingpanelManager/FocusManager.vala @@ -0,0 +1,128 @@ +/* + * Copyright 2024 elementary, Inc. (https://elementary.io) + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +public class GreeterCompositor.FocusManager : GLib.Object { + private unowned Meta.Display display; + private unowned Meta.Workspace? current_workspace = null; + private unowned Meta.Window? last_focused_window = null; + private unowned Meta.Window? last_focused_dialog_window = null; + + public FocusManager (Meta.Display _display) { + display = _display; + + unowned Meta.WorkspaceManager manager = display.get_workspace_manager (); + manager.workspace_switched.connect (() => { + update_current_workspace (); + }); + + update_current_workspace (); + } + + public void remember_focused_window () { + var windows = current_workspace.list_windows (); + foreach (unowned Meta.Window window in windows) { + window_created (window); + if (window.has_focus ()) { + last_focused_window = window; + } + } + + display.window_created.connect (window_created); + } + + public void restore_focused_window () { + // when a dialog was opened give it focus + if (last_focused_dialog_window != null) { + last_focused_dialog_window.focus (display.get_current_time ()); + // if dialog is closed pass focus to last focussed window + last_focused_dialog_window.unmanaged.connect (() => { + last_focused_dialog_window = null; + restore_focused_window (); + }); + } else if (last_focused_window != null) { + last_focused_window.focus (display.get_current_time ()); + } + + var windows = current_workspace.list_windows (); + foreach (unowned Meta.Window window in windows) { + window.focused.disconnect (window_focused); + window.unmanaged.disconnect (window_unmanaged); + } + + display.window_created.disconnect (window_created); + } + + void window_created (Meta.Window window) { + window.focused.connect (window_focused); + window.unmanaged.connect (window_unmanaged); + } + + void window_focused (Meta.Window window) { + // make sure we keep the last_focused_window when a dialog is started from wingpanel + if (window.window_type == Meta.WindowType.DIALOG) { + last_focused_dialog_window = window; + } else if (window.window_type != Meta.WindowType.DOCK) { // ignore focus to wingpanel + last_focused_window = window; + } + } + + void window_unmanaged (Meta.Window window) { + window.focused.disconnect (window_focused); + window.unmanaged.disconnect (window_unmanaged); + } + + public bool begin_grab_focused_window (int x, int y, int button, uint time, uint state) { + unowned var window = display.get_focus_window (); + if (window == null || !get_can_grab_window (window, x, y)) { + unowned Meta.Workspace workspace = display.get_workspace_manager ().get_active_workspace (); + List? windows = workspace.list_windows (); + if (windows == null) { + return false; + } + + window = null; + List copy = windows.copy (); + copy.reverse (); + copy.@foreach ((win) => { + if (window != null) { + return; + } + + if (get_can_grab_window (win, x, y)) { + window = win; + } + }); + } + + if (window != null) { +#if HAS_MUTTER44 + window.begin_grab_op (Meta.GrabOp.MOVING, null, null, time); +#else + display.begin_grab_op (window, Meta.GrabOp.MOVING, false, true, button, state, time, x, y); +#endif + return true; + } + + return false; + } + + private static bool get_can_grab_window (Meta.Window window, int x, int y) { + var frame = window.get_frame_rect (); + return !window.minimized && window.maximized_vertically && x >= frame.x && x <= frame.x + frame.width; + } + + private void update_current_workspace () { + unowned Meta.WorkspaceManager manager = display.get_workspace_manager (); + unowned var workspace = manager.get_workspace_by_index (manager.get_active_workspace_index ()); + + if (workspace == null) { + warning ("Cannot get active workspace"); + + return; + } + + current_workspace = workspace; + } +} diff --git a/compositor/meson.build b/compositor/meson.build index 489b47846..ee210a378 100644 --- a/compositor/meson.build +++ b/compositor/meson.build @@ -75,6 +75,7 @@ compositor_files = files( 'Background/SystemBackground.vala', 'WingpanelManager/WingpanelManager.vala', 'WingpanelManager/DBusWingpanelManager.vala', + 'WingpanelManager/FocusManager.vala', 'WingpanelManager/BackgroundUtils.vala', 'DBus.vala', 'DBusAccelerator.vala', From 1202157133800228ddcd6eacdf18c090b86e6dc8 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 16 Feb 2024 19:13:51 +0900 Subject: [PATCH 09/11] Reduce diff --- .../WingpanelManager/BackgroundUtils.vala | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/compositor/WingpanelManager/BackgroundUtils.vala b/compositor/WingpanelManager/BackgroundUtils.vala index d0f84795e..1841602d8 100644 --- a/compositor/WingpanelManager/BackgroundUtils.vala +++ b/compositor/WingpanelManager/BackgroundUtils.vala @@ -1,20 +1,6 @@ /* - * Copyright (c) 2011-2015 Wingpanel Developers (http://launchpad.net/wingpanel) - * - * 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 2 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. + * Copyright 2024 elementary, Inc. (https://elementary.io) + * SPDX-License-Identifier: GPL-2.0-or-later */ /* From dd4334b79dc5f01c193367bedfaf37e9fdb877f4 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 16 Feb 2024 20:14:36 +0900 Subject: [PATCH 10/11] Wingpanel Interface: remove workspaces management --- .../WingpanelManager/WingpanelManager.vala | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/compositor/WingpanelManager/WingpanelManager.vala b/compositor/WingpanelManager/WingpanelManager.vala index 5e721d76b..f02478005 100644 --- a/compositor/WingpanelManager/WingpanelManager.vala +++ b/compositor/WingpanelManager/WingpanelManager.vala @@ -37,12 +37,9 @@ public class GreeterCompositor.WingpanelManager : Object { public signal void state_changed (BackgroundState state, uint animation_duration); public int panel_height { private get; construct; } - private static WindowManager wm; - - private Meta.Workspace? current_workspace = null; + private static WindowManager wm; private BackgroundState current_state = BackgroundState.LIGHT; - private BackgroundUtils.ColorInformation? bk_color_info = null; public WingpanelManager (WindowManager _wm, int panel_height) { @@ -75,32 +72,21 @@ public class GreeterCompositor.WingpanelManager : Object { } private void update_current_workspace () { - unowned Meta.WorkspaceManager manager = wm.get_display ().get_workspace_manager (); - var workspace = manager.get_active_workspace (); - - if (workspace == null) { - warning ("Cannot get active workspace"); + unowned var display = wm.get_display (); - return; - } - - if (current_workspace != null) { - current_workspace.window_added.disconnect (on_window_added); - current_workspace.window_removed.disconnect (on_window_removed); - } - - current_workspace = workspace; - - foreach (Meta.Window window in current_workspace.list_windows ()) { + foreach (unowned var window in display.list_all_windows ()) { if (window.is_on_primary_monitor ()) { register_window (window); } } - current_workspace.window_added.connect (on_window_added); - current_workspace.window_removed.connect (on_window_removed); + display.window_created.connect ((window) => { + on_window_added (window); + + window.unmanaged.connect (on_window_removed); + }); - check_for_state_change (WORKSPACE_SWITCH_DURATION); + check_for_state_change (0); } private void register_window (Meta.Window window) { @@ -159,7 +145,7 @@ public class GreeterCompositor.WingpanelManager : Object { private void check_for_state_change (uint animation_duration) { bool has_maximized_window = false; - foreach (Meta.Window window in current_workspace.list_windows ()) { + foreach (Meta.Window window in wm.get_display ().list_all_windows ()) { if (window.is_on_primary_monitor ()) { if (!window.minimized && window.maximized_vertically) { has_maximized_window = true; From 6fd29f4626bc20ea589ecc9b71b03cf25b9db91d Mon Sep 17 00:00:00 2001 From: Leo Date: Tue, 20 Feb 2024 08:23:41 +0900 Subject: [PATCH 11/11] BackgroundManager: send `changed` signal immediately (#707) * BackgroundManager: send `changed` signal immediately * Sync with gala --- compositor/Background/BackgroundManager.vala | 10 +++++++--- .../WingpanelManager/BackgroundUtils.vala | 17 +++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/compositor/Background/BackgroundManager.vala b/compositor/Background/BackgroundManager.vala index 12588ba96..6ed3e7d52 100644 --- a/compositor/Background/BackgroundManager.vala +++ b/compositor/Background/BackgroundManager.vala @@ -13,6 +13,11 @@ public class GreeterCompositor.BackgroundManager : Meta.BackgroundGroup { public WindowManager wm { get; construct; } public int monitor_index { get; construct; } public bool control_position { get; construct; } + public Meta.BackgroundActor newest_background_actor { + get { + return (new_background_actor != null) ? new_background_actor : background_actor; + } + } private BackgroundSource background_source; private Meta.BackgroundActor background_actor; @@ -64,15 +69,14 @@ public class GreeterCompositor.BackgroundManager : Meta.BackgroundGroup { transition.remove_on_complete = true; transition.completed.connect (() => { old_background_actor.destroy (); - - changed (); }); old_background_actor.add_transition ("fade-out", transition); } else { old_background_actor.destroy (); - changed (); } + + changed (); } private void update_background_actor (bool animate = true) { diff --git a/compositor/WingpanelManager/BackgroundUtils.vala b/compositor/WingpanelManager/BackgroundUtils.vala index 1841602d8..6ec8a9d25 100644 --- a/compositor/WingpanelManager/BackgroundUtils.vala +++ b/compositor/WingpanelManager/BackgroundUtils.vala @@ -8,7 +8,7 @@ * related to it are copied from Gala.DBus. */ -namespace BackgroundUtils { +namespace GreeterCompositor.BackgroundUtils { private const double SATURATION_WEIGHT = 1.5; private const double WEIGHT_THRESHOLD = 1.0; @@ -34,17 +34,18 @@ namespace BackgroundUtils { public async ColorInformation get_background_color_information (GreeterCompositor.WindowManager wm, int reference_x, int reference_y, int reference_width, int reference_height) throws DBusError { - var background = wm.background_group.get_child_at_index (wm.get_display ().get_primary_monitor ()); + var bg_manager = (BackgroundManager) wm.background_group.get_child_at_index (wm.get_display ().get_primary_monitor ()); - if (background == null) { + if (bg_manager == null) { throw new DBusError.INVALID_ARGS ("Invalid monitor requested: %i".printf (wm.get_display ().get_primary_monitor ())); } var effect = new DummyOffscreenEffect (); - background.add_effect (effect); + unowned var newest_background_actor = bg_manager.newest_background_actor; + newest_background_actor.add_effect (effect); - var bg_actor_width = (int)background.width; - var bg_actor_height = (int)background.height; + var bg_actor_width = (int) newest_background_actor.width; + var bg_actor_height = (int) newest_background_actor.height; // A commit in mutter added some padding to offscreen textures, so we // need to avoid looking at the edges of the texture as it often has a @@ -77,7 +78,7 @@ namespace BackgroundUtils { paint_signal_handler = effect.done_painting.connect (() => { SignalHandler.disconnect (effect, paint_signal_handler); - background.remove_effect (effect); + newest_background_actor.remove_effect (effect); var texture = (Cogl.Texture)effect.get_texture (); var texture_width = texture.get_width (); @@ -197,7 +198,7 @@ namespace BackgroundUtils { get_background_color_information.callback (); }); - background.queue_redraw (); + newest_background_actor.queue_redraw (); yield;