qtwayland: declare proper `app_id` for wrapped executables

Since NixOS 21.11 it seems as if QT uses Wayland if possible[1].
However, my `pinentry-qt` flavor stopped floating because it's now
running in Wayland-mode rather than in XWayland mode where this seems to
be fine.

I wanted to add a rule to my `sway(1)`-config for that, but realized
that `pinentry` is missing an `app_id` to match:

    $ swaymsg -t get_tree | jq '.nodes[2].nodes[1].nodes[1].nodes[1].app_id'
    ""

This is because `QWaylandWindow::initWindow()` uses the application's
`baseName` to determine the app window. Unfortunately the `baseName`
drops all chars of the filename after the first dot[2]. This means that
every wrapped Nix package (i.e. `pkgs.foo` with `$out/bin/.foo-wrapped`)
will have an empty-string as baseName because the first character of the
filename is a dot. Since we're using the `wrapQtAppsHook` quite
excessively, a lot of programs are affected by this.

In order to work around this, I implemented a small patch for
`qtwayland` that strips away the `nixpkgs`-specific `.(name)-wrapped` of
a filename if needed and then sets the `app_id` to the expected
`baseName`. This is useful to make e.g. `sway`-configs with
`for_window`[3]-expressions from other distros compatible.

With this change, the `app_id` is set as I'd expect it:

    $ swaymsg -t get_tree | jq '.nodes[2].nodes[1].nodes[1].nodes[1].app_id'
    "pinentry-qt"

Even though we'll need the patch to get e.g. `foo` from `.foo-wrapped`,
I decided to file a bug-report against upstream[4].

[1] https://nixos.org/manual/nixos/stable/release-notes.html#sec-release-21.11
[2] https://doc.qt.io/qt-5/qfileinfo.html#baseName
[3] https://man.archlinux.org/man/sway.5.en
[4] https://bugreports.qt.io/browse/QTBUG-99137
main
Maximilian Bosch 3 years ago
parent e2b2136d63
commit b3823a35e5
No known key found for this signature in database
GPG Key ID: 091DBF4D1FC46B8E
  1. 36
      pkgs/development/libraries/qt-5/modules/qtwayland-app_id.patch
  2. 6
      pkgs/development/libraries/qt-5/modules/qtwayland.nix

@ -0,0 +1,36 @@
Ensure that the correct `app_id` for Wayland is set. The upstream implementation
uses `QFileInfo::baseName()`[1] which strips everything away after the first dot.
This means that `.foo-wrapped` has an empty `app_id` because `baseName` returns
an empty string in this case.
The patch basically checks whether the program has the form `.foo-wrapped` (i.e. got
wrapped by `makeWrapper`) and if that's the case, `foo` will be the correct `app_id`.
[1] https://doc.qt.io/qt-5/qfileinfo.html#baseName
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index ba881cb..b3fd031 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -167,7 +167,20 @@ void QWaylandWindow::initWindow()
Qt::SkipEmptyParts);
if (domainName.isEmpty()) {
- mShellSurface->setAppId(fi.baseName());
+ auto baseName = fi.baseName();
+ if (baseName.isEmpty()) {
+ auto fileName = fi.fileName();
+ if (fileName.endsWith("-wrapped") && fileName.startsWith(".")) {
+ do {
+ auto len = fileName.length();
+ fileName = fileName.right(len - 1);
+ fileName = fileName.left(len - 9);
+ } while (fileName.endsWith("-wrapped") && fileName.startsWith("."));
+ mShellSurface->setAppId(fileName);
+ }
+ } else {
+ mShellSurface->setAppId(baseName);
+ }
} else {
QString appId;
for (int i = 0; i < domainName.count(); ++i)

@ -6,4 +6,10 @@ qtModule {
buildInputs = [ wayland ];
nativeBuildInputs = [ pkg-config ];
outputs = [ "out" "dev" "bin" ];
patches = [
# NixOS-specific, ensure that app_id is correctly determined for
# wrapped executables from `wrapQtAppsHook` (see comment in patch for further
# context).
./qtwayland-app_id.patch
];
}

Loading…
Cancel
Save