diff options
Diffstat (limited to 'sway/ipc-json.c')
-rw-r--r-- | sway/ipc-json.c | 359 |
1 files changed, 268 insertions, 91 deletions
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index e3450df1..6e5ba4fd 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1,6 +1,8 @@ #include <json-c/json.h> +#include <libevdev/libevdev.h> #include <stdio.h> #include <ctype.h> +#include "config.h" #include "log.h" #include "sway/config.h" #include "sway/ipc-json.h" @@ -9,12 +11,17 @@ #include "sway/tree/workspace.h" #include "sway/output.h" #include "sway/input/input-manager.h" +#include "sway/input/cursor.h" #include "sway/input/seat.h" +#include <wlr/backend/libinput.h> #include <wlr/types/wlr_box.h> #include <wlr/types/wlr_output.h> #include <xkbcommon/xkbcommon.h> #include "wlr-layer-shell-unstable-v1-protocol.h" +static const int i3_output_id = INT32_MAX; +static const int i3_scratch_id = INT32_MAX - 1; + static const char *ipc_json_layout_description(enum sway_container_layout l) { switch (l) { case L_VERT: @@ -32,15 +39,68 @@ static const char *ipc_json_layout_description(enum sway_container_layout l) { } static const char *ipc_json_orientation_description(enum sway_container_layout l) { - if (l == L_VERT) { + switch (l) { + case L_VERT: return "vertical"; + case L_HORIZ: + return "horizontal"; + default: + return "none"; } +} - if (l == L_HORIZ) { - return "horizontal"; +static const char *ipc_json_border_description(enum sway_container_border border) { + switch (border) { + case B_NONE: + return "none"; + case B_PIXEL: + return "pixel"; + case B_NORMAL: + return "normal"; + case B_CSD: + return "csd"; } + return "unknown"; +} - return "none"; +static const char *ipc_json_output_transform_description(enum wl_output_transform transform) { + switch (transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + return "normal"; + case WL_OUTPUT_TRANSFORM_90: + return "90"; + case WL_OUTPUT_TRANSFORM_180: + return "180"; + case WL_OUTPUT_TRANSFORM_270: + return "270"; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return "flipped"; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return "flipped-90"; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return "flipped-180"; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return "flipped-270"; + } + return NULL; +} + +static const char *ipc_json_device_type_description(struct sway_input_device *device) { + switch (device->wlr_device->type) { + case WLR_INPUT_DEVICE_POINTER: + return "pointer"; + case WLR_INPUT_DEVICE_KEYBOARD: + return "keyboard"; + case WLR_INPUT_DEVICE_TOUCH: + return "touch"; + case WLR_INPUT_DEVICE_TABLET_TOOL: + return "tablet_tool"; + case WLR_INPUT_DEVICE_TABLET_PAD: + return "tablet_pad"; + case WLR_INPUT_DEVICE_SWITCH: + return "switch"; + } + return "unknown"; } json_object *ipc_json_get_version(void) { @@ -76,30 +136,43 @@ static json_object *ipc_json_create_empty_rect(void) { return ipc_json_create_rect(&empty); } -static void ipc_json_describe_root(struct sway_root *root, json_object *object) { - json_object_object_add(object, "type", json_object_new_string("root")); +static json_object *ipc_json_create_node(int id, char *name, + bool focused, json_object *focus, struct wlr_box *box) { + json_object *object = json_object_new_object(); + + json_object_object_add(object, "id", json_object_new_int(id)); + json_object_object_add(object, "name", + name ? json_object_new_string(name) : NULL); + json_object_object_add(object, "rect", ipc_json_create_rect(box)); + json_object_object_add(object, "focused", json_object_new_boolean(focused)); + json_object_object_add(object, "focus", focus); + + // set default values to be compatible with i3 + json_object_object_add(object, "border", + json_object_new_string( + ipc_json_border_description(B_NONE))); + json_object_object_add(object, "current_border_width", + json_object_new_int(0)); + json_object_object_add(object, "layout", + json_object_new_string( + ipc_json_layout_description(L_HORIZ))); + json_object_object_add(object, "orientation", + json_object_new_string( + ipc_json_orientation_description(L_HORIZ))); + json_object_object_add(object, "percent", NULL); + json_object_object_add(object, "window_rect", ipc_json_create_empty_rect()); + json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect()); + json_object_object_add(object, "geometry", ipc_json_create_empty_rect()); + json_object_object_add(object, "window", NULL); + json_object_object_add(object, "urgent", json_object_new_boolean(false)); + json_object_object_add(object, "floating_nodes", json_object_new_array()); + json_object_object_add(object, "sticky", json_object_new_boolean(false)); + + return object; } -static const char *ipc_json_get_output_transform(enum wl_output_transform transform) { - switch (transform) { - case WL_OUTPUT_TRANSFORM_NORMAL: - return "normal"; - case WL_OUTPUT_TRANSFORM_90: - return "90"; - case WL_OUTPUT_TRANSFORM_180: - return "180"; - case WL_OUTPUT_TRANSFORM_270: - return "270"; - case WL_OUTPUT_TRANSFORM_FLIPPED: - return "flipped"; - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - return "flipped-90"; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - return "flipped-180"; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - return "flipped-270"; - } - return NULL; +static void ipc_json_describe_root(struct sway_root *root, json_object *object) { + json_object_object_add(object, "type", json_object_new_string("root")); } static void ipc_json_describe_output(struct sway_output *output, @@ -110,7 +183,8 @@ static void ipc_json_describe_output(struct sway_output *output, json_object_object_add(object, "primary", json_object_new_boolean(false)); json_object_object_add(object, "layout", json_object_new_string("output")); json_object_object_add(object, "orientation", - json_object_new_string(ipc_json_orientation_description(L_NONE))); + json_object_new_string( + ipc_json_orientation_description(L_NONE))); json_object_object_add(object, "make", json_object_new_string(wlr_output->make)); json_object_object_add(object, "model", @@ -121,7 +195,7 @@ static void ipc_json_describe_output(struct sway_output *output, json_object_new_double(wlr_output->scale)); json_object_object_add(object, "transform", json_object_new_string( - ipc_json_get_output_transform(wlr_output->transform))); + ipc_json_output_transform_description(wlr_output->transform))); struct sway_workspace *ws = output_get_active_workspace(output); json_object_object_add(object, "current_workspace", @@ -187,6 +261,52 @@ json_object *ipc_json_describe_disabled_output(struct sway_output *output) { return object; } +static json_object *ipc_json_describe_scratchpad_output(void) { + struct wlr_box box; + root_get_box(root, &box); + + // Create focus stack for __i3_scratch workspace + json_object *workspace_focus = json_object_new_array(); + for (int i = root->scratchpad->length - 1; i >= 0; --i) { + struct sway_container *container = root->scratchpad->items[i]; + json_object_array_add(workspace_focus, + json_object_new_int(container->node.id)); + } + + json_object *workspace = ipc_json_create_node(i3_scratch_id, + "__i3_scratch", false, workspace_focus, &box); + json_object_object_add(workspace, "type", + json_object_new_string("workspace")); + + // List all hidden scratchpad containers as floating nodes + json_object *floating_array = json_object_new_array(); + for (int i = 0; i < root->scratchpad->length; ++i) { + struct sway_container *container = root->scratchpad->items[i]; + if (!container->workspace) { + json_object_array_add(floating_array, + ipc_json_describe_node_recursive(&container->node)); + } + } + json_object_object_add(workspace, "floating_nodes", floating_array); + + // Create focus stack for __i3 output + json_object *output_focus = json_object_new_array(); + json_object_array_add(output_focus, json_object_new_int(i3_scratch_id)); + + json_object *output = ipc_json_create_node(i3_output_id, + "__i3", false, output_focus, &box); + json_object_object_add(output, "type", + json_object_new_string("output")); + json_object_object_add(output, "layout", + json_object_new_string("output")); + + json_object *nodes = json_object_new_array(); + json_object_array_add(nodes, workspace); + json_object_object_add(output, "nodes", nodes); + + return output; +} + static void ipc_json_describe_workspace(struct sway_workspace *workspace, json_object *object) { int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1; @@ -200,11 +320,12 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace, json_object_object_add(object, "representation", workspace->representation ? json_object_new_string(workspace->representation) : NULL); - const char *layout = ipc_json_layout_description(workspace->layout); - json_object_object_add(object, "layout", json_object_new_string(layout)); - - const char *orientation = ipc_json_orientation_description(workspace->layout); - json_object_object_add(object, "orientation", json_object_new_string(orientation)); + json_object_object_add(object, "layout", + json_object_new_string( + ipc_json_layout_description(workspace->layout))); + json_object_object_add(object, "orientation", + json_object_new_string( + ipc_json_orientation_description(workspace->layout))); // Floating json_object *floating_array = json_object_new_array(); @@ -216,20 +337,6 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace, json_object_object_add(object, "floating_nodes", floating_array); } -static const char *describe_container_border(enum sway_container_border border) { - switch (border) { - case B_NONE: - return "none"; - case B_PIXEL: - return "pixel"; - case B_NORMAL: - return "normal"; - case B_CSD: - return "csd"; - } - return "unknown"; -} - static void ipc_json_describe_view(struct sway_container *c, json_object *object) { json_object_object_add(object, "pid", json_object_new_int(c->view->pid)); @@ -307,15 +414,18 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o json_object_new_string(container_is_floating(c) ? "floating_con" : "con")); json_object_object_add(object, "layout", - json_object_new_string(ipc_json_layout_description(c->layout))); + json_object_new_string( + ipc_json_layout_description(c->layout))); json_object_object_add(object, "orientation", - json_object_new_string(ipc_json_orientation_description(c->layout))); + json_object_new_string( + ipc_json_orientation_description(c->layout))); bool urgent = c->view ? view_is_urgent(c->view) : container_has_urgent_child(c); json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky)); + json_object_object_add(object, "fullscreen_mode", json_object_new_int(c->is_fullscreen)); struct sway_node *parent = node_get_parent(&c->node); struct wlr_box parent_box = {0, 0, 0, 0}; @@ -331,7 +441,8 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o } json_object_object_add(object, "border", - json_object_new_string(describe_container_border(c->current.border))); + json_object_new_string( + ipc_json_border_description(c->current.border))); json_object_object_add(object, "current_border_width", json_object_new_int(c->current.border_thickness)); json_object_object_add(object, "floating_nodes", json_object_new_array()); @@ -372,17 +483,10 @@ static void focus_inactive_children_iterator(struct sway_node *node, json_object *ipc_json_describe_node(struct sway_node *node) { struct sway_seat *seat = input_manager_get_default_seat(); bool focused = seat_get_focus(seat) == node; - - json_object *object = json_object_new_object(); char *name = node_get_name(node); struct wlr_box box; node_get_box(node, &box); - json_object_object_add(object, "id", json_object_new_int((int)node->id)); - json_object_object_add(object, "name", - name ? json_object_new_string(name) : NULL); - json_object_object_add(object, "rect", ipc_json_create_rect(&box)); - json_object_object_add(object, "focused", json_object_new_boolean(focused)); json_object *focus = json_object_new_array(); struct focus_inactive_data data = { @@ -390,24 +494,9 @@ json_object *ipc_json_describe_node(struct sway_node *node) { .object = focus, }; seat_for_each_node(seat, focus_inactive_children_iterator, &data); - json_object_object_add(object, "focus", focus); - // set default values to be compatible with i3 - json_object_object_add(object, "border", - json_object_new_string(describe_container_border(B_NONE))); - json_object_object_add(object, "current_border_width", json_object_new_int(0)); - json_object_object_add(object, "layout", - json_object_new_string(ipc_json_layout_description(L_HORIZ))); - json_object_object_add(object, "orientation", - json_object_new_string(ipc_json_orientation_description(L_HORIZ))); - json_object_object_add(object, "percent", NULL); - json_object_object_add(object, "window_rect", ipc_json_create_empty_rect()); - json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect()); - json_object_object_add(object, "geometry", ipc_json_create_empty_rect()); - json_object_object_add(object, "window", NULL); - json_object_object_add(object, "urgent", json_object_new_boolean(false)); - json_object_object_add(object, "floating_nodes", json_object_new_array()); - json_object_object_add(object, "sticky", json_object_new_boolean(false)); + json_object *object = ipc_json_create_node( + (int)node->id, name, focused, focus, &box); switch (node->type) { case N_ROOT: @@ -434,6 +523,8 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) { json_object *children = json_object_new_array(); switch (node->type) { case N_ROOT: + json_object_array_add(children, + ipc_json_describe_scratchpad_output()); for (i = 0; i < root->outputs->length; ++i) { struct sway_output *output = root->outputs->items[i]; json_object_array_add(children, @@ -470,22 +561,6 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) { return object; } -static const char *describe_device_type(struct sway_input_device *device) { - switch (device->wlr_device->type) { - case WLR_INPUT_DEVICE_POINTER: - return "pointer"; - case WLR_INPUT_DEVICE_KEYBOARD: - return "keyboard"; - case WLR_INPUT_DEVICE_TOUCH: - return "touch"; - case WLR_INPUT_DEVICE_TABLET_TOOL: - return "tablet_tool"; - case WLR_INPUT_DEVICE_TABLET_PAD: - return "tablet_pad"; - } - return "unknown"; -} - json_object *ipc_json_describe_input(struct sway_input_device *device) { if (!(sway_assert(device, "Device must not be null"))) { return NULL; @@ -502,7 +577,8 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { json_object_object_add(object, "product", json_object_new_int(device->wlr_device->product)); json_object_object_add(object, "type", - json_object_new_string(describe_device_type(device))); + json_object_new_string( + ipc_json_device_type_description(device))); if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { struct wlr_keyboard *keyboard = device->wlr_device->keyboard; @@ -525,6 +601,26 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { } } + if (wlr_input_device_is_libinput(device->wlr_device)) { + struct libinput_device *libinput_dev; + libinput_dev = wlr_libinput_get_device_handle(device->wlr_device); + + const char *events = "unknown"; + switch (libinput_device_config_send_events_get_mode(libinput_dev)) { + case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED: + events = "enabled"; + break; + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: + events = "disabled_on_external_mouse"; + break; + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED: + events = "disabled"; + break; + } + json_object_object_add(object, "libinput_send_events", + json_object_new_string(events)); + } + return object; } @@ -553,6 +649,31 @@ json_object *ipc_json_describe_seat(struct sway_seat *seat) { return object; } +static uint32_t event_to_x11_button(uint32_t event) { + switch (event) { + case BTN_LEFT: + return 1; + case BTN_MIDDLE: + return 2; + case BTN_RIGHT: + return 3; + case SWAY_SCROLL_UP: + return 4; + case SWAY_SCROLL_DOWN: + return 5; + case SWAY_SCROLL_LEFT: + return 6; + case SWAY_SCROLL_RIGHT: + return 7; + case BTN_SIDE: + return 8; + case BTN_EXTRA: + return 9; + default: + return 0; + } +} + json_object *ipc_json_describe_bar_config(struct bar_config *bar) { if (!sway_assert(bar, "Bar must not be NULL")) { return NULL; @@ -569,18 +690,36 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_new_string(bar->status_command) : NULL); json_object_object_add(json, "font", json_object_new_string((bar->font) ? bar->font : config->font)); + + json_object *gaps = json_object_new_object(); + json_object_object_add(gaps, "top", + json_object_new_int(bar->gaps.top)); + json_object_object_add(gaps, "right", + json_object_new_int(bar->gaps.right)); + json_object_object_add(gaps, "bottom", + json_object_new_int(bar->gaps.bottom)); + json_object_object_add(gaps, "left", + json_object_new_int(bar->gaps.left)); + json_object_object_add(json, "gaps", gaps); + if (bar->separator_symbol) { json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); } json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); + json_object_object_add(json, "status_padding", + json_object_new_int(bar->status_padding)); + json_object_object_add(json, "status_edge_padding", + json_object_new_int(bar->status_edge_padding)); json_object_object_add(json, "wrap_scroll", json_object_new_boolean(bar->wrap_scroll)); json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); + json_object_object_add(json, "strip_workspace_name", + json_object_new_boolean(bar->strip_workspace_name)); json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); json_object_object_add(json, "verbose", @@ -680,6 +819,8 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { struct bar_binding *binding = bar->bindings->items[i]; json_object *bind = json_object_new_object(); json_object_object_add(bind, "input_code", + json_object_new_int(event_to_x11_button(binding->button))); + json_object_object_add(bind, "event_code", json_object_new_int(binding->button)); json_object_object_add(bind, "command", json_object_new_string(binding->command)); @@ -699,5 +840,41 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { } json_object_object_add(json, "outputs", outputs); } +#if HAVE_TRAY + // Add tray outputs if defined + if (bar->tray_outputs && bar->tray_outputs->length > 0) { + json_object *tray_outputs = json_object_new_array(); + for (int i = 0; i < bar->tray_outputs->length; ++i) { + const char *name = bar->tray_outputs->items[i]; + json_object_array_add(tray_outputs, json_object_new_string(name)); + } + json_object_object_add(json, "tray_outputs", tray_outputs); + } + + json_object *tray_bindings = json_object_new_array(); + for (int i = 0; i < 10; ++i) { + if (bar->tray_bindings[i]) { + json_object *bind = json_object_new_object(); + json_object_object_add(bind, "input_code", + json_object_new_int(i)); + json_object_object_add(bind, "command", + json_object_new_string(bar->tray_bindings[i])); + json_object_array_add(tray_bindings, bind); + } + } + if (json_object_array_length(tray_bindings) > 0) { + json_object_object_add(json, "tray_bindings", tray_bindings); + } else { + json_object_put(tray_bindings); + } + + if (bar->icon_theme) { + json_object_object_add(json, "icon_theme", + json_object_new_string(bar->icon_theme)); + } + + json_object_object_add(json, "tray_padding", + json_object_new_int(bar->tray_padding)); +#endif return json; } |