Skip to content

Implement configurable drag behaviour#2476

Open
francislavoie wants to merge 2 commits into
home-sweet-gnome:masterfrom
francislavoie:drag-overview-opt
Open

Implement configurable drag behaviour#2476
francislavoie wants to merge 2 commits into
home-sweet-gnome:masterfrom
francislavoie:drag-overview-opt

Conversation

@francislavoie

Copy link
Copy Markdown

Fixes #2087 and I think also fixes #2407 (the hot corner behaviour mentioned in there is driven by separate logic which is unaffected by these changes).

Problem

When performing an external drag-and-drop (e.g. dragging selected text or a file from one application to another while crossing the panel), any mouse contact with the panel would instantly trigger the GNOME Overview. This makes cross-monitor drag-and-drop painful, leaving the user stranded in the overview mid-drag with no clear path to their intended drop target.

Steps to reproduce

  • I use a multi-monitor setup with dash-to-panel set on the left edge of the right monitor (so the dock is between both monitors), but it can be reproduced on a single monitor
  • Open two Firefox windows or Text Editor windows
  • Select some text in the apps, then drag it through the panel (anywhere, not even over any app icons and through an empty portion of the dock, not waiting on the dock at all, very rapidly passing it) to drop it in another window
  • Overview is triggered instantly as the mouse collides with the panel

Changes

Adds three new settings to control the behavior of dragging an item over the panel.

  • Adds a toggle to fully disable drag from having any effect when crossing the panel if it's generally undesirable.
  • Adds a configurable delay (in milliseconds) before activating the hover action (either preview or overview) during a drag operation, if dragging is enabled, helping prevent accidental activation if just passing through the panel without having the cursor sit on the panel.
  • Adds new functionality to show window previews if window previews are enabled (which is more streamlined), instead of opening the overview (which is quite intrusive causing all windows on all monitors to collapse into the overview)
image image

Demo

Screencast.From.2026-03-21.21-34-35.compressed.mp4
  • I have two text edit windows open, to demo dragging between multiple windows of the same app.
  • 0:00-0:10 I show the behaviour with dragging enabled, with 0ms delay, and using previews instead of overview. I select and drag some text from one window, then show that a given window can be focused via the preview panel while still dragging the piece of text, finally releasing the mouse to drop the held text into the second window.
  • 0:11-0:20 Then, dragging text again, I show that the hover style appears on other apps (ones not running) as you'd expect, as it does when you don't drag; but releasing the mouse on a non-running app does nothing. Just feels better to show the hover style because it's more consistent overall. Also shows that the hover style goes away when dragging off the panel (it was a bug that needed resolving while developing this).
  • 0:21-0:35 Then, I go to the settings, I increase the delay to 550ms, drag some text, and show that there's a longer delay before the preview appears. The delay helps to ignore accidental preview pop-ins if just dragging through the panel on a multi-monitor setup.
  • 0:36-0:46 Then I turn off dragging altogether, (which also disables the other two settings) and show that nothing happens when dragging over the panel, including no hover styles.
  • 0:47-1:04 Then I turn back on dragging but turn off preview mode (which means it opens the overview instead) and show that behaviour; with a 300ms delay it requires sitting on the app icon for a moment then overview appears. I show that overview only shows for apps with multiple windows (it doesn't for the settings app, only the text edit app since it has two windows), then I drag onto one of the two text windows and wait until overview animates and focuses that window.

Technical Breakdown

Two new GSettings keys:

  • drag-to-overview-delay (int, default -1): ms delay before activation; -1 disables entirely
  • drag-to-overview-preview (bool, default false): show window preview popup instead of overview

appIcons.js

  • handleDragOver: Replaces the old immediate-activation logic with a delay-gated timeout (T7). When the xdnd source is detected: cancels panel-level timeout, clears other icons' state via cancelXdndDragTimeouts(this), simulates hover highlight (Clutter won't set it during XDnD pointer grab), and starts a one-shot timer. On fire, either opens preview popup in drag mode or falls back to activate-window/show-overview depending on window count and the preview setting.
  • _onAppIconHoverChanged: Bails out when _inXdndDrag is set, preventing the normal preview requestOpen path from racing with the T7-managed open.
  • cancelXdndDragTimeout: Resets T7, _xdndActionFired, _inXdndDrag, and hover state. Used as the single cleanup entry point per icon.
  • acceptDrop: Cleans up xdnd state on drop.

panel.js

  • handleDragOver: Gated by drag-to-overview-delay. Uses get_actor_at_pos to scope activation to the taskbar area only (ignoring clock, systray, activities, etc.). Manages a panel-level timeout (T8) guarded by _xdndPanelActionFired to prevent re-triggering on cursor re-entry within the same drag session.
  • drag-begin / drag-end: Registers/removes a DND.addDragMonitor for the xdnd session. This is needed because XdndHandler._onPositionChanged only calls handleDragOver on actors under the cursor — when the cursor moves off the panel to the desktop (still within GNOME Shell), no panel/icon code runs to clean up simulated hover or close previews.
  • _onXdndDragMotion: The drag monitor callback. Picks the actor under cursor and checks if it's within taskbar.actor or the drag-mode previewMenu.menu. If neither, clears all icon hover state and closes any drag-opened preview.
  • acceptDrop: Cleans up panel-level xdnd state on drop.

taskbar.js

  • cancelXdndDragTimeouts(exceptIcon): Iterates all app icons calling cancelXdndDragTimeout(), optionally skipping one icon (the caller, to avoid clearing its own in-progress state).

windowPreview.js

  • _setDragMode(enabled): Toggles _dragMode on the PreviewMenu and calls _setXdndDelegate on all child previews. Activated when the preview is opened via drag (preventCloseWindow=true), cleared on close.
  • _setXdndDelegate(enabled): Assigns/removes a _delegate on each Preview actor with handleDragOver/acceptDrop, making previews visible as drop targets to the GNOME Shell DND system during xdnd. handleDragOver activates the hovered window.

prefs.js / SettingsBehavior.ui

  • New "Drag" preferences group with enable switch, delay spinner (0–5000ms), and preview toggle. The switch maps -1/≥0 to the single drag-to-overview-delay key.

Disclosure

Used Github Copilot + Claude Sonnet 4.6 to make the code changes, tested locally by hand with dbus-run-session -- gnome-shell --devkit --wayland, then had Claude Opus 4.6 do a final review pass and fix one bug I couldn't get Sonnet to fix in reasonable time.

@hansyulian

Copy link
Copy Markdown

hi, i face the same issue and i have confirmed that this MR fixed it, can we please put it into mainstream? thx!

@francislavoie

Copy link
Copy Markdown
Author

@charlesg99 this is ready for review, if you have the time to take a look. I've been using this locally for a couple months now and it works great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

weird hot corner behavior caused by extenstion Dragging app tab onto panel opens overview

2 participants