aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ian Fan <ianfan0@gmail.com>2018-09-12 08:28:28 +0100
committerLibravatar Ian Fan <ianfan0@gmail.com>2018-09-12 08:28:28 +0100
commit2eaef802061836dd83bbf753174fcb8488b2d8cd (patch)
tree33fcd285cc70a6cea257b1f3b6d24121d340a270
parentMerge pull request #2620 from ianyfan/commands (diff)
downloadsway-2eaef802061836dd83bbf753174fcb8488b2d8cd.tar.gz
sway-2eaef802061836dd83bbf753174fcb8488b2d8cd.tar.zst
sway-2eaef802061836dd83bbf753174fcb8488b2d8cd.zip
i3bar: count references to blocks
This prevents blocks from being destroyed before their hotspots are destroyed, in case it is used for a pending click event that fires between the bar receiving a new status, which destroys the block, and the bar rendering the new status, which destroys the hotspot; this problem can be easily produced by scrolling on a block that immediately causes a new status to be sent, with multiple outputs
-rw-r--r--include/swaybar/status_line.h3
-rw-r--r--swaybar/i3bar.c13
-rw-r--r--swaybar/render.c7
-rw-r--r--swaybar/status_line.c2
4 files changed, 19 insertions, 6 deletions
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h
index de9b98d7..150267cd 100644
--- a/include/swaybar/status_line.h
+++ b/include/swaybar/status_line.h
@@ -36,6 +36,7 @@ struct i3bar_protocol_state {
36 36
37struct i3bar_block { 37struct i3bar_block {
38 struct wl_list link; 38 struct wl_list link;
39 int ref_count;
39 char *full_text, *short_text, *align; 40 char *full_text, *short_text, *align;
40 bool urgent; 41 bool urgent;
41 uint32_t *color; 42 uint32_t *color;
@@ -73,7 +74,7 @@ void status_line_free(struct status_line *status);
73bool i3bar_handle_readable(struct status_line *status); 74bool i3bar_handle_readable(struct status_line *status);
74enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, 75enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
75 struct i3bar_block *block, int x, int y, enum x11_button button); 76 struct i3bar_block *block, int x, int y, enum x11_button button);
76void i3bar_block_free(struct i3bar_block *block); 77void i3bar_block_unref(struct i3bar_block *block);
77enum x11_button wl_button_to_x11_button(uint32_t button); 78enum x11_button wl_button_to_x11_button(uint32_t button);
78enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value); 79enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value);
79 80
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c
index ae37eeb9..1345ee9b 100644
--- a/swaybar/i3bar.c
+++ b/swaybar/i3bar.c
@@ -8,11 +8,10 @@
8#include "swaybar/config.h" 8#include "swaybar/config.h"
9#include "swaybar/status_line.h" 9#include "swaybar/status_line.h"
10 10
11void i3bar_block_free(struct i3bar_block *block) { 11static void i3bar_block_free(struct i3bar_block *block) {
12 if (!block) { 12 if (!block) {
13 return; 13 return;
14 } 14 }
15 wl_list_remove(&block->link);
16 free(block->full_text); 15 free(block->full_text);
17 free(block->short_text); 16 free(block->short_text);
18 free(block->align); 17 free(block->align);
@@ -22,10 +21,17 @@ void i3bar_block_free(struct i3bar_block *block) {
22 free(block); 21 free(block);
23} 22}
24 23
24void i3bar_block_unref(struct i3bar_block *block) {
25 if (--block->ref_count == 0) {
26 i3bar_block_free(block);
27 }
28}
29
25static bool i3bar_parse_json(struct status_line *status, const char *text) { 30static bool i3bar_parse_json(struct status_line *status, const char *text) {
26 struct i3bar_block *block, *tmp; 31 struct i3bar_block *block, *tmp;
27 wl_list_for_each_safe(block, tmp, &status->blocks, link) { 32 wl_list_for_each_safe(block, tmp, &status->blocks, link) {
28 i3bar_block_free(block); 33 wl_list_remove(&block->link);
34 i3bar_block_unref(block);
29 } 35 }
30 json_object *results = json_tokener_parse(text); 36 json_object *results = json_tokener_parse(text);
31 if (!results) { 37 if (!results) {
@@ -61,6 +67,7 @@ static bool i3bar_parse_json(struct status_line *status, const char *text) {
61 json_object_object_get_ex(json, "border_right", &border_right); 67 json_object_object_get_ex(json, "border_right", &border_right);
62 68
63 struct i3bar_block *block = calloc(1, sizeof(struct i3bar_block)); 69 struct i3bar_block *block = calloc(1, sizeof(struct i3bar_block));
70 block->ref_count = 1;
64 block->full_text = full_text ? 71 block->full_text = full_text ?
65 strdup(json_object_get_string(full_text)) : NULL; 72 strdup(json_object_get_string(full_text)) : NULL;
66 block->short_text = short_text ? 73 block->short_text = short_text ?
diff --git a/swaybar/render.c b/swaybar/render.c
index 7303e70f..2d848bfa 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -115,6 +115,10 @@ static enum hotspot_event_handling block_hotspot_callback(struct swaybar_output
115 return i3bar_block_send_click(status, block, x, y, button); 115 return i3bar_block_send_click(status, block, x, y, button);
116} 116}
117 117
118static void i3bar_block_unref_callback(void *data) {
119 i3bar_block_unref(data);
120}
121
118static uint32_t render_status_block(cairo_t *cairo, 122static uint32_t render_status_block(cairo_t *cairo,
119 struct swaybar_config *config, struct swaybar_output *output, 123 struct swaybar_config *config, struct swaybar_output *output,
120 struct i3bar_block *block, double *x, 124 struct i3bar_block *block, double *x,
@@ -179,8 +183,9 @@ static uint32_t render_status_block(cairo_t *cairo,
179 hotspot->width = width; 183 hotspot->width = width;
180 hotspot->height = height; 184 hotspot->height = height;
181 hotspot->callback = block_hotspot_callback; 185 hotspot->callback = block_hotspot_callback;
182 hotspot->destroy = NULL; 186 hotspot->destroy = i3bar_block_unref_callback;
183 hotspot->data = block; 187 hotspot->data = block;
188 block->ref_count++;
184 wl_list_insert(&output->hotspots, &hotspot->link); 189 wl_list_insert(&output->hotspots, &hotspot->link);
185 190
186 double pos = *x; 191 double pos = *x;
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index bc47580b..3ba990bd 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -130,7 +130,7 @@ void status_line_free(struct status_line *status) {
130 case PROTOCOL_I3BAR:; 130 case PROTOCOL_I3BAR:;
131 struct i3bar_block *block, *tmp; 131 struct i3bar_block *block, *tmp;
132 wl_list_for_each_safe(block, tmp, &status->blocks, link) { 132 wl_list_for_each_safe(block, tmp, &status->blocks, link) {
133 i3bar_block_free(block); 133 i3bar_block_unref(block);
134 } 134 }
135 free(status->i3bar_state.buffer); 135 free(status->i3bar_state.buffer);
136 break; 136 break;