From e1c8dc9bca44db635af5d5bbc60f8342fb3fa300 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Tue, 24 Dec 2024 12:13:04 +0100 Subject: [PATCH 1/2] ShellClients: Use translation y instead of clone and gesturetransition for animation --- src/Gestures/GestureTracker.vala | 21 ++++++ src/ShellClients/HideTracker.vala | 45 +++++++------ src/ShellClients/PanelClone.vala | 103 +++++++----------------------- 3 files changed, 68 insertions(+), 101 deletions(-) diff --git a/src/Gestures/GestureTracker.vala b/src/Gestures/GestureTracker.vala index 9ca525bb9..89b684d0d 100644 --- a/src/Gestures/GestureTracker.vala +++ b/src/Gestures/GestureTracker.vala @@ -75,6 +75,8 @@ public class Gala.GestureTracker : Object { */ public bool enabled { get; set; default = true; } + public bool recognizing { get; private set; } + /** * Emitted when a new gesture is detected. * This should only be used to determine whether the gesture should be handled. This shouldn't @@ -193,6 +195,23 @@ public class Gala.GestureTracker : Object { } } + /** + * Connects a callback that will only be called if != 0 completions were made. + * If with_gesture is false it will be called immediately, otherwise once {@link on_end} is emitted. + */ + public void add_success_callback (bool with_gesture, owned OnEnd callback) { + if (!with_gesture) { + callback (1, 1, min_animation_duration); + } else { + ulong handler_id = on_end.connect ((percentage, completions, duration) => { + if (completions != 0) { + callback (percentage, completions, duration); + } + }); + handlers.add (handler_id); + } + } + private void disconnect_all_handlers () { foreach (var handler in handlers) { disconnect (handler); @@ -242,6 +261,7 @@ public class Gala.GestureTracker : Object { on_begin (percentage); } + recognizing = true; previous_percentage = percentage; previous_time = elapsed_time; } @@ -283,6 +303,7 @@ public class Gala.GestureTracker : Object { } disconnect_all_handlers (); + recognizing = false; previous_percentage = 0; previous_time = 0; percentage_delta = 0; diff --git a/src/ShellClients/HideTracker.vala b/src/ShellClients/HideTracker.vala index 092b26c54..59ddef20d 100644 --- a/src/ShellClients/HideTracker.vala +++ b/src/ShellClients/HideTracker.vala @@ -10,11 +10,12 @@ public class Gala.HideTracker : Object { private const int UPDATE_TIMEOUT = 200; private const int HIDE_DELAY = 500; - public signal void hide (); - public signal void show (); + public signal void hide (GestureTracker gesture_tracker, bool with_gesture); + public signal void show (GestureTracker gesture_tracker, bool with_gesture); public Meta.Display display { get; construct; } public unowned PanelWindow panel { get; construct; } + public GestureTracker default_gesture_tracker { get; construct; } // Placeholder that will replace pan_action once the pan_backend gets merged public Pantheon.Desktop.HideMode hide_mode { get; set; } @@ -33,8 +34,8 @@ public class Gala.HideTracker : Object { private uint hide_timeout_id = 0; private uint update_timeout_id = 0; - public HideTracker (Meta.Display display, PanelWindow panel) { - Object (display: display, panel: panel); + public HideTracker (Meta.Display display, PanelWindow panel, GestureTracker default_gesture_tracker) { + Object (display: display, panel: panel, default_gesture_tracker: default_gesture_tracker); } ~HideTracker () { @@ -146,13 +147,13 @@ public class Gala.HideTracker : Object { } update_timeout_id = Timeout.add (UPDATE_TIMEOUT, () => { - update_overlap (); + update_overlap (default_gesture_tracker, false); update_timeout_id = 0; return Source.REMOVE; }); } - private void update_overlap () { + public void update_overlap (GestureTracker gesture_tracker, bool with_gesture) { overlap = false; focus_overlap = false; focus_maximized_overlap = false; @@ -185,25 +186,25 @@ public class Gala.HideTracker : Object { focus_maximized_overlap = VERTICAL in window.get_maximized (); } - update_hidden (); + update_hidden (gesture_tracker, with_gesture); } - private void update_hidden () { + private void update_hidden (GestureTracker gesture_tracker, bool with_gesture) { switch (hide_mode) { case MAXIMIZED_FOCUS_WINDOW: - toggle_display (focus_maximized_overlap); + toggle_display (focus_maximized_overlap, gesture_tracker, with_gesture); break; case OVERLAPPING_FOCUS_WINDOW: - toggle_display (focus_overlap); + toggle_display (focus_overlap, gesture_tracker, with_gesture); break; case OVERLAPPING_WINDOW: - toggle_display (overlap); + toggle_display (overlap, gesture_tracker, with_gesture); break; case ALWAYS: - toggle_display (true); + toggle_display (true, gesture_tracker, with_gesture); break; default: @@ -212,7 +213,11 @@ public class Gala.HideTracker : Object { } } - private void toggle_display (bool should_hide) { + private void toggle_display (bool should_hide, GestureTracker gesture_tracker, bool with_gesture) { + if (display.get_monitor_in_fullscreen (panel.window.get_monitor ())) { + return; + } + #if HAS_MUTTER45 hovered = panel.window.has_pointer (); #else @@ -222,7 +227,7 @@ public class Gala.HideTracker : Object { if (should_hide && !hovered && !panel.window.has_focus ()) { trigger_hide (); } else { - trigger_show (); + trigger_show (gesture_tracker, with_gesture); } } @@ -241,7 +246,7 @@ public class Gala.HideTracker : Object { } hide_timeout_id = Timeout.add_once (HIDE_DELAY, () => { - hide (); + hide (default_gesture_tracker, false); hide_timeout_id = 0; }); } @@ -253,9 +258,9 @@ public class Gala.HideTracker : Object { } } - private void trigger_show () { + private void trigger_show (GestureTracker gesture_tracker, bool with_gesture) { reset_hide_timeout (); - show (); + show (gesture_tracker, with_gesture); } private bool check_valid_gesture () { @@ -281,7 +286,7 @@ public class Gala.HideTracker : Object { if (delta_y < 0) { // Only allow swipes upwards panel.window.focus (pan_action.get_last_event (0).get_time ()); - trigger_show (); + trigger_show (default_gesture_tracker, false); } return false; @@ -325,7 +330,7 @@ public class Gala.HideTracker : Object { int.MAX ); - barrier.trigger.connect (trigger_show); + barrier.trigger.connect (() => trigger_show (default_gesture_tracker, false)); } #if HAS_MUTTER45 @@ -346,6 +351,6 @@ public class Gala.HideTracker : Object { int.MAX ); - barrier.trigger.connect (trigger_show); + barrier.trigger.connect (() => trigger_show (default_gesture_tracker, false)); } } diff --git a/src/ShellClients/PanelClone.vala b/src/ShellClients/PanelClone.vala index 6a32b101f..c3a292363 100644 --- a/src/ShellClients/PanelClone.vala +++ b/src/ShellClients/PanelClone.vala @@ -18,10 +18,10 @@ public class Gala.PanelClone : Object { set { if (value == NEVER) { hide_tracker = null; - show (); + show (default_gesture_tracker, false); return; } else if (hide_tracker == null) { - hide_tracker = new HideTracker (wm.get_display (), panel); + hide_tracker = new HideTracker (wm.get_display (), panel, default_gesture_tracker); hide_tracker.hide.connect (hide); hide_tracker.show.connect (show); } @@ -32,9 +32,11 @@ public class Gala.PanelClone : Object { public bool panel_hidden { get; private set; default = true; } - private SafeWindowClone clone; private Meta.WindowActor actor; + private GestureTracker default_gesture_tracker; + private GestureTracker last_gesture_tracker; + private HideTracker? hide_tracker; public PanelClone (WindowManager wm, PanelWindow panel) { @@ -42,20 +44,11 @@ public class Gala.PanelClone : Object { } construct { - clone = new SafeWindowClone (panel.window, true); - wm.ui_group.add_child (clone); + last_gesture_tracker = default_gesture_tracker = new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION); actor = (Meta.WindowActor) panel.window.get_compositor_private (); - // WindowActor position and Window position aren't necessarily the same. - // The clone needs the actor position - actor.notify["x"].connect (update_clone_position); - actor.notify["y"].connect (update_clone_position); - // Actor visibility might be changed by something else e.g. workspace switch - // but we want to keep it in sync with us - actor.notify["visible"].connect (update_visible); notify["panel-hidden"].connect (() => { - update_visible (); // When hidden changes schedule an update to make sure it's actually // correct since things might have changed during the animation if (hide_tracker != null) { @@ -63,69 +56,32 @@ public class Gala.PanelClone : Object { } }); - // Make sure the actor is visible once it's focused FIXME: better event not only focused - // https://github.com/elementary/gala/issues/2080 - panel.window.focused.connect (update_visible); - - update_visible (); - update_clone_position (); - Idle.add_once (() => { if (hide_mode == NEVER) { - show (); + show (default_gesture_tracker, false); } else { hide_tracker.schedule_update (); } }); } - private void update_visible () { - actor.visible = !panel_hidden; - - if (actor.visible && !wm.get_display ().get_monitor_in_fullscreen (panel.window.get_monitor ())) { - // The actor has just been revealed, make sure it's at the top - // https://github.com/elementary/gala/issues/2080 - actor.get_parent ().set_child_above_sibling (actor, null); - } - } - - private void update_clone_position () { - clone.set_position (calculate_clone_x (panel_hidden), calculate_clone_y (panel_hidden)); - } - - private float calculate_clone_x (bool hidden) { - switch (panel.anchor) { - case TOP: - case BOTTOM: - return actor.x; - default: - return 0; - } - } - - private float calculate_clone_y (bool hidden) { + private float calculate_y (bool hidden) { switch (panel.anchor) { case TOP: - return hidden ? actor.y - actor.height : actor.y; + return hidden ? -actor.height : 0; case BOTTOM: - return hidden ? actor.y + actor.height : actor.y; + return hidden ? actor.height : 0; default: return 0; } } - private int get_animation_duration () { - var fullscreen = wm.get_display ().get_monitor_in_fullscreen (panel.window.get_monitor ()); - var should_animate = AnimationsSettings.get_enable_animations () && !wm.workspace_view.is_opened () && !fullscreen; - return should_animate ? ANIMATION_DURATION : 0; - } - - private void hide () { - if (panel_hidden) { + private void hide (GestureTracker gesture_tracker, bool with_gesture) { + if (panel_hidden || last_gesture_tracker.recognizing) { return; } - panel_hidden = true; + last_gesture_tracker = gesture_tracker; if (!Meta.Util.is_wayland_compositor ()) { Utils.x11_set_window_pass_through (panel.window); @@ -136,39 +92,24 @@ public class Gala.PanelClone : Object { return; } - clone.visible = true; + new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (true)).start (with_gesture); - clone.save_easing_state (); - clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD); - clone.set_easing_duration (get_animation_duration ()); - clone.y = calculate_clone_y (true); - clone.restore_easing_state (); + gesture_tracker.add_success_callback (with_gesture, () => panel_hidden = true); } - private void show () { - if (!panel_hidden) { + private void show (GestureTracker gesture_tracker, bool with_gesture) { + if (!panel_hidden || last_gesture_tracker.recognizing) { return; } + last_gesture_tracker = gesture_tracker; + if (!Meta.Util.is_wayland_compositor ()) { Utils.x11_unset_window_pass_through (panel.window); } - clone.save_easing_state (); - clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD); - clone.set_easing_duration (get_animation_duration ()); - clone.y = calculate_clone_y (false); - clone.restore_easing_state (); - - unowned var y_transition = clone.get_transition ("y"); - if (y_transition != null) { - y_transition.completed.connect (() => { - clone.visible = false; - panel_hidden = false; - }); - } else { - clone.visible = false; - panel_hidden = false; - } + new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (false)).start (with_gesture); + + gesture_tracker.add_success_callback (with_gesture, () => panel_hidden = false); } } From 20bdf97b2832d614e125c746316de38524c4fa7a Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Tue, 24 Dec 2024 12:25:11 +0100 Subject: [PATCH 2/2] Introduce a shell group --- src/ShellClients/PanelClone.vala | 40 +++++++- src/ShellClients/PanelWindow.vala | 8 +- src/ShellClients/ShellClientsManager.vala | 12 ++- src/Widgets/MultitaskingView.vala | 111 +--------------------- src/WindowManager.vala | 83 ++++++++-------- 5 files changed, 93 insertions(+), 161 deletions(-) diff --git a/src/ShellClients/PanelClone.vala b/src/ShellClients/PanelClone.vala index c3a292363..0e4f63f24 100644 --- a/src/ShellClients/PanelClone.vala +++ b/src/ShellClients/PanelClone.vala @@ -8,7 +8,7 @@ public class Gala.PanelClone : Object { private const int ANIMATION_DURATION = 250; - public WindowManager wm { get; construct; } + public WindowManagerGala wm { get; construct; } public unowned PanelWindow panel { get; construct; } public Pantheon.Desktop.HideMode hide_mode { @@ -37,9 +37,11 @@ public class Gala.PanelClone : Object { private GestureTracker default_gesture_tracker; private GestureTracker last_gesture_tracker; + private bool force_hide = false; + private HideTracker? hide_tracker; - public PanelClone (WindowManager wm, PanelWindow panel) { + public PanelClone (WindowManagerGala wm, PanelWindow panel) { Object (wm: wm, panel: panel); } @@ -47,6 +49,8 @@ public class Gala.PanelClone : Object { last_gesture_tracker = default_gesture_tracker = new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION); actor = (Meta.WindowActor) panel.window.get_compositor_private (); + actor.get_parent ().remove_child (actor); + wm.shell_group.add_child (actor); notify["panel-hidden"].connect (() => { // When hidden changes schedule an update to make sure it's actually @@ -92,13 +96,16 @@ public class Gala.PanelClone : Object { return; } - new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (true)).start (with_gesture); + update_transients_visible (false); + + new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (true)) + .start (with_gesture, () => update_transients_visible (!panel_hidden)); gesture_tracker.add_success_callback (with_gesture, () => panel_hidden = true); } private void show (GestureTracker gesture_tracker, bool with_gesture) { - if (!panel_hidden || last_gesture_tracker.recognizing) { + if (!panel_hidden || force_hide || last_gesture_tracker.recognizing) { return; } @@ -108,8 +115,31 @@ public class Gala.PanelClone : Object { Utils.x11_unset_window_pass_through (panel.window); } - new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (false)).start (with_gesture); + new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (false)) + .start (with_gesture, () => update_transients_visible (!panel_hidden)); gesture_tracker.add_success_callback (with_gesture, () => panel_hidden = false); } + + private void update_transients_visible (bool visible) { + panel.window.foreach_transient ((transient) => { + var actor = (Meta.WindowActor) transient.get_compositor_private (); + + actor.visible = visible; + + return true; + }); + } + + public void set_force_hide (bool force_hide, GestureTracker gesture_tracker, bool with_gesture) { + this.force_hide = force_hide; + + if (force_hide) { + hide (gesture_tracker, with_gesture); + } else if (hide_mode == NEVER) { + show (gesture_tracker, with_gesture); + } else { + hide_tracker.update_overlap (gesture_tracker, with_gesture); + } + } } diff --git a/src/ShellClients/PanelWindow.vala b/src/ShellClients/PanelWindow.vala index 7e29bd656..5ef818d7f 100644 --- a/src/ShellClients/PanelWindow.vala +++ b/src/ShellClients/PanelWindow.vala @@ -8,7 +8,7 @@ public class Gala.PanelWindow : Object { private static HashTable window_struts = new HashTable (null, null); - public WindowManager wm { get; construct; } + public WindowManagerGala wm { get; construct; } public Meta.Window window { get; construct; } public Pantheon.Desktop.Anchor anchor { get; construct set; } @@ -19,7 +19,7 @@ public class Gala.PanelWindow : Object { private int width = -1; private int height = -1; - public PanelWindow (WindowManager wm, Meta.Window window, Pantheon.Desktop.Anchor anchor) { + public PanelWindow (WindowManagerGala wm, Meta.Window window, Pantheon.Desktop.Anchor anchor) { Object (wm: wm, window: window, anchor: anchor); } @@ -143,4 +143,8 @@ public class Gala.PanelWindow : Object { return TOP; } } + + public void set_force_hide (bool force_hide, GestureTracker gesture_tracker, bool with_gesture) { + clone.set_force_hide (force_hide, gesture_tracker, with_gesture); + } } diff --git a/src/ShellClients/ShellClientsManager.vala b/src/ShellClients/ShellClientsManager.vala index dfaa8b0ff..40a7876be 100644 --- a/src/ShellClients/ShellClientsManager.vala +++ b/src/ShellClients/ShellClientsManager.vala @@ -8,7 +8,7 @@ public class Gala.ShellClientsManager : Object { private static ShellClientsManager instance; - public static void init (WindowManager wm) { + public static void init (WindowManagerGala wm) { if (instance != null) { return; } @@ -20,7 +20,7 @@ public class Gala.ShellClientsManager : Object { return instance; } - public WindowManager wm { get; construct; } + public WindowManagerGala wm { get; construct; } private NotificationsClient notifications_client; private ManagedClient[] protocol_clients = {}; @@ -28,7 +28,7 @@ public class Gala.ShellClientsManager : Object { private GLib.HashTable panel_windows = new GLib.HashTable (null, null); private GLib.HashTable positioned_windows = new GLib.HashTable (null, null); - private ShellClientsManager (WindowManager wm) { + private ShellClientsManager (WindowManagerGala wm) { Object (wm: wm); } @@ -207,6 +207,12 @@ public class Gala.ShellClientsManager : Object { return positioned; } + public void set_force_hide_panels (bool force_hide, GestureTracker gesture_tracker, bool with_gesture) { + foreach (var panel in panel_windows.get_values ()) { + panel.set_force_hide (force_hide, gesture_tracker, with_gesture); + } + } + //X11 only private void parse_mutter_hints (Meta.Window window) requires (!Meta.Util.is_wayland_compositor ()) { if (window.mutter_hints == null) { diff --git a/src/Widgets/MultitaskingView.vala b/src/Widgets/MultitaskingView.vala index 6c00b783f..6f94e3fb6 100644 --- a/src/Widgets/MultitaskingView.vala +++ b/src/Widgets/MultitaskingView.vala @@ -39,7 +39,6 @@ namespace Gala { private IconGroupContainer icon_groups; private Clutter.Actor workspaces; - private Clutter.Actor dock_clones; private Clutter.Actor primary_monitor_container; private Clutter.BrightnessContrastEffect brightness_effect; @@ -83,8 +82,6 @@ namespace Gala { icon_groups = new IconGroupContainer (display.get_monitor_scale (display.get_primary_monitor ())); - dock_clones = new Clutter.Actor (); - brightness_effect = new Clutter.BrightnessContrastEffect (); update_brightness_effect (); @@ -101,7 +98,6 @@ namespace Gala { primary_monitor_container.add_child (icon_groups); primary_monitor_container.add_child (workspaces); add_child (primary_monitor_container); - add_child (dock_clones); unowned var manager = display.get_workspace_manager (); manager.workspace_added.connect (add_workspace); @@ -675,9 +671,9 @@ namespace Gala { } if (opening) { - show_docks (with_gesture, is_cancel_animation); + ShellClientsManager.get_instance ().set_force_hide_panels (true, multitasking_gesture_tracker, with_gesture); } else { - hide_docks (with_gesture, is_cancel_animation); + ShellClientsManager.get_instance ().set_force_hide_panels (false, multitasking_gesture_tracker, with_gesture); } GestureTracker.OnEnd on_animation_end = (percentage, completions) => { @@ -694,8 +690,6 @@ namespace Gala { wm.window_group.show (); wm.top_window_group.show (); - dock_clones.destroy_all_children (); - wm.pop_modal (modal_proxy); } @@ -716,107 +710,6 @@ namespace Gala { } } - private void show_docks (bool with_gesture, bool is_cancel_animation) { - unowned GLib.List window_actors = display.get_window_actors (); - foreach (unowned Meta.WindowActor actor in window_actors) { - const int MAX_OFFSET = 200; - - if (actor.is_destroyed () || !actor.visible) { - continue; - } - - unowned Meta.Window window = actor.get_meta_window (); - var monitor = window.get_monitor (); - - if (window.window_type != Meta.WindowType.DOCK) { - continue; - } - - if (NotificationStack.is_notification (window)) { - continue; - } - - if (display.get_monitor_in_fullscreen (monitor)) { - continue; - } - - var monitor_geom = display.get_monitor_geometry (monitor); - - var window_geom = window.get_frame_rect (); - var top = monitor_geom.y + MAX_OFFSET > window_geom.y; - var bottom = monitor_geom.y + monitor_geom.height - MAX_OFFSET < window_geom.y; - - if (!top && !bottom) { - continue; - } - - var initial_x = actor.x; - var initial_y = actor.y; - var target_y = (top) - ? actor.y - actor.height - : actor.y + actor.height; - - var clone = new SafeWindowClone (window, true); - dock_clones.add_child (clone); - - clone.set_position (initial_x, initial_y); - - GestureTracker.OnUpdate on_animation_update = (percentage) => { - var y = GestureTracker.animation_value (initial_y, target_y, percentage); - clone.y = y; - }; - - GestureTracker.OnEnd on_animation_end = (percentage, completions) => { - if (completions == 0) { - return; - } - - clone.save_easing_state (); - clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD); - clone.set_easing_duration ((!is_cancel_animation && AnimationsSettings.get_enable_animations ()) ? ANIMATION_DURATION : 0); - clone.y = target_y; - clone.restore_easing_state (); - }; - - if (!with_gesture || !AnimationsSettings.get_enable_animations ()) { - on_animation_end (1, 1, 0); - } else { - multitasking_gesture_tracker.connect_handlers (null, (owned) on_animation_update, (owned) on_animation_end); - } - } - } - - private void hide_docks (bool with_gesture, bool is_cancel_animation) { - foreach (unowned var child in dock_clones.get_children ()) { - var dock = (Clutter.Clone) child; - var initial_y = dock.y; - var target_y = dock.source.y; - - GestureTracker.OnUpdate on_animation_update = (percentage) => { - var y = GestureTracker.animation_value (initial_y, target_y, percentage); - dock.y = y; - }; - - GestureTracker.OnEnd on_animation_end = (percentage, completions) => { - if (completions == 0) { - return; - } - - dock.save_easing_state (); - dock.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD); - dock.set_easing_duration (AnimationsSettings.get_animation_duration (ANIMATION_DURATION)); - dock.y = target_y; - dock.restore_easing_state (); - }; - - if (!with_gesture || !AnimationsSettings.get_enable_animations ()) { - on_animation_end (1, 1, 0); - } else { - multitasking_gesture_tracker.connect_handlers (null, (owned) on_animation_update, (owned) on_animation_end); - } - } - } - private bool keybinding_filter (Meta.KeyBinding binding) { var action = Meta.Prefs.get_keybinding_action (binding.get_name ()); diff --git a/src/WindowManager.vala b/src/WindowManager.vala index 75b488b78..6cee0cde3 100644 --- a/src/WindowManager.vala +++ b/src/WindowManager.vala @@ -37,7 +37,7 @@ namespace Gala { */ public Clutter.Actor top_window_group { get; protected set; } - public Clutter.Actor notification_group { get; protected set; } + public Clutter.Actor shell_group { get; private set; } /** * {@inheritDoc} @@ -104,8 +104,6 @@ namespace Gala { private bool animating_switch_workspace = false; private bool switch_workspace_with_gesture = false; - private signal void window_created (Meta.Window window); - /** * Amount of pixels to move on the nudge animation. */ @@ -253,14 +251,6 @@ namespace Gala { stage.remove_child (top_window_group); ui_group.add_child (top_window_group); -#if HAS_MUTTER44 - var feedback_group = display.get_compositor ().get_feedback_group (); -#else - var feedback_group = display.get_feedback_group (); -#endif - stage.remove_child (feedback_group); - ui_group.add_child (feedback_group); - // Initialize plugins and add default components if no plugin overrides them unowned var plugin_manager = PluginManager.get_default (); plugin_manager.initialize (this); @@ -293,8 +283,16 @@ namespace Gala { } // Add the remaining components that should be on top - notification_group = new Clutter.Actor (); - ui_group.add_child (notification_group); + shell_group = new Clutter.Actor (); + ui_group.add_child (shell_group); + +#if HAS_MUTTER44 + var feedback_group = display.get_compositor ().get_feedback_group (); +#else + var feedback_group = display.get_feedback_group (); +#endif + stage.remove_child (feedback_group); + ui_group.add_child (feedback_group); pointer_locator = new PointerLocator (display); ui_group.add_child (pointer_locator); @@ -381,12 +379,14 @@ namespace Gala { update_input_area (); - display.window_created.connect ((window) => window_created (window)); - var scroll_action = new SuperScrollAction (display); scroll_action.triggered.connect (handle_super_scroll); stage.add_action_full ("wm-super-scroll-action", CAPTURE, scroll_action); + display.window_created.connect ((window) => + InternalUtils.wait_for_window_actor_visible (window, check_shell_window) + ); + stage.show (); plugin_manager.load_waiting_plugins (); @@ -1164,6 +1164,20 @@ namespace Gala { show_window_menu (window, menu, rect.x, rect.y); } + private void check_shell_window (Meta.WindowActor actor) { + unowned var window = actor.get_meta_window (); + if (ShellClientsManager.get_instance ().is_positioned_window (window) + || NotificationStack.is_notification (window) + ) { + actor.get_parent ().remove_child (actor); + shell_group.add_child (actor); + } + + if (NotificationStack.is_notification (window)) { + notification_stack.show_notification (actor); + } + } + /* * effects */ @@ -1479,12 +1493,7 @@ namespace Gala { actor.remove_all_transitions (); actor.show (); - // Notifications are a special case and have to be always be handled - // (also regardless of the animation setting) if (NotificationStack.is_notification (window)) { - clutter_actor_reparent (actor, notification_group); - notification_stack.show_notification (actor); - map_completed (actor); return; } @@ -1888,7 +1897,6 @@ namespace Gala { private List? windows; private List? parents; private List? tmp_actors; - private ulong switch_workspace_window_created_id = 0; private Clutter.Actor? out_group; private Clutter.Actor? in_group; private Clutter.Actor? wallpaper; @@ -2002,8 +2010,9 @@ namespace Gala { if (!window.showing_on_its_workspace () || move_primary_only && !window.is_on_primary_monitor () || window == moving || - window == grabbed_window) { - + window == grabbed_window || + actor.get_parent () == shell_group + ) { continue; } @@ -2116,17 +2125,6 @@ namespace Gala { prepare_workspace_switch (from, to, direction); - // while a workspace is being switched mutter doesn't map windows - // TODO: currently only notifications are handled here, other windows should be too - switch_workspace_window_created_id = window_created.connect ((window) => { - if (NotificationStack.is_notification (window)) { - InternalUtils.wait_for_window_actor_visible (window, (actor) => { - clutter_actor_reparent (actor, notification_group); - notification_stack.show_notification (actor); - }); - } - }); - var animation_mode = Clutter.AnimationMode.EASE_OUT_CUBIC; var x2 = -in_group.x; @@ -2198,11 +2196,8 @@ namespace Gala { return; } - if (switch_workspace_window_created_id > 0) { - disconnect (switch_workspace_window_created_id); - switch_workspace_window_created_id = 0; - } end_switch_workspace (); + if (!is_nudge_animation) { switch_workspace_completed (); } @@ -2220,9 +2215,9 @@ namespace Gala { } } - private void end_switch_workspace () { - if (windows == null || parents == null) - return; + private bool end_switch_workspace () { + if ((windows == null || parents == null) && tmp_actors == null) + return false; unowned var display = get_display (); unowned var active_workspace = display.get_workspace_manager ().get_active_workspace (); @@ -2287,10 +2282,14 @@ namespace Gala { switch_workspace_with_gesture = false; animating_switch_workspace = false; + + return true; } public override void kill_switch_workspace () { - end_switch_workspace (); + if (end_switch_workspace ()) { + switch_workspace_completed (); + } } public override void locate_pointer () {