Mac-style menubar for KDE 4 and others

Every two weeks I get a question about the state of (no, not Okteta, he) the port of the Mac-style menubar to KDE 4. Obviously because I once tried to work on it, but then stopped (and nobody took it up).

In the time around the KDE 4.2 release the frequency of this question has risen, including one email from Markus Slopianka, who pointed me to the “Global Menu Bar for GNOME” project, thanks for the hint.

Guess it’s time for me to at least place some information about the state of global menubars for KDE/Qt in a Planet KDE-feeded and googleable document, to have the information flowing and perhaps create some more action somewhere πŸ™‚ Because myself I won’t work on this anytime soon, given my TODO list and the priorities attached.

Personally I would like it very much if there is a Mac-style global menubar as option also for the FLOSS desktops/shells. One that is supported by all the common FLOSS toolkits, like Qt/KDE Libs, GTK+ (GNOME/XFCE/Mozilla/OOo),
Γ‰toilΓ©/GNUstep, Enlightenment Foundation Libraries and maybe more…
Or think of the NextStep-style menu (free floating vertical menu) as alternative option.

I would already be pleased if this works only for the toplevel menu entries, as listed in the menubar, so the submenu popups would be delivered again by the individual toolkit.
Still I could imagine that for menus without any special needs, e.g. custom rendered menu options, also all submenus could be shown by such a “X menu server”. And also the context menus. They are in separate windows anyway, so why not have them displayed by a third party (Another stage would be something like XMLGUI for all toolkits).

The above mentioned project “Global Menu Bar for GNOME” might be good candidate to be the central project to bring this feature into life. Looking at their roadmap it seems they have already reached some useful insights, working code, developers and are open for toolkit-independent solutions.

For KDE support of a Mac-style menubar has always been rather a hack, both in the past (KDE 3) and currently (KDE 4), see below for some detailed explanations. Best would be to put proper support directly into Qt. Like there is a special handling of the menubar for OS X, there could be one for FLOSS desktops/shells/X.org, given some well-defined standard system.

The following passage about the state in Qt/KDE is basically based on input/text from Thomas LΓΌbking, of Baghira and Bespin fame, added by me with info of my own stalled try with a KDE 4 port:

KDE 3

On KDE 3, menubars were ripped out of the application window (as supported by KMenuBar) and XEmbedded into a special Kicker panel/applet. The Kicker plugin then acted as a simple WM, monitoring activeWindow changes and selecting the proper menubar in accordance. This has it’s limits:

  • It could not be post-applied (e.g. via a Qt style) to Qt-only programs, as Qt (at least many programs) does not like it too much if you just take away it’s QMainWindow::layout()->menuBar()
  • It can be distracting if remaining part of the program but inside the window of another one. Especially if the program freezes and (from a user point of view) Kicker becomes inresponsive.

Next to the default KDE Kicker applet there was a special variant of the applet provided with the Baghira style.

KDE 4

As a user of the Mac-style menubar I tried to port the Kicker applet to Plasma in time for KDE 4.0. As the support in KWin and KMenuBar in the KDE Libs was already ported (almost no changes needed), I thought this to be easily done.

The Plasma applet was started in playground, almost an 1:1 port of the Kicker applet from KDE 3. I got stuck a little with some XEmbedded problems, then found out that there are other problems, which had also already hit Thomas, who might even have tackled this problem before me, and deeper and harder, as he is in the Qt style business πŸ™‚ Simply embedding the menubar widget (as X window element) in Plasma is not so straightforward as with Kicker.

Plasma/Oxygen

The core problem is Plasma, or to be more precise, the Oxygen theme, or to be even more preciser…er, the fact that it uses inverted colors by default.
Oxygen – as most styles – at least by default uses dark text on a bright window, but the default Oxygen Plasma theme is pretty much white on black.
Unfortunately the menubars, better the Qt style used for it, don’t know too much about the current Plasma themes colors. So even if you can convince the menubar to paint an X-wise transparent background (removing the backing store usage) you’ll likely end up with painting black text onto a black background….
All in all the menubar, though embedded into a Plasma panel, is not part of the Plasma program, it does not get auto-informed about theme and/or color settings or changes.

XBar

The XBar is developed by Thomas as part of the Bespin style. It uses a client/server approach to the Mac-style menubar. Currently it’s only used by the Bespin Style to post apply clients to Qt4 based programs. The only currently existing server is a Plasmoid, also part of the Bespin project.

For the client/server approach D-Bus is used as IPC for a most simple protocol. This resolves from the color issues and also allows to “do stuff” with the visual menubar (such as manipulating the string of the first entry or inject pseudo entries without having to fear side effects). Thomas chose D-Bus as it’s fast, reliable, tested … and the default IPC used by KDE and Qt πŸ˜‰

How it works

The server (aka the XBar plasmoid) registers itself as org.kde.XBar to the D-Bus session bus.
It provides functions to

  • add/remove complete menubars alongside a unique id
  • add/remove/change menu entries (for that unique id)
  • change the unique id (that’s e.g. the original menubars mainwindow which could change due to reparenting)
  • focus change requests (whether a client want’s its menubar to be visible now)
  • be informed that a popup actually appeared (this is technical, to allow visual status updates)

The clients (aka Bespin styled menubars) register as org.kde.XBar-<PID> to provide a central hook for an internal dispatcher (i.e. you can have as many menubars per program as ever you want).
They provide functions to

  • activate/deactivate the global menu usage (i.e. (un)hide the internal menubar)
  • open/close the popup for some menubar index
  • get notified that a menubar index was hovered (so they can decide to open the attached popup, depending on whether another popup is already open)
  • (raise the attached window – that’s rather a gimmick, you can change the current XBar menubar by mousewheeling and some XBar setup provides functions to do stuff with the window like raising/closing it ect.)

Processing

Right after starting up, the server calls all clients for activation. If they’re interested, they’ll register themselves to the server and hide the internal menubar.
When the server dies, it calls all clients for deactivation. (Both functions can of course be used w/o the server, e.g. by a simple bash script that allows you to click a window to toogle the global menu usage on or off).

As soon as a client starts it looks for an existing server and activates itself registers to the server and hides the internal menubar.
When the client dies, it unregisters from the server.
(In case a client segfaults, the server has a timer triggered cleanup routine that removes bodies every few seconds, so the user will usually not be confused with inoperative menubars)

Together the whole thing works “automagically” – you don’t have to change settings or so. Just add the server plasmoid and the global menus will start working. Remove it, and you return to the common MS-style menubars.

With the registration, the client sends the server a stringlist containing the strings for the cliented menubar. If in case of e.g. Kate the menubar is initially more or less empty and then gets and changes items later on, the server just gets the updates and repaints.

Whenever a cliented window gets activated, it requests it’s menu to be shown by the server. If it falls inactive, it tells the server to unset the menubar (i.e. it’s no more interested in its menu being shown)

The server implements a (in case of Plasma QGraphics-) widget that acts more or less like a simple menubar. (I.e. it holds a list of items, calculates their positions, watches mouse position changes, thus triggers hover events, etc.)
When the user selects an item and presses the lmb, the server sends a request to the current client to popup (or down – NOTICE: this should be changed to just one trigger notification) the attached client. The client then pops up (or down) the popup at the position demanded by the server and informs the server which popup is now open (for visual status updates).
The server also informs the client whenever the hovered item changes and this way allow it to change the currently open popup (popup sliding).

Implementation specifics:

  • The server currently uses QStyle to paint the items, but nothing would prevent us from e.g. making use of plasma theme elements.
  • The post-applied proxy-menubar implementation in Bespin has it’s drawbacks:
    • It’s pretty much a giant hack, as taking away or even just hiding the menubar isn’t very much appreciated by Qt
    • It’s not perfect and i’m not sure whether every issue (see below) can be addressed this way

What does not work (yet…)

Keyboard usage:
Using menu shortcuts will open the popups inside the window.
On the other hand, if you open a popup with the mouse, you cannot change to open popup with the left/right arrow keys. (Thomas simply was never interested in neither).

Closing the initially opened popup by clicking the “not-window” (aka. the desktop or other windows) if you change the open popup (even forth and back) “click-to-close” works as expected (some mouse grabbing issue)

Icons and non-label actions in the menubar:
Icons aren’t important, but Thomas doesn’t know what to do e.g. with Konqueror’s throbber (aside especially this thing being hardly more than annoying).

General Drawbacks

  • Links D-Bus for every program
  • Sometimes (with opera?) there can be a slight delay when changing the active window leading to the “no active menubar” content being displayed for a moment and thus flicker.

End of Thomas’ text. Thanks for this deep insight, Thomas. πŸ™‚

See here a screenshot of Bespin and the XBar in action (warning, fancy styling for having some fun when creating this post):
XBar from Bespin
Really, this is not my own desktop setup. Proof: I am still with good old KDE 3.5 πŸ™‚ How can I? KDE 3.5 works great, even if some have forgotten this. Never change a running system without strong needs. Still I see myself for going for KDE 4.3, given that all my little KDE 3 applets I am so used to (like the Khalkhi applet, oh, and the Mac-style menubar) have been ported until then.):

Zoom, zoom… sliding in and out with Okteta

Remember the days when some people considered KDE4 to be in the land of Hurd and Duke Nukem Forever? Now already KDE 4.2 is just around the corner, and looking greater then ever. I am so happy there is the Oxygen team with KDE πŸ™‚ And the storm-resistent Plasma people are really pushing the desktop to new highs. Plus KWin is really stunning (even for the poor people stuck with XRender, or can I do more with my Ati Rv 250? How exactly?)

Also in the module of the KDE Utilities, kdeutils, things have moved forward: Ark and KGpg have seen a lot of improvements and fixes, thanks to Harald Hvaal and Yew Ming Chen for Ark and Rolf Eike Beer for KGpg. Then David Johnson has given KCalc more love, and Michael Leupold has brought KWallet in the kdelibs and the KDE Wallet Manager into a usable state again. Furthermore Okteta has been advanced by me.

For most developers though KDE 4.2 is already history again. KDE 4.3 is the next goal.
Some new things have also been committed for Okteta already, including the next brilliant and unique feature in the land of hex editors (it’s rather fun stuff πŸ˜‰ ):
Know the problem of having your colleagues looking over shoulders onto your screen to get something presented, but they cannot decipher anything due to the longer distance from the screen?

See this strange three letters here?

Okteta with zoom of 100 %

No? Wait… *zoom, zoom with the slider* Here!

Okteta with zoom of 313 %

Making it possible to adjust your tools to your needs, isn’t that the core idea of FLOSS? πŸ™‚

PS: Sure, you can zoom the view in Okteta since its first release in KDE 4.1, but it’s hidden in the menu for most, or did you know about Ctrl+[+]/[-]?