aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h5
-rw-r--r--sway/commands.c30
-rw-r--r--sway/commands/ipc.c140
-rw-r--r--sway/config.c26
4 files changed, 200 insertions, 1 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 9e8d013e..3ab8d5af 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -120,6 +120,7 @@ sway_cmd cmd_gaps;
sway_cmd cmd_hide_edge_borders;
sway_cmd cmd_include;
sway_cmd cmd_input;
+sway_cmd cmd_ipc;
sway_cmd cmd_kill;
sway_cmd cmd_layout;
sway_cmd cmd_log_colors;
@@ -192,4 +193,8 @@ sway_cmd input_cmd_pointer_accel;
sway_cmd input_cmd_scroll_method;
sway_cmd input_cmd_tap;
+sway_cmd cmd_ipc_cmd;
+sway_cmd cmd_ipc_events;
+sway_cmd cmd_ipc_event_cmd;
+
#endif
diff --git a/sway/commands.c b/sway/commands.c
index 5d5087b1..47f7533c 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -180,6 +180,7 @@ static struct cmd_handler handlers[] = {
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "include", cmd_include },
{ "input", cmd_input },
+ { "ipc", cmd_ipc },
{ "kill", cmd_kill },
{ "layout", cmd_layout },
{ "log_colors", cmd_log_colors },
@@ -292,6 +293,26 @@ static struct cmd_handler bar_colors_handlers[] = {
{ "urgent_workspace", bar_colors_cmd_urgent_workspace },
};
+static struct cmd_handler ipc_handlers[] = {
+ { "bar-config", cmd_ipc_cmd },
+ { "command", cmd_ipc_cmd },
+ { "events", cmd_ipc_events },
+ { "inputs", cmd_ipc_cmd },
+ { "marks", cmd_ipc_cmd },
+ { "outputs", cmd_ipc_cmd },
+ { "tree", cmd_ipc_cmd },
+ { "workspaces", cmd_ipc_cmd },
+};
+
+static struct cmd_handler ipc_event_handlers[] = {
+ { "binding", cmd_ipc_event_cmd },
+ { "input", cmd_ipc_event_cmd },
+ { "mode", cmd_ipc_event_cmd },
+ { "output", cmd_ipc_event_cmd },
+ { "window", cmd_ipc_event_cmd },
+ { "workspace", cmd_ipc_event_cmd },
+};
+
static int handler_compare(const void *_a, const void *_b) {
const struct cmd_handler *a = _a;
const struct cmd_handler *b = _b;
@@ -311,10 +332,17 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
sizeof(bar_colors_handlers) / sizeof(struct cmd_handler),
sizeof(struct cmd_handler), handler_compare);
} else if (block == CMD_BLOCK_INPUT) {
- sway_log(L_DEBUG, "looking at input handlers");
res = bsearch(&d, input_handlers,
sizeof(input_handlers) / sizeof(struct cmd_handler),
sizeof(struct cmd_handler), handler_compare);
+ } else if (block == CMD_BLOCK_IPC) {
+ res = bsearch(&d, ipc_handlers,
+ sizeof(ipc_handlers) / sizeof(struct cmd_handler),
+ sizeof(struct cmd_handler), handler_compare);
+ } else if (block == CMD_BLOCK_IPC_EVENTS) {
+ res = bsearch(&d, ipc_event_handlers,
+ sizeof(ipc_event_handlers) / sizeof(struct cmd_handler),
+ sizeof(struct cmd_handler), handler_compare);
} else {
res = bsearch(&d, handlers,
sizeof(handlers) / sizeof(struct cmd_handler),
diff --git a/sway/commands/ipc.c b/sway/commands/ipc.c
new file mode 100644
index 00000000..e6ae27a4
--- /dev/null
+++ b/sway/commands/ipc.c
@@ -0,0 +1,140 @@
+#include <stdio.h>
+#include <string.h>
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "ipc.h"
+#include "log.h"
+#include "util.h"
+
+struct cmd_results *cmd_ipc(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ if (config->reading && strcmp("{", argv[0]) != 0) {
+ return cmd_results_new(CMD_INVALID, "ipc",
+ "Expected '{' at start of IPC config definition.");
+ }
+
+ if (!config->reading) {
+ return cmd_results_new(CMD_FAILURE, "ipc", "Can only be used in config file.");
+ }
+
+ return cmd_results_new(CMD_BLOCK_IPC, NULL, NULL);
+}
+
+struct cmd_results *cmd_ipc_events(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "events", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ if (config->reading && strcmp("{", argv[0]) != 0) {
+ return cmd_results_new(CMD_INVALID, "events",
+ "Expected '{' at start of IPC event config definition.");
+ }
+
+ if (!config->reading) {
+ return cmd_results_new(CMD_FAILURE, "events", "Can only be used in config file.");
+ }
+
+ return cmd_results_new(CMD_BLOCK_IPC_EVENTS, NULL, NULL);
+}
+
+struct cmd_results *cmd_ipc_cmd(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ bool enabled;
+ if (strcmp(argv[0], "enabled") == 0) {
+ enabled = true;
+ } else if (strcmp(argv[0], "disabled") == 0) {
+ enabled = false;
+ } else {
+ return cmd_results_new(CMD_INVALID, argv[-1],
+ "Argument must be one of 'enabled' or 'disabled'");
+ }
+
+ struct {
+ char *name;
+ enum ipc_command_type type;
+ } types[] = {
+ { "command", IPC_COMMAND },
+ { "workspaces", IPC_GET_WORKSPACES },
+ { "outputs", IPC_GET_OUTPUTS },
+ { "tree", IPC_GET_TREE },
+ { "marks", IPC_GET_MARKS },
+ { "bar-config", IPC_GET_BAR_CONFIG },
+ { "inputs", IPC_GET_INPUTS },
+ };
+
+ uint32_t type = 0;
+
+ for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
+ if (strcmp(types[i].name, argv[-1]) == 0) {
+ type = types[i].type;
+ break;
+ }
+ }
+
+ if (enabled) {
+ config->ipc_policy |= type;
+ sway_log(L_DEBUG, "Enabled IPC %s feature", argv[-1]);
+ } else {
+ config->ipc_policy &= ~type;
+ sway_log(L_DEBUG, "Disabled IPC %s feature", argv[-1]);
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
+
+struct cmd_results *cmd_ipc_event_cmd(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ bool enabled;
+ if (strcmp(argv[0], "enabled") == 0) {
+ enabled = true;
+ } else if (strcmp(argv[0], "disabled") == 0) {
+ enabled = false;
+ } else {
+ return cmd_results_new(CMD_INVALID, argv[-1],
+ "Argument must be one of 'enabled' or 'disabled'");
+ }
+
+ struct {
+ char *name;
+ enum ipc_command_type type;
+ } types[] = {
+ { "workspace", event_mask(IPC_EVENT_WORKSPACE) },
+ { "output", event_mask(IPC_EVENT_OUTPUT) },
+ { "mode", event_mask(IPC_EVENT_MODE) },
+ { "window", event_mask(IPC_EVENT_WINDOW) },
+ { "binding", event_mask(IPC_EVENT_BINDING) },
+ { "input", event_mask(IPC_EVENT_INPUT) },
+ };
+
+ uint32_t type = 0;
+
+ for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
+ if (strcmp(types[i].name, argv[-1]) == 0) {
+ type = types[i].type;
+ break;
+ }
+ }
+
+ if (enabled) {
+ config->ipc_policy |= type;
+ sway_log(L_DEBUG, "Enabled IPC %s event", argv[-1]);
+ } else {
+ config->ipc_policy &= ~type;
+ sway_log(L_DEBUG, "Disabled IPC %s event", argv[-1]);
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
diff --git a/sway/config.c b/sway/config.c
index b1b0aac9..e737f83c 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -641,6 +641,22 @@ bool read_config(FILE *file, struct sway_config *config) {
}
break;
+ case CMD_BLOCK_IPC:
+ if (block == CMD_BLOCK_END) {
+ block = CMD_BLOCK_IPC;
+ } else {
+ sway_log(L_ERROR, "Invalid block '%s'", line);
+ }
+ break;
+
+ case CMD_BLOCK_IPC_EVENTS:
+ if (block == CMD_BLOCK_IPC) {
+ block = CMD_BLOCK_IPC_EVENTS;
+ } else {
+ sway_log(L_ERROR, "Invalid block '%s'", line);
+ }
+ break;
+
case CMD_BLOCK_END:
switch(block) {
case CMD_BLOCK_MODE:
@@ -671,6 +687,16 @@ bool read_config(FILE *file, struct sway_config *config) {
block = CMD_BLOCK_END;
break;
+ case CMD_BLOCK_IPC:
+ sway_log(L_DEBUG, "End of IPC block");
+ block = CMD_BLOCK_END;
+ break;
+
+ case CMD_BLOCK_IPC_EVENTS:
+ sway_log(L_DEBUG, "End of IPC events block");
+ block = CMD_BLOCK_IPC;
+ break;
+
case CMD_BLOCK_END:
sway_log(L_ERROR, "Unmatched }");
break;