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