aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Ian Fan <ianfan0@gmail.com>2020-03-09 11:09:25 +0000
committerLibravatar Simon Ser <contact@emersion.fr>2020-03-30 17:31:00 +0200
commit65501f0e467efa5e5b5ac01ef098971489b2b8c9 (patch)
tree950e0644894076b22a421ed50817409f782998a0 /swaybar
parenttray: tidy code (diff)
downloadsway-65501f0e467efa5e5b5ac01ef098971489b2b8c9.tar.gz
sway-65501f0e467efa5e5b5ac01ef098971489b2b8c9.tar.zst
sway-65501f0e467efa5e5b5ac01ef098971489b2b8c9.zip
tray: track SNI callbacks
This removes any pending messages once the item is destroyed. Furthermore, this installs SNI event calbacks asynchronously in order to prevent sd-bus from bypassing pending messages.
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/tray/item.c57
-rw-r--r--swaybar/tray/watcher.c8
2 files changed, 37 insertions, 28 deletions
diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c
index 63578cd9..a5660f62 100644
--- a/swaybar/tray/item.c
+++ b/swaybar/tray/item.c
@@ -108,16 +108,9 @@ error:
108 return ret; 108 return ret;
109} 109}
110 110
111struct get_property_data {
112 struct swaybar_sni *sni;
113 const char *prop;
114 const char *type;
115 void *dest;
116};
117
118static int get_property_callback(sd_bus_message *msg, void *data, 111static int get_property_callback(sd_bus_message *msg, void *data,
119 sd_bus_error *error) { 112 sd_bus_error *error) {
120 struct get_property_data *d = data; 113 struct swaybar_sni_slot *d = data;
121 struct swaybar_sni *sni = d->sni; 114 struct swaybar_sni *sni = d->sni;
122 const char *prop = d->prop; 115 const char *prop = d->prop;
123 const char *type = d->type; 116 const char *type = d->type;
@@ -168,22 +161,26 @@ static int get_property_callback(sd_bus_message *msg, void *data,
168 set_sni_dirty(sni); 161 set_sni_dirty(sni);
169 } 162 }
170cleanup: 163cleanup:
164 wl_list_remove(&d->link);
171 free(data); 165 free(data);
172 return ret; 166 return ret;
173} 167}
174 168
175static void sni_get_property_async(struct swaybar_sni *sni, const char *prop, 169static void sni_get_property_async(struct swaybar_sni *sni, const char *prop,
176 const char *type, void *dest) { 170 const char *type, void *dest) {
177 struct get_property_data *data = malloc(sizeof(struct get_property_data)); 171 struct swaybar_sni_slot *data = calloc(1, sizeof(struct swaybar_sni_slot));
178 data->sni = sni; 172 data->sni = sni;
179 data->prop = prop; 173 data->prop = prop;
180 data->type = type; 174 data->type = type;
181 data->dest = dest; 175 data->dest = dest;
182 int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, 176 int ret = sd_bus_call_method_async(sni->tray->bus, &data->slot, sni->service,
183 sni->path, "org.freedesktop.DBus.Properties", "Get", 177 sni->path, "org.freedesktop.DBus.Properties", "Get",
184 get_property_callback, data, "ss", sni->interface, prop); 178 get_property_callback, data, "ss", sni->interface, prop);
185 if (ret < 0) { 179 if (ret >= 0) {
180 wl_list_insert(&sni->slots, &data->link);
181 } else {
186 sway_log(SWAY_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret)); 182 sway_log(SWAY_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
183 free(data);
187 } 184 }
188} 185}
189 186
@@ -254,13 +251,17 @@ static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *erro
254 return ret; 251 return ret;
255} 252}
256 253
257static void sni_match_signal(struct swaybar_sni *sni, sd_bus_slot **slot, 254static void sni_match_signal_async(struct swaybar_sni *sni, char *signal,
258 char *signal, sd_bus_message_handler_t callback) { 255 sd_bus_message_handler_t callback) {
259 int ret = sd_bus_match_signal(sni->tray->bus, slot, sni->service, sni->path, 256 struct swaybar_sni_slot *slot = calloc(1, sizeof(struct swaybar_sni_slot));
260 sni->interface, signal, callback, sni); 257 int ret = sd_bus_match_signal_async(sni->tray->bus, &slot->slot,
261 if (ret < 0) { 258 sni->service, sni->path, sni->interface, signal, callback, NULL, sni);
262 sway_log(SWAY_ERROR, "Failed to subscribe to signal %s: %s", signal, 259 if (ret >= 0) {
263 strerror(-ret)); 260 wl_list_insert(&sni->slots, &slot->link);
261 } else {
262 sway_log(SWAY_ERROR, "%s failed to subscribe to signal %s: %s",
263 sni->service, signal, strerror(-ret));
264 free(slot);
264 } 265 }
265} 266}
266 267
@@ -270,6 +271,7 @@ struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray) {
270 return NULL; 271 return NULL;
271 } 272 }
272 sni->tray = tray; 273 sni->tray = tray;
274 wl_list_init(&sni->slots);
273 sni->watcher_id = strdup(id); 275 sni->watcher_id = strdup(id);
274 char *path_ptr = strchr(id, '/'); 276 char *path_ptr = strchr(id, '/');
275 if (!path_ptr) { 277 if (!path_ptr) {
@@ -293,10 +295,9 @@ struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray) {
293 sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu); 295 sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu);
294 sni_get_property_async(sni, "Menu", "o", &sni->menu); 296 sni_get_property_async(sni, "Menu", "o", &sni->menu);
295 297
296 sni_match_signal(sni, &sni->new_icon_slot, "NewIcon", handle_new_icon); 298 sni_match_signal_async(sni, "NewIcon", handle_new_icon);
297 sni_match_signal(sni, &sni->new_attention_icon_slot, "NewAttentionIcon", 299 sni_match_signal_async(sni, "NewAttentionIcon", handle_new_attention_icon);
298 handle_new_attention_icon); 300 sni_match_signal_async(sni, "NewStatus", handle_new_status);
299 sni_match_signal(sni, &sni->new_status_slot, "NewStatus", handle_new_status);
300 301
301 return sni; 302 return sni;
302} 303}
@@ -307,11 +308,6 @@ void destroy_sni(struct swaybar_sni *sni) {
307 } 308 }
308 309
309 cairo_surface_destroy(sni->icon); 310 cairo_surface_destroy(sni->icon);
310
311 sd_bus_slot_unref(sni->new_icon_slot);
312 sd_bus_slot_unref(sni->new_attention_icon_slot);
313 sd_bus_slot_unref(sni->new_status_slot);
314
315 free(sni->watcher_id); 311 free(sni->watcher_id);
316 free(sni->service); 312 free(sni->service);
317 free(sni->path); 313 free(sni->path);
@@ -322,6 +318,13 @@ void destroy_sni(struct swaybar_sni *sni) {
322 list_free_items_and_destroy(sni->attention_icon_pixmap); 318 list_free_items_and_destroy(sni->attention_icon_pixmap);
323 free(sni->menu); 319 free(sni->menu);
324 free(sni->icon_theme_path); 320 free(sni->icon_theme_path);
321
322 struct swaybar_sni_slot *slot, *slot_tmp;
323 wl_list_for_each_safe(slot, slot_tmp, &sni->slots, link) {
324 sd_bus_slot_unref(slot->slot);
325 free(slot);
326 }
327
325 free(sni); 328 free(sni);
326} 329}
327 330
diff --git a/swaybar/tray/watcher.c b/swaybar/tray/watcher.c
index 951a0589..16afc27c 100644
--- a/swaybar/tray/watcher.c
+++ b/swaybar/tray/watcher.c
@@ -182,7 +182,13 @@ struct swaybar_watcher *create_watcher(char *protocol, sd_bus *bus) {
182 182
183 ret = sd_bus_request_name(bus, watcher->interface, 0); 183 ret = sd_bus_request_name(bus, watcher->interface, 0);
184 if (ret < 0) { 184 if (ret < 0) {
185 sway_log(SWAY_ERROR, "Failed to acquire service name: %s", strerror(-ret)); 185 if (-ret == EEXIST) {
186 sway_log(SWAY_DEBUG, "Failed to acquire service name '%s':"
187 "another tray is already running", watcher->interface);
188 } else {
189 sway_log(SWAY_ERROR, "Failed to acquire service name '%s': %s",
190 watcher->interface, strerror(-ret));
191 }
186 goto error; 192 goto error;
187 } 193 }
188 194