[KDE/Mac] QProcess for GUI apps on OSX (Re: closest equivalent to KApplicationPrivate::init() ?)
David Faure
faure at kde.org
Tue Jan 5 11:55:57 UTC 2016
On Tuesday 05 January 2016 11:58:49 René J.V. Bertin wrote:
> It's not that it is so different. My gripe is with the use of the word and concept GUI. I'm going to have to figure out exactly what GUI aspects are only available to app bundles on OS X currently, and to what extent LaunchServices can be used to start regular executables without delegating to Terminal.app.
Yes. Such additional data would be useful in this decision making process.
> OTOH, I think that NormalLaunch vs. GUILaunch could do it. That leaves the nature of the application open, and applies the concept to the launch procedure, which is appropriate.
OK.
> Apologies if this is what you had in mind all along...
No worries, we're both evolving our thoughts as the discussion progresses.
> >of behaviour differences which cannot be described as a simple feature-based enum. That's unfortunate. Is there any
> >chance for a less intrusive solution to make QProcess bring up the window?
>
> The central issue here is the fact that it is near impossible to tell windows from another application what to do, on OS X, and to know when it'll listen to such instructions (which appears to be required here). The only way I found for the calling process to bring the new application to the front involves using AppleScript in a way it wasn't really designed to be used. I doubt that would ever be acceptable for inclusion into Qt, partly because it can only be a polling algorithm, and it requires either invoking an external utility or else linking to AppleScript itself.
> It's not impossible though that the service being invoked through AppleScript ("System Events") can also be invoked directly, but I don't think it'd qualify as "less intrusive". More like "reinventing the wheel".
I'm surprised it's that complex, and that an OSX app cannot launch another one and have it appear in front.
Is there no app with an action that starts a calculator, a special-character selector, etc.?
Is there no alternative application launcher? ...
Surely there must be a way to do this without polling or scripting.
> >Otherwise I have another idea, calling the flags NormalLaunch (the current behaviour) and DetachedLaunch.
>
> Or GUILaunch, see above?
Works for me, but I guess we need more data to know exactly what the flag would entail.
> >If you look at the way krun.cpp uses QProcess, it answers the above: start, waitForStarted(), getting PID with processId(), and notification of exit with exit code
> >(among other things, to terminate startup notification). [1]
> >This means startDetached is not good enough, btw, I realize now: we need to get notified when the process exits.
>
> That might be tricky. I don't know if LaunchServices provides such a feature or if one would need to tap into even lower-level stuff like Mach ports (Mach, not Mac ;)). Applications do receive an "about to exit" message though, possibly even a "will exit" message (the difference being that you can prevent the exit in the former whereas the latter is a notification of impending doom). It's possible that Qt already catches that message, in which case it should be possible to emit a signal which can then be used in QProcess.
This assumes that such messages can be captured from *another* process (the Qt app). From your description, it doesn't sound like that's the case,
if it's a message being sent to the process which is about to exit.
SIGCHLD is the posix way for a parent process to know that a child process just exited, but that's not available for "detached" processes (not children),
and probably not when using LaunchServices either (also not a child).
I doubt QProcess catches anything else at the moment.
> >Wild idea:
> > startDetached(const QString & program, const QStringList & arguments,
> > const QObject * receiver, const char * member,
> > const QString & workingDirectory = QString(), qint64 * pid = 0)
> >
>
> I've been wondering why startDetached() wouldn't return a QProcess instance. No such instance is created internally in the current implementation, but it seems it should be possible to do so
I'm pretty sure it isn't possible to do so because that QProcess instance wouldn't be able to emit finished (see above).
> BTW, I see krun uses KProcess. I wasn't aware of that class; could we use it as a testbed to develop this whole idea before submitting it to Qt? Is there a reason KInit doesn't use KProcess -- it already depends on KIo which depends on KCoreAddons so it wouldn't mean pulling in new dependencies?
KProcess is just a subclass (wrapper) with historic API and with the feature of launching a command through a shell (which is what KRun uses it for).
It doesn't change anything of the core implementation of the actual handling of a child process.
If you want to hack one instead of the other for experimentation purposes, why not, but I don't think it will make it any easier to work on the wrapper
(which has no access to the QProcess internals).
> >- a new QGuiProcess class, tailored to starting GUI apps:
> > No channel handling.
> > Always start detached (i.e. killing current process won't kill secondary gui app).
> > And always uses LaunchServices on OSX.
> >Maybe all the above is just the reasoning that justifies having a separate class, to avoid having methods that don't apply.
>
> Would QGuiProcess inherit QProcess?
No because that would still have the issue of offering API for channel stuff and unavailable signals.
> There's the issue with LaunchServices delegating to Terminal.app for certain applications, but one could say that's a side-effect users of QGuiProcess will have to take into consideration.
That sounds like an expected result of GuiLaunch or QGuiProcess. You ask for a GUI, you start a commandline exe, you get a GUI terminal running that command.
> >[1] (BTW a notification that the process is all up and ready for interaction is, I think, impossible technically, we don't know what the app is doing; anyway, not needed).
>
> It is possible on OS X. Don't ask me how, but it is exactly what the polling in the AppleScript algorithm mentioned above waits for. Checking if the PID is running isn't enough, the process has to be registered somewhere else, and as long as that's not the case (= the app is starting up) it won't listen to the "activate" instruction.
OK. Yes I was thinking at the process layer. In the graphical layer you can of course check that your event is being processed by the event loop
of another app, if that event expects a reply. I suppose one could cook that up with X11 too - but I'm not aware of a need for that.
It's rather surprising that the events are not queued until the app processes them.
--
David Faure, faure at kde.org, http://www.davidfaure.fr
Working on KDE Frameworks 5
More information about the kde-mac
mailing list