Skip to content

Add Wayland docking support#844

Open
mliberty1 wants to merge 1 commit into
githubuser0xFFFF:masterfrom
jetperch:wayland-standalone
Open

Add Wayland docking support#844
mliberty1 wants to merge 1 commit into
githubuser0xFFFF:masterfrom
jetperch:wayland-standalone

Conversation

@mliberty1

Copy link
Copy Markdown

Thanks for your great work on Qt-ADS! I have been using it in the Joulescope UI for many years, and it has been excellent. I have a number of customers affected by my UI issue #316, poor Wayland support. I tried to get someone on Upwork to fix this, but failed. Today, I worked with Claude Code / Fable to get this done.

image

This PR is a self-contained fix for Wayland. It's hopefully relatively easy to accept since most changes are gated to only affect Wayland. It does touch a bunch of files, though. The addition of GlobalPos parameter to a few methods should be a flow-through no-change on other platforms.

The overall experience is functional, but definitely not as slick as Windows and macOS. However, functional is an improvement and good enough to address my customers' concerns about slow performance using xcb.

Curated AI-generated summary follows:

Summary

This PR adds support for docking (undocking, moving, and re-docking floating widgets) on Wayland. It implements the approach outlined in #714 and follows the same mechanism that Qt itself uses for QDockWidget/QToolBar on Wayland.

Wayland forbids the techniques the docking system relies on elsewhere: a client cannot move its own top level windows in screen coordinates, cannot query the global cursor position, and cannot position one top level over another. Instead of the mouse tracked drag preview, undocking now performs a compositor driven drag:

  • Floating containers always use native window decorations on Wayland, so the compositor moves the window (the custom QWidget title bar cannot).
  • Undocking executes a QDrag carrying the MIME types that QWaylandDataDevice translates into an xdg_toplevel_drag_v1 request, so the real floating window follows the cursor (no translucent preview).
  • CDockContainerWidget accepts drops and drives the drop overlays from the drag-and-drop event positions instead of QCursor::pos(), which is stale during a drag on Wayland.
  • Dragging the tab or dock-area title bar of a floating widget drags the existing floating window, so it can be docked back into another container.

Platform impact

Every change is guarded by a new ads::internal::isWayland() helper, so X11, Windows and macOS are unaffected. Where a function is shared (e.g. the drop overlay setup, now factored into CDockContainerWidget::showDropOverlays()), the behavior is preserved on the other platforms. I verified the X11 mouse-drag path still works unchanged.

This change is self-contained and does not depend on any other PR. On the non-Wayland paths the existing top-level Qt::Tool overlays are kept exactly as before; only on Wayland are the overlays child widgets.

Requirements and behavioral notes (also updated in README)

  • Requires Qt 6.6.3+ for the xdg_toplevel_drag_v1 support; on older Qt the code is harmless but the window will not follow the cursor, so X11/XWayland is still recommended there.
  • On Wayland: native decorations only (no custom title bar), the real window is dragged instead of a translucent preview, a floating window takes the dock manager's stylesheet when it is created (a later application-wide stylesheet change does not update an already-floating window), and the compositor owns window stacking (no forced stays-on-top).

Testing

Tested on GNOME / Mutter 50.1 with Qt 6.11 (PySide6): undock, move via the decoration, drop on an indicator to re-dock, drop outside to keep floating, re-dock a floating window via its title bar, floating-to-floating drop, and auto-hide undock. The X11/xcb path was regression tested and is unchanged.

Other compositors are not yet covered; on KDE/KWin a benign Qt warning (This plugin supports grabbing the mouse only for popup windows) is emitted by Qt's own drag-and-drop internals and does not block docking.

References

Wayland does not allow clients to move top level windows in screen
coordinates and does not report the global cursor position, so the mouse
tracked dragging used on the other platforms cannot work there. This
commit implements docking via compositor driven drags instead:

- Floating dock containers always use a native window decoration on
  Wayland, so the compositor (or Qt's client side decoration) handles
  moving of floating widgets
- Undocking executes a QDrag with the MIME types that QWaylandDataDevice
  translates into an xdg_toplevel_drag_v1 request, so the floating widget
  window follows the drag cursor (CFloatingDockContainer::startPlatformDrag)
- CDockContainerWidget accepts drops and shows the drop overlays driven
  by the drag and drop event positions instead of QCursor::pos(), which
  is stale during drag and drop on Wayland
- Dragging the tab or title bar of a floating widget's single dock area
  drags the existing floating widget, so it can be docked back into
  another container; the dock area title bar stays visible in floating
  containers on Wayland because it is the only re-dock handle
- The floating widget is not a child of the dock manager on Wayland.
  Showing a child floating widget turns the dock manager's child widgets
  into native windows; native children are wl_subsurfaces that take part
  in the compositor's drag and drop target picking and steal the drop
  focus from the dock container (likewise, the drop overlays must not
  use WA_TranslucentBackground, which would make them native)
- The Qt::Tool stays-on-top emulation in the dock manager event filter
  is disabled on Wayland: changing window flags of a shown window
  recreates its surface, which detaches a running toplevel drag

Verified on GNOME/Mutter 50.1 (Qt 6.11) with hardware-level input
injection: undock, leave floating, move via decoration, and re-dock all
work; X11/xcb behavior is unchanged (all changes are guarded by the new
ads::internal::isWayland()).

# Conflicts:
#	src/DockOverlay.cpp
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