How the Hyprland IPC Socket System Works for Inter‑Process Communication
Hyprland implements a lightweight, UNIX‑domain‑socket based IPC (inter‑process communication) layer that lets external programs query the compositor’s state and issue commands through a non‑blocking event loop integrated with the Wayland event system.
The Hyprland IPC socket system provides the foundation for scriptable window management in the hyprwm/Hyprland repository. This architecture enables real‑time communication between the compositor and external tools without relying on D‑Bus or complex protocols, allowing any component to emit events via the global g_pEventManager instance.
Core Architecture Components
The IPC implementation centers on three primary abstractions defined in src/managers/EventManager.hpp and implemented in src/managers/EventManager.cpp.
CEventManager and Socket Initialization
The CEventManager class acts as the IPC server. During instantiation, it creates a UNIX‑domain socket at ${XDG_RUNTIME_DIR}/hypr/.hyprsunset.sock (falling back to $HOME/.local/share/hypr/ if XDG_RUNTIME_DIR is unset) and registers it with the compositor’s Wayland event loop. It manages two critical callbacks: onServerEvent for incoming connections and onClientEvent for write‑ready or disconnected clients.
SHyprIPCEvent Structure
Events are encapsulated in the SHyprIPCEvent struct, which holds an event name string and an associated data payload. This simple event=data format allows easy parsing in any programming language.
Global Event Manager Instance
The g_pEventManager global pointer exposes the event system throughout the codebase. Any Hyprland component can emit an IPC event by constructing an SHyprIPCEvent and calling g_pEventManager->postEvent(event), which triggers the distribution pipeline.
Event Flow and Communication Lifecycle
The IPC system follows a five‑stage pipeline that ensures ordered, non‑blocking delivery:
-
Server startup –
CEventManagercreates the socket file and registersonServerEventandonClientEventcallbacks with the main loop. -
Client connection – When a client (such as
hyprctlor a custom script) connects,CEventManageradds a newSCliententry to them_clientsvector, storing the file descriptor and an event‑queue vector. -
Event emission – Compositor components build an
SHyprIPCEvent(e.g.,{"workspace","1"}) and invokepostEvent. This method callsformatEvent(event)to produce a"event data\n"string and pushes it onto every client’seventsqueue. -
Flushing – The main loop invokes
onClientEventfor each ready client. TheflushClientmethod writes queued strings to the socket, handling partial writes viawriteOffset. If a client closes or encounters an error, it is removed fromm_clients. -
Client read – Clients read lines delimited by
\n, parsing the first token as the event name and the remainder as payload. The reference implementation inhyprctl/src/main.cppdemonstrates parsing these responses for display or command execution.
Socket Path and Runtime Configuration
The socket file location follows XDG Base Directory specifications:
- Primary path:
${XDG_RUNTIME_DIR}/hypr/.hyprsunset.sock - Fallback path:
$HOME/.local/share/hypr/.hyprsunset.sock
Because the socket is non‑blocking and integrated into the Wayland event loop, IPC traffic never stalls the compositor, and the SClient abstraction guarantees each listener receives a consistent, ordered stream of events.
Practical IPC Usage Examples
Querying State with hyprctl
The hyprctl utility in hyprctl/src/main.cpp serves as the official command‑line client:
# Query the active workspace
hyprctl workspaces
# Listen for live events with JSON output
hyprctl monitors -j
Bash Scripts Using socat
For custom automation, you can write directly to the socket using socat:
#!/usr/bin/env bash
SOCKET="${XDG_RUNTIME_DIR:-$HOME/.local/share}/hypr/.hyprsunset.sock"
# Send a dispatch command to open a terminal
printf "dispatch exec,alacritty\n" | socat - UNIX-CONNECT:"$SOCKET"
Custom C++ Client
A minimal C++ implementation demonstrates direct socket communication:
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
int main() {
const char *runtimeDir = getenv("XDG_RUNTIME_DIR");
std::string socketPath = runtimeDir
? std::string(runtimeDir) + "/hypr/.hyprsunset.sock"
: std::string(getenv("HOME")) + "/.local/share/hypr/.hyprsunset.sock";
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
sockaddr_un addr{};
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
if (connect(fd, (sockaddr*)&addr, sizeof(addr)) == -Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →