Skip to content

x11: fix dnd-kitten drag immediately cancelled by spurious synthetic ButtonRelease#10025

Closed
Copilot wants to merge 1 commit into
masterfrom
copilot/fix-dnd-kitten-drag-issue-again
Closed

x11: fix dnd-kitten drag immediately cancelled by spurious synthetic ButtonRelease#10025
Copilot wants to merge 1 commit into
masterfrom
copilot/fix-dnd-kitten-drag-issue-again

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 18, 2026

When the dnd kitten starts a drag, XGrabPointer is called from the tick callback after an async IPC round-trip — significantly later than the original Button1 press. Calling XGrabPointer(CurrentTime) at that point causes some X11 compositors to emit a synthetic ButtonRelease to transition from the implicit button-press grab to the new explicit grab. Since drag.active is already true and no XdndPosition target exists yet, handle_drag_button_release cancels the drag immediately. Tab dragging is unaffected because XGrabPointer is called synchronously within the same event cycle as the triggering motion event.

Changes

  • glfw/x11_platform.h — add Time last_button1_press_time to the drag sub-struct
  • glfw/x11_window.c
    • Record event->xbutton.time on every Button1 press
    • In _glfwPlatformStartDrag, pass the saved timestamp (falling back to CurrentTime if zero) to XGrabPointer instead of CurrentTime

Using the button-press timestamp is standard X11 DnD practice: it tells the server the grab was active from the moment the button was pressed, suppressing the spurious synthetic transition events regardless of how much wall time elapses before the explicit grab is requested.

When the dnd kitten initiates a drag, XGrabPointer is called from the
tick callback after an async IPC round-trip.  Calling XGrabPointer with
CurrentTime long after the Button1 press causes some X11 compositors to
emit a synthetic ButtonRelease (transitioning from the implicit press-grab
to the explicit pointer grab), which immediately cancels the drag because
no XdndPosition target has been found yet.

Fix: save event->xbutton.time on each Button1 press and use that
timestamp in XGrabPointer instead of CurrentTime.  This is standard X11
DnD practice and tells the server the grab was active since the button
press, preventing the spurious synthetic event.

Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/16a2b7ff-bf7a-419a-883b-59a8c6def5f7

Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
@kovidgoyal
Copy link
Copy Markdown
Owner

@copilot that does not fix it. Doing further debugging, I find the release event is not coming from the X server but instead is coming from _glfwFreeDragSourceData in glfw/input.c

@kovidgoyal kovidgoyal closed this May 18, 2026
Copilot stopped work on behalf of kovidgoyal due to an error May 18, 2026 04:51
Copilot AI requested a review from kovidgoyal May 18, 2026 04:51
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.

2 participants