segmented_button: fix internal tab reorder end-to-end
Two independent bugs prevented tab drag-and-drop reorder from working on cosmic-comp (and likely other compositors): 1. allow_reorder required DndAction::Move to be negotiated via OfferEvent::SelectedAction, which cosmic-comp does not always emit for self-drops (the SelectedAction event either never arrives or arrives with DndAction::empty()). Add a fallback: accept self-drops whenever state.dragging_tab is set. dragging_tab is only populated by start_tab_drag on this same widget, so this is safe; mime match and on_reorder presence are checked below. 2. reorder_event_for_drop preferred drop_hint.side over positional swap, producing counter-intuitive no-ops: dropping A (pos 0) on the left half of B (pos 1) resolved to "Before B" which, after removing A, lands at pos 0 again — the tab appeared not to move. Always use default_insert_position, which derives direction from dragged vs target positions (Konsole/Firefox/Chrome-style swap semantics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
108441ef61
commit
a322516f33
1 changed files with 14 additions and 6 deletions
|
|
@ -406,11 +406,12 @@ where
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let position = state
|
// Always use positional swap (Konsole/Firefox/Chrome semantics):
|
||||||
.drop_hint
|
// dropping onto any part of a different tab swaps it with the dragged
|
||||||
.filter(|hint| hint.entity == target)
|
// tab. drop_hint.side-based Before/After is counter-intuitive: dropping
|
||||||
.map(|hint| InsertPosition::from(hint.side))
|
// A (pos 0) on the left half of B (pos 1) resolves to "Before B" which,
|
||||||
.unwrap_or_else(|| self.default_insert_position(dragged, target));
|
// after removing A, lands at pos 0 — so the tab appears not to move.
|
||||||
|
let position = self.default_insert_position(dragged, target);
|
||||||
Some(ReorderEvent {
|
Some(ReorderEvent {
|
||||||
dragged,
|
dragged,
|
||||||
target,
|
target,
|
||||||
|
|
@ -1201,7 +1202,14 @@ where
|
||||||
.dnd_state
|
.dnd_state
|
||||||
.drag_offer
|
.drag_offer
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|offer| offer.selected_action.contains(DndAction::Move));
|
.is_some_and(|offer| offer.selected_action.contains(DndAction::Move))
|
||||||
|
// Self-drop fallback: some compositors (cosmic-comp
|
||||||
|
// observed) do not emit OfferEvent::SelectedAction for
|
||||||
|
// internal drags, leaving selected_action empty.
|
||||||
|
// dragging_tab is only set by start_tab_drag on this
|
||||||
|
// same widget, so this covers the self-drop case
|
||||||
|
// safely; mime and on_reorder are checked below.
|
||||||
|
|| state.dragging_tab.is_some();
|
||||||
let pending_reorder = if allow_reorder
|
let pending_reorder = if allow_reorder
|
||||||
&& self.on_reorder.is_some()
|
&& self.on_reorder.is_some()
|
||||||
&& self.tab_drag.as_ref().is_some_and(|d| d.mime == *mime_type)
|
&& self.tab_drag.as_ref().is_some_and(|d| d.mime == *mime_type)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue