|
|
b19d38 |
From 73000f25e578b3ce6654fdf0d3da2ec3d9b95dd2 Mon Sep 17 00:00:00 2001
|
|
|
b19d38 |
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@redhat.com>
|
|
|
b19d38 |
Date: Tue, 2 Nov 2021 09:20:11 +0100
|
|
|
b19d38 |
Subject: [PATCH] desktop-icons: Fix stuck grab issue with rubber banding
|
|
|
b19d38 |
|
|
|
b19d38 |
The desktop icons extension can get into a state where the desktop no longer
|
|
|
b19d38 |
takes mouse input.
|
|
|
b19d38 |
|
|
|
b19d38 |
This happens if a user starts a rubber banding operation and then drags
|
|
|
b19d38 |
the mouse to somewhere on screen that has a pop up menu, and then pops
|
|
|
b19d38 |
the menu up.
|
|
|
b19d38 |
|
|
|
b19d38 |
This commit addresses the bug by limiting the grab actor to the
|
|
|
b19d38 |
backgrounds, and by explicitly ending the rubber banding operation
|
|
|
b19d38 |
when one of the icons own menus is shown.
|
|
|
b19d38 |
|
|
|
b19d38 |
One side effect of limiting the grab actor to the backgrounds, is the
|
|
|
b19d38 |
rubber banding code never gets to see motion outside of the backgrounds
|
|
|
b19d38 |
anymore. In order to keep drag operations feeling fluid when the user moves
|
|
|
b19d38 |
toward the edge of the screen, this commit also overrides the
|
|
|
b19d38 |
grab helpers captured-event handler so those motion events keep coming.
|
|
|
b19d38 |
|
|
|
b19d38 |
We also start to end the rubber band if for any reason the grab it had
|
|
|
b19d38 |
was released.
|
|
|
b19d38 |
---
|
|
|
b19d38 |
extensions/desktop-icons/desktopGrid.js | 1 +
|
|
|
b19d38 |
extensions/desktop-icons/desktopManager.js | 109 ++++++++++++---------
|
|
|
b19d38 |
extensions/desktop-icons/fileItem.js | 1 +
|
|
|
b19d38 |
3 files changed, 67 insertions(+), 44 deletions(-)
|
|
|
b19d38 |
|
|
|
b19d38 |
diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js
|
|
|
b19d38 |
index 002803c..c7846bf 100644
|
|
|
b19d38 |
--- a/extensions/desktop-icons/desktopGrid.js
|
|
|
b19d38 |
+++ b/extensions/desktop-icons/desktopGrid.js
|
|
|
b19d38 |
@@ -388,6 +388,7 @@ var DesktopGrid = GObject.registerClass({
|
|
|
b19d38 |
}
|
|
|
b19d38 |
|
|
|
b19d38 |
_openMenu(x, y) {
|
|
|
b19d38 |
+ Extension.desktopManager.endRubberBand();
|
|
|
b19d38 |
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
|
|
|
b19d38 |
this._submenu.menu.removeAll();
|
|
|
b19d38 |
let templates = Extension.templateManager.getTemplates();
|
|
|
b19d38 |
diff --git a/extensions/desktop-icons/desktopManager.js b/extensions/desktop-icons/desktopManager.js
|
|
|
b19d38 |
index 10e3ce0..08bc82b 100644
|
|
|
b19d38 |
--- a/extensions/desktop-icons/desktopManager.js
|
|
|
b19d38 |
+++ b/extensions/desktop-icons/desktopManager.js
|
|
|
b19d38 |
@@ -81,6 +81,7 @@ var DesktopManager = GObject.registerClass({
|
|
|
b19d38 |
this._unixMode = null;
|
|
|
b19d38 |
this._writableByOthers = null;
|
|
|
b19d38 |
this._discreteGpuAvailable = false;
|
|
|
b19d38 |
+ this._rubberBandActive = false;
|
|
|
b19d38 |
|
|
|
b19d38 |
this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => this._recreateDesktopIcons());
|
|
|
b19d38 |
this._rubberBand = new St.Widget({ style_class: 'rubber-band' });
|
|
|
b19d38 |
@@ -94,6 +95,20 @@ var DesktopManager = GObject.registerClass({
|
|
|
b19d38 |
this._mountRemovedId = this._mountMonitor.connect('mount-removed', (monitor, mount) => {
|
|
|
b19d38 |
this._recreateDesktopIcons(); });
|
|
|
b19d38 |
|
|
|
b19d38 |
+ let origCapturedEvent = this._grabHelper.onCapturedEvent;
|
|
|
b19d38 |
+ this._grabHelper.onCapturedEvent = (event) => {
|
|
|
b19d38 |
+ if (event.type() === Clutter.EventType.MOTION) {
|
|
|
b19d38 |
+ /* We handle motion events from a captured event handler so we
|
|
|
b19d38 |
+ * we can see motion over actors that are on other parts of the
|
|
|
b19d38 |
+ * stage.
|
|
|
b19d38 |
+ */
|
|
|
b19d38 |
+ this._handleMotion(event);
|
|
|
b19d38 |
+ return Clutter.EVENT_STOP;
|
|
|
b19d38 |
+ }
|
|
|
b19d38 |
+
|
|
|
b19d38 |
+ return origCapturedEvent.bind(this._grabHelper)(event);
|
|
|
b19d38 |
+ };
|
|
|
b19d38 |
+
|
|
|
b19d38 |
this._addDesktopIcons();
|
|
|
b19d38 |
this._monitorDesktopFolder();
|
|
|
b19d38 |
|
|
|
b19d38 |
@@ -133,57 +148,67 @@ var DesktopManager = GObject.registerClass({
|
|
|
b19d38 |
this._rubberBandInitialY = y;
|
|
|
b19d38 |
this._updateRubberBand(x, y);
|
|
|
b19d38 |
this._rubberBand.show();
|
|
|
b19d38 |
- this._grabHelper.grab({ actor: global.stage });
|
|
|
b19d38 |
+ this._rubberBandActive = true;
|
|
|
b19d38 |
+ this._grabHelper.grab({
|
|
|
b19d38 |
+ actor: Main.layoutManager._backgroundGroup,
|
|
|
b19d38 |
+ onUngrab: () => this.endRubberBand(false),
|
|
|
b19d38 |
+ });
|
|
|
b19d38 |
Extension.lockActivitiesButton = true;
|
|
|
b19d38 |
this._stageReleaseEventId = global.stage.connect('button-release-event', (actor, event) => {
|
|
|
b19d38 |
this.endRubberBand();
|
|
|
b19d38 |
});
|
|
|
b19d38 |
this._rubberBandId = global.stage.connect('motion-event', (actor, event) => {
|
|
|
b19d38 |
- /* In some cases, when the user starts a rubberband selection and ends it
|
|
|
b19d38 |
- * (by releasing the left button) over a window instead of doing it over
|
|
|
b19d38 |
- * the desktop, the stage doesn't receive the "button-release" event.
|
|
|
b19d38 |
- * This happens currently with, at least, Dash to Dock extension, but
|
|
|
b19d38 |
- * it probably also happens with other applications or extensions.
|
|
|
b19d38 |
- * To fix this, we also end the rubberband selection if we detect mouse
|
|
|
b19d38 |
- * motion in the stage without the left button pressed during a
|
|
|
b19d38 |
- * rubberband selection.
|
|
|
b19d38 |
- * */
|
|
|
b19d38 |
- let button = event.get_state();
|
|
|
b19d38 |
- if (!(button & Clutter.ModifierType.BUTTON1_MASK)) {
|
|
|
b19d38 |
- this.endRubberBand();
|
|
|
b19d38 |
- return;
|
|
|
b19d38 |
- }
|
|
|
b19d38 |
- [x, y] = event.get_coords();
|
|
|
b19d38 |
- this._updateRubberBand(x, y);
|
|
|
b19d38 |
- let x0, y0, x1, y1;
|
|
|
b19d38 |
- if (x >= this._rubberBandInitialX) {
|
|
|
b19d38 |
- x0 = this._rubberBandInitialX;
|
|
|
b19d38 |
- x1 = x;
|
|
|
b19d38 |
- } else {
|
|
|
b19d38 |
- x1 = this._rubberBandInitialX;
|
|
|
b19d38 |
- x0 = x;
|
|
|
b19d38 |
- }
|
|
|
b19d38 |
- if (y >= this._rubberBandInitialY) {
|
|
|
b19d38 |
- y0 = this._rubberBandInitialY;
|
|
|
b19d38 |
- y1 = y;
|
|
|
b19d38 |
- } else {
|
|
|
b19d38 |
- y1 = this._rubberBandInitialY;
|
|
|
b19d38 |
- y0 = y;
|
|
|
b19d38 |
- }
|
|
|
b19d38 |
- for (let [fileUri, fileItem] of this._fileItems) {
|
|
|
b19d38 |
- fileItem.emit('selected', true, true,
|
|
|
b19d38 |
- fileItem.intersectsWith(x0, y0, x1 - x0, y1 - y0));
|
|
|
b19d38 |
- }
|
|
|
b19d38 |
});
|
|
|
b19d38 |
}
|
|
|
b19d38 |
|
|
|
b19d38 |
- endRubberBand() {
|
|
|
b19d38 |
+ _handleMotion(event) {
|
|
|
b19d38 |
+ /* In some cases, when the user starts a rubberband selection and ends it
|
|
|
b19d38 |
+ * (by releasing the left button) over a window instead of doing it over
|
|
|
b19d38 |
+ * the desktop, the stage doesn't receive the "button-release" event.
|
|
|
b19d38 |
+ * This happens currently with, at least, Dash to Dock extension, but
|
|
|
b19d38 |
+ * it probably also happens with other applications or extensions.
|
|
|
b19d38 |
+ * To fix this, we also end the rubberband selection if we detect mouse
|
|
|
b19d38 |
+ * motion in the stage without the left button pressed during a
|
|
|
b19d38 |
+ * rubberband selection.
|
|
|
b19d38 |
+ * */
|
|
|
b19d38 |
+ let button = event.get_state();
|
|
|
b19d38 |
+ if (!(button & Clutter.ModifierType.BUTTON1_MASK)) {
|
|
|
b19d38 |
+ this.endRubberBand();
|
|
|
b19d38 |
+ return;
|
|
|
b19d38 |
+ }
|
|
|
b19d38 |
+ let [x, y] = event.get_coords();
|
|
|
b19d38 |
+ this._updateRubberBand(x, y);
|
|
|
b19d38 |
+ let x0, y0, x1, y1;
|
|
|
b19d38 |
+ if (x >= this._rubberBandInitialX) {
|
|
|
b19d38 |
+ x0 = this._rubberBandInitialX;
|
|
|
b19d38 |
+ x1 = x;
|
|
|
b19d38 |
+ } else {
|
|
|
b19d38 |
+ x1 = this._rubberBandInitialX;
|
|
|
b19d38 |
+ x0 = x;
|
|
|
b19d38 |
+ }
|
|
|
b19d38 |
+ if (y >= this._rubberBandInitialY) {
|
|
|
b19d38 |
+ y0 = this._rubberBandInitialY;
|
|
|
b19d38 |
+ y1 = y;
|
|
|
b19d38 |
+ } else {
|
|
|
b19d38 |
+ y1 = this._rubberBandInitialY;
|
|
|
b19d38 |
+ y0 = y;
|
|
|
b19d38 |
+ }
|
|
|
b19d38 |
+ for (let [fileUri, fileItem] of this._fileItems) {
|
|
|
b19d38 |
+ fileItem.emit('selected', true, true,
|
|
|
b19d38 |
+ fileItem.intersectsWith(x0, y0, x1 - x0, y1 - y0));
|
|
|
b19d38 |
+ }
|
|
|
b19d38 |
+ }
|
|
|
b19d38 |
+
|
|
|
b19d38 |
+ endRubberBand(ungrab=true) {
|
|
|
b19d38 |
+ if (!this._rubberBandActive)
|
|
|
b19d38 |
+ return;
|
|
|
b19d38 |
+
|
|
|
b19d38 |
+ this._rubberBandActive = false;
|
|
|
b19d38 |
this._rubberBand.hide();
|
|
|
b19d38 |
Extension.lockActivitiesButton = false;
|
|
|
b19d38 |
- this._grabHelper.ungrab();
|
|
|
b19d38 |
- global.stage.disconnect(this._rubberBandId);
|
|
|
b19d38 |
+ if (ungrab)
|
|
|
b19d38 |
+ this._grabHelper.ungrab();
|
|
|
b19d38 |
global.stage.disconnect(this._stageReleaseEventId);
|
|
|
b19d38 |
- this._rubberBandId = 0;
|
|
|
b19d38 |
this._stageReleaseEventId = 0;
|
|
|
b19d38 |
|
|
|
b19d38 |
this._selection = new Set([...this._selection, ...this._currentSelection]);
|
|
|
b19d38 |
@@ -825,10 +850,6 @@ var DesktopManager = GObject.registerClass({
|
|
|
b19d38 |
global.stage.disconnect(this._stageReleaseEventId);
|
|
|
b19d38 |
this._stageReleaseEventId = 0;
|
|
|
b19d38 |
|
|
|
b19d38 |
- if (this._rubberBandId)
|
|
|
b19d38 |
- global.stage.disconnect(this._rubberBandId);
|
|
|
b19d38 |
- this._rubberBandId = 0;
|
|
|
b19d38 |
-
|
|
|
b19d38 |
this._rubberBand.destroy();
|
|
|
b19d38 |
|
|
|
b19d38 |
if (this._queryFileInfoCancellable)
|
|
|
b19d38 |
diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js
|
|
|
b19d38 |
index 1e8ea89..37ee54d 100644
|
|
|
b19d38 |
--- a/extensions/desktop-icons/fileItem.js
|
|
|
b19d38 |
+++ b/extensions/desktop-icons/fileItem.js
|
|
|
b19d38 |
@@ -747,6 +747,7 @@ var FileItem = GObject.registerClass({
|
|
|
b19d38 |
}
|
|
|
b19d38 |
|
|
|
b19d38 |
_onPressButton(actor, event) {
|
|
|
b19d38 |
+ Extension.desktopManager.endRubberBand();
|
|
|
b19d38 |
this._updateClickState(event);
|
|
|
b19d38 |
let button = event.get_button();
|
|
|
b19d38 |
if (button == 3) {
|
|
|
b19d38 |
--
|
|
|
b19d38 |
2.31.1
|
|
|
b19d38 |
|