IPC Protocol
Waxed IPC Protocol
Overview
The Waxed IPC (Inter-Process Communication) protocol enables external control of the compositor through two complementary interfaces:
- Binary Protocol - A structured, wire-format protocol for programmatic access
- Text Protocol - A human-readable command syntax for
waxedctlCLI tool
Both protocols operate over a Unix domain socket, allowing external processes to:
- Load/unload plugins
- Query and modify plugin properties
- Execute API calls
- Query compositor status
Binary Protocol
Protocol Constants
PROTOCOL_MAGIC = 0x57415844 # "WAXD" in ASCII
PROTOCOL_VERSION = 1
MAX_PAYLOAD_SIZE = 4096 # Maximum command payload
MAX_RESPONSE_SIZE = 8192 # Maximum response payload
Command Packet Structure
All commands begin with a fixed-size CommandHeader followed by an optional payload.
| Field | Type | Size |
|---|---|---|
| magic | uint32_t | 4 bytes |
| version | uint32_t | 4 bytes |
| type | CommandType | 4 bytes |
| payload_size | uint32_t | 4 bytes |
| payload | char[] | 0 to 4096 bytes |
Total (with payload): 16 to 4112 bytes
CommandHeader Layout (16 bytes)
| Offset | Field | Type | Description |
|---|---|---|---|
| 0 | magic | uint32_t | Must be 0x57415844 (“WAXD”) |
| 4 | version | uint32_t | Protocol version (currently 1) |
| 8 | type | CommandType | Command type enum value |
| 12 | payload_size | uint32_t | Bytes in payload (0-4096) |
CommandType Enum
| Value | Enum Name | Description |
|---|---|---|
| 1 | PropertySet | Set a property value |
| 2 | PropertyGet | Query a property value |
| 3 | PropertyList | List all properties |
| 10 | PluginLoad | Load a plugin by name |
| 11 | PluginUnload | Unload a plugin by name |
| 12 | PluginShow | Make a plugin visible |
| 13 | PluginList | List all loaded plugins |
| 100 | Help | Request help text |
| 101 | Quit | Request compositor shutdown |
Response Packet Structure
All responses begin with a fixed-size ResponseHeader followed by an optional payload.
| Field | Type | Size |
|---|---|---|
| magic | uint32_t | 4 bytes |
| version | uint32_t | 4 bytes |
| status | ResponseStatus | 4 bytes |
| payload_size | uint32_t | 4 bytes |
| payload | char[] | 0 to 8192 bytes |
Total (with payload): 16 to 8208 bytes
ResponseHeader Layout (16 bytes)
| Offset | Field | Type | Description |
|---|---|---|---|
| 0 | magic | uint32_t | Must be 0x57415844 (“WAXD”) |
| 4 | version | uint32_t | Protocol version (currently 1) |
| 8 | status | ResponseStatus | Response status enum value |
| 12 | payload_size | uint32_t | Bytes in payload (0-8192) |
ResponseStatus Enum
| Value | Enum Name | Description |
|---|---|---|
| 0 | Success | Command completed successfully |
| 1 | Error | Generic error occurred |
| 2 | NotFound | Requested resource not found |
| 3 | InvalidCommand | Command format invalid or unknown |
| 4 | PermissionDenied | Operation not permitted |
Text Protocol (waxedctl)
The text protocol provides a human-readable command syntax for interactive use via waxedctl.
TextCommandType Enum
| Value | Enum Name | Description |
|---|---|---|
| 0 | PropertySet | Set a property on a plugin |
| 1 | PluginUnload | Unload a plugin by name |
| 2 | PluginLoad | Load a plugin by name |
| 3 | PluginShow | Make a plugin visible |
| 4 | PluginList | List all available plugins |
| 5 | Help | Show help text |
| 6 | Status | Query compositor status |
| 7 | ApiList | List all registered API calls |
| 8 | ApiCall | Execute an API call |
| 255 | Unknown | Unknown/invalid command |
Command Syntax
Simple Commands
help # Show help text
status # Query compositor status
list # List all plugins
api list # List all registered API calls
Plugin Commands
plugin:<name> load # Load a plugin
plugin:<name> unload # Unload a plugin
plugin:<name> show # Make a plugin visible
Property Commands
# Set property on specific plugin
plugin:<name> <ns>:<key>:<value>
# Set property on active plugin
<ns>:<key>:<value>
Property namespaces: yaml, json, config, property
API Commands
api <api_name> [args...] # Execute API call on visible plugin
TextCommand Structure
struct TextCommand {
TextCommandType type; // Command type
std::string plugin_name; // Target plugin name
std::string property_namespace; // Property namespace (e.g., "yaml")
std::string property_key; // Property key (e.g., "background")
std::string property_value; // Property value
std::string api_name; // API name for ApiCall
std::vector<std::string> api_args; // Arguments for ApiCall
};
TextResponse Structure
struct TextResponse {
ResponseStatus status; // Response status code
std::string message; // Human-readable message
std::string data; // Optional data payload (JSON, etc.)
};
Command Examples
Binary Protocol Examples
Example 1: PluginLoad Command
Load plugin “loginscreen” with no payload.
| Offset | Bytes | Value | Description |
|---|---|---|---|
| +00 | 57 41 58 44 | 0x57415844 | magic (“WAXD”) |
| +04 | 00 00 00 01 | 1 | version |
| +08 | 00 00 00 0A | 10 | type (PluginLoad) |
| +0C | 00 00 00 0C | 12 | payload_size |
| +10 | 6C 6F 67 69 | ”logi” | payload start |
| +14 | 73 63 72 65 | ”scre” | payload continued |
| +18 | 00 | null | null terminator |
Example 2: PropertySet Command
Set property “background” to “/path/image.jpg” on plugin “loginscreen”.
| Offset | Bytes | Value | Description |
|---|---|---|---|
| +00 | 57 41 58 44 | 0x57415844 | magic (“WAXD”) |
| +04 | 00 00 00 01 | 1 | version |
| +08 | 00 00 00 01 | 1 | type (PropertySet) |
| +0C | 00 00 00 1F | 31 | payload_size |
| +10 | (string data) | “loginscreen\0background\0/path/image.jpg\0” | payload |
Text Protocol Examples
# Load the loginscreen plugin
plugin:loginscreen load
# Set a property on loginscreen
plugin:loginscreen yaml:background:/path/to/image.jpg
# Unload the plugin
plugin:loginscreen unload
# Set property on active plugin
yaml:background:/path/to/image.jpg
# Execute API call
api surface 10 20 100 200 0x34325258
# Query status
status
Protocol Flow Diagrams
Command/Response Flow
Binary Packet Structure
Text Command Parsing Flow
Versioning
The protocol version is stored in both command and response headers. The current version is 1.
Backward compatibility is not maintained between protocol versions. All implementations must use matching protocol versions.
Security Considerations
- IPC socket should have restricted permissions (owner read/write only)
- Commands like
PluginLoadandQuitshould validate caller permissions - Property values should be sanitized before application
- API calls via text protocol are forwarded to the visible/drawing plugin
API Reference
C++ Header
#include <waxed/ipc/protocol.h>
Key Functions
// Parse a text command string
auto parse_text_command(std::string_view command_string) -> Result<TextCommand>;
// Generate help text
auto generate_help_text() -> std::string;
// Create a text response
auto create_text_response(ResponseStatus status, std::string message) -> TextResponse;
// Convert enum to string
auto to_string(TextCommandType type) -> std::string_view;
Struct Methods
// Get command payload as string
auto Command::get_payload() const -> std::string;
// Set response payload from string
auto Response::set_payload(const std::string& data) -> void;
// Get response payload as string
auto Response::get_payload() const -> std::string;