aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/stringop.h1
-rw-r--r--sway/ipc.c92
-rw-r--r--sway/stringop.c39
3 files changed, 132 insertions, 0 deletions
diff --git a/include/stringop.h b/include/stringop.h
index a5346829..4300f9ed 100644
--- a/include/stringop.h
+++ b/include/stringop.h
@@ -10,5 +10,6 @@ char *code_strchr(const char *string, char delimiter);
char *code_strstr(const char *haystack, const char *needle);
int unescape_string(char *string);
char *join_args(char **argv, int argc);
+char *join_list(list_t *list, char *separator);
#endif
diff --git a/sway/ipc.c b/sway/ipc.c
index 505c17f8..39e580cd 100644
--- a/sway/ipc.c
+++ b/sway/ipc.c
@@ -11,10 +11,13 @@
#include <stropts.h>
#include <sys/ioctl.h>
#include <fcntl.h>
+#include <ctype.h>
#include "ipc.h"
#include "log.h"
#include "config.h"
#include "commands.h"
+#include "list.h"
+#include "stringop.h"
static int ipc_socket = -1;
static struct wlc_event_source *ipc_event_source = NULL;
@@ -37,6 +40,10 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data);
void ipc_client_disconnect(struct ipc_client *client);
void ipc_client_handle_command(struct ipc_client *client);
bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length);
+void ipc_get_workspaces_callback(swayc_t *container, void *data);
+void ipc_get_outputs_callback(swayc_t *container, void *data);
+
+char *json_list(list_t *items);
void ipc_init(void) {
ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
@@ -195,6 +202,26 @@ void ipc_client_handle_command(struct ipc_client *client) {
ipc_send_reply(client, reply, (uint32_t) length);
break;
}
+ case IPC_GET_WORKSPACES:
+ {
+ list_t *workspaces = create_list();
+ container_map(&root_container, ipc_get_workspaces_callback, workspaces);
+ char *json = json_list(workspaces);
+ free_flat_list(workspaces);
+ ipc_send_reply(client, json, strlen(json));
+ free(json);
+ break;
+ }
+ case IPC_GET_OUTPUTS:
+ {
+ list_t *outputs = create_list();
+ container_map(&root_container, ipc_get_outputs_callback, outputs);
+ char *json = json_list(outputs);
+ free_flat_list(outputs);
+ ipc_send_reply(client, json, strlen(json));
+ free(json);
+ break;
+ }
default:
sway_log(L_INFO, "Unknown IPC command type %i", client->current_command);
ipc_client_disconnect(client);
@@ -227,3 +254,68 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
return true;
}
+
+char *json_list(list_t *items) {
+ char *json_elements = join_list(items, ",");
+ size_t len = strlen(json_elements);
+ char *json = malloc(len + 3);
+ json[0] = '[';
+ memcpy(json + 1, json_elements, len);
+ json[len+1] = ']';
+ json[len+2] = '\0';
+ free(json_elements);
+ return json;
+}
+
+void ipc_get_workspaces_callback(swayc_t *container, void *data) {
+ if (container->type == C_WORKSPACE) {
+ char *json = malloc(512); // Output should usually be around 180 chars
+ int num = isdigit(container->name[0]) ? atoi(container->name) : -1;
+ // TODO: escape the name (quotation marks, unicode)
+ sprintf(json,
+ "{"
+ "\"num\":%d,"
+ "\"name\":\"%s\","
+ "\"visible\":%s,"
+ "\"focused\":%s,"
+ "\"rect\":{"
+ "\"x\":%d,"
+ "\"y\":%d,"
+ "\"width\":%d,"
+ "\"height\":%d"
+ "},"
+ "\"output\":\"%s\","
+ "\"urgent\":%s"
+ "}",
+ num, container->name, container->visible ? "true" : "false", container->is_focused ? "true" : "false",
+ container->x, container->y, container->width, container->height,
+ container->parent->name, "false" // TODO: urgent hint
+ );
+ list_add((list_t *)data, json);
+ }
+}
+
+void ipc_get_outputs_callback(swayc_t *container, void *data) {
+ if (container->type == C_OUTPUT) {
+ char *json = malloc(512); // Output should usually be around 130 chars
+ // TODO: escape the name (quotation marks, unicode)
+ sprintf(json,
+ "{"
+ "\"name\":\"%s\","
+ "\"active\":%s,"
+ "\"primary\":%s,"
+ "\"rect\":{"
+ "\"x\":%d,"
+ "\"y\":%d,"
+ "\"width\":%d,"
+ "\"height\":%d"
+ "},"
+ "\"current_workspace\":\"%s\""
+ "}",
+ container->name, "true", "false", // TODO: active, primary
+ container->x, container->y, container->width, container->height,
+ container->focused ? container->focused->name : ""
+ );
+ list_add((list_t *)data, json);
+ }
+}
diff --git a/sway/stringop.c b/sway/stringop.c
index 1dff97bf..c39e2c34 100644
--- a/sway/stringop.c
+++ b/sway/stringop.c
@@ -4,6 +4,7 @@
#include "string.h"
#include "list.h"
#include <strings.h>
+#include <log.h>
/* Note: This returns 8 characters for trimmed_start per tab character. */
char *strip_whitespace(char *_str, int *trimmed_start) {
@@ -197,3 +198,41 @@ char *join_args(char **argv, int argc) {
res[len - 1] = '\0';
return res;
}
+
+/*
+ * Join a list of strings, adding separator in between. Separator can be NULL.
+ */
+char *join_list(list_t *list, char *separator) {
+ if (!sway_assert(list != NULL, "list != NULL") || list->length == 0) {
+ return NULL;
+ }
+
+ size_t len = 1; // NULL terminator
+ size_t sep_len = 0;
+ if (separator != NULL) {
+ sep_len = strlen(separator);
+ len += (list->length - 1) * sep_len;
+ }
+
+ for (int i = 0; i < list->length; i++) {
+ len += strlen(list->items[i]);
+ }
+
+ char *res = malloc(len);
+
+ char *p = res + strlen(list->items[0]);
+ strcpy(res, list->items[0]);
+
+ for (int i = 1; i < list->length; i++) {
+ if (sep_len) {
+ memcpy(p, separator, sep_len);
+ p += sep_len;
+ }
+ strcpy(p, list->items[i]);
+ p += strlen(list->items[i]);
+ }
+
+ *p = '\0';
+
+ return res;
+}