mirror of
https://github.com/elementary/gala.git
synced 2024-08-16 18:40:27 +03:00
Add "Switch windows" gesture (#1802)
This commit is contained in:
parent
72b9e012f3
commit
2699c5a453
@ -355,6 +355,7 @@
|
||||
<value nick="none" value="0" />
|
||||
<value nick="switch-to-workspace" value="1" />
|
||||
<value nick="move-to-workspace" value="2" />
|
||||
<value nick="switch-windows" value="3" />
|
||||
</enum>
|
||||
<enum id="GestureSwipeUp">
|
||||
<value nick="none" value="0" />
|
||||
|
@ -10,15 +10,20 @@
|
||||
public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
public const int ICON_SIZE = 64;
|
||||
public const int WRAPPER_PADDING = 12;
|
||||
|
||||
private const string CAPTION_FONT_NAME = "Inter";
|
||||
private const int MIN_OFFSET = 64;
|
||||
private const int ANIMATION_DURATION = 200;
|
||||
|
||||
public bool opened { get; private set; default = false; }
|
||||
// https://github.com/elementary/gala/issues/1317#issuecomment-982484415
|
||||
private const int GESTURE_RANGE_LIMIT = 10;
|
||||
|
||||
public Gala.WindowManager? wm { get; construct; }
|
||||
private Gala.ModalProxy modal_proxy = null;
|
||||
public GestureTracker gesture_tracker { get; construct; }
|
||||
public bool opened { get; private set; default = false; }
|
||||
|
||||
private bool handling_gesture = false;
|
||||
private int modifier_mask;
|
||||
private Gala.ModalProxy modal_proxy = null;
|
||||
private Granite.Settings granite_settings;
|
||||
private Clutter.Canvas canvas;
|
||||
private Clutter.Actor container;
|
||||
@ -28,8 +33,6 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
private Gtk.StyleContext style_context;
|
||||
private unowned Gtk.CssProvider? dark_style_provider = null;
|
||||
|
||||
private int modifier_mask;
|
||||
|
||||
private WindowSwitcherIcon? _current_icon = null;
|
||||
private WindowSwitcherIcon? current_icon {
|
||||
get {
|
||||
@ -51,8 +54,11 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
|
||||
private float scaling_factor = 1.0f;
|
||||
|
||||
public WindowSwitcher (Gala.WindowManager wm) {
|
||||
Object (wm: wm);
|
||||
public WindowSwitcher (Gala.WindowManager wm, GestureTracker gesture_tracker) {
|
||||
Object (
|
||||
wm: wm,
|
||||
gesture_tracker: gesture_tracker
|
||||
);
|
||||
}
|
||||
|
||||
construct {
|
||||
@ -184,6 +190,10 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
Meta.Display display, Meta.Window? window,
|
||||
Clutter.KeyEvent event, Meta.KeyBinding binding
|
||||
) {
|
||||
if (handling_gesture) {
|
||||
return;
|
||||
}
|
||||
|
||||
var workspace = display.get_workspace_manager ().get_active_workspace ();
|
||||
|
||||
// copied from gnome-shell, finds the primary modifier in the mask
|
||||
@ -219,6 +229,49 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
next_window (backward);
|
||||
}
|
||||
|
||||
public void handle_gesture (GestureDirection direction) {
|
||||
handling_gesture = true;
|
||||
|
||||
unowned var display = wm.get_display ();
|
||||
unowned var workspace_manager = display.get_workspace_manager ();
|
||||
unowned var active_workspace = workspace_manager.get_active_workspace ();
|
||||
|
||||
var windows_exist = collect_all_windows (display, active_workspace);
|
||||
if (!windows_exist) {
|
||||
return;
|
||||
}
|
||||
open_switcher ();
|
||||
|
||||
// if direction == LEFT we need to move to the end of the list first, thats why last_window_index is set to -1
|
||||
var last_window_index = direction == RIGHT ? 0 : -1;
|
||||
GestureTracker.OnUpdate on_animation_update = (percentage) => {
|
||||
var window_index = GestureTracker.animation_value (0, GESTURE_RANGE_LIMIT, percentage, true);
|
||||
|
||||
if (window_index >= container.get_n_children ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_index > last_window_index) {
|
||||
while (last_window_index < window_index) {
|
||||
next_window (direction == LEFT);
|
||||
last_window_index++;
|
||||
}
|
||||
} else if (window_index < last_window_index) {
|
||||
while (last_window_index > window_index) {
|
||||
next_window (direction == RIGHT);
|
||||
last_window_index--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GestureTracker.OnEnd on_animation_end = (percentage, cancel_action, calculated_duration) => {
|
||||
handling_gesture = false;
|
||||
close_switcher (wm.get_display ().get_current_time ());
|
||||
};
|
||||
|
||||
gesture_tracker.connect_handlers (null, (owned) on_animation_update, (owned) on_animation_end);
|
||||
}
|
||||
|
||||
private bool collect_all_windows (Meta.Display display, Meta.Workspace? workspace) {
|
||||
var windows = display.get_tab_list (Meta.TabList.NORMAL, workspace);
|
||||
if (windows == null) {
|
||||
@ -319,11 +372,6 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
);
|
||||
|
||||
toggle_display (true);
|
||||
|
||||
// if we did not have the grab before the key was released, close immediately
|
||||
if ((get_current_modifiers () & modifier_mask) == 0) {
|
||||
close_switcher (wm.get_display ().get_current_time ());
|
||||
}
|
||||
}
|
||||
|
||||
private void toggle_display (bool show) {
|
||||
@ -381,7 +429,7 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
}
|
||||
|
||||
if (!cancel) {
|
||||
var workspace = window.get_workspace ();
|
||||
unowned var workspace = window.get_workspace ();
|
||||
if (workspace != wm.get_display ().get_workspace_manager ().get_active_workspace ()) {
|
||||
workspace.activate_with_focus (window, time);
|
||||
} else {
|
||||
@ -431,7 +479,9 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
}
|
||||
|
||||
public override void key_focus_out () {
|
||||
close_switcher (wm.get_display ().get_current_time ());
|
||||
if (!handling_gesture) {
|
||||
close_switcher (wm.get_display ().get_current_time ());
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_MUTTER45
|
||||
@ -439,16 +489,20 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
#else
|
||||
private bool container_motion_event (Clutter.MotionEvent event) {
|
||||
#endif
|
||||
if (handling_gesture) {
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
float x, y;
|
||||
event.get_coords (out x, out y);
|
||||
var actor = container.get_stage ().get_actor_at_pos (Clutter.PickMode.ALL, (int)x, (int)y);
|
||||
if (actor == null) {
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
var selected = actor as WindowSwitcherIcon;
|
||||
if (selected == null) {
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
if (current_icon != selected) {
|
||||
@ -463,7 +517,7 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
#else
|
||||
private bool container_mouse_release (Clutter.ButtonEvent event) {
|
||||
#endif
|
||||
if (opened && event.get_button () == Clutter.Button.PRIMARY) {
|
||||
if (opened && event.get_button () == Clutter.Button.PRIMARY && !handling_gesture) {
|
||||
close_switcher (event.get_time ());
|
||||
}
|
||||
|
||||
@ -475,7 +529,7 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
#else
|
||||
public override bool key_release_event (Clutter.KeyEvent event) {
|
||||
#endif
|
||||
if ((get_current_modifiers () & modifier_mask) == 0) {
|
||||
if ((get_current_modifiers () & modifier_mask) == 0 && !handling_gesture) {
|
||||
close_switcher (event.get_time ());
|
||||
}
|
||||
|
||||
@ -489,10 +543,14 @@ public class Gala.WindowSwitcher : Clutter.Actor {
|
||||
#endif
|
||||
switch (event.get_key_symbol ()) {
|
||||
case Clutter.Key.Right:
|
||||
next_window (false);
|
||||
if (!handling_gesture) {
|
||||
next_window (false);
|
||||
}
|
||||
return Clutter.EVENT_STOP;
|
||||
case Clutter.Key.Left:
|
||||
next_window (true);
|
||||
if (!handling_gesture) {
|
||||
next_window (true);
|
||||
}
|
||||
return Clutter.EVENT_STOP;
|
||||
case Clutter.Key.Escape:
|
||||
close_switcher (event.get_time (), true);
|
||||
|
@ -71,7 +71,7 @@ namespace Gala {
|
||||
|
||||
private Meta.PluginInfo info;
|
||||
|
||||
private WindowSwitcher? winswitcher = null;
|
||||
private WindowSwitcher? window_switcher = null;
|
||||
private ActivatableComponent? window_overview = null;
|
||||
|
||||
public ScreenSaverManager? screensaver { get; private set; }
|
||||
@ -332,15 +332,15 @@ namespace Gala {
|
||||
});
|
||||
|
||||
if (plugin_manager.window_switcher_provider == null) {
|
||||
winswitcher = new WindowSwitcher (this);
|
||||
ui_group.add_child (winswitcher);
|
||||
window_switcher = new WindowSwitcher (this, gesture_tracker);
|
||||
ui_group.add_child (window_switcher);
|
||||
|
||||
Meta.KeyBinding.set_custom_handler ("switch-applications", (Meta.KeyHandlerFunc) winswitcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-applications-backward", (Meta.KeyHandlerFunc) winswitcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-windows", (Meta.KeyHandlerFunc) winswitcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-windows-backward", (Meta.KeyHandlerFunc) winswitcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-group", (Meta.KeyHandlerFunc) winswitcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-group-backward", (Meta.KeyHandlerFunc) winswitcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-applications", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-applications-backward", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-windows", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-windows-backward", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-group", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
|
||||
Meta.KeyBinding.set_custom_handler ("switch-group-backward", (Meta.KeyHandlerFunc) window_switcher.handle_switch_windows);
|
||||
}
|
||||
|
||||
if (plugin_manager.window_overview_provider == null
|
||||
@ -530,12 +530,8 @@ namespace Gala {
|
||||
return;
|
||||
}
|
||||
|
||||
var can_handle_swipe = (
|
||||
gesture.type == Clutter.EventType.TOUCHPAD_SWIPE &&
|
||||
(gesture.direction == GestureDirection.LEFT || gesture.direction == GestureDirection.RIGHT)
|
||||
);
|
||||
|
||||
if (!can_handle_swipe) {
|
||||
if (gesture.type != Clutter.EventType.TOUCHPAD_SWIPE ||
|
||||
(gesture.direction != GestureDirection.LEFT && gesture.direction != GestureDirection.RIGHT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -550,6 +546,9 @@ namespace Gala {
|
||||
var three_fingers_move_to_workspace = fingers == 3 && three_finger_swipe_horizontal == "move-to-workspace";
|
||||
var four_fingers_move_to_workspace = fingers == 4 && four_finger_swipe_horizontal == "move-to-workspace";
|
||||
|
||||
var three_fingers_switch_windows = fingers == 3 && three_finger_swipe_horizontal == "switch-windows";
|
||||
var four_fingers_switch_windows = fingers == 4 && four_finger_swipe_horizontal == "switch-windows";
|
||||
|
||||
switch_workspace_with_gesture = three_fingers_switch_to_workspace || four_fingers_switch_to_workspace;
|
||||
if (switch_workspace_with_gesture) {
|
||||
var direction = gesture_tracker.settings.get_natural_scroll_direction (gesture);
|
||||
@ -572,6 +571,11 @@ namespace Gala {
|
||||
switch_to_next_workspace (direction);
|
||||
return;
|
||||
}
|
||||
|
||||
var switch_windows = three_fingers_switch_windows || four_fingers_switch_windows;
|
||||
if (switch_windows && !window_switcher.opened) {
|
||||
window_switcher.handle_gesture (gesture.direction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user