Shortcuts and Events
Subscribe to compositor events and manage client-owned shortcut bindings.
Event and shortcut operations are available at the minimum API versions stated below; connection-owned bindings end when their connection closes.
API version 1.9: event subscriptions
Send a request with op: "events" and an events array to subscribe this connection to selected native events. Event names must appear in hello.events.
Use the existing subscription operations for the windows and monitors snapshot names. The greeting lists generic-event-subscriptions and input-gesture-events in hello.capabilities.
The list may contain up to 64 unique event names. A valid request replaces the connection's previous event list. Send an empty list to unsubscribe from these events. Invalid lists leave the previous subscription in place.
{
"op": "events",
"api_version": { "major": 1, "minor": 9 },
"events": ["gnoblin.input.gesture", "gnoblin.window.focused"]
}The server acknowledges a valid request with event: "subscribed" and the accepted event names. Requests without API version 1.9 receive an error. Subscriptions last until replaced or the connection closes.
The stable gnoblin.input.gesture event comes from Mutter's mutter.touchpad.gesture source. gesture is swipe, pinch, or hold; phase is begin, update, end, or cancel. Every event has fingers, sequence, time, and Mutter's original input_time.
Swipe updates include dx and dy. Pinch updates include scale and angle_delta.
input_time is Mutter's original timestamp. Socket sequence values increase across native events and may have gaps when a connection filters other events. time is monotonic-clock microseconds. Device names and private focus contexts are not sent.
API version 1.10: shortcut focus grants
Subscribe to gnoblin.shortcut.activated with an API 1.10 event request. The event is sent only to subscribed connections and includes the configured command shortcut name, trigger: "press", and a connection-specific focus_context token. Built-in action shortcuts are not included.
The token expires five seconds after the key press and is bound to the connection that received it. It can authorize one focus request or, with API 1.12, one interactive move or resize request.
{ "op": "events", "api_version": { "major": 1, "minor": 10 }, "events": ["gnoblin.shortcut.activated"] }Use the received token with window.focus when the user selects a listed window:
{
"op": "api",
"id": "focus",
"api_version": { "major": 1, "minor": 10 },
"method": "window.focus",
"arguments": { "id": "42", "focus_context": "TOKEN_FROM_SHORTCUT_EVENT" }
}window.focus accepts exactly the string fields id and focus_context. Every attempt with a valid connection token consumes it, including requests with an invalid window ID or unknown argument. API 1.12 also accepts this token for one interactive move or resize operation. The request fails if the token expired, was already used, belongs to another connection, or was revoked.
Config reloads, session locks, subscription changes, and disconnects revoke socket tokens. Native Lua Window:focus(context) uses its protected Lua context instead of a socket token.
Any compositor-socket client can focus a listed window with an XDG Activation token. The client must create the token after user input on one of its Wayland surfaces, and the socket connection must belong to that same process.
Mutter verifies the input serial and source surface; Gnoblin consumes the token once. Requests fail while the session is locked. Lua callbacks do not receive raw activation tokens or input serials.
API version 1.11: dynamic shortcut bindings
Register a binding
Use shortcut.bind to register a connection-owned global accelerator. The arguments object accepts only id and accelerator.
- IDs contain 1 to 64 letters, digits, underscores, or hyphens.
- Accelerators use Mutter's GTK accelerator syntax and are limited to 128 bytes.
- Mutter rejects invalid accelerators and bindings already claimed by another owner.
- Bare
Superis the overlay key and is not accepted by this method. - Bindings activate on key press and ignore autorepeat.
- Each connection can register up to 32 bindings. The compositor accepts 128 dynamic bindings in total.
{
"op": "api",
"id": "bind-search",
"api_version": { "major": 1, "minor": 11 },
"method": "shortcut.bind",
"arguments": { "id": "search", "accelerator": "<Super>space" }
}Use shortcut.unbind with the same ID to release a binding. A client can remove only its own IDs. Disconnecting the client releases all its bindings.
To keep a binding registered after its held session ends, use shortcut.session.end with the binding ID and active session ID. This works only for a session owned by the current connection. The ended event reports reason cancelled.
Send the session_id from gnoblin.shortcut.session.activated:
{
"op": "api",
"id": "end-switcher-session",
"api_version": { "major": 1, "minor": 64 },
"method": "shortcut.session.end",
"arguments": { "id": "switcher", "session_id": 42 }
}Receive activations
Subscribe to gnoblin.shortcut.binding-activated with API 1.11 to receive activations for bindings owned by that connection. Each event includes the ID, accelerator, trigger: "press", and Mutter's input timestamp. It also includes a monotonic timestamp and a connection-specific focus token. The token can authorize one window.focus, window.begin_move, or window.begin_resize request and expires after five seconds.
{ "op": "events", "api_version": { "major": 1, "minor": 11 }, "events": ["gnoblin.shortcut.binding-activated"] }API 1.11 adds gnoblin.operation.completed, which carries an operation ID and either a success value or a structured error. The legacy event remains for older clients. Subscribe with op: "events"; clients tracking input-source or shortcut-capture APIs also receive completion notifications. Match them by operation ID.
Dynamic bindings are connection-owned and disappear when the client disconnects. The API 1.11 binding activates on press. API 1.22 adds held and modal shortcut sessions, described below. It does not buffer typing for later delivery to a popup.
API version 1.12: interactive window grabs
API 1.12 adds window.begin_move and window.begin_resize. Both require a connection-bound focus_context token from a trusted shortcut activation and consume it on every attempt, including invalid arguments. API 1.68 modal key events also provide these tokens.
Use window.begin_move to start Mutter's keyboard move grab for a listed window:
{
"op": "api",
"id": "move",
"api_version": { "major": 1, "minor": 12 },
"method": "window.begin_move",
"arguments": { "id": "42", "focus_context": "TOKEN_FROM_SHORTCUT_EVENT" }
}Use window.begin_resize with one of north, south, east, west, north_east, north_west, south_east, or south_west:
{
"op": "api",
"id": "resize",
"api_version": { "major": 1, "minor": 12 },
"method": "window.begin_resize",
"arguments": { "id": "42", "edge": "south_east", "focus_context": "TOKEN_FROM_SHORTCUT_EVENT" }
}The greeting advertises window-interactive-grabs when these methods are available. Mutter starts the keyboard grab with the trusted shortcut timestamp and current pointer sprite. Calls fail if the token is expired, already used, revoked, or belongs to another connection; if the session is locked; or if the window cannot be moved or resized.
API version 1.22: held and modal shortcut sessions
API 1.22 extends shortcut.bind with four optional fields:
triggerispress(the default) orrelease.holdisnone(the default),super,control, oralt. A held binding emits a shortcut-session activation and remains active until the held modifier is released.modeispassive(the default) ormodal. Modal mode requires a non-noneholdvalue and captures keyboard input while the held modifier remains down.capture_inputis a boolean, defaulting tofalse. It is supported only for an explicitaccelerator: "Super"binding. Bare Super must usetrigger: "release"andhold: "none".
Subscribe to these API 1.22 events to track a held binding:
gnoblin.shortcut.session.activatedstarts or repeats the session.gnoblin.shortcut.session.keycarrieskeyval,keycode,modifiers,phase, andtime. The phase ispressorrelease.gnoblin.shortcut.session.endedreports why the session stopped.
Client-owned shortcuts and controls
Use shortcut.bind and shortcut.unbind to register a connection-owned accelerator. The native bridge reports activation through gnoblin.shortcut.binding-activated. It does not provide modal grabs, held modifier sessions, a switcher fallback, or buffered typing. See API version 1.11 for the request shape.
Window, workspace, input, permission, portal-grant, privacy, animation, and launch methods are listed in the API-version tables above. They use op: "api" with a version, request ID, method name, and arguments object.
API version 1.71: layer lifecycle events
Request API 1.71 or newer to subscribe. The hello message advertises the event names and the layer-lifecycle-events capability.
{
"op": "events",
"api_version": { "major": 1, "minor": 71 },
"events": ["gnoblin.layer.created", "gnoblin.layer.changed", "gnoblin.layer.removed"]
}Every event includes state revision, sequence, and monotonic time. Layer records use the fields from layer.list.
createdincludeslayer. Its stable ID islayer.id; it may be unmapped.changedincludeslayer_id, the updatedlayer, and achangedarray of fields. Mapping and unmapping are changes; per-recordrevisionis excluded.removedincludeslayer_idand the final record aslast.
Lua receives the same events, with its layer snapshot refreshed before each callback.
Built-in and configured shortcuts
API 1.5 shortcut.actions lists built-in window-manager and Mutter actions. Its optional group accepts wm for window-manager actions, mutter for compositor actions, or wayland for Mutter’s Wayland actions. Omit group to list all supported groups. Results include an ID, group, key, default bindings, and a description when available. Defaults come from Gnoblin’s pinned Mutter metadata and do not include user overrides.
API 1.9 shortcut.list returns native configured shortcuts. Each record contains:
name,enabled,trigger, andrevision;bindingas a string for one accelerator or an array for several;- a command argument array or a built-in action ID.
Disabled declarations and external-client shortcuts are not included. Use shortcuts.list for new clients.