swipeTracker: Try harder to start touchpad gestures with a direction

Make the touchpad gesture keep track of its state, and enter in a
rejected state if the swipe is happening in the wrong direction.

Effectively, this means touchpad gestures are locked on a single
direction, and horizontal+vertical swipeTrackers won't be handling
events at the same time.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1643>
This commit is contained in:
Carlos Garnacho 2021-02-12 12:13:57 +01:00
parent e135f077fb
commit 504ca7d4c3

View File

@ -39,6 +39,12 @@ const State = {
SCROLLING: 1, SCROLLING: 1,
}; };
const TouchpadState = {
NONE: 0,
HANDLING: 1,
IGNORED: 2,
};
const EventHistory = class { const EventHistory = class {
constructor() { constructor() {
this.reset(); this.reset();
@ -98,6 +104,7 @@ const TouchpadSwipeGesture = GObject.registerClass({
_init(allowedModes) { _init(allowedModes) {
super._init(); super._init();
this._allowedModes = allowedModes; this._allowedModes = allowedModes;
this._state = TouchpadState.NONE;
this._touchpadSettings = new Gio.Settings({ this._touchpadSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.peripherals.touchpad', schema_id: 'org.gnome.desktop.peripherals.touchpad',
}); });
@ -110,6 +117,9 @@ const TouchpadSwipeGesture = GObject.registerClass({
if (event.type() !== Clutter.EventType.TOUCHPAD_SWIPE) if (event.type() !== Clutter.EventType.TOUCHPAD_SWIPE)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (event.get_gesture_phase() === Clutter.TouchpadGesturePhase.BEGIN)
this._state = TouchpadState.NONE;
if (event.get_touchpad_gesture_finger_count() !== GESTURE_FINGER_COUNT) if (event.get_touchpad_gesture_finger_count() !== GESTURE_FINGER_COUNT)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
@ -119,11 +129,17 @@ const TouchpadSwipeGesture = GObject.registerClass({
if (!this.enabled) if (!this.enabled)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (this._state === TouchpadState.IGNORED)
return Clutter.EVENT_PROPAGATE;
let time = event.get_time(); let time = event.get_time();
let [x, y] = event.get_coords(); let [x, y] = event.get_coords();
let [dx, dy] = event.get_gesture_motion_delta(); let [dx, dy] = event.get_gesture_motion_delta();
if (this._state === TouchpadState.NONE && dx === 0 && dy === 0)
return Clutter.EVENT_PROPAGATE;
let gestureOrientation = -1; let gestureOrientation = -1;
if (dx !== dy) { if (dx !== dy) {
gestureOrientation = Math.abs(dx) > Math.abs(dy) gestureOrientation = Math.abs(dx) > Math.abs(dy)
@ -131,9 +147,12 @@ const TouchpadSwipeGesture = GObject.registerClass({
: Clutter.Orientation.VERTICAL; : Clutter.Orientation.VERTICAL;
} }
if (gestureOrientation >= 0 && if (this._state === TouchpadState.NONE &&
gestureOrientation !== this.orientation) gestureOrientation >= 0 &&
gestureOrientation !== this.orientation) {
this._state = TouchpadState.IGNORED;
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}
const vertical = this.orientation === Clutter.Orientation.VERTICAL; const vertical = this.orientation === Clutter.Orientation.VERTICAL;
let delta = (vertical ? dy : dx) * SWIPE_MULTIPLIER; let delta = (vertical ? dy : dx) * SWIPE_MULTIPLIER;
@ -141,10 +160,12 @@ const TouchpadSwipeGesture = GObject.registerClass({
switch (event.get_gesture_phase()) { switch (event.get_gesture_phase()) {
case Clutter.TouchpadGesturePhase.BEGIN: case Clutter.TouchpadGesturePhase.BEGIN:
this.emit('begin', time, x, y);
break;
case Clutter.TouchpadGesturePhase.UPDATE: case Clutter.TouchpadGesturePhase.UPDATE:
if (this._state === TouchpadState.NONE) {
this.emit('begin', time, x, y);
this._state = TouchpadState.HANDLING;
}
if (this._touchpadSettings.get_boolean('natural-scroll')) if (this._touchpadSettings.get_boolean('natural-scroll'))
delta = -delta; delta = -delta;
@ -154,10 +175,11 @@ const TouchpadSwipeGesture = GObject.registerClass({
case Clutter.TouchpadGesturePhase.END: case Clutter.TouchpadGesturePhase.END:
case Clutter.TouchpadGesturePhase.CANCEL: case Clutter.TouchpadGesturePhase.CANCEL:
this.emit('end', time, distance); this.emit('end', time, distance);
this._state = TouchpadState.NONE;
break; break;
} }
return gestureOrientation === this.orientation return this._state === TouchpadState.HANDLING
? Clutter.EVENT_STOP ? Clutter.EVENT_STOP
: Clutter.EVENT_PROPAGATE; : Clutter.EVENT_PROPAGATE;
} }