Skip to content
Waxed Display Server
← Back to Docs

IPC Protocol

Waxed IPC Protocol

Overview

The Waxed IPC (Inter-Process Communication) protocol enables external control of the compositor through two complementary interfaces:

  1. Binary Protocol - A structured, wire-format protocol for programmatic access
  2. Text Protocol - A human-readable command syntax for waxedctl CLI 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.

FieldTypeSize
magicuint32_t4 bytes
versionuint32_t4 bytes
typeCommandType4 bytes
payload_sizeuint32_t4 bytes
payloadchar[]0 to 4096 bytes

Total (with payload): 16 to 4112 bytes

CommandHeader Layout (16 bytes)

OffsetFieldTypeDescription
0magicuint32_tMust be 0x57415844 (“WAXD”)
4versionuint32_tProtocol version (currently 1)
8typeCommandTypeCommand type enum value
12payload_sizeuint32_tBytes in payload (0-4096)

CommandType Enum

ValueEnum NameDescription
1PropertySetSet a property value
2PropertyGetQuery a property value
3PropertyListList all properties
10PluginLoadLoad a plugin by name
11PluginUnloadUnload a plugin by name
12PluginShowMake a plugin visible
13PluginListList all loaded plugins
100HelpRequest help text
101QuitRequest compositor shutdown

Response Packet Structure

All responses begin with a fixed-size ResponseHeader followed by an optional payload.

FieldTypeSize
magicuint32_t4 bytes
versionuint32_t4 bytes
statusResponseStatus4 bytes
payload_sizeuint32_t4 bytes
payloadchar[]0 to 8192 bytes

Total (with payload): 16 to 8208 bytes

ResponseHeader Layout (16 bytes)

OffsetFieldTypeDescription
0magicuint32_tMust be 0x57415844 (“WAXD”)
4versionuint32_tProtocol version (currently 1)
8statusResponseStatusResponse status enum value
12payload_sizeuint32_tBytes in payload (0-8192)

ResponseStatus Enum

ValueEnum NameDescription
0SuccessCommand completed successfully
1ErrorGeneric error occurred
2NotFoundRequested resource not found
3InvalidCommandCommand format invalid or unknown
4PermissionDeniedOperation not permitted

Text Protocol (waxedctl)

The text protocol provides a human-readable command syntax for interactive use via waxedctl.

TextCommandType Enum

ValueEnum NameDescription
0PropertySetSet a property on a plugin
1PluginUnloadUnload a plugin by name
2PluginLoadLoad a plugin by name
3PluginShowMake a plugin visible
4PluginListList all available plugins
5HelpShow help text
6StatusQuery compositor status
7ApiListList all registered API calls
8ApiCallExecute an API call
255UnknownUnknown/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.

OffsetBytesValueDescription
+0057 41 58 440x57415844magic (“WAXD”)
+0400 00 00 011version
+0800 00 00 0A10type (PluginLoad)
+0C00 00 00 0C12payload_size
+106C 6F 67 69”logi”payload start
+1473 63 72 65”scre”payload continued
+1800nullnull terminator

Example 2: PropertySet Command

Set property “background” to “/path/image.jpg” on plugin “loginscreen”.

OffsetBytesValueDescription
+0057 41 58 440x57415844magic (“WAXD”)
+0400 00 00 011version
+0800 00 00 011type (PropertySet)
+0C00 00 00 1F31payload_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

Waxed CompositorClientWaxed CompositorClient3. Parse and execute command1. Connect to Unix domain socket2. Send Command (binary or text)4. Response (binary or text)5. Close socket or send next command

Binary Packet Structure

Response Packet

ResponseHeader (16 bytes - fixed)

magic: 0x57415844 ('WAXD')

version: 1

status: ResponseStatus enum

payload_size: 0-8192 bytes

Payload (variable: 0-8192 bytes)

UTF-8 string data

May contain JSON for structured responses

Command Packet

CommandHeader (16 bytes - fixed)

magic: 0x57415844 ('WAXD')

version: 1

type: CommandType enum

payload_size: 0-4096 bytes

Payload (variable: 0-4096 bytes)

UTF-8 string data

Null-terminated for string commands

Text Command Parsing Flow

Yes

No

Text Command Parser

Trim whitespace

Simple commands? help, status, list

Return TextCommand

Split by spaces

Parse first part - key:value syntax

Determine command type

Plugin Command

Property Specifier

API Call

Unknown Command


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 PluginLoad and Quit should 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;