diff options
-rw-r--r-- | include/ipc-server.h | 4 | ||||
-rw-r--r-- | sway/commands.c | 154 | ||||
-rw-r--r-- | sway/config.c | 2 | ||||
-rw-r--r-- | sway/focus.c | 15 | ||||
-rw-r--r-- | sway/ipc-server.c | 171 | ||||
-rw-r--r-- | sway/layout.c | 7 | ||||
-rw-r--r-- | swaybar/main.c | 30 |
7 files changed, 273 insertions, 110 deletions
diff --git a/include/ipc-server.h b/include/ipc-server.h index 5ac255cf..ab9807ef 100644 --- a/include/ipc-server.h +++ b/include/ipc-server.h | |||
@@ -2,13 +2,15 @@ | |||
2 | #define _SWAY_IPC_SERVER_H | 2 | #define _SWAY_IPC_SERVER_H |
3 | 3 | ||
4 | #include "container.h" | 4 | #include "container.h" |
5 | #include "config.h" | ||
5 | #include "ipc.h" | 6 | #include "ipc.h" |
6 | 7 | ||
7 | void ipc_init(void); | 8 | void ipc_init(void); |
8 | void ipc_terminate(void); | 9 | void ipc_terminate(void); |
9 | struct sockaddr_un *ipc_user_sockaddr(void); | 10 | struct sockaddr_un *ipc_user_sockaddr(void); |
10 | 11 | ||
11 | void ipc_event_workspace(swayc_t *old, swayc_t *new); | 12 | void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change); |
13 | void ipc_event_barconfig_update(struct bar_config *bar); | ||
12 | const char *swayc_type_string(enum swayc_types type); | 14 | const char *swayc_type_string(enum swayc_types type); |
13 | 15 | ||
14 | #endif | 16 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index f6d9b947..b1b1c5b6 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "resize.h" | 25 | #include "resize.h" |
26 | #include "input_state.h" | 26 | #include "input_state.h" |
27 | #include "criteria.h" | 27 | #include "criteria.h" |
28 | #include "ipc-server.h" | ||
28 | 29 | ||
29 | typedef struct cmd_results *sway_cmd(int argc, char **argv); | 30 | typedef struct cmd_results *sway_cmd(int argc, char **argv); |
30 | 31 | ||
@@ -1147,16 +1148,26 @@ static struct cmd_results *cmd_resize(int argc, char **argv) { | |||
1147 | 1148 | ||
1148 | static struct cmd_results *cmd_bar(int argc, char **argv) { | 1149 | static struct cmd_results *cmd_bar(int argc, char **argv) { |
1149 | struct cmd_results *error = NULL; | 1150 | struct cmd_results *error = NULL; |
1150 | if ((error = checkarg(argc, "bar", EXPECTED_EQUAL_TO, 1))) { | 1151 | if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 1))) { |
1151 | return error; | 1152 | return error; |
1152 | } | 1153 | } |
1153 | 1154 | ||
1154 | if (strcmp("{", argv[0]) != 0) { | 1155 | if (config->reading && strcmp("{", argv[0]) != 0) { |
1155 | return cmd_results_new(CMD_INVALID, "bar", | 1156 | return cmd_results_new(CMD_INVALID, "bar", |
1156 | "Expected '{' at start of bar config definition."); | 1157 | "Expected '{' at start of bar config definition."); |
1157 | } | 1158 | } |
1158 | 1159 | ||
1159 | if (!config->reading) { | 1160 | if (!config->reading) { |
1161 | if (argc > 1) { | ||
1162 | if (strcasecmp("mode", argv[0]) == 0) { | ||
1163 | return bar_cmd_mode(argc-1, argv + 1); | ||
1164 | } | ||
1165 | |||
1166 | if (strcasecmp("hidden_state", argv[0]) == 0) { | ||
1167 | return bar_cmd_hidden_state(argc-1, argv + 1); | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1160 | return cmd_results_new(CMD_FAILURE, "bar", "Can only be used in config file."); | 1171 | return cmd_results_new(CMD_FAILURE, "bar", "Can only be used in config file."); |
1161 | } | 1172 | } |
1162 | 1173 | ||
@@ -1679,53 +1690,144 @@ static struct cmd_results *bar_cmd_height(int argc, char **argv) { | |||
1679 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 1690 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
1680 | } | 1691 | } |
1681 | 1692 | ||
1693 | static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, const char *hidden_state) { | ||
1694 | char *old_state = bar->hidden_state; | ||
1695 | if (strcasecmp("toggle", hidden_state) == 0 && !config->reading) { | ||
1696 | if (strcasecmp("hide", bar->hidden_state) == 0) { | ||
1697 | bar->hidden_state = strdup("show"); | ||
1698 | } else if (strcasecmp("show", bar->hidden_state) == 0) { | ||
1699 | bar->hidden_state = strdup("hide"); | ||
1700 | } | ||
1701 | } else if (strcasecmp("hide", hidden_state) == 0) { | ||
1702 | bar->hidden_state = strdup("hide"); | ||
1703 | } else if (strcasecmp("show", hidden_state) == 0) { | ||
1704 | bar->hidden_state = strdup("show"); | ||
1705 | } else { | ||
1706 | return cmd_results_new(CMD_INVALID, "hidden_state", "Invalid value %s", hidden_state); | ||
1707 | } | ||
1708 | |||
1709 | if (strcmp(old_state, bar->hidden_state) != 0) { | ||
1710 | if (!config->reading) { | ||
1711 | ipc_event_barconfig_update(bar); | ||
1712 | } | ||
1713 | sway_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", bar->hidden_state, bar->id); | ||
1714 | } | ||
1715 | |||
1716 | // free old mode | ||
1717 | free(old_state); | ||
1718 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1719 | } | ||
1720 | |||
1721 | |||
1682 | static struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { | 1722 | static struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { |
1683 | struct cmd_results *error = NULL; | 1723 | struct cmd_results *error = NULL; |
1684 | if ((error = checkarg(argc, "hidden_state", EXPECTED_EQUAL_TO, 1))) { | 1724 | if ((error = checkarg(argc, "hidden_state", EXPECTED_AT_LEAST, 1))) { |
1725 | return error; | ||
1726 | } | ||
1727 | if ((error = checkarg(argc, "hidden_state", EXPECTED_LESS_THAN, 3))) { | ||
1685 | return error; | 1728 | return error; |
1686 | } | 1729 | } |
1687 | 1730 | ||
1731 | if (config->reading && argc > 1) { | ||
1732 | return cmd_results_new(CMD_INVALID, "hidden_state", "Unexpected value %s in config mode", argv[1]); | ||
1733 | } | ||
1734 | |||
1688 | const char *state = argv[0]; | 1735 | const char *state = argv[0]; |
1689 | char *old_state = config->current_bar->hidden_state; | ||
1690 | 1736 | ||
1691 | if (strcasecmp("hide", state) == 0) { | 1737 | if (config->reading) { |
1692 | config->current_bar->hidden_state = strdup(state); | 1738 | return bar_set_hidden_state(config->current_bar, state); |
1693 | } else if(strcmp("show", state) == 0) { | 1739 | } |
1694 | config->current_bar->hidden_state = strdup(state); | 1740 | |
1741 | const char *id; | ||
1742 | if (argc == 2) { | ||
1743 | id = argv[1]; | ||
1744 | } | ||
1745 | |||
1746 | int i; | ||
1747 | struct bar_config *bar; | ||
1748 | for (i = 0; i < config->bars->length; ++i) { | ||
1749 | bar = config->bars->items[i]; | ||
1750 | if (id && strcmp(id, bar->id) == 0) { | ||
1751 | return bar_set_hidden_state(bar, state); | ||
1752 | } | ||
1753 | |||
1754 | error = bar_set_hidden_state(bar, state); | ||
1755 | if (error) { | ||
1756 | return error; | ||
1757 | } | ||
1758 | } | ||
1759 | |||
1760 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1761 | } | ||
1762 | |||
1763 | static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode) { | ||
1764 | char *old_mode = bar->mode; | ||
1765 | if (strcasecmp("toggle", mode) == 0 && !config->reading) { | ||
1766 | if (strcasecmp("dock", bar->mode) == 0) { | ||
1767 | bar->mode = strdup("hide"); | ||
1768 | } else if (strcasecmp("hide", bar->mode) == 0) { | ||
1769 | bar->mode = strdup("dock"); | ||
1770 | } | ||
1771 | } else if (strcasecmp("dock", mode) == 0) { | ||
1772 | bar->mode = strdup("dock"); | ||
1773 | } else if (strcasecmp("hide", mode) == 0) { | ||
1774 | bar->mode = strdup("hide"); | ||
1775 | } else if (strcasecmp("invisible", mode) == 0) { | ||
1776 | bar->mode = strdup("invisible"); | ||
1695 | } else { | 1777 | } else { |
1696 | return cmd_results_new(CMD_INVALID, "hidden_state", "Invalid value %s", state); | 1778 | return cmd_results_new(CMD_INVALID, "mode", "Invalid value %s", mode); |
1697 | } | 1779 | } |
1698 | 1780 | ||
1699 | sway_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", state, config->current_bar->id); | 1781 | if (strcmp(old_mode, bar->mode) != 0) { |
1782 | if (!config->reading) { | ||
1783 | ipc_event_barconfig_update(bar); | ||
1784 | } | ||
1785 | sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); | ||
1786 | } | ||
1700 | 1787 | ||
1701 | // free old state | 1788 | // free old mode |
1702 | free(old_state); | 1789 | free(old_mode); |
1703 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 1790 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
1704 | } | 1791 | } |
1705 | 1792 | ||
1706 | static struct cmd_results *bar_cmd_mode(int argc, char **argv) { | 1793 | static struct cmd_results *bar_cmd_mode(int argc, char **argv) { |
1707 | struct cmd_results *error = NULL; | 1794 | struct cmd_results *error = NULL; |
1708 | if ((error = checkarg(argc, "mode", EXPECTED_EQUAL_TO, 1))) { | 1795 | if ((error = checkarg(argc, "mode", EXPECTED_AT_LEAST, 1))) { |
1796 | return error; | ||
1797 | } | ||
1798 | if ((error = checkarg(argc, "mode", EXPECTED_LESS_THAN, 3))) { | ||
1709 | return error; | 1799 | return error; |
1710 | } | 1800 | } |
1711 | 1801 | ||
1802 | if (config->reading && argc > 1) { | ||
1803 | return cmd_results_new(CMD_INVALID, "mode", "Unexpected value %s in config mode", argv[1]); | ||
1804 | } | ||
1805 | |||
1712 | const char *mode = argv[0]; | 1806 | const char *mode = argv[0]; |
1713 | char *old_mode = config->current_bar->mode; | 1807 | |
1714 | 1808 | if (config->reading) { | |
1715 | if (strcasecmp("dock", mode) == 0) { | 1809 | return bar_set_mode(config->current_bar, mode); |
1716 | config->current_bar->mode = strdup(mode); | ||
1717 | } else if(strcmp("hide", mode) == 0) { | ||
1718 | config->current_bar->mode = strdup(mode); | ||
1719 | } else if(strcmp("invisible", mode) == 0) { | ||
1720 | config->current_bar->mode = strdup(mode); | ||
1721 | } else { | ||
1722 | return cmd_results_new(CMD_INVALID, "mode", "Invalid value %s", mode); | ||
1723 | } | 1810 | } |
1724 | 1811 | ||
1725 | sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", mode, config->current_bar->id); | 1812 | const char *id; |
1813 | if (argc == 2) { | ||
1814 | id = argv[1]; | ||
1815 | } | ||
1816 | |||
1817 | int i; | ||
1818 | struct bar_config *bar; | ||
1819 | for (i = 0; i < config->bars->length; ++i) { | ||
1820 | bar = config->bars->items[i]; | ||
1821 | if (id && strcmp(id, bar->id) == 0) { | ||
1822 | return bar_set_mode(bar, mode); | ||
1823 | } | ||
1824 | |||
1825 | error = bar_set_mode(bar, mode); | ||
1826 | if (error) { | ||
1827 | return error; | ||
1828 | } | ||
1829 | } | ||
1726 | 1830 | ||
1727 | // free old mode | ||
1728 | free(old_mode); | ||
1729 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 1831 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
1730 | } | 1832 | } |
1731 | 1833 | ||
diff --git a/sway/config.c b/sway/config.c index e86eda53..853a7111 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -701,7 +701,7 @@ struct bar_config *default_bar_config(void) { | |||
701 | bar->bindings = create_list(); | 701 | bar->bindings = create_list(); |
702 | bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p' && sleep 1; done"); | 702 | bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p' && sleep 1; done"); |
703 | bar->swaybar_command = NULL; | 703 | bar->swaybar_command = NULL; |
704 | bar->font = strdup("monospace 10"); | 704 | bar->font = strdup("pango:monospace 10"); |
705 | bar->height = -1; | 705 | bar->height = -1; |
706 | bar->workspace_buttons = true; | 706 | bar->workspace_buttons = true; |
707 | bar->separator_symbol = NULL; | 707 | bar->separator_symbol = NULL; |
diff --git a/sway/focus.c b/sway/focus.c index c1170ca4..cf0ee7f6 100644 --- a/sway/focus.c +++ b/sway/focus.c | |||
@@ -34,7 +34,7 @@ static void update_focus(swayc_t *c) { | |||
34 | // Case where workspace changes | 34 | // Case where workspace changes |
35 | case C_WORKSPACE: | 35 | case C_WORKSPACE: |
36 | if (prev) { | 36 | if (prev) { |
37 | ipc_event_workspace(prev, c); | 37 | ipc_event_workspace(prev, c, "focus"); |
38 | // update visibility of old workspace | 38 | // update visibility of old workspace |
39 | update_visibility(prev); | 39 | update_visibility(prev); |
40 | 40 | ||
@@ -122,11 +122,6 @@ bool set_focused_container(swayc_t *c) { | |||
122 | p = p->parent; | 122 | p = p->parent; |
123 | p->is_focused = false; | 123 | p->is_focused = false; |
124 | } | 124 | } |
125 | // active_ws might have been destroyed by now | ||
126 | // (focus swap away from empty ws = destroy ws) | ||
127 | if (active_ws_child_count == 0) { | ||
128 | active_ws = NULL; | ||
129 | } | ||
130 | 125 | ||
131 | // get new focused view and set focus to it. | 126 | // get new focused view and set focus to it. |
132 | p = get_focused_view(c); | 127 | p = get_focused_view(c); |
@@ -146,7 +141,13 @@ bool set_focused_container(swayc_t *c) { | |||
146 | } | 141 | } |
147 | 142 | ||
148 | if (active_ws != workspace) { | 143 | if (active_ws != workspace) { |
149 | ipc_event_workspace(active_ws, workspace); | 144 | // active_ws might have been destroyed by now |
145 | // (focus swap away from empty ws = destroy ws) | ||
146 | if (active_ws_child_count == 0) { | ||
147 | active_ws = NULL; | ||
148 | } | ||
149 | |||
150 | ipc_event_workspace(active_ws, workspace, "focus"); | ||
150 | } | 151 | } |
151 | return true; | 152 | return true; |
152 | } | 153 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 9dd3e1a5..e161c756 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -43,6 +43,7 @@ void ipc_client_handle_command(struct ipc_client *client); | |||
43 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); | 43 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); |
44 | void ipc_get_workspaces_callback(swayc_t *workspace, void *data); | 44 | void ipc_get_workspaces_callback(swayc_t *workspace, void *data); |
45 | void ipc_get_outputs_callback(swayc_t *container, void *data); | 45 | void ipc_get_outputs_callback(swayc_t *container, void *data); |
46 | json_object *ipc_json_describe_bar_config(struct bar_config *bar); | ||
46 | 47 | ||
47 | void ipc_init(void) { | 48 | void ipc_init(void) { |
48 | ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); | 49 | 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) { | |||
290 | const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); | 291 | const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); |
291 | if (strcmp(event_type, "workspace") == 0) { | 292 | if (strcmp(event_type, "workspace") == 0) { |
292 | client->subscribed_events |= IPC_GET_WORKSPACES; | 293 | client->subscribed_events |= IPC_GET_WORKSPACES; |
293 | } | 294 | } else if (strcmp(event_type, "barconfig_update") == 0) { |
294 | else { | 295 | client->subscribed_events |= IPC_GET_BAR_CONFIG; |
296 | } else { | ||
295 | ipc_send_reply(client, "{\"success\": false}", 18); | 297 | ipc_send_reply(client, "{\"success\": false}", 18); |
296 | ipc_client_disconnect(client); | 298 | ipc_client_disconnect(client); |
297 | json_object_put(request); | 299 | json_object_put(request); |
@@ -397,64 +399,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
397 | ipc_send_reply(client, error, (uint32_t)strlen(error)); | 399 | ipc_send_reply(client, error, (uint32_t)strlen(error)); |
398 | break; | 400 | break; |
399 | } | 401 | } |
400 | json_object *json = json_object_new_object(); | 402 | json_object *json = ipc_json_describe_bar_config(bar); |
401 | json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||
402 | json_object_object_add(json, "tray_output", NULL); | ||
403 | json_object_object_add(json, "mode", json_object_new_string(bar->mode)); | ||
404 | json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); | ||
405 | //json_object_object_add(json, "modifier", json_object_new_string(bar->modifier)); // TODO: Fix modifier | ||
406 | switch (bar->position) { | ||
407 | case DESKTOP_SHELL_PANEL_POSITION_TOP: | ||
408 | json_object_object_add(json, "position", json_object_new_string("top")); | ||
409 | break; | ||
410 | case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: | ||
411 | json_object_object_add(json, "position", json_object_new_string("bottom")); | ||
412 | break; | ||
413 | case DESKTOP_SHELL_PANEL_POSITION_LEFT: | ||
414 | json_object_object_add(json, "position", json_object_new_string("left")); | ||
415 | break; | ||
416 | case DESKTOP_SHELL_PANEL_POSITION_RIGHT: | ||
417 | json_object_object_add(json, "position", json_object_new_string("right")); | ||
418 | break; | ||
419 | } | ||
420 | json_object_object_add(json, "status_command", json_object_new_string(bar->status_command)); | ||
421 | json_object_object_add(json, "font", json_object_new_string(bar->font)); | ||
422 | if (bar->separator_symbol) { | ||
423 | json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); | ||
424 | } | ||
425 | json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); | ||
426 | json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); | ||
427 | json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); | ||
428 | json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); | ||
429 | json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); | ||
430 | |||
431 | json_object *colors = json_object_new_object(); | ||
432 | json_object_object_add(colors, "background", json_object_new_string(bar->colors.background)); | ||
433 | json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline)); | ||
434 | json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator)); | ||
435 | |||
436 | json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border)); | ||
437 | json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg)); | ||
438 | json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text)); | ||
439 | |||
440 | json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border)); | ||
441 | json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg)); | ||
442 | json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text)); | ||
443 | |||
444 | json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border)); | ||
445 | json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg)); | ||
446 | json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text)); | ||
447 | |||
448 | json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||
449 | json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||
450 | json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||
451 | |||
452 | json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border)); | ||
453 | json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg)); | ||
454 | json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text)); | ||
455 | |||
456 | json_object_object_add(json, "colors", colors); | ||
457 | |||
458 | const char *json_string = json_object_to_json_string(json); | 403 | const char *json_string = json_object_to_json_string(json); |
459 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 404 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); |
460 | json_object_put(json); // free | 405 | json_object_put(json); // free |
@@ -551,22 +496,114 @@ void ipc_get_outputs_callback(swayc_t *container, void *data) { | |||
551 | } | 496 | } |
552 | } | 497 | } |
553 | 498 | ||
554 | void ipc_event_workspace(swayc_t *old, swayc_t *new) { | 499 | json_object *ipc_json_describe_bar_config(struct bar_config *bar) { |
500 | if (!sway_assert(bar, "Bar must not be NULL")) { | ||
501 | return NULL; | ||
502 | } | ||
503 | |||
504 | json_object *json = json_object_new_object(); | ||
505 | json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||
506 | json_object_object_add(json, "tray_output", NULL); | ||
507 | json_object_object_add(json, "mode", json_object_new_string(bar->mode)); | ||
508 | json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); | ||
509 | //json_object_object_add(json, "modifier", json_object_new_string(bar->modifier)); // TODO: Fix modifier | ||
510 | switch (bar->position) { | ||
511 | case DESKTOP_SHELL_PANEL_POSITION_TOP: | ||
512 | json_object_object_add(json, "position", json_object_new_string("top")); | ||
513 | break; | ||
514 | case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: | ||
515 | json_object_object_add(json, "position", json_object_new_string("bottom")); | ||
516 | break; | ||
517 | case DESKTOP_SHELL_PANEL_POSITION_LEFT: | ||
518 | json_object_object_add(json, "position", json_object_new_string("left")); | ||
519 | break; | ||
520 | case DESKTOP_SHELL_PANEL_POSITION_RIGHT: | ||
521 | json_object_object_add(json, "position", json_object_new_string("right")); | ||
522 | break; | ||
523 | } | ||
524 | json_object_object_add(json, "status_command", json_object_new_string(bar->status_command)); | ||
525 | json_object_object_add(json, "font", json_object_new_string(bar->font)); | ||
526 | if (bar->separator_symbol) { | ||
527 | json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); | ||
528 | } | ||
529 | json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); | ||
530 | json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); | ||
531 | json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); | ||
532 | json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); | ||
533 | json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); | ||
534 | |||
535 | json_object *colors = json_object_new_object(); | ||
536 | json_object_object_add(colors, "background", json_object_new_string(bar->colors.background)); | ||
537 | json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline)); | ||
538 | json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator)); | ||
539 | |||
540 | json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border)); | ||
541 | json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg)); | ||
542 | json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text)); | ||
543 | |||
544 | json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border)); | ||
545 | json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg)); | ||
546 | json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text)); | ||
547 | |||
548 | json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border)); | ||
549 | json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg)); | ||
550 | json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text)); | ||
551 | |||
552 | json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||
553 | json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||
554 | json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||
555 | |||
556 | json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border)); | ||
557 | json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg)); | ||
558 | json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text)); | ||
559 | |||
560 | json_object_object_add(json, "colors", colors); | ||
561 | |||
562 | return json; | ||
563 | } | ||
564 | |||
565 | void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { | ||
555 | json_object *obj = json_object_new_object(); | 566 | json_object *obj = json_object_new_object(); |
556 | json_object_object_add(obj, "change", json_object_new_string("focus")); | 567 | json_object_object_add(obj, "change", json_object_new_string(change)); |
557 | if (old) { | 568 | if (strcmp("focus", change) == 0) { |
558 | json_object_object_add(obj, "old", ipc_json_describe_workspace(old)); | 569 | if (old) { |
570 | json_object_object_add(obj, "old", ipc_json_describe_workspace(old)); | ||
571 | } else { | ||
572 | json_object_object_add(obj, "old", NULL); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | if (new) { | ||
577 | json_object_object_add(obj, "current", ipc_json_describe_workspace(new)); | ||
559 | } else { | 578 | } else { |
560 | json_object_object_add(obj, "old", NULL); | 579 | json_object_object_add(obj, "current", NULL); |
561 | } | 580 | } |
562 | json_object_object_add(obj, "current", ipc_json_describe_workspace(new)); | 581 | |
563 | const char *json_string = json_object_to_json_string(obj); | 582 | const char *json_string = json_object_to_json_string(obj); |
564 | 583 | ||
565 | for (int i = 0; i < ipc_client_list->length; i++) { | 584 | for (int i = 0; i < ipc_client_list->length; i++) { |
566 | struct ipc_client *client = ipc_client_list->items[i]; | 585 | struct ipc_client *client = ipc_client_list->items[i]; |
567 | if ((client->subscribed_events & IPC_GET_WORKSPACES) == 0) break; | 586 | if ((client->subscribed_events & IPC_GET_WORKSPACES) == 0) { |
587 | continue; | ||
588 | } | ||
568 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 589 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
569 | } | 590 | } |
570 | 591 | ||
571 | json_object_put(obj); // free | 592 | json_object_put(obj); // free |
572 | } | 593 | } |
594 | |||
595 | void ipc_event_barconfig_update(struct bar_config *bar) { | ||
596 | json_object *json = ipc_json_describe_bar_config(bar); | ||
597 | const char *json_string = json_object_to_json_string(json); | ||
598 | int i; | ||
599 | struct ipc_client *client; | ||
600 | for (i = 0; i < ipc_client_list->length; ++i) { | ||
601 | client = ipc_client_list->items[i]; | ||
602 | if ((client->subscribed_events & IPC_GET_BAR_CONFIG) == 0) { | ||
603 | continue; | ||
604 | } | ||
605 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | ||
606 | } | ||
607 | |||
608 | json_object_put(json); // free | ||
609 | } | ||
diff --git a/sway/layout.c b/sway/layout.c index a9e7c7f1..563e9d11 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "workspace.h" | 10 | #include "workspace.h" |
11 | #include "focus.h" | 11 | #include "focus.h" |
12 | #include "output.h" | 12 | #include "output.h" |
13 | #include "ipc-server.h" | ||
13 | 14 | ||
14 | swayc_t root_container; | 15 | swayc_t root_container; |
15 | list_t *scratchpad; | 16 | list_t *scratchpad; |
@@ -312,6 +313,12 @@ void move_container_to(swayc_t* container, swayc_t* destination) { | |||
312 | // reset container geometry | 313 | // reset container geometry |
313 | container->width = container->height = 0; | 314 | container->width = container->height = 0; |
314 | add_child(destination, container); | 315 | add_child(destination, container); |
316 | |||
317 | // If the workspace only has one child after adding one, it | ||
318 | // means that the workspace was just initialized. | ||
319 | if (destination->children->length + destination->floating->length == 1) { | ||
320 | ipc_event_workspace(NULL, destination, "init"); | ||
321 | } | ||
315 | } else { | 322 | } else { |
316 | // reset container geometry | 323 | // reset container geometry |
317 | container->width = container->height = 0; | 324 | container->width = container->height = 0; |
diff --git a/swaybar/main.c b/swaybar/main.c index 88cd1dbe..4323d370 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <sys/select.h> | 7 | #include <sys/select.h> |
8 | #include <sys/wait.h> | ||
8 | #include <errno.h> | 9 | #include <errno.h> |
9 | #include <json-c/json.h> | 10 | #include <json-c/json.h> |
10 | #include <sys/un.h> | 11 | #include <sys/un.h> |
@@ -87,7 +88,7 @@ struct colors colors = { | |||
87 | }, | 88 | }, |
88 | }; | 89 | }; |
89 | 90 | ||
90 | void sway_terminate(void) { | 91 | void swaybar_teardown() { |
91 | window_teardown(window); | 92 | window_teardown(window); |
92 | if (registry) { | 93 | if (registry) { |
93 | registry_teardown(registry); | 94 | registry_teardown(registry); |
@@ -99,16 +100,31 @@ void sway_terminate(void) { | |||
99 | 100 | ||
100 | if (pid) { | 101 | if (pid) { |
101 | // terminate status_command process | 102 | // terminate status_command process |
102 | kill(pid, SIGTERM); | 103 | int ret = kill(pid, SIGTERM); |
104 | if (ret != 0) { | ||
105 | sway_log(L_ERROR, "Unable to terminate status_command [pid: %d]", pid); | ||
106 | } else { | ||
107 | int status; | ||
108 | waitpid(pid, &status, 0); | ||
109 | } | ||
103 | } | 110 | } |
104 | 111 | ||
105 | if (pipefd[0]) { | 112 | if (pipefd[0]) { |
106 | close(pipefd[0]); | 113 | close(pipefd[0]); |
107 | } | 114 | } |
115 | } | ||
116 | |||
108 | 117 | ||
118 | void sway_terminate(void) { | ||
119 | swaybar_teardown(); | ||
109 | exit(EXIT_FAILURE); | 120 | exit(EXIT_FAILURE); |
110 | } | 121 | } |
111 | 122 | ||
123 | void sig_handler(int signal) { | ||
124 | swaybar_teardown(); | ||
125 | exit(0); | ||
126 | } | ||
127 | |||
112 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | 128 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { |
113 | cairo_set_source_rgba(cairo, | 129 | cairo_set_source_rgba(cairo, |
114 | ((color & 0xFF000000) >> 24) / 256.0, | 130 | ((color & 0xFF000000) >> 24) / 256.0, |
@@ -525,14 +541,12 @@ int main(int argc, char **argv) { | |||
525 | line[0] = '\0'; | 541 | line[0] = '\0'; |
526 | } | 542 | } |
527 | 543 | ||
544 | signal(SIGTERM, sig_handler); | ||
545 | |||
528 | poll_for_update(); | 546 | poll_for_update(); |
529 | 547 | ||
530 | window_teardown(window); | 548 | // gracefully shutdown swaybar and status_command |
531 | registry_teardown(registry); | 549 | swaybar_teardown(); |
532 | fclose(command); | ||
533 | // terminate status_command process | ||
534 | kill(pid, SIGTERM); | ||
535 | close(pipefd[0]); | ||
536 | 550 | ||
537 | return 0; | 551 | return 0; |
538 | } | 552 | } |