virtualdesktops: Add per-output desktops
Add the ability to switch virtual desktops independently for each output. Short demo:
Related MRs:
- plasma-workspace: plasma-workspace!6139 (merged)
- plasma-desktop: plasma-desktop!3427 (merged)
- plasma-wayland-protocols: libraries/plasma-wayland-protocols!122 (merged)
- kwayland: kwayland!138 (merged)
- develop-kde-org: documentation/develop-kde-org!797 (merged)
- kdeplasma-addons: kdeplasma-addons!1034 (merged)
Disclosures
- AI:
- None of the submitted code is AI generated. I wrote all of it myself (largely by copying existing code).
- I used OpenAI Codex in the following ways:
- I used it to generate a quick prototype to give me an idea of where to start. The prototype was MUCH more limited and I rewrote it from scratch (i.e. none of the code submitted here is from there).
- I used it to help me with debugging/understanding some of the stuff new to me (e.g. how does a value get to QML, wayland protocols, understanding crashes, ...).
- I used it to review the code before submitting it (in addition to manually reviewing it myself). It caught a few minor issues.
- I used it to write a "touchpad simulator" patch that I used for testing touchpad gestures (not submitted).
- I have a very limited prior experience with C++ (<10k LoC at school, 6+ years ago). I have no prior experience with Qt, CMake, etc.
- I've been a full-time PHP programmer for 6+ years. So it's possible that I made some mistakes in stuff that I'm not used to thinkining about: data ownership, null pointers, memory leaks, use after free, undefined behavior, ...
- I'm new to KDE. I only installed it on an old laptop a few months ago and I used it for only a few hours since then. So it's possible that I missed/misunderstood some functionality.
- I've been using AwesomeWM at work (6+ years). So the inspiration for how the per-output desktops should work comes from there.
- Motivation:
- I wanted to challange myself a little bit by trying to work in an unfamiliar environment.
- I'm looking to switch to Wayland for fractional scaling etc. The lack of per-output desktops is preventing me from using Plasma (though there may be other blockers as well).
- I'm mostly available only on weekends (not necessarily all weekends).
Behavior
Here is a summary of the behavior (with per-output desktops enabled) from the user perspective:
- Virtual desktops exist independently of screens.
- Each screen can show any virtual desktop (1 at a time).
- Each virtual desktop can be shown on any number of screens.
- Each window belongs to 1 screen (even if it spans multiple screens), and to any number of virtual desktops. The window is visible if its screen shows one of the virtual desktops that the window belongs to.
- Switching desktops via keyboard shortcuts (and most other methods) affects the currently active screen.
- API allows you to switch any screen to any desktop.
If you want to try it yourself, I prepared AUR packages which backport the changes to Plasma 6.6. Read the instructions carefully. Use the AUR packages at your own risk (ideally in a VM, not a work machine etc).
Please note that the functionality implemented by this MR does NOT work like Hyprland etc, where workspaces are separate for each screen and switching to a workspace activates its screen as well. This is not because I'm not aware of the alternative behavior, but because I prefer it the way I implemented it. I'm aware that some/many people are going to be disappointed by that. But there is no one right way that is going to satisfy everyone. Had I implemented it the Hyprland way, I'd dissappoint different people.
If you're one of the people who would prefer a Hyprland-like behavior, please keep in mind that if this MR succeeds, it doesn't mean that all is lost for you (there's no reason that KWin can't eventually support both). Not only are you no worse off than before (the current behavior of having the same desktop on all screens is supported), this MR actually implements a lot of the stuff that you'll need to implement the behavior that you want (e.g. you can't have a Hyprland-like behavior, if you can't show different desktops on different screens).
Implementation
The current desktops are tracked separately for each output. The old behavior of switching all outputs at once is optionally enforced by KWin whenever a desktop changes on any output. However, this detail is hidden by the VirtualDesktopManager and all other components see the desktop changes independently for each output.
VirtualDesktopManager::current, currentDesktop, setCurrent, ... optionally accept the output with fallback to active output for compatibility. Hopefully, this should smooth over some of the things that I might have missed since desktops are probably mostly switched for the active output.
Limitations
The per-desktop outputs are only supported on Wayland (no X11 or XWayland) for the following reasons:
- X11 uses some sort of standardized protocol (EWMH), so I didn't want to mess with that.
- AFAIK X11 support is set to be removed in Plasma 6.8. XWayland will presumably remain, but I'm not sure whether there are any use-cases for XWayland stuff needing to see/set the current desktop. If there are, they'll still be partially covered by the "active output" fallback.
Building
The MRs depend on each other (this also causes the build pipelines to fail). They are meant to be built (and eventually merged) in the following order:
- plasma-wayland-protocols,
- kwayland (only necessary for tests),
- kwin,
- plasma-workspace,
- plasma-desktop,
- kdeplasma-addons (only necessary for cube effect),
- develop-kde-org (only documentation).
My test setup
I used the following setup to develop this feature. I'm documenting it here in case it helps you see that I did something wrong.
- I'm developing it on ArchLinux (physical machine).
- I set up kde-builder and built
workspace(I haven't tried anything that's not in workspace). - I set up a fresh EdeavourOS VM (libvirt). I specifically installed it with Gnome to make sure that there are no KDE components other than those that I compiled myself.
- I set up the VM with 2 displays and I'm connecting to it via virt-viewer.
- Unfortunately, virt-viewer seems to break when I try to disable one of the displays. So that limited my testing of this scenario.
- Disabling the display in Plasma also seems to be broken.
- I mostly tested dynamically added and removed displays via screensharing's virtual screen.
- I installed kde-builder in the VM and ran
kde-builder --install-distro-packages. - I have
~/kdemounted as a shared folder in the VM. - I installed the development sessions inside the VM.
- I'm making code changes on the physical machine. Then I run e.g.
kde-builder --no-src --no-include-dependencies kwin. Then I log out and back in in the VM and try the changes. - I did a very limited testing on my secondary laptop where I mounted
~/kdevia NFS. This was mainly to double check touchpad gestures and dynamically added/removed displays.
TBD
I plan to deliver the following things later:
- kwayland changes: once the Wayland protocol changes are agreed upon.
-
PlasmaVirtualDesktopManagementInterfacetests: once the Wayland protocol changes are settled. - kdeplasma-addons cube effect: After KWin API changes are approved.
- Update KWin scripting API docs: After KWin API changes are approved.
Things I'm not sure about
- I'm not really sure which APIs are supposed to be public and which aren't.
- D-Bus API: I'm not sure what it's for and if/how it needs to be updated. I found some people using it in their custom scripts on Github.
- SessionManager: It has some code that's supposed to save and restore the last used desktop. But it's not clear to me whether it works. It seems that the last used desktop is restored via activities (though kwin can be compiled without activities, so maybe that's why). For now I didn't touch it.
-
DesktopBackgroundItemuses current desktop, but I didn't figure out how to trigger it. -
WindowHeapDelegate.qmlhaspresentOnCurrentDesktopwhich may now be incorrect. But I didn't manage to find a scenario where the property has any noticeable effect. - I didn't manage to figure out how to run the tests in
tests/directory. So I have no idea whether I broke something there.
New feature checklist
This feature does not meet all of the requirements stated in README, but I'm hoping that there's some leeway.
it does not violate the primary missions as stated at the start of this document
Hopefully not.
it does not introduce instabilities
I'm not aware of anything now, but it's definitely possible.
it is maintained, that is bugs are fixed in a timely manner (second next minor release) if it is not a corner case.
This is a one-time thing for me. I'm not looking to become a regular contributor to KDE. I will try to fix issues reported in the review and get this merged. I may help with issues reported after that, but I'm not promising anything. Therefore, if you're not willing to maintain it yourselves you should reject the MR.
it works together with all existing features
It does work with all the features that I was able to find (except as mentioned above).
it supports both single and multi screen
Yes.
it adds a significant advantage
Yes (IMO).
it is feature complete, that is supports at least all useful features from competitive implementations
Yes, there are no competitive implementations (in kwin) that I'm aware of.
it is not a special case for a small user group
I'm not sure. People with multiple displays are definitely going to be a minority. And not all of them will be using virtual desktops. And not all of those might have an issue with how they work now.
it does not increase code complexity significantly
That's up to you to determine.
it does not affect KWin's license (GPLv2+)
There are no license issues. Everything is either written by me from scratch, or derived from existing KWin source.