https://blog.broulik.de/2025/08/on-window-activation/ Skip to content Kai Uwe's Blog Stories of a KDE developer Menu and widgets * Sponsor [?] * Impressum * Privacy Policy Search for: [ ] [Search] Recent Posts * New Hardware Fun * On Window Activation * PI(M)P Your Clock * KIO Goodies * Be Free to Have Multiple Clocks Recent Comments * rincewind on New Hardware Fun * bnoob on New Hardware Fun * Seth Richardson on On Window Activation * Kevin Krammer on On Window Activation * pallaswept on On Window Activation Archives * August 2025 * June 2025 * May 2025 * April 2025 * March 2025 * January 2025 * December 2024 * November 2024 * September 2024 * August 2024 * June 2024 * April 2024 * March 2024 * February 2024 * January 2024 * December 2023 * November 2023 * October 2023 * September 2023 * August 2023 * July 2023 * May 2023 * December 2022 * November 2022 * October 2022 * January 2022 * October 2021 * June 2021 * May 2021 * March 2021 * January 2021 * December 2020 * October 2020 * August 2020 * June 2020 * May 2020 * April 2020 * February 2020 * January 2020 * December 2019 * November 2019 * October 2019 * August 2019 * July 2019 * May 2019 * April 2019 * February 2019 * November 2018 * August 2018 * March 2018 * October 2017 * April 2017 * March 2017 * December 2016 * November 2016 * October 2016 * September 2016 * August 2016 * June 2016 * April 2016 * March 2016 * February 2016 * January 2016 * December 2015 * November 2015 * October 2015 * August 2015 * April 2015 * February 2015 Categories * Allgemein * Planet KDE Meta * Log in * Entries feed * Comments feed * WordPress.org On Window Activation You click a link in your chat app, your browser with a hundred tabs comes to the front and opens that page. How hard can it be? Well, you probably know by now that Wayland, unlike X, doesn't let one application force its idiot wishes on everyone else. In order for an application to bring its window to the front, it needs to make use of the XDG Activation protocol. KWrite (text editor) window, window has no focus (colors are softened). Task bar with a couple of apps, KWrite icon has an orange background behind it, indicating KWrite is demanding attentionA KWrite window that failed to activate and instead is weeping bitterly for attention in the task bar In essence, an application cannot take focus, it can only receive focus. In the example above, your chat app would request an XDG Activation token from the compositor. It then asks the system to open the given URL (typically launching the web browser) and sends along the token. The browser can then use this token to activate its window. This token is just a magic string, it doesn't matter how it gets from one application to another. Typically, a new application is launched with the XDG_ACTIVATION_TOKEN variable in its environment. When activating an existing one, an activation-token property is added to the platform_data dict sent via DBus. There's also older protocols that weren't designed with this in mind, such as Notifications, StatusNotifierItem (tray icons), or PolKit requests where we cannot change the existing method signatures. Here we instead added some way to set a token just before the actual call. However, just because you have a token doesn't mean you can raise your window! The compositor can invalidate your token at any time and reject your activation request. The idea is that the compositor gets enough information to decide whether the request is genuine or some application popping up a dialog in the middle of you typing something. A token request can include the surface that requests the activation, the input serial from the focus or mouse event that resulted in this request, and/or the application ID of the application that should be activated. While all of this is optional (and there can be valid reasons why you don't have a particular piece of information at this time), the compositor is more likely to decline activation if the information is incomplete or doesn't match what the requesting application provided. A lot of places in Qt, KDE Frameworks, and other toolkits and applications have already been adjusted to this workflow and work seamlessly. For example, calling requestActivate on a QWindow will check if there is an XDG_ACTIVATION_TOKEN in the environment and use it, otherwise request one. Qt also does this automatically when the window opens to match the behavior of other platforms. Likewise, things like ApplicationLauncherJob and OpenUrlJob will automatically request a token before proceeding. On the other hand, KDBusService (for implementing single instance applications) automatically sets the corresponding environment variable when it received a token via DBus. Together this makes sure that most KDE applications just work out of the box. You might be wondering: didn't KWin-X11 have "focus stealing prevention"? It sure does. There's a complicated set of heuristics based on _NET_WM_USER_TIME to judge whether the new window appeared as a result of explicit user interaction or is unsolicited. Remember how back in ye olde days, KWin's focus stealing prevention would keep the Adobe Flash Player fullscreen window from showing ontop of the YouTube video you're watching? Yeah, it's not perfect. KWin can also only react on things that have already happened. For instance, when an application uses XSetInputFocus on a window from a different application, KWin will detect that and consider it a malicious request and restore previous focus but for a split second focus did change. If you want to know more, there's a 200+ lines comment in activation.cpp in KWin's git repo that explains it all. But then again the application could just do whatever it wants and bypass all of this. "Window Behavior" configuration dialog, various window-related tabs and options, mouse cursor pointing at a combo box "Focus stealing prevention" whose current item is "Extreme"Xtreme Focus Stealing Prevention(tm) Unfortunately, there's still a few places that don't do XDG Activation correctly. It didn't matter much under X - in doubt we could just forceActiveWindow - but now we have to fix those scenarios properly! In order to test whether your application is well-behaved, use the latest git master branch of KWin and set "Focus Stealing Prevention" in Window Management settings to "Extreme". This will make KWin activate a window if and only if it requests activation with a valid token. Using this, over the past couple of days Xaver Hugl of KWin fame and I fixed a bunch of issues, including but not limited to: * Dolphin threw away its token before activating its main window when launching a new instance (activating an existing one worked fine) * KRunner, Kickoff, and other Plasmoid popups did not request activation at all * LayerShell-Qt now requests activation on show (to match Qt behavior) * LayerShell-Qt didn't read the XDG_ACTIVATION_TOKEN from the environment when provided * Privileged clients, like Plasma and KGlobalAccel, were unable to request tokens in some situations * Modifier key presses no longer count towards focus stealing prevention: they're often used as part of a global keyboard shortcut and don't necessarily mean the user is interacting with the active window Furthermore, the DBusRunner specification gained a SetActivationToken method which is called just before Run. Baloo (desktop search) runner now uses this to ensure opening files in an existing application window works. Likewise for the KClock runner bringing KClock to the front properly. I further improved the recent documents runner and places runner to send the file type to the OpenUrlJob so it doesn't have to determine it again. This makes the job much quicker and avoids KRunner closing before the activation token is requested by the job. However, we have yet to find a proper solution for this in KRunner. With all of this in place, we'll likely switch on KWin's focus stealing on Wayland at a low level and make it gradually stricter as applications are being fixed. Posted on 2025-08-042025-08-04Author Kai UweCategories Planet KDETags Plasma, Wayland 6 thoughts on "On Window Activation" 1. Kevin Krammer says: 2025-08-04 at 13:06 Do you think it would be possible for a terminal, e.g. Konsole, to somehow inject such a token into its shell process so that tools like kde-open could then pick it up? Reply 1. Christoph Cullmann says: 2025-08-04 at 19:44 see https://invent.kde.org/utilities/kate/-/merge_requests/ 1841 and linked stuff Reply 1. Kevin Krammer says: 2025-08-05 at 09:13 Ah, nice! The other way around but much more straight forward, likely shareable with other applications. Changing the shell's environment would probably require to "be the shell" or some LD_PRELOAD trickery. Reply 2. nyanpasu64 says: 2025-08-04 at 15:21 How does requiring activation tokens interact with requirements like "launch a program from a terminal and it should be given focus if the controlling terminal is still activated and untouched"? (I recall issues with some Qt apps not gaining focus on startup on macOS, but forgot the exact circumstances.) I've also observed weirdness where Firefox doesn't get activated when launching it from XWayland applications, xdg-open, or even right-clicking in Dolphin. There's a writeup on Mozilla at https: //bugzilla.mozilla.org/show_bug.cgi?id=1873981#c28, and in my testing I found activate() is called twice with "not-granted-666" when it fails, and once with "not-granted-666" and once with "kwin-..." when it succeeds. I don't know why Firefox doesn't get a token properly in some cases. Reply 3. pallaswept says: 2025-08-05 at 05:44 I am reminded of this https://discuss.kde.org/t/ ideas-for-better-focus-stealing-prevention/32154/ thread where we discussed ways to prevent focus stealing. OP actually wanted to keep focus stealing, sometimes, so it's a bit off-topic, but I discussed how to prevent it entirely. I guess in the context of this change, that could be adapted to: when the user provides input (to any window, or to plasma/the desktop itself) all the tokens need to be invalidated so that the new window doesn't steal focus (and subsequent input) from wherever they were typing/clicking while they waited for it to appear. An example you can try that causes focus stealing on 6.4: Open konsole. Open your app launcher. Click the kate icon and start typing stuff. Now half of it is in konsole and half is in kate. Kate stole focus mid-sentence, because konsole had focus and we were actively using it. Probably, konsole shouldn't have even been given focus after we clicked the kate icon (because that should focus kate), but if it is, focus definitely shouldn't be later granted to kate if we started typing a command into konsole in the meantime. That's the worst and most dangerous type of focus stealing; mid-sentence. A real world example where this bites me every day is starting apps at boot time. I click the app launcher, click firefox, firefox starts opening windows and they get focus, I click the app launcher to open another app, another firefox window opens, and my focus is stolen and the app launcher closes. I click the app launcher again to try again, nope, stolen by the next firefox window, have to wait until the windows have all finished opening before I can do anything else. It's a paper cut, but it's still great to see someone taking care of it. Thanks Kai and Xavier! Reply 4. Seth Richardson says: 2025-08-05 at 14:48 After years of Wayland I just moved back to X11 because of this. It was starting to annoy the hell out of me, it's good to see that it is being addressed. What I would like to know is since when this focus stealing is being prevented at all because I never noticed this before. Reply Leave a Reply Cancel reply Your email address will not be published. Required fields are marked * [ ] [ ] [ ] [ ] [ ] [ ] [ ] Comment * [ ] [ ] Name * [ ] Email * [ ] Website [ ] [ ] By using this form you agree with the storage and handling of your data by this website. * [Post Comment] [ ] [ ] [ ] [ ] [ ] [ ] [ ] D[ ] Post navigation Previous Previous post: PI(M)P Your Clock Next Next post: New Hardware Fun Privacy Policy Proudly powered by WordPress