diff --git a/src/ShellClients/HideTracker.vala b/src/ShellClients/HideTracker.vala index 6a784e5f1..39c2121ec 100644 --- a/src/ShellClients/HideTracker.vala +++ b/src/ShellClients/HideTracker.vala @@ -6,14 +6,27 @@ */ public class Gala.HideTracker : Object { - private const uint UPDATE_TIMEOUT = 200; + private const int BARRIER_OFFSET = 50; // Allow hot corner trigger + private const int UPDATE_TIMEOUT = 200; + private const int HIDE_DELAY = 500; public signal void hide (); public signal void show (); public Meta.Display display { get; construct; } public unowned PanelWindow panel { get; construct; } - public Pantheon.Desktop.HideMode hide_mode { get; set; default = NEVER; } + + private Pantheon.Desktop.HideMode _hide_mode = NEVER; + public Pantheon.Desktop.HideMode hide_mode { + get { + return _hide_mode; + } + set { + _hide_mode = value; + + setup_barrier (); + } + } private Clutter.PanAction pan_action; @@ -25,12 +38,21 @@ public class Gala.HideTracker : Object { private Meta.Window current_focus_window; + private Barrier? barrier; + + private uint hide_timeout_id = 0; private uint update_timeout_id = 0; public HideTracker (Meta.Display display, PanelWindow panel) { Object (display: display, panel: panel); } + ~HideTracker () { + if (hide_timeout_id != 0) { + Source.remove (hide_timeout_id); + } + } + construct { // Can't be local otherwise we get a memory leak :( // See https://gitlab.gnome.org/GNOME/vala/-/issues/1548 @@ -163,10 +185,6 @@ public class Gala.HideTracker : Object { private void update_hidden () { switch (hide_mode) { - case NEVER: - toggle_display (false); - break; - case MAXIMIZED_FOCUS_WINDOW: toggle_display (focus_maximized_overlap); break; @@ -182,6 +200,10 @@ public class Gala.HideTracker : Object { case ALWAYS: toggle_display (true); break; + + default: + warning ("HideTracker: unsupported hide mode."); + break; } } @@ -196,23 +218,44 @@ public class Gala.HideTracker : Object { #endif if (should_hide && !hovered && !panel.window.has_focus ()) { - // Don't hide if we have transients, e.g. an open popover, dialog, etc. - var has_transients = false; - panel.window.foreach_transient (() => { - has_transients = true; - return false; - }); - - if (has_transients) { - return; - } + trigger_hide (); + } else { + trigger_show (); + } + } + + private void trigger_hide () { + // Don't hide if we have transients, e.g. an open popover, dialog, etc. + var has_transients = false; + panel.window.foreach_transient (() => { + has_transients = true; + return false; + }); + + if (has_transients) { + reset_hide_timeout (); + + return; + } + hide_timeout_id = Timeout.add_once (HIDE_DELAY, () => { hide (); - } else { - show (); + hide_timeout_id = 0; + }); + } + + private void reset_hide_timeout () { + if (hide_timeout_id != 0) { + Source.remove (hide_timeout_id); + hide_timeout_id = 0; } } + private void trigger_show () { + reset_hide_timeout (); + show (); + } + private bool check_valid_gesture () { if (panel.anchor != BOTTOM) { debug ("Swipe to reveal is currently only supported for bottom anchors"); @@ -236,9 +279,71 @@ public class Gala.HideTracker : Object { if (delta_y < 0) { // Only allow swipes upwards panel.window.focus (pan_action.get_last_event (0).get_time ()); - show (); + trigger_show (); } return false; } + + private void setup_barrier () { + var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ()); + var scale = display.get_monitor_scale (display.get_primary_monitor ()); + var offset = InternalUtils.scale_to_int (BARRIER_OFFSET, scale); + + switch (panel.anchor) { + case TOP: + setup_barrier_top (monitor_geom, offset); + break; + + case BOTTOM: + setup_barrier_bottom (monitor_geom, offset); + break; + + default: + warning ("Barrier side not supported yet"); + break; + } + } + +#if HAS_MUTTER45 + private void setup_barrier_top (Mtk.Rectangle monitor_geom, int offset) { +#else + private void setup_barrier_top (Meta.Rectangle monitor_geom, int offset) { +#endif + barrier = new Barrier ( + display.get_context ().get_backend (), + monitor_geom.x + offset, + monitor_geom.y, + monitor_geom.x + monitor_geom.width - offset, + monitor_geom.y, + POSITIVE_Y, + 0, + 0, + int.MAX, + int.MAX + ); + + barrier.trigger.connect (trigger_show); + } + +#if HAS_MUTTER45 + private void setup_barrier_bottom (Mtk.Rectangle monitor_geom, int offset) { +#else + private void setup_barrier_bottom (Meta.Rectangle monitor_geom, int offset) { +#endif + barrier = new Barrier ( + display.get_context ().get_backend (), + monitor_geom.x + offset, + monitor_geom.y + monitor_geom.height, + monitor_geom.x + monitor_geom.width - offset, + monitor_geom.y + monitor_geom.height, + NEGATIVE_Y, + 0, + 0, + int.MAX, + int.MAX + ); + + barrier.trigger.connect (trigger_show); + } } diff --git a/src/ShellClients/PanelClone.vala b/src/ShellClients/PanelClone.vala index 68f83070d..e089887b2 100644 --- a/src/ShellClients/PanelClone.vala +++ b/src/ShellClients/PanelClone.vala @@ -141,7 +141,7 @@ public class Gala.PanelClone : Object { clone.restore_easing_state (); } - public void show () { + private void show () { if (!panel_hidden) { return; } diff --git a/src/ShellClients/PanelWindow.vala b/src/ShellClients/PanelWindow.vala index 075f77bf9..5351cbe5a 100644 --- a/src/ShellClients/PanelWindow.vala +++ b/src/ShellClients/PanelWindow.vala @@ -6,8 +6,6 @@ */ public class Gala.PanelWindow : Object { - private const int BARRIER_OFFSET = 50; // Allow hot corner trigger - private static HashTable window_struts = new HashTable (null, null); public WindowManager wm { get; construct; } @@ -17,8 +15,6 @@ public class Gala.PanelWindow : Object { public Meta.Side anchor; - private Barrier? barrier; - private PanelClone clone; private uint idle_move_id = 0; @@ -42,8 +38,6 @@ public class Gala.PanelWindow : Object { Source.remove (idle_move_id); } - destroy_barrier (); - if (window_struts.remove (window)) { update_struts (); } @@ -159,13 +153,10 @@ public class Gala.PanelWindow : Object { public void set_hide_mode (Pantheon.Desktop.HideMode hide_mode) { clone.hide_mode = hide_mode; - destroy_barrier (); - if (hide_mode == NEVER) { make_exclusive (); } else { unmake_exclusive (); - setup_barrier (); } } @@ -208,71 +199,4 @@ public class Gala.PanelWindow : Object { update_struts (); } } - - private void destroy_barrier () { - barrier = null; - } - - private void setup_barrier () { - var display = wm.get_display (); - var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ()); - var scale = display.get_monitor_scale (display.get_primary_monitor ()); - var offset = InternalUtils.scale_to_int (BARRIER_OFFSET, scale); - - switch (anchor) { - case TOP: - setup_barrier_top (monitor_geom, offset); - break; - - case BOTTOM: - setup_barrier_bottom (monitor_geom, offset); - break; - - default: - warning ("Barrier side not supported yet"); - break; - } - } - -#if HAS_MUTTER45 - private void setup_barrier_top (Mtk.Rectangle monitor_geom, int offset) { -#else - private void setup_barrier_top (Meta.Rectangle monitor_geom, int offset) { -#endif - barrier = new Barrier ( - wm.get_display ().get_context ().get_backend (), - monitor_geom.x + offset, - monitor_geom.y, - monitor_geom.x + monitor_geom.width - offset, - monitor_geom.y, - POSITIVE_Y, - 0, - 0, - int.MAX, - int.MAX - ); - - barrier.trigger.connect (clone.show); - } - -#if HAS_MUTTER45 - private void setup_barrier_bottom (Mtk.Rectangle monitor_geom, int offset) { -#else - private void setup_barrier_bottom (Meta.Rectangle monitor_geom, int offset) { -#endif - barrier = new Barrier ( - wm.get_display ().get_context ().get_backend (), - monitor_geom.x + offset, - monitor_geom.y + monitor_geom.height, - monitor_geom.x + monitor_geom.width - offset, - monitor_geom.y + monitor_geom.height, - NEGATIVE_Y, - 0, - 0, - int.MAX, - int.MAX - ); - - barrier.trigger.connect (clone.show); - } }