MAY
31
2016

New Plasma Task Manager backend: Faster, better, Wayland

During the last several months, I've been rewriting the backend for Plasma's Task Manager, the strip of launchers and windows embedded into the panel at the bottom of the screen.

Plasma Task Manager widget
My current Task

What's in a Backend

The backend's responsibility is to gather (or store) pinned launchers, startup notifications and window information, and combine all that raw data into the abstraction known as tasks, forming a rough lifecycle: Launchers transition into startup notifications and then window buttons, though none of these states is technically required or guaranteed, resulting in the need to be able to match up each type of thing with any other based on what is known about them. Along the way the data is also filtered (e.g. by activity or virtual desktop), sorted (say, alphabetically, or at the user's behest, when tasks get dragged around) and optionally grouped.

The code currently performing these duties has been with us a long time—it goes back to, incredibly, KDE versions released some 16 years ago. Rewriting it finally became necessary as part of our ongoing efforts to add support for the Wayland windowing system to Plasma, as the old code was heavily tied to X11 concepts and window metadata. However it also had some fundamental limitations and problems that badly needed addressing, and was written to engineering standards we've since surpassed in the community (e.g. it wasn't unit-testable, while the new backend is written to be).

The Goods

As such the new backend certainly enables the Task Manager to support Wayland, but also immediately translates to various improvements for users on X11, as well as the developer audience:

  • Improved performance. On virtual desktop or activity switches, or certain settings changes, the old backend would trigger a full reset of the Task Manager UI, requiring costly reinstanciation and relayout of all the buttons. The new backend is smart enough to only make the changes necessary each time, saving a lot of cycles.

  • Improved behavior, particularly when grouping tasks. The old backend could act unreliably and unpredictably at times, failing to properly reform groups after virtual desktop switches, or losing sort order for tasks in a group when the group was broken apart. A much cleaner internal implementation of grouping should do away with these sort of annoyances. Further, a key task of the backend is to determine that two different types of things (say, a launcher and a window) belong to the same application, based on their metadata—these types of equivalence checks were sometimes done in subtly different ways across different parts of the old backend, such as sorting and grouping. The new backend consistently uses the same data and business logic in all cases, making behavior more predictable. Additionally, changes made in the system Menu Editor (e.g. selecting a different icon for an application) now appear immediately in launcher and window buttons, instead of taking their time or even requiring a restart.

  • Improved memory usage. The old backend would keep data for windows common to virtual desktops or activities redundantly, as well as store some icon data not actually used anymore by modern codepaths. The new backend keeps less data, and keeps it only once.

  • Cleaner and more maintainable code. After 16 years of development and maintenance, the old backend had turned into a big hairy ball. Along with a lack of unit tests, this kept us from fixing some of the above issues for fear of breaking more in the process. The new codebase benefits from being written to the list of requirements gathered over all those years. It knows much better how to separate its concerns, and implements features such as sorting and grouping agnostic to the underlying windowing system. The new code being much easier to work with will also enable us to translate user feedback into Task Manager changes much more readily again.

  • Improved Wayland support. While more work remains to be done to get task management to feature parity with X11, this is now largely a matter of supplying the new backend with the data it needs, feeding into upper layers ready to consume it and fully shared between both supported windowing systems. The much improved Wayland support will also enable the task management backend to be shared between Plasma Desktop and Plasma Mobile for the first time.

Now nearing completion, this new backend will undergo heavy testing and polish over the next several weeks. We hope to ship it with the upcoming Plasma 5.7 release.

Comments

Hey,

thanks for the answer, I'll check weechat/terminology upgrades. The user claims it was by the recent 5.6.4 upgrade, but we can never be sure about that, maybe terminology/weechat got an upgrade too which breaks it.

The "demant attention" hint is useful, I'll check further - a point to start at least :-).


By STiAT at Wed, 06/01/2016 - 11:48

We're using Fedora 25 which I think has plasma 5.9. Task manager grouping is not working for us because we use multiple desktop java apps and all the windows from all the apps get grouped together with the name java. I am a developer but know nothing about KDE. Can you direct me to where in the code the grouping is determined. Alternately if you know someone able to make changes for us we can likely work out some kind of payment for the work. Thanks!


By Darren at Wed, 06/14/2017 - 22:10

plasma-workspace.git/libtaskmanager/taskgroupingproxymodel.cpp

Do note that this is most likely broken apps and will have to be fixed in the apps rather than in libtaskmanager. Feel free to submit a bug ticket with info though.


By eike hein at Thu, 06/15/2017 - 10:54

I would love it if we could fix it in the apps. They are internal and I'm very familiar with them. Can you describe any more details about what might correct it on an app level?

The same apps group the way we'd like on older KDE and on LXQT and Mate in Fedora 25 but we'd prefer to stick with KDE.


By Darren at Mon, 06/19/2017 - 16:57

Use 'xprop' on the windows, and make sure the second string in the output for WM_CLASS is something unique for every app. The way to set that is toolkit-specific (e.g. Qt and GTK+ do the right thing for you automatically). Have a search for WM_CLASS + your Java GUI framework.


By eike hein at Mon, 06/19/2017 - 17:11

Thanks for the help. This blog page details the problem and solution http://elliotth.blogspot.it/2007/02/fixing-wmclass-for-your-java.html. The code below is the key

   Toolkit xToolkit = Toolkit.getDefaultToolkit();
   java.lang.reflect.Field awtAppClassNameField =
       xToolkit.getClass().getDeclaredField("awtAppClassName");
   awtAppClassNameField.setAccessible(true);
   awtAppClassNameField.set(xToolkit, applicationName);

By Darren at Mon, 06/19/2017 - 18:01

Sweet! Glad it worked out.


By eike hein at Mon, 06/19/2017 - 18:26

Sorry to bug you again. Two of our internal apps were fixed with the solution I posted before. Two other apps that I used the solution on are still behaving as if the solution has not been applied. Below is the output of xprop on the main window of a misbehaving app. The second string of WM_CLASS is set to "Omega" which is what I want displayed in the task manager when windows are grouped.

When there is only one window open, task manager displays "Omega Database Search v6.5" when a second window is opened, the task manager displays "java" and if one of the other apps with the same problem is opened, they are all combined under Java on the task manager.

Any other ideas I can check out?

NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x3, 0x1, 0x1, 0x0, 0x0
_MOTIF_DRAG_RECEIVER_INFO(_MOTIF_DRAG_RECEIVER_INFO) = 0x6c, 0x0, 0x5, 0x0, 0x39, 0x0, 0xc0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0
XdndAware(ATOM) = BITMAP
_NET_WM_STATE(ATOM) = 
WM_HINTS(WM_HINTS):
                Client accepts input or input focus: False
                Initial state is Normal State.
_NET_WM_ICON(CARDINAL) =        Icon (14 x 13):
                      
                      
             ████     
           ██    ██   
           █      █   
          █        █  
          █        █  
          █        █  
           █      █   
           ██    ██   
             █  █     
          █  █  █  █  
          ████  ████  


_NET_WM_PID(CARDINAL) = 27955
WM_CLIENT_MACHINE(STRING) = "REDACTED"
WM_PROTOCOLS(ATOM): protocols  WM_DELETE_WINDOW, WM_TAKE_FOCUS
_KDE_NET_WM_USER_CREATION_TIME(CARDINAL) = 91075067
WM_CLASS(STRING) = "sun-awt-X11-XFramePeer", "Omega"
WM_CLIENT_LEADER(WINDOW): window id # 0x5c00008
_NET_WM_ICON_NAME(UTF8_STRING) = "Omega Database Search v6.5"
WM_ICON_NAME(STRING) = "Omega Database Search v6.5"
_NET_WM_NAME(UTF8_STRING) = "Omega Database Search v6.5"
WM_NAME(STRING) = "Omega Database Search v6.5"
WM_NORMAL_HINTS(WM_SIZE_HINTS):
                user specified location: 703, 183
                program specified location: 703, 183
                program specified size: 1205 by 872
                window gravity: NorthWest
[[email protected] ppd]# clear
[[email protected] ppd]# xprop
_NET_WM_ICON_GEOMETRY(CARDINAL) = 2277, 2116, 355, 42
_NET_WM_ALLOWED_ACTIONS(ATOM) = _NET_WM_ACTION_MOVE, _NET_WM_ACTION_RESIZE, _NET_WM_ACTION_MINIMIZE, _NET_WM_ACTION_SHADE, _NET_WM_ACTION_MAXIMIZE_VERT, _NET_WM_ACTION_MAXIMIZE_HORZ, _NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_CHANGE_DESKTOP, _NET_WM_ACTION_CLOSE
_KDE_NET_WM_FRAME_STRUT(CARDINAL) = 6, 6, 41, 6
_NET_FRAME_EXTENTS(CARDINAL) = 6, 6, 41, 6
_NET_WM_DESKTOP(CARDINAL) = 0
_KDE_NET_WM_ACTIVITIES(STRING) = "c1fa5cc2-4677-4c04-be5f-acb5e59840b1"
WM_STATE(WM_STATE):
                window state: Normal
                icon window: 0x0
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x3, 0x1, 0x1, 0x0, 0x0
_MOTIF_DRAG_RECEIVER_INFO(_MOTIF_DRAG_RECEIVER_INFO) = 0x6c, 0x0, 0x5, 0x0, 0x39, 0x0, 0xc0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0
XdndAware(ATOM) = BITMAP
_NET_WM_STATE(ATOM) = 
WM_HINTS(WM_HINTS):
                Client accepts input or input focus: False
                Initial state is Normal State.
_NET_WM_ICON(CARDINAL) =        Icon (14 x 13):
                      
                      
             ████     
           ██    ██   
           █      █   
          █        █  
          █        █  
          █        █  
           █      █   
           ██    ██   
             █  █     
          █  █  █  █  
          ████  ████  


_NET_WM_PID(CARDINAL) = 27955
WM_CLIENT_MACHINE(STRING) = "REDACTED"
WM_PROTOCOLS(ATOM): protocols  WM_DELETE_WINDOW, WM_TAKE_FOCUS
_KDE_NET_WM_USER_CREATION_TIME(CARDINAL) = 91075067
WM_CLASS(STRING) = "sun-awt-X11-XFramePeer", "Omega"
WM_CLIENT_LEADER(WINDOW): window id # 0x5c00008
_NET_WM_ICON_NAME(UTF8_STRING) = "Omega Database Search v6.5"
WM_ICON_NAME(STRING) = "Omega Database Search v6.5"
_NET_WM_NAME(UTF8_STRING) = "Omega Database Search v6.5"
WM_NAME(STRING) = "Omega Database Search v6.5"
WM_NORMAL_HINTS(WM_SIZE_HINTS):
                user specified location: 703, 183
                program specified location: 703, 183
                program specified size: 1205 by 872
                window gravity: NorthWest

By Darren at Thu, 07/06/2017 - 16:56

Does the app install an Omega.desktop file, or any .desktop file with StartupWMClass=Omega in it?


By eike hein at Fri, 07/07/2017 - 05:35

No this app does not have a .desktop file at all. The applications that are working the way I want do have .desktop files but there is no StartupWMClass line in them.

I created an Omega.desktop file and the name on the task bar still changes to java instead of Omega when a second window is opened. I also tried with a StartupWMClass=Omega but there was no difference.


By Darren at Mon, 07/10/2017 - 17:14

Pages