Allow tab reordering in elevated windows via pointer-driven drag#20278
Allow tab reordering in elevated windows via pointer-driven drag#20278jreverett wants to merge 1 commit into
Conversation
When Terminal runs elevated the OS modern drag/drop service is unavailable across integrity levels, so CanDragDrop() is false and the TabView's CanReorderTabs/CanDragTabs are disabled. As a result tabs cannot be rearranged by dragging in an elevated window. This adds a pointer-driven reorder that activates only when CanDragDrop() is false, leaving the native drag/drop path untouched otherwise. Each TabViewItem gets a PointerMoved handler that, on a left-button drag, captures the pointer, floats the dragged tab via a TranslateTransform, slides sibling tabs aside to preview the drop, and commits the move once on release using the existing _TryMoveTab primitive (the same one behind the Move Tab actions). The dragged tab is clamped to the tab strip bounds. Tearing a tab out into a separate window still requires the OS drag/drop service and remains unavailable when elevated. Addresses microsoft#6661.
|
@microsoft-github-policy-service agree |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Tested locally. It works! I noticed a subtle difference in elevated sessions though. You can only move along the rail and tab tear-off is not supported. I think that's fine though, but wanted to make note of it. |
Great! Yes lack of tear-off is noted in the PR description, I couldn't find a way around that and I think that really will need to wait for WinUI3 integration to be supported. The reordering along rails is what is really needed though (at least in my opinion), the current behaviour of having to right click and reorder the tabs gets annoying quickly |
Summary of the Pull Request
Enables reordering tabs by dragging them when Windows Terminal is running elevated (as administrator). Today, dragging a tab in an elevated window does nothing, because the OS modern drag/drop service can't operate across integrity levels, so the
TabView's drag/reorder is disabled. This adds a small, self-contained, pointer-driven reorder that only activates when the native drag/drop path is unavailable.References and Relevant Issues
Addresses the in-strip tab-reorder portion of #6661.
This intentionally does not attempt to restore tab tear-out (dragging a tab out into its own window). Tear-out genuinely depends on the OS drag/drop service that is unavailable to elevated processes, so it remains disabled when elevated. The scope here is in-strip reordering only.
Detailed Description of the Pull Request / Additional comments
Background
When Terminal runs elevated,
Utils::CanUwpDragDrop()returnsfalse(it already special-cases a fully UAC-disabled session, where there is no integrity separation and native drag still works).TerminalPagepropagates this throughCanDragDrop()and setsTabView.CanReorderTabs/CanDragTabsaccordingly. So in a normal elevated session both arefalseand tabs can't be dragged at all. This is the long-standing workaround for the cross-integrity-level drag/drop crash.Approach
Rather than re-enabling the native (crashing) path, this drives reorder directly from raw pointer events — the same idea as the existing Move tab forward/backward actions, which already reorder without the drag/drop service:
TabViewItemgets aPointerMovedhandler (_OnTabPointerMoved), registered only whenCanDragDrop()is false, so non-elevated sessions are completely unaffected (the handler isn't even attached).TranslateTransform, clamped to the tab-strip bounds so it can't slide off-screen.PointerCaptureLost) using the existing_TryMoveTabprimitive.PointerPressedis consumed byTabViewItemfor selection, so the drag begins fromPointerMovedrather thanPointerPressed. Single-click selection and middle-click-close are unaffected.Why this is safe
CanReorderTabs/CanDragTabsstayfalsewhen elevated.!CanDragDrop(), so it is inert wherever native drag already works._TryMoveTab).Validation Steps Performed
Demo — reordering tabs in an elevated window:
MoveTabsTerminalAdmin.mp4
Built and deployed the dev package and tested in an elevated window:
In a non-elevated window:
CanDragDrop()is true).Automated tests: none added. This is a pointer- and layout-geometry-driven interaction (
TransformToVisual,ActualWidth, pointer capture) that the TAEFLocalTests_TerminalApphost can't meaningfully exercise (no live visual layout), and the suite has no existing drag/reorder tests to extend. Validated manually as above.PR Checklist