Skip to content

Harden cross-desktop fallback and packaging metadata#6

Open
Zakkaus wants to merge 2 commits into
locez:mainfrom
Zakkaus:feat/cross-de-packaging
Open

Harden cross-desktop fallback and packaging metadata#6
Zakkaus wants to merge 2 commits into
locez:mainfrom
Zakkaus:feat/cross-de-packaging

Conversation

@Zakkaus

@Zakkaus Zakkaus commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Hardens the cross-desktop fallback path and fills in the packaging metadata a
Linux desktop app is expected to ship. Comes out of a cross-DE / GPU /
OSS-hygiene audit of the code against the Gentoo ebuild in
gentoo-zh/overlay#10842.

Two classes of change: runtime correctness (detect layer-shell support and
Qt-ABI compatibility at runtime instead of guessing from the desktop name), and
packaging hygiene (AppStream metainfo, man page, PEP 639 license, desktop
entry keys, an explicit blur build option).

Runtime correctness

X11 gate (native.py). On an X11 session the bridge .so still dlopens
(its Qt/Wayland deps are present regardless), but every call no-ops on an xcb
surface -- which silently disabled the top-most/drag fallback the overlay is
supposed to use there. The controller now refuses the bridge up front unless the
platform is Wayland, so the fallback actually runs.

Runtime layer-shell probe (koto_has_layer_shell). New C export does a
one-shot wl_registry probe for zwlr_layer_shell_v1. This is authoritative
where the desktop-name check is not: it catches Weston, Cinnamon, and GNOME
under any XDG_CURRENT_DESKTOP value, and avoids the Budgie/wlroots false
positive. It is hasattr-guarded on the Python side, so an older bridge without
the symbol still loads and falls back to the existing name check.

Qt-ABI handshake (koto_layer_qt_version). The bridge links Qt QPA/private
API, which carries no cross-minor ABI guarantee. _load() now refuses a bridge
built against a different Qt minor than the running PyQt6. This only bites a
hand-built/mismatched wheel; a distro build shares one system Qt. Also
hasattr-guarded.

main.py. Drops the dead QT_AUTO_SCREEN_SCALE_FACTOR env knob -- a Qt5-ism
Qt6 never reads (it misleads readers into thinking scaling is pinned). Keeps
QT_SCALE_FACTOR, which does pin the device pixel ratio.

Packaging

  • CMakeLists: blur is now an explicit KOTONOHA_ENABLE_BLUR option (default
    ON, FATAL_ERROR if requested without wayland-scanner) rather than a silent
    find_program degrade. This removes the "automagic" dependency pattern
    packagers reject. Default ON is safe because the build already hard-requires
    the wayland-client dev package, which ships wayland-scanner. Adds a
    KOTONOHA_INSTALL_LICENSE gate and a Qt-version STATUS line.
  • pyproject: PEP 639 license = "MIT" + license-files = ["LICENSE"]
    (emits License-Expression/License-File, metadata 2.4); trims build-only
    sources (*.cpp, *.sh, protocols/*.xml) from the wheel.
  • AppStream: packaging/dev.locez.kotonoha.metainfo.xml so the app is
    visible in Discover/GNOME Software. project_license is MIT (the LGPL is
    dependency linkage, not this component's source license); launchable points
    at the installed kotonoha.desktop; no <screenshots> until a hosted image
    and a tagged release exist.
  • Man page: packaging/kotonoha.1 (--port/-p, -v/--verbose, default
    port 28745).
  • Desktop entry: Version=1.5, StartupNotify=false (tray app, no window
    on launch), StartupWMClass=kotonoha (matches the app_id Qt derives from
    setApplicationName).
  • All distros ship the new files: the metainfo and man page are installed by
    the Debian (debian/install) and Fedora (%install/%files) packaging too,
    not just the external Gentoo ebuild. The deb/rpm CI smoke jobs assert both
    landed.
  • Dropped a duplicate asset: assets/icons/icon.png was byte-identical to
    the default assets/icon.png; discover_icon_paths already deduped it out by
    digest at runtime, so it never showed in the picker -- removing it trims ~858K
    from the repo and wheel.
  • README documents the KOTONOHA_ENABLE_BLUR / KOTONOHA_INSTALL_LICENSE
    build options.

Capability matrix

Session Overlay mode Blur
KDE Plasma (Wayland) layer-shell (float above fullscreen) yes (KWin)
wlroots (Sway/Hyprland, Wayland) layer-shell no (no KWin protocol)
GNOME/Mutter (Wayland) top-most ordinary window (probe returns 0) no
Weston / Cinnamon (Wayland) top-most ordinary window (probe returns 0) no
X11 (any WM) top-most window via _NET_WM_STATE_ABOVE no

GPU vendor (NVIDIA/AMD/Intel) is irrelevant here: the overlay is a wl_shm
raster QWidget surface with no GL/EGL/QtQuick path, so no vendor-specific env
tuning applies. The "EGL not available" log line is benign noise.

Tests

tests/test_native.py covers the X11 gate, the runtime probe
(present / absent / old-bridge-without-symbol), and the real-bridge Qt
handshake. tests/test_native_packaging.py updated for the new wheel.exclude.
Full suite: 357 passing.

Not in this PR

The corrected kotonoha-9999.ebuild for gentoo-zh/overlay#10842 is handled
separately in that repo (adds dev-util/wayland-scanner BDEPEND, qtbase:6[gui],
layer-shell-qt:6, LICENSE="MIT LGPL-2.1+", installs the metainfo + man page).
Wiring KOTONOHA_INSTALL_LICENSE=OFF into the wheel build is deferred until the
deb/rpm specs migrate their license declarations to .dist-info/licenses/.

Zakkaus added 2 commits July 15, 2026 10:02
Runtime layer-shell detection and Qt-ABI safety, plus the packaging
files a Linux desktop app is expected to ship. Addresses the cross-DE /
GPU / OSS-hygiene audit against overlay#10842.

native bridge (native.py / layer_shell_bridge.cpp):
- Gate the overlay on a Wayland session first: on X11 the .so dlopens
  fine but every call no-ops on an xcb surface, silently killing the
  top-most/drag fallback. Refuse it up front so the fallback runs.
- Add koto_has_layer_shell(): a one-shot wl_registry probe for
  zwlr_layer_shell_v1. This is authoritative where the desktop-name
  check is not -- it catches Weston/Cinnamon/GNOME-under-any-XDG-value
  and avoids the Budgie/wlroots false positive. hasattr-guarded, so an
  older bridge without the symbol still loads via the name check.
- Add koto_layer_qt_version() + a Qt-ABI handshake in _load(): the
  bridge links Qt QPA/private API (no cross-minor ABI guarantee), so
  refuse a bridge built against a different Qt minor than the running
  PyQt6. Only bites a mismatched hand-built wheel; distro builds share
  one system Qt. Also hasattr-guarded for old bridges.
- Docstring/reason strings stop over-promising top-most/positioning on
  layer-shell-less Wayland.

main.py: drop the dead QT_AUTO_SCREEN_SCALE_FACTOR knob (a Qt5-ism Qt6
never reads); keep QT_SCALE_FACTOR, which does pin the DPR.

CMakeLists: make blur an explicit KOTONOHA_ENABLE_BLUR option (default
ON, FATAL_ERROR if requested without wayland-scanner) instead of a
silent find_program degrade -- kills the automagic dependency. Add a
KOTONOHA_INSTALL_LICENSE gate and a Qt-version STATUS line.

pyproject: PEP 639 license = "MIT" + license-files; trim build-only
sources (*.cpp, *.sh, protocols/*.xml) from the wheel.

packaging: ship dev.locez.kotonoha.metainfo.xml (AppStream) and a
kotonoha.1 man page; add Version/StartupNotify/StartupWMClass to the
desktop entry.

Tests: new tests/test_native.py covers the X11 gate, the runtime probe
(present/absent/old-bridge), and the real-bridge handshake.
The AppStream metainfo and man page were only wired into the external
Gentoo ebuild; the repo's own Debian and Fedora packaging shipped
neither. Install both there too so every distro build is consistent:

- debian/install: metainfo -> usr/share/metainfo, man page ->
  usr/share/man/man1 (dh_compress gzips it).
- fedora spec: install both in %install and list them in %files
  (man page globbed as kotonoha.1* for the compressed suffix).
- package.yml deb/rpm smoke jobs assert both landed.

Drop src/kotonoha/assets/icons/icon.png: it is byte-identical to the
default assets/icon.png, so discover_icon_paths already dedupes it out
by digest at runtime -- it never appeared in the picker. Removing it
trims ~858K of dead weight from the repo and wheel.

README documents the KOTONOHA_ENABLE_BLUR / KOTONOHA_INSTALL_LICENSE
build options.

Tests updated to lock in the deb/rpm install lines and CI checks.
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