sway-ipc(7)
πΈ hey bestie, welcome to sway-ipc(7) πΈ
okay so this is the manual page for sway-ipc β the IPC protocol for sway(1) π
it's literally the group chat between your programs and your sway process. slay.
β¨ NAME β¨
sway-ipc β IPC protocol for sway
π DESCRIPTION π
This details the interprocess communication (IPC) protocol for sway(1). This IPC protocol can be used to control or obtain information from a sway process. no cap.
The IPC protocol uses a UNIX socket as the method of communication. The path to the socket is stored in the environment variable SWAYSOCK and, for backwards compatibility with i3, I3SOCK. You can also retrieve the socket path by calling sway --get-socketpath. iykyk π«Ά
π MESSAGE AND REPLY FORMAT π
The format for messages and replies is:
<magic-string> <payload-length> <payload-type> <payload>
Where:
<magic-string>isi3-ipc, for compatibility with i3<payload-length>is a 32-bit integer in native byte order<payload-type>is a 32-bit integer in native byte order
For example, sending the exit command would look like the following hexdump:
00000000 | 69 33 2d 69 70 63 04 00 00 00 00 00 00 00 65 78 |i3-ipc........ex|
00000010 | 69 74 |it |
The payload for replies will be a valid serialized JSON data structure. periodt β¨
π MESSAGES AND REPLIES π
The following message types and their corresponding reply types are currently supported. For all replies, any properties not listed are subject to removal. bestie, don't get attached to undocumented properties π
0βRUN_COMMANDβ Runs the payload as sway commands1βGET_WORKSPACESβ Get the list of current workspaces2βSUBSCRIBEβ Subscribe the IPC connection to the events listed in the payload3βGET_OUTPUTSβ Get the list of current outputs4βGET_TREEβ Get the node layout tree5βGET_MARKSβ Get the names of all the marks currently set6βGET_BAR_CONFIGβ Get the specified bar config or a list of bar config names7βGET_VERSIONβ Get the version of sway that owns the IPC socket8βGET_BINDING_MODESβ Get the list of binding mode names9βGET_CONFIGβ Returns the config that was last loaded10βSEND_TICKβ Sends a tick event with the specified payload11βSYNCβ Replies failure object for i3 compatibility12βGET_BINDING_STATEβ Request the current binding state, e.g. the currently active binding mode name.100βGET_INPUTSβ Get the list of input devices101βGET_SEATSβ Get the list of seats
π 0. RUN_COMMAND π
MESSAGE
Parses and runs the payload as sway commands. main character energy fr fr π₯
REPLY
An array of objects corresponding to each command that was parsed. Each object has the property success, which is a boolean indicating whether the command was successful. The object may also contain the properties error and parse_error. The error property is a human readable error message while parse_error is a boolean indicating whether the reason the command failed was because the command was unknown or not able to be parsed. okay so parse_error is the "wait, what command??" flag π
Example Reply:
[
{
"success": true
},
{
"success": false,
"parse_error": true,
"error": "Invalid/unknown command"
}
]
π¦ 1. GET_WORKSPACES π¦
MESSAGE
Retrieves the list of workspaces.
REPLY
The reply is an array of objects corresponding to each workspace. Each object has the following properties:
numβ integer β The workspace number or-1for workspaces that do not start with a numbernameβ string β The name of the workspacevisibleβ boolean β Whether the workspace is currently visible on any outputfocusedβ boolean β Whether the workspace is currently focused by the default seat (seat0)urgentβ boolean β Whether a window on the workspace has the urgent flag setrectβ object β The bounds of the workspace. It consists ofx,y,width, andheightoutputβ string β The name of the output that the workspace is on
that's the whole vibe check for workspaces, bestie π
And here's what that reply actually looks like when it comes back at you π
[
{
"num": 1,
"name": "1",
"visible": true,
"focused": true,
"rect": {
"x": 0,
"y": 23,
"width": 1920,
"height": 1057
},
"output": "eDP-1"
},
]
π¦ 2. SUBSCRIBE π¦
MESSAGE
Okay so this one is literally you telling the IPC connection "bestie, keep me in the loop." You subscribe this IPC connection to the event types you list in the message payload. The payload should be a valid JSON array of events β yes, an array, don't try to be cute and send one string. Scroll down to the EVENTS section for the full list of what you can subscribe to, iykyk.
REPLY
You get back a single object containing the property success, which is a boolean telling you whether the subscription went through or not. That's it. That's the whole reply. Iconic and minimal π
Example Reply:
{
"success": true
}
β¨ 3. GET_OUTPUTS β¨
MESSAGE
Retrieve the list of outputs. That's your monitors, your displays, your whole "where am I even rendering to" situation π₯οΈ
REPLY
An array of objects, one per output. Each object is stacked with the following properties:
name(string) β The name of the output. On DRM, this is the connector.make(string) β The make of the output.model(string) β The model of the output.serial(string) β The output's serial number as a hexadecimal string.active(boolean) β Whether this output is active/enabled.dpms(boolean) β (Deprecated, usepowerinstead) Whether this output is on/off (via DPMS).power(boolean) β Whether this output is on/off.primary(boolean) β For i3 compatibility, this will befalse. It does not make sense in Wayland. Like, fr, there's no "primary" monitor vibe here.scale(float) β The scale currently in use on the output or-1for disabled outputs.subpixel_hinting(string) β The subpixel hinting current in use on the output. This can bergb,bgr,vrgb,vbgr, ornone.transform(string) β The transform currently in use for the output. This can benormal,90,180,270,flipped-90,flipped-180, orflipped-270.current_workspace(string) β The workspace currently visible on the output ornullfor disabled outputs.modes(array) β An array of supported mode objects. Each object containswidth,height, andrefresh.current_mode(object) β An object representing the current mode containingwidth,height, andrefresh.rect(object) β The bounds for the output consisting ofx,y,width, andheight.hdr(boolean) β Whether HDR is enabled.
Heads up bestie:dpmsis deprecated, so if you're writing new stuff, usepowerinstead. The old one still shows up for compatibility but it's giving legacy energy π
Example Reply:
[
{
"name": "HDMI-A-2",
"make": "Unknown",
"model": "NS-19E310A13",
"serial": "0x00000001",
"active": true,
"primary": false,
"scale": 1.0,
"subpixel_hinting": "rgb",
"transform": "normal",
"current_workspace": "1",
"modes": [
{
"width": 640,
"height": 480,
"refresh": 59940
},
{
"width": 800,
"height": 600,
"refresh": 60317
},
{
"width": 1024,
"height": 768,
"refresh": 60004
},
{
"width": 1920,
"height": 1080,
"refresh": 60000
}
],
"current_mode": {
"width": 1920,
"height": 1080,
"refresh": 60000
}
}
]
πΈ 4. GET_TREE πΈ
MESSAGE
Retrieve a JSON representation of the tree. Yes, the whole layout tree β containers, windows, the entire nesting situation. Main character energy for real π
REPLY
An array of objects that represent the current tree. Each object represents one node and will have the following properties:
(and we're about to get into those properties next β don't go anywhere π)
idβ integer β the internal unique ID for this node. yes it's a number, no you can't pick it πnameβ string β the name of the node, like the output name or the window title. for the scratchpad this will be__i3_scratch, purely for compatibility with i3 π«Άtypeβ string β the node type, and it's one of:root,output,workspace,con, orfloating_conborderβ string β the border style for the node:normal,none,pixel, orcsdcurrent_border_widthβ integer β how many pixels are being used for the border widthlayoutβ string β the node's layout, which can besplith,splitv,stacked,tabbed, oroutputorientationβ string β the node's orientation:vertical,horizontal, ornonepercentβ float β the percentage of the node's parent that it takes up, ornullfor the root and other special nodes such as the scratchpad πΈrectβ object β the absolute geometry of the node. window decorations are excluded from this, but borders are included β¨window_rectβ object β the geometry of the content inside the node, and these coordinates are relative to the node itself. window decorations and borders live outside thewindow_rectπdeco_rectβ object β the geometry of the decorations for the node, relative to the parent nodegeometryβ object β the natural geometry of the contents if it were to size itself πurgentβ boolean β whether the node or any of its descendants has the urgent hint set. > ngl bestie, note that this one may not exist when compiled without xwayland support πstickyβ boolean β whether the node is sticky (shows on all workspaces) π¦marksβ array β the list of marks assigned to the nodefocusedβ boolean β whether the node is currently focused by the default seat (seat0)focusβ array β array of child node IDs in the current focus ordernodesβ array β the tiling children nodes for the node πfloating_nodesβ array β the floating children nodes for the noderepresentationβ string β (only workspaces!) a string representation of the layout of the workspace that can be used as an aid in
...okay so that last row's description wrapped into "submitting reproduction steps for bug reports" β that's still the field from before, nothing new, carry on π
fullscreen_modeβ integer β (only containers and windows πͺ) the fullscreen mode of the node.0means none,1means full workspace, and2means global fullscreen.floatingβ string β the floating state of the container. Can be either"auto_off"or"user_on"β¨scratchpad_stateβ string β whether the window is in the scratchpad. Can be either"none"or"fresh"πapp_idβ string β (only windows) for an xdg-shell window, the name of the application, if set. Otherwisenullπ«Άpidβ integer β (only windows) the PID of the application that owns the window π₯foreign_toplevel_identifierβ string β (only windows) theext-foreign-toplevel-list-v1toplevel identifier of this node πvisibleβ boolean β (only windows) whether the node is visible πshellβ string β (only windows) the shell of the window, such asxdg_shellorxwaylandπinhibit_idleβ boolean β (only windows) whether the window is inhibiting the idle state π΄idle_inhibitorsβ object β (only windows) an object containing the state of the application and user idle inhibitors.applicationcan beenabledornone.usercan befocus,fullscreen,open,visibleornone.sandbox_engineβ string β (only windows) the associated sandbox engine (ornull) π§sandbox_app_idβ string β (only windows) the app ID provided by the associated sandbox engine (ornull)sandbox_instance_idβ string β (only windows) the instance ID provided by the associated sandbox engine (ornull)tagβ string β (only windows) for an xdg-shell window, tag of the toplevel, if set. Otherwisenullπ·οΈwindowβ integer β (only xwayland windows) the X11 window ID for the xwayland window πwindow_propertiesβ object β (only xwayland windows) an object containing thetitle,class,instance,window_role,window_type, andtransient_forfor the window π
ngl bestie, that's a lot of fields β but like, every single one is just a little fact about a node, no cap. Missing ones just come back as null, which is the node equivalent of "no thoughts, head empty" π
Example Reply (the GET_TREE one β buckle up bestie, it's a whole saga) π³
Okay so this is what a real reply to GET_TREE looks like. It's a recursive thing β containers inside containers inside containers, all the way down, like a set of matryoshka dolls that went to therapy. Notice the top node is "type": "root", then under it comes an "output" called __i3, then a "workspace" called __i3_scratch, and then your actual outputs start showing up. Everything under nodes is a child; everything under floating_nodes is a floater. Slay.
{
"id": 1,
"name": "root",
"rect": {
"x": 0,
"y": 0,
"width": 1920,
"height": 1080
},
"focused": false,
"focus": [
3
],
"border": "none",
"current_border_width": 0,
"layout": "splith",
"orientation": "horizontal",
"percent": null,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"type": "root",
"nodes": [
{
"id": 2147483647,
"name": "__i3",
"rect": {
"x": 0,
"y": 0,
"width": 1920,
"height": 1080
},
"focused": false,
"focus": [
2147483646
],
"border": "none",
"current_border_width": 0,
"layout": "output",
"orientation": "horizontal",
"percent": null,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"type": "output",
"nodes": [
{
"id": 2147483646,
"name": "__i3_scratch",
"rect": {
"x": 0,
"y": 0,
"width": 1920,
"height": 1080
},
"focused": false,
"focus": [
],
"border": "none",
"current_border_width": 0,
"layout": "splith",
"orientation": "horizontal",
"percent": null,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"type": "workspace"
}
]
},
{
"id": 3,
"name": "eDP-1",
"rect": {
"x": 0,
"y": 0,
"width": 1920,
"height": 1080
},
"focused": false,
"focus": [
4
],
"border": "none",
"current_border_width": 0,
"layout": "output",
"orientation": "none",
"percent": 1.0,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"type": "output",
"active": true,
"primary": false,
"make": "Unknown",
"model": "0x38ED",
"serial": "0x00000000",
"scale": 1.0,
"transform": "normal",
"current_workspace": "1",
"modes": [
{
"width": 1920,
"height": 1080,
"refresh": 60052
}
],
"current_mode": {
"width": 1920,
"height": 1080,
"refresh": 60052
},
"nodes": [
{
"id": 4,
"name": "1",
"rect": {
"x": 0,
"y": 23,
"width": 1920,
"height": 1057
},
"focused": false,
"focus": [
6,
5
],
"border": "none",
"current_border_width": 0,
"layout": "splith",
"orientation": "horizontal",
"percent": null,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"num": 1,
"output": "eDP-1",
"type": "workspace",
"representation": "H[URxvt termite]",
"nodes": [
{
"id": 5,
"name": "urxvt",
"rect": {
"x": 0,
"y": 23,
"width": 960,
"height": 1057
},
"focused": false,
"focus": [
],
"border": "normal",
"current_border_width": 2,
"layout": "none",
"orientation": "none",
"percent": 0.5,
"window_rect": {
"x": 2,
"y": 0,
"width": 956,
"height": 1030
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 960,
"height": 25
},
"geometry": {
"x": 0,
And yes, it keeps going from there β the tree does not care about your scrollbar, bestie π (more in the next part, don't touch that dial) π«Ά
"y": 0,
"width": 1124,
"height": 422
},
"window": 4194313,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"type": "con",
"fullscreen_mode": 0,
"pid": 23959,
"app_id": null,
"visible": true,
"shell": "xwayland",
"inhibit_idle": true,
"idle_inhibitors": {
"application": "none",
"user": "visible",
},
"window_properties": {
"class": "URxvt",
"instance": "urxvt",
"title": "urxvt",
"transient_for": null
},
"nodes": [
]
},
{
"id": 6,
"name": "",
"rect": {
"x": 960,
"y": 23,
"width": 960,
"height": 1057
},
"focused": true,
"focus": [
],
"border": "normal",
"current_border_width": 2,
"layout": "none",
"orientation": "none",
"percent": 0.5,
"window_rect": {
"x": 2,
"y": 0,
"width": 956,
"height": 1030
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 960,
"height": 25
},
"geometry": {
"x": 0,
"y": 0,
"width": 817,
"height": 458
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"sticky": false,
"type": "con",
"fullscreen_mode": 0,
"pid": 25370,
"app_id": "termite",
"visible": true,
"shell": "xdg_shell",
"inhibit_idle": false,
"idle_inhibitors": {
"application": "none",
"user": "fullscreen",
},
"nodes": [
]
}
]
}
]
}
]
}
Ok that's the rest of the tree dump bestie, we survived ππ the JSON was long but we ate.
5. GET_MARKS π
MESSAGE
Get the marks that are currently set, bestie. Like, right now, as they are.
REPLY
An array of the marks currently set. And here's the little detail that matters: since each mark can only be set for one container, this is a set, so every value is unique and the order is undefined. So don't come for me about ordering, it's giving "no promises" π
Example Reply:
[
"one",
"test"
]
6. GET_BAR_CONFIG (WITHOUT A PAYLOAD) π¦
MESSAGE
When you send this one without a payload, it retrieves the list of configured bar IDs. Simple as that, no cap.
REPLY
An array of bar IDs, which are strings. That's it. That's the whole vibe β¨
Example Reply:
[
"bar-0",
"bar-1"
]
6. GET_BAR_CONFIG (WITH A PAYLOAD) π
MESSAGE
But when you do send it with a bar ID as the payload, it retrieves the config associated with the bar ID you specified in the payload. This is what swaybar uses, but for real it could also be used for third-party bars β highkey a whole serve π₯
REPLY
An object that represents the configuration for the bar with the bar ID you sent as the payload. The following properties exist, with more information about their values in sway-bar(5):
Okay so this next bit is the whole vibe of a bar config β every property it can have, what type of data each one is, and what it's actually doing. Read it like a menu, bestie, because that's basically what it is π
id(string) β the bar ID. That's it, that's the whole thing, it's just the name of the bar.mode(string) β the mode for the bar. It can bedock,hide, orinvisible.position(string) β the bar's position. Right now it can be eitherbottomortop.status_command(string) β the command that gets run to generate the status line. yes, that whole command string, right there in the config β¨font(string) β the font used for the text on the bar.workspace_buttons(boolean) β whether to display the workspace buttons on the bar or not.workspace_min_width(integer) β the minimum width, inpx, for those workspace buttons on the bar.binding_mode_indicator(boolean) β whether to display the current binding mode on the bar.verbose(boolean) β for i3 compatibility this will be the boolean valuefalse. lowkey iconic of it tbh.colors(object) β an object holding the#RRGGBBAAcolors to use for the bar. There's more info on this below, keep scrolling π«Άgaps(object) β an object representing the gaps for the bar, made up oftop,right,bottom, andleft. all four, no skimping.bar_height(integer) β the absolute height to use for the bar, or0to automatically size it based on the font.0means "figure it out yourself", basically.status_padding(integer) β the vertical padding to use for the status line.status_edge_padding(integer) β the horizontal padding to use for the status line when it's at the end of an output.
That's the full rundown, no cap β every property, every type, nothing skipped π
The colors object has these properties, and literally every single one of them is a string holding the #RRGGBBAA representation of the color π
no cap:
backgroundβ the color for the bar background on outputs that are not focusedstatuslineβ the color for the status line text on outputs that are not focusedseparatorβ the color for the separator text on outputs that are not focusedfocused_backgroundβ the color for the background of the bar on the focused output πfocused_statuslineβ the color for the status line text on the focused outputfocused_separatorβ the color for the separator text on the focused outputfocused_workspace_textβ the color for the text of the focused workspace buttonfocused_workspace_bgβ the color for the background of the focused workspace buttonfocused_workspace_borderβ the color for the border of the focused workspace buttonactive_workspace_textβ the color for the text of the workspace buttons for the visible workspaces on outputs that are not focusedactive_workspace_bgβ the color for the background of the workspace buttons for the visible workspaces on outputs that are not focusedactive_workspace_borderβ the color for the border of the workspace buttons for the visible workspaces on outputs that are not focusedinactive_workspace_textβ the color for the text of the workspace buttons for workspaces that are not visible πinactive_workspace_bgβ the color for the background of the workspace buttons for workspaces that are not visibleinactive_workspace_borderβ the color for the border of the workspace buttons for workspaces that are not visibleurgent_workspace_textβ the color for the text of the workspace buttons for workspaces that contain an urgent window π₯urgent_workspace_bgβ the color for the background of the workspace buttons for workspaces that contain an urgent windowurgent_workspace_borderβ the color for the border of the workspace buttons for workspaces that contain an urgent windowbinding_mode_textβ the color for the text of the binding mode indicatorbinding_mode_bgβ the color for the background of the binding mode indicatorbinding_mode_borderβ the color for the border of the binding mode indicator
bestie pls note π«Ά the whole object is just color strings β twenty-one of them β so if you're diffing your config against the reply, every key here should look like #RRGGBBAA or something is off.
Example Reply π
{
"id": "bar-0",
"mode": "dock",
"position": "top",
"status_command": "while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done",
"font": "monospace 10",
"gaps": {
"top": 0,
"right": 0,
"bottom": 0,
"left": 0
},
"bar_height": 0,
"status_padding": 1,
"status_edge_padding": 3,
"workspace_buttons": true,
"workspace_min_width": 0,
"binding_mode_indicator": true,
"verbose": false,
"pango_markup": false,
"colors": {
"background": "#323232ff",
"statusline": "#ffffffff",
"separator": "#666666ff",
"focused_background": "#323232ff",
"focused_statusline": "#ffffffff",
"focused_separator": "#666666ff",
"focused_workspace_border": "#4c7899ff",
"focused_workspace_bg": "#285577ff",
"focused_workspace_text": "#ffffffff",
"inactive_workspace_border": "#32323200",
"inactive_workspace_bg": "#32323200",
"inactive_workspace_text": "#5c5c5cff",
"active_workspace_border": "#333333ff",
"active_workspace_bg": "#5f676aff",
"active_workspace_text": "#ffffffff",
"urgent_workspace_border": "#2f343aff",
"urgent_workspace_bg": "#900000ff",
"urgent_workspace_text": "#ffffffff",
"binding_mode_border": "#2f343aff",
"binding_mode_bg": "#900000ff",
"binding_mode_text": "#ffffffff"
},
}
okay that's a whole lot of JSON but look at it. it's giving organization. it's giving aesthetic. π
7. GET_VERSION</p> β
MESSAGE
bestie. it literally just asks the sway process for its version info. that's it. that's the message.
REPLY
an object with all these properties in it:
major(integer) β the major version of the sway processminor(integer) β the minor version of the sway processpatch(integer) β the patch version of the sway processhuman_readable(string) β a human readable version string that will likely contain more useful information such as the git commit short hash and git branchloaded_config_file_name(string) β the path to the loaded config file
Example Reply πΈ
{
"human_readable": "1.0-rc1-117-g2f7247e0 (Feb 24 2019, branch 'master')",
"major": 1,
"minor": 0,
"patch": 0,
"loaded_config_file_name": "/home/redsoxfan/.config/sway/config"
}
8. GET_BINDING_MODES</p> π¦
MESSAGE
asks for the list of binding modes that are currently configured. very demure. very mindful.
REPLY
an array of strings, where each string is the name of a binding mode. and no matter what, this will always contain at least one mode (currently default), which is the default binding mode β so you're never gonna get an empty list back, okurrr π«Ά
Example Reply β¨
[
"default",
"resize",
]
9. GET_CONFIG</p> π
MESSAGE
hands you back the contents of the config that was last loaded, like a little mixtape but make it dotfiles.
REPLY
an object with a single string property holding the contents of the config π
Example Reply π
{
"config": "set $mod Mod4\nbindsym $mod+q exit\n"
}
10. SEND_TICK</p> π₯
MESSAGE
this is the sync-up moment. it issues a TICK event to all clients subscribing to the event, to make sure that all events prior to the tick were received. and if you give it a payload, that payload gets included in the TICK event. cute, right? it's giving "did everyone see that, sound off in the chat". π
REPLY
a single object containing the property success, which is a boolean value indicating whether the TICK event was sent.
Example Reply β
{
"success": true
}
11. SYNC</p> π
MESSAGE
okay so this one's here for i3 compatibility, and that's the whole vibe β it just returns a failure object, because it does not make sense to implement in sway due to the X11 nature of the command. if you are curious about what this IPC command does in i3, refer to the i3 documentation. not us, bestie. go ask i3. π
REPLY
a single object that contains the property success, which is set to the boolean value false.
ngl the word "Exact" is doing a lot of heavy lifting here β this reply is not a maybe, it's not a depends. it's just false. periodt.
Exact Reply π
{
"success": false
}
12. GET_BINDING_STATE</p> π
MESSAGE
returns the currently active binding mode. the main character mode, if you will.
REPLY
a single object that contains the property name, which is set to the currently active binding mode as a string.
Example Reply π
{
"name": "default"
}
100. GET_INPUTS</p> π§
MESSAGE
retrieves a list of the input devices currently available. yes, all of them. your keyboard, your mouse, whatever cursed peripheral you've got plugged in β it's all on the list. π
REPLY
an array of objects corresponding to each input device. each object has the following properties:
identifierβ string π β the identifier for the input device, bestienameβ string π·οΈ β the human readable name for the devicevendorβ integer π β the vendor code for the input deviceproductβ integer π¦ β the product code for the input devicetypeβ string π β the device type. rn this can bekeyboard,pointer,touch,tablet_tool,tablet_pad, orswitchxkb_active_layout_nameβ string β¨οΈ β (only keyboards!) the name of the active keyboard layoutxkb_layout_namesβ array π β (only keyboards!) a list a layout names configured for the keyboardxkb_active_layout_indexβ integer π’ β (only keyboards!) the index of the active keyboard layoutscroll_factorβ floating π±οΈ β (only pointers!) multiplier applied on scroll event valueslibinputβ object π§ β (only libinput devices!) an object describing the current device settings. see below for more info π
so yeah β the libinput object describes the device configuration for libinput devices β¨ and here's the thing: only properties that are supported for the device will be added to the object. no extra filler, she's selective π
and bestie, in addition to the possible options listed, all string properties may also be unknown, in the case that a new option is added to libinput π«Ά (yes that's a real vibe β libinput moves fast, sway keeps up, and unknown is the diplomatic answer π)
for the meaning of the possible values, go read sway-input(5) π β it's all spelled out there.
the following properties will be included for devices that support them: πΈ
Okay so this next chunk is the libinput device properties vibe check β it's a whole list of properties a device can have, each with its data type and what it means. Think of it as the device's little personality profile π
send_events(string) β whether the device is actually sending events. It can beenabled,disabled, ordisabled_on_external_mouse.tap(string) β whether tap to click is on. It can beenabledordisabled.tap_button_map(string) β the finger-to-button mapping that's in use for tapping. It can belmrorlrm.tap_drag(string) β whether tap-and-drag is on. It can beenabledordisabled.tap_drag_lock(string) β whether drag-lock is on. It can beenabled,disabled, orenabled_sticky.accel_speed(double) β the pointer-acceleration currently in use.accel_profile(string) β the acceleration profile in use. It can benone,flat, oradaptive.natural_scroll(string) β whether natural scrolling is on. It can beenabledordisabled.left_handed(string) β whether left-handed mode is on. It can beenabledordisabled.click_method(string) β the click method in use. It can benone,button_areas, orclickfinger.click_button_map(string) β the finger-to-button mapping in use forclickfinger. It can belmrorlrm.middle_emulation(string) β whether middle emulation is on. It can beenabledordisabled.scroll_method(string) β the scroll method in use. It can benone,two_finger,edge, oron_button_down.scroll_button(int) β the scroll button to use whenscroll_methodison_button_down. This one's given as an input event code, jsyk.scroll_button_lock(string) β whether scroll button lock is on. It can beenabledordisabled.dwt(string) β whether disable-while-typing is on. It can beenabledordisabled.dwtp(string) β whether disable-while-trackpointing is on. It can beenabledor_disabled_ π (no bestie I didn't typo that, that's literally what the page says, love that for us)calibration_matrix(array) β an array of 6 floats representing the calibration matrix for absolute devices such as touchscreens.
Real talk π«Ά β those string values are exactly what you'll see and send. Don't go inventing your own spellings oftwo_fingerorenabled_sticky, the parser will simply not be your friend.
Example Reply:
[
{
"identifier": "1:1:AT_Translated_Set_2_keyboard",
"name": "AT Translated Set 2 keyboard",
"vendor": 1,
"product": 1,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "1267:5:Elan_Touchpad",
"name": "Elan Touchpad",
"vendor": 1267,
"product": 5,
"type": "pointer",
"libinput": {
"send_events": "enabled",
"tap": "enabled",
"tap_button_map": "lmr",
"tap_drag": "enabled",
"tap_drag_lock": "disabled",
"accel_speed": 0.0,
"accel_profile": "none",
"natural_scroll", "disabled",
"left_handed": "disabled",
"click_method": "button_areas",
"middle_emulation": "disabled",
"scroll_method": "edge",
"dwt": "enabled",
"dwtp": "enabled"
}
},
{
"identifier": "3034:22494:USB2.0_VGA_UVC_WebCam:_USB2.0_V",
"name": "USB2.0 VGA UVC WebCam: USB2.0 V",
"vendor": 3034,
"product": 22494,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:3:Sleep_Button",
"name": "Sleep Button",
"vendor": 0,
"product": 3,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:5:Lid_Switch",
"name": "Lid Switch",
"vendor": 0,
"product": 5,
"type": "switch",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:6:Video_Bus",
"name": "Video Bus",
"vendor": 0,
"product": 6,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:1:Power_Button",
"name": "Power Button",
"vendor": 0,
"product": 1,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
}
]
πΈ 101. GET_SEATS πΈ
MESSAGE
okay so this one just asks sway for a list of all the seats it's got configured rn. That's it. That's the ask. πͺ
REPLY
You get back an array of objects, one per seat. And bestie, there will always be at least one seat β no empty-array situation here, ever. Each of those objects is serving these properties:
nameβ string β the unique name for the seat πcapabilitiesβ integer β the number of capabilities that the seat hasfocusβ integer β the id of the node currently focused by the seat, or0when the seat is not currently focused by a node (i.e. a surface layer or xwayland unmanaged has focus) π―devicesβ array β an array of input devices that are attached to the seat. Currently, this is an array of objects that are identical to those returned byGET_INPUTSπ
Example Reply:
[
{
"name": "seat0",
"capabilities": 3,
"focus": 7,
"devices": [
{
"identifier": "1:1:AT_Translated_Set_2_keyboard",
"name": "AT Translated Set 2 keyboard",
"vendor": 1,
"product": 1,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "1267:5:Elan_Touchpad",
"name": "Elan Touchpad",
"vendor": 1267,
"product": 5,
"type": "pointer",
"libinput": {
"send_events": "enabled",
"tap": "enabled",
"tap_button_map": "lmr",
"tap_drag": "enabled",
"tap_drag_lock": "disabled",
"accel_speed": 0.0,
"accel_profile": "none",
"natural_scroll", "disabled",
"left_handed": "disabled",
"click_method": "button_areas",
"middle_emulation": "disabled",
"scroll_method": "edge",
"dwt": "enabled",
"dwtp": "enabled"
}
},
{
"identifier": "3034:22494:USB2.0_VGA_UVC_WebCam:_USB2.0_V",
"name": "USB2.0 VGA UVC WebCam: USB2.0 V",
"vendor": 3034,
"product": 22494,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:3:Sleep_Button",
"name": "Sleep Button",
"vendor": 0,
"product": 3,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:5:Lid_Switch",
"name": "Lid Switch",
"vendor": 0,
"product": 5,
"type": "switch",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:6:Video_Bus",
"name": "Video Bus",
"vendor": 0,
"product": 6,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
},
{
"identifier": "0:1:Power_Button",
"name": "Power Button",
"vendor": 0,
"product": 1,
"type": "keyboard",
"xkb_active_layout_name": "English (US)",
"libinput": {
"send_events": "enabled"
}
}
]
}
]
π EVENTS π
so events are literally just sway's way of sliding into your client's DMs to tell you something changed. π A client can subscribe to any events it wants to be notified of changes for β pick your faves, no pressure. And the event arrives in the exact same format as a reply, which is honestly so convenient of it. β¨
Here's what's on the menu rn:
okay so hereβs the event-type lineup, bestie β exact codes, names, and what they mean, no cap β¨
0x80000000βworkspaceβ Sent whenever an event involving a workspace occurs such as initialization of a new workspace or another workspace gaining focus π0x80000001βoutputβ Sent when outputs are updated πΈ0x80000002βmodeβ Sent whenever the binding mode changes π0x80000003βwindowβ Sent whenever an event involving a window occurs such as it being reparented, focused, or closed πͺ0x80000004βbarconfig_updateβ Sent whenever a bar config changes π0x80000005βbindingβ Sent when a configured binding is executed π0x80000006βshutdownβ Sent when the ipc shuts down because sway is exiting π0x80000007βtickβ Sent when an ipc client sends aSEND_TICKmessage β0x80000014βbar_state_updateβ Sent when the visibility of a bar should change due to a modifier π0x80000015βinputβ Sent when something related to input devices changes π¦
0x80000000. WORKSPACE
Sent whenever a change involving a workspace occurs. The event consists of a single object with the following properties:
changeβstringβ The type of change that occurred. See below for more information π₯currentβobjectβ An object representing the affected workspace ornullfor reload changes π«Άoldβobjectβ For a focus change, this will be an object representing the workspace being switched from. Otherwise, it isnullπ
The following change types are currently available:
initβ The workspace was created β¨emptyβ The workspace is empty and is being destroyed since it is not visible πfocusβ The workspace was focused. See theoldproperty for the previous focus πmoveβ The workspace was moved to a different output πrenameβ The workspace was renamed π·οΈurgentβ A window on the workspace has had its urgency hint set or all urgency hints for windows on the workspace have been cleared π¨reloadβ The configuration file has been reloaded π
Example Event:
{
"change": "init",
"old": null,
"current": {
"id": 10,
"name": "2",
"rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"focused": false,
"focus": [
],
"border": "none",
"current_border_width": 0,
"layout": "splith",
"percent": null,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"window": null,
"urgent": false,
"floating_nodes": [
],
"num": 2,
"output": "eDP-1",
"type": "workspace",
"representation": null,
"nodes": [
]
}
}
0x80000001. OUTPUT
Sent whenever an output is added, removed, or its configuration is changed. The event is a single object with the property change, which is a string containing the reason for the change. Currently, the only value for change is unspecified.
Example Event:
{
"change": "unspecified"
}
0x80000002. MODE
Sent whenever the binding mode changes. The event consists of a single object with the following properties:
change(string) β the binding mode that became activepango_markup(boolean) β whether that mode should be parsed as pango markup or not
Example event, bestie, so you know exactly what it looks like:
{
"change": "default",
"pango_markup": false
}
0x80000003. WINDOW π
Sent whenever literally anything happens to a window. The event is one single object with these properties:
change(string) β the type of change that occurred. Full list is right below πcontainer(object) β an object representing the affected window
And here's the change types you can get rn:
newβ the window was created β¨closeβ the window was closed πfocusβ the window was focusedtitleβ the window's title has changedfullscreen_modeβ the window's fullscreen mode has changedmoveβ the window has been reparented in the treefloatingβ the window has become floating or is no longer floatingurgentβ the window's urgency hint has changed statusmarkβ a mark has been added or removed from the window
Example event (yes it's a whole meal, just roll with it):
{
"change": "new",
"container": {
"id": 12,
"name": null,
"rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"focused": false,
"focus": [
],
"border": "none",
"current_border_width": 0,
"layout": "none",
"percent": 0.0,
"window_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"deco_rect": {
"x": 0,
"y": 0,
"width": 0,
"height": 0
},
"geometry": {
"x": 0,
"y": 0,
"width": 1124,
"height": 422
},
"window": 4194313,
"urgent": false,
"floating_nodes": [
],
"type": "con",
"pid": 19787,
"app_id": null,
"window_properties": {
"class": "URxvt",
"instance": "urxvt",
"transient_for": null
},
"nodes": [
]
}
}
0x80000004. BARCONFIG_UPDATE π
Sent whenever a config for a bar changes. The event is identical to the one you get from GET_BAR_CONFIG when a bar ID is given as a payload β so go peek at section 6, GET_BAR_CONFIG (WITH A PAYLOAD), above for the deets. No cap, it's the same thing.
0x80000005. BINDING β¨οΈ
Sent whenever a binding is executed. The event is a single object with these properties:
change(string) β the change that occurred for the binding. Currently this will only beruncommand(string) β the command associated with the bindingevent_state_mask(array) β an array of strings that correspond to each modifier key for the bindinginput_code(integer) β for keyboard bindcodes, this is the key code for the binding. For mouse bindings, this is the X11 button number, if there is an equivalent. In all other cases, this will be0.symbol(string) β for keyboard bindsyms, this is the bindsym for the binding. Otherwise, this will benullinput_type(string) β the input type that triggered the binding. This is eitherkeyboardormouse
Example event:
{
"change": "run",
"binding": {
"command": "workspace 2",
"event_state_mask": [
"Mod4"
],
"input_code": 0,
"symbol": "2",
"input_type": "keyboard"
}
}
0x80000006. SHUTDOWN π«Ά
Sent whenever the IPC is shutting down. The event is a single object with the property change, which is a string containing the reason for the shutdown. Currently, the only value for change is exit, which is issued when sway is exiting. Like, that's it, that's the whole vibe check.
Example event:
{
"change": "exit"
}
0x80000007. TICK β°
Sent when first subscribing to tick events or by a SEND_TICK message. The event is a single object with the following properties:
first(boolean) β whether this event got triggered by you subscribing to the tick events π«payload(string) β the payload that came in aSEND_TICKmessage, if there was one. No payload? Then it's an empty string, simple as that.
Example Event, copy-paste realness:
{
"first": true
"payload": ""
}
π₯ 0x80000014. BAR_STATE_UPDATE π₯
Fires when a bar's visibility changes because somebody pressed a modifier. The event is a single object, and it's giving these properties:
id(string) β the bar ID that got affected πvisible_by_modifier(boolean) β whether the bar should be made visible because a modifier is being pressed
Example Event, periodt:
{
"id": "bar-0",
"visible_by_modifier": true
}
β¨οΈ 0x80000015. INPUT β¨οΈ
Sent whenever something input-device-related changes. Single object, here's the tea:
change(string) β what actually changedinput(object) β an object representing the input, and it's literally identical to the onesGET_INPUTSgives you (yes, same shape, no cap) π«Ά
The change types you can get right now:
addedβ the input device became available β¨removedβ the input device is no longer available πxkb_keymapβ (keyboards only) the keymap for the keyboard changedxkb_layoutβ (keyboards only) the effective layout in the keymap changedlibinput_configβ (libinput device only) a libinput config option for the device changed
Example Event, and yes this one is a whole meal:
{
"change": "xkb_layout",
"input": {
"identifier": "1:1:AT_Translated_Set_2_keyboard",
"name": "AT Translated Set 2 keyboard",
"vendor": 1,
"product": 1,
"type": "keyboard",
"xkb_layout_names": [
"English (US)",
"English (Dvorak)"
],
"xkb_active_layout_index": 1,
"xkb_active_layout_name": "English (Dvorak)",
"libinput": {
"send_events": "enabled"
}
}
}
π SEE ALSO π
Go read these next, bestie, they're the whole friend group:
aaaand that's the whole page, we ate and left zero crumbs π
β¨ This lil masterpiece is from 2026-04-26 and lives under the name sway-ipc(7) β go forth and script something iconic, ily, bye! ππ¦π
π¦ where this page comes from
- alpine 3.24: sway-doc 1.12_rc3-r0 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms