add swipe gesture scrolling support (Wayland only) (#90)

This commit is contained in:
Himadri Bhattacharjee
2025-03-26 21:10:52 +05:30
committed by Peter Fajdiga
parent b4fe71f91b
commit c99cad96c3
6 changed files with 130 additions and 3 deletions

View File

@@ -101,6 +101,34 @@
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>Touchpad scrolling (Wayland only)</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QCheckBox" name="kcfg_gestureScroll">
<property name="text">
<string>Enable scrolling with touchpad gestures</string>
</property>
<property name="toolTip">
<string>Scroll with a three-finger horizontal swipe gesture</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_gestureScrollInvert">
<property name="text">
<string>Invert scroll direction (Natural scrolling)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
@@ -343,6 +371,36 @@
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_gestureScrollStep">
<property name="text">
<string>Touchpad gesture scrolling speed:</string>
</property>
<property name="toolTip">
<string>The amount to scroll per edge-to-edge gesture</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSpinBox" name="kcfg_gestureScrollStep">
<property name="suffix">
<string> px</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1920</number>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_presetWidths">
<property name="text">
<string>Preset widths:</string>
@@ -352,7 +410,7 @@
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QLineEdit" name="kcfg_presetWidths">
<property name="toolTip">
<string>Comma-separated list of widths. Supported units: "px" and "%".</string>
@@ -360,14 +418,14 @@
</widget>
</item>
<item row="10" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_offScreenOpacity">
<property name="text">
<string>Obscured window opacity:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QSpinBox" name="kcfg_offScreenOpacity">
<property name="suffix">
<string> %</string>
@@ -380,6 +438,7 @@
</property>
</widget>
</item>
</layout>
</widget>

View File

@@ -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)
}
}

View File

@@ -18,6 +18,9 @@ type Config = {
scrollingLazy: boolean;
scrollingCentered: boolean;
scrollingGrouped: boolean;
gestureScroll: boolean;
gestureScrollInvert: boolean;
gestureScrollStep: number;
tiledKeepBelow: boolean;
floatingKeepAbove: boolean;
windowRules: string;

View File

@@ -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",

View File

@@ -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;
};

View File

@@ -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) {