Bug 339333 - making non-gui applications
Summary: making non-gui applications
Status: RESOLVED FIXED
Alias: None
Product: buildsystem
Classification: Developer tools
Component: KDE4 (cmake) (show other bugs)
Version: unspecified
Platform: Compiled Sources macOS
: NOR minor
Target Milestone: ---
Assignee: Alexander Neundorf
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-23 15:01 UTC by RJVB
Modified: 2018-11-12 10:06 UTC (History)
3 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
possible/proposed changes to KDE4Macros.cmake and K*Application to let applications marked NOGUI in the CMake file be built with GUIenabled=false by default (3.04 KB, patch)
2014-09-23 20:52 UTC, RJVB
Details
companion patch for kde-runtime::kglobalaccel, which is incompatible with the kdelibs patch (508 bytes, patch)
2014-09-23 20:59 UTC, RJVB
Details
companion patch for kde-runtime::kglobalaccel, which is incompatible with the kdelibs patch (1.85 KB, patch)
2014-09-24 13:57 UTC, RJVB
Details

Note You need to log in before you can comment on or make changes to this bug.
Description RJVB 2014-09-23 15:01:57 UTC
A lot of the helper applications that are defined/created as NOGUI in their respective CMake files actually do get a rudimentary GUI on OS X: a bare-bones Application menu and a presence in the application switcher and on the Dock (usually with a default icon).

This appears to be the case because the don't create their `KApplication` or KUniqueApplication` (or `QApplication`) instance with `GUIEnabled=false`. I'm a bit at a loss why this wouldn't be required on Linux, but on OS X it clearly is necessary in order not to give the application a visual presence.

2 questions:

- is it safe to modify the code to create the aforementioned instance with something like `app(false)` so that somewhere down the line Qt does *not* load its Cocoa initialisation (load its `nib` file etc)?

- if so, why wouldn't the CMake file add a preprocessor macro (e.g. `KDE_WITHOUT_GUI`) so that NOGUI applications can be created by setting a flag in a single location? It would even be possible to change the default value of the `GUIEnabled` ctor argument depending on that macro ...

Reproducible: Always

Steps to Reproduce:
1. launch a helper application like kwalletd, that's defined NOGUI in its CMake file


Actual Results:  
On Linux, the application runs in the background, without creating a GUI. On OS X, it creates a GUI with a bare-bones Application menu and presence in the Dock and the application switcher.

Expected Results:  
No presence on OS X as on Linux
Comment 1 Christoph Feck 2014-09-23 15:17:06 UTC
> On Linux, the application runs in the background, without creating a GUI

If you use KApplication without GUIEnabled=false, even on linux it will connect to the X server. For kwalletd, however, I guess this is wanted, because it asks for passwords?
Comment 2 RJVB 2014-09-23 15:34:09 UTC
Connecting to the X server isn't an issue in itself because it doesn't create a visual presence - and of course a moot point on OS X and other non-X11 platforms. 
I'm not sure if kwalletd asks for passwords itself, or just serves to (re)distribute Wallet calls. In any case it apparently doesn't need to be a GUI application to do that.

(and that might explain why its dialogs don't always open in front of all other windows?)

I'm rebuilding kdelibs git/4.14 with the modifications described above (-DKDE_WITHOUT_GUI and GUIenabled defaulting to false in that case). If that solves the issue with the "unwanted icons in my Dock" (currently 3, there's be 4 or even 5 without my OS X keychain patch) I'll fire it off into a RR and hope someone will test it on Linux.
Comment 3 RJVB 2014-09-23 20:52:24 UTC
Created attachment 88822 [details]
possible/proposed changes to KDE4Macros.cmake and K*Application to let applications marked NOGUI in the CMake file be built with GUIenabled=false by default

This patch modifies KDE4Macros.cmake to add a -DKDE_WITHOUT_GUI compile flag to executable targets defined with NOGUI, and changes the default settings for KApplication and KUniqueApplication to GUIenabled=false .
Comment 4 RJVB 2014-09-23 20:53:42 UTC
this patch is for kdelibs, of course
Comment 5 RJVB 2014-09-23 20:59:00 UTC
Created attachment 88823 [details]
companion patch for kde-runtime::kglobalaccel, which is incompatible with the kdelibs patch

It turns out that the kglobalaccel is defined as a NOGUI application (and indeed behaves as such on Linux), but requires a GUI on OS X.
This can be corrected by removing the NOGUI label from the CMake file (if that doesn't interfere with the way the application is built on other OSes). The patch resolves the issue by undefining KDE_WITHOUT_GUI before including kapplication.h .
Comment 6 Ian Wadham 2014-09-24 07:02:20 UTC
This is interesting. You may be getting to the bottom of a long-standing mystery: why some KDE apps have default icons and appear sometimes in the Dock, even though you do not know what they are or whether you started them somehow. There are others that have an icon, but only show it when they start running. When "resting" they have a default icon.

Another oddity is kdeinit4, which is built as a GUI app and installed as one, in /Applications/MacPorts/KDE, because it needs to be able to start GUI apps, but it never appears in the Dock and cannot be Force Quitted, because it has a special bundle file, kdelibs/kinit/Info.plist.template, containing the lines:
    <key>LSUIElement</key>
    <string>1</string>
See https://developer.apple.com/library/mac/documentation/general/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/20001431-108256
Comment 7 RJVB 2014-09-24 09:26:05 UTC
(In reply to Ian Wadham from comment #6)
> This is interesting. You may be getting to the bottom of a long-standing
> mystery: why some KDE apps have default icons and appear sometimes in the
> Dock, even though you do not know what they are or whether you started them
> somehow. There are others that have an icon, but only show it when they
> start running. When "resting" they have a default icon.

I think that was never a big mystery. KDE has plenty of helper applications, some of which need to be able to present a GUI. Most of these never get an icon, not even when they're installed inside an app bundle, for the simple reason that they don't have one on Linux. The notable exception example is kwalletd, which doesn't live in an app bundle, doesn't have an icon (this could have been done in the resource fork on 10.6 and earlier) but gives itself an icon when started.
Sadly it turns out that not all those NOGUI applications can actually do without a GUI, or rather require something in Qt's initialisation procedure that also loads the qt_menu.nib (cleverly copied into $TMPDIR so that each application has its own instance even when not in an app bundle).

Another good counter example is kded4. Like kdeinit4 it's not a NOGUI app, and yet it has neither menu nor presence in the Dock; it uses the same LSUIElement "trick". One could try to apply that to other agents, like kglobalaccel, nepomukfilewatcher, etc.

> Another oddity is kdeinit4, which is built as a GUI app and installed as
> one, in /Applications/MacPorts/KDE, because it needs to be able to start GUI
> apps, but it never appears in the Dock and cannot be Force Quitted, because

Well, it doesn't appear in the Force Quit dialog. It's not immune to SIGKILL or any of the other signals you can send it.

> it has a special bundle file, kdelibs/kinit/Info.plist.template, containing
> the lines:
>     <key>LSUIElement</key>
>     <string>1</string>

The Property List Editor calls that key "Application is agent (UIElement)" (missing indefinite article not my omission). That seems to be perfectly appropriate ...
Comment 8 RJVB 2014-09-24 10:28:23 UTC
(In reply to RJVB from comment #7)

> > it has a special bundle file, kdelibs/kinit/Info.plist.template, containing
> > the lines:
> >     <key>LSUIElement</key>
> >     <string>1</string>
> 
> The Property List Editor calls that key "Application is agent (UIElement)"
> (missing indefinite article not my omission). That seems to be perfectly
> appropriate ...

And this is what "does it", in the CMake list defining kdeinit4:

  set_target_properties(kdeinit4 PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.template)
  set_target_properties(kdeinit4 PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kde.kdeinit4")
  set_target_properties(kdeinit4 PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "KDE Init")

and for kded4:

if (Q_WS_MAC)
    set_target_properties(kded4 PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.template)
    set_target_properties(kded4 PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kded.kded4")
    set_target_properties(kded4 PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "KDE Daemon")
endif (Q_WS_MAC)
Comment 9 RJVB 2014-09-24 11:05:07 UTC
> if (Q_WS_MAC)
>     set_target_properties(kded4 PROPERTIES MACOSX_BUNDLE_INFO_PLIST
> ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.template)
>     set_target_properties(kded4 PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER
> "org.kded.kded4")
>     set_target_properties(kded4 PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "KDE
> Daemon")
> endif (Q_WS_MAC)

Adding adapted statements to the nepomukstorage and nepomukfilewatcher CMake files indeed made those services disappear from Dock and menubar. 

Now to figure out how to achieve the same thing for kglobalaccel, because that one doesn't live in an app bundle (and thus has no Info.plist).
Comment 10 RJVB 2014-09-24 13:54:43 UTC
Comment on attachment 88823 [details]
companion patch for kde-runtime::kglobalaccel, which is incompatible with the kdelibs patch

diff --git kglobalaccel/main.cpp kglobalaccel/main.cpp
index 4d230b8..73d3b43 100644
--- kglobalaccel/main.cpp
+++ kglobalaccel/main.cpp
@@ -21,6 +21,14 @@
 
 #include "kglobalacceld.h"
 
+#ifdef Q_OS_MAC
+// kglobalaccel is defined NOGUI in the CMakeFile, but should not initialise with GUIenabled=false
+// so I have to undo the automatic propagation of NOGUI I just created in kdelibs4
+#undef KDE_WITHOUT_GUI
+// we'll need CoreFoundation; see below
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
 #include <kuniqueapplication.h>
 #include <kaboutdata.h>
 #include <kcmdlineargs.h>
@@ -44,7 +52,6 @@ static void sighandler(int /*sig*/)
        qApp->quit();
 }
 
-
 extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
     {
     // Disable Session Management the right way (C)
@@ -54,6 +61,20 @@ extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
     // get a hang on kglobalaccel restart (kglobalaccel tries to register with ksmserver,
     // ksmserver tries to register with kglobalaccel).
     unsetenv( "SESSION_MANAGER" );
+#ifdef Q_OS_MAC
+    CFBundleRef mainBundle = CFBundleGetMainBundle();
+    if( mainBundle ){
+        // get the application's Info Dictionary. For app bundles this would live in the bundle's Info.plist,
+        // for regular executables it is obtained in another way.
+        CFMutableDictionaryRef infoDict = (CFMutableDictionaryRef) CFBundleGetInfoDictionary(mainBundle);
+        if( infoDict ){
+            // Add or set the "LSUIElement" key with/to value "1". This can simply be a CFString.
+            CFDictionarySetValue(infoDict, CFSTR("LSUIElement"), CFSTR("1"));
+            // That's it. We're now considered as an "agent" by the window server, and thus will have
+            // neither menubar nor presence in the Dock or App Switcher.
+        }
+    }
+#endif
 
     KAboutData aboutdata(
             "kglobalaccel",
Comment 11 RJVB 2014-09-24 13:57:23 UTC
Created attachment 88829 [details]
companion patch for kde-runtime::kglobalaccel, which is incompatible with the kdelibs patch

New patch for kglobalaccel, exploiting the LSUIElement "trick" that an application can use to register itself as an agent (service) with the OS.
Comment 12 RJVB 2014-09-26 12:13:57 UTC
Git commit 4da7a503903240fe7ccf67db1fe0eeb8c8073dc3 by René J.V. Bertin.
Committed on 26/09/2014 at 12:13.
Pushed by rjvbb into branch 'master'.

[OS X] turn kglobalaccel into an "agent", removing it from Dock
and application switcher, using a CoreFoundation-based programmatic
approach equivalent to setting LSUIElement=1 in an Info.plist .
REVIEW:120354

M  +22   -0    kglobalaccel/main.cpp

http://commits.kde.org/kde-runtime/4da7a503903240fe7ccf67db1fe0eeb8c8073dc3
Comment 13 Andrew Crouthamel 2018-11-12 02:47:53 UTC
Dear Bug Submitter,

This bug has been stagnant for a long time. Could you help us out and re-test if the bug is valid in the latest version? I am setting the status to NEEDSINFO pending your response, please change the Status back to REPORTED when you respond.

Thank you for helping us make KDE software even better for everyone!
Comment 14 RJVB 2018-11-12 10:06:15 UTC
This has been fixed in KF5 with ecm_mark_nongui_application