"This Week in KDE Apps" is back! It's been a long time since the last issue, but every week, we cover as much as possible of what's happening in the world of KDE apps.
Getting back to all that's new in the KDE App scene, let's dig in!
Yuki Joou improved the handling of sender information in the mail viewer header (25.12.0 - link). She also fixed the mail composer not showing the right sender address (25.12.0 - link).
Merkuro Calendar Manage your tasks and events with speed and ease
Yuki also worked on Merkuro Calendar and fixed adding sub-items to tasks (25.12.0 - link), added a menu button to show/hide all calendars from an account (25.12.0 - link), and made sure we are only showing one refresh button in the account context menu (25.12.0 - link)
Supporting PIM libraries
Volker Krause made some more parts of the KMime API const correct and adapted various parts of the PIM codebase to that.
Allen Winter made Akonadi prefer MariaDB to MySQL when both are available (25.12.0 - link).
A Pixel 3a with postmarketOS running KRetro on Plasma Mobile
KRetro is a libretro frontend from KDE written in Qt with Kirigami! That means when given both a libretro core, and a game cartridge/disk ROM, it plays your favourite games. It is designed to be convergent, usable across all Plasma Platforms: Desktop, Mobile and Bigscreen.
What is Libretro?
You may have heard of RetroArch, a popular and famously portable retro game emulator frontend with a console-style UI. One of the important innovations from RetroArch is libretro, a standard API that can adapt the many numbers of independent game console emulators to a single program. This is what allows RetroArch to support a vast number of systems without needing to build support for each bespoke emulator into the frontend itself.
A libretro “core” is simply a .so/.dylib/.dll dynamic library file that packages an emulator (or an independent game), and can be loaded into any application that can consume it using the libretro.h C API specification.
Through the libretro API, cores are adapted to the native Qt interface of KRetro (for example, pixels are drawn onto a QImage, audio is rendered out using Qt Multimedia, and reading keyboard events is handled by the QML engine).
The Road to KRetro
KRetro screenshots – Desktop game view and player view, and the mobile player view.
KRetro’s development started in 2023 with a desire to help build more apps for Plasma Mobile (shout out to Devin for the idea and help along the way). I worked on it for a while, but unfortunately got busy with school and other things. In addition, the Qt 6 transition came and went, which left KRetro effectively abandoned.
The name? The K-prefix naming has mostly been phased out these days in KDE for new apps… you could say it is a retro naming scheme
What KRetro Can Do Today
As you probably guessed, this is an Alpha quality release, and while I did my best to have the experience be polished, you should expect bugs and missing features.
The Game Library view on KRetro – a list of game ROMs
More importantly, KRetro is not feature complete. This release is intentionally limited – I wanted to make sure the scope was not too large so meaningful progress can be made towards a release.
As of this first alpha release, KRetro can play games from the following fixed list of consoles:
Nintendo Entertainment System/Famicom
Super Nintendo Entertainment System/Super Famicom
Game Boy Advance
Sega Master System
Sega Genesis/Mega Drive
libretro 2048 (a built-in demo game)
KRetro Controller Settings Page
KRetro also supports fully mappable controls for both keyboard and controller inputs, though only 1 port is available for now (so no multiplayer). Controller support is provided by SDL3 (and keyboard input is handled directly from the QML engine).
Per-game save states menu in KRetro
KRetro has a system for managing save states for each of your games, including a default save slot that automatically saves and restores your game progress when you quit and launch KRetro.
The Road Ahead: What’s Left to Do?
Lots! In fact, too many things to list here in detail. There are a number of big ticket items though, like enabling OpenGL/Vulkan support for cores (this will allow supporting most 3D consoles, like the N64, Wii, or Playstation), or allowing arbitrary core+rom combinations (allowing users to select any of the 200+ libretro cores they want, instead of having a fixed list of consoles as it is currently).
There are also lots of smaller quality of life features, for example:
Supporting more than 1 controller
Improve the touch controller layout on tablets
A better game/ROM list with extended metadata
Save state screenshots
And many more…
The Mobile platform also needs some more love specifically, like having transparent and customizable touch controller layouts.
Plasma Bigscreen support is generally pretty rough (given that Bigscreen itself isn’t released yet either), there is only basic remote navigation support for selecting games, and all other parts of the UI require a mouse to reach (such as the settings page).
KRetro has also at one point in the past run on Android (which is to say – it should be able to run on Android, but this hasn’t been tested in quite a while, and is probably broken), and iOS builds have never been attempted (however it has been run on macOS).
Does any of these features interest you, and you want to help out? Do you have more ideas? Come and contribute on the KDE Invent page!
Trying out KRetro
Sonic the Hedgehog on KRetro
Given that this is the first release, and an alpha quality release, KRetro is not packaged on any distros yet. The easiest way to experience KRetro if you are on x86_64 is to use the nightly flatpak:
$ wget https://download.kde.org/unstable/kretro/0.0.1/kretro-0.0.1.tar.xz
$ tar xvf kretro-0.0.1.tar.xz && cd kretro-0.0.1/
$ mkdir build && cd build
$ cmake .. # install required dependencies if needed
$ make -j${nproc}
$ ./bin/kretro # or sudo make install
Besides installing KRetro, you will also need some libretro cores. On the nightly flatpak, these are already bundled in for you, and you’re ready to play games! If you install KRetro manually, the recommended/tested cores are as follows:
Nestopia for NES
snes9x for SNES
mGBA for GBA
Gearsystem for SMS
BlastEm for Genesis/MD
Some distros (like Arch and Alpine) already package these, so you can install them from their package managers (ex. pacman -S libretro-snes9x). Once installed, you can select them for use in the KRetro settings.
Games are detected and matched to their respective console type by their file extension, so all you need to do is place your game ROMs in “~/Documents/Games” (or another folder of your choosing).
For general discussion (especially if you want to contribute), I recommend you join the KDE Games Matrix room.
And last but not least, if you would like to develop and hack on KRetro, you can find everything you need at: https://invent.kde.org/games/kretro
Thank you!
Thank you for reading this far! I hope you will try out KRetro and enjoy it, and I hope the KRetro community will grow too!
I would like to give a special thanks to Devin Lin for his invaluable help, without him KRetro would never have gotten this far. I’d like to also give thanks to Carl Schwan for helping me along the KDE development process, his contributions to KRetro, and for being my sponsor for getting KDE developer status.
In 2016, after being a Mac guy for 23 years, I took the plunge and made a full-time switch to Linux. I did my research, and over and over again encountered the idea that GNOME was good for MacOS refugees like myself. So I gave it a try!
But my experience didn’t support the meme. I think a lot of people make this assertion without really having a deep understanding of the MacOS user experience, or the actual positive qualities of the software, because I don’t think GNOME offers a particularly Mac-like experience at all.
Don’t get me wrong, I think GNOME shell is pretty good, and largely succeeds at doing what it sets out to do. But that thing does not appear to be “offer an experience that’s a lot like MacOS.”
I still see this mentioned on forums and YouTube videos today. I don’t think it’s helpful, and today I want to provide a bit of context from my perspective.
So let’s compare MacOS and GNOME! Right away we see some obvious differences:
One of the the two major anchoring user interface (UI) elements on MacOS is the dock. It’s an app launcher and switcher, an unread count notifier, a place for minimized windows to go, a quick shortcut to the trash, downloads folder, and any other files or folders you put on it.
GNOME doesn’t have this. Its anchoring UI element is the Activities Overview screen, which contains a small program launcher, but the whole thing is hidden by default, meaning it can’t be easily used for monitoring unread counts or switching between apps. It’s also not customizable at all, while the MacOS dock is extensively customizable. It’s just a very different experience.
Global menubar and app functionality
The other major anchoring UI element is the global menu. Every Mac app exports a global menu structure, including the desktop itself. This allows Mac apps to be visually simple, because all the powerful features are hidden away in the menu structure.
GNOME has a top bar, but there’s no global menu on it. And while GNOME apps do generally have a level of visual simplicity that’s similar to Mac apps, they’re usually more limited in functionality, and they don’t export menu structures full of extra features.
Desktop icons
On MacOS, you can put files and folders on the desktop, and use it for managing frequently or recently used files. Internal and removable drives appear there, too.
GNOME doesn’t have this. The desktop is just a picture; you can’t use it for anything functional.
Window minimize/maximize buttons
On MacOS, if you need to get a window out of your way, you minimize it, just like you do on Windows, Plasma, etc. It flies into the dock and it’s clear how you get it back. You can also maximize a window from another button on the titlebar, and it goes into another.
GNOME apps have neither of these buttons. As a result, it’s not clear how to get a window out of the way or make it bigger without a lot of manual work. You can add those buttons later using the separate Tweaks app, but it’s clear that the system was not designed for it.
At-a-glance app status monitoring
MacOS includes a classic “System Tray” style UI on the top bar holding the global menu. Here apps can put little icons that communicate their state while running but without any visible windows. The MacOS dock also displays unread counts and progress information for running apps.
GNOME doesn’t have these features, either at all, or in a way that’s always visible. Instead, it relies on apps sending notifications about changes to their status.
Configurability
Contrary to popular belief, MacOS is surprisingly rich in personalization options. You can customize the widgets on the desktop or notification center, the text size, highlight colors, sidebar icon sizes, places panel items, screensaver, scrollbar appearance and behavior, lock screen message, menubar positioning, UI alert sound, almost everything about the dock, and so on.
GNOME’s approach to configuration is much more minimal, and the officially-supported options are pretty sparse. Instead, mostly the way you personalize the system is by using Extensions, which can do much more than you can in MacOS, but also offer no long-term compatibility guarantee, so there’s a chance any of the extensions will break with every new release.
So where does the bridge from MacOS lead?
Again, I think GNOME is pretty good… it just doesn’t offer a MacOS-like experience. What it does offer is a near-zero distraction experience. That’s the design goal, and it succeeds. But it’s not MacOS’s design goal.
So if not GNOME, where’s the more MacOS-like experience for refugees? Honestly, KDE Plasma is what I would recommend. It’s where this MacOS refugee ended up, at least. Let’s compare again, but this time with KDE Plasma:
Like MacOS, Plasma has a dock-style panel. Despite a few visual differences, it handles the same things: launching apps, switching between apps, seeing apps’ unread counts, and holding minimized windows. This panel also contains the System Tray UI. It’s here rather than on a top panel, but it’s a small difference.
Though neither screenshot shows files on the desktop, both support it. Similarly, both support desktop widgets for building highly personalized workflows.
You can also minimize and maximize windows in Plasma just like you can on MacOS.
And finally, you can personalize a Plasma system in a wide variety of ways — as much or more than you can can on MacOS, in most cases — and all in a 1st-party supported way. There are also GNOME-style extensions available for people who want even more, but these make use of a stable API that only changes about once every 10 years, so compatibility issues are much rarer.
There are still differences, of course: major ones are Plasma’s Windows-start-menu-style Kickoff Application Launcher and the lack of a global menu. But Kickoff can be swapped out for something else or removed, and the Global Menu is actually a fully-supported 1st-party feature, simply being off by default. If this is a part of MacOS that you really like, turning it on is very easy:
Other smaller differences include disks not appearing on the desktop, and maximized windows not going into new virtual desktops.
But in my opinion and experience, these differences are relatively minor, and I don’t think it’s worth chasing the dream of a 100% pixel-for-pixel clone of MacOS on Linux. Rather, I think it’s best to take the most successful parts and ditch the sources of awkwardness. And in my opinion, KDE Plasma fits the bill.
So if you’re leaving MacOS because you found it too distracting, then I think GNOME may be a good option. But if you’re leaving for other reasons, give Plasma a try!
A few months ago, we announced that LabPlot had received funding from the NGI Zero Core fund. This was to help us focus on three features we’ve wanted to add for a while: Analysis of Live Data, Python scripting, and more statistical analysis functions.
We’re pleased to announce that we have now completed the main goals for this project. As part of the new statistical functions, we’ve added a comprehensive suite of statistical hypothesis tests:
One-Sample t-Test
Independent Two-Sample t-Test
Paired Two-Sample t-Test
Welch t-Test
One-Way ANOVA Test
One-Way ANOVA with Repeated Measures Test
Mann-Whitney U Test
Wilcoxon Signed Rank Test
Kruskal-Wallis Test
Friedman Test
Log-Rank Test
Chi-Square Independence Test
Chi-Square Goodness of Fit Test
These new features have been implemented and will be ready for you to use soon. We hope they will be a valuable addition for our users. This work was made possible by the financial support from the NLnet Foundation and the European Commission through the Next Generation Internet Program, and we are grateful for their contribution.
The work on LabPlot continues, and our team is already busy on the next set of improvements and functions. As always, your feedback is important in guiding our next steps. We look forward to sharing more updates with you in the future.
In the past two months since the last updateKDE Itinerary got the ability to use the current location as a starting point for journey
searches, a currency converter and the ability to store hotel room details, among many other improvements.
New Features
Journey searches starting at the current location
The current device location can now be used as a starting point for journey searches.
Current location option in departure location search.
The same blog post also covers the newly added currency converter. While Itinerary was
able to show currency conversion rates since some time already
it now also allows to enter arbitrary values and get those converted in either direction.
Currency converter.
Hotel room details
Another addition is a new field in hotel reservations to record room numbers or room access codes,
which is particularly useful in hotels where you are presented with all that just on a display
during (automated) check-in, rather than a physical key or paper card.
In about two weeks there’s the first edition of the Open Transport Community Conference
in Vienna, Austria. That covers many topics highly relevant for Itinerary, from
public transport routing over liberating public transport schedule data to ticket barcodes, to just name a few.
Excited to see what will come out of this.
There’ll also be two more OSM Hack Weekends, one in Berlin
and one in Karlsruhe.
Infrastructure Work
Served transit modes at stops
For public transport data backends supporting this, KPublicTransport can now also
list the served modes of transportation or even the served public transport lines for stops in geocoding
queries.
This allows for a more detailed display of location search results. The current location search UI doesn’t
make use of this to the fullest extent yet though, only generic mode icons are shown based on this so far.
Transit modes in location search results.
This is currently available with OpenTripPlanner and Hafas-based backends,
and will also benefit KTrip.
Matrix trip synchronization
There has been some progress on the long-promised Matrix-based trip synchronization
between different instances of Itinerary. In particular, the synchronization code can now properly handle
the Matrix event size limit and transparently place larger elements into encrypted files. It also covers
all of Itinerary’s internal data types (reservations, transfers, live data, Wallet passes and documents) meanwhile.
There’s still issues to work out around the edges, especially the first moments of syncing a new trip and the very last ones
when deleting a trip.
Android SDK 35 support
Itinerary together with all other KDE applications for Android and their underlying stack had to be adapted to work correctly with
the now mandatory edge-to-edge mode of Android SDK 35. If this works correctly you wont notice a difference, apart from a few
places with fullscreen content. Without it things would have either looked very broken or we would not have been
allowed to update via the Google Play store anymore.
Fullscreen content expanding to the screen edge.
There’s a separate post with more details on this topic.
This allows to fix issues in the input data that we so far failed to get fixed upstream, and to normalize conventions between
different datasets.
Prominent examples include the German long distance trains now being named in the expected way (using
the trip number rather than the much less commonly used line number), and Flixbus busses in
Europe actually being classified as long-distance bus services (which is important for filtering to work).
There’s more to fix still, the French long distance trains for example have a similar problem as the German ones,
this probably deserves its own post eventually.
Fixes & Improvements
Travel document extractor
Added or improved travel document extractors for AirAsia, B&B Hotels, Booking.com, Center Parcs, Colosseum, Cvent, Ethiad, Eurostar, Eventbrite, FCB, Finnair, LTG Link, Northlink Ferries, Odoo, pathe.fr, Pretix, RegioJet, Ryanair, SNCF, Tito, tixly, United Airlines and ZSSK.
Fixed parsing of Apple Wallet passes with an UTF-8 BOM in their message catalogs.
Added support for Apple Wallet pass bundles (.pkpasses files).
Use Aztec barcodes for MÁV domestic tickets, even when given as PDF417 barcode. This hopefully fixes issues with getting PDF417 MAV tickets scanned correctly.
Give extractor scripts the ability to explicitly request rotated text.
Consider dividing trains when determining whether two reservations refer to the same trip.
All of this has been made possible thanks to your travel document donations!
Also show ticket barcodes for hotels when available. While somewhat rare this is quite relevant when used.
Initially position the journey result view at the end for searches by arrival time (bug 507149).
Prefer 2D barcodes in Apple Wallet passes when available, those are more reliable to scan on a mobile phone display.
Remove duplicated entries from seat number displays.
Include location search history and downloaded public transport assets in the exported data as well, allowing for a more
complete migration to another device.
Use a more appropriate time format in delay notifications.
Fix rendering of some rich text Apple Wallet fields.
Also show event names on the trip map view.
Show the maximum occupancy of any stop if we have no occupancy information at the departure stop.
Improved the performance of displaying journey search results.
Downloading public transport logos now also follows the setting for using Wikimedia online content.
Fixed scaling issues in public transport SVG icons.
Put action groups consistently into the overflow menu of they don’t fit into the toolbar.
Fixed transfer time calculation to events without end time.
Allow adding another transfers if an adjacent transfer is far enough away.
Fixed handling of elements without an explicit end time in automatic trip grouping.
Prefer the current trip when determining the default import target.
Fix applying flight journey query results to flight reservations, and create entries for aerial lifts.
How you can help
Feedback and travel document samples are very much welcome, as are all other forms of contributions.
Feel free to join us in the KDE Itinerary Matrix channel.
When you’re using your system in a language that’s not English, you can now find Emojis in the Emoji Selector window by searching for their English names, in addition to the names in your primary language. (Kai Uwe Broulik, link)
Week numbers shown in Plasma’s various calendars have now been italicized to distinguish them from day numbers. (Akseli Lahtinen, link)
Plasma 6.6.0
Made multiple UI improvements to the time zone chooser map that’s visible in a few places: you can now zoom in and out farther, the map zooms in a more predictible way, there’s no more blurry text, and the borders of the clickable areas now perfectly map the borders drawn on the map. (Niccolò Venerandi, link 1, link 2, and link 3)
When using a right-to-left language like Arabic or Hebrew, Plasma will now show reversed versions of the audio icons in various places when the icon theme contains them — and the Breeze icon theme now does. (Farid Abdelnour and Nate Graham, link 1, link 2, link 3, link 4, and link 5)
Notable Bug Fixes
Plasma 6.4.6
Discover’s automatic shutdown/restart feature now allows apps with unsaved changes to prompt you to save first, preventing potential data loss. (Nate Graham and Aleix Pol Gonzalez, link)
Fixed an issue preventing the message about other users being logged in when you try to restart or shut down from appearing. (Nate Graham, link)
Fixed an issue preventing Flatpak apps from being able to create launchers using the Dynamic Launcher portal. (Nicolas Fella, link)
Fixed an issue that made the Applications table on System Monitor’s main page blurry with certain scale factors. (Arjen Hiemstra, link)
Removing the background of widgets in System Monitor now visually adjusts them to the color scheme properly. (Arjen Hiemstra, link)
Timestamps are now shown as expected for print jobs in the print queue. (Mike Noe, link)
The numbers in Plasma’s Timer widget now visually adjust to the color scheme properly. (Marco Martin, link)
When you’ve got Discover set up to prioritize apps from distro repos over Flatpak and/or Snap, searching for apps no longer inappropriately prioritizes the Flatpak or Snap versions. (Akseli Lahtinen, link)
Ampersands now appear correctly in text that shows up in the context menus of Task Manager tasks. (Marco Martin, link)
Fixed an issue that made the Media Player widget display filenames containing certain characters incorrectly. (Conor Smith, link)
Dragging a desktop widget partially off of a screen edge no longer makes the visualization of its position disappear. (Akseli Lahtinen, link)
Plasma 6.5.0
Fixed a case where DIscover could crash while quitting. (Aleix Pol Gonzales, link)
Fixed an issue in Discover that made it sometimes fail to display reviews properly for certain apps. (Akseli Lahtinen, link)
Fixed several issues with the Application Dashboard launcher: now it closes on focus loss like other launchers, doesn’t resize itself inappropriately if it’s open when the screen resolution, scale, or geometry changes, and no longer fails to pre-select items for many types of search results. (Niccolò Venerandi, link 1, link 2, and link 3)
Fixed an issue with the desktop grid view of KWin’s Overview effect that made it not show windows on inactive virtual desktops when using an unrelated non-default option. (Marco Martin, link)
Fixed a few sources of visual glitches when dragging items on the desktop when using a fractional scale factor. (Akseli Lahtinen, link)
If you’ve got a misbehaving screen that connects and disconnects multiple times when plugged in (screens suck), you’ll no longer see multiple system notifications about this. (Kai Uwe Broulik, link)
Using a font with a very tall baseline (for example, with many Arabic fonts) no longer makes text overflow out of the grid items on the Add Widgets sidebar. (Niccolò Venerandi, link)
The Reset button on System Settings’ Date & Time page now resets the current time zone too, if it’s been changed at all. (Niccolò Venerandi, link)
Removed Spectacle’s “Show capture instructions” option, because it didn’t do anything anymore after we removed the giant text field in the rectangular region UI in Plasma 6.4. (Nate Graham, link)
Frameworks 6.19
Fixed a case where Plasma would crash when asked to display certain malformed themes. (Marco Martin, link)
Fixed the “Delete oldest files from the trash” option for how to handle a full trash. (Pan Zhang, link)
Fixed an issue that made it impossible to paste text containing “file:///” into a Sticky Note widget. (Akseli Lahtinen, link)
Fixed an issue that made Plasma consume CPU time for no reason while the Networks widget is visible in the active part of the System Tray, until the first time the System Tray popup is opened. (Fabian Vogt, link)
Plasma 6.5.0
The time that Discover last notified you about updates is now stored in the state config file, not the settings config file. This is part of the meta-project to move rapidly-changing information out of config files so you can version-control them more easily. (Nicolas Fella, link)
Plasma 6.6.0
Old stale config data about ancient panels no longer clutters up your Plasma config file; it’s now deleted as intended. (Nicolas Fella, link)
Slightly improved the speed and memory efficiency of opening the Sticky Note widget’s context menu. (Kai Uwe Broulik, link)
Frameworks 6.19
Fixed an issue that made System Monitor render graphs when not visible, wasting resources. (Arjen Hiemstra, link)
How You Can Help
KDE has become important in the world, and your time and contributions have helped us get there. As we grow, we need your support to keep KDE sustainable.
You can help KDE by becoming an active community member and getting involved somehow. Each contributor makes a huge difference in KDE — you are not a number or a cog in a machine! You don’t have to be a programmer, either; many other opportunities exist, too.
You can also help us by making a donation! A monetary contribution of any size will help us cover operational costs, salaries, travel expenses for contributors, and in general just keep KDE bringing Free Software to the world.
I’m delighted to announce the new 6.1.0 release of KPhotoAlbum, the photo management software for KDE/Linux!
This is the first new release of our new KF6/Qt6 port, and it brings some fine-tuning, but we could also bring forward the code apart from bugfixes. here's the ChangeLog:
Added
Add command line option --config
Add command line option --save-and-quit
Add home and end key shortcuts to date bar
Add option to append description text when changing multiple image descriptions (#470433)
Show visual feedback when setting a rating in the viewer (#509964)
Changed
index.xml file format version bumped to “11”: The new file format version improves the “compressed” file format and handles arbitrary category names correctly. Positionable tags are also now stored natively in the “compressed” file format with far less overhead.
Disable “View” actions when not appropriate (#505185)
It's been another few weeks of progress on the KWin GameController Plugin and I've got a lot to share! After spending the previous weeks setting up the foundation, I've progressed things forward by improving the logic a bit more, creating a few integration tests, integrating it into System Settings, and making sure it runs well on real hardware like the steamdeck.
The primary change was splitting up GameController into two classes. The new one being GenericInputDevice which lives in emulatedInputDevice.{cpp/h}. This allowed me to separate the GameController logic responsible for emulating keyboard and mouse into it's own separate class. Now GameController wrapper class is just responsible for monitoring controller input, resetting idle timer on user activity, and logging.
GenericInputDevice
GenericInputDevice is a class that inherits from InputDevice and is used to emulated Keyboard/Mouse in order to send those inputs through KWins input pipeline. The input_events come from GameController and get processed exactly like they were previously. Each GameController has access to an instance of GenericInputDevice to make its own calls. In the near future I plan on creating a static instance of this class for all GameController to access.
// Inside Gamecontroller construct
m_inputdevice=std::make_unique<EmulatedInputDevice>();KWin::input()->addInputDevice(m_inputdevice.get());..// GameController Event Handling Function
voidGameController::handleEvdevEvent(){input_eventev;for(;;){constintrc=libevdev_next_event(m_evdev.get(),LIBEVDEV_READ_FLAG_NORMAL,&ev);if(rc==0){logEvent(&ev);input()->simulateUserActivity();if(m_usageCount==0||isTestEnvironment)m_inputdevice->emulateInputDevice(ev);..// EmulatedInputDevice
voidEmulatedInputDevice::emulateInputDevice(constinput_event&ev){m_ev=ev;if(ev.type==EV_KEY){qCDebug(KWIN_GAMECONTROLLER)<<"Face button pressed: Simulating User Activity";evkeyMapping();}elseif(m_ev.type==EV_ABS){qCDebug(KWIN_GAMECONTROLLER)<<"Analog buttons pressed: Simulating User Activity";evabsMapping();}}voidEmulatedInputDevice::evkeyMapping(){boolstate=m_ev.value?true:false;std::chrono::microsecondstime=std::chrono::seconds(m_ev.time.tv_sec)+std::chrono::microseconds(m_ev.time.tv_usec);switch(m_ev.code){caseBTN_SOUTH:// A button → Enter
sendKeySequence(QKeySequence(Qt::Key_Return),state,time);break;caseBTN_EAST:// B button → Escape
sendKeySequence(QKeySequence(Qt::Key_Escape),state,time);break;caseBTN_NORTH:// X button → Virtual Keyboard
// TO-DO toggle Virtual Keyboard not working on my distro ( Kubuntu )
EmulatedInputDevice::toggleVirtualKeyboard(QStringLiteral("forceActivate"));caseBTN_WEST:// Y button → Space
sendKeySequence(QKeySequence(Qt::Key_Space),state,time);break;caseBTN_TL:// L button → Ctrl
sendKeySequence(QKeySequence(Qt::Key_Control),state,time);break;caseBTN_TR:// R button → Alt
sendKeySequence(QKeySequence(Qt::Key_Alt),state,time);break;caseBTN_START:// START button → Meta
sendKeySequence(QKeySequence(Qt::Key_Meta),state,time);break;caseBTN_SELECT:// SELECT
break;// Add more button mappings here as needed
default:break;}}..
Integration Test: Qt Test
Part of the requirements for proposing significant contributions to KWin is creating integration test. This provides some assurance that things, like core functionality of the plugin, won't break so easily in the future as new code gets added. For testing KWin, uses the Qt Test Framework. Learning how to use the framework to create my own tests has been fairly simple and straightforward. Still, what exactly to test, and how to test it, was not so straightforward.
I learned along the way that I'd be creating integration tests, instead of unit tests. The tests don't reference the plugins directly; instead, they test the effect of the plugins on the system overall. That meant that things which required an instance of the plugin to test were not possible in this case. That included testing hotplug capability, or the number of applications that the plugin thinks have opened an input device. Thankfully there were few very important functionalities that could be tested!
Those include:
// Test system idle time reset. Prevents suspend
voidtestResetIdleTime();// Test Controller To Keyboard Input Emulation
voidtestKeyboardMapping();// Test Controller To Pointer/Mouse Input Emulation
voidtestPointerMapping();
I took a lot of inspiration from the buttonrebind_test.cpp.
System Settings KCM
It was agreed upon early on that this plugin would be opt-in, giving the user to enable and disable it when they choose. For that I created a KDE Control Module or KCM. Or better put, I built on the existing Game Controller KCM :) I added a new UI element, a toggle, for users to enable and disable the plugin. On the backend, I added a Q_PROPERTY, pluginEnabled, which is responsible for checking the kwinrc Plugin configs, and writing to them, in order to manage the state of this plugin. This is what it currently looks like (subject to change):
Handling Lizard Mode
This was probably one of the most daunting parts of the project for me when I first started. I knew that steamOS had its own way of handling input coming from the Steam Deck controller which has nothing to do with KDE or Steam app. This is what allows the controller to work for navigating the device in game and desktop mode. It's what is refered to as "Lizard Mode". The controller -> keyboard/pointer rebinds that I implemented was based off of the rebinds of this Lizard mode. Ideally using a controller to navigate desktop feels/works the same across all devices on KDE.
It's important that this new plugin not disrupt the current input system for the steamdeck. Originally I was warned that opening the fd for this device would cause Lizard mode to be disabled, which would mean I would have to either:
A: Find a way to disable Lizard mode and implement it from scratch...
B: Figure out what disabled Lizard mode on FD open and how to prevent / enable it as needed.
or C: Just change the flag for opening the controller fd and everything works just fine :)
Yup. After some testing and the smallest change I've had to make all project the Steam Deck controller was able to be detected by the plugin as well as its input detected! Even better than that, and not sure why I did not put this together before, Steam Deck already maps its input to keyboard/mouse. Duh. So this gamepad plugin doesn't need to worry about mapping and of Steam Deck input to just use it prevent system sleep when activity from that controller is detected.
During my testing, I discovered that Steam Deck shows up on the system as 5 different controllers. Each having their own purpose, one to handle analog input (triggers, trackpads, sticks) another to handle face buttons & D-pad, another for keyboard, etc.. These are used by the system depending on the users needs. Again, this made life a lot easier. This are logs from evtest and gamecontroller plugin:
At the start of this project I had adopted a child. Some of you reading this post might have met my child. It's named. It had been drifting inside the KDE community some time, looking for someone to take care of it. But it never happened, and thus time just went on, and on.
As some put it:
Wow this is an ELEVEN (!) year old bug.
This issue is so old it can go to middle school.
and my favorite
Is there any hope that this bug will be fixed before the heat death of the universe?
By the time I met Bug328987, it had been around for ≈12 years. But still! In the eyes of KDE, it was a young, bright eyed, workflow-breaking bug, like all the bugs out there, and it had potential to be fixed! After months of back and forth with mentors, living in KDE matrix server like it were my personal Discord server, and learning how to not do things in the code base - I'm proud to say gamecontroller plugin properly addresses Bug328987. Bringing to an end its more than a decade long journey. They grow up so fast.
What’s next from here
Integration into Kwin Proper: "Draft" label has been removed from MR and is ready for review.
Final Fixes and Touch-up: Get Virtual Keyboard working, KCM toggle hot-plug, improve analog -> pointer emulation.
Beyond Keywords: How I Built a Semantic Search Engine for Any Video Ever tried to find a specific moment in a long video? You might remember the scene vividly—a character gives a crucial speech, or there’s a beautiful, silent shot of a landscape—but you can’t remember the exact timestamp. You end up scrubbing back and forth, wasting minutes, or even hours, trying to pinpoint that one moment.
Traditional video search relies on titles, descriptions, and manual tags.
Design Systems is a relatively new concept that aims to organize the way design happens in structured systems such as applications, websites, organizations, etc.
Historically, working with graphics for the digital age has been unorganized, lives in personal computers, is not collaborative and leads to uncoordinated design.
When the world of graphic design meets development, designers were often confused about why mockups are not followed, why colors are not the same, not the same shapes, etc. All the while, developers ask designers why they can’t provide something that more closely resembles the system they aim to change. It’s uncoordinated work entering a highly-systemized world.
Often, both sides are confused and system changes become much more difficult to achieve.
Meet UI-design applications. The first wave of these started with Sketch (for Mac). Sketch is a fast and powerful vector graphics application that introduced a number of advantages over traditional SVG editors meant for artistic work. For example:
Infinite canvas
Area bounding
CSS-based design
CSS-based organization
Easy exports into various sizes
Asset library management
Collaborative design
Through their efforts, a sleuth of similar applications appeared in the scene, one building upon what the previous one lacked. Until we arrived at Figma, yes, Figma.
Figma did a few things right at the start of their development. They provided stronger asset library management, easier online collaboration, web-based editor with near-native speeds (If not faster now with the use of Web Assembly and other technologies), and variable and token management.
Through these enhancements Figma became the de-facto application to use for UI-oriented graphic development.
But what do they all do?
Put simply, these applications develop color, typography, spacings, shadows, icons, etc sets of organized assets. The assets have properties borrowed from development, such as, components, variables and tokens.
Designers can set up entire color libraries in a graphical way and then apply those colors to SVG graphics. Upon export, these graphics contain enough information for developers to more easily implement the design.
All the while, designers only have to spend time at the beginning of a project to set up all the assets required for designing. Additionally, Figma and other applications have been keenly focused on building graphical ways to deal with code-oriented complexities.
For example, Figma and PenPot detect variants creation and can express their values in dropdown menus that get created on the fly by the designers. If you create a button and your variants are size oriented, you can have a dropdown in the application’s UI that shows SM, MD, LG, XL, etc. These are huge time savers. Traditionally, designers would have to do a lot of copy/paste in their designs. With integrations like these, designers simply switch the variant for another and the design updates itself.
A similar idea happens with graphical components in these applications. Users are able to create a master version of an asset, let’s say a button, set up all of their locked and open parameters, colors, typography, margins, gutters, etc. When you make copies of this component, any changes made at the component level will be updated anywhere copies were placed. For very large design documents containing a company’s brand strategy, for example, these types of changes save countless hours of tedious copy/paste work.
Tokens
In recent times, and through various changes in the app-making industry, UI design applications have created the concept of tokens. Tokens are essentially named attributes for graphical components. They are often used as correlated language between design applications and systems.
For example, for Ocean Design, the team created tokens named thus:
pd.ref.color.primary50
PD: Plasma Design
REF: Reference color (Raw color value as opposed to applied color, which is called “sys”)
PRIMARY50: Color role and its named color value in a line from light to dark values of the same color family.
This value can be replicated in Plasma. Through the storing of a master list of token values, Plasma can stay coordinated with graphic primary50, the system would have to do the same and just change the raw color value of that token without having to create new tokens, break coordination with the design system, or have to interpret information coming from designers.
Tokens are becoming more common use and reflect the desire of developers and designers to have even tighter integration between design and development.
Independence
Design Systems also allow for great independence between design and development. Having laid the groundwork to create coordinated design, applications like Figma and PenPot allow users to download asset libraries, reuse, and create UI. All without redefining the source library. It democratizes graphic design while keeping designers coordinated in their designs.
Developers looking to execute an application idea can much more easily create coordinate UI that supports their efforts. Developers would have much less design-oriented work to do and dedicate more into the features they want to deliver.
Ocean Design
Ocean Design aims not only to become a new UI design for Plasma but also plug in these powerful design applications into our development ecosystem and deliver UI to users faster, more coordinated, and more often.
If you’re interested in learning more about this effort, connect with our teams here:
Plasma Visual Design Team (General chat about all things designs for the Plasma Desktop)
Ocean Design Team (Focused discussion on Ocean Design)