The dynamic linker needs to load libgtk4-layer-shell.so
before libwayland-client.so
.
In your build system, make sure gtk4-layer-shell
is explicitly linked to and first in the list. For example in meson it should appear first in the list of dependencies
to your executable
. To debug where a problem might be follow these steps:
- Inspect the compiler commands (for example by running
ninja -C build -v
) and make sure gtk4-layer-shell is being linked before libwayland-client (ideally before GTK as well, though that doesn't seem to be necessary) - Run
ldd
on your binary and make sure gtk4-layer-shell appears before libwayland - Run your binary with
LD_DEBUG=libs
and make sure gtk4-layer-shell is loaded before libwayland. It may be helpful to redirect stderr to stdout and grep for "find library", so a full command might look likeLD_DEBUG=libs build/my-bin 2>&1 | grep 'find library='
GI Repository likes to load all dependencies before loading a library, so you need to make sure this is at the top of your main script:
# For GTK4 Layer Shell to get linked before libwayland-client we must explicitly load it before importing with gi
from ctypes import CDLL
CDLL('libgtk4-layer-shell.so')
If that still isn't working you can debug with LD_DEBUG
as described above.
You should be able to get most things working using the LD_PRELOAD
environment variable. Run the program with it set to the path of gtk4-layer-shell:
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libgtk4-layer-shell.so my-app
At time of writing GTK4 has no official support for non-XDG Wayland shells (which is fair enough, since GTK3 only had partial broken support). To get around this we shim some libwayland calls. We define some symbols normally defined by libwayland, so that GTK calls into us when it thinks it's calling into libwayland. We dlopen
the real libwayland and pass most calls directly on to it, while modifying calls that pertain to XDG Shell and Layer Shell. This allows us to provide GTK the XDG Shell interface it expects and speak Layer Shell to libwayland-client (and beyond that the Wayland compositor).
The main downside is that if libwayland gets loaded before us, it's calls take precedence and the shim doesn't work. We attempt to detect this and display a warning.
Triggering the link error intentionally (for example for testing that the library detects it) can be difficult. You need at least the following:
- Build separate from the gtk4-layer-shell project. If your app is built within the project (even if it's a different executable) meson links our library first.
- Link libwayland-client before gtk4-layer-shell
- Make at least one call to libwayland in your app (otherwise your linking of libwayland-client is ignored)
Alternatively you can test by editing the CDLL call out of the example Python script and calling ninja -C build && GI_TYPELIB_PATH=$PWD/build/src LD_LIBRARY_PATH=$PWD/build/src python examples/simple-example.py
.
Old versions of my wayland-debug tool set used LD_PRELOAD
to load a patched libwayland, which breaks this library. wayland-debug has been updated to use LD_LIBRARY_PATH
instead which seems to work fine. If you have any problems please let me know.