diff --git a/Settings.ui b/Settings.ui
index 5a59c5079..c65c045d5 100644
--- a/Settings.ui
+++ b/Settings.ui
@@ -30,6 +30,12 @@
0.1
10
+
+
+
+
+
+
+
start
diff --git a/gestures.js b/gestures.js
index ecad1e38e..e31960a28 100644
--- a/gestures.js
+++ b/gestures.js
@@ -15,6 +15,7 @@ const DIRECTIONS = {
};
let vy, time, vState, navigator, direction, signals;
+let touchPanGesture; // touchscreen 4-finger pan gesture (local addition)
let handoffToOverview = false;
// 1 is natural scrolling, -1 is unnatural
let natural = 1;
@@ -172,6 +173,76 @@ export function enable(extension) {
}
return Clutter.EVENT_PROPAGATE;
});
+
+ /**
+ Touchscreen pan -> scroll the window strip.
+
+ PaperWM natively only handles touchpad swipes (TOUCHPAD_SWIPE events)
+ and a single-finger top-bar touch scroll; a touchscreen never emits
+ TOUCHPAD_SWIPE. This adds a touchscreen equivalent via Clutter's gesture
+ framework. Unlike a raw captured-event handler, a gesture recognised by
+ the framework intercepts touch even over windows.
+
+ Defaults to 4 fingers: GNOME owns the 3-finger touchscreen swipe
+ (workspace switching) and wins gesture recognition. Finger count,
+ sensitivity and enabled state are configurable via the touch-gesture-*
+ settings.
+ */
+ touchPanGesture = new Clutter.PanGesture();
+ touchPanGesture.set_pan_axis(Clutter.PanAxis.X);
+ let panSpace = null;
+
+ // Push finger count and enabled state to the gesture; re-apply on change.
+ // Sensitivity is read live per pan-update (see below).
+ const applyTouchGestureSettings = () => {
+ const fingers = Settings.prefs.touch_gesture_fingers;
+ touchPanGesture.set_min_n_points(fingers);
+ touchPanGesture.set_max_n_points(fingers);
+ touchPanGesture.set_enabled(Settings.prefs.touch_gesture_enabled);
+ };
+ applyTouchGestureSettings();
+ signals.connect(gsettings, 'changed::touch-gesture-enabled', applyTouchGestureSettings);
+ signals.connect(gsettings, 'changed::touch-gesture-fingers', applyTouchGestureSettings);
+
+ signals.connect(touchPanGesture, 'recognize', () => {
+ const space = Tiling.spaces.activeSpace ?? Tiling.spaces.selectedSpace;
+ panSpace = space ?? null;
+ if (!panSpace)
+ return;
+ panSpace.vx = 0;
+ dxs = [];
+ dts = [];
+ start = panSpace.targetX;
+ panSpace.hState = Clutter.TouchpadGesturePhase.UPDATE;
+ direction = DIRECTIONS.Horizontal;
+ Easer.removeEase(panSpace.cloneContainer);
+ swipeTrackersEnable(false);
+ navigator = Navigator.getNavigator();
+ update(panSpace, 0, GLib.get_monotonic_time() / 1000);
+ });
+
+ signals.connect(touchPanGesture, 'pan-update', gesture => {
+ if (!panSpace)
+ return;
+ const delta = gesture.get_delta();
+ update(panSpace, -delta.get_x() * Settings.prefs.touch_gesture_sensitivity,
+ GLib.get_monotonic_time() / 1000);
+ });
+
+ const finishPan = () => {
+ if (!panSpace)
+ return;
+ panSpace.hState = Clutter.TouchpadGesturePhase.END;
+ done(panSpace);
+ direction = undefined;
+ dxs = [];
+ dts = [];
+ panSpace = null;
+ };
+ signals.connect(touchPanGesture, 'end', finishPan);
+ signals.connect(touchPanGesture, 'cancel', finishPan);
+
+ global.stage.add_action(touchPanGesture);
}
function shouldPropagate(fingers) {
@@ -206,6 +277,10 @@ export function disable() {
signals = null;
Utils.timeout_remove(endVerticalTimeout);
endVerticalTimeout = null;
+ if (touchPanGesture) {
+ global.stage.remove_action(touchPanGesture);
+ touchPanGesture = null;
+ }
touchpadSettings = null;
}
diff --git a/prefs.js b/prefs.js
index b2cab90e7..bc9e06136 100644
--- a/prefs.js
+++ b/prefs.js
@@ -447,6 +447,15 @@ class SettingsWidget {
const fingerNumberDefault = 0;
enumOptionsChanged('gesture-horizontal-fingers', fingerOptions, fingerOptionDefault, fingerNumberDefault);
enumOptionsChanged('gesture-workspace-fingers', fingerOptions, fingerOptionDefault, fingerNumberDefault);
+
+ // Touchscreen gesture settings
+ booleanStateChanged('touch-gesture-enabled');
+ enumOptionsChanged(
+ 'touch-gesture-fingers',
+ { 'four-fingers': 4, 'five-fingers': 5 },
+ 'four-fingers',
+ 4);
+ doubleValueChanged('touch-gesture-sensitivity', 'touch-gesture-sensitivity');
enumOptionsChanged(
'default-focus-mode',
{
diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled
index 484bc3286..7d91a4147 100644
Binary files a/schemas/gschemas.compiled and b/schemas/gschemas.compiled differ
diff --git a/schemas/org.gnome.shell.extensions.paperwm.gschema.xml b/schemas/org.gnome.shell.extensions.paperwm.gschema.xml
index 1819e96b0..71e244ae0 100644
--- a/schemas/org.gnome.shell.extensions.paperwm.gschema.xml
+++ b/schemas/org.gnome.shell.extensions.paperwm.gschema.xml
@@ -768,6 +768,21 @@
Number of fingers for workspace switching. 0:DISABLED 3:THREE_FINGERS 4:FOUR_FINGERS
+
+ true
+ Enables the PaperWM touchscreen swipe gesture
+
+
+
+ 4
+ Number of fingers for the touchscreen tiling swipe. 4:FOUR_FINGERS 5:FIVE_FINGERS
+
+
+
+ 1.8
+ Touchscreen swipe sensitivity: how far the tiling moves per unit of finger travel
+
+
diff --git a/settings.js b/settings.js
index c35d34c23..d1baba964 100644
--- a/settings.js
+++ b/settings.js
@@ -67,6 +67,9 @@ export function enable(extension) {
'gesture-enabled',
'gesture-horizontal-fingers',
'gesture-workspace-fingers',
+ 'touch-gesture-enabled',
+ 'touch-gesture-fingers',
+ 'touch-gesture-sensitivity',
'open-window-position',
'overview-ensure-viewport-animation',
'overview-min-windows-per-row',