Prevent application activation on startup / hide application programmatically
-
Hello everyone,
This is (mainly) a Macos question.
One of my app should be able to switch from a "run in the background" mode (with no window at all) to a full-featured GUI mode (e.g. with windows, and also dock icon and menu on the Mac).
This app starts in background mode, with no window.
Unfortunately, MacOS automatically activates the app, even if it has no QWidget shown at all. Hence, for example, MacOS displays the app's menu in MacOS menu bar, even if the app has so far no window shown.Ideally, I would need to prevent the app's activation on startup.
I also investigated various other potential solutions, all of which resulting in a question.So, here are the questions ! :
1/ Do you know if a QApplication can "hide" itself programmatically ("hide" in the sense of MacOs show/hide an application, as in the App's menu on the Mac, and hopefully in a portable C++ way).
2/ Do you know if a QApplication can "unactivate" itself programmatically (ie. ask the OS to switch activation to the latest activated application, hopefully in a portable C++ way) ?
3/ Do you know how a QApplication can refuse an activation request received from the OS (eg deny a ApplicationStateChange event, received when the app is activated) ?
I guess this is not possible : activation of an application is the OS decision, and is already achieved when the app's receives an "has-been-activated" event.4/ yet again more mac-specific... Are you aware of C++ way to change a QApplication "type" ( in the sense of MacOS, that is switch for example the app's MacOS' LSUIElement from false to true) ?
Thank you very much for your attention !
Nicolas -
@NicolasC
Hi,
Have a look at LSUIElement
I used it a couple of times for background apps.Sorry, I didn't see you mention LSUIElement already.
I have an old mac app that doesn't appear at first launch, only at the second one.
Maybe you can catch a Reopen event with an event filter (or native filter) on QApplication. -
Hi,
It sounds a bit like it should be a service/front end architecture. Can you explain your use case ?
Note that it just came to my mind that the PostgresApp works a bit like this except it has an icon in the system tray. Otherwise it's not visible.
-
Hello, and thanks for your answers and hints.
@mpergand said in Prevent application activation on startup / hide application programmatically:
I have an old mac app that doesn't appear at first launch, only at the second one.
Maybe you can catch a Reopen event with an event filter (or native filter) on QApplication.
In my case, all the Qt apps appear (and activates) at first launch. So a Reopen event (which I do not find in QEvent) is not it.@SGaist said in Prevent application activation on startup / hide application programmatically:
It sounds a bit like it should be a service/front end architecture. Can you explain your use case ?
Yes sure ! Here is a more detailed description :
- AppA is a full featured app. It launches AppB, and communicates with AppB. Possibly, multiple versions of AppB can execute at the same time.
- AppB is aimed at performing computations (sound synthesis by physical simulation, sexy ! :)). It is also a full featured QApplication : it creates a GUI, menus, etc, but these are not always shown. On the Mac, AppB also should always have an icon in the Dock (hence, setting LSUIElement true is not the best option)
- At start, AppB has no GUI when it is launched by AppA - it starts as a 'background app' for AppA.
- Hence, at start AppB should not be "activated" by the OS - that is : AppA, should remain the OS' active app when it launches an AppB.
- Still, from AppA, the user can send a message to AppB to request it to display its GUI. Likewise, on the Mac, the user can also click on AppB icon in the Dock. In both case, AppB reacts by showing its window(s), and AppB should become the active app.
Hence, globally speaking, my issue is to get control over appB activation (prevent activation at start ; ensure activation when GUI is shown).
On Linux (and windows), AppB is not activated by the OS if its windows are not shown at start. OK !
But, problem :
On the Mac, it was OK some years ago. But starting as far as I remember with Qt5.9 // macos X.13 (??) : AppB gets activated automatically at sartup, even when none of its GUI is shown (hence AppA looses its active state when launching AppB, which is painful when the user launches multiple AppB one after another).FInally @SGaist
Note that it just came to my mind that the PostgresApp works a bit like this except it has an icon in the system tray. Otherwise it's not visible.
Thanks for the hint. In fact, PostgresApp's structure is different. It is made of numerous (~<10) processes. One is a system-tray app (no icon in the dock, no main menu...). It can launch another app, which automatically activates itself (as my AppB does... but in the case of Postgres'app it is normal since this "child app" has always a main window )
-
And no comes a reply to myself !
We figured out how to hack towards the behaviour we need.
1/ we add an ObjectiveC .mm file to the project, to call somme MacOS Cocoa's stuff
2/ At application AppB startup, from this ObjectiveC file we call
[NSApp hide:nil]
which "hides" the application, and reactivate our AppA.
Well... This turns into some flickering of the active application (because AppA looses for a few ms activation when AppB starts ; then AppB hides itself and AppA gets the active app again), but we can live with that !
Thanks
-