diff --git a/lib/Gestures/Backends/ToucheggBackend.vala b/lib/Gestures/Backends/ToucheggBackend.vala index c280efc09..137563024 100644 --- a/lib/Gestures/Backends/ToucheggBackend.vala +++ b/lib/Gestures/Backends/ToucheggBackend.vala @@ -180,7 +180,11 @@ private class Gala.ToucheggBackend : Object, GestureBackend { signal_params.get ("(uudiut)", out type, out direction, out percentage, out fingers, out performed_on_device_type, out elapsed_time); +#if HAS_MUTTER49 + if (Meta.Util.is_wayland_compositor () && performed_on_device_type != DeviceType.TOUCHSCREEN) { +#else if (Meta.Util.is_wayland_compositor () && performed_on_device_type != DeviceType.TOUCHSCREEN && type != PINCH) { +#endif return; } diff --git a/lib/Gestures/Backends/TouchpadPinchBackend.vala b/lib/Gestures/Backends/TouchpadPinchBackend.vala new file mode 100644 index 000000000..45fb0a295 --- /dev/null +++ b/lib/Gestures/Backends/TouchpadPinchBackend.vala @@ -0,0 +1,95 @@ +/* + * Copyright 2026 elementary, Inc. (https://elementary.io) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Authored by: Leonhard Kargl + */ + +private class Gala.TouchpadPinchBackend : Object, GestureBackend { + private enum State { + NONE, + IGNORED, + ONGOING + } + + public Clutter.Actor actor { get; construct; } + + private State state = NONE; + private double percentage = 0.0; + + public TouchpadPinchBackend (Clutter.Actor actor) { + Object (actor: actor); + } + + construct { + actor.captured_event.connect (handle_event); + } + + public override void cancel_gesture () { + state = IGNORED; + } + + private bool handle_event (Clutter.Event event) { + if (event.get_type () != TOUCHPAD_PINCH) { + return Clutter.EVENT_PROPAGATE; + } + + if (state != ONGOING && (event.get_gesture_phase () == END || event.get_gesture_phase () == CANCEL)) { + reset (); + return Clutter.EVENT_PROPAGATE; + } + + if (state == IGNORED) { + return Clutter.EVENT_PROPAGATE; + } + + if (state == NONE && event.get_gesture_phase () != BEGIN) { + /* We never got a begin phase so something else initially handled the gesture + but disappeared. Don't start handling it now. Will probably never happen */ + return Clutter.EVENT_PROPAGATE; + } + + if (state != ONGOING) { + var gesture = new Gesture (); + gesture.direction = OUT; + gesture.type = event.get_type (); + gesture.fingers = (int) event.get_touchpad_gesture_finger_count (); + gesture.performed_on_device_type = event.get_source_device ().get_device_type (); + + if (!on_gesture_detected (gesture, event.get_time ())) { + state = IGNORED; + return Clutter.EVENT_PROPAGATE; + } + + state = ONGOING; + } + + if (event.get_gesture_phase () == UPDATE) { + /* When the gesture ends the pinch scale is already reset */ + percentage = event.get_gesture_pinch_scale () - 1.0; + } + + switch (event.get_gesture_phase ()) { + case BEGIN: + on_begin (0, event.get_time ()); + break; + + case UPDATE: + on_update (percentage, event.get_time ()); + break; + + case END: + case CANCEL: + on_end (percentage, event.get_time ()); + reset (); + break; + } + + return Clutter.EVENT_STOP; + } + + private void reset () { + state = NONE; + percentage = 0.0; + } +} diff --git a/lib/Gestures/Backends/TouchpadBackend.vala b/lib/Gestures/Backends/TouchpadSwipeBackend.vala similarity index 94% rename from lib/Gestures/Backends/TouchpadBackend.vala rename to lib/Gestures/Backends/TouchpadSwipeBackend.vala index c1219cc9b..e6c6bded2 100644 --- a/lib/Gestures/Backends/TouchpadBackend.vala +++ b/lib/Gestures/Backends/TouchpadSwipeBackend.vala @@ -5,7 +5,7 @@ * Authored by: Leonhard Kargl */ -private class Gala.TouchpadBackend : Object, GestureBackend { +private class Gala.TouchpadSwipeBackend : Object, GestureBackend { public enum Group { NONE, MULTITASKING_VIEW, @@ -26,7 +26,7 @@ private class Gala.TouchpadBackend : Object, GestureBackend { public Clutter.Actor actor { get; construct; } public Group group { get; construct; } - private static List instances = new List (); + private static List instances = new List (); private State state = NONE; private GestureDirection direction = UNKNOWN; @@ -34,11 +34,11 @@ private class Gala.TouchpadBackend : Object, GestureBackend { private double distance_y = 0; private double distance = 0; - public TouchpadBackend (Clutter.Actor actor, Group group) { + public TouchpadSwipeBackend (Clutter.Actor actor, Group group) { Object (actor: actor, group: group); } - ~TouchpadBackend () { + ~TouchpadSwipeBackend () { instances.remove (this); } diff --git a/lib/Gestures/Triggers/GlobalTrigger.vala b/lib/Gestures/Triggers/GlobalTrigger.vala index 5d856309a..4043973ee 100644 --- a/lib/Gestures/Triggers/GlobalTrigger.vala +++ b/lib/Gestures/Triggers/GlobalTrigger.vala @@ -27,8 +27,12 @@ public class Gala.GlobalTrigger : Object, GestureTrigger { } internal void enable_backends (GestureController controller) { - var group = action == MULTITASKING_VIEW || action == SWITCH_WORKSPACE ? TouchpadBackend.Group.MULTITASKING_VIEW : TouchpadBackend.Group.NONE; + var group = action == MULTITASKING_VIEW || action == SWITCH_WORKSPACE ? TouchpadSwipeBackend.Group.MULTITASKING_VIEW : TouchpadSwipeBackend.Group.NONE; controller.enable_backend (ToucheggBackend.get_default ()); - controller.enable_backend (new TouchpadBackend (wm.stage, group)); + controller.enable_backend (new TouchpadSwipeBackend (wm.stage, group)); +#if HAS_MUTTER49 + // On mutter < 49 there is a bug that pinch gestures aren't delivered when over a window so rely on touch egg there + controller.enable_backend (new TouchpadPinchBackend (wm.stage)); +#endif } } diff --git a/lib/meson.build b/lib/meson.build index 137badfdb..11821b0a7 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -22,7 +22,8 @@ gala_lib_sources = files( 'Effects/ShadowEffect.vala', 'Gestures/Backends/GestureBackend.vala', 'Gestures/Backends/ToucheggBackend.vala', - 'Gestures/Backends/TouchpadBackend.vala', + 'Gestures/Backends/TouchpadPinchBackend.vala', + 'Gestures/Backends/TouchpadSwipeBackend.vala', 'Gestures/Backends/ScrollBackend.vala', 'Gestures/Targets/ActorTarget.vala', 'Gestures/Targets/GestureTarget.vala', diff --git a/po/POTFILES b/po/POTFILES index 584195233..870388dc4 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -34,7 +34,7 @@ lib/Effects/RoundedCornersEffect.vala lib/Effects/ShadowEffect.vala lib/Gestures/Backends/GestureBackend.vala lib/Gestures/Backends/ToucheggBackend.vala -lib/Gestures/Backends/TouchpadBackend.vala +lib/Gestures/Backends/TouchpadSwipeBackend.vala lib/Gestures/Backends/ScrollBackend.vala lib/Gestures/Targets/ActorTarget.vala lib/Gestures/Targets/GestureTarget.vala