summaryrefslogtreecommitdiff
path: root/sway/ipc-json.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/ipc-json.c')
-rw-r--r--sway/ipc-json.c359
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;
}