Skip to content

fix(kde): resolve focused window to its .desktop ID so picker bindings activate - #175

Merged
mmaher88 merged 1 commit into
masterfrom
fix/kde-flatpak-wmclass
Nov 9, 2026
Merged

mmaher88 merged 1 commit into
masterfrom
fix/kde-flatpak-wmclass

Conversation

@mmaher88

@mmaher88 mmaher88 commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Problem

Adding an app profile for Google Chrome (flatpak) from the "add profile" picker created a binding that never activated; Chrome stayed on Default.

  • The picker (LinuxDesktopBase::runningApplications) records each app under its .desktop file ID → com.google.Chrome.

  • KDeDesktop::focusChanged passed KWin's desktopFileName through verbatim. On Wayland that is the window's app_id, which is not always a .desktop ID. Read from a live Plasma 6 session:

    window resourceClass desktopFileName .desktop file
    Chrome (flatpak) google-chrome google-chrome com.google.Chrome.desktop (StartupWMClass=google-chrome)
    Evince org.gnome.Evince org.gnome.Evince org.gnome.Evince.desktop
    Dolphin org.kde.dolphin org.kde.dolphin org.kde.dolphin.desktop
  • ProfileEngine::profileForApp compares exactly (case-insensitive), so google-chrome ≠ com.google.Chrome → Default.

Fix

Fixed at the source, in the desktop layer. ProfileEngine stays exact-match, which keeps the design from 6b7dedd (identity resolution lives in the desktop backend).

  • KDeDesktop::focusChanged uses desktopFileName only when it names an installed .desktop file. Otherwise it resolves desktopFileName, then resourceClass, through StartupWMClass or the reverse-DNS tail. Hyprland and GNOME already use this lookup. If nothing claims the window, it falls back to KWin's name.
  • LinuxDesktopBase::findDesktopFile() checks for an exact .desktop ID across all dirs before the fuzzy scan, and returns empty on no match. Native Chrome's google-chrome.desktop therefore still wins when both builds are installed, so existing google-chrome bindings made for native Chrome keep working. resolveDesktopFile() keeps its fall-back-to-input contract, so the Hyprland and GNOME call sites are unchanged. They now also get the exact-ID-first behaviour.
  • A focus debug line logs when a KWin window is remapped (KWin window "google-chrome" resolved to desktop file "com.google.Chrome").
  • New test seam setDesktopDirsForTest().

Reverse-DNS apps whose desktopFileName already is their .desktop ID resolve exactly as before: Okular, Evince, Xournal++, Dolphin, Telegram.

Tests

tests/test_wmclass_resolution.cpp adds a picker → binding → KWin-focus round trip against fixture desktop dirs:

  • FlatpakChromePickerBindingActivatesOnFocus: the regression. It failed before the fix (focus emitted google-chrome).
  • ExistingDesktopFileNameIsTrustedVerbatim: native google-chrome.desktop beats flatpak's StartupWMClass claim.
  • UnknownAppFallsBackToDesktopFileName
  • ReverseDnsApps/KdeFocusRoundTrip: Evince, Dolphin, flatpak Okular, Xournal++, flatpak Telegram, plus the X11 / no-desktopFileName path for Okular and Telegram.

logitune-tests: 784 passed (with XDG_DATA_DIRS=<build dir>). The pre-push hook ran the C++, tray, QML and Python suites, all green.

Hardware check (KDE Plasma 6 Wayland, MX Master 3S)

I relaunched the app from this branch with a com.google.Chrome=Google Chrome binding on the connected mouse, then focused flatpak Chrome:

[logitune.focus] KWin window "google-chrome" resolved to desktop file "com.google.Chrome"
[logitune.focus] focus: "com.google.Chrome"
[logitune.app  ] diverting button 3 CID 53 ...   (profile applied)
[logitune.device] thumb wheel setReporting confirmed ...

Focusing away re-applied Default.

Not changed

Bindings stored under a key that no longer names an installed app (for example google-chrome after moving from native to flatpak Chrome) don't match the flatpak window. The picker shows the app under its new ID, so re-adding the profile fixes it.

🤖 Generated with Claude Code

…s activate

The "add profile" picker records an app under its .desktop file ID, but
KDeDesktop::focusChanged passed KWin's desktopFileName through verbatim.
On Wayland that is the window's app_id, which is not always a .desktop ID:
flatpak Chrome reports "google-chrome" while its desktop file is
com.google.Chrome.desktop (StartupWMClass=google-chrome). A Chrome binding
created from the picker therefore never matched and Chrome stayed on Default.

focusChanged now trusts desktopFileName only when it names an installed
.desktop file; otherwise it resolves it (then resourceClass) through
StartupWMClass / reverse-DNS tail, the same lookup Hyprland and GNOME use,
and falls back to KWin's name when nothing claims the window.

LinuxDesktopBase gains findDesktopFile(), which checks for an exact .desktop
ID before the fuzzy scan (so native Chrome's google-chrome.desktop still wins
when both builds are installed) and reports "no match" as an empty string.
resolveDesktopFile() keeps its fall-back-to-input contract on top of it.

Tests: picker -> binding -> KWin focus round trip against fixture desktop
dirs (new setDesktopDirsForTest seam), covering flatpak Chrome plus the
reverse-DNS apps already bound in the wild (Okular, Evince, Xournal++,
Dolphin, Telegram) and the X11 no-desktopFileName path.
@mmaher88
mmaher88 merged commit a50311f into master Nov 9, 2026
6 checks passed
@mmaher88
mmaher88 deleted the fix/kde-flatpak-wmclass branch November 9, 2026 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant