summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h2
-rw-r--r--include/sway/config.h4
-rw-r--r--include/sway/debug.h2
-rw-r--r--include/sway/ipc-json.h2
-rw-r--r--include/swaybar/bar.h2
-rw-r--r--include/swaybar/config.h2
-rw-r--r--include/swaybar/render.h4
-rw-r--r--include/swaybar/tray/dbus.h18
-rw-r--r--include/swaybar/tray/sni_watcher.h10
-rw-r--r--include/swaybar/tray/tray.h32
-rw-r--r--meson.build1
-rw-r--r--sway/commands.c13
-rw-r--r--sway/commands/output/background.c18
-rw-r--r--sway/commands/resize.c30
-rw-r--r--sway/config/output.c4
-rw-r--r--sway/config/seat.c2
-rw-r--r--sway/debug-tree.c2
-rw-r--r--sway/input/cursor.c11
-rw-r--r--sway/input/seat.c12
-rw-r--r--sway/ipc-json.c2
-rw-r--r--sway/main.c73
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway-bar.5.scd3
-rw-r--r--sway/sway-input.5.scd4
-rw-r--r--sway/sway.5.scd58
-rw-r--r--sway/tree/container.c2
-rw-r--r--sway/tree/root.c15
-rw-r--r--swaybar/bar.c41
-rw-r--r--swaybar/config.c2
-rw-r--r--swaybar/render.c24
-rw-r--r--swayidle/main.c4
-rw-r--r--swaylock/main.c2
-rw-r--r--swaynag/config.c2
33 files changed, 169 insertions, 235 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index bfca6d1e..afa65340 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -95,7 +95,7 @@ struct cmd_results *add_color(const char *name,
95/** 95/**
96 * TODO: Move this function and its dependent functions to container.c. 96 * TODO: Move this function and its dependent functions to container.c.
97 */ 97 */
98void container_resize_tiled(struct sway_container *parent, enum wlr_edges edge, 98bool container_resize_tiled(struct sway_container *parent, enum wlr_edges edge,
99 int amount); 99 int amount);
100 100
101sway_cmd cmd_assign; 101sway_cmd cmd_assign;
diff --git a/include/sway/config.h b/include/sway/config.h
index 2e532f7e..2395bc51 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -450,8 +450,6 @@ void free_sway_variable(struct sway_variable *var);
450 */ 450 */
451char *do_var_replacement(char *str); 451char *do_var_replacement(char *str);
452 452
453struct cmd_results *check_security_config();
454
455int input_identifier_cmp(const void *item, const void *data); 453int input_identifier_cmp(const void *item, const void *data);
456 454
457struct input_config *new_input_config(const char* identifier); 455struct input_config *new_input_config(const char* identifier);
@@ -472,7 +470,7 @@ struct seat_config *copy_seat_config(struct seat_config *seat);
472 470
473void free_seat_config(struct seat_config *ic); 471void free_seat_config(struct seat_config *ic);
474 472
475struct seat_attachment_config *seat_attachment_config_new(); 473struct seat_attachment_config *seat_attachment_config_new(void);
476 474
477struct seat_attachment_config *seat_config_get_attachment( 475struct seat_attachment_config *seat_config_get_attachment(
478 struct seat_config *seat_config, char *identifier); 476 struct seat_config *seat_config, char *identifier);
diff --git a/include/sway/debug.h b/include/sway/debug.h
index bf3a5f6d..0e9bb056 100644
--- a/include/sway/debug.h
+++ b/include/sway/debug.h
@@ -17,6 +17,6 @@ struct sway_debug {
17 17
18extern struct sway_debug debug; 18extern struct sway_debug debug;
19 19
20void update_debug_tree(); 20void update_debug_tree(void);
21 21
22#endif 22#endif
diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h
index fef243e3..1cbfd15d 100644
--- a/include/sway/ipc-json.h
+++ b/include/sway/ipc-json.h
@@ -4,7 +4,7 @@
4#include "sway/tree/container.h" 4#include "sway/tree/container.h"
5#include "sway/input/input-manager.h" 5#include "sway/input/input-manager.h"
6 6
7json_object *ipc_json_get_version(); 7json_object *ipc_json_get_version(void);
8 8
9json_object *ipc_json_describe_disabled_output(struct sway_output *o); 9json_object *ipc_json_describe_disabled_output(struct sway_output *o);
10json_object *ipc_json_describe_node(struct sway_node *node); 10json_object *ipc_json_describe_node(struct sway_node *node);
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h
index 20992014..de234111 100644
--- a/include/swaybar/bar.h
+++ b/include/swaybar/bar.h
@@ -83,6 +83,8 @@ struct swaybar_output {
83 enum wl_output_subpixel subpixel; 83 enum wl_output_subpixel subpixel;
84 struct pool_buffer buffers[2]; 84 struct pool_buffer buffers[2];
85 struct pool_buffer *current_buffer; 85 struct pool_buffer *current_buffer;
86 bool dirty;
87 bool frame_scheduled;
86}; 88};
87 89
88struct swaybar_workspace { 90struct swaybar_workspace {
diff --git a/include/swaybar/config.h b/include/swaybar/config.h
index 6739c28a..5f5688cf 100644
--- a/include/swaybar/config.h
+++ b/include/swaybar/config.h
@@ -50,7 +50,7 @@ struct swaybar_config {
50 } colors; 50 } colors;
51}; 51};
52 52
53struct swaybar_config *init_config(); 53struct swaybar_config *init_config(void);
54void free_config(struct swaybar_config *config); 54void free_config(struct swaybar_config *config);
55uint32_t parse_position(const char *position); 55uint32_t parse_position(const char *position);
56 56
diff --git a/include/swaybar/render.h b/include/swaybar/render.h
index 071e2298..ebdc69e4 100644
--- a/include/swaybar/render.h
+++ b/include/swaybar/render.h
@@ -1,10 +1,8 @@
1#ifndef _SWAYBAR_RENDER_H 1#ifndef _SWAYBAR_RENDER_H
2#define _SWAYBAR_RENDER_H 2#define _SWAYBAR_RENDER_H
3 3
4struct swaybar;
5struct swaybar_output; 4struct swaybar_output;
6struct swaybar_config;
7 5
8void render_frame(struct swaybar *bar, struct swaybar_output *output); 6void render_frame(struct swaybar_output *output);
9 7
10#endif 8#endif
diff --git a/include/swaybar/tray/dbus.h b/include/swaybar/tray/dbus.h
deleted file mode 100644
index eb9cfea7..00000000
--- a/include/swaybar/tray/dbus.h
+++ /dev/null
@@ -1,18 +0,0 @@
1#ifndef _SWAYBAR_DBUS_H
2#define _SWAYBAR_DBUS_H
3
4#include <stdbool.h>
5#include <dbus/dbus.h>
6extern DBusConnection *conn;
7
8/**
9 * Should be called in main loop to dispatch events
10 */
11void dispatch_dbus();
12
13/**
14 * Initializes async dbus communication
15 */
16int dbus_init();
17
18#endif /* _SWAYBAR_DBUS_H */
diff --git a/include/swaybar/tray/sni_watcher.h b/include/swaybar/tray/sni_watcher.h
deleted file mode 100644
index 25ddfcd2..00000000
--- a/include/swaybar/tray/sni_watcher.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef _SWAYBAR_SNI_WATCHER_H
2#define _SWAYBAR_SNI_WATCHER_H
3
4/**
5 * Starts the sni_watcher, the watcher is practically a black box and should
6 * only be accessed though functions described in its spec
7 */
8int init_sni_watcher();
9
10#endif /* _SWAYBAR_SNI_WATCHER_H */
diff --git a/include/swaybar/tray/tray.h b/include/swaybar/tray/tray.h
deleted file mode 100644
index 2d0662be..00000000
--- a/include/swaybar/tray/tray.h
+++ /dev/null
@@ -1,32 +0,0 @@
1#ifndef _SWAYBAR_TRAY_H
2#define _SWAYBAR_TRAY_H
3
4#include <stdint.h>
5#include <stdbool.h>
6#include "swaybar/tray/dbus.h"
7#include "swaybar/tray/sni.h"
8#include "swaybar/bar.h"
9#include "list.h"
10
11extern struct tray *tray;
12
13struct tray {
14 list_t *items;
15};
16
17/**
18 * Processes a mouse event on the bar
19 */
20void tray_mouse_event(struct output *output, int x, int y,
21 uint32_t button, uint32_t state);
22
23uint32_t tray_render(struct output *output, struct config *config);
24
25void tray_upkeep(struct bar *bar);
26
27/**
28 * Initializes the tray with D-Bus
29 */
30void init_tray(struct bar *bar);
31
32#endif /* _SWAYBAR_TRAY_H */
diff --git a/meson.build b/meson.build
index de6573ea..080709fa 100644
--- a/meson.build
+++ b/meson.build
@@ -42,7 +42,6 @@ pango = dependency('pango')
42pangocairo = dependency('pangocairo') 42pangocairo = dependency('pangocairo')
43gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) 43gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false)
44pixman = dependency('pixman-1') 44pixman = dependency('pixman-1')
45libcap = dependency('libcap', required: false)
46libinput = dependency('libinput', version: '>=1.6.0') 45libinput = dependency('libinput', version: '>=1.6.0')
47libpam = cc.find_library('pam', required: false) 46libpam = cc.find_library('pam', required: false)
48systemd = dependency('libsystemd', required: false) 47systemd = dependency('libsystemd', required: false)
diff --git a/sway/commands.c b/sway/commands.c
index bff230f7..03761c52 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -391,14 +391,12 @@ struct cmd_results *config_command(char *exec) {
391 // Var replacement, for all but first argument of set 391 // Var replacement, for all but first argument of set
392 // TODO commands 392 // TODO commands
393 for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { 393 for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) {
394 if (*argv[i] == '\"' || *argv[i] == '\'') {
395 strip_quotes(argv[i]);
396 }
394 argv[i] = do_var_replacement(argv[i]); 397 argv[i] = do_var_replacement(argv[i]);
395 unescape_string(argv[i]); 398 unescape_string(argv[i]);
396 } 399 }
397 // Strip quotes for first argument.
398 // TODO This part needs to be handled much better
399 if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
400 strip_quotes(argv[1]);
401 }
402 if (handler->handle) { 400 if (handler->handle) {
403 results = handler->handle(argc-1, argv+1); 401 results = handler->handle(argc-1, argv+1);
404 } else { 402 } else {
@@ -422,11 +420,6 @@ struct cmd_results *config_subcommand(char **argv, int argc,
422 char *input = argv[0] ? argv[0] : "(empty)"; 420 char *input = argv[0] ? argv[0] : "(empty)";
423 return cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); 421 return cmd_results_new(CMD_INVALID, input, "Unknown/invalid command");
424 } 422 }
425 // Strip quotes for first argument.
426 // TODO This part needs to be handled much better
427 if (argc > 1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
428 strip_quotes(argv[1]);
429 }
430 if (handler->handle) { 423 if (handler->handle) {
431 return handler->handle(argc - 1, argv + 1); 424 return handler->handle(argc - 1, argv + 1);
432 } 425 }
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c
index 9e370d43..30fb47c4 100644
--- a/sway/commands/output/background.c
+++ b/sway/commands/output/background.c
@@ -123,19 +123,13 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
123 } 123 }
124 free(src); 124 free(src);
125 } else { 125 } else {
126 // Escape spaces and quotes in the final path for swaybg 126 // Escape double quotes in the final path for swaybg
127 for (size_t i = 0; i < strlen(src); i++) { 127 for (size_t i = 0; i < strlen(src); i++) {
128 switch (src[i]) { 128 if (src[i] == '"') {
129 case ' ': 129 src = realloc(src, strlen(src) + 2);
130 case '\'': 130 memmove(src + i + 1, src + i, strlen(src + i) + 1);
131 case '\"': 131 *(src + i) = '\\';
132 src = realloc(src, strlen(src) + 2); 132 i++;
133 memmove(src + i + 1, src + i, strlen(src + i) + 1);
134 *(src + i) = '\\';
135 i++;
136 break;
137 default:
138 break;
139 } 133 }
140 } 134 }
141 135
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 99e9dbda..1343b165 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -179,11 +179,11 @@ static void container_recursive_resize(struct sway_container *container,
179 } 179 }
180} 180}
181 181
182static void resize_tiled(struct sway_container *parent, int amount, 182static bool resize_tiled(struct sway_container *parent, int amount,
183 enum resize_axis axis) { 183 enum resize_axis axis) {
184 struct sway_container *focused = parent; 184 struct sway_container *focused = parent;
185 if (!parent) { 185 if (!parent) {
186 return; 186 return false;
187 } 187 }
188 188
189 enum sway_container_layout parallel_layout = 189 enum sway_container_layout parallel_layout =
@@ -216,7 +216,7 @@ static void resize_tiled(struct sway_container *parent, int amount,
216 } 216 }
217 if (!parent) { 217 if (!parent) {
218 // Can't resize in this direction 218 // Can't resize in this direction
219 return; 219 return false;
220 } 220 }
221 221
222 // Implement up/down/left/right direction by zeroing one of the weights, 222 // Implement up/down/left/right direction by zeroing one of the weights,
@@ -248,22 +248,22 @@ static void resize_tiled(struct sway_container *parent, int amount,
248 if (sibling_pos < parent_pos && minor_weight) { 248 if (sibling_pos < parent_pos && minor_weight) {
249 double pixels = -amount / minor_weight; 249 double pixels = -amount / minor_weight;
250 if (major_weight && (sibling_size + pixels / 2) < min_sane) { 250 if (major_weight && (sibling_size + pixels / 2) < min_sane) {
251 return; // Too small 251 return false; // Too small
252 } else if (!major_weight && sibling_size + pixels < min_sane) { 252 } else if (!major_weight && sibling_size + pixels < min_sane) {
253 return; // Too small 253 return false; // Too small
254 } 254 }
255 } else if (sibling_pos > parent_pos && major_weight) { 255 } else if (sibling_pos > parent_pos && major_weight) {
256 double pixels = -amount / major_weight; 256 double pixels = -amount / major_weight;
257 if (minor_weight && (sibling_size + pixels / 2) < min_sane) { 257 if (minor_weight && (sibling_size + pixels / 2) < min_sane) {
258 return; // Too small 258 return false; // Too small
259 } else if (!minor_weight && sibling_size + pixels < min_sane) { 259 } else if (!minor_weight && sibling_size + pixels < min_sane) {
260 return; // Too small 260 return false; // Too small
261 } 261 }
262 } 262 }
263 } else { 263 } else {
264 double pixels = amount; 264 double pixels = amount;
265 if (parent_size + pixels < min_sane) { 265 if (parent_size + pixels < min_sane) {
266 return; // Too small 266 return false; // Too small
267 } 267 }
268 } 268 }
269 } 269 }
@@ -317,9 +317,10 @@ static void resize_tiled(struct sway_container *parent, int amount,
317 } else { 317 } else {
318 arrange_workspace(parent->workspace); 318 arrange_workspace(parent->workspace);
319 } 319 }
320 return true;
320} 321}
321 322
322void container_resize_tiled(struct sway_container *parent, 323bool container_resize_tiled(struct sway_container *parent,
323 enum wlr_edges edge, int amount) { 324 enum wlr_edges edge, int amount) {
324 enum resize_axis axis = RESIZE_AXIS_INVALID; 325 enum resize_axis axis = RESIZE_AXIS_INVALID;
325 switch (edge) { 326 switch (edge) {
@@ -338,7 +339,7 @@ void container_resize_tiled(struct sway_container *parent,
338 case WLR_EDGE_NONE: 339 case WLR_EDGE_NONE:
339 break; 340 break;
340 } 341 }
341 resize_tiled(parent, amount, axis); 342 return resize_tiled(parent, amount, axis);
342} 343}
343 344
344/** 345/**
@@ -395,6 +396,10 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis,
395 case RESIZE_AXIS_INVALID: 396 case RESIZE_AXIS_INVALID:
396 return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction"); 397 return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction");
397 } 398 }
399 if (grow_x == 0 && grow_y == 0) {
400 return cmd_results_new(CMD_INVALID, "resize",
401 "Cannot resize any further");
402 }
398 con->x += grow_x; 403 con->x += grow_x;
399 con->y += grow_y; 404 con->y += grow_y;
400 con->width += grow_width; 405 con->width += grow_width;
@@ -442,7 +447,10 @@ static struct cmd_results *resize_adjust_tiled(enum resize_axis axis,
442 } 447 }
443 } 448 }
444 449
445 resize_tiled(current, amount->amount, axis); 450 if (!resize_tiled(current, amount->amount, axis)) {
451 return cmd_results_new(CMD_INVALID, "resize",
452 "Cannot resize any further");
453 }
446 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 454 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
447} 455}
448 456
diff --git a/sway/config/output.c b/sway/config/output.c
index 74d79130..6f337b66 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -237,7 +237,7 @@ void apply_output_config(struct output_config *oc, struct sway_output *output) {
237 wlr_log(WLR_DEBUG, "Setting background for output %d to %s", 237 wlr_log(WLR_DEBUG, "Setting background for output %d to %s",
238 output_i, oc->background); 238 output_i, oc->background);
239 239
240 size_t len = snprintf(NULL, 0, "%s %d %s %s %s", 240 size_t len = snprintf(NULL, 0, "%s %d \"%s\" %s %s",
241 config->swaybg_command ? config->swaybg_command : "swaybg", 241 config->swaybg_command ? config->swaybg_command : "swaybg",
242 output_i, oc->background, oc->background_option, 242 output_i, oc->background, oc->background_option,
243 oc->background_fallback ? oc->background_fallback : ""); 243 oc->background_fallback ? oc->background_fallback : "");
@@ -246,7 +246,7 @@ void apply_output_config(struct output_config *oc, struct sway_output *output) {
246 wlr_log(WLR_DEBUG, "Unable to allocate swaybg command"); 246 wlr_log(WLR_DEBUG, "Unable to allocate swaybg command");
247 return; 247 return;
248 } 248 }
249 snprintf(command, len + 1, "%s %d %s %s %s", 249 snprintf(command, len + 1, "%s %d \"%s\" %s %s",
250 config->swaybg_command ? config->swaybg_command : "swaybg", 250 config->swaybg_command ? config->swaybg_command : "swaybg",
251 output_i, oc->background, oc->background_option, 251 output_i, oc->background, oc->background_option,
252 oc->background_fallback ? oc->background_fallback : ""); 252 oc->background_fallback ? oc->background_fallback : "");
diff --git a/sway/config/seat.c b/sway/config/seat.c
index 83dac4c0..46456caf 100644
--- a/sway/config/seat.c
+++ b/sway/config/seat.c
@@ -30,7 +30,7 @@ struct seat_config *new_seat_config(const char* name) {
30 return seat; 30 return seat;
31} 31}
32 32
33struct seat_attachment_config *seat_attachment_config_new() { 33struct seat_attachment_config *seat_attachment_config_new(void) {
34 struct seat_attachment_config *attachment = 34 struct seat_attachment_config *attachment =
35 calloc(1, sizeof(struct seat_attachment_config)); 35 calloc(1, sizeof(struct seat_attachment_config));
36 if (!attachment) { 36 if (!attachment) {
diff --git a/sway/debug-tree.c b/sway/debug-tree.c
index 9644f4e5..16b479f9 100644
--- a/sway/debug-tree.c
+++ b/sway/debug-tree.c
@@ -120,7 +120,7 @@ static int draw_node(cairo_t *cairo, struct sway_node *node,
120 return height; 120 return height;
121} 121}
122 122
123void update_debug_tree() { 123void update_debug_tree(void) {
124 if (!debug.render_tree) { 124 if (!debug.render_tree) {
125 return; 125 return;
126 } 126 }
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index aa0e07f5..3ddc27a0 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -30,7 +30,7 @@
30// when dragging to the edge of a layout container. 30// when dragging to the edge of a layout container.
31#define DROP_LAYOUT_BORDER 30 31#define DROP_LAYOUT_BORDER 30
32 32
33static uint32_t get_current_time_msec() { 33static uint32_t get_current_time_msec(void) {
34 struct timespec now; 34 struct timespec now;
35 clock_gettime(CLOCK_MONOTONIC, &now); 35 clock_gettime(CLOCK_MONOTONIC, &now);
36 return now.tv_nsec / 1000; 36 return now.tv_nsec / 1000;
@@ -1006,8 +1006,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
1006 if (seat_is_input_allowed(seat, surface)) { 1006 if (seat_is_input_allowed(seat, surface)) {
1007 wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec, 1007 wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec,
1008 event->touch_id, sx, sy); 1008 event->touch_id, sx, sy);
1009 cursor->image_client = NULL; 1009 cursor_set_image(cursor, NULL, NULL);
1010 wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
1011 } 1010 }
1012} 1011}
1013 1012
@@ -1175,11 +1174,13 @@ static void handle_request_set_cursor(struct wl_listener *listener,
1175 1174
1176void cursor_set_image(struct sway_cursor *cursor, const char *image, 1175void cursor_set_image(struct sway_cursor *cursor, const char *image,
1177 struct wl_client *client) { 1176 struct wl_client *client) {
1178 if (!cursor->image || strcmp(cursor->image, image) != 0) { 1177 if (!image) {
1178 wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
1179 } else if (!cursor->image || strcmp(cursor->image, image) != 0) {
1179 wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, 1180 wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image,
1180 cursor->cursor); 1181 cursor->cursor);
1181 cursor->image = image;
1182 } 1182 }
1183 cursor->image = image;
1183 cursor->image_client = client; 1184 cursor->image_client = client;
1184} 1185}
1185 1186
diff --git a/sway/input/seat.c b/sway/input/seat.c
index a9c564e7..4817eae7 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -368,11 +368,20 @@ static void seat_update_capabilities(struct sway_seat *seat) {
368 caps |= WL_SEAT_CAPABILITY_TOUCH; 368 caps |= WL_SEAT_CAPABILITY_TOUCH;
369 break; 369 break;
370 case WLR_INPUT_DEVICE_TABLET_TOOL: 370 case WLR_INPUT_DEVICE_TABLET_TOOL:
371 caps |= WL_SEAT_CAPABILITY_POINTER;
372 break;
371 case WLR_INPUT_DEVICE_TABLET_PAD: 373 case WLR_INPUT_DEVICE_TABLET_PAD:
372 break; 374 break;
373 } 375 }
374 } 376 }
375 wlr_seat_set_capabilities(seat->wlr_seat, caps); 377 wlr_seat_set_capabilities(seat->wlr_seat, caps);
378
379 // Hide cursor if seat doesn't have pointer capability
380 if ((caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
381 cursor_set_image(seat->cursor, NULL, NULL);
382 } else {
383 cursor_set_image(seat->cursor, "left_ptr", NULL);
384 }
376} 385}
377 386
378static void seat_apply_input_config(struct sway_seat *seat, 387static void seat_apply_input_config(struct sway_seat *seat,
@@ -552,8 +561,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
552 output->name, (double)output->scale); 561 output->name, (double)output->scale);
553 } 562 }
554 563
555 wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, 564 cursor_set_image(seat->cursor, "left_ptr", NULL);
556 "left_ptr", seat->cursor->cursor);
557 wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, 565 wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
558 seat->cursor->cursor->y); 566 seat->cursor->cursor->y);
559} 567}
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index f054ac9f..45915094 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -42,7 +42,7 @@ static const char *ipc_json_orientation_description(enum sway_container_layout l
42 return "none"; 42 return "none";
43} 43}
44 44
45json_object *ipc_json_get_version() { 45json_object *ipc_json_get_version(void) {
46 int major = 0, minor = 0, patch = 0; 46 int major = 0, minor = 0, patch = 0;
47 json_object *version = json_object_new_object(); 47 json_object *version = json_object_new_object();
48 48
diff --git a/sway/main.c b/sway/main.c
index 990f5f3a..50b05b21 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -12,10 +12,6 @@
12#include <sys/wait.h> 12#include <sys/wait.h>
13#include <sys/un.h> 13#include <sys/un.h>
14#include <unistd.h> 14#include <unistd.h>
15#ifdef __linux__
16#include <sys/capability.h>
17#include <sys/prctl.h>
18#endif
19#include <wlr/util/log.h> 15#include <wlr/util/log.h>
20#include "sway/commands.h" 16#include "sway/commands.h"
21#include "sway/config.h" 17#include "sway/config.h"
@@ -45,7 +41,7 @@ void sig_handler(int signal) {
45 sway_terminate(EXIT_SUCCESS); 41 sway_terminate(EXIT_SUCCESS);
46} 42}
47 43
48void detect_raspi() { 44void detect_raspi(void) {
49 bool raspi = false; 45 bool raspi = false;
50 FILE *f = fopen("/sys/firmware/devicetree/base/model", "r"); 46 FILE *f = fopen("/sys/firmware/devicetree/base/model", "r");
51 if (!f) { 47 if (!f) {
@@ -85,7 +81,7 @@ void detect_raspi() {
85 } 81 }
86} 82}
87 83
88void detect_proprietary() { 84void detect_proprietary(void) {
89 FILE *f = fopen("/proc/modules", "r"); 85 FILE *f = fopen("/proc/modules", "r");
90 if (!f) { 86 if (!f) {
91 return; 87 return;
@@ -120,7 +116,7 @@ void run_as_ipc_client(char *command, char *socket_path) {
120 close(socketfd); 116 close(socketfd);
121} 117}
122 118
123static void log_env() { 119static void log_env(void) {
124 const char *log_vars[] = { 120 const char *log_vars[] = {
125 "PATH", 121 "PATH",
126 "LD_LIBRARY_PATH", 122 "LD_LIBRARY_PATH",
@@ -135,7 +131,7 @@ static void log_env() {
135 } 131 }
136} 132}
137 133
138static void log_distro() { 134static void log_distro(void) {
139 const char *paths[] = { 135 const char *paths[] = {
140 "/etc/lsb-release", 136 "/etc/lsb-release",
141 "/etc/os-release", 137 "/etc/os-release",
@@ -162,7 +158,7 @@ static void log_distro() {
162 } 158 }
163} 159}
164 160
165static void log_kernel() { 161static void log_kernel(void) {
166 FILE *f = popen("uname -a", "r"); 162 FILE *f = popen("uname -a", "r");
167 if (!f) { 163 if (!f) {
168 wlr_log(WLR_INFO, "Unable to determine kernel version"); 164 wlr_log(WLR_INFO, "Unable to determine kernel version");
@@ -181,28 +177,8 @@ static void log_kernel() {
181 pclose(f); 177 pclose(f);
182} 178}
183 179
184static void executable_sanity_check() {
185#ifdef __linux__
186 struct stat sb;
187 char *exe = realpath("/proc/self/exe", NULL);
188 stat(exe, &sb);
189 // We assume that cap_get_file returning NULL implies ENODATA
190 if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) {
191 wlr_log(WLR_ERROR,
192 "sway executable has both the s(g)uid bit AND file caps set.");
193 wlr_log(WLR_ERROR,
194 "This is strongly discouraged (and completely broken).");
195 wlr_log(WLR_ERROR,
196 "Please clear one of them (either the suid bit, or the file caps).");
197 wlr_log(WLR_ERROR,
198 "If unsure, strip the file caps.");
199 exit(EXIT_FAILURE);
200 }
201 free(exe);
202#endif
203}
204 180
205static void drop_permissions(bool keep_caps) { 181static void drop_permissions(void) {
206 if (getuid() != geteuid() || getgid() != getegid()) { 182 if (getuid() != geteuid() || getgid() != getegid()) {
207 if (setgid(getgid()) != 0) { 183 if (setgid(getgid()) != 0) {
208 wlr_log(WLR_ERROR, "Unable to drop root"); 184 wlr_log(WLR_ERROR, "Unable to drop root");
@@ -217,20 +193,6 @@ static void drop_permissions(bool keep_caps) {
217 wlr_log(WLR_ERROR, "Root privileges can be restored."); 193 wlr_log(WLR_ERROR, "Root privileges can be restored.");
218 exit(EXIT_FAILURE); 194 exit(EXIT_FAILURE);
219 } 195 }
220#ifdef __linux__
221 if (keep_caps) {
222 // Drop every cap except CAP_SYS_PTRACE
223 cap_t caps = cap_init();
224 cap_value_t keep = CAP_SYS_PTRACE;
225 wlr_log(WLR_INFO, "Dropping extra capabilities");
226 if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) ||
227 cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) ||
228 cap_set_proc(caps)) {
229 wlr_log(WLR_ERROR, "Failed to drop extra capabilities");
230 exit(EXIT_FAILURE);
231 }
232 }
233#endif
234} 196}
235 197
236void enable_debug_flag(const char *flag) { 198void enable_debug_flag(const char *flag) {
@@ -347,7 +309,7 @@ int main(int argc, char **argv) {
347 wlr_log(WLR_ERROR, "Don't use options with the IPC client"); 309 wlr_log(WLR_ERROR, "Don't use options with the IPC client");
348 exit(EXIT_FAILURE); 310 exit(EXIT_FAILURE);
349 } 311 }
350 drop_permissions(false); 312 drop_permissions();
351 char *socket_path = getenv("SWAYSOCK"); 313 char *socket_path = getenv("SWAYSOCK");
352 if (!socket_path) { 314 if (!socket_path) {
353 wlr_log(WLR_ERROR, "Unable to retrieve socket path"); 315 wlr_log(WLR_ERROR, "Unable to retrieve socket path");
@@ -358,34 +320,17 @@ int main(int argc, char **argv) {
358 return 0; 320 return 0;
359 } 321 }
360 322
361 executable_sanity_check();
362 bool suid = false;
363
364 if (!server_privileged_prepare(&server)) { 323 if (!server_privileged_prepare(&server)) {
365 return 1; 324 return 1;
366 } 325 }
367 326
368#if defined(__linux__) || defined(__FreeBSD__)
369 if (getuid() != geteuid() || getgid() != getegid()) {
370#ifdef __linux__
371 // Retain capabilities after setuid()
372 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
373 wlr_log(WLR_ERROR, "Cannot keep caps after setuid()");
374 exit(EXIT_FAILURE);
375 }
376#endif
377 suid = true;
378 }
379#endif
380
381 log_kernel(); 327 log_kernel();
382 log_distro(); 328 log_distro();
383 detect_proprietary(); 329 detect_proprietary();
384 detect_raspi(); 330 detect_raspi();
385 331
386#if defined(__linux__) || defined(__FreeBSD__) 332 drop_permissions();
387 drop_permissions(suid); 333
388#endif
389 // handle SIGTERM signals 334 // handle SIGTERM signals
390 signal(SIGTERM, sig_handler); 335 signal(SIGTERM, sig_handler);
391 336
diff --git a/sway/meson.build b/sway/meson.build
index 05a0316a..b6394ecb 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -165,7 +165,6 @@ sway_deps = [
165 cairo, 165 cairo,
166 gdk_pixbuf, 166 gdk_pixbuf,
167 jsonc, 167 jsonc,
168 libcap,
169 libinput, 168 libinput,
170 math, 169 math,
171 pango, 170 pango,
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index a61e2829..00b9386e 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -6,8 +6,7 @@ sway-bar - bar configuration file and commands
6 6
7# DESCRIPTION 7# DESCRIPTION
8 8
9Sway allows configuring swaybar in the sway configuration file. Swaybar 9Sway allows configuring swaybar in the sway configuration file.
10commands must be used inside a _bar { }_ block in the config file.
11 10
12# COMMANDS 11# COMMANDS
13 12
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index 4fe7e7b7..14f2a007 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -7,7 +7,6 @@ sway-input - input configuration file and commands
7# DESCRIPTION 7# DESCRIPTION
8 8
9Sway allows for configuration of devices within the sway configuration file. 9Sway allows for configuration of devices within the sway configuration file.
10sway-input commands must be used inside an _input { }_ block in the config.
11To obtain a list of available device identifiers, run *swaymsg -t get\_inputs*. 10To obtain a list of available device identifiers, run *swaymsg -t get\_inputs*.
12 11
13# INPUT COMMANDS 12# INPUT COMMANDS
@@ -119,8 +118,7 @@ The following commands may only be used in the configuration file.
119 118
120## SEAT CONFIGURATION 119## SEAT CONFIGURATION
121 120
122Configure options for multiseat mode. sway-seat commands must be used inside a 121Configure options for multiseat mode.
123_seat { }_ block in the config.
124 122
125A *seat* is a collection of input devices that act independently of each other. 123A *seat* is a collection of input devices that act independently of each other.
126Seats are identified by name and the default seat is _seat0_ if no seats are 124Seats are identified by name and the default seat is _seat0_ if no seats are
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 927bf55c..1526eee3 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -19,6 +19,24 @@ bindsym Shift+XF86AudioRaiseVolume exec \\
19 pactl set-sink-volume @DEFAULT_SINK@ -1% 19 pactl set-sink-volume @DEFAULT_SINK@ -1%
20``` 20```
21 21
22Commands can also be given as a block in the form *command { <subcommands...>
23}*. Anything before the opening *{* will be prepended to the lines inside the
24block. For example:
25
26```
27output eDP-1 {
28 background ~/wallpaper.png
29 resolution 1920x1080
30}
31```
32
33is identical to
34
35```
36output eDP-1 background ~/wallpaper.png
37output eDP-1 resolution 1920x1080
38```
39
22These commands can be executed in your config file, via *swaymsg*(1), or via 40These commands can be executed in your config file, via *swaymsg*(1), or via
23the bindsym command. 41the bindsym command.
24 42
@@ -37,10 +55,8 @@ which you may only select one. *[...]* is used for optional arguments, and
37 55
38The following commands may only be used in the configuration file. 56The following commands may only be used in the configuration file.
39 57
40*bar {* <commands...> *}* 58*bar* [<bar-id>] <bar-subcommands...>
41 _commands..._ after *{* will be interpreted as bar commands. For 59 For details on bar subcommands, see *sway-bar*(5).
42 details, see *sway-bar*(5). A newline is required between *{* and the
43 first command, and *}* must be alone on a line.
44 60
45*default\_orientation* horizontal|vertical|auto 61*default\_orientation* horizontal|vertical|auto
46 Sets the default container layout for tiled containers. 62 Sets the default container layout for tiled containers.
@@ -51,10 +67,6 @@ The following commands may only be used in the configuration file.
51 *wordexp*(3) for details). The same include file can only be included once; 67 *wordexp*(3) for details). The same include file can only be included once;
52 subsequent attempts will be ignored. 68 subsequent attempts will be ignored.
53 69
54*set* $<name> <value>
55 Sets variable $_name_ to _value_. You can use the new variable in the
56 arguments of future commands.
57
58*swaybg\_command* <command> 70*swaybg\_command* <command>
59 Executes custom background _command_. Default is _swaybg_. Refer to 71 Executes custom background _command_. Default is _swaybg_. Refer to
60 *output* below for more information. 72 *output* below for more information.
@@ -424,20 +436,15 @@ The default colors are:
424*hide\_edge\_borders* none|vertical|horizontal|both|smart 436*hide\_edge\_borders* none|vertical|horizontal|both|smart
425 Hides window borders adjacent to the screen edges. Default is _none_. 437 Hides window borders adjacent to the screen edges. Default is _none_.
426 438
427*input* <input\_device> *{* <commands...> *}* 439*input* <input\_device> <input-subcommands...>
428 _commands..._ after *{* will be interpreted as input commands applying to 440 For details on input subcommands, see *sway-input*(5).
429 the specified input device. For details, see *sway-input*(5). A newline is
430 required between *{* and the first command, and *}* must be alone on a
431 line.
432 441
433 \* may be used in lieu of a specific device name to configure all input 442 \* may be used in lieu of a specific device name to configure all input
434 devices. A list of input device names may be obtained via *swaymsg -t 443 devices. A list of input device names may be obtained via *swaymsg -t
435 get\_inputs*. 444 get\_inputs*.
436 445
437*seat* <seat> *{* <commands...> *}* 446*seat* <seat> <seat-subcommands...>
438 _commands..._ after *{* will be interpreted as seat commands applying to 447 For details on seat subcommands, see *sway-input*(5).
439 the specified seat. For details, see *sway-input*(5). A newline is required
440 between *{* and the first command, and *}* must be alone on a line.
441 448
442*seat* <seat> cursor move|set <x> <y> 449*seat* <seat> cursor move|set <x> <y>
443 Move specified seat's cursor relative to current position or wrap to 450 Move specified seat's cursor relative to current position or wrap to
@@ -465,10 +472,8 @@ The default colors are:
465*mode* <mode> 472*mode* <mode>
466 Switches to the specified mode. The default mode _default_. 473 Switches to the specified mode. The default mode _default_.
467 474
468*mode* [--pango\_markup] <mode> *{* <commands...> *}* 475*mode* [--pango\_markup] <mode> <mode-subcommands...>
469 _commands..._ after *{* will be added to the specified mode. A newline is 476 The only two valid _mode-subcommands..._ are *bindsym* and *bindcode*.
470 required between *{* and the first command, and *}* must be alone on a
471 line. Only *bindsym* and *bindcode* commands are permitted in mode blocks.
472 If _--pango\_markup_ is given, then _mode_ will be interpreted as pango 477 If _--pango\_markup_ is given, then _mode_ will be interpreted as pango
473 markup. 478 markup.
474 479
@@ -533,8 +538,15 @@ You may combine output commands into one, like so:
533 output HDMI-A-1 mode 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch 538 output HDMI-A-1 mode 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch
534 539
535You can get a list of output names with *swaymsg -t get\_outputs*. You may also 540You can get a list of output names with *swaymsg -t get\_outputs*. You may also
536match any output by using the output name "\*". Be sure to add this output 541match any output by using the output name "\*".
537config after the others, or it will be matched instead of the others. 542
543*set* $<name> <value>
544 Sets variable $_name_ to _value_. You can use the new variable in the
545 arguments of future commands. When the variable is used, it can be escaped
546 with an additional $ (ie $$_name_) to have the replacement happen at run
547 time instead of when reading the config. However, it does not always make
548 sense for the variable to be replaced at run time since some arguments do
549 need to be known at config time.
538 550
539*show\_marks* yes|no 551*show\_marks* yes|no
540 If *show\_marks* is yes, marks will be displayed in the window borders. 552 If *show\_marks* is yes, marks will be displayed in the window borders.
diff --git a/sway/tree/container.c b/sway/tree/container.c
index baaa82fd..66370a42 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -593,7 +593,7 @@ void container_update_representation(struct sway_container *con) {
593 } 593 }
594} 594}
595 595
596size_t container_titlebar_height() { 596size_t container_titlebar_height(void) {
597 return config->font_height + TITLEBAR_V_PADDING * 2; 597 return config->font_height + TITLEBAR_V_PADDING * 2;
598} 598}
599 599
diff --git a/sway/tree/root.c b/sway/tree/root.c
index d6f67bd7..6748e9c9 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -273,6 +273,12 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data),
273 container_for_each_child(container, f, data); 273 container_for_each_child(container, f, data);
274 } 274 }
275 } 275 }
276
277 // Saved workspaces
278 for (int i = 0; i < root->saved_workspaces->length; ++i) {
279 struct sway_workspace *ws = root->saved_workspaces->items[i];
280 workspace_for_each_container(ws, f, data);
281 }
276} 282}
277 283
278struct sway_output *root_find_output( 284struct sway_output *root_find_output(
@@ -320,6 +326,15 @@ struct sway_container *root_find_container(
320 } 326 }
321 } 327 }
322 } 328 }
329
330 // Saved workspaces
331 for (int i = 0; i < root->saved_workspaces->length; ++i) {
332 struct sway_workspace *ws = root->saved_workspaces->items[i];
333 if ((result = workspace_find_container(ws, test, data))) {
334 return result;
335 }
336 }
337
323 return NULL; 338 return NULL;
324} 339}
325 340
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 15e81976..388c24c4 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -72,6 +72,16 @@ static void swaybar_output_free(struct swaybar_output *output) {
72 free(output); 72 free(output);
73} 73}
74 74
75static void set_output_dirty(struct swaybar_output *output) {
76 if (output->frame_scheduled) {
77 output->dirty = true;
78 return;
79 }
80 if (output->surface) {
81 render_frame(output);
82 }
83}
84
75static void layer_surface_configure(void *data, 85static void layer_surface_configure(void *data,
76 struct zwlr_layer_surface_v1 *surface, 86 struct zwlr_layer_surface_v1 *surface,
77 uint32_t serial, uint32_t width, uint32_t height) { 87 uint32_t serial, uint32_t width, uint32_t height) {
@@ -79,7 +89,7 @@ static void layer_surface_configure(void *data,
79 output->width = width; 89 output->width = width;
80 output->height = height; 90 output->height = height;
81 zwlr_layer_surface_v1_ack_configure(surface, serial); 91 zwlr_layer_surface_v1_ack_configure(surface, serial);
82 render_frame(output->bar, output); 92 set_output_dirty(output);
83} 93}
84 94
85static void layer_surface_closed(void *_output, 95static void layer_surface_closed(void *_output,
@@ -325,27 +335,22 @@ static void output_geometry(void *data, struct wl_output *wl_output, int32_t x,
325 const char *make, const char *model, int32_t transform) { 335 const char *make, const char *model, int32_t transform) {
326 struct swaybar_output *output = data; 336 struct swaybar_output *output = data;
327 output->subpixel = subpixel; 337 output->subpixel = subpixel;
328 if (output->surface) {
329 render_frame(output->bar, output);
330 }
331} 338}
332 339
333static void output_mode(void *data, struct wl_output *output, uint32_t flags, 340static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
334 int32_t width, int32_t height, int32_t refresh) { 341 int32_t width, int32_t height, int32_t refresh) {
335 // Who cares 342 // Who cares
336} 343}
337 344
338static void output_done(void *data, struct wl_output *output) { 345static void output_done(void *data, struct wl_output *wl_output) {
339 // Who cares 346 struct swaybar_output *output = data;
347 set_output_dirty(output);
340} 348}
341 349
342static void output_scale(void *data, struct wl_output *wl_output, 350static void output_scale(void *data, struct wl_output *wl_output,
343 int32_t factor) { 351 int32_t factor) {
344 struct swaybar_output *output = data; 352 struct swaybar_output *output = data;
345 output->scale = factor; 353 output->scale = factor;
346 if (output->surface) {
347 render_frame(output->bar, output);
348 }
349} 354}
350 355
351struct wl_output_listener output_listener = { 356struct wl_output_listener output_listener = {
@@ -381,7 +386,7 @@ static void xdg_output_handle_done(void *data,
381 wl_list_insert(&bar->outputs, &output->link); 386 wl_list_insert(&bar->outputs, &output->link);
382 387
383 add_layer_surface(output); 388 add_layer_surface(output);
384 render_frame(bar, output); 389 set_output_dirty(output);
385 } 390 }
386} 391}
387 392
@@ -470,12 +475,10 @@ static const struct wl_registry_listener registry_listener = {
470 .global_remove = handle_global_remove, 475 .global_remove = handle_global_remove,
471}; 476};
472 477
473static void render_all_frames(struct swaybar *bar) { 478static void set_bar_dirty(struct swaybar *bar) {
474 struct swaybar_output *output; 479 struct swaybar_output *output;
475 wl_list_for_each(output, &bar->outputs, link) { 480 wl_list_for_each(output, &bar->outputs, link) {
476 if (output->surface != NULL) { 481 set_output_dirty(output);
477 render_frame(bar, output);
478 }
479 } 482 }
480} 483}
481 484
@@ -528,7 +531,7 @@ bool bar_setup(struct swaybar *bar,
528 assert(pointer->cursor_surface); 531 assert(pointer->cursor_surface);
529 532
530 ipc_get_workspaces(bar); 533 ipc_get_workspaces(bar);
531 render_all_frames(bar); 534 set_bar_dirty(bar);
532 return true; 535 return true;
533} 536}
534 537
@@ -543,7 +546,7 @@ static void display_in(int fd, short mask, void *data) {
543static void ipc_in(int fd, short mask, void *data) { 546static void ipc_in(int fd, short mask, void *data) {
544 struct swaybar *bar = data; 547 struct swaybar *bar = data;
545 if (handle_ipc_readable(bar)) { 548 if (handle_ipc_readable(bar)) {
546 render_all_frames(bar); 549 set_bar_dirty(bar);
547 } 550 }
548} 551}
549 552
@@ -551,10 +554,10 @@ static void status_in(int fd, short mask, void *data) {
551 struct swaybar *bar = data; 554 struct swaybar *bar = data;
552 if (mask & (POLLHUP | POLLERR)) { 555 if (mask & (POLLHUP | POLLERR)) {
553 status_error(bar->status, "[error reading from status command]"); 556 status_error(bar->status, "[error reading from status command]");
554 render_all_frames(bar); 557 set_bar_dirty(bar);
555 remove_event(fd); 558 remove_event(fd);
556 } else if (status_handle_readable(bar->status)) { 559 } else if (status_handle_readable(bar->status)) {
557 render_all_frames(bar); 560 set_bar_dirty(bar);
558 } 561 }
559} 562}
560 563
diff --git a/swaybar/config.c b/swaybar/config.c
index db7b0db6..4e851cca 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -22,7 +22,7 @@ uint32_t parse_position(const char *position) {
22 } 22 }
23} 23}
24 24
25struct swaybar_config *init_config() { 25struct swaybar_config *init_config(void) {
26 struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); 26 struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config));
27 config->status_command = NULL; 27 config->status_command = NULL;
28 config->pango_markup = false; 28 config->pango_markup = false;
diff --git a/swaybar/render.c b/swaybar/render.c
index 90e5bac7..dc31a5ea 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -473,7 +473,22 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) {
473 return max_height > output->height ? max_height : output->height; 473 return max_height > output->height ? max_height : output->height;
474} 474}
475 475
476void render_frame(struct swaybar *bar, struct swaybar_output *output) { 476static void output_frame_handle_done(void *data, struct wl_callback *callback,
477 uint32_t time) {
478 wl_callback_destroy(callback);
479 struct swaybar_output *output = data;
480 output->frame_scheduled = false;
481 if (output->dirty) {
482 render_frame(output);
483 output->dirty = false;
484 }
485}
486
487static const struct wl_callback_listener output_frame_listener = {
488 .done = output_frame_handle_done
489};
490
491void render_frame(struct swaybar_output *output) {
477 assert(output->surface != NULL); 492 assert(output->surface != NULL);
478 493
479 struct swaybar_hotspot *hotspot, *tmp; 494 struct swaybar_hotspot *hotspot, *tmp;
@@ -518,6 +533,8 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) {
518 output->width * output->scale, 533 output->width * output->scale,
519 output->height * output->scale); 534 output->height * output->scale);
520 if (!output->current_buffer) { 535 if (!output->current_buffer) {
536 cairo_surface_destroy(recorder);
537 cairo_destroy(cairo);
521 return; 538 return;
522 } 539 }
523 cairo_t *shm = output->current_buffer->cairo; 540 cairo_t *shm = output->current_buffer->cairo;
@@ -535,6 +552,11 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) {
535 output->current_buffer->buffer, 0, 0); 552 output->current_buffer->buffer, 0, 0);
536 wl_surface_damage(output->surface, 0, 0, 553 wl_surface_damage(output->surface, 0, 0,
537 output->width, output->height); 554 output->width, output->height);
555
556 struct wl_callback *frame_callback = wl_surface_frame(output->surface);
557 wl_callback_add_listener(frame_callback, &output_frame_listener, output);
558 output->frame_scheduled = true;
559
538 wl_surface_commit(output->surface); 560 wl_surface_commit(output->surface);
539 } 561 }
540 cairo_surface_destroy(recorder); 562 cairo_surface_destroy(recorder);
diff --git a/swayidle/main.c b/swayidle/main.c
index 678d622f..5b6c95a7 100644
--- a/swayidle/main.c
+++ b/swayidle/main.c
@@ -92,7 +92,7 @@ static int release_lock(void *data) {
92 return 0; 92 return 0;
93} 93}
94 94
95void acquire_sleep_lock() { 95void acquire_sleep_lock(void) {
96 sd_bus_message *msg = NULL; 96 sd_bus_message *msg = NULL;
97 sd_bus_error error = SD_BUS_ERROR_NULL; 97 sd_bus_error error = SD_BUS_ERROR_NULL;
98 struct sd_bus *bus; 98 struct sd_bus *bus;
@@ -161,7 +161,7 @@ static int dbus_event(int fd, uint32_t mask, void *data) {
161 return 1; 161 return 1;
162} 162}
163 163
164void setup_sleep_listener() { 164void setup_sleep_listener(void) {
165 struct sd_bus *bus; 165 struct sd_bus *bus;
166 166
167 int ret = sd_bus_default_system(&bus); 167 int ret = sd_bus_default_system(&bus);
diff --git a/swaylock/main.c b/swaylock/main.c
index 693cbc10..ed8c5607 100644
--- a/swaylock/main.c
+++ b/swaylock/main.c
@@ -32,7 +32,7 @@ void sway_terminate(int exit_code) {
32 exit(exit_code); 32 exit(exit_code);
33} 33}
34 34
35static void daemonize() { 35static void daemonize(void) {
36 int fds[2]; 36 int fds[2];
37 if (pipe(fds) != 0) { 37 if (pipe(fds) != 0) {
38 wlr_log(WLR_ERROR, "Failed to pipe"); 38 wlr_log(WLR_ERROR, "Failed to pipe");
diff --git a/swaynag/config.c b/swaynag/config.c
index 4d0824c9..cd34dcc2 100644
--- a/swaynag/config.c
+++ b/swaynag/config.c
@@ -11,7 +11,7 @@
11#include "util.h" 11#include "util.h"
12#include "wlr-layer-shell-unstable-v1-client-protocol.h" 12#include "wlr-layer-shell-unstable-v1-client-protocol.h"
13 13
14static char *read_from_stdin() { 14static char *read_from_stdin(void) {
15 char *buffer = NULL; 15 char *buffer = NULL;
16 while (!feof(stdin)) { 16 while (!feof(stdin)) {
17 char *line = read_line(stdin); 17 char *line = read_line(stdin);