Skip to content

Commit c8d687d

Browse files
committed
make sni asynchronous :( cleanup )
1 parent 6ffc149 commit c8d687d

File tree

2 files changed

+102
-91
lines changed

2 files changed

+102
-91
lines changed

swaybar/tray/host.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111

1212
static void add_sni(struct swaybar_tray *tray, char *id) {
1313
wlr_log(WLR_DEBUG, "Registering Status Notifier Item '%s'", id);
14-
list_add(tray->items, create_sni(id, tray));
15-
set_bar_dirty(tray->bar);
14+
struct swaybar_sni *sni = create_sni(id, tray);
15+
if (sni) {
16+
list_add(tray->items, sni);
17+
}
1618
}
1719

1820
static int handle_sni_registered(sd_bus_message *msg, void *data,

swaybar/tray/item.c

Lines changed: 98 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,28 @@
1818

1919
// TODO implement menu, and use IconThemePath
2020

21-
static void sni_get_pixmap(struct swaybar_sni *sni, char *prop, list_t **dest) {
22-
sd_bus_error error = SD_BUS_ERROR_NULL;
23-
sd_bus_message *msg;
24-
int ret = sd_bus_get_property(sni->tray->bus, sni->service, sni->path,
25-
sni->interface, prop, &error, &msg, "a(iiay)");
26-
if (ret < 0) {
27-
wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, error.message);
28-
sd_bus_error_free(&error);
29-
return;
30-
}
21+
static bool sni_ready(struct swaybar_sni *sni) {
22+
return sni->status && (sni->status[0] == 'N' ?
23+
sni->attention_icon_name || sni->attention_icon_pixmap :
24+
sni->icon_name || sni->icon_pixmap);
25+
}
26+
27+
static void set_sni_dirty(struct swaybar_sni *sni) {
28+
sni->min_size = sni->max_size = 0; // invalidate previous icon
29+
set_bar_dirty(sni->tray->bar);
30+
}
3131

32-
ret = sd_bus_message_enter_container(msg, 'a', "(iiay)");
32+
static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
33+
const char *prop, list_t **dest) {
34+
int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)");
3335
if (ret < 0) {
3436
wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
35-
return;
37+
return ret;
3638
}
3739

3840
list_t *pixmaps = create_list();
3941
if (!pixmaps) {
40-
return;
42+
return -12; // -ENOMEM
4143
}
4244

4345
while (!sd_bus_message_at_end(msg, 0)) {
@@ -46,6 +48,7 @@ static void sni_get_pixmap(struct swaybar_sni *sni, char *prop, list_t **dest) {
4648
wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
4749
goto cleanup;
4850
}
51+
4952
int size;
5053
ret = sd_bus_message_read(msg, "ii", NULL, &size);
5154
if (ret < 0) {
@@ -71,67 +74,108 @@ static void sni_get_pixmap(struct swaybar_sni *sni, char *prop, list_t **dest) {
7174
}
7275
*dest = pixmaps;
7376

74-
sd_bus_message_unref(msg);
75-
return;
77+
return ret;
7678
cleanup:
77-
sd_bus_message_unref(msg);
7879
list_free_items_and_destroy(pixmaps);
80+
return ret;
7981
}
8082

81-
static void sni_get_property(struct swaybar_sni *sni, char *prop, char *type,
82-
void *dest) {
83-
sd_bus_error error = SD_BUS_ERROR_NULL;
84-
sd_bus_message *msg;
85-
int ret = sd_bus_get_property(sni->tray->bus, sni->service, sni->path,
86-
sni->interface, prop, &error, &msg, type);
83+
struct get_property_data {
84+
struct swaybar_sni *sni;
85+
const char *prop;
86+
const char *type;
87+
void *dest;
88+
};
89+
90+
static int get_property_callback(sd_bus_message *msg, void *data,
91+
sd_bus_error *error) {
92+
struct get_property_data *d = data;
93+
struct swaybar_sni *sni = d->sni;
94+
const char *prop = d->prop;
95+
const char *type = d->type;
96+
void *dest = d->dest;
97+
98+
int ret = 0;
99+
if (sd_bus_message_is_method_error(msg, NULL)) {
100+
sd_bus_error err = *sd_bus_message_get_error(msg);
101+
wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, err.message);
102+
goto cleanup;
103+
}
104+
105+
ret = sd_bus_message_enter_container(msg, 'v', type);
87106
if (ret < 0) {
88-
wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, error.message);
89-
sd_bus_error_free(&error);
107+
wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
108+
goto cleanup;
109+
}
110+
111+
if (!type) {
112+
ret = read_pixmap(msg, sni, prop, dest);
113+
if (ret < 0) {
114+
goto cleanup;
115+
}
90116
} else {
91117
ret = sd_bus_message_read(msg, type, dest);
92118
if (ret < 0) {
93-
wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
119+
wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop,
120+
strerror(-ret));
121+
goto cleanup;
94122
} else if (*type == 's' || *type == 'o') {
95123
char **str = dest;
96124
*str = strdup(*str);
97125
}
98-
sd_bus_message_unref(msg);
99126
}
127+
128+
if (sni_ready(sni)) {
129+
set_sni_dirty(sni);
130+
}
131+
132+
cleanup:
133+
free(data);
134+
return ret;
100135
}
101136

102-
static void set_sni_dirty(struct swaybar_sni *sni) {
103-
sni->min_size = sni->max_size = 0; // invalidate previous icon
104-
set_bar_dirty(sni->tray->bar);
137+
static void sni_get_property_async(struct swaybar_sni *sni, const char *prop,
138+
const char *type, void *dest) {
139+
struct get_property_data *data = malloc(sizeof(struct get_property_data));
140+
data->sni = sni;
141+
data->prop = prop;
142+
data->type = type;
143+
data->dest = dest;
144+
int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service,
145+
sni->path, "org.freedesktop.DBus.Properties", "Get",
146+
get_property_callback, data, "ss", sni->interface, prop);
147+
if (ret < 0) {
148+
wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, strerror(-ret));
149+
}
105150
}
106151

107152
static int handle_new_icon(sd_bus_message *msg, void *data, sd_bus_error *error) {
108153
struct swaybar_sni *sni = data;
154+
wlr_log(WLR_DEBUG, "%s has new IconName", sni->watcher_id);
155+
109156
free(sni->icon_name);
110-
sni_get_property(sni, "IconName", "s", &sni->icon_name);
111-
list_free_items_and_destroy(sni->icon_pixmap);
112-
sni_get_pixmap(sni, "IconPixmap", &sni->icon_pixmap);
113-
wlr_log(WLR_DEBUG, "%s has new IconName='%s'", sni->watcher_id, sni->icon_name);
157+
sni->icon_name = NULL;
158+
sni_get_property_async(sni, "IconName", "s", &sni->icon_name);
114159

115-
if (sni->status[0] != 'N') {
116-
set_sni_dirty(sni);
117-
}
160+
list_free_items_and_destroy(sni->icon_pixmap);
161+
sni->icon_pixmap = NULL;
162+
sni_get_property_async(sni, "IconPixmap", NULL, &sni->icon_pixmap);
118163

119164
return 0;
120165
}
121166

122167
static int handle_new_attention_icon(sd_bus_message *msg, void *data,
123168
sd_bus_error *error) {
124169
struct swaybar_sni *sni = data;
170+
wlr_log(WLR_DEBUG, "%s has new AttentionIconName", sni->watcher_id);
171+
125172
free(sni->attention_icon_name);
126-
sni_get_property(sni, "AttentionIconName", "s", &sni->attention_icon_name);
127-
list_free_items_and_destroy(sni->attention_icon_pixmap);
128-
sni_get_pixmap(sni, "IconPixmap", &sni->attention_icon_pixmap);
129-
wlr_log(WLR_DEBUG, "%s has new AttentionIconName='%s'", sni->watcher_id,
130-
sni->attention_icon_name);
173+
sni->attention_icon_name = NULL;
174+
sni_get_property_async(sni, "AttentionIconName", "s", &sni->attention_icon_name);
131175

132-
if (sni->status[0] == 'N') {
133-
set_sni_dirty(sni);
134-
}
176+
list_free_items_and_destroy(sni->attention_icon_pixmap);
177+
sni->attention_icon_pixmap = NULL;
178+
sni_get_property_async(sni, "AttentionIconPixmap", NULL, &sni->attention_icon_pixmap);
135179

136180
return 0;
137181
}
@@ -145,7 +189,7 @@ static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *erro
145189
struct swaybar_sni *sni = data;
146190
free(sni->status);
147191
sni->status = strdup(status);
148-
wlr_log(WLR_DEBUG, "%s has new Status='%s'", sni->watcher_id, status);
192+
wlr_log(WLR_DEBUG, "%s has new Status '%s'", sni->watcher_id, status);
149193
set_sni_dirty(sni);
150194
}
151195
return ret;
@@ -181,18 +225,13 @@ struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray) {
181225

182226
// Ignored: Category, Id, Title, WindowId, OverlayIconName,
183227
// OverlayIconPixmap, AttentionMovieName, ToolTip
184-
sni_get_property(sni, "Status", "s", &sni->status);
185-
sni_get_property(sni, "IconName", "s", &sni->icon_name);
186-
sni_get_pixmap(sni, "IconPixmap", &sni->icon_pixmap);
187-
sni_get_property(sni, "AttentionIconName", "s", &sni->attention_icon_name);
188-
sni_get_pixmap(sni, "AttentionIconPixmap", &sni->attention_icon_pixmap);
189-
sni_get_property(sni, "ItemIsMenu", "b", &sni->item_is_menu);
190-
sni_get_property(sni, "Menu", "o", &sni->menu);
191-
192-
wlr_log(WLR_DEBUG, "Properties: Status='%s' IconName='%s' "
193-
"AttentionIconName='%s' ItemIsMenu=%s Menu='%s'",
194-
sni->status, sni->icon_name, sni->attention_icon_name,
195-
sni->item_is_menu ? "true" : "false", sni->menu);
228+
sni_get_property_async(sni, "Status", "s", &sni->status);
229+
sni_get_property_async(sni, "IconName", "s", &sni->icon_name);
230+
sni_get_property_async(sni, "IconPixmap", NULL, &sni->icon_pixmap);
231+
sni_get_property_async(sni, "AttentionIconName", "s", &sni->attention_icon_name);
232+
sni_get_property_async(sni, "AttentionIconPixmap", NULL, &sni->attention_icon_pixmap);
233+
sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu);
234+
sni_get_property_async(sni, "Menu", "o", &sni->menu);
196235

197236
sni_match_signal(sni, "NewIcon", handle_new_icon);
198237
sni_match_signal(sni, "NewAttentionIcon", handle_new_attention_icon);
@@ -292,43 +331,12 @@ static enum hotspot_event_handling icon_hotspot_callback(
292331
return HOTSPOT_PROCESS;
293332
}
294333

295-
static bool sni_ready(struct swaybar_sni *sni) { // TODO remove
296-
if (!sni->status) {
297-
sni_get_property(sni, "Status", "s", &sni->status);
298-
if (!sni->status) {
299-
return false;
300-
}
301-
}
302-
303-
if (sni->status[0] == 'N') { // NeedsAttention
304-
if (!sni->attention_icon_name) {
305-
sni_get_property(sni, "AttentionIconName", "s", &sni->attention_icon_name);
306-
}
307-
if (!sni->attention_icon_name && !sni->attention_icon_pixmap) {
308-
sni_get_pixmap(sni, "AttentionIconPixmap", &sni->attention_icon_pixmap);
309-
}
310-
return sni->attention_icon_name || sni->attention_icon_pixmap;
311-
} else {
312-
if (!sni->icon_name) {
313-
sni_get_property(sni, "IconName", "s", &sni->icon_name);
314-
}
315-
if (!sni->icon_name && !sni->icon_pixmap) {
316-
sni_get_pixmap(sni, "IconPixmap", &sni->icon_pixmap);
317-
}
318-
return sni->icon_name || sni->icon_pixmap;
319-
}
320-
}
321-
322334
uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
323335
struct swaybar_sni *sni) {
324-
if (!sni_ready(sni)) {
325-
return 0;
326-
}
327336
uint32_t height = output->height * output->scale;
328337
int padding = output->bar->config->tray_padding;
329338
int ideal_size = height - 2*padding;
330-
331-
if (ideal_size < sni->min_size || ideal_size > sni->max_size) {
339+
if ((ideal_size < sni->min_size || ideal_size > sni->max_size) && sni_ready(sni)) {
332340
bool icon_found = false;
333341
char *icon_name = sni->status[0] == 'N' ?
334342
sni->attention_icon_name : sni->icon_name;
@@ -367,6 +375,7 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
367375
}
368376
}
369377
if (!sni->icon) {
378+
// TODO fallback
370379
return 0;
371380
}
372381

0 commit comments

Comments
 (0)