Skip to content

fix(title_bar): clear CSD drag flag via paint-phase window-level mous…#2465

Open
gaoyia wants to merge 1 commit into
longbridge:mainfrom
gaoyia:patch-3
Open

fix(title_bar): clear CSD drag flag via paint-phase window-level mous…#2465
gaoyia wants to merge 1 commit into
longbridge:mainfrom
gaoyia:patch-3

Conversation

@gaoyia

@gaoyia gaoyia commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

On Linux client-side decorations, when the pointer leaves the title-bar element mid-drag, the element-level on_mouse_up never fires. As a result should_move stays true, and the next mouse move re-triggers start_window_move, causing the window to keep moving unexpectedly.

This PR registers a window-level mouse_up listener that resets should_move. Because window.on_mouse_event may only be called during the paint phase (calling it from RenderOnce::render panics with "this method can only be called during paint"), the listener is wrapped in a zero-size Element (TitleBarWindowMouseUpListener) that is only attached on Linux when the window is client-decorated.

The existing drag and double-click logic is left unchanged.

Description

On Linux with client-side decorations (CSD), the title bar tracks a should_move flag: mouse-down sets it, the next mouse-move calls start_window_move, and mouse-up clears it. The problem is that once the compositor begins moving the window, the pointer can leave the title-bar element, so its element-level on_mouse_up never fires. The flag stays true, and a later mouse-move re-triggers start_window_move, making the window "stick" to the cursor.

This PR adds a window-level mouse_up listener that clears should_move regardless of where the pointer is released. Since window.on_mouse_event may only be called during the paint phase — calling it from RenderOnce::render panics with "this method can only be called during paint" — the listener is implemented as a zero-size Element (TitleBarWindowMouseUpListener, display: none) that registers the listener in its paint. The listener only reacts to left-button release during the bubble phase. It is attached only when is_linux && is_client_decorated, so other platforms and server-side decorations are unaffected. The existing drag and double-click (maximize) behavior is unchanged.

Break Changes

None.

How to Test

On Linux with client-side decorations:

  1. Press and hold the left mouse button on the title bar and start dragging the window.
  2. While dragging, move the pointer off the title-bar element (e.g. over the window content), then release the button.
  3. Move the mouse again — the window should NOT resume following the cursor.

Also verify normal behavior is intact:

  • Dragging the title bar moves the window.
  • Double-clicking the title bar toggles maximize.

On macOS/Windows, confirm no behavioral change (the listener is not attached).

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes.
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific)

…e_up listener

On Linux client-side decorations, when the pointer leaves the title-bar
element mid-drag, the element-level `on_mouse_up` never fires. As a
result `should_move` stays `true` and the next mouse move re-triggers
`start_window_move`, causing the window to keep moving unexpectedly.

Register a window-level `mouse_up` listener that resets `should_move`.
Because `window.on_mouse_event` may only be called during the paint
phase (calling it from `RenderOnce::render` panics with "this method can
only be called during paint"), the listener is wrapped in a zero-size
`Element` (`TitleBarWindowMouseUpListener`) that is only attached on
Linux when the window is client-decorated.

The existing drag and double-click logic is left unchanged.
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.

1 participant