Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wayland does not support QWindow::requestActivate() #288

Closed
PerBothner opened this issue Dec 30, 2020 · 15 comments
Closed

Wayland does not support QWindow::requestActivate() #288

PerBothner opened this issue Dec 30, 2020 · 15 comments

Comments

@PerBothner
Copy link

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.)

@PerBothner
Copy link
Author

A work-around is to set XDG_SESSION_TYPE. For example:

 XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo

@githubuser0xFFFF
Copy link
Owner

githubuser0xFFFF commented Dec 31, 2020

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.

@PerBothner
Copy link
Author

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.)

@PerBothner
Copy link
Author

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.

@ssokolow
Copy link

ssokolow commented Oct 15, 2021

To give some context that previous comments are lacking:

  1. 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]
  2. 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.)
  3. 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])
  4. 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?)

@AHSauge
Copy link

AHSauge commented Aug 12, 2022

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.

@ssokolow
Copy link

ssokolow commented Aug 12, 2022

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.

@AHSauge
Copy link

AHSauge commented Aug 12, 2022

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.

@AHSauge
Copy link

AHSauge commented Aug 13, 2022

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

@PerBothner
Copy link
Author

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.

@PerBothner
Copy link
Author

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.

@AHSauge
Copy link

AHSauge commented Aug 13, 2022

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

@AHSauge
Copy link

AHSauge commented Aug 13, 2022

@tytan652
Copy link

tytan652 commented Oct 21, 2022

Wayland does not allow global/absolute positioning only relative and ADS seems to rely on global.

@githubuser0xFFFF
Copy link
Owner

I close the issue because it is a Qt problem and not an ADS issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants