diff --git a/package/contents/ui/config.ui b/package/contents/ui/config.ui
index 8adb2d0..6ac6e65 100644
--- a/package/contents/ui/config.ui
+++ b/package/contents/ui/config.ui
@@ -101,6 +101,34 @@
+ -
+
+
+ Touchpad scrolling (Wayland only)
+
+
+
-
+
+
+ Enable scrolling with touchpad gestures
+
+
+ Scroll with a three-finger horizontal swipe gesture
+
+
+
+
+ -
+
+
+ Invert scroll direction (Natural scrolling)
+
+
+
+
+
+
+
-
@@ -343,6 +371,36 @@
-
+
+
+ Touchpad gesture scrolling speed:
+
+
+ The amount to scroll per edge-to-edge gesture
+
+
+
+ -
+
+
+ px
+
+
+ 10000
+
+
+ 100
+
+
+ 100
+
+
+ 1920
+
+
+
+
+ -
Preset widths:
@@ -352,7 +410,7 @@
- -
+
-
Comma-separated list of widths. Supported units: "px" and "%".
@@ -360,14 +418,14 @@
- -
+
-
Obscured window opacity:
- -
+
-
%
@@ -380,6 +438,7 @@
+
diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml
index f59bb93..d4cd1a2 100644
--- a/package/contents/ui/main.qml
+++ b/package/contents/ui/main.qml
@@ -35,4 +35,20 @@ Item {
flags: Notification.Persistent
urgency: Notification.HighUrgency
}
+
+ SwipeGestureHandler {
+ direction: SwipeGestureHandler.Direction.Left
+ fingerCount: 3
+ onActivated: qmlBase.karouselInstance.gestureScrollFinish()
+ onCancelled: qmlBase.karouselInstance.gestureScrollFinish()
+ onProgressChanged: qmlBase.karouselInstance.gestureScroll(-progress)
+ }
+
+ SwipeGestureHandler {
+ direction: SwipeGestureHandler.Direction.Right
+ fingerCount: 3
+ onActivated: qmlBase.karouselInstance.gestureScrollFinish()
+ onCancelled: qmlBase.karouselInstance.gestureScrollFinish()
+ onProgressChanged: qmlBase.karouselInstance.gestureScroll(progress)
+ }
}
diff --git a/src/lib/config/config.ts b/src/lib/config/config.ts
index c2dde3d..f6a63e0 100644
--- a/src/lib/config/config.ts
+++ b/src/lib/config/config.ts
@@ -18,6 +18,9 @@ type Config = {
scrollingLazy: boolean;
scrollingCentered: boolean;
scrollingGrouped: boolean;
+ gestureScroll: boolean;
+ gestureScrollInvert: boolean;
+ gestureScrollStep: number;
tiledKeepBelow: boolean;
floatingKeepAbove: boolean;
windowRules: string;
diff --git a/src/lib/config/definition.ts b/src/lib/config/definition.ts
index b089665..15c2a8a 100644
--- a/src/lib/config/definition.ts
+++ b/src/lib/config/definition.ts
@@ -149,6 +149,21 @@ const configDef = [
type: "Bool",
default: false,
},
+ {
+ name: "gestureScroll",
+ type: "Bool",
+ default: false,
+ },
+ {
+ name: "gestureScrollInvert",
+ type: "Bool",
+ default: false,
+ },
+ {
+ name: "gestureScrollStep",
+ type: "UInt",
+ default: 1920,
+ },
{
name: "tiledKeepBelow",
type: "Bool",
diff --git a/src/lib/layout/Desktop.ts b/src/lib/layout/Desktop.ts
index 5fc1188..54eccf9 100644
--- a/src/lib/layout/Desktop.ts
+++ b/src/lib/layout/Desktop.ts
@@ -1,6 +1,7 @@
class Desktop {
public readonly grid: Grid;
private scrollX: number;
+ private gestureScrollXInitial: number | null;
private dirty: boolean;
private dirtyScroll: boolean;
private dirtyPins: boolean;
@@ -15,6 +16,7 @@ class Desktop {
layoutConfig: LayoutConfig,
) {
this.scrollX = 0;
+ this.gestureScrollXInitial = null;
this.dirty = true;
this.dirtyScroll = true;
this.dirtyPins = true;
@@ -124,6 +126,24 @@ class Desktop {
this.setScroll(this.scrollX + dx, force);
}
+ public gestureScroll(amount: number) {
+ if (!this.config.gestureScroll) {
+ return
+ }
+ if (this.gestureScrollXInitial === null) {
+ this.gestureScrollXInitial = this.scrollX;
+ }
+
+ if (this.config.gestureScrollInvert) {
+ amount = -amount;
+ }
+ this.setScroll(this.gestureScrollXInitial + this.config.gestureScrollStep * amount, false);
+ }
+
+ public gestureScrollFinish() {
+ this.gestureScrollXInitial = null;
+ }
+
public arrange() {
// TODO (optimization): only arrange visible windows
this.updateArea();
@@ -160,6 +180,9 @@ namespace Desktop {
marginBottom: number;
marginLeft: number;
marginRight: number;
+ gestureScroll: boolean;
+ gestureScrollInvert: boolean;
+ gestureScrollStep: number;
scroller: Desktop.Scroller;
clamper: Desktop.Clamper;
};
diff --git a/src/lib/world/World.ts b/src/lib/world/World.ts
index ddd90c0..2db41cf 100644
--- a/src/lib/world/World.ts
+++ b/src/lib/world/World.ts
@@ -61,6 +61,9 @@ class World {
marginRight: config.gapsOuterRight,
scroller: World.createScroller(config),
clamper: config.scrollingLazy ? new EdgeClamper() : new CenterClamper(),
+ gestureScroll: config.gestureScroll,
+ gestureScrollInvert: config.gestureScrollInvert,
+ gestureScrollStep: config.gestureScrollStep,
},
layoutConfig,
Workspace.currentActivity,
@@ -124,6 +127,14 @@ class World {
this.doIfTiled(Workspace.activeWindow, f);
}
+ public gestureScroll(amount: number) {
+ this.do((clientManager, desktopManager) => desktopManager.getCurrentDesktop().gestureScroll(amount));
+ }
+
+ public gestureScrollFinish() {
+ this.do((clientManager, desktopManager) => desktopManager.getCurrentDesktop().gestureScrollFinish());
+ }
+
public destroy() {
this.workspaceSignalManager.destroy();
for (const shortcutAction of this.shortcutActions) {