From 7991d6c728eb5ce0088ebdbf9156be1e1ff7f654 Mon Sep 17 00:00:00 2001 From: mattchristenson Date: Tue, 29 Sep 2026 22:24:56 -0500 Subject: [PATCH] fix: remove a drag's drop preview even when the dragged window lost the focus or closed At the end of a drag, Forge removed the drop preview of the window that had the focus then, and did nothing if no window had it. If the dragged window had closed during the drag (a browser tab dropped back into its window) or another window had the focus, the preview stayed on screen until the session ended (#529, #433, #175). Remove the preview of the window that was dragged (the grab-op-end signal says which), and a window's preview when it is destroyed. Fixes #529 Co-Authored-By: Claude Opus 5.5 --- lib/extension/window.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/extension/window.js b/lib/extension/window.js index 61820e1e..970ed8ef 100644 --- a/lib/extension/window.js +++ b/lib/extension/window.js @@ -1694,6 +1694,9 @@ export class WindowManager extends GObject.Object { nodeWindow = this.tree.findNodeByActor(actor); if (nodeWindow?.isWindow()) { + // a window closed while it was being dragged (e.g. a browser tab dropped back into its + // window) would leave its drop preview on screen + this._removePreviewHint(nodeWindow); this.tree.removeNode(nodeWindow); this.renderTree("window-destroy-quick", true); this.removeFloatOverride(nodeWindow.nodeValue, true); @@ -2501,9 +2504,22 @@ export class WindowManager extends GObject.Object { } } + /** Remove the drop preview a drag showed for `nodeWindow`, if any. */ + _removePreviewHint(nodeWindow) { + const previewHint = nodeWindow?.previewHint; + if (!previewHint) return; + nodeWindow.previewHint = null; + previewHint.hide(); + if (global.window_group.contains(previewHint)) global.window_group.remove_child(previewHint); + previewHint.destroy(); + } + _handleGrabOpEnd(_display, _metaWindow, grabOp) { this._stopLiveResizeLoop(); this.unfreezeRender(); + // The drop preview belongs to the window that was dragged, which may not have the focus any + // more: remove it whichever window has the focus now (#529, #433) + if (_metaWindow) this._removePreviewHint(this.findNodeWindow(_metaWindow)); let focusMetaWindow = this.focusMetaWindow; if (!focusMetaWindow) return; let focusNodeWindow = this.findNodeWindow(focusMetaWindow); @@ -2549,12 +2565,7 @@ export class WindowManager extends GObject.Object { focusNodeWindow.grabMode = null; focusNodeWindow.initGrabOp = null; - if (focusNodeWindow.previewHint) { - focusNodeWindow.previewHint.hide(); - global.window_group.remove_child(focusNodeWindow.previewHint); - focusNodeWindow.previewHint.destroy(); - focusNodeWindow.previewHint = null; - } + this._removePreviewHint(focusNodeWindow); if (focusNodeWindow.mode === WINDOW_MODES.GRAB_TILE) { focusNodeWindow.mode = WINDOW_MODES.TILE;