Is it possible to write something like the MacOS dock in Qt?
-
I'm curious if it's possible to create something similar to the Dock in MacOS using Qt6 running on Wayland. Something like this:
From what I can tell (after spending about two hours with Qt6 so far), everything must be in some sort of window. Unfortunately, that means those windows are subject to the rules of your window manager. For example, if you're running a tiling window manager, it's gonna organize those windows as it sees fit. Instead, what we would need to do is physically draw pixels at certain coordinates of the screen, such as on the bottom or top. This would draw over any other existing windows and not affect their placement.
From the somewhat small amount of research I did, it seems the answer to this is directly interacting with the Wayland compositor and bypass the window manager completely. However, from what I can tell, this would also nullify any benefits you'd get from the Qt framework as well. No more Qt widgets, animations, QML, etc. Instead, you'd probably have to use OpenGL or perhaps a library such as Cairo to draw on the screen.
Short version of what I'm asking: Can I use Qt6 to paint outside my window (or not even have a window) and specify exactly where on the monitor I'd like to paint. Or, is this a case of "you're not using the right tool for the job, instead you should use x, y or z and not Qt)."
Thanks!
-
@Mike-Christensen said in Is it possible to write something like the MacOS dock in Qt?:
Can I use Qt6 to paint outside my window (or not even have a window)
Yes and no. You don't need a window (but at least some other valid context/device to paint).
Qt can't paint on the native OS desktop directly for example. -
M Mike Christensen referenced this topic
-
Hi,
You might find some inspiration from the KDE Latte Dock project.
-
@SGaist Oh nice! Looks like it uses both Wayland and Qt. I'd be curious if it's using Qt to draw the actual dock (and for dock animation effects) or just for actual windows such as configuration and settings. Either way, looks worth digging into and seeing how the architecture works.
-
@Pl45m4 Yea, that's the conclusion I came to as well.. It seems there's two paths one could go down trying to implement a dock using Wayland and Qt:
-
Talk to Wayland directly. It will give you a surface that you own that you can draw pixels onto. You'd have to use something like OpenGL or Cairo or what not if you wanted to do anything fancy or wanted to take advantage of the GPU or what not. All these libraries seem like a mess though; a lot haven't been updated in years or have terrible documentation or terrible Wayland support for example. Also, Qt wouldn't be of any use here (at least for GUI rendering) since I can't just give it some arbitrary Wayland surface to draw on.
-
Use Qt and create a window. Unfortunately, this window would be owned by the window manager such as Hyprland or Sway or what have you. I'd have to disable any sort of window decorations like titlebars, borders, buttons, etc. It also means the window manager would control my window layout. For example, a tiling window manager like Hyprland, depending on layout mode, is gonna just make my window the master and it'll take up half the screen. The solution to this would be to interface directly with the window manager and say "Make this window be a popout window, make it be this size, turn off the borders, tile everything else around it, etc". From what I can tell, window managers such as Sway and Hyprland actually implement IPC based interfaces to do this sort of thing, so it all might be doable. It would mean my program would no longer be "window manager agnostic" though since it does not technically own a Wayland client outside the grasp of the window manager.
I think so far, every piece of code I've looked at (Such as Swaybar) is using the first approach. They do appear to be using things like Gtk, and I think a bunch of them might be depending on compatibility layers such as XWayland to get around some of the limitations.
I wish Wayland just had built in "dock and taskbar" support where you could just register your client as a dock, and Qt had support for that. One can dream anyway.
-
-
@Mike-Christensen said in Is it possible to write something like the MacOS dock in Qt?:
@Pl45m4 Yea, that's the conclusion I came to as well.. It seems there's two paths one could go down trying to implement a dock using Wayland and Qt:
- Talk to Wayland directly. It will give you a surface that you own that you can draw pixels onto. You'd have to use something like OpenGL or Cairo or what not if you wanted to do anything fancy or wanted to take advantage of the GPU or what not. All these libraries seem like a mess though; a lot haven't been updated in years or have terrible documentation or terrible Wayland support for example. Also, Qt wouldn't be of any use here (at least for GUI rendering) since I can't just give it some arbitrary Wayland surface to draw on.
I haven't done the work to verify the functionality, but if you pursue the route of acquiring an opengl context directly from the Wayland compositor, you should be able to feed it into a QOpenGLWindow.
- Use Qt and create a window. Unfortunately, this window would be owned by the window manager such as Hyprland or Sway or what have you. I'd have to disable any sort of window decorations like titlebars, borders, buttons, etc. It also means the window manager would control my window layout. For example, a tiling window manager like Hyprland, depending on layout mode, is gonna just make my window the master and it'll take up half the screen. The solution to this would be to interface directly with the window manager and say "Make this window be a popout window, make it be this size, turn off the borders, tile everything else around it, etc". From what I can tell, window managers such as Sway and Hyprland actually implement IPC based interfaces to do this sort of thing, so it all might be doable. It would mean my program would no longer be "window manager agnostic" though since it does not technically own a Wayland client outside the grasp of the window manager.
I think so far, every piece of code I've looked at (Such as Swaybar) is using the first approach. They do appear to be using things like Gtk, and I think a bunch of them might be depending on compatibility layers such as XWayland to get around some of the limitations.
Possibly a misreading, but this feels like a misunderstanding of how Wayland works. There is no Wayland server separate from the window manager, unlike X. Compositors may extend the protocol, or offer external channels. Using these does tie applications to the compositor. The protocol is growing, and at least in theory open to additions. Based on a quick search, https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/28 was one proposal to include dock-like behavior.
https://wayland.freedesktop.org/architecture.html:
In wayland the compositor is the display server.
[...]
-
@Mike-Christensen FWIW there is no such thing as "drawing outside a window". But your understanding of what a window is might be somewhat incomplete - a window is any surface / context that can be drawn on and receive input events. A window doesn't need to be framed, decorated, or even rectangular. Normal windows and dialogs are windows of course, but even in a regular application - tool tips are separate windows, menus are separate windows, floating toolbars are windows, and so on. The same is true in a more macro perspective - docks and panels are windows, heck - even the desktop itself is a window (historically managed by the file browser application). This restriction is not a Qt thing, it is a fundamental property of windowing systems.
The reason all those windows look and behave so differently is because the Window Manager (under X11) / Compositor (under Wayland) has a different role for each, and applies its layout policy appropriately for each role. If you tell it you are a modal dialog - it will block events to all other windows of application. If you tell it you are a tool tip - it will make sure you stay on top of everything else.
In X11, there was a standard way to communicate those things which was the EWMH protocol, which had a dedicated dock role, and was sufficient to communicate most requirements for a dock-like window (i.e. be on every virtual desktop, stay on top, stick to one side of the screen, no intersection with other normal windows and so on).
In Wayland the situation is more complex for authors of desktop shell tools... The core protocol doesn't bother itself with trivia like defining concrete surface roles. "Talking to wayland directly" gives you nothing in this department, except being able to render into a buffer (but you still don't control anything about where it is placed). The most common protocol extension for desktop window management (xdg-shell) is intentionally very restrictive. It is up to each individual compositor to implement additional extension protocols that open up more capability - some don't, i.e GNOME I believe has special private API for the shell to use with its' compositor, and the shell can't be replaced.
You mention hyprland - it (like most other compositors implemented using wlroots) implements an unofficial shell protocol called wlr-layer-shell-unstable. This protocol is sufficient to mark the window of your Qt based dock as having the required properties. The Qt Wayland platform plugin doesn't support it out of the box, but it itself is extensible and looks like there was already some effort in this direction - see https://github.com/KDE/layer-shell-qt