Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/Gestures/Gesture.vala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace Gala {
SWITCH_WINDOWS,
MULTITASKING_VIEW,
DOCK,
ZOOM,
N_ACTIONS
}

Expand Down
24 changes: 17 additions & 7 deletions src/Gestures/GestureController.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
62 changes: 39 additions & 23 deletions src/Gestures/GestureSettings.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
125 changes: 49 additions & 76 deletions src/Zoom.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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");

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