diff options
-rw-r--r-- | include/ipc.h | 3 | ||||
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | include/sway/ipc-server.h | 1 | ||||
-rw-r--r-- | include/swaybar/bar.h | 37 | ||||
-rw-r--r-- | include/swaybar/config.h | 5 | ||||
-rw-r--r-- | include/swaybar/i3bar.h | 2 | ||||
-rw-r--r-- | include/swaybar/ipc.h | 4 | ||||
-rw-r--r-- | include/swaybar/status_line.h | 3 | ||||
-rw-r--r-- | sway/commands/bar/hidden_state.c | 34 | ||||
-rw-r--r-- | sway/commands/bar/mode.c | 34 | ||||
-rw-r--r-- | sway/config/bar.c | 2 | ||||
-rw-r--r-- | sway/input/keyboard.c | 28 | ||||
-rw-r--r-- | sway/ipc-server.c | 18 | ||||
-rw-r--r-- | sway/sway-bar.5.scd | 16 | ||||
-rw-r--r-- | sway/sway.5.scd | 12 | ||||
-rw-r--r-- | swaybar/bar.c | 102 | ||||
-rw-r--r-- | swaybar/config.c | 4 | ||||
-rw-r--r-- | swaybar/ipc.c | 128 | ||||
-rw-r--r-- | swaybar/main.c | 8 | ||||
-rw-r--r-- | swaybar/render.c | 32 | ||||
-rw-r--r-- | swaybar/status_line.c | 14 |
21 files changed, 358 insertions, 130 deletions
diff --git a/include/ipc.h b/include/ipc.h index a3f60e19..9063b933 100644 --- a/include/ipc.h +++ b/include/ipc.h | |||
@@ -30,6 +30,9 @@ enum ipc_command_type { | |||
30 | IPC_EVENT_BINDING = ((1<<31) | 5), | 30 | IPC_EVENT_BINDING = ((1<<31) | 5), |
31 | IPC_EVENT_SHUTDOWN = ((1<<31) | 6), | 31 | IPC_EVENT_SHUTDOWN = ((1<<31) | 6), |
32 | IPC_EVENT_TICK = ((1<<31) | 7), | 32 | IPC_EVENT_TICK = ((1<<31) | 7), |
33 | |||
34 | // sway-specific event types | ||
35 | IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20), | ||
33 | }; | 36 | }; |
34 | 37 | ||
35 | #endif | 38 | #endif |
diff --git a/include/sway/config.h b/include/sway/config.h index f21ecbb1..be5a00b5 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -191,6 +191,7 @@ struct bar_config { | |||
191 | * In "show" mode, it will always be shown on top of the active workspace. | 191 | * In "show" mode, it will always be shown on top of the active workspace. |
192 | */ | 192 | */ |
193 | char *hidden_state; | 193 | char *hidden_state; |
194 | bool visible_by_modifier; // only relevant in "hide" mode | ||
194 | /** | 195 | /** |
195 | * Id name used to identify the bar through IPC. | 196 | * Id name used to identify the bar through IPC. |
196 | * | 197 | * |
diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index 80180ec4..3c43f74d 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h | |||
@@ -15,6 +15,7 @@ void ipc_event_workspace(struct sway_workspace *old, | |||
15 | struct sway_workspace *new, const char *change); | 15 | struct sway_workspace *new, const char *change); |
16 | void ipc_event_window(struct sway_container *window, const char *change); | 16 | void ipc_event_window(struct sway_container *window, const char *change); |
17 | void ipc_event_barconfig_update(struct bar_config *bar); | 17 | void ipc_event_barconfig_update(struct bar_config *bar); |
18 | void ipc_event_bar_state_update(struct bar_config *bar); | ||
18 | void ipc_event_mode(const char *mode, bool pango); | 19 | void ipc_event_mode(const char *mode, bool pango); |
19 | void ipc_event_shutdown(const char *reason); | 20 | void ipc_event_shutdown(const char *reason); |
20 | void ipc_event_binding(struct sway_binding *binding); | 21 | void ipc_event_binding(struct sway_binding *binding); |
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index de234111..9ff3fe7b 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -37,7 +37,7 @@ enum hotspot_event_handling { | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct swaybar_hotspot { | 39 | struct swaybar_hotspot { |
40 | struct wl_list link; | 40 | struct wl_list link; // swaybar_output::hotspots |
41 | int x, y, width, height; | 41 | int x, y, width, height; |
42 | enum hotspot_event_handling (*callback)(struct swaybar_output *output, | 42 | enum hotspot_event_handling (*callback)(struct swaybar_output *output, |
43 | int x, int y, enum x11_button button, void *data); | 43 | int x, int y, enum x11_button button, void *data); |
@@ -46,6 +46,15 @@ struct swaybar_hotspot { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | struct swaybar { | 48 | struct swaybar { |
49 | char *id; | ||
50 | char *mode; | ||
51 | bool mode_pango_markup; | ||
52 | |||
53 | // only relevant when bar is in "hide" mode | ||
54 | bool visible_by_modifier; | ||
55 | bool visible_by_urgency; | ||
56 | bool visible; | ||
57 | |||
49 | struct wl_display *display; | 58 | struct wl_display *display; |
50 | struct wl_compositor *compositor; | 59 | struct wl_compositor *compositor; |
51 | struct zwlr_layer_shell_v1 *layer_shell; | 60 | struct zwlr_layer_shell_v1 *layer_shell; |
@@ -60,11 +69,11 @@ struct swaybar { | |||
60 | int ipc_event_socketfd; | 69 | int ipc_event_socketfd; |
61 | int ipc_socketfd; | 70 | int ipc_socketfd; |
62 | 71 | ||
63 | struct wl_list outputs; | 72 | struct wl_list outputs; // swaybar_output::link |
64 | }; | 73 | }; |
65 | 74 | ||
66 | struct swaybar_output { | 75 | struct swaybar_output { |
67 | struct wl_list link; | 76 | struct wl_list link; // swaybar::outputs |
68 | struct swaybar *bar; | 77 | struct swaybar *bar; |
69 | struct wl_output *output; | 78 | struct wl_output *output; |
70 | struct zxdg_output_v1 *xdg_output; | 79 | struct zxdg_output_v1 *xdg_output; |
@@ -72,8 +81,8 @@ struct swaybar_output { | |||
72 | struct zwlr_layer_surface_v1 *layer_surface; | 81 | struct zwlr_layer_surface_v1 *layer_surface; |
73 | uint32_t wl_name; | 82 | uint32_t wl_name; |
74 | 83 | ||
75 | struct wl_list workspaces; | 84 | struct wl_list workspaces; // swaybar_workspace::link |
76 | struct wl_list hotspots; | 85 | struct wl_list hotspots; // swaybar_hotspot::link |
77 | 86 | ||
78 | char *name; | 87 | char *name; |
79 | bool focused; | 88 | bool focused; |
@@ -88,7 +97,7 @@ struct swaybar_output { | |||
88 | }; | 97 | }; |
89 | 98 | ||
90 | struct swaybar_workspace { | 99 | struct swaybar_workspace { |
91 | struct wl_list link; | 100 | struct wl_list link; // swaybar_output::workspaces |
92 | int num; | 101 | int num; |
93 | char *name; | 102 | char *name; |
94 | bool focused; | 103 | bool focused; |
@@ -96,10 +105,24 @@ struct swaybar_workspace { | |||
96 | bool urgent; | 105 | bool urgent; |
97 | }; | 106 | }; |
98 | 107 | ||
99 | bool bar_setup(struct swaybar *bar, const char *socket_path, const char *bar_id); | 108 | bool bar_setup(struct swaybar *bar, const char *socket_path); |
100 | void bar_run(struct swaybar *bar); | 109 | void bar_run(struct swaybar *bar); |
101 | void bar_teardown(struct swaybar *bar); | 110 | void bar_teardown(struct swaybar *bar); |
102 | 111 | ||
112 | /* | ||
113 | * Determines whether the bar should be visible and changes it to be so. | ||
114 | * If the current visibility of the bar is the different to what it should be, | ||
115 | * then it adds or destroys the layer surface as required, | ||
116 | * as well as sending the cont or stop signal to the status command. | ||
117 | * If the current visibility of the bar is already what it should be, | ||
118 | * then this function is a no-op, unless moving_layer is true, which occurs | ||
119 | * when the bar changes from "hide" to "dock" mode or vice versa, and the bar | ||
120 | * needs to be destroyed and re-added in order to change its layer. | ||
121 | * | ||
122 | * Returns true if the bar is now visible, otherwise false. | ||
123 | */ | ||
124 | bool determine_bar_visibility(struct swaybar *bar, bool moving_layer); | ||
125 | void free_hotspots(struct wl_list *list); | ||
103 | void free_workspaces(struct wl_list *list); | 126 | void free_workspaces(struct wl_list *list); |
104 | 127 | ||
105 | #endif | 128 | #endif |
diff --git a/include/swaybar/config.h b/include/swaybar/config.h index d0336c27..5d40790a 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h | |||
@@ -13,7 +13,7 @@ struct box_colors { | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | struct config_output { | 15 | struct config_output { |
16 | struct wl_list link; | 16 | struct wl_list link; // swaybar_config::outputs |
17 | char *name; | 17 | char *name; |
18 | size_t index; | 18 | size_t index; |
19 | }; | 19 | }; |
@@ -31,7 +31,8 @@ struct swaybar_config { | |||
31 | char *font; | 31 | char *font; |
32 | char *sep_symbol; | 32 | char *sep_symbol; |
33 | char *mode; | 33 | char *mode; |
34 | bool mode_pango_markup; | 34 | char *hidden_state; |
35 | char *modifier; | ||
35 | bool strip_workspace_numbers; | 36 | bool strip_workspace_numbers; |
36 | bool binding_mode_indicator; | 37 | bool binding_mode_indicator; |
37 | bool wrap_scroll; | 38 | bool wrap_scroll; |
diff --git a/include/swaybar/i3bar.h b/include/swaybar/i3bar.h index 12d9b317..d4a48e07 100644 --- a/include/swaybar/i3bar.h +++ b/include/swaybar/i3bar.h | |||
@@ -5,7 +5,7 @@ | |||
5 | #include "status_line.h" | 5 | #include "status_line.h" |
6 | 6 | ||
7 | struct i3bar_block { | 7 | struct i3bar_block { |
8 | struct wl_list link; | 8 | struct wl_list link; // status_link::blocks |
9 | int ref_count; | 9 | int ref_count; |
10 | char *full_text, *short_text, *align; | 10 | char *full_text, *short_text, *align; |
11 | bool urgent; | 11 | bool urgent; |
diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 8731dac2..d8cd0c76 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h | |||
@@ -3,9 +3,9 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include "swaybar/bar.h" | 4 | #include "swaybar/bar.h" |
5 | 5 | ||
6 | bool ipc_initialize(struct swaybar *bar, const char *bar_id); | 6 | bool ipc_initialize(struct swaybar *bar); |
7 | bool handle_ipc_readable(struct swaybar *bar); | 7 | bool handle_ipc_readable(struct swaybar *bar); |
8 | void ipc_get_workspaces(struct swaybar *bar); | 8 | bool ipc_get_workspaces(struct swaybar *bar); |
9 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); | 9 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); |
10 | void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind); | 10 | void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind); |
11 | 11 | ||
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index ca88b0c5..5e7e8771 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h | |||
@@ -22,6 +22,9 @@ struct status_line { | |||
22 | const char *text; | 22 | const char *text; |
23 | struct wl_list blocks; // i3bar_block::link | 23 | struct wl_list blocks; // i3bar_block::link |
24 | 24 | ||
25 | int stop_signal; | ||
26 | int cont_signal; | ||
27 | |||
25 | bool click_events; | 28 | bool click_events; |
26 | bool clicked; | 29 | bool clicked; |
27 | char *buffer; | 30 | char *buffer; |
diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c index 502ce2c4..28adf6c7 100644 --- a/sway/commands/bar/hidden_state.c +++ b/sway/commands/bar/hidden_state.c | |||
@@ -32,7 +32,7 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, | |||
32 | } | 32 | } |
33 | // free old mode | 33 | // free old mode |
34 | free(old_state); | 34 | free(old_state); |
35 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 35 | return NULL; |
36 | } | 36 | } |
37 | 37 | ||
38 | struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { | 38 | struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { |
@@ -50,24 +50,20 @@ struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { | |||
50 | 50 | ||
51 | const char *state = argv[0]; | 51 | const char *state = argv[0]; |
52 | if (config->reading) { | 52 | if (config->reading) { |
53 | return bar_set_hidden_state(config->current_bar, state); | 53 | error = bar_set_hidden_state(config->current_bar, state); |
54 | } | 54 | } else { |
55 | 55 | const char *id = argc == 2 ? argv[1] : NULL; | |
56 | const char *id = NULL; | 56 | for (int i = 0; i < config->bars->length; ++i) { |
57 | if (argc == 2) { | 57 | struct bar_config *bar = config->bars->items[i]; |
58 | id = argv[1]; | 58 | if (id) { |
59 | } | 59 | if (strcmp(id, bar->id) == 0) { |
60 | struct bar_config *bar; | 60 | error = bar_set_hidden_state(bar, state); |
61 | for (int i = 0; i < config->bars->length; ++i) { | 61 | break; |
62 | bar = config->bars->items[i]; | 62 | } |
63 | if (id && strcmp(id, bar->id) == 0) { | 63 | } else if ((error = bar_set_hidden_state(bar, state))) { |
64 | return bar_set_hidden_state(bar, state); | 64 | break; |
65 | } | 65 | } |
66 | |||
67 | error = bar_set_hidden_state(bar, state); | ||
68 | if (error) { | ||
69 | return error; | ||
70 | } | 66 | } |
71 | } | 67 | } |
72 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 68 | return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); |
73 | } | 69 | } |
diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c index 28e2d77b..dbdd3897 100644 --- a/sway/commands/bar/mode.c +++ b/sway/commands/bar/mode.c | |||
@@ -33,7 +33,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode | |||
33 | 33 | ||
34 | // free old mode | 34 | // free old mode |
35 | free(old_mode); | 35 | free(old_mode); |
36 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 36 | return NULL; |
37 | } | 37 | } |
38 | 38 | ||
39 | struct cmd_results *bar_cmd_mode(int argc, char **argv) { | 39 | struct cmd_results *bar_cmd_mode(int argc, char **argv) { |
@@ -51,24 +51,20 @@ struct cmd_results *bar_cmd_mode(int argc, char **argv) { | |||
51 | 51 | ||
52 | const char *mode = argv[0]; | 52 | const char *mode = argv[0]; |
53 | if (config->reading) { | 53 | if (config->reading) { |
54 | return bar_set_mode(config->current_bar, mode); | 54 | error = bar_set_mode(config->current_bar, mode); |
55 | } | 55 | } else { |
56 | 56 | const char *id = argc == 2 ? argv[1] : NULL; | |
57 | const char *id = NULL; | 57 | for (int i = 0; i < config->bars->length; ++i) { |
58 | if (argc == 2) { | 58 | struct bar_config *bar = config->bars->items[i]; |
59 | id = argv[1]; | 59 | if (id) { |
60 | } | 60 | if (strcmp(id, bar->id) == 0) { |
61 | 61 | error = bar_set_mode(bar, mode); | |
62 | struct bar_config *bar; | 62 | break; |
63 | for (int i = 0; i < config->bars->length; ++i) { | 63 | } |
64 | bar = config->bars->items[i]; | 64 | } else if ((error = bar_set_mode(bar, mode))) { |
65 | if (id && strcmp(id, bar->id) == 0) { | 65 | break; |
66 | return bar_set_mode(bar, mode); | 66 | } |
67 | } | ||
68 | error = bar_set_mode(bar, mode); | ||
69 | if (error) { | ||
70 | return error; | ||
71 | } | 67 | } |
72 | } | 68 | } |
73 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 69 | return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); |
74 | } | 70 | } |
diff --git a/sway/config/bar.c b/sway/config/bar.c index 5726e95b..8b88642e 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "stringop.h" | 16 | #include "stringop.h" |
17 | #include "list.h" | 17 | #include "list.h" |
18 | #include "log.h" | 18 | #include "log.h" |
19 | #include "util.h" | ||
19 | 20 | ||
20 | static void terminate_swaybar(pid_t pid) { | 21 | static void terminate_swaybar(pid_t pid) { |
21 | wlr_log(WLR_DEBUG, "Terminating swaybar %d", pid); | 22 | wlr_log(WLR_DEBUG, "Terminating swaybar %d", pid); |
@@ -101,6 +102,7 @@ struct bar_config *default_bar_config(void) { | |||
101 | bar->binding_mode_indicator = true; | 102 | bar->binding_mode_indicator = true; |
102 | bar->verbose = false; | 103 | bar->verbose = false; |
103 | bar->pid = 0; | 104 | bar->pid = 0; |
105 | bar->modifier = get_modifier_mask_by_name("Mod4"); | ||
104 | if (!(bar->mode = strdup("dock"))) { | 106 | if (!(bar->mode = strdup("dock"))) { |
105 | goto cleanup; | 107 | goto cleanup; |
106 | } | 108 | } |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index fb1fe7b5..2c8b41cd 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "sway/input/input-manager.h" | 9 | #include "sway/input/input-manager.h" |
10 | #include "sway/input/keyboard.h" | 10 | #include "sway/input/keyboard.h" |
11 | #include "sway/input/seat.h" | 11 | #include "sway/input/seat.h" |
12 | #include "sway/ipc-server.h" | ||
12 | #include "log.h" | 13 | #include "log.h" |
13 | 14 | ||
14 | /** | 15 | /** |
@@ -66,10 +67,10 @@ static void update_shortcut_state(struct sway_shortcut_state *state, | |||
66 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; | 67 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; |
67 | state->last_raw_modifiers = raw_modifiers; | 68 | state->last_raw_modifiers = raw_modifiers; |
68 | 69 | ||
69 | if (last_key_was_a_modifier && state->last_keycode) { | 70 | if (last_key_was_a_modifier && state->last_keycode) { |
70 | // Last pressed key before this one was a modifier | 71 | // Last pressed key before this one was a modifier |
71 | state_erase_key(state, state->last_keycode); | 72 | state_erase_key(state, state->last_keycode); |
72 | } | 73 | } |
73 | 74 | ||
74 | if (event->state == WLR_KEY_PRESSED) { | 75 | if (event->state == WLR_KEY_PRESSED) { |
75 | // Add current key to set; there may be duplicates | 76 | // Add current key to set; there may be duplicates |
@@ -235,7 +236,6 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { | |||
235 | code_modifiers); | 236 | code_modifiers); |
236 | } | 237 | } |
237 | 238 | ||
238 | |||
239 | bool handled = false; | 239 | bool handled = false; |
240 | 240 | ||
241 | // Identify active release binding | 241 | // Identify active release binding |
@@ -337,6 +337,19 @@ static int handle_keyboard_repeat(void *data) { | |||
337 | return 0; | 337 | return 0; |
338 | } | 338 | } |
339 | 339 | ||
340 | static void determine_bar_visibility(uint32_t modifiers) { | ||
341 | for (int i = 0; i < config->bars->length; ++i) { | ||
342 | struct bar_config *bar = config->bars->items[i]; | ||
343 | if (strcmp(bar->mode, bar->hidden_state) == 0) { // both are "hide" | ||
344 | bool should_be_visible = (~modifiers & bar->modifier) == 0; | ||
345 | if (bar->visible_by_modifier != should_be_visible) { | ||
346 | bar->visible_by_modifier = should_be_visible; | ||
347 | ipc_event_bar_state_update(bar); | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
340 | static void handle_keyboard_modifiers(struct wl_listener *listener, | 353 | static void handle_keyboard_modifiers(struct wl_listener *listener, |
341 | void *data) { | 354 | void *data) { |
342 | struct sway_keyboard *keyboard = | 355 | struct sway_keyboard *keyboard = |
@@ -346,6 +359,9 @@ static void handle_keyboard_modifiers(struct wl_listener *listener, | |||
346 | keyboard->seat_device->input_device->wlr_device; | 359 | keyboard->seat_device->input_device->wlr_device; |
347 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 360 | wlr_seat_set_keyboard(wlr_seat, wlr_device); |
348 | wlr_seat_keyboard_notify_modifiers(wlr_seat, &wlr_device->keyboard->modifiers); | 361 | wlr_seat_keyboard_notify_modifiers(wlr_seat, &wlr_device->keyboard->modifiers); |
362 | |||
363 | uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); | ||
364 | determine_bar_visibility(modifiers); | ||
349 | } | 365 | } |
350 | 366 | ||
351 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | 367 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, |
@@ -464,7 +480,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
464 | keyboard->keyboard_key.notify = handle_keyboard_key; | 480 | keyboard->keyboard_key.notify = handle_keyboard_key; |
465 | 481 | ||
466 | wl_list_remove(&keyboard->keyboard_modifiers.link); | 482 | wl_list_remove(&keyboard->keyboard_modifiers.link); |
467 | wl_signal_add( &wlr_device->keyboard->events.modifiers, | 483 | wl_signal_add(&wlr_device->keyboard->events.modifiers, |
468 | &keyboard->keyboard_modifiers); | 484 | &keyboard->keyboard_modifiers); |
469 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; | 485 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; |
470 | } | 486 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 2d915502..63c95503 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -349,6 +349,22 @@ void ipc_event_barconfig_update(struct bar_config *bar) { | |||
349 | json_object_put(json); | 349 | json_object_put(json); |
350 | } | 350 | } |
351 | 351 | ||
352 | void ipc_event_bar_state_update(struct bar_config *bar) { | ||
353 | if (!ipc_has_event_listeners(IPC_EVENT_BAR_STATE_UPDATE)) { | ||
354 | return; | ||
355 | } | ||
356 | wlr_log(WLR_DEBUG, "Sending bar_state_update event"); | ||
357 | |||
358 | json_object *json = json_object_new_object(); | ||
359 | json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||
360 | json_object_object_add(json, "visible_by_modifier", | ||
361 | json_object_new_boolean(bar->visible_by_modifier)); | ||
362 | |||
363 | const char *json_string = json_object_to_json_string(json); | ||
364 | ipc_send_event(json_string, IPC_EVENT_BAR_STATE_UPDATE); | ||
365 | json_object_put(json); | ||
366 | } | ||
367 | |||
352 | void ipc_event_mode(const char *mode, bool pango) { | 368 | void ipc_event_mode(const char *mode, bool pango) { |
353 | if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { | 369 | if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { |
354 | return; | 370 | return; |
@@ -651,6 +667,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
651 | client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE); | 667 | client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE); |
652 | } else if (strcmp(event_type, "barconfig_update") == 0) { | 668 | } else if (strcmp(event_type, "barconfig_update") == 0) { |
653 | client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); | 669 | client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); |
670 | } else if (strcmp(event_type, "bar_state_update") == 0) { | ||
671 | client->subscribed_events |= event_mask(IPC_EVENT_BAR_STATE_UPDATE); | ||
654 | } else if (strcmp(event_type, "mode") == 0) { | 672 | } else if (strcmp(event_type, "mode") == 0) { |
655 | client->subscribed_events |= event_mask(IPC_EVENT_MODE); | 673 | client->subscribed_events |= event_mask(IPC_EVENT_MODE); |
656 | } else if (strcmp(event_type, "shutdown") == 0) { | 674 | } else if (strcmp(event_type, "shutdown") == 0) { |
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 6729c9ac..873741c0 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd | |||
@@ -65,6 +65,22 @@ Sway allows configuring swaybar in the sway configuration file. | |||
65 | is given, when mouse button _n_ has been released). To disable the default | 65 | is given, when mouse button _n_ has been released). To disable the default |
66 | behavior for a button, use the command _nop_. | 66 | behavior for a button, use the command _nop_. |
67 | 67 | ||
68 | *mode* dock|hide|invisible | ||
69 | Specifies the visibility of the bar. In _dock_ mode, it is permanently | ||
70 | visible at one edge of the screen. In _hide_ mode, it is hidden unless the | ||
71 | modifier key is pressed, though this behaviour depends on the hidden state. | ||
72 | In _invisible_ mode, it is permanently hidden. Default is _dock_. | ||
73 | |||
74 | *hidden\_state* hide|show | ||
75 | Specifies the behaviour of the bar when it is in _hide_ mode. When the | ||
76 | hidden state is _hide_, then it is normally hidden, and only unhidden by | ||
77 | pressing the modifier key or in case of urgency hints. When the hidden | ||
78 | state is _show_, then it is permanently visible, drawn on top of the | ||
79 | currently visible workspace. Default is _hide_. | ||
80 | |||
81 | *modifier* <Modifier>|none | ||
82 | Specifies the modifier key that shows a hidden bar. Default is _Mod4_. | ||
83 | |||
68 | ## TRAY | 84 | ## TRAY |
69 | 85 | ||
70 | Swaybar provides a system tray where third-party applications may place icons. | 86 | Swaybar provides a system tray where third-party applications may place icons. |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 2e1d13a8..67cc1cb1 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -614,6 +614,18 @@ match any output by using the output name "\*". | |||
614 | *workspace\_layout* default|stacking|tabbed | 614 | *workspace\_layout* default|stacking|tabbed |
615 | Specifies the initial layout for new workspaces. | 615 | Specifies the initial layout for new workspaces. |
616 | 616 | ||
617 | # BAR CONTROL | ||
618 | |||
619 | *bar hidden\_state* hide|show|toggle [<bar\_id>] | ||
620 | Sets the hidden state of the bar (see *sway-bar*(5)), either individually, | ||
621 | by specifying a bar id, or if none is given, for all bar instances. | ||
622 | _toggle_ switches between _hide_ and _show_. | ||
623 | |||
624 | *bar mode* dock|hide|invisible|toggle [<bar\_id>] | ||
625 | Sets the mode of the bar (see *sway-bar*(5)), either individually, | ||
626 | by specifying a bar id, or if none is given, for all bar instances. | ||
627 | _toggle_ switches between _dock_ and _hide_. | ||
628 | |||
617 | # CRITERIA | 629 | # CRITERIA |
618 | 630 | ||
619 | A criteria is a string in the form of, for example: | 631 | A criteria is a string in the form of, for example: |
diff --git a/swaybar/bar.c b/swaybar/bar.c index 5b7fea71..9f72c94c 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -32,9 +32,21 @@ | |||
32 | 32 | ||
33 | static void bar_init(struct swaybar *bar) { | 33 | static void bar_init(struct swaybar *bar) { |
34 | bar->config = init_config(); | 34 | bar->config = init_config(); |
35 | bar->visible = true; | ||
35 | wl_list_init(&bar->outputs); | 36 | wl_list_init(&bar->outputs); |
36 | } | 37 | } |
37 | 38 | ||
39 | void free_hotspots(struct wl_list *list) { | ||
40 | struct swaybar_hotspot *hotspot, *tmp; | ||
41 | wl_list_for_each_safe(hotspot, tmp, list, link) { | ||
42 | wl_list_remove(&hotspot->link); | ||
43 | if (hotspot->destroy) { | ||
44 | hotspot->destroy(hotspot->data); | ||
45 | } | ||
46 | free(hotspot); | ||
47 | } | ||
48 | } | ||
49 | |||
38 | void free_workspaces(struct wl_list *list) { | 50 | void free_workspaces(struct wl_list *list) { |
39 | struct swaybar_workspace *ws, *tmp; | 51 | struct swaybar_workspace *ws, *tmp; |
40 | wl_list_for_each_safe(ws, tmp, list, link) { | 52 | wl_list_for_each_safe(ws, tmp, list, link) { |
@@ -59,14 +71,8 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
59 | wl_output_destroy(output->output); | 71 | wl_output_destroy(output->output); |
60 | destroy_buffer(&output->buffers[0]); | 72 | destroy_buffer(&output->buffers[0]); |
61 | destroy_buffer(&output->buffers[1]); | 73 | destroy_buffer(&output->buffers[1]); |
74 | free_hotspots(&output->hotspots); | ||
62 | free_workspaces(&output->workspaces); | 75 | free_workspaces(&output->workspaces); |
63 | struct swaybar_hotspot *hotspot, *hotspot_tmp; | ||
64 | wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) { | ||
65 | if (hotspot->destroy) { | ||
66 | hotspot->destroy(hotspot->data); | ||
67 | } | ||
68 | free(hotspot); | ||
69 | } | ||
70 | wl_list_remove(&output->link); | 76 | wl_list_remove(&output->link); |
71 | free(output->name); | 77 | free(output->name); |
72 | free(output); | 78 | free(output); |
@@ -75,9 +81,7 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
75 | static void set_output_dirty(struct swaybar_output *output) { | 81 | static void set_output_dirty(struct swaybar_output *output) { |
76 | if (output->frame_scheduled) { | 82 | if (output->frame_scheduled) { |
77 | output->dirty = true; | 83 | output->dirty = true; |
78 | return; | 84 | } else if (output->surface) { |
79 | } | ||
80 | if (output->surface) { | ||
81 | render_frame(output); | 85 | render_frame(output); |
82 | } | 86 | } |
83 | } | 87 | } |
@@ -335,21 +339,68 @@ const struct wl_seat_listener seat_listener = { | |||
335 | }; | 339 | }; |
336 | 340 | ||
337 | static void add_layer_surface(struct swaybar_output *output) { | 341 | static void add_layer_surface(struct swaybar_output *output) { |
338 | if (output->surface != NULL) { | 342 | if (output->layer_surface) { |
339 | return; | 343 | return; |
340 | } | 344 | } |
341 | struct swaybar *bar = output->bar; | 345 | struct swaybar *bar = output->bar; |
342 | 346 | ||
343 | output->surface = wl_compositor_create_surface(bar->compositor); | 347 | struct swaybar_config *config = bar->config; |
344 | assert(output->surface); | 348 | bool hidden = strcmp(config->mode, "hide") == 0; |
345 | output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( | 349 | output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( |
346 | bar->layer_shell, output->surface, output->output, | 350 | bar->layer_shell, output->surface, output->output, |
351 | hidden ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : | ||
347 | ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); | 352 | ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); |
348 | assert(output->layer_surface); | 353 | assert(output->layer_surface); |
349 | zwlr_layer_surface_v1_add_listener(output->layer_surface, | 354 | zwlr_layer_surface_v1_add_listener(output->layer_surface, |
350 | &layer_surface_listener, output); | 355 | &layer_surface_listener, output); |
351 | zwlr_layer_surface_v1_set_anchor(output->layer_surface, | 356 | |
352 | bar->config->position); | 357 | zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position); |
358 | if (hidden) { | ||
359 | zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | static void destroy_layer_surface(struct swaybar_output *output) { | ||
364 | if (!output->layer_surface) { | ||
365 | return; | ||
366 | } | ||
367 | zwlr_layer_surface_v1_destroy(output->layer_surface); | ||
368 | wl_surface_attach(output->surface, NULL, 0, 0); // detach buffer | ||
369 | output->layer_surface = NULL; | ||
370 | output->width = 0; | ||
371 | output->frame_scheduled = false; | ||
372 | } | ||
373 | |||
374 | bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) { | ||
375 | struct swaybar_config *config = bar->config; | ||
376 | bool visible = !(strcmp(config->mode, "invisible") == 0 || | ||
377 | (strcmp(config->mode, config->hidden_state) == 0 // both "hide" | ||
378 | && !bar->visible_by_modifier && !bar->visible_by_urgency)); | ||
379 | |||
380 | struct swaybar_output *output; | ||
381 | if (visible == bar->visible) { | ||
382 | if (visible && moving_layer) { | ||
383 | // need to destroy layer surface to move to a different layer | ||
384 | wl_list_for_each(output, &bar->outputs, link) { | ||
385 | destroy_layer_surface(output); | ||
386 | add_layer_surface(output); | ||
387 | } | ||
388 | } | ||
389 | } else { | ||
390 | bar->visible = visible; | ||
391 | wl_list_for_each(output, &bar->outputs, link) { | ||
392 | if (visible) { | ||
393 | add_layer_surface(output); | ||
394 | } else { | ||
395 | destroy_layer_surface(output); | ||
396 | } | ||
397 | } | ||
398 | wlr_log(WLR_DEBUG, "Sending %s signal to status command", | ||
399 | visible ? "cont" : "stop"); | ||
400 | kill(bar->status->pid, | ||
401 | visible ? bar->status->cont_signal : bar->status->stop_signal); | ||
402 | } | ||
403 | return visible; | ||
353 | } | 404 | } |
354 | 405 | ||
355 | static bool bar_uses_output(struct swaybar *bar, const char *name) { | 406 | static bool bar_uses_output(struct swaybar *bar, const char *name) { |
@@ -420,8 +471,11 @@ static void xdg_output_handle_done(void *data, | |||
420 | wl_list_remove(&output->link); | 471 | wl_list_remove(&output->link); |
421 | wl_list_insert(&bar->outputs, &output->link); | 472 | wl_list_insert(&bar->outputs, &output->link); |
422 | 473 | ||
423 | add_layer_surface(output); | 474 | output->surface = wl_compositor_create_surface(bar->compositor); |
424 | set_output_dirty(output); | 475 | assert(output->surface); |
476 | if (bar->visible) { | ||
477 | add_layer_surface(output); | ||
478 | } | ||
425 | } | 479 | } |
426 | } | 480 | } |
427 | 481 | ||
@@ -517,14 +571,13 @@ static void set_bar_dirty(struct swaybar *bar) { | |||
517 | } | 571 | } |
518 | } | 572 | } |
519 | 573 | ||
520 | bool bar_setup(struct swaybar *bar, | 574 | bool bar_setup(struct swaybar *bar, const char *socket_path) { |
521 | const char *socket_path, const char *bar_id) { | ||
522 | bar_init(bar); | 575 | bar_init(bar); |
523 | init_event_loop(); | 576 | init_event_loop(); |
524 | 577 | ||
525 | bar->ipc_socketfd = ipc_open_socket(socket_path); | 578 | bar->ipc_socketfd = ipc_open_socket(socket_path); |
526 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); | 579 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); |
527 | if (!ipc_initialize(bar, bar_id)) { | 580 | if (!ipc_initialize(bar)) { |
528 | return false; | 581 | return false; |
529 | } | 582 | } |
530 | if (bar->config->status_command) { | 583 | if (bar->config->status_command) { |
@@ -565,8 +618,11 @@ bool bar_setup(struct swaybar *bar, | |||
565 | pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); | 618 | pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); |
566 | assert(pointer->cursor_surface); | 619 | assert(pointer->cursor_surface); |
567 | 620 | ||
568 | ipc_get_workspaces(bar); | 621 | if (bar->config->workspace_buttons) { |
569 | set_bar_dirty(bar); | 622 | if (ipc_get_workspaces(bar)) { |
623 | set_bar_dirty(bar); | ||
624 | } | ||
625 | } | ||
570 | return true; | 626 | return true; |
571 | } | 627 | } |
572 | 628 | ||
@@ -625,4 +681,6 @@ void bar_teardown(struct swaybar *bar) { | |||
625 | if (bar->status) { | 681 | if (bar->status) { |
626 | status_line_free(bar->status); | 682 | status_line_free(bar->status); |
627 | } | 683 | } |
684 | free(bar->id); | ||
685 | free(bar->mode); | ||
628 | } | 686 | } |
diff --git a/swaybar/config.c b/swaybar/config.c index 09d40c24..eafb0b69 100644 --- a/swaybar/config.c +++ b/swaybar/config.c | |||
@@ -30,7 +30,8 @@ struct swaybar_config *init_config(void) { | |||
30 | config->pango_markup = false; | 30 | config->pango_markup = false; |
31 | config->position = parse_position("bottom"); | 31 | config->position = parse_position("bottom"); |
32 | config->font = strdup("monospace 10"); | 32 | config->font = strdup("monospace 10"); |
33 | config->mode = NULL; | 33 | config->mode = strdup("dock"); |
34 | config->hidden_state = strdup("hide"); | ||
34 | config->sep_symbol = NULL; | 35 | config->sep_symbol = NULL; |
35 | config->strip_workspace_numbers = false; | 36 | config->strip_workspace_numbers = false; |
36 | config->binding_mode_indicator = true; | 37 | config->binding_mode_indicator = true; |
@@ -84,6 +85,7 @@ void free_config(struct swaybar_config *config) { | |||
84 | free(config->status_command); | 85 | free(config->status_command); |
85 | free(config->font); | 86 | free(config->font); |
86 | free(config->mode); | 87 | free(config->mode); |
88 | free(config->hidden_state); | ||
87 | free(config->sep_symbol); | 89 | free(config->sep_symbol); |
88 | for (int i = 0; i < config->bindings->length; i++) { | 90 | for (int i = 0; i < config->bindings->length; i++) { |
89 | struct swaybar_binding *binding = config->bindings->items[i]; | 91 | struct swaybar_binding *binding = config->bindings->items[i]; |
diff --git a/swaybar/ipc.c b/swaybar/ipc.c index a67814c1..e1b30b52 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c | |||
@@ -152,12 +152,12 @@ static bool ipc_parse_config( | |||
152 | json_object_put(bar_config); | 152 | json_object_put(bar_config); |
153 | return false; | 153 | return false; |
154 | } | 154 | } |
155 | json_object *markup, *mode, *hidden_bar, *position, *status_command; | 155 | json_object *markup, *mode, *hidden_state, *position, *status_command; |
156 | json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; | 156 | json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; |
157 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; | 157 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; |
158 | json_object *bindings; | 158 | json_object *bindings; |
159 | json_object_object_get_ex(bar_config, "mode", &mode); | 159 | json_object_object_get_ex(bar_config, "mode", &mode); |
160 | json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); | 160 | json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); |
161 | json_object_object_get_ex(bar_config, "position", &position); | 161 | json_object_object_get_ex(bar_config, "position", &position); |
162 | json_object_object_get_ex(bar_config, "status_command", &status_command); | 162 | json_object_object_get_ex(bar_config, "status_command", &status_command); |
163 | json_object_object_get_ex(bar_config, "font", &font); | 163 | json_object_object_get_ex(bar_config, "font", &font); |
@@ -220,6 +220,14 @@ static bool ipc_parse_config( | |||
220 | list_add(config->bindings, binding); | 220 | list_add(config->bindings, binding); |
221 | } | 221 | } |
222 | } | 222 | } |
223 | if (hidden_state) { | ||
224 | free(config->hidden_state); | ||
225 | config->hidden_state = strdup(json_object_get_string(hidden_state)); | ||
226 | } | ||
227 | if (mode) { | ||
228 | free(config->mode); | ||
229 | config->mode = strdup(json_object_get_string(mode)); | ||
230 | } | ||
223 | 231 | ||
224 | struct config_output *output, *tmp; | 232 | struct config_output *output, *tmp; |
225 | wl_list_for_each_safe(output, tmp, &config->outputs, link) { | 233 | wl_list_for_each_safe(output, tmp, &config->outputs, link) { |
@@ -254,7 +262,7 @@ static bool ipc_parse_config( | |||
254 | return true; | 262 | return true; |
255 | } | 263 | } |
256 | 264 | ||
257 | void ipc_get_workspaces(struct swaybar *bar) { | 265 | bool ipc_get_workspaces(struct swaybar *bar) { |
258 | struct swaybar_output *output; | 266 | struct swaybar_output *output; |
259 | wl_list_for_each(output, &bar->outputs, link) { | 267 | wl_list_for_each(output, &bar->outputs, link) { |
260 | free_workspaces(&output->workspaces); | 268 | free_workspaces(&output->workspaces); |
@@ -266,8 +274,10 @@ void ipc_get_workspaces(struct swaybar *bar) { | |||
266 | json_object *results = json_tokener_parse(res); | 274 | json_object *results = json_tokener_parse(res); |
267 | if (!results) { | 275 | if (!results) { |
268 | free(res); | 276 | free(res); |
269 | return; | 277 | return false; |
270 | } | 278 | } |
279 | |||
280 | bar->visible_by_urgency = false; | ||
271 | size_t length = json_object_array_length(results); | 281 | size_t length = json_object_array_length(results); |
272 | json_object *ws_json; | 282 | json_object *ws_json; |
273 | json_object *num, *name, *visible, *focused, *out, *urgent; | 283 | json_object *num, *name, *visible, *focused, *out, *urgent; |
@@ -294,12 +304,16 @@ void ipc_get_workspaces(struct swaybar *bar) { | |||
294 | output->focused = true; | 304 | output->focused = true; |
295 | } | 305 | } |
296 | ws->urgent = json_object_get_boolean(urgent); | 306 | ws->urgent = json_object_get_boolean(urgent); |
307 | if (ws->urgent) { | ||
308 | bar->visible_by_urgency = true; | ||
309 | } | ||
297 | wl_list_insert(&output->workspaces, &ws->link); | 310 | wl_list_insert(&output->workspaces, &ws->link); |
298 | } | 311 | } |
299 | } | 312 | } |
300 | } | 313 | } |
301 | json_object_put(results); | 314 | json_object_put(results); |
302 | free(res); | 315 | free(res); |
316 | return determine_bar_visibility(bar, false); | ||
303 | } | 317 | } |
304 | 318 | ||
305 | static void ipc_get_outputs(struct swaybar *bar) { | 319 | static void ipc_get_outputs(struct swaybar *bar) { |
@@ -345,10 +359,10 @@ void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) { | |||
345 | IPC_COMMAND, bind->command, &len)); | 359 | IPC_COMMAND, bind->command, &len)); |
346 | } | 360 | } |
347 | 361 | ||
348 | bool ipc_initialize(struct swaybar *bar, const char *bar_id) { | 362 | bool ipc_initialize(struct swaybar *bar) { |
349 | uint32_t len = strlen(bar_id); | 363 | uint32_t len = strlen(bar->id); |
350 | char *res = ipc_single_command(bar->ipc_socketfd, | 364 | char *res = ipc_single_command(bar->ipc_socketfd, |
351 | IPC_GET_BAR_CONFIG, bar_id, &len); | 365 | IPC_GET_BAR_CONFIG, bar->id, &len); |
352 | if (!ipc_parse_config(bar->config, res)) { | 366 | if (!ipc_parse_config(bar->config, res)) { |
353 | free(res); | 367 | free(res); |
354 | return false; | 368 | return false; |
@@ -356,56 +370,108 @@ bool ipc_initialize(struct swaybar *bar, const char *bar_id) { | |||
356 | free(res); | 370 | free(res); |
357 | ipc_get_outputs(bar); | 371 | ipc_get_outputs(bar); |
358 | 372 | ||
359 | const char *subscribe = "[ \"workspace\", \"mode\" ]"; | 373 | struct swaybar_config *config = bar->config; |
360 | len = strlen(subscribe); | 374 | char subscribe[128]; // suitably large buffer |
375 | len = snprintf(subscribe, 128, | ||
376 | "[ \"barconfig_update\" , \"bar_state_update\" %s %s ]", | ||
377 | config->binding_mode_indicator ? ", \"mode\"" : "", | ||
378 | config->workspace_buttons ? ", \"workspace\"" : ""); | ||
361 | free(ipc_single_command(bar->ipc_event_socketfd, | 379 | free(ipc_single_command(bar->ipc_event_socketfd, |
362 | IPC_SUBSCRIBE, subscribe, &len)); | 380 | IPC_SUBSCRIBE, subscribe, &len)); |
363 | return true; | 381 | return true; |
364 | } | 382 | } |
365 | 383 | ||
384 | static bool handle_bar_state_update(struct swaybar *bar, json_object *event) { | ||
385 | json_object *json_id; | ||
386 | json_object_object_get_ex(event, "id", &json_id); | ||
387 | const char *id = json_object_get_string(json_id); | ||
388 | if (strcmp(id, bar->id) != 0) { | ||
389 | return false; | ||
390 | } | ||
391 | |||
392 | json_object *visible_by_modifier; | ||
393 | json_object_object_get_ex(event, "visible_by_modifier", &visible_by_modifier); | ||
394 | bar->visible_by_modifier = json_object_get_boolean(visible_by_modifier); | ||
395 | return determine_bar_visibility(bar, false); | ||
396 | } | ||
397 | |||
398 | static bool handle_barconfig_update(struct swaybar *bar, | ||
399 | json_object *json_config) { | ||
400 | json_object *json_id; | ||
401 | json_object_object_get_ex(json_config, "id", &json_id); | ||
402 | const char *id = json_object_get_string(json_id); | ||
403 | if (strcmp(id, bar->id) != 0) { | ||
404 | return false; | ||
405 | } | ||
406 | |||
407 | struct swaybar_config *config = bar->config; | ||
408 | |||
409 | json_object *json_state; | ||
410 | json_object_object_get_ex(json_config, "hidden_state", &json_state); | ||
411 | const char *new_state = json_object_get_string(json_state); | ||
412 | char *old_state = config->hidden_state; | ||
413 | if (strcmp(new_state, old_state) != 0) { | ||
414 | wlr_log(WLR_DEBUG, "Changing bar hidden state to %s", new_state); | ||
415 | free(old_state); | ||
416 | config->hidden_state = strdup(new_state); | ||
417 | return determine_bar_visibility(bar, false); | ||
418 | } | ||
419 | |||
420 | free(config->mode); | ||
421 | json_object *json_mode; | ||
422 | json_object_object_get_ex(json_config, "mode", &json_mode); | ||
423 | config->mode = strdup(json_object_get_string(json_mode)); | ||
424 | wlr_log(WLR_DEBUG, "Changing bar mode to %s", config->mode); | ||
425 | |||
426 | return determine_bar_visibility(bar, true); | ||
427 | } | ||
428 | |||
366 | bool handle_ipc_readable(struct swaybar *bar) { | 429 | bool handle_ipc_readable(struct swaybar *bar) { |
367 | struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); | 430 | struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); |
368 | if (!resp) { | 431 | if (!resp) { |
369 | return false; | 432 | return false; |
370 | } | 433 | } |
434 | |||
435 | json_object *result = json_tokener_parse(resp->payload); | ||
436 | if (!result) { | ||
437 | wlr_log(WLR_ERROR, "failed to parse payload as json"); | ||
438 | free_ipc_response(resp); | ||
439 | return false; | ||
440 | } | ||
441 | |||
442 | bool bar_is_dirty = true; | ||
371 | switch (resp->type) { | 443 | switch (resp->type) { |
372 | case IPC_EVENT_WORKSPACE: | 444 | case IPC_EVENT_WORKSPACE: |
373 | ipc_get_workspaces(bar); | 445 | bar_is_dirty = ipc_get_workspaces(bar); |
374 | break; | 446 | break; |
375 | case IPC_EVENT_MODE: { | 447 | case IPC_EVENT_MODE: { |
376 | json_object *result = json_tokener_parse(resp->payload); | ||
377 | if (!result) { | ||
378 | free_ipc_response(resp); | ||
379 | wlr_log(WLR_ERROR, "failed to parse payload as json"); | ||
380 | return false; | ||
381 | } | ||
382 | json_object *json_change, *json_pango_markup; | 448 | json_object *json_change, *json_pango_markup; |
383 | if (json_object_object_get_ex(result, "change", &json_change)) { | 449 | if (json_object_object_get_ex(result, "change", &json_change)) { |
384 | const char *change = json_object_get_string(json_change); | 450 | const char *change = json_object_get_string(json_change); |
385 | free(bar->config->mode); | 451 | free(bar->mode); |
386 | if (strcmp(change, "default") == 0) { | 452 | bar->mode = strcmp(change, "default") != 0 ? strdup(change) : NULL; |
387 | bar->config->mode = NULL; | ||
388 | } else { | ||
389 | bar->config->mode = strdup(change); | ||
390 | } | ||
391 | } else { | 453 | } else { |
392 | wlr_log(WLR_ERROR, "failed to parse response"); | 454 | wlr_log(WLR_ERROR, "failed to parse response"); |
393 | json_object_put(result); | 455 | bar_is_dirty = false; |
394 | free_ipc_response(resp); | 456 | break; |
395 | return false; | ||
396 | } | 457 | } |
397 | if (json_object_object_get_ex(result, | 458 | if (json_object_object_get_ex(result, |
398 | "pango_markup", &json_pango_markup)) { | 459 | "pango_markup", &json_pango_markup)) { |
399 | bar->config->mode_pango_markup = json_object_get_boolean( | 460 | bar->mode_pango_markup = json_object_get_boolean(json_pango_markup); |
400 | json_pango_markup); | ||
401 | } | 461 | } |
402 | json_object_put(result); | ||
403 | break; | 462 | break; |
404 | } | 463 | } |
464 | case IPC_EVENT_BARCONFIG_UPDATE: | ||
465 | bar_is_dirty = handle_barconfig_update(bar, result); | ||
466 | break; | ||
467 | case IPC_EVENT_BAR_STATE_UPDATE: | ||
468 | bar_is_dirty = handle_bar_state_update(bar, result); | ||
469 | break; | ||
405 | default: | 470 | default: |
406 | free_ipc_response(resp); | 471 | bar_is_dirty = false; |
407 | return false; | 472 | break; |
408 | } | 473 | } |
474 | json_object_put(result); | ||
409 | free_ipc_response(resp); | 475 | free_ipc_response(resp); |
410 | return true; | 476 | return bar_is_dirty; |
411 | } | 477 | } |
diff --git a/swaybar/main.c b/swaybar/main.c index db204f4a..2672abef 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -22,7 +22,6 @@ void sway_terminate(int code) { | |||
22 | 22 | ||
23 | int main(int argc, char **argv) { | 23 | int main(int argc, char **argv) { |
24 | char *socket_path = NULL; | 24 | char *socket_path = NULL; |
25 | char *bar_id = NULL; | ||
26 | bool debug = false; | 25 | bool debug = false; |
27 | 26 | ||
28 | static struct option long_options[] = { | 27 | static struct option long_options[] = { |
@@ -59,7 +58,7 @@ int main(int argc, char **argv) { | |||
59 | socket_path = strdup(optarg); | 58 | socket_path = strdup(optarg); |
60 | break; | 59 | break; |
61 | case 'b': // Type | 60 | case 'b': // Type |
62 | bar_id = strdup(optarg); | 61 | swaybar.id = strdup(optarg); |
63 | break; | 62 | break; |
64 | case 'v': | 63 | case 'v': |
65 | fprintf(stdout, "swaybar version " SWAY_VERSION "\n"); | 64 | fprintf(stdout, "swaybar version " SWAY_VERSION "\n"); |
@@ -80,7 +79,7 @@ int main(int argc, char **argv) { | |||
80 | wlr_log_init(WLR_ERROR, NULL); | 79 | wlr_log_init(WLR_ERROR, NULL); |
81 | } | 80 | } |
82 | 81 | ||
83 | if (!bar_id) { | 82 | if (!swaybar.id) { |
84 | wlr_log(WLR_ERROR, "No bar_id passed. " | 83 | wlr_log(WLR_ERROR, "No bar_id passed. " |
85 | "Provide --bar_id or let sway start swaybar"); | 84 | "Provide --bar_id or let sway start swaybar"); |
86 | return 1; | 85 | return 1; |
@@ -96,13 +95,12 @@ int main(int argc, char **argv) { | |||
96 | 95 | ||
97 | signal(SIGTERM, sig_handler); | 96 | signal(SIGTERM, sig_handler); |
98 | 97 | ||
99 | if (!bar_setup(&swaybar, socket_path, bar_id)) { | 98 | if (!bar_setup(&swaybar, socket_path)) { |
100 | free(socket_path); | 99 | free(socket_path); |
101 | return 1; | 100 | return 1; |
102 | } | 101 | } |
103 | 102 | ||
104 | free(socket_path); | 103 | free(socket_path); |
105 | free(bar_id); | ||
106 | 104 | ||
107 | bar_run(&swaybar); | 105 | bar_run(&swaybar); |
108 | bar_teardown(&swaybar); | 106 | bar_teardown(&swaybar); |
diff --git a/swaybar/render.c b/swaybar/render.c index dc31a5ea..097eb462 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -296,11 +296,15 @@ static uint32_t render_status_line(cairo_t *cairo, | |||
296 | 296 | ||
297 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 297 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, |
298 | struct swaybar_output *output, double x) { | 298 | struct swaybar_output *output, double x) { |
299 | const char *mode = output->bar->mode; | ||
300 | if (!mode) { | ||
301 | return 0; | ||
302 | } | ||
303 | |||
299 | struct swaybar_config *config = output->bar->config; | 304 | struct swaybar_config *config = output->bar->config; |
300 | const char *mode = config->mode; | ||
301 | int text_width, text_height; | 305 | int text_width, text_height; |
302 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 306 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, |
303 | output->scale, config->mode_pango_markup, | 307 | output->scale, output->bar->mode_pango_markup, |
304 | "%s", mode); | 308 | "%s", mode); |
305 | 309 | ||
306 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | 310 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; |
@@ -333,8 +337,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, | |||
333 | double text_y = height / 2.0 - text_height / 2.0; | 337 | double text_y = height / 2.0 - text_height / 2.0; |
334 | cairo_set_source_u32(cairo, config->colors.binding_mode.text); | 338 | cairo_set_source_u32(cairo, config->colors.binding_mode.text); |
335 | cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); | 339 | cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); |
336 | pango_printf(cairo, config->font, output->scale, config->mode_pango_markup, | 340 | pango_printf(cairo, config->font, output->scale, |
337 | "%s", mode); | 341 | output->bar->mode_pango_markup, "%s", mode); |
338 | return output->height; | 342 | return output->height; |
339 | } | 343 | } |
340 | 344 | ||
@@ -465,7 +469,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { | |||
465 | max_height = h > max_height ? h : max_height; | 469 | max_height = h > max_height ? h : max_height; |
466 | } | 470 | } |
467 | } | 471 | } |
468 | if (config->binding_mode_indicator && config->mode) { | 472 | if (config->binding_mode_indicator) { |
469 | uint32_t h = render_binding_mode_indicator(cairo, output, x); | 473 | uint32_t h = render_binding_mode_indicator(cairo, output, x); |
470 | max_height = h > max_height ? h : max_height; | 474 | max_height = h > max_height ? h : max_height; |
471 | } | 475 | } |
@@ -490,16 +494,12 @@ static const struct wl_callback_listener output_frame_listener = { | |||
490 | 494 | ||
491 | void render_frame(struct swaybar_output *output) { | 495 | void render_frame(struct swaybar_output *output) { |
492 | assert(output->surface != NULL); | 496 | assert(output->surface != NULL); |
493 | 497 | if (!output->layer_surface) { | |
494 | struct swaybar_hotspot *hotspot, *tmp; | 498 | return; |
495 | wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) { | ||
496 | if (hotspot->destroy) { | ||
497 | hotspot->destroy(hotspot->data); | ||
498 | } | ||
499 | wl_list_remove(&hotspot->link); | ||
500 | free(hotspot); | ||
501 | } | 499 | } |
502 | 500 | ||
501 | free_hotspots(&output->hotspots); | ||
502 | |||
503 | cairo_surface_t *recorder = cairo_recording_surface_create( | 503 | cairo_surface_t *recorder = cairo_recording_surface_create( |
504 | CAIRO_CONTENT_COLOR_ALPHA, NULL); | 504 | CAIRO_CONTENT_COLOR_ALPHA, NULL); |
505 | cairo_t *cairo = cairo_create(recorder); | 505 | cairo_t *cairo = cairo_create(recorder); |
@@ -519,10 +519,12 @@ void render_frame(struct swaybar_output *output) { | |||
519 | if (config_height >= 0 && height < (uint32_t)config_height) { | 519 | if (config_height >= 0 && height < (uint32_t)config_height) { |
520 | height = config_height; | 520 | height = config_height; |
521 | } | 521 | } |
522 | if (height != output->height) { | 522 | if (height != output->height || output->width == 0) { |
523 | // Reconfigure surface | 523 | // Reconfigure surface |
524 | zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); | 524 | zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); |
525 | zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); | 525 | if (strcmp(output->bar->config->mode, "dock") == 0) { |
526 | zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); | ||
527 | } | ||
526 | // TODO: this could infinite loop if the compositor assigns us a | 528 | // TODO: this could infinite loop if the compositor assigns us a |
527 | // different height than what we asked for | 529 | // different height than what we asked for |
528 | wl_surface_commit(output->surface); | 530 | wl_surface_commit(output->surface); |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index ed6dc7c8..000609ce 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -83,6 +83,17 @@ bool status_handle_readable(struct status_line *status) { | |||
83 | return true; | 83 | return true; |
84 | } | 84 | } |
85 | } | 85 | } |
86 | |||
87 | json_object *signal; | ||
88 | if (json_object_object_get_ex(header, "stop_signal", &signal)) { | ||
89 | status->stop_signal = json_object_get_int(signal); | ||
90 | wlr_log(WLR_DEBUG, "Setting stop signal to %d", status->stop_signal); | ||
91 | } | ||
92 | if (json_object_object_get_ex(header, "cont_signal", &signal)) { | ||
93 | status->cont_signal = json_object_get_int(signal); | ||
94 | wlr_log(WLR_DEBUG, "Setting cont signal to %d", status->cont_signal); | ||
95 | } | ||
96 | |||
86 | json_object_put(header); | 97 | json_object_put(header); |
87 | 98 | ||
88 | wl_list_init(&status->blocks); | 99 | wl_list_init(&status->blocks); |
@@ -121,6 +132,9 @@ bool status_handle_readable(struct status_line *status) { | |||
121 | 132 | ||
122 | struct status_line *status_line_init(char *cmd) { | 133 | struct status_line *status_line_init(char *cmd) { |
123 | struct status_line *status = calloc(1, sizeof(struct status_line)); | 134 | struct status_line *status = calloc(1, sizeof(struct status_line)); |
135 | status->stop_signal = SIGSTOP; | ||
136 | status->cont_signal = SIGCONT; | ||
137 | |||
124 | status->buffer_size = 8192; | 138 | status->buffer_size = 8192; |
125 | status->buffer = malloc(status->buffer_size); | 139 | status->buffer = malloc(status->buffer_size); |
126 | 140 | ||