Exploring Plasma's System Tray Widget
A user on reddit recently asked how to resize a few widgets. With the “Notes” widget, it is pretty straight forward by changing the Layout.preferredWidth
/ Layout.preferredHeight
as outlined in KDE’s Getting Started with Plasma Widgets article on the KDE wiki. However the user wanted to resize the System Tray and had no idea how to do so.
I personally wouldn’t recommend a new user modify the system tray, as it uses some fairly complicated code in order to embed other widgets inside itself (like the panel). However, this offers a learning opportunity for the reader on how a Plasma Widget is written, so lets jump down the rabbit hole.
Compact / Full Representations
First a refresher on how Plasma widget’s are structured.
A widget has 2 different “views”. The compact area that’s shown when there’s not much space, like when it’s in the panel, and the full view when there is enough room, which is shown in a popup.
When we do not define the full view, the main Item is treated as the full representation.
When we do not define the compact view, Plasma uses a “default” compact representation that displays the icon defined in the metadata.desktop
or the icon defined with Plasmoid.icon
.
We can also ignore the “compact” representation, and show the full representation in the panel. With this, the widget will not have a popup.
The System Tray Widget
The System Tray widget is a specical beast. In order for it to work, it needs to embed other widgets inside itself (like the panel). It embeds the Volume widget, the Network widget, the Notification widget, etc. Normal widgets (aka applets) cannot do this. It needs to be a special ContainmentInterface instead of the standard AppletInterface that a widget uses.
To get around this, the System Tray widget has a public “container” widget under the namespace org.kde.plasma.systray
, which has some C++ magic to load a single private widget org.kde.plasma.private.sytray
.
Notice how the “public” widget sets preferredRepresentation
so that we only have a “full representation” as the default view with no “compact view”. It doesn’t set the Plasmoid.fullRepresentation
so this means the main Item is the full representation. And when the “private” internalSystray
widget is loaded, it sets adds it as a child of the main Item (called id: root
in this case).
So, in order for the user to edit the system tray’s popup size, we don’t want to modify the “public” container widget’s code. Instead we want to edit the private code under org.kde.plasma.private.sytray
.
SysTray’s Private Widget
Navigate to the systray’s private widget /usr/share/plasma/plasmoids/org.kde.plasma.private.systemtray/
, then open up it’s contents/ui/main.qml
.
I’m not quite sure where it defines full/compact representations. However this private widget is definitely different as it defines it’s own Dialog popup. I think that since it’s loaded as a ContainmentInterface, it needs to define those itself.
Note: The dialog for a normal widget is defined in
plasma-desktop
repo under desktoppackage/contents/applet if you’re interested in comparing them.
Back to the system tray widget. Now with the PlasmaCore.Dialog, the size of the dialog is the same size as the Dialog.mainItem
, so if we look at it we see that the mainItem
is passed an ExpandedRepresentation {}
. If we look in the contents/ui/
folder, we see that there is an ExpandedRepresentation.qml
file. So lets open that up as there does not seem to be any width/height definitions in the main.qml
file for the dialog.
And there we go. Layout.minimumWidth
/Layout.minimumHeight
is what is controlling the size of the system tray width/height.
Changing the SysTray Popup Height
Again, I do not recommend changing the system tray widget. It’s actively being updated and bugfixed. However we can modify it for learning puposes.
If we add import QtQuick.Window 2.2
to the top of the ExpandedRepresentation.qml
file, we can then use QML’s Screen variables like Screen.desktopAvailableHeight
. Normally we should probably using plasmoid.screenGeography.height
, however it appears that variable isn’t “defined” in this widget as it’s set to be a 0x0 rectangle.
If we set height to Screen.desktopAvailableHeight
, the system tray popup should be the same height as our screen!
We can test with the following. Note that we do not use the private namespace.
Cool. Now lets try to get the popup to slide in from the right!
If we go back to the private system tray’s main.qml
and look at the PlasmaCore.Dialog
once more, we can see that the dialog specifies which location/edge/direction the dialog should appear from.
If we look at the API docs for the PlasmaCore.Dialog, we’ll see that the property is a Plasma::Types::Location enum value. So we should be able to change plasmoid.location
to a hardcoded value of PlasmaCore.Types.RightEdge
to make it slide in from the right.
In the above example, I restarted Plasma to test in my panel. As you can see, while it does animate the slide in from the right, it’s no longer positioned above the system tray. The reason why it’s on the left side of the screen is because it’s trying to position itself to the “left” of my bottom panel, just like we saw with the plasmawindowed
window up above.
This is because the Dialog.visualParent is set. If we remove the visualParent: root
line of code, the popup will now appear at the default location of (0,0)
, or the top left of the screen.
Now lets move the popup to the right side of the screen. We’ll set the dialog’s x-coordinate to be the “width of the screen” minus “width of the dialog”. Don’t forget to add the import to the top of the file!
This is just for fun!
Reminder that editing files in /usr/share/plasma/plasmoids
not recommended. Whenever your system updates Plasma, the files will be overwritten with an updated version with bugfixes + new features, or just revert it back to the original file.
While we could copy the system tray’s code to the home directory, I would not recommend doing this for the system tray, as it has a lot of C++ code that works with the QML view code, and using and older version of QML code you modified with new C++ code after a Plasma update could possibly cause PlasmaShell to crash. So while a system tray that opens from the right side of the screen is neat, a KDE Plasma tweaker should probably keep it as is.