Keyboard shortcuts
gnoblin.shortcuts.configured() returns the command and action shortcuts that
the configuration declares. It omits shortcuts owned by shell clients. A
configured entry with capture_input = true starts a shortcut session and sends
events to Lua listeners. It has no ShortcutState record. Socket clients
receive session events for dynamic bindings they register and subscribe to.
Each read-only record contains:
On this page
name,binding,enabled,trigger, andrevision.- Either
command(an argument array) oraction(agroup.keyidentifier). bindingas a string for one accelerator or an array for multiple bindings.
enabled is false for a configured built-in action with no bindings. Disabled
shortcut declarations are omitted. These records are not objects: change them
with gnoblin.configure.shortcuts. The socket request shortcuts.list returns
the same records.
for _, shortcut in ipairs(gnoblin.shortcuts.configured()) do
print(shortcut.name, shortcut.binding)
endSee the compositor bridge for socket request details.
gnoblin.shortcuts.bind(id, accelerator, options?) registers a binding and
returns a Shortcut.
accelerator is a chord in the chord syntax,
such as <Super><Alt>F9. A chord in another form, such as Super+Alt+F9, is
an error that names the form to write. The Shortcut reports the chord in its
written form.
The optional options table takes these fields:
holdacceptsnone,super,control, oralt. It defaults tonone.triggeracceptspressorrelease. It defaults topress.modeacceptspassiveormodal. It defaults topassive. Modal mode requires a held modifier and captures keyboard events while it is held.capture_inputdefaults tofalse. Set it totruefor a bareSuperbinding; this flag is rejected for other accelerators. A bareSuperbinding also requirestrigger: "release",hold: "none", and an available compositor early modifier hook.
Every binding is a Shortcut object. It has these fields:
id,accelerator,hold,trigger,modeandcapture_input.alive, which is false once the binding has ended.
bind returns the object at once with the values you asked for. If the
compositor refuses the binding, for example because another client holds the
accelerator, the shortcut ends and its closed listeners receive the reason as
a second argument. An ID that this runtime already binds is an error: unbind it
first.
gnoblin.shortcuts.list() returns the shortcuts that this runtime has bound
and not unbound, in ID order. They are the same objects that bind returned.
A Shortcut raises these signals. Use shortcut:on(signal, fn); fn receives
the shortcut and the event:
| Signal | When | Event |
|---|---|---|
activated |
The accelerator fires (on release for a release trigger). | gnoblin.shortcut.binding-activated |
deactivated |
A press-triggered binding is released. | gnoblin.shortcut.binding-deactivated |
session_activated |
A held or modal binding starts its session. | gnoblin.shortcut.session.activated |
session_key |
A session receives a key. | gnoblin.shortcut.session.key |
session_ended |
A session ends. | gnoblin.shortcut.session.ended |
closed |
The binding has ended. | None |
The global events stay for code that watches every binding. The activated
event carries a grant on a real activation.
shortcut:unbind() removes the binding and returns an Operation. The
Shortcut ends, and its closed listeners run, when the compositor has removed
the binding. Listening ends after closed, and alive is false. Binding the
same ID again makes a new object.
shortcut:end_session(session_id) takes the session_id from the binding's
session_activated signal or gnoblin.shortcut.session.activated event. It is
a method of the shortcut because the shortcut owns the session.
- It releases the session's keyboard capture and keeps the binding registered.
- A stale session ID, or a binding owned by another connection, is rejected.
- The matching ended event uses reason
cancelled.
Socket clients keep the wire names shortcut.unbind and shortcut.session.end.
This binding ends each of its sessions when the session starts:
local switcher = gnoblin.shortcuts.bind("switcher", "<Alt>Tab", {hold = "alt", mode = "modal"})
switcher:on("session_activated", function(shortcut, event)
shortcut:end_session(event.session_id)
end)
switcher:on("closed", function(shortcut, reason)
print("switcher ended", reason)
end)Dynamic registrations belong to the Lua runtime that created them. They end
when the runtime stops or reloads, and the "closed" listeners of a Shortcut
run with the reason "config_reloaded" or "runtime_stopped". Active sessions end on modifier release,
unbind, config reload, session lock, capture preemption, owner disconnect, or
after ten seconds.
The ten seconds are a fixed guard against a lost key release, not a lease: nothing renews it. To take the keyboard for a script, with a lease and composed text, use a keyboard grab, which also explains why sessions do not use it.
Lua listeners can subscribe to these shortcut session events. A Shortcut raises
the same events on its own object as session_activated, session_key and
session_ended:
gnoblin.shortcut.session.activatedwhen a held binding starts.gnoblin.shortcut.session.keyfor captured keyboard input. Fields includekeyval,keycode,modifiers,phase(pressorrelease), andtime. Real key presses and releases can carry agrant; repeated events do not carry one.gnoblin.shortcut.session.endedwhen a session ends. Reasons arereleased,unbound,owner_disconnected,config_changed,locked,preempted,timed_out,cancelled,compositor_stopped, andruntime_stopped. Thecancelledreason is used byshortcut.session.end.runtime_stoppedis sent to a socket client when the Lua runtime stops while that client owns the active session.
Lua listeners receive the same authority as a Grant
in event.grant on real, non-repeated session.key events. Synthetic and input-method
events are excluded. The gesture ends after five seconds, and each focus-sensitive
operation can take its scope from it once. Gnoblin still delivers the key event if
it cannot issue a grant.
gnoblin.shortcut.binding-activated can carry a grant on
trusted activation. gnoblin.shortcut.binding-deactivated is emitted for
press-triggered bindings. The event contains:
idandacceleratorto identify the binding.input_time, Mutter's timestamp for the key release.
Release-triggered bindings activate on release and do not emit a second deactivation event.
Modal sessions capture keyboard events only. Pointer input remains available to the shell's layer-shell surfaces and client windows.
gnoblin.shortcuts.actions(group?) reads Gnoblin's packaged keybinding
catalogue. The build generates it from executable handlers in the pinned
Mutter source and the matching pinned keybinding schema sources. Gnoblin ships
the descriptions and default bindings with the runtime, so listing actions and
validating configured actions do not need installed GSettings schemas.
Omit group to list actions from all three groups.
| Group | Contains |
|---|---|
wm |
Window-manager actions, such as closing or maximizing a window. |
mutter |
Compositor actions defined by Mutter. |
wayland |
Actions defined by Mutter specifically for its Wayland compositor. |
An unknown group raises an error. The catalogue includes only actions with an
executable handler in Gnoblin's pinned Mutter build. The gnome:shell group is
not included. This read API is separate from gnoblin.configure.shortcuts,
which declares shortcut configuration.
To assign a built-in action, set action = action.id on a named
gnoblin.configure.shortcuts entry. See the
shortcut configuration reference for the
declarative form. gnoblin.shortcuts.bind() registers a Gnoblin shortcut event;
it does not invoke a built-in action.
Each action record contains:
id,group, andkey.- Optional
description, when the pinned schema provides one. default_bindings, the pinned schema's exact accelerator string array.
These are packaged schema defaults, not the current user override. An empty
array means that the action has no default accelerator. Actions are returned
in wm, mutter, wayland order, with keys sorted alphabetically within each
group.
for _, action in ipairs(gnoblin.shortcuts.actions("wm")) do
if action.id == "wm.close" then
for _, binding in ipairs(action.default_bindings) do
print(binding)
end
end
endCapture a shortcut
| Method | Arguments | Successful result |
|---|---|---|
shortcut.capture(args) |
Optional timeout in seconds, from 1 to 60; default 30 |
Pending operation; completion returns {accelerator} |
Call gnoblin.shortcuts.capture() from a runtime event callback. On success,
value.accelerator is the normalized accelerator string.
Press Escape to cancel. Capture fails if another capture is active, the session is locked, Mutter has an active input-capture session, or a compositor stage grab is active. If an input-capture session or stage grab starts during capture, Gnoblin cancels the operation before forwarding keys to that owner. The native runtime does not expose key events to Lua.
The socket capability and request contract are documented in the compositor bridge.
gnoblin.once("gnoblin.window.focused", function()
local operation = gnoblin.shortcuts.capture({timeout = 10})
operation:on_complete(function(value, err)
if err then
print("Shortcut capture failed: " .. err.message)
else
print(value.accelerator)
end
end)
end)See gnoblinctl for command-line forms of these operations.