diff --git a/completions/zsh/_swaymsg b/completions/zsh/_swaymsg index 1c3ccd65..6bb03279 100644 --- a/completions/zsh/_swaymsg +++ b/completions/zsh/_swaymsg @@ -15,6 +15,7 @@ types=( 'get_workspaces' +'get_seats' 'get_inputs' 'get_outputs' 'get_tree' diff --git a/include/ipc.h b/include/ipc.h index 9665a88d..8172c782 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -4,6 +4,7 @@ #define event_mask(ev) (1 << (ev & 0x7F)) enum ipc_command_type { + // i3 command types - see i3's I3_REPLY_TYPE constants IPC_COMMAND = 0, IPC_GET_WORKSPACES = 1, IPC_SUBSCRIBE = 2, @@ -12,9 +13,13 @@ enum ipc_command_type { IPC_GET_MARKS = 5, IPC_GET_BAR_CONFIG = 6, IPC_GET_VERSION = 7, - IPC_GET_INPUTS = 8, - IPC_GET_CLIPBOARD = 9, - // Events send from sway to clients. Events have the highest bits set. + + // sway-specific command types + IPC_GET_INPUTS = 100, + IPC_GET_CLIPBOARD = 101, + IPC_GET_SEATS = 102, + + // Events sent from sway to clients. Events have the highest bits set. IPC_EVENT_WORKSPACE = ((1<<31) | 0), IPC_EVENT_OUTPUT = ((1<<31) | 1), IPC_EVENT_MODE = ((1<<31) | 2), diff --git a/include/sway/config.h b/include/sway/config.h index a0e7e81f..b20458cb 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -263,8 +263,10 @@ enum ipc_feature { IPC_FEATURE_EVENT_BINDING = 4096, IPC_FEATURE_EVENT_INPUT = 8192, IPC_FEATURE_GET_CLIPBOARD = 16384, + IPC_FEATURE_GET_SEATS = 32768, - IPC_FEATURE_ALL_COMMANDS = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384, + IPC_FEATURE_ALL_COMMANDS = + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384 | 32768, IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 7d87d377..440e3a24 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -9,6 +9,7 @@ json_object *ipc_json_get_version(); json_object *ipc_json_describe_container(struct sway_container *c); json_object *ipc_json_describe_container_recursive(struct sway_container *c); json_object *ipc_json_describe_input(struct sway_input_device *device); +json_object *ipc_json_describe_seat(struct sway_seat *seat); json_object *ipc_json_describe_bar_config(struct bar_config *bar); #endif diff --git a/sway/ipc-json.c b/sway/ipc-json.c index ea7fd9ad..ad37216f 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -267,6 +267,31 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { return object; } +json_object *ipc_json_describe_seat(struct sway_seat *seat) { + if (!(sway_assert(seat, "Seat must not be null"))) { + return NULL; + } + + json_object *object = json_object_new_object(); + struct sway_container *focus = seat_get_focus(seat); + + json_object_object_add(object, "name", + json_object_new_string(seat->wlr_seat->name)); + json_object_object_add(object, "capabilities", + json_object_new_int(seat->wlr_seat->capabilities)); + json_object_object_add(object, "focus", + json_object_new_int(focus ? focus->id : 0)); + + json_object *devices = json_object_new_array(); + struct sway_seat_device *device = NULL; + wl_list_for_each(device, &seat->devices, link) { + json_object_array_add(devices, ipc_json_describe_input(device->input_device)); + } + json_object_object_add(object, "devices", devices); + + return object; +} + json_object *ipc_json_describe_bar_config(struct bar_config *bar) { if (!sway_assert(bar, "Bar must not be NULL")) { return NULL; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 39d1d0a7..8734e8f8 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -546,6 +546,19 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_SEATS: + { + json_object *seats = json_object_new_array(); + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &input_manager->seats, link) { + json_object_array_add(seats, ipc_json_describe_seat(seat)); + } + const char *json_string = json_object_to_json_string(seats); + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(seats); // free + goto exit_cleanup; + } + case IPC_GET_TREE: { json_object *tree = diff --git a/swaymsg/main.c b/swaymsg/main.c index 7e3622d9..89af7345 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -106,6 +106,35 @@ static void pretty_print_input(json_object *i) { json_object_get_int(vendor)); } +static void pretty_print_seat(json_object *i) { + json_object *name, *capabilities, *devices; + json_object_object_get_ex(i, "name", &name); + json_object_object_get_ex(i, "capabilities", &capabilities); + json_object_object_get_ex(i, "devices", &devices); + + const char *fmt = + "Seat: %s\n" + " Capabilities: %d\n"; + + printf(fmt, json_object_get_string(name), + json_object_get_int(capabilities)); + + size_t devices_len = json_object_array_length(devices); + if (devices_len > 0) { + printf(" Devices:\n"); + for (size_t i = 0; i < devices_len; ++i) { + json_object *device = json_object_array_get_idx(devices, i); + + json_object *device_name; + json_object_object_get_ex(device, "name", &device_name); + + printf(" %s\n", json_object_get_string(device_name)); + } + } + + printf("\n"); +} + static void pretty_print_output(json_object *o) { json_object *name, *rect, *focused, *active, *ws; json_object_object_get_ex(o, "name", &name); @@ -211,7 +240,8 @@ static void pretty_print_clipboard(json_object *v) { static void pretty_print(int type, json_object *resp) { if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && - type != IPC_GET_VERSION && type != IPC_GET_CLIPBOARD) { + type != IPC_GET_VERSION && type != IPC_GET_CLIPBOARD && + type != IPC_GET_SEATS) { printf("%s\n", json_object_to_json_string_ext(resp, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); return; @@ -244,6 +274,9 @@ static void pretty_print(int type, json_object *resp) { case IPC_GET_OUTPUTS: pretty_print_output(obj); break; + case IPC_GET_SEATS: + pretty_print_seat(obj); + break; } } } @@ -324,6 +357,8 @@ int main(int argc, char **argv) { type = IPC_COMMAND; } else if (strcasecmp(cmdtype, "get_workspaces") == 0) { type = IPC_GET_WORKSPACES; + } else if (strcasecmp(cmdtype, "get_seats") == 0) { + type = IPC_GET_SEATS; } else if (strcasecmp(cmdtype, "get_inputs") == 0) { type = IPC_GET_INPUTS; } else if (strcasecmp(cmdtype, "get_outputs") == 0) { diff --git a/swaymsg/swaymsg.1.txt b/swaymsg/swaymsg.1.txt index abc517c8..52209b12 100644 --- a/swaymsg/swaymsg.1.txt +++ b/swaymsg/swaymsg.1.txt @@ -48,6 +48,9 @@ IPC Message Types *get_workspaces*:: Gets a JSON-encoded list of workspaces and their status. +*get_seats*:: + Gets a JSON-encoded list of current seats. + *get_inputs*:: Gets a JSON-encoded list of current inputs.