Skip to content

Commit ed01957

Browse files
committed
Gestures: Add more details and introduce on_gesture_handled
Add information about whether a gesture will be handled. This might be used to determine whether events are supposed to be consumed. Add information about the origin of a gesture. This might be used to determine whether a gesture should be handled (e.g. only allow swipe from screen edge). Add common GestureBackend interface that all backends have to implement. Add a on_gesture_handled signal to the GestureTracker which runs if and only if true was returned in on_gesture_detected. Before it is emitted prepare_gesture_handling will be called on the backend. This will be needed for the upcoming PanBackend to avoid conflicts in event consuming. Add a utility get_action to the GestureSettings that gets the corresponding action for a gesture. This allows to remove some duplicated code.
1 parent c164204 commit ed01957

File tree

8 files changed

+158
-92
lines changed

8 files changed

+158
-92
lines changed

src/Gestures/Gesture.vala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,25 @@ namespace Gala {
3535
}
3636

3737
public class Gesture {
38+
public const float INVALID_COORD = float.MAX;
39+
3840
public Clutter.EventType type;
3941
public GestureDirection direction;
4042
public int fingers;
4143
public Clutter.InputDeviceType performed_on_device_type;
44+
45+
/**
46+
* The x coordinate of the initial contact point for the gesture.
47+
* Doesn't have to be set. In that case it is set to {@link INVALID_COORD}.
48+
* Currently the only backend not setting this is {@link GestureTracker.enable_touchpad}.
49+
*/
50+
public float origin_x = INVALID_COORD;
51+
52+
/**
53+
* The y coordinate of the initial contact point for the gesture.
54+
* Doesn't have to be set. In that case it is set to {@link INVALID_COORD}.
55+
* Currently the only backend not setting this is {@link GestureTracker.enable_touchpad}.
56+
*/
57+
public float origin_y = INVALID_COORD;
4258
}
4359
}

src/Gestures/GestureSettings.vala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
* Utility class to access the gesture settings. Easily accessible through GestureTracker.settings.
2121
*/
2222
public class Gala.GestureSettings : Object {
23+
public enum GestureAction {
24+
NONE,
25+
SWITCH_WORKSPACE,
26+
MOVE_TO_WORKSPACE,
27+
SWITCH_WINDOWS,
28+
MULTITASKING_VIEW
29+
}
30+
2331
private static GLib.Settings gala_settings;
2432
private static GLib.Settings touchpad_settings;
2533

@@ -69,4 +77,41 @@ public class Gala.GestureSettings : Object {
6977
public static string get_string (string setting_id) {
7078
return gala_settings.get_string (setting_id);
7179
}
80+
81+
public static GestureAction get_action (Gesture gesture) {
82+
if (gesture.type == TOUCHPAD_SWIPE) {
83+
var fingers = gesture.fingers;
84+
85+
if (gesture.direction == LEFT || gesture.direction == RIGHT) {
86+
var three_finger_swipe_horizontal = get_string ("three-finger-swipe-horizontal");
87+
var four_finger_swipe_horizontal = get_string ("four-finger-swipe-horizontal");
88+
89+
if (fingers == 3 && three_finger_swipe_horizontal == "switch-to-workspace" ||
90+
fingers == 4 && four_finger_swipe_horizontal == "switch-to-workspace") {
91+
return SWITCH_WORKSPACE;
92+
}
93+
94+
if (fingers == 3 && three_finger_swipe_horizontal == "move-to-workspace" ||
95+
fingers == 4 && four_finger_swipe_horizontal == "move-to-workspace") {
96+
return MOVE_TO_WORKSPACE;
97+
}
98+
99+
100+
if (fingers == 3 && three_finger_swipe_horizontal == "switch-windows" ||
101+
fingers == 4 && four_finger_swipe_horizontal == "switch-windows") {
102+
return SWITCH_WINDOWS;
103+
}
104+
} else if (gesture.direction == UP || gesture.direction == DOWN) {
105+
var three_finger_swipe_up = get_string ("three-finger-swipe-up");
106+
var four_finger_swipe_up = get_string ("four-finger-swipe-up");
107+
108+
if (fingers == 3 && three_finger_swipe_up == "multitasking-view" ||
109+
fingers == 4 && four_finger_swipe_up == "multitasking-view") {
110+
return MULTITASKING_VIEW;
111+
}
112+
}
113+
}
114+
115+
return NONE;
116+
}
72117
}

src/Gestures/GestureTracker.vala

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19+
public interface Gala.GestureBackend : Object {
20+
public signal bool on_gesture_detected (Gesture gesture, uint32 timestamp);
21+
public signal void on_begin (double delta, uint64 time);
22+
public signal void on_update (double delta, uint64 time);
23+
public signal void on_end (double delta, uint64 time);
24+
25+
public virtual void prepare_gesture_handling () { }
26+
}
27+
1928
/**
2029
* Allow to use multi-touch gestures from different sources (backends).
2130
* Usage:
@@ -68,11 +77,24 @@ public class Gala.GestureTracker : Object {
6877

6978
/**
7079
* Emitted when a new gesture is detected.
71-
* If the receiving code needs to handle this gesture, it should call to connect_handlers to
72-
* start receiving updates.
80+
* This should only be used to determine whether the gesture should be handled. This shouldn't
81+
* do any preparations instead those should be done in {@link on_gesture_handled}. This is because
82+
* the backend might have to do some preparations itself before you are allowed to do some to avoid
83+
* conflicts.
7384
* @param gesture Information about the gesture.
85+
* @return true if the gesture will be handled false otherwise. If false is returned the other
86+
* signals may still be emitted but aren't guaranteed to be.
7487
*/
75-
public signal void on_gesture_detected (Gesture gesture);
88+
public signal bool on_gesture_detected (Gesture gesture);
89+
90+
/**
91+
* Emitted if true was returned form {@link on_gesture_detected}. This should
92+
* be used to do any preparations for gesture handling and to call {@link connect_handlers} to
93+
* start receiving updates.
94+
* @param gesture the same gesture as in {@link on_gesture_detected}
95+
* @param timestamp the timestamp of the event that initiated the gesture or {@link Meta.CURRENT_TIME}.
96+
*/
97+
public signal void on_gesture_handled (Gesture gesture, uint32 timestamp);
7698

7799
/**
78100
* Emitted right after on_gesture_detected with the initial gesture information.
@@ -201,10 +223,14 @@ public class Gala.GestureTracker : Object {
201223
return value;
202224
}
203225

204-
private void gesture_detected (Gesture gesture) {
205-
if (enabled) {
206-
on_gesture_detected (gesture);
226+
private bool gesture_detected (GestureBackend backend, Gesture gesture, uint32 timestamp) {
227+
if (enabled && on_gesture_detected (gesture)) {
228+
backend.prepare_gesture_handling ();
229+
on_gesture_handled (gesture, timestamp);
230+
return true;
207231
}
232+
233+
return false;
208234
}
209235

210236
private void gesture_begin (double percentage, uint64 elapsed_time) {

src/Gestures/ScrollBackend.vala

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,13 @@
1919
/**
2020
* This gesture backend transforms the touchpad scroll events received by an actor into gestures.
2121
*/
22-
public class Gala.ScrollBackend : Object {
22+
public class Gala.ScrollBackend : Object, GestureBackend {
2323
// Mutter does not expose the size of the touchpad, so we use the same values as GTK apps.
2424
// From GNOME Shell, TOUCHPAD_BASE_[WIDTH|HEIGHT] / SCROLL_MULTIPLIER
2525
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/swipeTracker.js
2626
private const double FINISH_DELTA_HORIZONTAL = 40;
2727
private const double FINISH_DELTA_VERTICAL = 30;
2828

29-
public signal void on_gesture_detected (Gesture gesture);
30-
public signal void on_begin (double delta, uint64 time);
31-
public signal void on_update (double delta, uint64 time);
32-
public signal void on_end (double delta, uint64 time);
33-
3429
public Clutter.Actor actor { get; construct; }
3530
public Clutter.Orientation orientation { get; construct; }
3631
public GestureSettings settings { get; construct; }
@@ -62,7 +57,7 @@ public class Gala.ScrollBackend : Object {
6257
return false;
6358
}
6459

65-
uint64 time = event.get_time ();
60+
var time = event.get_time ();
6661
double x, y;
6762
event.get_scroll_delta (out x, out y);
6863

@@ -80,10 +75,12 @@ public class Gala.ScrollBackend : Object {
8075

8176
if (!started) {
8277
if (delta_x != 0 || delta_y != 0) {
83-
Gesture gesture = build_gesture (delta_x, delta_y, orientation);
78+
float origin_x, origin_y;
79+
event.get_coords (out origin_x, out origin_y);
80+
Gesture gesture = build_gesture (origin_x, origin_y, delta_x, delta_y, orientation, time);
8481
started = true;
8582
direction = gesture.direction;
86-
on_gesture_detected (gesture);
83+
on_gesture_detected (gesture, time);
8784

8885
double delta = calculate_delta (delta_x, delta_y, direction);
8986
on_begin (delta, time);
@@ -114,7 +111,7 @@ public class Gala.ScrollBackend : Object {
114111
&& event.get_scroll_direction () == Clutter.ScrollDirection.SMOOTH;
115112
}
116113

117-
private static Gesture build_gesture (double delta_x, double delta_y, Clutter.Orientation orientation) {
114+
private static Gesture build_gesture (float origin_x, float origin_y, double delta_x, double delta_y, Clutter.Orientation orientation, uint32 timestamp) {
118115
GestureDirection direction;
119116
if (orientation == Clutter.Orientation.HORIZONTAL) {
120117
direction = delta_x > 0 ? GestureDirection.RIGHT : GestureDirection.LEFT;
@@ -126,7 +123,9 @@ public class Gala.ScrollBackend : Object {
126123
type = Clutter.EventType.SCROLL,
127124
direction = direction,
128125
fingers = 2,
129-
performed_on_device_type = Clutter.InputDeviceType.TOUCHPAD_DEVICE
126+
performed_on_device_type = Clutter.InputDeviceType.TOUCHPAD_DEVICE,
127+
origin_x = origin_x,
128+
origin_y = origin_y
130129
};
131130
}
132131

src/Gestures/ToucheggBackend.vala

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,7 @@
2020
* Singleton class to manage the connection with Touchégg daemon and receive touch events.
2121
* See: [[https://github.com/JoseExposito/touchegg]]
2222
*/
23-
public class Gala.ToucheggBackend : Object {
24-
public signal void on_gesture_detected (Gesture gesture);
25-
public signal void on_begin (double delta, uint64 time);
26-
public signal void on_update (double delta, uint64 time);
27-
public signal void on_end (double delta, uint64 time);
28-
23+
public class Gala.ToucheggBackend : Object, GestureBackend {
2924
/**
3025
* Gesture type as returned by the daemon.
3126
*/
@@ -202,7 +197,7 @@ public class Gala.ToucheggBackend : Object {
202197
switch (signal_name) {
203198
case DBUS_ON_GESTURE_BEGIN:
204199
Idle.add (() => {
205-
on_gesture_detected (make_gesture (type, direction, fingers, performed_on_device_type));
200+
on_gesture_detected (make_gesture (type, direction, fingers, performed_on_device_type), Meta.CURRENT_TIME);
206201
on_begin (delta, elapsed_time);
207202
return false;
208203
});

src/Widgets/MultitaskingView.vala

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,16 @@ namespace Gala {
7171
multitasking_gesture_tracker = new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION);
7272
multitasking_gesture_tracker.enable_touchpad ();
7373
multitasking_gesture_tracker.on_gesture_detected.connect (on_multitasking_gesture_detected);
74+
multitasking_gesture_tracker.on_gesture_handled.connect (() => toggle (true, false));
7475

7576
workspace_gesture_tracker = new GestureTracker (AnimationDuration.WORKSPACE_SWITCH_MIN, AnimationDuration.WORKSPACE_SWITCH);
7677
workspace_gesture_tracker.enable_touchpad ();
7778
workspace_gesture_tracker.enable_scroll (this, Clutter.Orientation.HORIZONTAL);
7879
workspace_gesture_tracker.on_gesture_detected.connect (on_workspace_gesture_detected);
80+
workspace_gesture_tracker.on_gesture_handled.connect ((gesture, timestamp) => {
81+
var direction = workspace_gesture_tracker.settings.get_natural_scroll_direction (gesture);
82+
switch_workspace_with_gesture (direction, timestamp);
83+
});
7984

8085
workspaces = new Clutter.Actor ();
8186

@@ -290,39 +295,31 @@ namespace Gala {
290295
workspaces.add_transition ("nudge", nudge);
291296
}
292297

293-
private void on_multitasking_gesture_detected (Gesture gesture) {
294-
if (gesture.type != Clutter.EventType.TOUCHPAD_SWIPE ||
295-
(gesture.fingers == 3 && GestureSettings.get_string ("three-finger-swipe-up") != "multitasking-view") ||
296-
(gesture.fingers == 4 && GestureSettings.get_string ("four-finger-swipe-up") != "multitasking-view")
297-
) {
298-
return;
298+
private bool on_multitasking_gesture_detected (Gesture gesture) {
299+
if (GestureSettings.get_action (gesture) != MULTITASKING_VIEW) {
300+
return false;
299301
}
300302

301-
if (gesture.direction == GestureDirection.UP && !opened) {
302-
toggle (true, false);
303-
} else if (gesture.direction == GestureDirection.DOWN && opened) {
304-
toggle (true, false);
303+
if (gesture.direction == UP && !opened || gesture.direction == DOWN && opened) {
304+
return true;
305305
}
306+
307+
return false;
306308
}
307309

308-
private void on_workspace_gesture_detected (Gesture gesture) {
310+
private bool on_workspace_gesture_detected (Gesture gesture) {
309311
if (!opened) {
310-
return;
312+
return false;
311313
}
312314

313-
var can_handle_swipe = gesture.type == Clutter.EventType.TOUCHPAD_SWIPE &&
314-
(gesture.direction == GestureDirection.LEFT || gesture.direction == GestureDirection.RIGHT);
315-
316-
var fingers = (gesture.fingers == 3 && Gala.GestureSettings.get_string ("three-finger-swipe-horizontal") == "switch-to-workspace") ||
317-
(gesture.fingers == 4 && Gala.GestureSettings.get_string ("four-finger-swipe-horizontal") == "switch-to-workspace");
318-
319-
if (gesture.type == Clutter.EventType.SCROLL || (can_handle_swipe && fingers)) {
320-
var direction = workspace_gesture_tracker.settings.get_natural_scroll_direction (gesture);
321-
switch_workspace_with_gesture (direction);
315+
if (gesture.type == SCROLL || GestureSettings.get_action (gesture) == SWITCH_WORKSPACE) {
316+
return true;
322317
}
318+
319+
return false;
323320
}
324321

325-
private void switch_workspace_with_gesture (Meta.MotionDirection direction) {
322+
private void switch_workspace_with_gesture (Meta.MotionDirection direction, uint32 timestamp) {
326323
if (switching_workspace_in_progress) {
327324
return;
328325
}
@@ -380,7 +377,7 @@ namespace Gala {
380377

381378
switching_workspace_with_gesture = true;
382379
if (target_workspace != null) {
383-
target_workspace.activate (display.get_current_time ());
380+
target_workspace.activate (timestamp);
384381
}
385382

386383
if (is_nudge_animation) {

0 commit comments

Comments
 (0)