From 66c66c730436f325c6917b787b742af5e89102ab Mon Sep 17 00:00:00 2001
From: Mikkel Oscar Lyderik <mikkeloscar@gmail.com>
Date: Mon, 21 Dec 2015 15:28:34 +0100
Subject: [PATCH 1/2] Implement `barconfig_update` IPC event

---
 include/ipc-server.h |   2 +
 sway/ipc-server.c    | 147 +++++++++++++++++++++++++------------------
 2 files changed, 89 insertions(+), 60 deletions(-)

diff --git a/include/ipc-server.h b/include/ipc-server.h
index 5ac255cf..9858d6f0 100644
--- a/include/ipc-server.h
+++ b/include/ipc-server.h
@@ -2,6 +2,7 @@
 #define _SWAY_IPC_SERVER_H
 
 #include "container.h"
+#include "config.h"
 #include "ipc.h"
 
 void ipc_init(void);
@@ -9,6 +10,7 @@ void ipc_terminate(void);
 struct sockaddr_un *ipc_user_sockaddr(void);
 
 void ipc_event_workspace(swayc_t *old, swayc_t *new);
+void ipc_event_barconfig_update(struct bar_config *bar);
 const char *swayc_type_string(enum swayc_types type);
 
 #endif
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 9dd3e1a5..96d4f945 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -43,6 +43,7 @@ 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 *workspace, void *data);
 void ipc_get_outputs_callback(swayc_t *container, void *data);
+json_object *ipc_json_describe_bar_config(struct bar_config *bar);
 
 void ipc_init(void) {
 	ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
@@ -290,8 +291,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
 			const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
 			if (strcmp(event_type, "workspace") == 0) {
 				client->subscribed_events |= IPC_GET_WORKSPACES;
-			}
-			else {
+			} else if (strcmp(event_type, "barconfig_update") == 0) {
+				client->subscribed_events |= IPC_GET_BAR_CONFIG;
+			} else {
 				ipc_send_reply(client, "{\"success\": false}", 18);
 				ipc_client_disconnect(client);
 				json_object_put(request);
@@ -397,64 +399,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
 				ipc_send_reply(client, error, (uint32_t)strlen(error));
 				break;
 			}
-			json_object *json = json_object_new_object();
-			json_object_object_add(json, "id", json_object_new_string(bar->id));
-			json_object_object_add(json, "tray_output", NULL);
-			json_object_object_add(json, "mode", json_object_new_string(bar->mode));
-			json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state));
-			//json_object_object_add(json, "modifier", json_object_new_string(bar->modifier)); // TODO: Fix modifier
-			switch (bar->position) {
-			case DESKTOP_SHELL_PANEL_POSITION_TOP:
-				json_object_object_add(json, "position", json_object_new_string("top"));
-				break;
-			case DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
-				json_object_object_add(json, "position", json_object_new_string("bottom"));
-				break;
-			case DESKTOP_SHELL_PANEL_POSITION_LEFT:
-				json_object_object_add(json, "position", json_object_new_string("left"));
-				break;
-			case DESKTOP_SHELL_PANEL_POSITION_RIGHT:
-				json_object_object_add(json, "position", json_object_new_string("right"));
-				break;
-			}
-			json_object_object_add(json, "status_command", json_object_new_string(bar->status_command));
-			json_object_object_add(json, "font", json_object_new_string(bar->font));
-			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, "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, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator));
-			json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose));
-
-			json_object *colors = json_object_new_object();
-			json_object_object_add(colors, "background", json_object_new_string(bar->colors.background));
-			json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline));
-			json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator));
-
-			json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border));
-			json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg));
-			json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text));
-
-			json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border));
-			json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg));
-			json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text));
-
-			json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border));
-			json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg));
-			json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text));
-
-			json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border));
-			json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg));
-			json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text));
-
-			json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border));
-			json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg));
-			json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text));
-
-			json_object_object_add(json, "colors", colors);
-
+			json_object *json = ipc_json_describe_bar_config(bar);
 			const char *json_string = json_object_to_json_string(json);
 			ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
 			json_object_put(json); // free
@@ -551,6 +496,72 @@ void ipc_get_outputs_callback(swayc_t *container, void *data) {
 	}
 }
 
+json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
+	if (!sway_assert(bar, "Bar must not be NULL")) {
+		return NULL;
+	}
+
+	json_object *json = json_object_new_object();
+	json_object_object_add(json, "id", json_object_new_string(bar->id));
+	json_object_object_add(json, "tray_output", NULL);
+	json_object_object_add(json, "mode", json_object_new_string(bar->mode));
+	json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state));
+	//json_object_object_add(json, "modifier", json_object_new_string(bar->modifier)); // TODO: Fix modifier
+	switch (bar->position) {
+	case DESKTOP_SHELL_PANEL_POSITION_TOP:
+		json_object_object_add(json, "position", json_object_new_string("top"));
+		break;
+	case DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
+		json_object_object_add(json, "position", json_object_new_string("bottom"));
+		break;
+	case DESKTOP_SHELL_PANEL_POSITION_LEFT:
+		json_object_object_add(json, "position", json_object_new_string("left"));
+		break;
+	case DESKTOP_SHELL_PANEL_POSITION_RIGHT:
+		json_object_object_add(json, "position", json_object_new_string("right"));
+		break;
+	}
+	json_object_object_add(json, "status_command", json_object_new_string(bar->status_command));
+	json_object_object_add(json, "font", json_object_new_string(bar->font));
+	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, "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, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator));
+	json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose));
+
+	json_object *colors = json_object_new_object();
+	json_object_object_add(colors, "background", json_object_new_string(bar->colors.background));
+	json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline));
+	json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator));
+
+	json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border));
+	json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg));
+	json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text));
+
+	json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border));
+	json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg));
+	json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text));
+
+	json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border));
+	json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg));
+	json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text));
+
+	json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border));
+	json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg));
+	json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text));
+
+	json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border));
+	json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg));
+	json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text));
+
+	json_object_object_add(json, "colors", colors);
+
+	return json;
+}
+
 void ipc_event_workspace(swayc_t *old, swayc_t *new) {
 	json_object *obj = json_object_new_object();
 	json_object_object_add(obj, "change", json_object_new_string("focus"));
@@ -570,3 +581,19 @@ void ipc_event_workspace(swayc_t *old, swayc_t *new) {
 
 	json_object_put(obj); // free
 }
+
+void ipc_event_barconfig_update(struct bar_config *bar) {
+	json_object *json = ipc_json_describe_bar_config(bar);
+	const char *json_string = json_object_to_json_string(json);
+	int i;
+	struct ipc_client *client;
+	for (i = 0; i < ipc_client_list->length; ++i) {
+		client = ipc_client_list->items[i];
+		if ((client->subscribed_events & IPC_GET_BAR_CONFIG) == 0) {
+			continue;
+		}
+		ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
+	}
+
+	json_object_put(json); // free
+}

From c803b79764cc570ffbb5354adeb58d0e89f230cc Mon Sep 17 00:00:00 2001
From: Mikkel Oscar Lyderik <mikkeloscar@gmail.com>
Date: Mon, 21 Dec 2015 15:31:09 +0100
Subject: [PATCH 2/2] Trigger event on bar mode|hidden_state commands

---
 sway/commands.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sway/commands.c b/sway/commands.c
index de5b9705..93c74915 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -25,6 +25,7 @@
 #include "resize.h"
 #include "input_state.h"
 #include "criteria.h"
+#include "ipc-server.h"
 
 typedef struct cmd_results *sway_cmd(int argc, char **argv);
 
@@ -1707,7 +1708,7 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, const ch
 
 	if (strcmp(old_state, bar->hidden_state) != 0) {
 		if (!config->reading) {
-			// TODO: IPC event
+			ipc_event_barconfig_update(bar);
 		}
 		sway_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", bar->hidden_state, bar->id);
 	}
@@ -1779,7 +1780,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode
 
 	if (strcmp(old_mode, bar->mode) != 0) {
 		if (!config->reading) {
-			// TODO: IPC event
+			ipc_event_barconfig_update(bar);
 		}
 		sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id);
 	}