It has been an incredible 12-week journey contributing to the KDE Community for Google Summer of Code 2026! The guidance and support from my mentors, Benson Muite and Srisharan VS was incredible. Lots of contributions and conversation over this happy period.
Here is a comprehensive summary of what we accomplished this summer:
XMPP Integration in Login and UI updates (Weeks 1-3)
I began by integrating in-game XMPP server registration (following XEP-0077: In-Band Registration), complete with compliance checks to ensure protocol adherence. On the frontend, I redesigned the Profile Page to dynamically fetch profile icons and usernames directly from the user's logged-in XMPP account.
Tournaments and Gameplay Enhancements (Weeks 4-7)
I made the core logic and UI for creating XMPP game rooms (XEP-0045: Multi-User Chat) and player invitations. I introduced two major tournament styles: Round-Robin and King of the Hill. To keep matches competitive, I implemented time limits for accepting invites and executing game moves.
Beyond tournaments, the actual gameplay received a massive polish. I added smooth displacement animations so shells transition flawlessly from pit to pit, introduced togglable game music, and finalized flatpak artifact builds to make distribution easier.
Game Bots for Automation and In-Game Chat (Weeks 8-10)
To ensure players always have an opponent, I developed an API Bot for Mankala that automates gameplay moves, complete with OpenAPI documentation. For human opponents, I implemented a real-time text chat system during multiplayer modes directly over our XMPP architecture.
Real-Time Voice Chat (Weeks 11-12)
Taking inspiration from KDE’s Kaidan, I utilized the QXmpp library to implement Jingle (XEP-0167: Jingle RTP Sessions) for media sessions. I designed a C++ VoiceCallManager to listen for incoming Jingle requests, establish peer-to-peer connections, and route audio via QtMultimedia.
The biggest challenge was perfectly syncing the game window with the Jingle state. By exposing properties like call status and remote JIDs to QML, the UI now dynamically hides the text chat and reveals the active voice call layout instantly when a call connects.
Community & Documentation
I had the privilege of giving a talk on Mankala at the ILUGC monthly meetup, adding standard CONTRIBUTING.md / SETUP.md documentation, and setting up a Craft blueprint. I will be asking ILUGC members for feedback on the new builds.
A huge thank you to my mentors and the KDE community for their constant guidance...🚀
This week was full of user interface improvements and performance enhancements, and we snuck in a few features as well:
Notable new features
Plasma 6.8
Remote desktop sessions now offer a fully shared clipboard, rather than only sending the server’s clipboard to the client. (Nick Haghiri, krdp MR #213)
Notable UI improvements
Plasma 6.8
Events shown in the Digital Clock widget now display their descriptions inline, rather than in a hover tooltip. (Francesco Fortunelli, KDE Bugzilla #429700)
The scrolling speed sliders on System Settings’ Mouse and Touchpad pages are now accompanied by spinboxes that permit fine-tuning their speeds. (Wladimir Leuschner, KDE Bugzilla #477745)
Discover now shows all of the external links that apps can set in their metadata. (Taras Oleksyn, KDE Bugzilla #522213)
Interactive UI elements on the logout screen are now only shown on the active monitor, mirroring the same thing on the lock and login screens. And the whole thing now fades in and out faster, too. (Ramil Nurmanov, and Nate Graham, KDE Bugzilla #431382 and kwin MR #9711)
The wallpaper chooser UI that’s visible in System Settings and the desktop configuration window now loads in a smoother and less glitchy-looking way. (Artem Grinev, plasma-workspace MR #6892)
The Power & Battery widget’s “Manually Block Sleep and Screen Locking” switch is now vertically aligned to its icon. See, KDE really does care about margins and alignment! 😁 (Angel Parra, powerdevil MR #662)
New
Old
Notable bug fixes
Plasma 6.6.7
The Power & Battery widget’s tooltip no longer talks about scrolling to change the power mode on systems without either of the power-profiles-daemon or tuned-ppd systems installed and working. (Nate Graham, powerdevil MR #663)
Plasma 6.7.5
Fixed a somewhat common way that Discover could crash on systems using the RPM-OSTree architecture, such as Fedora Kinoite. (Aleix Pol Gonzalez, discover MR #1385)
If the fwupd system service is broken or masked using systemd, the rest of Discover still works as expected. (Tobias Fella, discover MR #1373)
When the Task Manager widget is used with a right-to-left language or its tasks are configured to appear “to the left”, the tasks now move to the expected location when manually rearranged by dragging. (Christoph Wolk, KDE Bugzilla #504898)
Custom accent colors defined within wallpapers are once again honored. (Zhora Zmeykin, KDE Bugzilla #514656)
Plasma 6.8
Fixed a case where the remote desktop server could crash when closing a connection. (Wengsheng Tang, krdp MR #189)
Resizing an aspect-ratio-locked window no longer sometimes makes it disappear! (Vlad Zahorodnii, KDE Bugzilla #479547)
The OSD displayed when muting or unmuting microphones using the Microphone Indicator widget now shows the correct icon. (Undef Fox, KDE Bugzilla #472107)
Apps packaged as Flatpaks or using Nix now get pinned to the Task Manager widget in a more robust way, so they’re less likely to get broken in the future if the underlying locations of their .desktop files change. (Christoph Wolk, KDE Bugzilla #505066)
The Emoji Selector window now uses the same consistent order for the gendered variants of all emojis, not just some of them. (Tobias Ozór, plasma-desktop MR #3939)
New
Old
The pointer now looks even sharper at absurdly enormous sizes when you shake it for ages and ages. (Vlad Zahorodnii, kwin MR #9176)
Right-clicking twice on the same pixel of the desktop without moving the pointer no longer shows the wrong context menu the second time. (Christoph Wolk, KDE Bugzilla #504765)
Frameworks 6.30
Fixed a bug that could make KDE Connect consume 100% of a whole CPU core. (David Redondo, KDE Bugzilla #517743)
Very large images on the clipboard no longer sometimes fail to paste successfully. (Zhora Zmeykin, KDE Bugzilla #519651)
Kup’s notification about backup progress no longer erroneously tells you that the backup destination is on your phone that’s paired with KDE Connect. (Harald Sitter, KDE Bugzilla #518494)
Notable in performance & technical
Plasma 6.6.7
Added support for monitoring GPU usage for Intel A380 GPUs. (Takahiro Hashimoto, KDE Bugzilla #517334)
Pasting very large PNG images no longer sometimes causes some lagging and stuttering. (Zhora Zmeykin, plasma-workspace MR #6874)
Plasma 6.7.5
KWin now supports more than one wl_data_device, which opens the door to improved drag-and-drop support in Firefox. (Martin Stransky, KDE Bugzilla #521494)
Spectacle is now slightly faster at taking screenshots. (Zhora Zmeykin, kwin MR #9752)
Plasma 6.8
The new kscreenctl tool now supports setting custom CVT timings/modelines. (Vlad Zahorodnii, KDE Bugzilla #517654)
Frameworks 6.30
Reduced the number of times the common Kirigami.Icon component needs to read from the disk while looking for fallback icons. (Jakob Petsovits, kirigami MR #2139)
The Baloo file indexer now correctly ignores Btrfs snapshots that happen to be stored in your home directory, instead of pointlessly trying to index them. (Hadi Chokr, baloo MR #295)
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.
Would you like to help put together this weekly report? Introduce yourself in the Matrix room and join the team!
Beyond that, you can help KDE by directly getting involved in any other projects. Donating time is actually more impactful than donating money. 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.
You can also help out by making a donation! This helps cover operational costs, salaries, travel expenses for contributors, and in general just keeps KDE bringing Free Software to the world.
To get a new Plasma feature or a bug fix mentioned here
Almost nobody was using it; really only Kubuntu. Other discrete-release operating systems like Debian and openSUSE Leap generally ignored it.
It wasn’t a real LTS; we only backported some fixes for Plasma, and nothing for the Frameworks it was built upon, nor the Gear-aligned KDE apps it shipped with.
Our backporting of fixes was fairly blind since there weren’t CI resources to validate them, and nobody ever felt like testing them manually.
As a consolation prize for canceling the Plasma LTS product, we decided at the time to add an additional bug-fix release to the normal Plasma schedule, effectively lengthening the support period for each non-LTS Plasma version by 2 months — from 4 months to 6.
And as a result, there have been no Plasma 6 LTS versions.
…Until now!
Plasma 6.6 is now an LTS version. And not just Plasma 6.6 itself, but also a specific version of KDE Frameworks: 6.24, which will also receive backported bug-fixes. And Gear 25.12, too!
What changed?
It wasn’t a change to my or anyone else in KDE’s opinion of what a proper LTS product looks like. Rather, it was the Kubuntu Focus company stepping up to fund the creation of one, as announced today!
That’s right, Kubuntu focus is sponsoring a Plasma 6.6 LTS product for the next three years!
This consists of a couple of pieces:
First of all, Kubuntu Focus is sponsoring Techpaladin Software to fix bugs identified by Kubuntu 26.04 users. (full disclosure: I’m the CEO of Techpaladin Software). We’re not just backporting bug-fixes that happen to get made, but rather actively working with the Kubuntu folks to identify and fix pain points experienced by them and their users.
Plasma 6.6 will thus remain eligible for bug reports for the next three years, and we’ll do our best to get them fixed and backported.
Speaking of which, we’ll be backporting fixes for more than just Plasma 6.6 — relevant ones will also to Frameworks 6.24 and Gear 25.12, the versions that Kubuntu 26.04 ships with. The whole KDE part of the software stack!
Finally, Kubuntu Focus is sponsoring additional continuous integration resources owned by KDE e.V. to handle the load of validating changes made to these older versions. And they’ve been generous enough to sponsor more than was strictly speaking needed for the initiative, so KDE in general benefits from faster CI times even for non-LTS work!
We’re calling the whole thing the “Bullet-Proof KDE Initiative”.
This is what a real LTS initiative looks like, folks: people involved with an OS putting the resources into making a non-LTS upstream release into an LTS one, properly. With bug fixes — not just security fixes — backported to all levels of the software stack, not just the top one.
So I predict Kubuntu 26.04 promises to offer the best KDE experience of any Kubuntu release ever!
I know a lot of folks really enjoyed Kubuntu’s 24.04 release because of how it lined up with Plasma 5.27, which we made an LTS release for an extended period of time during the Plasma 6 transition. Well, this is the same thing, only with a great version of Plasma 6 included, and supported for even longer!
Aha, so you’re a sell-out who changed his opinions about LTS due to money!
My opinion remains the same: I don’t dislike LTS products — only fake ones that promise support but don’t actually deliver it. With this initiative, users of Kubuntu 26.04 get a real LTS product, with real support backed by a pair of commercial companies.
So this is all a commercial thing? KDE gone korporate?
It’s largely a commercial initiative between Kubuntu Focus and Techpaladin Software, yes — though KDE e.V. has signed off on the initiative and agreed to accept funding for the new CI resources.
Both companies are good citizens in the KDE ecosystem: KDE e.V. patrons, employers of engineers you’ve heard of, and providers of hardware and services to users of KDE software.
And the benefits accrue far beyond just the companies. Obviously Kubuntu 26.04 users benefit, even those who didn’t buy a computer from Kubuntu Focus. And as I mentioned earlier, all of KDE now has more general-purpose CI resources. Also, many of the LTS bugs that Techpaladin people have already fixed were affecting people on later Plasma versions, too! Everyone wins here.
So the commercial part is not a limitation on what anyone else gets for free or is allowed to do; it’s just an acknowledgement that creating a real LTS product costs money.
Wow, really cool! How can I help?
Anyone in the wider KDE community who’s interested in this kind of thing should feel comfortable backporting important and safe bug-fixes to the stable branches for Plasma 6.6, Frameworks 6.24, and Gear 25.12. There will be a Kubuntu CI runner that makes sure nothing breaks (at least, nothing that’s tested in the CI! So keep that test coverage high).
And if you happen to run discrete-release OS and would like to get in on the action, feel free to ship Plasma 6.6 and invest some of your own resources into it! It will be very welcome to see more people fixing bugs reported by LTS users that are still present on master, or backporting more recent bug-fixes to the LTS version. Again, everybody wins here!
Over the last two weeks, I worked on adding multi-select support for deleting multiple entries at once. It sounded like a straightforward feature at first, but it ended up leading me down an interesting debugging involving an asynchronous race condition.
Multi-Select with Ctrl+Click and Shift+Click (!44)
KeepSecret now supports the standard multi-selection behavior users expect from desktop applications. You can Ctrl+click to select or deselect individual entries, and Shift+click to select a range of entries. I also updated the right-click behavior so that if you right-click on an unselected entry, it becomes the current selection first.
Another improvement was simplifying the delete logic. Previously, deleting a single entry and deleting multiple entries followed different code paths. Now both actions share the same implementation, making the code cleaner and easier to maintain.
While working on this feature, I also fixed a few small UI issues. The entry details panel would sometimes open unexpectedly after a right-click, occasionally close when it shouldn't, or remain visible even after the selected wallet had been deleted. These edge cases are now handled correctly.
The Race Condition
Deleting multiple entries at once would sometimes fail with a confusing libsecret-CRITICAL error and a “Could not retrieve the secret value” message. The problem was inconsistent—it could happen with the first item or with one of the later items.
I first checked a few possible causes, like stale proxy-model indices and timing issues between deletion and model updates. Eventually, I found the real problem.
When an item was loaded, it also started an asynchronous request to fetch its secret. But the delete operation could run before that request finished. If the item was deleted first, the callback would later try to access an item that no longer existed.
Since we don't need the actual secret value when deleting an entry, I changed the loading process to skip that unnecessary request. This removed the race condition instead of trying to work around the timing issue.
I added a touch-friendly version of the desktop multi-select feature. Long-pressing an entry enters selection mode, where checkboxes appear and tapping entries toggles their selection. It reuses the existing selection logic, so the Delete Selected Secrets action works without any changes.
Nate Graham also suggested that this pattern could eventually be useful as a reusable component for other mobile apps. Marco Martin is testing the long-press behavior on a touch device next, since it currently also gets triggered by clicking and holding with a mouse.
My favorite tabletop game of all time is Star Wars: Armada, a Star Wars themed ship combat wargame.
Armada has many deep and tactically interesting features, but one of my favorites is the unique suite of defense tokens available to each spaceship to protect itself against attacks, from among the following six options:
Scatter – the attack is completely canceled. “I wasn’t where you were shooting”
Evade – cancel an attack die at long range, or re-roll one at short and medium range. “I dodged your attack, so it missed or became a glancing blow”
Brace – halve the damage. “Ouch, you hit me! But it wasn’t as bad as it could have been”
Redirect – move some damage to an adjacent hull zone. “You hit me, but not where I was weakest”
Contain – downgrade a critical hit to normal damage – “My damage control efforts turned the potential catastrophe into just a normal crisis”
Anyway, this is well and good for games about spaceships, but what’s the relevance? Let’s imagine that we humans have these defense tokens, too. And today I’d like to talk about how they relate not to physical attacks, but interpersonal ones.
You negligent fool! You nit-picking jerk!
Someone has blindsided you with unexpected criticism! The monkey brain sees this as an attack:
And what’s the most satisfying defense token to use? Salvo, for sure. Hit back:
Oh yeah, that’s pretty rich coming from you given how you messed up that other thing last week!
The angry email. The “call-out” social media post. The sharp reply on chat. The hyper-critical blog post. They feel good, right?
But Salvo doesn’t actually avoid any damage. in Armada, if you Salvo every attack, your ship explodes, with the only other effect being that the attacking ship gets hurt too — usually a lot less.
From the perspective of minimizing interpersonal friction in a group setting, Salvo is the worst defense token. It didn’t end the conflict created by this unexpected criticism; in fact, now the conflict is bigger and louder, because the criticizer has also gotten hurt. Other people may leap to their defense, or yours, and pretty soon the battle lines are established. What started as a community soon feels like a war zone.
Redirect isn’t great, either; in a community context it’s basically blame-shifting, which similarly doesn’t prevent any damage; it just moves it around, and the community still suffers.
Neither is is not what we want for our community if the goal is to remain friendly and welcoming!
Prevent and reduce damage
If we want to keep our ship flying community alive, we need to prefer the defense tokens that prevent or reduce damage:
Scatter: prevent conflicts in the first place by meeting expectations, being mindful of other people’s feelings, and maintaining your relationships.
Evade: notice impending conflicts and help make them fizzle out early. Be humble.
Brace: mend fences and fix problems so the conflicts that do erupt shrink over time.
Contain: keep conflicts localized to the participants, and prevent them from spiraling out of control. Don’t let drama spill out into the larger team or the whole organization — or heaven forbid into the media! Accept valid criticism and let others have the last word.
These social defense tokens are harder and less satisfying to use than Salvo and Redirect. But over the long term, they do a much better job.
Which brings us to KDE
Today I think KDE is known as a pretty friendly place. And when I look around, I see a lot of examples of people — consciously or unconsciously — using defense tokens in their interpersonal relationships that reduce harm rather than moving it around or sending it back.
It’s not perfect, of course. We all mess up sometimes. And a culture like this takes years to develop. But I think the strong social bonds between contributors inside KDE are self-evident, and represent a significant part of the organization’s success today.
So I want to congratulate KDE and encourage us all to keep it up! I know times are tough and a lot of things in the world feel like they’re exploding, or getting ready to. Things suck more than they should, and there’s always more we can do to improve it. But as long as we maintain our relationships with one another, it becomes a lubricant that makes all those things so much more possible to survive or achieve.
I participated in the KEcoLab sprint held from May 27th to May 28th at the KDAB office in Berlin. It was my first time being at a KEcoLab sprint, I have mostly been an online participant before this so it was nice to meetup with both Karan and Joseph and work together in person. I also got to meet Carl Schwan and Volker Kraus.
Day 0
I arrived a day early by an overnight train around 7 am. I couldn’t check in to the hostel before 3pm so decided to explore the city instead.
I explored the area around Alexandrplatz and got some nice photos, more of that will be covered in my next blog about Berlin.
I met up with Karan and was able to check in a bit early. We had Vietnamese Pho for lunch.
Later at evening me and Karan met with Joseph and he showed us around. We visited Tempelhofer Feld and Joseph also treated us to a nice Turkish dinner.
Day 1
We met at the KDAB office at 10am to start the sprint. We started the day by fixing the RDP connection. Recently we have been unable to maintain a reliable RDP connection with the remote lab, we required someone to be present in the lab to help us establish access. We restarted the SUT (System Under Test) and tried to establish a connection again when we found out we were prompted by a dialog box to allow remote connection. This isn’t an ideal situation for a remote lab because this permission is reset on reboot. We found that the solution to the exact issue we were facing was already solved by Harald Sitter through this patch to XDG desktop portal. We ran the commands in the patch and tested it few more times to confirm it was working reliably.
Next we started working on setting up the 2nd SUT which was generously donated by Cornelius to KDE.
Unfortunately the PC refused to post. As soon as it was turned on it would produce 6 loud beeps. The pc we had access to was a Fujisu Esprimo p510 85+ with 4gb of ram and an Intel core i5 using AMI Aptio 4.6 Bios.
We tried to debug the issues by removing the ram sticks one after another but the beep was still audible and the frequency remained constant. We tried multiple different cables as well to rule out a faulty display cable. Point to note, the CPU fan during this time would be at full throttle and the usb ports were also not getting power.
We also tried replacement ram sticks that folks at KDAB had but it didnt solve the issue. Replacing the CMOS battery also didn’t help.
As last ditch effort, we removed the CPU fan and tried to boot the system (the system was immediately switched off once the beeps started so roughly 2s uptime) to see if the beeps would still be persistent but it was still present although we did find the reason why the fan was running at full throttle, the thermal paste was completely dry.
Going by the manufacturer’s documentation, 6 beeps presents itself as “Flash update is failed”, searching online didn’t give us a viable solution and since the usb ports were not working reflashing the bios was also out of question.
We ended the day by shifting our focus towards generating a new Okular Measurement Report for the Blue Angel Certification. We were also interested in seeing how much energy consumption would have changed since the first report. Our Season of KDE 26 mentee Hrishikesh Gohain had worked towards this. There were few changes we needed to make to run the pipeline successfully. We tested them locally first on our laptops and once it passed successfully, we ran the script overnight and that was our last task of Day 1. Following was the pipeline that was run.
At the end of the day, we visited c-base, berlin. It was a nice experience and we were also lucky to visit the members only spaces and got a whole tour of the place by one of the members. Aferwards we all went to a nice Azerbaijanish place.
Later me and Karan spent the rest of the night exploring Berlin on a lime scooter. Suffice to say, Berlin at night is quite a beaut!
Day 2
We started the day by checking the report generated by the pipeline we ran last day. We had unfortunately run into the following error.
Error in performanceData$HDDRead + performanceData$HDDWritten : non-numeric argument to binary operator
We then looked into running the setup locally on our laptops to debug the issue. We found out that when stopping the pipeline before completion, it results in the intermediate data being overwritten instead of the files being deleted on a fresh run which resulted in data corruption and hence the error. We fixed that with 64, 18 and 16 patches and ran the pipeline again.
Next we focused on brainstorming ideas about the workflow to measure the Plasma Desktop Environment. We were initially thinking about using the second PC for measuring it due to security reasons but since we were unable to set up the 2nd server we had to shift our plans. We also got some nice inputs regarding this from Volker. Following points were discussed
No root access to user files for test user.
In a standard usage scenario, PC would run for approx. 8 hours -> this was used to determine the baseline, standard usage scenario and idle modes for the plasma testing.
Testing different snapshots of Plasma against regressions in new releases -> maybe even KDE Linux can be a good candidate.
How to run the daemon from the pipeline without root permissions.
Password stored as gitlab secret and given permission to owners (or maybe don’t require a password).
Switching to a newer set of hardware long term.
Testing plasma on older hardware and modern hardware -> for ex. video playback.
Cleanup of the existing hardware -> for ex. monitor is not needed.
Afterwards we reviewed the open issues, submitting patches for the active bugs and closed those that had already been resolved.
We then went through the report generated by the pipeline and unfortunately found out that the readings were too inaccurate and had way too much divergence in measurement values as compared to the initial report generated for Blue Angel certification. (We are allowed at max 10% increase for Blue Angel Certification).
We found out that there were several startAction and stopAction pairs missing from the script which was causing irregular measurement readings. These actions are used to generate the csv files and the R script is particularly sensitive to these labels which explains why the readings were so wildly inaccurate. So we ran the script again and checked it afterwards the sprint. There were still some issues encountered later on but they were resolved by Joseph and we got a new report for the Blue Angel Certification.
We were also joined by Koleesch who traveled from Postdam for the evening session of the KEcoLab sprint.
While we still had the following day to explore Berlin, it was our last night in the city. Karan and I spent it with Carl Schwan at Tempelhofer Feld before taking one final late night walk through the streets.
Day n/n and Final Thoughts
I had a late night train back to Marburg so me and Karan first spent the day exploring the German Musuem of Technology, it was very big and had so many artifacts describing the history of Berlin and Germany throughout the years. We were’nt able to visit the entire musuem since Karan had an early flight back to Geneva but we were able to go through the Railway and Aviation section. Regardless to say I was mesmerized. Later on I also visited Berliner Mauer and the area surrounding it.
I enjoyed my time in Berlin and huge thanks to KDE e.V for making it possible by sponsoring my travel and stay, and to KDAB and Volker for providing the office space for our sprint.
Hi everyone! This week we added voice chat for Mankala.
For Mankala, our goal was to elevate the player experience by adding real-time voice chat. We have already added text chat using XMPP, and to make this experience better, voice chat is a much better option to add.
Mankala relies on the XMPP protocol for matchmaking and text chat using the opponent and player XMPP IDs, respectively. I took KDE’s own chat application in reference: Kaidan, to implement Jingle (XEP-0167)—the XMPP extension for media sessions and connect it using an audio processing pipeline. After that, I designed the UI for this voice call to connect, accept, and decline calls with sync in UI and XMPP.
How voice is being implemented
I used the QXmpp library to handle the Jingle signaling and designed a C++ class, VoiceCallManager, which controls all the call sessions. This manager listens for incoming Jingle requests and establishes the peer-to-peer connection.
// VoiceCallManager.cpp
void VoiceCallManager::initializeManager() {
auto* callManager = m_client->findExtension<QXmppCallManager>();
// Listen for incoming XMPP Jingle calls
connect(callManager, &QXmppCallManager::callReceived,
this, [this](QXmppCall* call) {
m_activeCall = call;
m_remoteJid = call->jid();
m_isCallActive = true;
// Notify the QML frontend that a call has started
emit callStateChanged();
emit remoteInfoChanged();
// Accept the call and set up QtMultimedia audio routing
call->accept();
setupAudioPipeline();
});
}
Challenges faced
It was hard to have Game Window and Jingle work together. To handle this, I exposed the call state—such as isCallActive and remoteJid so that the UI can connect these signals easily, making the call interactive in the layout.
Here is how the QML dynamically reacts to the C++ properties:
// GameWindowLandscape.qml
ColumnLayout {
anchors. fill: parent
// 1. The Standard Text Chat UI
Item {
id: textChatView
Layout.fillWidth: true
Layout.fillHeight: true
// Hide text chat when a voice call is active!
visible: !voiceManager.isCallActive
/* ... text chat UI components ... */
}
// 2. The Active Voice Call UI
ColumnLayout {
id: activeCallView
Layout.fillWidth: true
Layout.fillHeight: true
visible: voiceManager.isCallActive
Kirigami.Icon {
source: "im-jabber"
width: 96; height: 96
}
Text {
text: voiceManager.remoteName
font.pixelSize: 24
font. bold: true
}
Button {
text: "End Call"
icon.name: "call-stop"
onClicked: voiceManager.endCall()
}
}
}
By binding QML components to the VoiceCallManager signals, the UI updates instantly based on the state of the call. After this we have successfully implemented voice and text chat for Mankala.
Correction: Sources' keys not displayed in settings
Feature: Keep focus on selection when the current filter is changed
Feature: New option to choose to currency format (currency or numerical)
Feature: Better management of deprecated source of download of currencies
We need your feedback
AI support is now available in Skrooge, and this first version is just the start. I’d love to hear about your experience: what works well, what could be better, and any use cases you want to see.
Please send your feedback by email.
For Linux users, it's highly recommended to use the official KStars Flatpak hosted at Flathub.
This release brings major improvements including the World's First AI powered Guider! Furthermore, KStars now ships with an MCP server which enables connection to any LLM for full control. In this release a limited subset of skills have been introduced, and we hope to make the MCP server feature complete by the next release. Additionally, we improved rotator calibration, guide camera streaming support, and scheduler performance with large job lists. We've also fixed dozens of stability issues and added comprehensive tilt correction for mosaic masks. Here are some highlights.
AI Guiding Assistant
Pavan Kumar is our brilliant Google Summer of Code student who spent the summer developing an AI assisted guider. He delivered the AI Guiding Assistant for Ekos, a mount specific predictive guiding architecture that trains custom models for worm gear, harmonic drive, and direct drive mounts. The wizard walks you through system identification protocols, exports training data, and loads trained models for feed forward correction.
The assistant adds a feed forward predictive layer on top of Ekos's existing proportional guiding controller. A one time characterization wizard runs a system identification pass on your mount, and the resulting data trains a small model specific to your mount class (worm gear, harmonic drive, or direct drive). During guiding, a confidence gated controller blends the AI's predicted corrections with the classic proportional fallback, so the system defers to the proven controller whenever its own confidence is low. It runs entirely on device with no cloud dependency and no GPU requirement, does not need retraining every session, and deliberately does not attempt to predict stochastic noise sources like atmospheric seeing.
AI Guide protocol separated from the wizard UI for better modularity
Fixed filter models and reworked the system identification protocol and trainer
Wizard navigation fixed when closing and reopening; export now only includes the latest session logs
Added button to read offline training instructions directly from the wizard
Oscillator improvements for better stability during training
Fixed the fingerprint builder to correctly validate model compatibility across sessions
The AI Assisted Guider is still in experimental stage. Help us by sharing your feedback and exporting logs to us to analyze.
Guide
Andreas R. landed a run of guiding fixes this release:
Fixed streaming guide mode calibration failures on fast and harmonic mounts. The pulse guard is no longer armed during calibration, preventing "Lost track of the guide star" aborts that starved the AI Guider's system identification run
Fixed dark guiding (GPG and AI feed forward) in streaming mode by distinguishing between frame prediction pulses from real correction pulses, so the measurement loop no longer starves at the 0.5 s dark interval
Fixed the AI feed forward block reading declination from FITS headers. OBJCTDEC is a sexagesimal string, but the code was calling toDouble(), so declination silently stayed 0.0 on every frame. Now reads altitude, declination, and pier side directly from the mount object instead of headers
Added per optical train persistence for Predictive Guiding (GPG) period length, so users switching between worm gear and harmonic drive mounts on the same machine no longer clobber each other's tuned period values
Fixed the GPG circular buffer losing insertion order after 8192 samples. The read offset (start) was never advanced when the buffer filled, corrupting the chronological sequence and breaking the Gaussian Process training after roughly 68 to 82 minutes of continuous guiding at short exposures
Fixed guide camera binning not restored from optical train settings on Ekos startup with real hardware. The combo box was empty when setAllSettings() ran, so the saved binning was silently dropped. Also fixed a false "not supported" detection that compared against the driver's current binning instead of its maximum
Added an "Assume DEC orthogonal to RA" calibration option, which bypasses independent DEC angle measurement when periodic error or backlash causes erratic DEC calibration datapoints, deriving the guide angle solely from the RA axis with DEC forced to a 90 degree offset
Rotator
Fixed rotator auto reverse detection and added direction parity correction. The wrong direction detector never fired because the PA error tracker was unconditionally cleared before the confirming solve could check it. Now detects reversed rotation, trials the parity flag, recalibrates the offset immediately, and persists the correction only once a retry confirms it worked
Renamed internal flag to m_RotatorParityRetried to avoid confusion with the rotator's own driver level reverse functionality
Exposed the learned parity as a "Rotator direction reversed" checkbox in Align settings (below Flip Policy), so it can also be set manually without touching the driver's ROTATOR_REVERSE switch
Clear previousPAError when rotator times out or fails, preventing false positive auto reverse triggers
Fixed false positive rotator wrong direction detection by resetting m_PreviousPAError at key state transitions (successful rotation, mount slew, PA error decrease)
Rotator motion commands are now only sent when necessary, reducing unnecessary chatter
Camera & Capture
Added simple option for camera warmup instead of requiring users to create a task action for it, so camera sensors can now pre warm before a session starts
Andreas R. fixed the filter combo not reflecting the selected job in the Sequence Editor. In standalone mode, filter name lookup always returned -1 because filterLabels() returned an empty list without an INDI connection. Now resolves by name against the combo box contents
Auto default remote directory based on frame type in the capture module: %h/Videos for Video frame type, %h/Pictures otherwise, whenever the field is empty or still holds a previously auto generated %h path
Fixed an issue where video frame type selections didn't properly disable preview and loop, and set remote directory to a sane value so INDI can successfully write the video file
Scheduler & Observatory Automation
Andreas R. contributed two fixes here:
Added a wall clock timeout to the guiding stage (reusing the existing CaptureOperationsTimeout setting, default 300s) to prevent infinite retry loops when PHD2 fails to find a guide star, preventing wasted nights on a single target
Cached .esq file content to eliminate O(N) disk I/O per evaluation cycle. With 80 jobs on a Raspberry Pi, the greedy scheduler was spending 9 to 10 minutes of pure overhead re reading and parsing XML files from the SD card per cycle. The cache is keyed by file path and modification time; XML is still re parsed per call but disk I/O is eliminated
Hy Murveit sped up loading large .esl files by not repeatedly calling currentPositionChanged. A 100 job file now loads in a second or two instead of 40 seconds.
Wolfgang Reissenberger made two scheduler improvements:
Replaced stderr output with debug log output in the scheduler for cleaner diagnostics
Changed doubled sequence validation to only emit a warning instead of blocking, allowing setups with multiple cameras to use the same sequence on different targets
Alignment & Mount Modeler
Christian Kemper fixed two solver related issues:
Fixed solver algorithm selection based on available hints, so constrained plate solves now run faster than blind solves on multi core machines. The patchMultiAlgorithm() logic now selects MULTI_DEPTHS when a position hint is present and the scale window is narrow enough, MULTI_SCALES otherwise. The 1 Default align profile is now created with sensible bounds so fresh installs benefit immediately
Fixed scale bounds being double widened. Align::startSolving() and PolarAlignmentAssistant::startSolver() were applying their own 0.8x/1.2x margin on top of the same widening in SolverUtils::prepareSolver(), producing a net [low × 0.64, high × 1.44] window instead of the intended [low × 0.8, high × 1.2]
Fixed several Sentry and user reported crashes on camera timeout and restart drivers; Focus, Align, and Capture now have consistent timeout behavior
Salman Naheed added mount model commands for programmatic access
Andreas R. fixed filter not being reset to Sequence Job filter post meridian flip if the filter was different in Align
Process JSON alignment data from INDI mounts for improved integration
When running plate solving manually, reset target position angle and previous PA error, since otherwise they remain forever until successful or another load and slew is called
FITS Viewer & File Handling
Fixed unwarranted 180 degree rotation when pier side differs from the FITS file used for Load and Slew
Andreas R. fixed the Statistics panel showing full image stats when ROI is active. When a new image loaded while the selection rectangle was active, the panel reverted to full image statistics and users had to "jiggle" the box to refresh. Now checks whether the selection rect is shown and recalculates the ROI buffer from the new image data automatically
Christian Kemper fixed a CFITSIO_LIBRARIES typo that was dropping cfitsio from the link line. The variable name was missing the trailing S, silently overwriting the library and causing undefined references at link time for targets that depend only on Qt::Core and cfitsio
Focus
Added Tilt Correction Advisory to the Aberration Inspector, which computes and displays suggested tilt plate adjustments after autofocus with a mosaic mask. Supports 3 point plates (ETA, Octopi, manual 3 screw) and 4 point plates (TouTek style corner screws). Includes a rear view diagram with color coded points, mode toggle (Relative or Push only), thread presets (M2.5 to M6, Wanderer ETA, Custom), camera rotation dial, and an "Apply to ETA" button that sends corrections directly to Wanderer ETA M54 via INDI
Thomas Nemer fixed two focus related bugs:
Fixed Focus::autoFocusLinear and scanStartPos passing measure as weight. Two callsites passed getLastMeasure() into a weight slot instead of getLastWeight(), corrupting the V curve fit and the weights exposed via Focus Advisor
Fixed Focus::focusOut ignoring caller supplied step count. A duplicate assignment was unconditionally overwriting any explicit value, so focusOut(100) always moved by the UI default
MCP Server (Remote Control)
Thomas Nemer established the MCP server foundation, an in process MCP server inside Ekos that lets external clients drive KStars over JSON RPC 2.0 over HTTP, with bearer token auth and an optional read only token. It includes transport, tool registry, server orchestrator, settings UI, and comprehensive unit tests. His additional work this release includes:
MCP mount control tool family (12 tools: coords, goto, goto_target, sync, park/unpark, abort, set_tracking, set_track_mode, set_slew_rate, get_slew_rates, set_meridian_flip)
MCP catalog search tool, which resolves fuzzy or user supplied names ("M42", "andromeda", "polaris") into canonical KStars names for use with mount_goto_target
Focuser tool family (status, move_absolute, move_relative, abort_move) with a shared device lookup helper
Image access tool family (image_last_info, image_last_thumbnail) with per camera frame cache
"Available tools" panel in MCP settings, so operators can see which tools are exposed, what each does, and enable or disable individual tools or entire families via checkboxes
Unit tests isolated from the real token keychain, so the test suite no longer clobbers the developer's stored MCP credentials
Silenced Wmissing field initializers warnings in tool registrations
Stability & Bug Fixes
Ilia Belov fixed a crash when a stale EkosLive dialog response arrives after the dialog was dismissed. KSMessageBox is a reused singleton, and buttons of a dismissed dialog stayed as its children; a remote response sent after dismissal clicked a stale button and crashed KStars with SIGSEGV
Andreas R. fixed missing i18n and null check crashes in BuildFilterOffsets: button labels, tooltips, and status text were untranslatable, and several methods accessed m_BFOModel.item() without null checks
Fixed a crash when building offsets by using showDialog properly
Made Build Filter Offsets accessible programmatically and via EkosLive
Set proper unique object names for both Filter Manager and Build Filter Offsets
Fixed an issue where combo boxes in global config were not getting saved; only write the combo's index when it is populated and has a valid selection
Fixed -1 corrupting persisted combo settings before device connects. Several combos (guide/CCD binning) are only populated once a device connects, so currentIndex() returned -1 and overwrote the saved option
Suppress pulses from reaching the mount when disabled
Mark state as aborted if user explicitly cancels the dialog
Shut the profile down instead of indefinitely waiting when checkINDITimeout fires
Correctly wait for remote drivers and add contribution of all sequence files
Build & Infrastructure
Attempt to make Flatpak arm64 builds use only 4 cores to work around OOM errors
Limit Eigen to 4 CPU cores so it can build on the arm64 Flatpak CI runner
Do not build testing, demos, docs, or Fortran in Eigen
KStars now compiles with OpenCV 5
Scarlett Moore added cmake root path env for Snapcraft
Other Improvements
Extended filter offsets maximum range to 1 million per user request
Added a script to generate indidrivers.xml
Fixed wizard state transition when stopped
Offset is now updated after each solve, with more logging to diagnose future issues
Guilherme Marçal Silva updated the kstars.notifyrc file
Christian Kemper made three additional fixes:
Added KSPaths bundle Resources/kstars/ search on macOS, so data files are now found directly in the app bundle
Corrected DST rule for countries that abolished daylight saving in citydb
Normalized the country column in citydb to ISO 3166 1 alpha 2 codes
Replaced the binary citydb.sqlite with a source built TSV format; the database is now generated at build time
The idea was simple enough… its a timer, lets make a digital watch. And having grown up in the 80's my brain obviously went directly to those old Casio watches we all had, wanted, lost, or somehow managed to keep alive for 20 years
So I started with a very basic shape, mostly trying to get the proportions right, and from there it slowly became more and more of a actual object. The side buttons appeared, the LCD got some depth, the case became more angular, and I spent a frankly unreasonable amount of time trying to make the brushed steel look like brushed steel.
Then came the fun part… all the little useless details.
The light and alarm symbols, the not days of the week but rather running timers , the branding and of course the very prestigious "kool desktop environment 2026" written across the top. Absolutely essential information at 64 pixels
The last bit was adding the gear/play element so it reads as KTimer and not simply as the KASIO watch I apparently wanted when I was 12.
And thats pretty much how these things happen… start with a rectangle, add a few details, remove some, add way too many again, move things around for far too long and eventually decide its an icon.
A k Time well spent… probably.
Progress on the icon side is coming along nicely. BTW me and Filip are gona do a presentations together in aKdemy about Oxygen, if you are planing on attending (you should), you know were to find us
Thanks, I really don’t care much about labels, my goal is more, are they fun and make you feal something? Do they describe the function? Do they look as smart as the app? Do they look like we care about the user experience???
Deixe um comentário