diff --git a/src/Gestures/Gesture.vala b/src/Gestures/Gesture.vala index 9c0f13ed5..5eb38cf36 100644 --- a/src/Gestures/Gesture.vala +++ b/src/Gestures/Gesture.vala @@ -41,6 +41,7 @@ namespace Gala { SWITCH_WINDOWS, MULTITASKING_VIEW, DOCK, + ZOOM, N_ACTIONS } diff --git a/src/Gestures/GestureController.vala b/src/Gestures/GestureController.vala index a901d9b52..e3e8bd1f8 100644 --- a/src/Gestures/GestureController.vala +++ b/src/Gestures/GestureController.vala @@ -47,6 +47,12 @@ public class Gala.GestureController : Object { public double overshoot_lower_clamp { get; construct set; default = 0d; } public double overshoot_upper_clamp { get; construct set; default = 1d; } + /** + * When disabled gesture progress will stay where the gesture ended and not snap to full integers values. + * This will also cause the controller to emit smooth progress information even if animations are disabled. + */ + public bool snap { get; construct set; default = true; } + private double _progress = 0; public double progress { get { return _progress; } @@ -129,13 +135,13 @@ public class Gala.GestureController : Object { || backend == scroll_backend && GestureSettings.get_action (gesture) == NONE); if (recognizing) { - if (gesture.direction == UP || gesture.direction == RIGHT) { + if (gesture.direction == UP || gesture.direction == RIGHT || gesture.direction == OUT) { direction_multiplier = 1; } else { direction_multiplier = -1; } - if (!AnimationsSettings.get_enable_animations ()) { + if (snap && !AnimationsSettings.get_enable_animations ()) { prepare (); finish (0, progress + direction_multiplier); recognizing = false; @@ -188,17 +194,21 @@ public class Gala.GestureController : Object { return; } + recognizing = false; + progress += calculate_applied_delta (percentage, previous_delta); var to = progress; - if (velocity.abs () > SUCCESS_VELOCITY_THRESHOLD) { - to += (velocity > 0 ? direction_multiplier : -direction_multiplier) * 0.5; - } + if (snap) { + if (velocity.abs () > SUCCESS_VELOCITY_THRESHOLD) { + to += (velocity > 0 ? direction_multiplier : -direction_multiplier) * 0.5; + } - recognizing = false; + to = Math.round (to); + } - finish (velocity, Math.round (to)); + finish (velocity, to); previous_percentage = 0; previous_time = 0; diff --git a/src/Gestures/GestureSettings.vala b/src/Gestures/GestureSettings.vala index 5fc436288..0ef5ff39e 100644 --- a/src/Gestures/GestureSettings.vala +++ b/src/Gestures/GestureSettings.vala @@ -71,37 +71,53 @@ public class Gala.GestureSettings : Object { } public static GestureAction get_action (Gesture gesture) { - if (gesture.type == TOUCHPAD_SWIPE) { - var fingers = gesture.fingers; + var fingers = gesture.fingers; - if (gesture.direction == LEFT || gesture.direction == RIGHT) { - var three_finger_swipe_horizontal = get_string ("three-finger-swipe-horizontal"); - var four_finger_swipe_horizontal = get_string ("four-finger-swipe-horizontal"); + switch (gesture.type) { + case TOUCHPAD_SWIPE: + if (gesture.direction == LEFT || gesture.direction == RIGHT) { + var three_finger_swipe_horizontal = get_string ("three-finger-swipe-horizontal"); + var four_finger_swipe_horizontal = get_string ("four-finger-swipe-horizontal"); - if (fingers == 3 && three_finger_swipe_horizontal == "switch-to-workspace" || - fingers == 4 && four_finger_swipe_horizontal == "switch-to-workspace") { - return SWITCH_WORKSPACE; - } + if (fingers == 3 && three_finger_swipe_horizontal == "switch-to-workspace" || + fingers == 4 && four_finger_swipe_horizontal == "switch-to-workspace") { + return SWITCH_WORKSPACE; + } + + if (fingers == 3 && three_finger_swipe_horizontal == "move-to-workspace" || + fingers == 4 && four_finger_swipe_horizontal == "move-to-workspace") { + return MOVE_TO_WORKSPACE; + } - if (fingers == 3 && three_finger_swipe_horizontal == "move-to-workspace" || - fingers == 4 && four_finger_swipe_horizontal == "move-to-workspace") { - return MOVE_TO_WORKSPACE; - } + if (fingers == 3 && three_finger_swipe_horizontal == "switch-windows" || + fingers == 4 && four_finger_swipe_horizontal == "switch-windows") { + return SWITCH_WINDOWS; + } + } else if (gesture.direction == UP || gesture.direction == DOWN) { + var three_finger_swipe_up = get_string ("three-finger-swipe-up"); + var four_finger_swipe_up = get_string ("four-finger-swipe-up"); - if (fingers == 3 && three_finger_swipe_horizontal == "switch-windows" || - fingers == 4 && four_finger_swipe_horizontal == "switch-windows") { - return SWITCH_WINDOWS; + if (fingers == 3 && three_finger_swipe_up == "multitasking-view" || + fingers == 4 && four_finger_swipe_up == "multitasking-view") { + return MULTITASKING_VIEW; + } } - } else if (gesture.direction == UP || gesture.direction == DOWN) { - var three_finger_swipe_up = get_string ("three-finger-swipe-up"); - var four_finger_swipe_up = get_string ("four-finger-swipe-up"); + break; - if (fingers == 3 && three_finger_swipe_up == "multitasking-view" || - fingers == 4 && four_finger_swipe_up == "multitasking-view") { - return MULTITASKING_VIEW; + case TOUCHPAD_PINCH: + var three_finger_pinch = get_string ("three-finger-pinch"); + var four_finger_pinch = get_string ("four-finger-pinch"); + + if (fingers == 3 && three_finger_pinch == "zoom" + || fingers == 4 && four_finger_pinch == "zoom" + ) { + return ZOOM; } - } + break; + + default: + break; } return NONE; diff --git a/src/Zoom.vala b/src/Zoom.vala index 84a64de43..ba33d933b 100644 --- a/src/Zoom.vala +++ b/src/Zoom.vala @@ -5,7 +5,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -public class Gala.Zoom : Object { +public class Gala.Zoom : Object, GestureTarget { private const float MIN_ZOOM = 1.0f; private const float MAX_ZOOM = 10.0f; private const float SHORTCUT_DELTA = 0.5f; @@ -14,11 +14,15 @@ public class Gala.Zoom : Object { public WindowManager wm { get; construct; } + public Clutter.Actor? actor { get { return wm.ui_group; } } + private uint mouse_poll_timer = 0; private float current_zoom = MIN_ZOOM; private ulong wins_handler_id = 0UL; - private GestureTracker gesture_tracker; + private GestureController gesture_controller; + private double current_commit = 0; + private GLib.Settings behavior_settings; public Zoom (WindowManager wm) { @@ -30,10 +34,10 @@ public class Gala.Zoom : Object { display.add_keybinding ("zoom-in", schema, Meta.KeyBindingFlags.NONE, (Meta.KeyHandlerFunc) zoom_in); display.add_keybinding ("zoom-out", schema, Meta.KeyBindingFlags.NONE, (Meta.KeyHandlerFunc) zoom_out); - gesture_tracker = new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION); - gesture_tracker.enable_touchpad (); - gesture_tracker.on_gesture_detected.connect (on_gesture_detected); - gesture_tracker.on_gesture_handled.connect (on_gesture_handled); + gesture_controller = new GestureController (ZOOM, this) { + snap = false + }; + gesture_controller.enable_touchpad (); behavior_settings = new GLib.Settings ("io.elementary.desktop.wm.behavior"); @@ -60,29 +64,13 @@ public class Gala.Zoom : Object { [CCode (instance_pos = -1)] private void zoom_in (Meta.Display display, Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding) { - zoom (SHORTCUT_DELTA, true, AnimationsSettings.get_enable_animations ()); + zoom (SHORTCUT_DELTA, true); } [CCode (instance_pos = -1)] private void zoom_out (Meta.Display display, Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding) { - zoom (-SHORTCUT_DELTA, true, AnimationsSettings.get_enable_animations ()); - } - - private bool on_gesture_detected (Gesture gesture) { - if (gesture.type != Clutter.EventType.TOUCHPAD_PINCH || - (gesture.direction != GestureDirection.IN && gesture.direction != GestureDirection.OUT) - ) { - return false; - } - - if ((gesture.fingers == 3 && GestureSettings.get_string ("three-finger-pinch") == "zoom") || - (gesture.fingers == 4 && GestureSettings.get_string ("four-finger-pinch") == "zoom") - ) { - return true; - } - - return false; + zoom (-SHORTCUT_DELTA, true); } private bool handle_super_scroll (uint32 timestamp, double dx, double dy) { @@ -93,38 +81,51 @@ public class Gala.Zoom : Object { var d = dx.abs () > dy.abs () ? dx : dy; if (d > 0) { - zoom (SHORTCUT_DELTA, true, AnimationsSettings.get_enable_animations ()); + zoom (SHORTCUT_DELTA, true); } else if (d < 0) { - zoom (-SHORTCUT_DELTA, true, AnimationsSettings.get_enable_animations ()); + zoom (-SHORTCUT_DELTA, true); } return Clutter.EVENT_STOP; } - private double on_gesture_handled (Gesture gesture, uint32 timestamp) { - var initial_zoom = current_zoom; - var target_zoom = (gesture.direction == GestureDirection.IN) - ? initial_zoom - MAX_ZOOM - : initial_zoom + MAX_ZOOM; - - GestureTracker.OnUpdate on_animation_update = (percentage) => { - var zoom_level = GestureTracker.animation_value (initial_zoom, target_zoom, percentage); - var delta = zoom_level - current_zoom; - - if (!AnimationsSettings.get_enable_animations ()) { - if (delta.abs () >= SHORTCUT_DELTA) { - delta = (delta > 0) ? SHORTCUT_DELTA : -SHORTCUT_DELTA; - } else { - delta = 0; - } + private void zoom (float delta, bool play_sound) { + // Nothing to do if zooming out of our bounds is requested + if ((current_zoom <= MIN_ZOOM && delta < 0) || (current_zoom >= MAX_ZOOM && delta >= 0)) { + if (play_sound) { + InternalUtils.bell_notify (wm.get_display ()); } + return; + } - zoom (delta, false, false); - }; + gesture_controller.goto (current_commit + (delta / 10)); + } + + public override void propagate (UpdateType update_type, GestureAction action, double progress) { + switch (update_type) { + case COMMIT: + current_commit = progress; + break; + + case UPDATE: + var target_zoom = (float) progress * 10 + 1; + if (!AnimationsSettings.get_enable_animations ()) { + var delta = target_zoom - current_zoom; + if (delta.abs () >= SHORTCUT_DELTA - float.EPSILON) { + target_zoom = current_zoom + ((delta > 0) ? SHORTCUT_DELTA : -SHORTCUT_DELTA); + } else { + return; + } + } - gesture_tracker.connect_handlers (null, (owned) on_animation_update, null); + current_zoom = target_zoom; + update_ui (); - return 0; + break; + + default: + break; + } } private inline Graphene.Point compute_new_pivot_point () { @@ -139,15 +140,7 @@ public class Gala.Zoom : Object { return new_pivot; } - private void zoom (float delta, bool play_sound, bool animate) { - // Nothing to do if zooming out of our bounds is requested - if ((current_zoom <= MIN_ZOOM && delta < 0) || (current_zoom >= MAX_ZOOM && delta >= 0)) { - if (play_sound) { - InternalUtils.bell_notify (wm.get_display ()); - } - return; - } - + private void update_ui () { unowned var wins = wm.ui_group; // Add timer to poll current mouse position to reposition window-group // to show requested zoomed area @@ -169,9 +162,6 @@ public class Gala.Zoom : Object { }); } - current_zoom += delta; - var animation_duration = animate ? ANIMATION_DURATION : 0; - if (wins_handler_id > 0) { wins.disconnect (wins_handler_id); wins_handler_id = 0; @@ -185,29 +175,12 @@ public class Gala.Zoom : Object { mouse_poll_timer = 0; } - wins.save_easing_state (); - wins.set_easing_mode (Clutter.AnimationMode.EASE_OUT_CUBIC); - wins.set_easing_duration (animation_duration); wins.set_scale (MIN_ZOOM, MIN_ZOOM); - wins.restore_easing_state (); - - if (animate) { - wins_handler_id = wins.transitions_completed.connect (() => { - wins.disconnect (wins_handler_id); - wins_handler_id = 0; - wins.set_pivot_point (0.0f, 0.0f); - }); - } else { - wins.set_pivot_point (0.0f, 0.0f); - } + wins.set_pivot_point (0.0f, 0.0f); return; } - wins.save_easing_state (); - wins.set_easing_mode (Clutter.AnimationMode.EASE_OUT_CUBIC); - wins.set_easing_duration (animation_duration); wins.set_scale (current_zoom, current_zoom); - wins.restore_easing_state (); } }