GTK4 Layer Shell

repository·main·Indexed 43 days ago

https://github.com/wmww/gtk4-layer-shell

A library providing GTK4 applications access to the Wayland Layer Shell and Session Lock protocols. It enables the creation of desktop components such as panels, notifications, and lock screens. Compatible with C, C++, and languages supporting GObject introspection like Python and Vala, with additional bindings for Rust and Ruby. Supports wlroots-based (Sway), Smithay-based (COSMIC), Mir-based, and KDE Plasma compositors.

Tokens
2.4K
Snippets
7
Records
14
Agent score
56%

What's inside GTK4 Layer Shell

  1. What is GTK4 Layer Shell?

    main

    GTK4 Layer Shell is a library that enables GTK4 applications to use the Wayland Layer Shell and Session Lock protocols.

    • Layer Shell protocol: Allows building desktop shell components like panels, notifications, and wallpapers by anchoring windows to specific corners/edges of an output or stretching them across the entire output.
    • Session Lock protocol: Allows building lock screens.

    The library is compatible with C, C++, and any language supporting GObject introspection (e.g., Python, Vala).

  2. Understand the GTK4 Layer Shell shim mechanism

    main

    GTK4 lacks official support for non-XDG Wayland shells. gtk4-layer-shell works by shimming libwayland calls.

    How it works:

    1. The library defines symbols that are normally part of libwayland.
    2. When GTK calls these symbols, it hits the shim instead of the real libwayland.
    3. The shim then uses dlopen to load the real libwayland and passes calls through.
    4. The shim intercepts and modifies calls pertaining to XDG Shell and Layer Shell to provide the expected interface to GTK while communicating correctly with the Wayland compositor.

    Critical Requirement: If libwayland-client.so is loaded before the shim, the real library's symbols take precedence, and the shim fails to intercept the calls. The library will attempt to detect this and display a warning.

  3. Check Wayland compositor compatibility

    main

    GTK4 Layer Shell only works on Wayland compositors that support the Layer Shell protocol.

    Supported:

    • wlroots-based compositors (e.g., Sway)
    • Smithay-based compositors (e.g., COSMIC)
    • Mir-based compositors (Note: You may need to enable the protocol with --add-wayland-extension zwlr_layer_shell_v1)
    • KDE Plasma on Wayland

    Not Supported:

    • Gnome-on-Wayland
    • Any X11 desktop
  4. Use Layer Shell Preload to add Layer Shell support to arbitrary Wayland apps

    main

    If you have a pre-built Wayland application that does not natively support the Layer Shell protocol, you can use liblayer-shell-preload.so to inject support without recompiling the binary. This is achieved by using the LD_PRELOAD environment variable to load the library into the application's process.

    Warning: This is an unofficial hack. There is no official support, and you should not report bugs to the application or toolkit developers if liblayer-shell-preload.so is being used.

    $ LD_PRELOAD=/usr/lib/liblayer-shell-preload.so LAYER_ANCHOR='lrb' LAYER_HEIGHT=50 LAYER_EXCLUSIVE=1 LAYER_KEYBOARD=on-demand weston-terminal
  5. Install build dependencies

    main

    Depending on your distribution, install the required packages to build the library.

    Ubuntu (18.04 and later):

    sudo apt install meson ninja-build libwayland-dev wayland-protocols libgtk-4-dev gobject-introspection libgirepository1.0-dev gtk-doc-tools python3 valac

    Arch Linux:

    pacman -S --needed meson ninja gtk4 wayland wayland-protocols gobject-introspection libgirepository gtk-doc python vala
    sudo apt install meson ninja-build libwayland-dev wayland-protocols libgtk-4-dev gobject-introspection libgirepository1.0-dev gtk-doc-tools python3 valac
  6. Use LD_PRELOAD to force GTK4 Layer Shell loading

    main

    If you cannot easily change your build system or script, you can force the correct linking order by using the LD_PRELOAD environment variable. This ensures libgtk4-layer-shell.so is loaded before any other libraries (like libwayland-client.so).

    Run your application as follows:

    LD_PRELOAD=/path/to/libgtk4-layer-shell.so my-app
    LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libgtk4-layer-shell.so my-app
  7. Use GTK4 Layer Shell in C/C++

    main

    The easiest way to build against the library is using the gtk-layer-shell-0 pkg-config package.

    Important Linking Rule: If you link against libwayland, you must link libwayland after gtk4-layer-shell.

    See examples/simple-example.c for a minimal complete application.

  8. Build GTK4 Layer Shell from source

    main

    To build the library from source, follow these steps:

    1. Clone the repository.
    2. Install build dependencies (see Build Dependencies).
    3. Configure the build with Meson:
      meson setup -Dexamples=true -Ddocs=true -Dtests=true build
      Note: You may need to use --prefix=/usr on Arch Linux.
    4. Compile the project:
      ninja -C build
    5. Install the project:
      sudo ninja -C build install
    6. Update the shared library cache:
      sudo ldconfig
    meson setup -Dexamples=true -Ddocs=true -Dtests=true build
    ninja -C build
    sudo ninja -C build install
    sudo ldconfig
  9. Fix GTK4 Layer Shell linking issues in Python

    main

    Because the GI (GObject Introspection) repository loads dependencies automatically, you must explicitly load libgtk4-layer-shell.so using ctypes at the very top of your main script, before any gi imports.

    Add this to the beginning of your script:

    from ctypes import CDLL
    CDLL('libgtk4-layer-shell.so')
    # 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')
  10. Fix GTK4 Layer Shell linking issues in C/C++

    main

    If your application is failing to use layer shell features, it is likely because libwayland-client.so is being loaded before libgtk4-layer-shell.so. The dynamic linker must load libgtk4-layer-shell.so first so that it can shim the necessary Wayland calls.

    To fix this in your build system:

    1. Ensure gtk4-layer-shell is explicitly linked.
    2. Ensure gtk4-layer-shell appears first in your list of dependencies (e.g., in Meson, place it at the beginning of the dependencies array for your executable).

    Debugging steps:

    • Inspect compiler commands: Run ninja -C build -v and verify gtk4-layer-shell is linked before libwayland-client (and ideally before GTK).
    • Check binary dependencies: Run ldd on your binary and verify gtk4-layer-shell appears before libwayland.
    • Trace library loading: Run your binary with LD_DEBUG=libs to ensure the correct loading order. You can grep the output for library discovery: LD_DEBUG=libs build/my-bin 2>&1 | grep 'find library='
    # Example Meson dependency order
    executable('my-app', 
      sources: 'main.cpp', 
      dependencies: [gtk4_layer_shell_dep, gtk4_dep, wayland_dep] # gtk4-layer-shell must be first
    )
  11. Configure Meson build options

    main

    When running meson setup, you can use the following options to customize the build:

    OptionDefaultDescription
    -DexamplesfalseBuild example C apps. If enabled, gtk4-layer-demo is installed.
    -DdocsfalseGenerate documentation.
    -DtestsfalseBuild the test suite.
    -Dsmoke-teststrueTest that all examples can run. Disable if you lack specific language dependencies.
    -DintrospectiontrueBuild GObject Introspection data (required for Python, Vala, etc.).
    -DvapitrueBuild VAPI data and Vala examples. Requires -Dintrospection=true.