Universal Wayland Session Manager

repository·master·Indexed 22 days ago

https://github.com/vladimir-csp/uwsm

A tool for managing Wayland compositor sessions, featuring systemd environment synchronization, XDG autostart handling, and structured compositor launching with plugin-extendable tweaks. It provides a CLI for starting and stopping sessions, launching applications as systemd scopes or services via the 'app' subcommand, and managing session states through 'check' and 'aux' utilities.

Tokens
7.3K
Snippets
22
Records
33
Agent score
28%

What's inside uwsm

  1. How UWSM manages compositor identity and globals

    master

    UWSM uses a global state object CompGlobals to store information about the session being managed. This information is populated during the start or aux modes via fill_comp_globals().

    Key Global Fields:

    • id: The unique identifier for the compositor (e.g., the basename of the command).
    • cmdline: The full command line used to launch the compositor.
    • bin_id: A sanitized, lowercase version of the binary name used for systemd unit naming.
    • desktop_names: A deduplicated list of desktop environment names (e.g., sway, hyprland).
    • name / description: Human-readable names and comments derived from Desktop Entries or CLI flags.
    • cli_args: The original arguments passed to the CLI (excluding the command itself).
  2. How Desktop Entry argument replacement works

    master

    When launching an application via a .desktop file, uwsm performs iterative argument replacement to ensure the command line matches the intended Desktop Entry specification.

    Supported Field Codes:

    • %f: Replaces with the first provided file path.
    • %u: Replaces with the first provided path, converted to a URL via path2url.
    • %F: Replaces with the full list of provided file paths.
    • %U: Replaces with the full list of provided paths, each converted to a URL.
    • %c: Replaces with the localized name of the entry.
    • %k: Replaces with the filename of the entry.
    • %i: If an Icon key exists in the entry, it appends --icon <icon_name> to the command.

    Iterative Replacement Logic: If a field code like %f or %u is used and multiple arguments are provided, uwsm generates multiple command lines (one for each argument) to allow for iterative execution of the application for each file/URL provided.

  3. Configure 'autoready' behavior via environment variables

    master

    When using the aux exec command, UWSM uses an 'autoready' mechanism to synchronize environment variables with systemd. You can control this via:

    • UWSM_WAIT_VARNAMES: A space-separated list of environment variables to wait for (in addition to WAYLAND_DISPLAY).
    • UWSM_WAIT_VARNAMES_SETTLETIME: A float value representing the delay (in seconds) to wait after variables are detected before proceeding. Defaults to 0.2 if invalid or unset.
  4. Stop the running compositor

    master

    Use stop_wm() to stop the currently active compositor. It queries the system D-Bus for active or activating wayland-wm@*.service units. If a unit is found, it sends a stop job to systemd and waits for the job to complete.

    Returns:

    • True if a compositor was stopped.
    • False if no compositor was running.
    stop_wm()
  5. Run UWSM in 'app' mode to launch applications

    master

    Use the app mode to launch applications within a managed UWSM environment. This ensures the application is correctly placed in a systemd slice and inherits the necessary session environment. You can specify the command line, terminal requirements, slice names, and unit properties.

    # Example conceptual invocation via CLI
    uwsm app --cmdline "my-app" --slice-name "my-slice" --app-name "my-app"
  6. Find the default terminal emulator with find_terminal_entry()

    master

    The find_terminal_entry() function searches for an appropriate terminal emulator based on XDG standards and local configurations.

    It follows this priority:

    1. Explicit Lists: Checks configuration files (e.g., xdg-terminals.list or {desktop}-xdg-terminals.list) in XDG config and data directories. It supports:
      • +entry.desktop: Explicitly include.
      • -entry.desktop: Explicitly exclude.
      • entry.desktop: Standard entry.
      • /execarg_default:entry.desktop:arg: Sets a default execution argument for a specific entry.
    2. Application Search: If no explicit list matches, it searches all installed applications for entries that qualify as terminals.
    3. Negative Cache: Uses a cache (not-terminals) to remember applications that have been identified as not being terminals to speed up future searches.

    Returns a tuple of (terminal_entry_object, entry_id, entry_action) or (None, None, None) if no terminal is found.

    entry, entry_id, entry_action = find_terminal_entry()
  7. Finalize the session environment

    master
    The finalize mode is used to finalize the environment variables for the session. It accepts a list of variable names to include, which can be passed via CLI or via the UWSM_FINALIZE_VARNAMES environment variable.
  8. Manage Desktop Entry parsing and validation

    master

    The MainArg class and associated functions provide tools to parse and validate XDG Desktop Entry strings. This includes handling .desktop files, extracting specific actions (e.g., entry.desktop:action), and resolving paths.

    Key capabilities:

    • Parsing: Distinguishes between a raw executable path and a Desktop Entry ID or file path.
    • Validation: check_entry_basic validates the entry against the XDG spec, checking for required keys like Exec, handling TryExec, and verifying the existence of the target executable.
    • Action Extraction: entry_action_keys allows retrieving specific action groups (like Desktop Action <name>) from a .desktop file, including expanded and tokenized Exec strings.
    • Visibility: check_entry_showin enforces OnlyShowIn and NotShowIn rules based on the XDG_CURRENT_DESKTOP environment variable.
    from uwsm.main import MainArg, check_entry_basic
    
    # Example: Parsing a desktop entry with an action
    arg = MainArg("my-app.desktop:open")
    print(arg.entry_id)      # "my-app.desktop"
    print(arg.entry_action)  # "open"
    
    # Example: Validating an entry
    # (Assumes 'entry' is a pyxdg DesktopEntry object)
    check_entry_basic(entry, entry_action="open")
  9. Wait for a systemd unit to reach a specific state

    master

    The wait_for_unit function blocks execution until a specified systemd unit reaches one of the target states.

    • Parameters:
      • unit: The name of the systemd unit.
      • bus: A DbusInteractions instance.
      • timeout: Seconds to wait (0 for no wait).
      • states: A list of target states. Supported values: active, activating, inactive, deactivating.
    • Returns: True if the unit reaches the desired state within the timeout, False otherwise.
    from uwsm.main import wait_for_unit, DbusInteractions
    
    bus = DbusInteractions("session")
    success = wait_for_unit("sway.service", bus, timeout=10, states=["active"])
    if success:
        print("Unit is active!")
  10. Manage environment variables with `save_env` and `load_env`

    master

    These functions provide a mechanism to persist and restore environment variables using runtime files in the uwsm runtime directory.

    save_env(filename, env=None, separator="\0")

    Saves a dictionary of environment variables to a file.

    • filename: The name of the file to create within the uwsm runtime directory.
    • env: The dictionary of variables to save. If None, the current os.environ is used. Variables are filtered via filter_varnames.
    • separator: The delimiter used between key=value pairs. Defaults to a null byte (\0). Using \n is recommended for systemd EnvironmentFile= usage.

    load_env(filename, delete=False)

    Reads environment variables from a runtime file.

    • filename: The name of the file to read.
    • delete: If True, the file is removed after reading.
    • Returns: A dictionary of the loaded variables.
    # Example: Saving environment for systemd EnvironmentFile
    save_env("env_session.conf", env=os.environ, separator="\n")
    
    # Example: Loading environment
    env = load_env("env_session.conf", delete=True)
  11. Escape strings for systemd unit specifiers

    master

    When creating systemd units or identifiers, strings must be escaped according to systemd rules. The simple_systemd_escape function handles this.

    • Behavior: Replaces / with - and uses C-style hex escapes (\xXX) for special characters.
    • start parameter: If True, it handles leading dots by escaping them.
    from uwsm.main import simple_systemd_escape
    
    escaped = simple_systemd_escape("my/path/to.file")
    # Result will have '/' replaced by '-' and other chars escaped