Skip to content

Commit c5b6451

Browse files
authored
WindowSwitcher: Use GestureController (#2302)
1 parent 305a6a4 commit c5b6451

File tree

2 files changed

+92
-111
lines changed

2 files changed

+92
-111
lines changed

src/Widgets/WindowSwitcher/WindowSwitcher.vala

Lines changed: 91 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@
77
* SPDX-License-Identifier: GPL-3.0-or-later
88
*/
99

10-
public class Gala.WindowSwitcher : CanvasActor {
10+
public class Gala.WindowSwitcher : CanvasActor, GestureTarget {
1111
public const int ICON_SIZE = 64;
1212
public const int WRAPPER_PADDING = 12;
1313

1414
private const string CAPTION_FONT_NAME = "Inter";
1515
private const int MIN_OFFSET = 64;
1616
private const int ANIMATION_DURATION = 200;
17-
// https://github.com/elementary/gala/issues/1317#issuecomment-982484415
18-
private const int GESTURE_RANGE_LIMIT = 10;
17+
private const double GESTURE_STEP = 0.1;
1918

20-
public Gala.WindowManager? wm { get; construct; }
21-
public GestureTracker gesture_tracker { get; construct; }
19+
public WindowManager wm { get; construct; }
2220
public bool opened { get; private set; default = false; }
2321

24-
private bool handling_gesture = false;
22+
public Clutter.Actor? actor { get { return this; } }
23+
24+
private GestureController gesture_controller;
2525
private int modifier_mask;
2626
private Gala.ModalProxy modal_proxy = null;
2727
private Drawing.StyleManager style_manager;
@@ -49,18 +49,25 @@ public class Gala.WindowSwitcher : CanvasActor {
4949
}
5050
}
5151

52+
private double previous_progress = 0d;
53+
5254
private float scaling_factor = 1.0f;
5355

54-
public WindowSwitcher (Gala.WindowManager wm, GestureTracker gesture_tracker) {
55-
Object (
56-
wm: wm,
57-
gesture_tracker: gesture_tracker
58-
);
56+
public WindowSwitcher (WindowManager wm) {
57+
Object (wm: wm);
5958
}
6059

6160
construct {
6261
style_manager = Drawing.StyleManager.get_instance ();
6362

63+
gesture_controller = new GestureController (SWITCH_WINDOWS, this) {
64+
overshoot_upper_clamp = int.MAX,
65+
overshoot_lower_clamp = int.MIN,
66+
snap = false
67+
};
68+
gesture_controller.enable_touchpad ();
69+
gesture_controller.notify["recognizing"].connect (recognizing_changed);
70+
6471
container = new Clutter.Actor () {
6572
reactive = true,
6673
#if HAS_MUTTER46
@@ -220,12 +227,55 @@ public class Gala.WindowSwitcher : CanvasActor {
220227
ctx.restore ();
221228
}
222229

230+
public override void propagate (UpdateType update_type, GestureAction action, double progress) {
231+
if (update_type != UPDATE || container.get_n_children () == 0) {
232+
return;
233+
}
234+
235+
var is_step = ((int) (previous_progress / GESTURE_STEP) - (int) (progress / GESTURE_STEP)).abs () >= 1;
236+
237+
previous_progress = progress;
238+
239+
if (container.get_n_children () == 1 && current_icon != null && is_step) {
240+
InternalUtils.bell_notify (wm.get_display ());
241+
return;
242+
}
243+
244+
var current_index = (int) (progress / GESTURE_STEP) % container.get_n_children ();
245+
246+
if (current_index < 0) {
247+
current_index = container.get_n_children () + current_index;
248+
}
249+
250+
var new_icon = (WindowSwitcherIcon) container.get_child_at_index (current_index);
251+
if (new_icon != current_icon) {
252+
current_icon = new_icon;
253+
}
254+
}
255+
256+
private void select_icon (WindowSwitcherIcon? icon) {
257+
if (icon == null) {
258+
gesture_controller.progress = 0;
259+
current_icon = null;
260+
return;
261+
}
262+
263+
int index = 0;
264+
for (var child = container.get_first_child (); child != null; child = child.get_next_sibling ()) {
265+
if (child == icon) {
266+
gesture_controller.progress = index * GESTURE_STEP;
267+
break;
268+
}
269+
index++;
270+
}
271+
}
272+
223273
[CCode (instance_pos = -1)]
224274
public void handle_switch_windows (
225275
Meta.Display display, Meta.Window? window,
226276
Clutter.KeyEvent event, Meta.KeyBinding binding
227277
) {
228-
if (handling_gesture) {
278+
if (gesture_controller.recognizing) {
229279
return;
230280
}
231281

@@ -264,83 +314,55 @@ public class Gala.WindowSwitcher : CanvasActor {
264314
next_window (backward);
265315
}
266316

267-
public void handle_gesture (GestureDirection direction) {
268-
handling_gesture = true;
317+
private void recognizing_changed () {
318+
if (gesture_controller.recognizing) {
319+
unowned var display = wm.get_display ();
320+
unowned var workspace_manager = display.get_workspace_manager ();
321+
unowned var active_workspace = workspace_manager.get_active_workspace ();
269322

270-
unowned var display = wm.get_display ();
271-
unowned var workspace_manager = display.get_workspace_manager ();
272-
unowned var active_workspace = workspace_manager.get_active_workspace ();
273-
274-
var windows_exist = collect_all_windows (display, active_workspace);
275-
if (!windows_exist) {
276-
return;
277-
}
278-
open_switcher ();
279-
280-
// if direction == LEFT we need to move to the end of the list first, thats why last_window_index is set to -1
281-
var last_window_index = direction == RIGHT ? 0 : -1;
282-
GestureTracker.OnUpdate on_animation_update = (percentage) => {
283-
var window_index = GestureTracker.animation_value (0, GESTURE_RANGE_LIMIT, percentage, true);
284-
285-
if (window_index >= container.get_n_children ()) {
323+
var windows_exist = collect_all_windows (display, active_workspace);
324+
if (!windows_exist) {
286325
return;
287326
}
288-
289-
if (window_index > last_window_index) {
290-
while (last_window_index < window_index) {
291-
next_window (direction == LEFT);
292-
last_window_index++;
293-
}
294-
} else if (window_index < last_window_index) {
295-
while (last_window_index > window_index) {
296-
next_window (direction == RIGHT);
297-
last_window_index--;
298-
}
299-
}
300-
};
301-
302-
GestureTracker.OnEnd on_animation_end = (percentage, cancel_action, calculated_duration) => {
303-
handling_gesture = false;
327+
open_switcher ();
328+
} else {
304329
close_switcher (wm.get_display ().get_current_time ());
305-
};
306-
307-
gesture_tracker.connect_handlers (null, (owned) on_animation_update, (owned) on_animation_end);
330+
}
308331
}
309332

310333
private bool collect_all_windows (Meta.Display display, Meta.Workspace? workspace) {
334+
select_icon (null);
335+
311336
var windows = display.get_tab_list (Meta.TabList.NORMAL, workspace);
312337
if (windows == null) {
313338
return false;
314339
}
315340

316-
unowned var current_window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
317-
if (current_window == null) {
318-
current_icon = null;
319-
}
320-
321341
container.remove_all_children ();
322342

343+
unowned var current_window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
323344
foreach (unowned var window in windows) {
324345
var icon = new WindowSwitcherIcon (window, ICON_SIZE, scaling_factor);
346+
add_icon (icon);
347+
325348
if (window == current_window) {
326-
current_icon = icon;
349+
select_icon (icon);
327350
}
328-
329-
add_icon (icon);
330351
}
331352

332353
return true;
333354
}
334355

335356
private bool collect_current_windows (Meta.Display display, Meta.Workspace? workspace) {
357+
select_icon (null);
358+
336359
var windows = display.get_tab_list (Meta.TabList.NORMAL, workspace);
337360
if (windows == null) {
338361
return false;
339362
}
340363

341364
unowned var current_window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
342365
if (current_window == null) {
343-
current_icon = null;
344366
return false;
345367
}
346368

@@ -351,11 +373,11 @@ public class Gala.WindowSwitcher : CanvasActor {
351373
foreach (unowned var window in windows) {
352374
if (window_tracker.get_app_for_window (window) == app) {
353375
var icon = new WindowSwitcherIcon (window, ICON_SIZE, scaling_factor);
376+
add_icon (icon);
377+
354378
if (window == current_window) {
355-
current_icon = icon;
379+
select_icon (icon);
356380
}
357-
358-
add_icon (icon);
359381
}
360382
}
361383

@@ -367,8 +389,8 @@ public class Gala.WindowSwitcher : CanvasActor {
367389
icon.get_accessible ().accessible_parent = container.get_accessible ();
368390

369391
icon.motion_event.connect ((_icon, event) => {
370-
if (current_icon != _icon && !handling_gesture) {
371-
current_icon = (WindowSwitcherIcon) _icon;
392+
if (current_icon != _icon && !gesture_controller.recognizing) {
393+
select_icon ((WindowSwitcherIcon) _icon);
372394
}
373395

374396
return Clutter.EVENT_PROPAGATE;
@@ -470,28 +492,7 @@ public class Gala.WindowSwitcher : CanvasActor {
470492
}
471493

472494
private void next_window (bool backward) {
473-
Clutter.Actor actor;
474-
475-
if (container.get_n_children () == 1 && current_icon != null) {
476-
InternalUtils.bell_notify (wm.get_display ());
477-
return;
478-
}
479-
480-
if (current_icon == null) {
481-
actor = container.get_first_child ();
482-
} else if (!backward) {
483-
actor = current_icon.get_next_sibling ();
484-
if (actor == null) {
485-
actor = container.get_first_child ();
486-
}
487-
} else {
488-
actor = current_icon.get_previous_sibling ();
489-
if (actor == null) {
490-
actor = container.get_last_child ();
491-
}
492-
}
493-
494-
current_icon = (WindowSwitcherIcon) actor;
495+
gesture_controller.progress += backward ? -GESTURE_STEP : GESTURE_STEP;
495496
}
496497

497498
private void update_caption_text () {
@@ -501,7 +502,7 @@ public class Gala.WindowSwitcher : CanvasActor {
501502
}
502503

503504
public override void key_focus_out () {
504-
if (!handling_gesture) {
505+
if (!gesture_controller.recognizing) {
505506
close_switcher (wm.get_display ().get_current_time ());
506507
}
507508
}
@@ -511,7 +512,7 @@ public class Gala.WindowSwitcher : CanvasActor {
511512
#else
512513
private bool container_mouse_release (Clutter.ButtonEvent event) {
513514
#endif
514-
if (opened && event.get_button () == Clutter.Button.PRIMARY && !handling_gesture) {
515+
if (opened && event.get_button () == Clutter.Button.PRIMARY && !gesture_controller.recognizing) {
515516
close_switcher (event.get_time ());
516517
}
517518

@@ -523,7 +524,7 @@ public class Gala.WindowSwitcher : CanvasActor {
523524
#else
524525
public override bool key_release_event (Clutter.KeyEvent event) {
525526
#endif
526-
if ((get_current_modifiers () & modifier_mask) == 0 && !handling_gesture) {
527+
if ((get_current_modifiers () & modifier_mask) == 0 && !gesture_controller.recognizing) {
527528
close_switcher (event.get_time ());
528529
}
529530

@@ -537,12 +538,12 @@ public class Gala.WindowSwitcher : CanvasActor {
537538
#endif
538539
switch (event.get_key_symbol ()) {
539540
case Clutter.Key.Right:
540-
if (!handling_gesture) {
541+
if (!gesture_controller.recognizing) {
541542
next_window (false);
542543
}
543544
return Clutter.EVENT_STOP;
544545
case Clutter.Key.Left:
545-
if (!handling_gesture) {
546+
if (!gesture_controller.recognizing) {
546547
next_window (true);
547548
}
548549
return Clutter.EVENT_STOP;

src/WindowManager.vala

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,7 @@ namespace Gala {
107107
private GLib.Settings behavior_settings;
108108
private GLib.Settings new_behavior_settings;
109109

110-
private GestureTracker gesture_tracker;
111-
112110
construct {
113-
gesture_tracker = new GestureTracker (AnimationDuration.WORKSPACE_SWITCH_MIN, AnimationDuration.WORKSPACE_SWITCH);
114-
gesture_tracker.enable_touchpad ();
115-
gesture_tracker.on_gesture_detected.connect (on_gesture_detected);
116-
gesture_tracker.on_gesture_handled.connect (on_gesture_handled);
117-
118111
info = Meta.PluginInfo () {name = "Gala", version = Config.VERSION, author = "Gala Developers",
119112
license = "GPLv3", description = "A nice elementary window manager"};
120113

@@ -258,7 +251,7 @@ namespace Gala {
258251
}
259252

260253
if (plugin_manager.window_switcher_provider == null) {
261-
window_switcher = new WindowSwitcher (this, gesture_tracker);
254+
window_switcher = new WindowSwitcher (this);
262255
ui_group.add_child (window_switcher);
263256

264257
Meta.KeyBinding.set_custom_handler ("switch-applications", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
@@ -568,19 +561,6 @@ namespace Gala {
568561
}
569562
}
570563

571-
private bool on_gesture_detected (Gesture gesture) {
572-
if (workspace_view.is_opened ()) {
573-
return false;
574-
}
575-
576-
return GestureSettings.get_action (gesture) == SWITCH_WINDOWS && !window_switcher.opened;
577-
}
578-
579-
private double on_gesture_handled (Gesture gesture, uint32 timestamp) {
580-
window_switcher.handle_gesture (gesture.direction);
581-
return 0;
582-
}
583-
584564
/**
585565
* {@inheritDoc}
586566
*/

0 commit comments

Comments
 (0)