Waybar

repository·master·Indexed 12 days ago

https://github.com/alexays/waybar

A highly customizable Wayland bar designed for Sway and other wlroots-based compositors. It provides modules for monitoring hardware, connectivity, audio, and desktop status, and supports custom widget creation via a C FFI module.

Tokens
3.1K
Snippets
9
Records
18
Agent score
95%

What's inside Waybar

  1. Create custom widgets with the C FFI module

    master

    The C FFI module allows you to create advanced custom Waybar widgets by providing a dynamic library that exposes standard C functions and constants. Waybar loads and executes these libraries at runtime.

    You can implement these modules in any language that provides C-compatible interfaces and GTK bindings (such as C, C++, Rust, Go, or Python). The specific symbols, functions, and constants required for implementation are defined in waybar_cffi_module.h.

  2. Quickstart: Run Waybar from source

    master

    To quickly test Waybar without installing it to your system, clone the repository, build it using Meson and Ninja, and execute the binary directly from the build directory.

    Note: Waybar launches with a sensible default configuration located at resources/config.jsonc. To customize your setup, copy the default config and stylesheet into ~/.config/waybar/ and edit them there.

    git clone https://github.com/Alexays/Waybar
    cd Waybar
    meson setup build
    ninja -C build
    ./build/waybar          # run without installing
  3. Install Waybar via package managers

    master
    Waybar is available in most major Linux distributions. Check your distribution's package manager for availability. For Ubuntu users, a PPA with more recent versions is available via Launchpad.
  4. Load a C FFI module in Waybar configuration

    master

    To use a C FFI module, add it to your Waybar configuration JSON. You must include the module name in a position array (like modules-left, modules-center, or modules-right) and define a configuration object for it containing the module_path key, which points to the compiled dynamic library file (e.g., a .so file).

    {
    	// ...
    	"modules-center": [
    		// ...
    		"cffi/c_example"
    	],
    	// ...
    	"cffi/c_example": {
    		// Path to the compiled dynamic library file
    		"module_path": "resources/custom_modules/cffi_example/build/wb_cffi_example.so"
    	}
    }
  5. Build and install Waybar from source

    master

    To build Waybar from the source code, use the Meson build system. You can optionally install the resulting binaries to your system using ninja install.

    git clone https://github.com/Alexays/Waybar
    cd Waybar
    meson setup build
    ninja -C build
    ninja -C build install   # optional
  6. Install build dependencies for Waybar

    master

    Before building from source, you must install the required build dependencies. Use the command appropriate for your distribution.

    # Arch Linux
    pacman -S --asdeps \
      gtkmm3 jsoncpp libsigc++ fmt wayland chrono-date spdlog gtk3 \
      gobject-introspection libgirepository libpulse libnl libappindicator-gtk3 \
      libdbusmenu-gtk3 libmpdclient sndio libevdev libxkbcommon upower meson \
      cmake scdoc wayland-protocols glib2-devel
  7. Control Waybar via Signals

    master

    Waybar responds to specific POSIX signals to change its behavior. You can control the visibility of the bar or trigger a reload using SIGUSR1 and SIGUSR2.

    Supported signal actions depend on the bar's configuration:

    • SIGUSR1 and SIGUSR2: Can be configured to HIDE, SHOW, TOGGLE, or RELOAD the bar.
    • SIGINT: Triggers a quit/shutdown of the Waybar process.
    • SIGCHLD: Used internally for reaping child processes.
    • Real-time signals (SIGRTMIN + 1 through SIGRTMAX): These are passed directly to the bar's internal signal handler via bar->handleSignal(signum).
  8. Logging to systemd journal

    master
    If Waybar is running as a systemd service, it automatically attempts to upgrade its logging from stderr to the native systemd journal protocol. It detects this by checking the JOURNAL_STREAM environment variable and verifying that the device and inode of stderr match the values provided. If successful, spdlog is configured to use the systemd_logger_st.
  9. Implement a custom CFFI module for Waybar

    master

    To create a custom module using the Waybar CFFI (C Foreign Function Interface) API, you must implement a set of specific exported functions and define a version constant. This allows Waybar to initialize, manage the lifecycle, and interact with your custom C code.

    Required Exports

    1. wbcffi_version: A const size_t that must be defined to specify the API version compatibility. In this example, it is set to 2.
    2. wbcffi_init: The initialization function called by Waybar. It receives:
      • init_info: A pointer to a wbcffi_init_info struct containing the Waybar module object and a function pointer get_root_widget to retrieve the GTK container where your module should be rendered.
      • config_entries: An array of wbcffi_config_entry containing key-value pairs from your Waybar configuration.
      • config_entries_len: The number of configuration entries.
      • Return Value: A void* pointer to your module's private instance data (which you must allocate, e.g., via malloc).
    3. wbcffi_deinit: The cleanup function called when the module is removed. Use this to free any memory or resources allocated during wbcffi_init.
    4. wbcffi_update: Called when Waybar requests an update of the module's state.
    5. wbcffi_refresh: Called when the module receives a refresh signal (identified by an integer signal).
    6. wbcffi_doaction: Called when a specific action is triggered, passing the action name as a string.

    Implementation Workflow

    1. Include waybar_cffi_module.h.
    2. Define a private struct to hold your module's state (e.g., pointers to GTK widgets and the Waybar module object).
    3. In wbcffi_init, use init_info->get_root_widget(init_info->obj) to get the parent GTK container.
    4. Create and add your GTK widgets to that container.
    5. Return your allocated state struct.
    #include "waybar_cffi_module.h"
    
    // 1. Define version
    const size_t wbcffi_version = 2;
    
    // 2. Define private state
    typedef struct {
      wbcffi_module* waybar_module;
      GtkBox* container;
      GtkButton* button;
    } ExampleMod;
    
    // 3. Implement lifecycle functions
    void* wbcffi_init(const wbcffi_init_info* init_info, const wbcffi_config_entry* config_entries, size_t config_entries_len) {
      ExampleMod* inst = malloc(sizeof(ExampleMod));
      inst->waybar_module = init_info->obj;
      
      GtkContainer* root = init_info->get_root_widget(init_info->obj);
      // ... setup GTK widgets ...
      
      return inst;
    }
    
    void wbcffi_deinit(void* instance) {
      free(instance);
    }
    
    void wbcffi_update(void* instance) { /* handle update */ }
    
    void wbcffi_refresh(void* instance, int signal) { /* handle refresh */ }
    
    void wbcffi_doaction(void* instance, const char* name) { /* handle action */ }
  10. Install runtime dependencies for Waybar

    master

    Certain Waybar modules require specific libraries to function. Ensure these are installed on your system.

    LibraryModule
    libpulsePulseAudio module
    libnlNetwork module
    libappindicator-gtk3Tray module
    libdbusmenu-gtk3Tray module
    libmpdclientMPD module
    libsndiosndio module
    libevdevKeyboardState module
  11. Use the Client class to run Waybar

    master

    The waybar::Client class is the primary entry point for managing the Waybar application lifecycle. It handles the Wayland display connection, GTK application initialization, and the management of multiple bar instances across different outputs.

    To run Waybar within a custom application, use the inst() singleton method to get the client instance and then call main(argc, argv).

    #include <waybar/client.hpp>
    
    int main(int argc, char* argv[]) {
        waybar::Client* client = waybar::Client::inst();
        return client->main(argc, argv);
    }