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.
The highlight of this release is the playlist, which got a lot of features:
multiple playlists through tabs (Muhammet Sadık Uğursoy)
drag and drop reordering (Muhammet Sadık Uğursoy)
add files and folders through drag and drop (Muhammet Sadık Uğursoy)
filtering (Muhammet Sadık Uğursoy)
option to control playback behavior when a file ends: repeat playlist, repeat file, stop after last file in playlist, stop after current fille and play a random item
Another big change is to the Mouse settings, now you can use a mouse button + modifier key combo (ctrl + left click, shift + scroll up/down etc.).
Feature requests and bugs should be posted on bugs.kde.org, ignoring the bug report template can result in your report being ignored.
Changelog
1.5.0
Known issues
On Windows the Shortcuts and Custom Commands settings pages don't work.
Features
Settings
General
added single instance setting to play new file when appending to the playlist
removed the "File dialog location setting"
Playlist: added settings to control playback behavior
Mouse
changed to allow modifier keys
added support for Mouse Forward and Back buttons
Subtitles: if a relative folder name in the Load subtitle from list starts with an * (asterisk) then subtitles will be searched in all folders contaning the folder name.
Example: If the Load subtitle from list contains an entry *sub and you have the following folders next to the video file subs, more subs and subtitles all of these folders will be searched.
the settings window now has a minimum width and height
PlayList
added support for multiple playlists
items can be reordered manually through drag and dropdown
items can be selected, ctrl+click to select multiple items, shift+click to select a range
items can be filtered
added setings to control playback behavior when a file ends
when saving the playlist the file extension is set to m3u
can add files and folders through drag and drop
multiple files can be added through the option in the header
hide playlist when mouse leaves window while maximized, prevents opening the playlist when moving mouse to another monitor
Playback
if a file can't be played now an error is shown and playback stops instead of trying to play the next file (prevents a potential infinite loop when no file in the playlist can be played)
can play files starting with a dot (hidden files)
an error is shown when failing to get youtube playlist
Other
mpris: add support for Shuffle and LoopStatus
changed the action selection popup to use Kirigami.SearchDialog
replaced the spinning icon with a progress bar and label
the drop area of the video is split in 2 parts now
top part always appends to the default playlist
bottom part clears the default playlist and adds the dropped files and folders, when only one file is dropped it behaves as the open file action (clears the playlist and loads sibling files if enabled in settings)
recent files are now stored in a sqlite database
time positions used to restore videos are also stored in the database
sleep is blocked on Windows too
all strings should be translatable now
Bugfixes
fixed the loop action, osd was not showing and progress bar was not highlighting the loop range
before loading check that the file exists
fixed loading wrong subtitles when using recursive subs
fixed the progress bar getting taller when the chapters menu becomes visible
fixed a bug where the video would pause after clicking the progress/seek bar
Beginning of 2025 I was searching through the version history of Qt OPC UA - trying to find out when a certain issue got introduced. At some point I was curious: How long does this thing go back?! Turns out that the first git commit is dated 25th of September 2015. Which means we have been doing this for over 10 years now!
Kirigami Addons is a collection of supplementary components for Kirigami
applications. Version 1.10.0 is a relatively minor release, introducing KirigamiApp
and some improvements on Android regarding the new edge-to-edge support introduced in Android 15.
New Features
Aleix Pol Gonzalez added a KirigamiApp component which removes quite a bit of boilerplate to setup a Kirigami applications.
It now looks like this and will setup theming, crash reporting and more automatically in one place:
intmain(intargc,char*argv[]){KirigamiApp::Appapp(argc,argv);KirigamiAppkapp;// Set up KAboutData
// QCommandLineParser creation and processing
if(!kapp.start("org.kde.myapp",u"Main",newQQmlApplicationEngine)){return-1;}returnapp.exec();}
Bug fixes
Volker Krause added edge-to-edge support to the BottomDrawer and the MaximizedComponents.
First maintenance release of the 25.08 series is out continuing the focus on stability and polish with many fixes for crashes and regressions as well as user interface and usability improvements.
Some packaging issues caused a small delay for this release announcement, sorry for the inconvenience.
Thanks to all the people who help make Kdenlive more stable by reporting bugs, providing patches or sending constructive feedback.
Subject: [Kwrite-devel] I just wanted to be the first to post here )
Welcome to kwrite-devel
I hope this is an active list and we can attract some more developers
Anyone have any ideas on coding style,enhancements problems
please feel free to post your questions/comments here.
or, depending which mail arrived faster in your inbox:
Subject: [Kwrite-devel] Welcome to this mailinglist.
Hello,
Welcome to the kwrite development mailinglist. *test*test*
Cheers,
Waldo
The journey
Like the first mail wanted, that list was very active for a long period of time.
The initial posters no longer are active in the project, but some people like me still stick around even after more than two decades.
A lot of important design decisions were discussed on the mailing list and many user questions got answered.
The end
The list traffic slowed down more and more over the last years even as the actual amount of contributions (and presumable the user base) did increase.
Reasons are for sure that for development, we use mostly our KDE GitLab instance for communication.
It is just that easier to couple discussions with code there and link development issues to merge requests or commits.
I can not remember any serious discussion on larger development topics outside our GitLab in the last years.
For users I assume mailing lists are just too arcane today.
Perhaps that is a misconception I have, but at least from most people I know in real life, most of the online support questions went of to either websites or random other channels.
Some people survive without any mail account beside the one needed to create some online accounts or install thei mobile phone.
I need to moderate away at least 10 to 100 spam mails for any real mail on the list, that is just a not needed overhead nobody should waste time with.
Therefore in the near future we will close that list, it will not get a 25 years birthday party :-)
But where to ask & discuss stuff now?
I already updated our documentation and web site to point to the current contact points.
Like every year, one of the highlights is Akademy! This time we were in Berlin, making it quite easy to get there from Hamburg:)
The weather was surprisingly nice, especially when heading out in the evening to try lots of different restaurants.
And of course - since being in Berlin - you gotta try a local Döner there :D.
One talk I was particularly surprised about was Saturday’s keynote “Open by Design: How Governments Can Lead the Shift to Digital Sovereignty” by Alexander Rosenthal.
Besides the information about OpenSource-Software being used on different levels of federal/state/local, the aspects of OpenData.
This made me realize that software is not the only thing one should focus on being open. Also, the huge amount of memes in the slides made the talk super refreshing and a nice start into Akademy!
Nate’s talk “Minding the Big Picture: Opportunity From Chaos” also fit this topic. OpenSource can provide a stable foundation
and reduced dependence on individual companies.
My main development focus and also the most frequent topic of the blog is the Clazy project. Akademy is a good occasion to tell other people about it.
So I took the occasion and held a fast-track talk about Clazy to tell how awesome and useful it is. It was also quite good to get people talking about it and share their ideas/problems.
I also did a decent amount of coding on Clazy. This included a request from aacid about Clazy not working properly with a Qt variant
that is build into a specific namespace. This was quite the rabbithole, but I managed to get the passing tests from 50% to 90%.
The last few edgecases are not as relevant if most of Clazy works properly.
For the use-arrow-operator-instead-of-data a false-positive is fixed where the check complains if you do a .data() call and then cast the pointer.
This is in most cases needed, if not, clang-tidy should warn about unneeded casts. Finally, fixits for detaching-temporary and detaching-member are more reliable when multiple calls are chained.
The biggest surprise though came at the Akademy awards. I am very honored to have received one, this left me quite speechless.
Me finally catching some words after getting the Award <3
This also means I am responsible for choosing the person for next year’s award. So you better get busy doing cool stuff 😎👀.
Finally, I want to thank everyone who helped organize Akademy and made it as awesome as it was!
Kaidan supports the simultaneous usage of multiple accounts now.
Imagine you could use the same chat app at work and with your friends.
All your favorite and accustomed features would always be accessible without switching apps.
It is possible with XMPP and finally with Kaidan too!
In order to quickly distinguish the account a chat belongs to, there is a small avatar of the corresponding account in the corner of a chat’s avatar.
Furthermore, Kaidan makes sure that you do not accidentally add a new contact to the wrong account.
That is achieved by selecting the account before you enter the contact’s chat address or scan their QR code.
The same applies to the group chat actions.
Secure Password Storage
The account passwords are stored in the device’s password manager.
You do not need to keep passwords in your mind.
Instead, you can use random ones.
They are securely stored in a central place.
Mark Messages
If you already read the latest messages from a contact but do not have time now to respond, you can simply mark them.
A separate counter is shown for the marked messages.
Take your time and come back to those messages later.
You will not forget to reply anymore!
Forward Messages
You can forward messages from one chat to another.
After clicking the corresponding context menu button, you can choose a chat to forward the message to.
By default, only the chats of the current account are listed to make it as simple as possible for you.
But you are able to list chats of other accounts as well.
Once you selected a chat, the message is added to its input field.
You can directly send it or adjust it beforehand.
Changelog
There are several other improvements.
Have a look at the following changelog for more details.
Features:
Add support for using multiple accounts simultaneously (melvo)
List accounts and show button to add new accounts (melvo)
Show dialog to select account for global action such as adding a contact (melvo)
Allow to enable/disable accounts instead of connecting/disconnecting them manually (melvo)
Update nicknames of own accounts once connected (melvo)
Show small account avatars next to regular avatars if multiple accounts are used (melvo)
Hide global drawer handle on chat if window is narrow (melvo)
Use PNG/.png instead of JPEG/.jpg for thumbnails to allow transparency (melvo)
Use AAC/.m4a instead of MP3/.mp3 for voice messages to improve compatibility (melvo)
Provide size of sent images to recipients allowing receiving client to scale thumbnails to size of original image (melvo)
Provide size of generated thumbnails to recipients (melvo)
Increase size of generated thumbnails (melvo)
Show circle instead of bar for upload/download progress (melvo)
Try all providers on connection error during automatic registration (melvo)
Add message forwarding (melvo)
Enable voice message recording via Flatpak (melvo)
Store account passwords encrypted if password manager is available (fazevedo)
Apply consistent criteria for all message corrections (melvo)
Add support to mark messages locally in order to reply to them later or to quickly find important messages (melvo)
Reuse SASL 2 user agent and FAST token on every restart for faster connection establishment (melvo)
Bugfixes:
Fix selecting media via long press in media overview (melvo)
Fix OMEMO initialization (melvo)
Fix displaying geo location map (melvo)
Fix showing hints on invalid input of various input fields (melvo)
Fix name/date of chat list item moving if counter for unread messages dis-/appears (melvo)
Fix counter for unread messages (melvo)
Fix handling removed message reactions (melvo)
Fix canceling personal data sharing via contact details (melvo)
Fix finding existing notifications for personal data sharing requests (melvo)
Fix cursor behavior in message input field by allowing vertical cursor movements while participant picker is closed and prohibiting horizontal cursor movements while participant picker is open (melvo)
This post is to celebrate a few things despite the events that are clouding our feelings. 😠
Another thing to not celebrate is the slaughtering by Sourceforge of my developer web site, which they are calling "sunsetting", by October. I've already migrated it.
On the other, brighter hand, I'm celebrating this week La Mercè, which is the local festivity of Barcelona.
Castellers of Barcelona
Another event to celebrate is the first 2 million downloads of VMPK for Linux, Windows and Mac. The Sourceforge statistics do not include the installs thru Flatpak, but you may realize that more than 75% of the Sourceforge downloads are the Windows packages. The 2 mil download happened some past day of this year 2025. I've promised a celebration, and now, I have released the Android port of VMPK under the GPLv3 license in GitHub.
If you already have the F-Droid app, you only need to add the IzzyOnDroid repository in Settings>Repositories and install it today, or you may prefer to use the official F-Droid repo.
I would like to add to the celebration a video live streaming concerto, but I am too lazy and odd playing for that. Better use this wonderful rendering of the Tchaikovsky Violin concerto by TwoSet Violin, with Brett Yang playing the soloist and Eddy Chen the rest of the orchestra. Enjoy!