Feat(taskbar): drag to reorder pinned taskbar applications - #3715
Feat(taskbar): drag to reorder pinned taskbar applications #3715GhostEagle68 wants to merge 1 commit into
Conversation
|
I do believe that #3635 would be beneficial merged together with this, althoughbot necessary. And I have a local build with that PR and this one and no issues together |
|
Would need to be rebased and tested on vertical bar. |
|
Hey, sorry to bother you, I have a quick question. Would you, be interested in widening the scope of this PR? I'm basically looking to migrate to Noctalia, but the one thing I really miss is a classic taskbar where you can re-order the windows via dragging and dropping, much like browser tabs. Your PR is already halfway there, with the exception that it only concerns pinned app buttons (tiles), and there also needs to be some mechanism to inform the underlying compositor about the new order, so that it can arrange it's own windows in the same order that they appear in the taskbar widget (this is only relevant to scrolling wms like Niri). Here is a very quick demonstration (bottom bar). Waybar + niri_window_buttons video.mp4I asked about my issue on the Discord server, where I was made aware of this PR. And yeah, it's probably a long shot, but it doesn't hurt to ask as they say. Cheers. |
00f5543 to
cb04deb
Compare
@ItsLemmy Rebased and tested both horizontal and vertical recording_20260815_232116.mp4recording_20260815_232229.mp4Edit: |
1. [P1] Drag cleanup incorrectly depends on a config reloadtaskbar_widget.cpp:916-924 commitDragReorder() returns true after merely scheduling setOverride(). The release handler then clears m_drag.area and m_drag.spacer, making endDragVisual() a no-op. The tile remains excluded from layout and the spacer remains attached, under the assumption that setOverride() will rebuild the taskbar. That assumption is false when:
The taskbar then retains transient drag state until an unrelated rebuild; later layouts can move the spacer without 2. [P1] Spacer changes violate the UI phase and layer boundariestaskbar_widget.cpp:430-448 beginDragVisual(), endDragVisual(), and syncDragSpacer() change layout participation and insert/remove children directly from pointer callbacks. Structural scene changes belong in Layout; callbacks should update drag state and call The spacer is also created with ui::node() and stored as Node*. Shell code may use controls only; InputArea is the sole 3. [P2] Releasing after the hold delay still launches the applicationtaskbar_widget.cpp:913-927 After 300 ms, the timer sets m_drag.armed, but release only checks m_drag.active. A hold followed by release without That contradicts the described hold-to-drag behavior and differs from the existing dock implementation, which consumes an armed gesture on release. Treat armed as consumed, set click suppression, and cancel the drag without committing. 4. [P2] The movement threshold ignores interface scaletaskbar_widget.cpp:942 kDragArmDistance is a fixed 8.0F, while task geometry scales with m_contentScale. At 2× interface scale, the effective The canonical threshold already exists as Style::dragStartThreshold in logical pixels. Compare against |
|
Mark it ready for review, when done, thx |
Summary
Adds drag-to-reorder for pinned tiles in the taskbar widget: press a pinned tile, drag it along the bar, and drop it in a new position. The new order is written to
widget.<name>.pinned, so it persists.How it works:
setParticipatesInLayout(false)) soFlexstops repositioning it, and an invisible spacer of the same size is inserted at the target index to hold the drop gap open. Neighbours reflow around it, and the strip keeps its width. On drop the tile is parked in the gap so the strip looks settled while the config write lands.setOverride, deferred throughDeferredCall::callLaterbecause the write rebuilds the taskbar and would otherwise destroy theInputAreawhose handler is still running.Reordering is enabled only when there are at least two pinned entries, the widget has a config name to persist to, and
group_by_workspaceis off (in that mode the flat pinned order isn't what's on screen).Motivation
Pinned tiles land in whatever order they were pinned, and the only way to rearrange them is to unpin and re-pin in sequence. Dragging is what people expect from a taskbar.
Type of Change
Related Issue
None
Testing
On Hyprland with a horizontal bottom bar and 6 pinned apps: dragging in both directions, dropping at both ends, dropping back on the origin (no write), plain/middle/right clicks on pinned and unpinned tiles, and clicks immediately following a drag. Reordered state verified in
settings.tomland after restarting noctalia.2026-07-30.13-12-06.online-video-cutter.com.mp4
Notice the unpinned apps (VSC and Claude) on the right are not affected.
Manual Coverage
Checklist
CONTRIBUTING.md.just formatwith clang-format v22+ installed, or this PR has no code changes.assets/translations/en.json, or this PR adds no new user-facing strings.Additional Notes
Untested paths. Only tested on a horizontal bottom bar with one output. The vertical-bar path is implemented (all geometry is expressed along a "main axis" that follows
m_vertical). Also multi-monitor is likewise untested.No
--insertAtcorrection.Dock::endDragdecrements the insert position when the target is past the source, because itscomputeDragTargetIndexreturns an insertion slot. This one returns a destination index (sourceIndex + lround(travel / pitch), clamped), so after erasing the source, inserting at the target is already correct. Copying the dock's correction here would shift rightward drags one slot short.Drop latency. There's a ~55ms gap between release and the rebuild, which is
setOverridewriting the file and runningloadAll()— the same cost as any other settings change. The tile is parked in its final position first so this isn't visible, but I mention it in case the config reload path is something you'd want to look at separately.Disclosure: I used Claude Code as a pair-programming assistant on this feature; for reading unfamiliar parts of the scene graph and layout code, and for review. The design decisions, testing, and verification are all mine.