Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShellClients: Allow force hiding all panels #2150

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Gestures/GestureTracker.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -242,6 +261,7 @@ public class Gala.GestureTracker : Object {
on_begin (percentage);
}

recognizing = true;
previous_percentage = percentage;
previous_time = elapsed_time;
}
Expand Down Expand Up @@ -283,6 +303,7 @@ public class Gala.GestureTracker : Object {
}

disconnect_all_handlers ();
recognizing = false;
previous_percentage = 0;
previous_time = 0;
percentage_delta = 0;
Expand Down
45 changes: 25 additions & 20 deletions src/ShellClients/HideTracker.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand All @@ -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 () {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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);
}
}

Expand All @@ -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;
});
}
Expand All @@ -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 () {
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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));
}
}
122 changes: 39 additions & 83 deletions src/ShellClients/PanelClone.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
}
Expand All @@ -30,102 +30,61 @@ public class Gala.PanelClone : Object {
}
}

public bool panel_hidden { get; private set; default = true; }

private SafeWindowClone clone;
private Meta.WindowActor actor;

private bool panel_hidden = false;

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

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);
actor.get_parent ().remove_child (actor);
wm.shell_group.add_child (actor);

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) {
hide_tracker.schedule_update ();
}
});

// 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);
Expand All @@ -136,39 +95,36 @@ 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 || force_hide || 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;
});
new GesturePropertyTransition (actor, gesture_tracker, "translation-y", null, calculate_y (false)).start (with_gesture);

gesture_tracker.add_success_callback (with_gesture, () => panel_hidden = false);
}

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 {
clone.visible = false;
panel_hidden = false;
hide_tracker.update_overlap (gesture_tracker, with_gesture);
}
}
}
Loading
Loading