Skip to content

v2.12.2 — drag and drop actually drops - #68

Merged
kostyk348 merged 1 commit into
mainfrom
feat/v2.12.2-drag-and-drop
Nov 8, 2026
Merged

kostyk348 merged 1 commit into
mainfrom
feat/v2.12.2-drag-and-drop

Conversation

@kostyk348

Copy link
Copy Markdown
Owner

Report

«да не работал драг энд дроп ало» — the user was right. Page drag-and-drop in the sidebar never delivered. Two defects.

Defect 1 — invisible drop targets, silently missed drops

While a drag is in flight, egui suppresses hovered() for every widget except the one being dragged («while dragging or clicking something, nothing else is hovered», egui/interaction.rs). The sidebar probed drop targets with hovered():

  • during a drag, no row ever lit up as a target — nothing told the user where a drop would land;
  • the drop registered only because egui restores hover on the release frame — releasing anywhere outside a row (over the document, the footer, the scrollbar) cancelled the move with no explanation.

Fix: drop targets and the root drop zone are probed with contains_pointer() — the same primitive the calendar rescheduler and the block grip drag already use (which is why those two worked). The highlight follows the pointer for the whole drag; the drop lands where the highlight shows.

Defect 2 — a lost release froze the page tree

dragged_page was cleared only on a release event. A button-up outside the window (or eaten by a modal) left a stale state: row clicks are gated on the drag state being empty, so the whole tree went dead, and the next stray release moved a page to wherever the pointer happened to be.

Fix: the sidebar cancels a drag whose button is up and no release arrived this frame — the same stale-state cleanup the block drag already had. A real release frame (any_released) is untouched.

Tests

323 → 326, headless egui on the real draw_sidebar path:

  • dropping one page onto another emits the reparent and clears the drag state;
  • dropping a page into its own subtree stays a rejected cycle;
  • a lost release cannot stick.

Sidebar rows now carry a stable explicit id (page-row).

Type

  • Fix (drag-and-drop delivery + drag-state hygiene)

Capsule format impact

  • None

The user was right: page drag-and-drop in the sidebar never delivered.

Defect 1 — invisible drop targets and silently missed drops. While a drag
is in flight, egui suppresses hovered() for every widget except the one
being dragged ('while dragging or clicking something, nothing else is
hovered', egui/interaction.rs). The sidebar probed drop targets with
hovered(), so during a drag no row ever lit up and the drop registered
only because egui restores hover on the release frame — releasing anywhere
outside a row (over the document, the footer, the scrollbar) cancelled the
move with no explanation. Drop targets and the root drop zone are now
probed with contains_pointer(), the same primitive the calendar
rescheduler and the block grip drag already use: the highlight follows the
pointer for the whole drag and the drop lands where the highlight shows.

Defect 2 — a lost release could freeze the page tree. dragged_page was
only cleared when a release event arrived; a button-up outside the window
or one eaten by a modal left a stale state that made every row click dead
(row clicks are gated on the drag state being empty) and let the next
stray release move a page to wherever the pointer was. The sidebar now
cancels a drag whose button is up and no release arrived this frame — the
same stale-state cleanup the block drag already had. A real release frame
(any_released) is untouched.

Sidebar rows carry a stable explicit id (page-row) now; the new headless
tests address them. Tests 323 -> 326: dropping one page onto another
emits the reparent and clears the drag state, dropping a page into its own
subtree stays a rejected cycle, and a lost release cannot stick.
@kostyk348
kostyk348 merged commit 62d91e5 into main Nov 8, 2026
2 checks passed
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