[KDE/Mac] [OS X/Wayland] using WIds created by a different process to create KMessageBox'es and other widgets/windows
René J.V. Bertin
rjvbertin at gmail.com
Wed Dec 9 12:29:41 UTC 2015
Several classes exist that have the possibility to create widgets or windows from a Qt WId, and those are used (exclusively? mostly?) by certain helper agents like the kwalletd to display dialogs parented by a window from the application that sent the request that justified posting the dialog in question.
This procedure works fine on X11 where there is a single server that provides and controls the basic UI elements (windows) and where a WId is (presumable) something that translates to an X11 window reference. On OS X (and MS Windows?), a WId is in fact cast from a pointer to an instance of a native widget class (QNSView, QNSWindow; QCocoaView in Qt4), and using these from a different process can evidently lead to a SIGSEGV.
Yet applications like kwalletd are not out of place on platforms that are not X11 ... and I understand from Martin that the same or a highly comparable situation exists with Wayland.
I'd like to start a discussion on how this can be dealt with. Qt does not keep track of who "owns" each existing WId (not on OS X at least), but until now QWidget::find(WId) has always returned NULL for me when given an invalid WId (including those owned by another process).
A function like createWIdDialog (in KWidgetsAddons) already detects this, and can be adapted to handle this situation differently where required (it currently calls setMainWindow() when QWidget::find returned NULL and the WId isn't NULL itself). For a KMessageBox it would then make sense on OS X to call a platform function to ensure that the dialog is posted in front; i.o.w. in front of all windows rather than where the owning application decided to place the window (WId). (Not doing anything of the sort would mean the dialog opens in the "layer" of the background application, i.e. somewhere behind most or all other open windows).
I'm working on an OS X plugin for KWindowSystem, so a priori I should be able to provide an appropriate activateWindow implementation.
I'd appreciate suggestions what classes that allow to create instances from WIds should provide this "in your face" approach if the target WId comes from another process.
KWindowSystem::setMainWindow() is a different matter. Firstly, it does NOT use the plugin architecture currently, but simply assumes that QWindow::fromWinId() will always work (and never crash). For the time being it will thus require ifdefs. Beyond that, exactly how should I adapt it? Never do anything on OS X (the solution used currently in KDELibs4/MacPorts)? Or check the result from QWidget::find() and only do its job when that function returns a valid pointer (which could actually be the general approach if that find() function isn't expensive on platforms where calling it is redundant).
Beyond that I suppose that setMainWindow() is *not* the place to push the new window to the foreground so that it doesn't get overlooked - or is it?
In other words, what exactly is the role of KWindowSystem's main window?
PS: I did indeed write a native, "Keychain backend" (SecKeyChain) for KWallet4, but after having used and polished that backed for over a year I think it is not feasible to provide a satisfactory implementation that maps enough of the KWallet feature set to the much more restricted SecKeyChain API. Applications depending on KWallet (and their users) are better off with an adapted kwalletd that functions correctly, IMHO.
More information about the kde-mac