Handle touch events in desktop icons

Resolves: RHEL-22713
This commit is contained in:
Florian Müllner 2024-03-06 20:41:17 +01:00
parent 68f3eab84d
commit 5dee2b2bf2
No known key found for this signature in database
2 changed files with 248 additions and 1 deletions

View File

@ -0,0 +1,242 @@
From a796215ddce14ebe80774b99e29d0d28109c818b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 6 Mar 2024 20:14:14 +0100
Subject: [PATCH] desktop-icons: Handle touch events
File icons currently only deal with button events. Split up the
current handlers and use them to handle touch events as well.
---
extensions/desktop-icons/fileItem.js | 181 +++++++++++++++++++--------
1 file changed, 128 insertions(+), 53 deletions(-)
diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js
index 37ee54db..26afddb2 100644
--- a/extensions/desktop-icons/fileItem.js
+++ b/extensions/desktop-icons/fileItem.js
@@ -140,6 +140,7 @@ var FileItem = GObject.registerClass({
this._container.connect('leave-event', (actor, event) => this._onLeave(actor, event));
this._container.connect('enter-event', (actor, event) => this._onEnter(actor, event));
this._container.connect('button-release-event', (actor, event) => this._onReleaseButton(actor, event));
+ this._container.connect('touch-event', (actor, event) => this._onTouchEvent(actor, event));
/* Set the metadata and update relevant UI */
this._updateMetadataFromFileInfo(fileInfo);
@@ -229,6 +230,10 @@ var FileItem = GObject.registerClass({
if (this._iconAllocationIdleId)
GLib.source_remove(this._iconAllocationIdleId);
+ if (this._longPressTimeoutId)
+ GLib.source_remove(this._longPressTimeoutId);
+ delete this._longPressTimeoutId;
+
/* Menu */
this._removeMenu();
}
@@ -731,58 +736,141 @@ var FileItem = GObject.registerClass({
}
_updateClickState(event) {
+ const eventType = event.type();
+ const isButton =
+ eventType === Clutter.EventType.BUTTON_PRESS ||
+ eventType === Clutter.EventType.BUTTON_RELEASE;
+ const button = isButton ? event.get_button() : 0;
+ const time = event.get_time();
+
let settings = Clutter.Settings.get_default();
- if ((event.get_button() == this._lastClickButton) &&
- ((event.get_time() - this._lastClickTime) < settings.double_click_time))
+ if (button === this._lastClickButton &&
+ (time - this._lastClickTime) < settings.double_click_time)
this._clickCount++;
else
this._clickCount = 1;
- this._lastClickTime = event.get_time();
- this._lastClickButton = event.get_button();
+ this._lastClickTime = time;
+ this._lastClickButton = button;
}
_getClickCount() {
return this._clickCount;
}
+ _handlePressEvent(event) {
+ const pressSequence = event.get_event_sequence();
+ if (this._pressSequence &&
+ pressSequence?.get_slot() !== this._pressSequence.get_slot())
+ return Clutter.EVENT_PROPAGATE;
+
+ this._primaryButtonPressed = true;
+ this._pressSequence = pressSequence;
+ this._pressDevice = event.get_device();
+
+ if (this._getClickCount() !== 1)
+ return Clutter.EVENT_STOP;
+
+ const [x, y] = event.get_coords();
+ this._buttonPressInitialX = x;
+ this._buttonPressInitialY = y;
+
+ const shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK);
+ const controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK);
+ if (controlPressed || shiftPressed)
+ this.emit('selected', true, false, !this._isSelected);
+ else if (!this._isSelected)
+ this.emit('selected', false, false, true);
+
+ return Clutter.EVENT_STOP;
+ }
+
+ _handleSecondaryPress() {
+ if (!this.isSelected)
+ this.emit('selected', false, false, true);
+ this._ensureMenu().toggle();
+ if (this._actionOpenWith) {
+ let allowOpenWith = Extension.desktopManager.getNumberOfSelectedItems() === 1;
+ this._actionOpenWith.setSensitive(allowOpenWith);
+ }
+ const specialFilesSelected =
+ Extension.desktopManager.checkIfSpecialFilesAreSelected();
+ if (this._actionCut)
+ this._actionCut.setSensitive(!specialFilesSelected);
+ if (this._actionCopy)
+ this._actionCopy.setSensitive(!specialFilesSelected);
+ if (this._actionTrash)
+ this._actionTrash.setSensitive(!specialFilesSelected);
+ return Clutter.EVENT_STOP;
+ }
+
+ _handleReleaseEvent(event) {
+ if (this._longPressTimeoutId)
+ GLib.source_remove(this._longPressTimeoutId);
+ delete this._longPressTimeoutId;
+
+ if (!this._primaryButtonPressed || this._pressDevice !== event.get_device())
+ return Clutter.EVENT_PROPAGATE;
+
+ const pressSequence = event.get_event_sequence();
+ if (this._pressSequence &&
+ pressSequence?.get_slot() !== this._pressSequence.get_slot())
+ return Clutter.EVENT_PROPAGATE;
+
+ // primaryButtonPressed is TRUE only if the user has pressed the button
+ // over an icon, and if (s)he has not started a drag&drop operation
+ this._primaryButtonPressed = false;
+ delete this._pressDevice;
+ delete this._pressSequence;
+
+ let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK);
+ let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK);
+ if (!controlPressed && !shiftPressed)
+ this.emit('selected', false, false, true);
+ if (this._getClickCount() === 1 && Prefs.CLICK_POLICY_SINGLE && !shiftPressed && !controlPressed)
+ this.doOpen();
+ if (this._getClickCount() === 2 && !Prefs.CLICK_POLICY_SINGLE)
+ this.doOpen();
+ return Clutter.EVENT_STOP;
+ }
+
+ _onTouchEvent(actor, event) {
+ // on X11, let pointer emulation deal with touch
+ if (!Meta.is_wayland_compositor())
+ return Clutter.EVENT_PROPAGATE;
+
+ const type = event.type();
+ if (type === Clutter.EventType.TOUCH_BEGIN) {
+ Extension.desktopManager.endRubberBand();
+ this._updateClickState(event);
+
+ if (!this._handlePressEvent(event))
+ return Clutter.EVENT_PROPAGATE;
+
+ const { longPressDuration } = Clutter.Settings.get_default();
+ this._longPressTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
+ longPressDuration,
+ () => {
+ this._handleSecondaryPress();
+ delete this._longPressTimeoutId;
+ return GLib.SOURCE_REMOVE;
+ });
+
+ return Clutter.EVENT_STOP;
+ } else if (type === Clutter.EventType.TOUCH_END) {
+ return this._handleReleaseEvent(event);
+ }
+ return Clutter.EVENT_PROPAGATE;
+ }
+
_onPressButton(actor, event) {
Extension.desktopManager.endRubberBand();
this._updateClickState(event);
let button = event.get_button();
- if (button == 3) {
- if (!this.isSelected)
- this.emit('selected', false, false, true);
- this._ensureMenu().toggle();
- if (this._actionOpenWith) {
- let allowOpenWith = (Extension.desktopManager.getNumberOfSelectedItems() == 1);
- this._actionOpenWith.setSensitive(allowOpenWith);
- }
- let specialFilesSelected = Extension.desktopManager.checkIfSpecialFilesAreSelected();
- if (this._actionCut)
- this._actionCut.setSensitive(!specialFilesSelected);
- if (this._actionCopy)
- this._actionCopy.setSensitive(!specialFilesSelected);
- if (this._actionTrash)
- this._actionTrash.setSensitive(!specialFilesSelected);
- return Clutter.EVENT_STOP;
- } else if (button == 1) {
- if (this._getClickCount() == 1) {
- let [x, y] = event.get_coords();
- this._primaryButtonPressed = true;
- this._buttonPressInitialX = x;
- this._buttonPressInitialY = y;
- let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK);
- let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK);
- if (controlPressed || shiftPressed) {
- this.emit('selected', true, false, !this._isSelected);
- } else {
- if (!this._isSelected)
- this.emit('selected', false, false, true);
- }
- }
- return Clutter.EVENT_STOP;
- }
+ if (button == 3)
+ return this._handleSecondaryPress();
+ if (button == 1)
+ return this._handlePressEvent(event);
return Clutter.EVENT_PROPAGATE;
}
@@ -821,22 +909,9 @@ var FileItem = GObject.registerClass({
_onReleaseButton(actor, event) {
let button = event.get_button();
- if (button == 1) {
- // primaryButtonPressed is TRUE only if the user has pressed the button
- // over an icon, and if (s)he has not started a drag&drop operation
- if (this._primaryButtonPressed) {
- this._primaryButtonPressed = false;
- let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK);
- let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK);
- if (!controlPressed && !shiftPressed)
- this.emit('selected', false, false, true);
- if ((this._getClickCount() == 1) && Prefs.CLICK_POLICY_SINGLE && !shiftPressed && !controlPressed)
- this.doOpen();
- return Clutter.EVENT_STOP;
- }
- if ((this._getClickCount() == 2) && (!Prefs.CLICK_POLICY_SINGLE))
- this.doOpen();
- }
+ if (button == 1)
+ return this._handleReleaseEvent(event);
+
return Clutter.EVENT_PROPAGATE;
}
--
2.44.0

View File

@ -7,7 +7,7 @@
Name: gnome-shell-extensions
Version: 40.7
Release: 14%{?dist}
Release: 15%{?dist}
Summary: Modify and extend GNOME Shell functionality and behavior
License: GPLv2+
@ -45,6 +45,7 @@ Patch022: 0001-docking-Only-remove-spacer-if-necessary.patch
Patch023: 0001-classification-banner-Hide-from-picks.patch
Patch024: 0001-desktop-icons-Notify-icon-drags.patch
Patch025: prefer-window-icon.patch
Patch026: 0001-desktop-icons-Handle-touch-events.patch
%description
GNOME Shell Extensions is a collection of extensions providing additional and
@ -448,6 +449,10 @@ workspaces.
%changelog
* Wed Mar 19 2024 Florian Müllner <fmuellner@redhat.com> - 40.7-15
- Handle touch events in desktop icons
Resolves: RHEL-22713
* Tue Mar 19 2024 Florian Müllner <fmuellner@redhat.com> - 40.7-14
- Prefer window icons in window list
Resolves: RHEL-24713