Skip to content

Commit 0f0b50a

Browse files
committed
ShellClients: Allow force hiding all panels
This is e.g. used by the multitasking view. It also supports hiding with gesture
1 parent 4f38089 commit 0f0b50a

File tree

7 files changed

+88
-169
lines changed

7 files changed

+88
-169
lines changed

src/Gestures/GesturePropertyTransition.vala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* with easing without a gesture. Respects the enable animation setting.
1111
*/
1212
public class Gala.GesturePropertyTransition : Object {
13-
public delegate void DoneCallback ();
13+
public delegate void DoneCallback (bool cancel_action);
1414

1515
/**
1616
* The actor whose property will be animated.
@@ -90,13 +90,13 @@ public class Gala.GesturePropertyTransition : Object {
9090

9191
if (actual_from_value.type () != current_value.type ()) {
9292
warning ("from_value of type %s is not of the same type as the property %s which is %s. Can't animate.", from_value.type_name (), property, current_value.type_name ());
93-
finish ();
93+
finish (true);
9494
return;
9595
}
9696

9797
if (current_value.type () != to_value.type ()) {
9898
warning ("to_value of type %s is not of the same type as the property %s which is %s. Can't animate.", to_value.type_name (), property, current_value.type_name ());
99-
finish ();
99+
finish (true);
100100
return;
101101
}
102102

@@ -118,9 +118,9 @@ public class Gala.GesturePropertyTransition : Object {
118118

119119
unowned var transition = actor.get_transition (property);
120120
if (transition == null) {
121-
finish ();
121+
finish (cancel_action);
122122
} else {
123-
transition.stopped.connect (finish);
123+
transition.stopped.connect (() => finish (cancel_action));
124124
}
125125
};
126126

@@ -147,9 +147,9 @@ public class Gala.GesturePropertyTransition : Object {
147147
}
148148
}
149149

150-
private void finish () {
150+
private void finish (bool cancel_action) {
151151
if (done_callback != null) {
152-
done_callback ();
152+
done_callback (cancel_action);
153153
}
154154

155155
unref ();

src/Gestures/GestureTracker.vala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class Gala.GestureTracker : Object {
6666
*/
6767
public bool enabled { get; set; default = true; }
6868

69+
public bool recognizing { get; private set; }
70+
6971
/**
7072
* Emitted when a new gesture is detected.
7173
* If the receiving code needs to handle this gesture, it should call to connect_handlers to
@@ -212,6 +214,7 @@ public class Gala.GestureTracker : Object {
212214
on_begin (percentage);
213215
}
214216

217+
recognizing = true;
215218
previous_percentage = percentage;
216219
previous_time = elapsed_time;
217220
}
@@ -248,6 +251,7 @@ public class Gala.GestureTracker : Object {
248251
}
249252

250253
disconnect_all_handlers ();
254+
recognizing = false;
251255
previous_percentage = 0;
252256
previous_time = 0;
253257
percentage_delta = 0;

src/ShellClients/HideTracker.vala

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,21 @@
66
*/
77

88
public class Gala.HideTracker : Object {
9+
private const int ANIMATION_DURATION = 250;
910
private const int BARRIER_OFFSET = 50; // Allow hot corner trigger
1011
private const int UPDATE_TIMEOUT = 200;
1112
private const int HIDE_DELAY = 500;
1213

13-
public signal void hide ();
14-
public signal void show ();
14+
public signal void hide (GestureTracker gesture_tracker, bool with_gesture);
15+
public signal void show (GestureTracker gesture_tracker, bool with_gesture);
1516

1617
public Meta.Display display { get; construct; }
1718
public unowned PanelWindow panel { get; construct; }
1819

1920
public Pantheon.Desktop.HideMode hide_mode { get; set; }
2021

2122
private Clutter.PanAction pan_action;
23+
private GestureTracker gesture_tracker; // Placeholder that will replace pan_action once the pan_backend gets merged
2224

2325
private bool hovered = false;
2426

@@ -79,6 +81,8 @@ public class Gala.HideTracker : Object {
7981

8082
display.get_workspace_manager ().active_workspace_changed.connect (schedule_update);
8183

84+
gesture_tracker = new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION);
85+
8286
pan_action = new Clutter.PanAction () {
8387
n_touch_points = 1,
8488
pan_axis = X_AXIS
@@ -146,13 +150,13 @@ public class Gala.HideTracker : Object {
146150
}
147151

148152
update_timeout_id = Timeout.add (UPDATE_TIMEOUT, () => {
149-
update_overlap ();
153+
update_overlap (gesture_tracker, false);
150154
update_timeout_id = 0;
151155
return Source.REMOVE;
152156
});
153157
}
154158

155-
private void update_overlap () {
159+
public void update_overlap (GestureTracker gesture_tracker, bool with_gesture) {
156160
overlap = false;
157161
focus_overlap = false;
158162
focus_maximized_overlap = false;
@@ -185,25 +189,25 @@ public class Gala.HideTracker : Object {
185189
focus_maximized_overlap = VERTICAL in window.get_maximized ();
186190
}
187191

188-
update_hidden ();
192+
update_hidden (gesture_tracker, with_gesture);
189193
}
190194

191-
private void update_hidden () {
195+
private void update_hidden (GestureTracker gesture_tracker, bool with_gesture) {
192196
switch (hide_mode) {
193197
case MAXIMIZED_FOCUS_WINDOW:
194-
toggle_display (focus_maximized_overlap);
198+
toggle_display (focus_maximized_overlap, gesture_tracker, with_gesture);
195199
break;
196200

197201
case OVERLAPPING_FOCUS_WINDOW:
198-
toggle_display (focus_overlap);
202+
toggle_display (focus_overlap, gesture_tracker, with_gesture);
199203
break;
200204

201205
case OVERLAPPING_WINDOW:
202-
toggle_display (overlap);
206+
toggle_display (overlap, gesture_tracker, with_gesture);
203207
break;
204208

205209
case ALWAYS:
206-
toggle_display (true);
210+
toggle_display (true, gesture_tracker, with_gesture);
207211
break;
208212

209213
default:
@@ -212,7 +216,11 @@ public class Gala.HideTracker : Object {
212216
}
213217
}
214218

215-
private void toggle_display (bool should_hide) {
219+
private void toggle_display (bool should_hide, GestureTracker gesture_tracker, bool with_gesture) {
220+
if (display.get_monitor_in_fullscreen (panel.window.get_monitor ())) {
221+
return;
222+
}
223+
216224
#if HAS_MUTTER45
217225
hovered = panel.window.has_pointer ();
218226
#else
@@ -222,7 +230,7 @@ public class Gala.HideTracker : Object {
222230
if (should_hide && !hovered && !panel.window.has_focus ()) {
223231
trigger_hide ();
224232
} else {
225-
trigger_show ();
233+
trigger_show (gesture_tracker, with_gesture);
226234
}
227235
}
228236

@@ -241,7 +249,7 @@ public class Gala.HideTracker : Object {
241249
}
242250

243251
hide_timeout_id = Timeout.add_once (HIDE_DELAY, () => {
244-
hide ();
252+
hide (gesture_tracker, false);
245253
hide_timeout_id = 0;
246254
});
247255
}
@@ -253,9 +261,9 @@ public class Gala.HideTracker : Object {
253261
}
254262
}
255263

256-
private void trigger_show () {
264+
private void trigger_show (GestureTracker gesture_tracker, bool with_gesture) {
257265
reset_hide_timeout ();
258-
show ();
266+
show (gesture_tracker, with_gesture);
259267
}
260268

261269
private bool check_valid_gesture () {
@@ -281,7 +289,7 @@ public class Gala.HideTracker : Object {
281289

282290
if (delta_y < 0) { // Only allow swipes upwards
283291
panel.window.focus (pan_action.get_last_event (0).get_time ());
284-
trigger_show ();
292+
trigger_show (gesture_tracker, false);
285293
}
286294

287295
return false;
@@ -325,7 +333,7 @@ public class Gala.HideTracker : Object {
325333
int.MAX
326334
);
327335

328-
barrier.trigger.connect (trigger_show);
336+
barrier.trigger.connect (() => trigger_show (gesture_tracker, false));
329337
}
330338

331339
#if HAS_MUTTER45
@@ -346,6 +354,6 @@ public class Gala.HideTracker : Object {
346354
int.MAX
347355
);
348356

349-
barrier.trigger.connect (trigger_show);
357+
barrier.trigger.connect (() => trigger_show (gesture_tracker, false));
350358
}
351359
}

src/ShellClients/PanelClone.vala

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class Gala.PanelClone : Object {
1818
set {
1919
if (value == NEVER) {
2020
hide_tracker = null;
21-
show ();
21+
show (new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION), false);
2222
return;
2323
} else if (hide_tracker == null) {
2424
hide_tracker = new HideTracker (wm.get_display (), panel);
@@ -35,6 +35,9 @@ public class Gala.PanelClone : Object {
3535
private SafeWindowClone clone;
3636
private Meta.WindowActor actor;
3737

38+
private GestureTracker? last_gesture_tracker;
39+
private bool force_hide = false;
40+
3841
private HideTracker? hide_tracker;
3942

4043
public PanelClone (WindowManager wm, PanelWindow panel) {
@@ -72,7 +75,7 @@ public class Gala.PanelClone : Object {
7275

7376
Idle.add_once (() => {
7477
if (hide_mode == NEVER) {
75-
show ();
78+
show (new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION), false);
7679
} else {
7780
hide_tracker.schedule_update ();
7881
}
@@ -114,17 +117,13 @@ public class Gala.PanelClone : Object {
114117
}
115118
}
116119

117-
private int get_animation_duration () {
118-
var fullscreen = wm.get_display ().get_monitor_in_fullscreen (panel.window.get_monitor ());
119-
var should_animate = AnimationsSettings.get_enable_animations () && !wm.workspace_view.is_opened () && !fullscreen;
120-
return should_animate ? ANIMATION_DURATION : 0;
121-
}
122-
123-
private void hide () {
124-
if (panel_hidden) {
120+
private void hide (GestureTracker gesture_tracker, bool with_gesture) {
121+
if (panel_hidden || last_gesture_tracker != null && last_gesture_tracker.recognizing) {
125122
return;
126123
}
127124

125+
last_gesture_tracker = gesture_tracker;
126+
128127
panel_hidden = true;
129128

130129
if (!Meta.Util.is_wayland_compositor ()) {
@@ -138,37 +137,43 @@ public class Gala.PanelClone : Object {
138137

139138
clone.visible = true;
140139

141-
clone.save_easing_state ();
142-
clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
143-
clone.set_easing_duration (get_animation_duration ());
144-
clone.y = calculate_clone_y (true);
145-
clone.restore_easing_state ();
140+
new GesturePropertyTransition (clone, gesture_tracker, "y", null, calculate_clone_y (true)).start (with_gesture);
146141
}
147142

148-
private void show () {
149-
if (!panel_hidden) {
143+
private void show (GestureTracker gesture_tracker, bool with_gesture) {
144+
if (!panel_hidden || force_hide || last_gesture_tracker != null && last_gesture_tracker.recognizing) {
150145
return;
151146
}
152147

148+
last_gesture_tracker = gesture_tracker;
149+
153150
if (!Meta.Util.is_wayland_compositor ()) {
154151
Utils.x11_unset_window_pass_through (panel.window);
155152
}
156153

157-
clone.save_easing_state ();
158-
clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
159-
clone.set_easing_duration (get_animation_duration ());
160-
clone.y = calculate_clone_y (false);
161-
clone.restore_easing_state ();
162-
163-
unowned var y_transition = clone.get_transition ("y");
164-
if (y_transition != null) {
165-
y_transition.completed.connect (() => {
166-
clone.visible = false;
167-
panel_hidden = false;
168-
});
154+
new GesturePropertyTransition (clone, gesture_tracker, "y", null, calculate_clone_y (false)).start (with_gesture, (cancel_action) => {
155+
if (!cancel_action) {
156+
// We need the small timeout because in the case that we're showing in sync with the multitasking view
157+
// we have to make sure that we hide the clone after the multitasking view was already hidden otherwise
158+
// it flickers because the actual window actors are hidden by the multitasking view
159+
Timeout.add_once (10, () => {
160+
force_hide = false;
161+
clone.visible = false;
162+
panel_hidden = false;
163+
});
164+
}
165+
});
166+
}
167+
168+
public void set_force_hide (bool force_hide, GestureTracker gesture_tracker, bool with_gesture) {
169+
this.force_hide = force_hide;
170+
171+
if (force_hide) {
172+
hide (gesture_tracker, with_gesture);
173+
} else if (hide_mode == NEVER) {
174+
show (gesture_tracker, with_gesture);
169175
} else {
170-
clone.visible = false;
171-
panel_hidden = false;
176+
hide_tracker.update_overlap (gesture_tracker, with_gesture);
172177
}
173178
}
174179
}

src/ShellClients/PanelWindow.vala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,8 @@ public class Gala.PanelWindow : Object {
143143
return TOP;
144144
}
145145
}
146+
147+
public void set_force_hide (bool force_hide, GestureTracker gesture_tracker, bool with_gesture) {
148+
clone.set_force_hide (force_hide, gesture_tracker, with_gesture);
149+
}
146150
}

src/ShellClients/ShellClientsManager.vala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ public class Gala.ShellClientsManager : Object {
207207
return positioned;
208208
}
209209

210+
public void set_force_hide_panels (bool force_hide, GestureTracker gesture_tracker, bool with_gesture) {
211+
foreach (var panel in panel_windows.get_values ()) {
212+
panel.set_force_hide (force_hide, gesture_tracker, with_gesture);
213+
}
214+
}
215+
210216
//X11 only
211217
private void parse_mutter_hints (Meta.Window window) requires (!Meta.Util.is_wayland_compositor ()) {
212218
if (window.mutter_hints == null) {

0 commit comments

Comments
 (0)