Wayland does not support QWindow::requestActivate()
PerBothner opened this issue ยท 15 comments
I tried running the example programs on Fedora Linux 34 using the default Gnome/Wayland window manager, and failed pretty badly. I could re-arrange tabs, but otherwise moving windows just made them into top-level windows.
I saw various warnings:
QSocketNotifier: Can only be used with threads started with QThread
Warning: Wayland does not support QWindow::requestActivate() ((null):0, (null))
The latter repeated multiple times. I usually end up with a Segmentation fault.
I am able to run other Qt5 applications, including by own Qt front-end for DomTerm, which uses QWebEngine. (I'm evaluating using this library for DomTerm, in place of an existing pure-JavaScript library.)
A work-around is to set XDG_SESSION_TYPE
. For example:
XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo
Thank you for reporting this problem. I have given up in fixing esoteric Linux related issues like this. Unfortunately, there is no such thing as a Linux operating system - there are only a variety of different distributions. So it is not possible to support "Linux". It is only possible to support a small subset of Linux distributions. ADS works with Ubuntu 20.04 and 18.04 and that is o.k. for me.
I will keep this issue open so that other people can find your solution.
So if someone would like to step in to fix this - the source code is here.
I understand you don't want to deal with this now, as there is a work-around, and it is possible the problem will be fixed by a future Qt or Wayland release. That said, Fedora is hardly some esoteric distribution: It's the forward edge of Red Hat Linux, and Linux in general. Ubuntu already includes Wayland. While it isn't the default yet, there is no question it will be sooner or later, as it will for most Linux distributions. The unpcoming WSL release will incorporate a Wayland "server". (I could also point out that Windows and MacOS also exist in different versions.)
I might take a look at the issue, though I am hardly an expert in either Qt or Wayland. Though probably first I'll try to have DomTerm make use of ADS, and see if it's a good solution. (It looks very nice so far.)
The message is related to calls to activateWindow
. I commented out those calls in the code, which avoided the message, but the test programs don't work. (The window appears but dragging a dockable doesn't work.)
It is possible things work better on Qt6, but I haven't had a chance to try that.
To give some context that previous comments are lacking:
- Wayland is the successor to X11, by X11 developers who are so fed up with maintaining it that XWayland (the "run X apps in Wayland" system) got split out and it took years to find someone willing to shepherd the accumulated patches for the standalone X server into a release. [1] [2] [3]
- Wayland would have been called X12 but they didn't want people complaining about how different the architecture was more than they already do. (The design began with the brainstorming on this wiki page, IIRC.)
- Wayland probably would be the default on all Linux desktop by now if nVidia hadn't spent a decade trying to throw their weight around with their drivers and having to be laboriously shown why their EGLStreams API was unsuited to implementing Wayland compositors. (Seriously. Desktops refused to implement it until nVidia paid their own developers to contribute the code and provided a liason, and then KDE developers had to keep sending them back to the driver team with bugs that couldn't be fixed due to limitations in the API. [1] [2])
QWidget::activateWindow
not working in Wayland is probably a designed feature, not a bug.
To explain that last one, I have to explain Wayland's security model a bit.
Basically, X11 grants every application power to do everything and just trusts that they won't log your keys or AutoHotkey their way into installing an exploit. Wayland is designed around a more Android/iOS-like security model where applications can't access things outside themselves using the base protocol and requesting permission for fancier things requires carefully-designed protocol extensions that the system can present permission prompts for. It's basically like the Firefox legacy extension API vs. the Chrome/WebExtensions API.
It's meant to be paired with something like Flatpak which adds in the rest of the sandboxing and the distro-independent packaging and distribution. (Qt already supports much of this. For example, if you run a Qt application in a Flatpak, it will automatically indirect QFileDialog
through the XDG Portal (an Android Intents equivalent) for displaying a privileged Open/Save dialog which takes care of mounting the requested path into the sandbox.)
QWidget::activateWindow
is a global operation and was always something the window manager could ignore (eg. KDE and GNOME's Focus Stealing Prevention feature), but I suspect Wayland simply doesn't have an API that directly correlates to activateWindow
for the same reason Wayland splits setting screen resolution into un-privileged "full-screen me, but don't permanently change anything" and privileged "change the actual display settings" sides.
It probably won't be fixed until the Qt devs decide how best to map its APIs to a permissions model that fundamentally lacks verbs for things like "what are my absolute coordinates on the desktop?" and "steal focus from another application". (i.e. Do they want it to become conditional on another window from the same application already having focus or do they want a separate method for that?)
A work-around is to set
XDG_SESSION_TYPE
. For example:XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo
This fix doesn't work when compiling with Qt6. Instead, you should use QT_QPA_PLATFORM=xcb
Piling on to what @ssokolow wrote above: This is not going to be fixed in Qt as per this comment
qt.qpa.wayland: Wayland does not support QWindow::requestActivate()
This means your window tried to grab focus in the compositor, which is not allowed in wayland. Don't create a bug for it, there's nothing we can do.
What I'm gathering is that this would need to be implemented some other way and/or through integration per compositor (the major ones being KWin, mutter and wlroots). Given that we're talking about transferring focus between windows within the same application, I feel this should be possible and/or a valid enough use case to work, but right now I don't know how to approach it.
What I'm gathering is that this would need to be implemented some other way and/or through integration per compositor (the major ones being KWin, mutter and wlroots). Given that we're talking about transferring focus between windows within the same application, I feel this should be possible and/or a valid enough use case to work, but right now I don't know how to approach it.
I could certainly imagine a Wayland protocol extension that allows transferring focus between different window handles created through the same Wayland socket. It'd probably even be less controversial than GNOME's decision to refuse to support the server-side window decoration protocol in favour of forcing every application to either link against GTK or implement their own decorations which probably won't match.
What I'm gathering is that this would need to be implemented some other way and/or through integration per compositor (the major ones being KWin, mutter and wlroots). Given that we're talking about transferring focus between windows within the same application, I feel this should be possible and/or a valid enough use case to work, but right now I don't know how to approach it.
I could certainly imagine a Wayland protocol extension that allows transferring focus between different window handles created through the same Wayland socket. It'd probably even be less controversial than GNOME's decision to refuse to support the server-side window decoration protocol in favour of forcing every application to either link against GTK or implement their own decorations which probably won't match.
I think what we're looking for might be XDG activation and this example. It's Qt 6.3, so I can't test this on my own machine yet, but I'm updating a VM to test this out. Looking at the Qt source code, it seems this might actually solve this issue entirely. I'm finding this change to be promising at least.
So I got good news and I got bad news.
Good news: I can confirm Qt 6.3 is helping here. No more warning about QWindow::requestActivate
.
Bad news: The problem now is that any logic related to screen coordinates (not too surprisingly) doesn't work at all. So while you can detach stuff, re-attaching stuff doesn't work. Similarly, moving widgets around is extremely buggy. At best, you might find an attachment point at random
It appears the "Wyaland way" to move things around to use a postioner. Unfortunately, as you see the documentation is rather lacking. I don't know if there is a Qt inteface to positioners.
In DomTerm I use the drag and drop builtin to modern web browsers, using my fork of GoldenLayout. That seems to mostly work.
I also implemented a hybrid approach in Qt, using a combination of QWidgets and QWebEngineView. An outer QWebEngineView contains the GoldenLayout UI as well as the window titlebar. Each subwindow has it own child QWebEngineView or more generally a child QWidget. This works pretty well. One possible downside is that it is rather resource-hungry, making use of QtWebEngineView, at least for the docking UI. If you're using that anyway, it seems a reasonable option.
It appears the "Wyaland way" to move things around to use a postioner. Unfortunately, as you see the documentation is rather lacking. I don't know if there is a Qt inteface to positioners.
Well, it's lacking since it's unofficial, draft documentation you're reading right there. There are other (also unofficial) sources covering xdg_positioner. The closest I'm getting in Qt is QWaylandXdgPopup, but that seems more for menus and other pop-ups, not moving individual windows around. It also corresponds to xdg_popup, so not the same thing. The Qt documentation itself doesn't seem to even reference xdg_positioner even though there clearly is something implementing it
Searching more around, it seems this is not working in Qt right now
- https://bugreports.qt.io/browse/QTBUG-91483
- https://bugreports.qt.io/browse/QTBUG-87332
- https://bugs.kde.org/show_bug.cgi?id=453558
It seems to all cumulate down to this though
Wayland does not allow global/absolute positioning only relative and ADS seems to rely on global.
I close the issue because it is a Qt problem and not an ADS issue