summaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/main.c2
-rw-r--r--swaybar/tray/host.c4
-rw-r--r--swaybar/tray/item.c151
-rw-r--r--swaybar/tray/tray.c2
4 files changed, 94 insertions, 65 deletions
diff --git a/swaybar/main.c b/swaybar/main.c
index 06238c62..fa99b1ba 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
76 if (debug) { 76 if (debug) {
77 wlr_log_init(WLR_DEBUG, NULL); 77 wlr_log_init(WLR_DEBUG, NULL);
78 } else { 78 } else {
79 wlr_log_init(WLR_ERROR, NULL); 79 wlr_log_init(WLR_INFO, NULL);
80 } 80 }
81 81
82 if (!swaybar.id) { 82 if (!swaybar.id) {
diff --git a/swaybar/tray/host.c b/swaybar/tray/host.c
index 30339fec..cc8dd188 100644
--- a/swaybar/tray/host.c
+++ b/swaybar/tray/host.c
@@ -21,7 +21,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
21static void add_sni(struct swaybar_tray *tray, char *id) { 21static void add_sni(struct swaybar_tray *tray, char *id) {
22 int idx = list_seq_find(tray->items, cmp_sni_id, id); 22 int idx = list_seq_find(tray->items, cmp_sni_id, id);
23 if (idx == -1) { 23 if (idx == -1) {
24 wlr_log(WLR_DEBUG, "Registering Status Notifier Item '%s'", id); 24 wlr_log(WLR_INFO, "Registering Status Notifier Item '%s'", id);
25 struct swaybar_sni *sni = create_sni(id, tray); 25 struct swaybar_sni *sni = create_sni(id, tray);
26 if (sni) { 26 if (sni) {
27 list_add(tray->items, sni); 27 list_add(tray->items, sni);
@@ -54,7 +54,7 @@ static int handle_sni_unregistered(sd_bus_message *msg, void *data,
54 struct swaybar_tray *tray = data; 54 struct swaybar_tray *tray = data;
55 int idx = list_seq_find(tray->items, cmp_sni_id, id); 55 int idx = list_seq_find(tray->items, cmp_sni_id, id);
56 if (idx != -1) { 56 if (idx != -1) {
57 wlr_log(WLR_DEBUG, "Unregistering Status Notifier Item '%s'", id); 57 wlr_log(WLR_INFO, "Unregistering Status Notifier Item '%s'", id);
58 destroy_sni(tray->items->items[idx]); 58 destroy_sni(tray->items->items[idx]);
59 list_del(tray->items, idx); 59 list_del(tray->items, idx);
60 set_bar_dirty(tray->bar); 60 set_bar_dirty(tray->bar);
diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c
index 41cacd16..0833dcb9 100644
--- a/swaybar/tray/item.c
+++ b/swaybar/tray/item.c
@@ -19,7 +19,7 @@
19// TODO menu 19// TODO menu
20 20
21static bool sni_ready(struct swaybar_sni *sni) { 21static bool sni_ready(struct swaybar_sni *sni) {
22 return sni->status && (sni->status[0] == 'N' ? 22 return sni->status && (sni->status[0] == 'N' ? // NeedsAttention
23 sni->attention_icon_name || sni->attention_icon_pixmap : 23 sni->attention_icon_name || sni->attention_icon_pixmap :
24 sni->icon_name || sni->icon_pixmap); 24 sni->icon_name || sni->icon_pixmap);
25} 25}
@@ -35,11 +35,12 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
35 const char *prop, list_t **dest) { 35 const char *prop, list_t **dest) {
36 int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)"); 36 int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)");
37 if (ret < 0) { 37 if (ret < 0) {
38 wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret)); 38 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
39 return ret; 39 return ret;
40 } 40 }
41 41
42 if (sd_bus_message_at_end(msg, 0)) { 42 if (sd_bus_message_at_end(msg, 0)) {
43 wlr_log(WLR_DEBUG, "%s %s no. of icons = 0", sni->watcher_id, prop);
43 return ret; 44 return ret;
44 } 45 }
45 46
@@ -51,14 +52,14 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
51 while (!sd_bus_message_at_end(msg, 0)) { 52 while (!sd_bus_message_at_end(msg, 0)) {
52 ret = sd_bus_message_enter_container(msg, 'r', "iiay"); 53 ret = sd_bus_message_enter_container(msg, 'r', "iiay");
53 if (ret < 0) { 54 if (ret < 0) {
54 wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret)); 55 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
55 goto error; 56 goto error;
56 } 57 }
57 58
58 int size; 59 int size;
59 ret = sd_bus_message_read(msg, "ii", NULL, &size); 60 ret = sd_bus_message_read(msg, "ii", NULL, &size);
60 if (ret < 0) { 61 if (ret < 0) {
61 wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret)); 62 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
62 goto error; 63 goto error;
63 } 64 }
64 65
@@ -66,7 +67,7 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
66 size_t npixels; 67 size_t npixels;
67 ret = sd_bus_message_read_array(msg, 'y', &pixels, &npixels); 68 ret = sd_bus_message_read_array(msg, 'y', &pixels, &npixels);
68 if (ret < 0) { 69 if (ret < 0) {
69 wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret)); 70 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
70 goto error; 71 goto error;
71 } 72 }
72 73
@@ -78,7 +79,10 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
78 79
79 sd_bus_message_exit_container(msg); 80 sd_bus_message_exit_container(msg);
80 } 81 }
82 list_free_items_and_destroy(*dest);
81 *dest = pixmaps; 83 *dest = pixmaps;
84 wlr_log(WLR_DEBUG, "%s %s no. of icons = %d", sni->watcher_id, prop,
85 pixmaps->length);
82 86
83 return ret; 87 return ret;
84error: 88error:
@@ -103,15 +107,15 @@ static int get_property_callback(sd_bus_message *msg, void *data,
103 107
104 int ret; 108 int ret;
105 if (sd_bus_message_is_method_error(msg, NULL)) { 109 if (sd_bus_message_is_method_error(msg, NULL)) {
106 sd_bus_error err = *sd_bus_message_get_error(msg); 110 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop,
107 wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, err.message); 111 sd_bus_message_get_error(msg)->message);
108 ret = -sd_bus_error_get_errno(&err); 112 ret = sd_bus_message_get_errno(msg);
109 goto cleanup; 113 goto cleanup;
110 } 114 }
111 115
112 ret = sd_bus_message_enter_container(msg, 'v', type); 116 ret = sd_bus_message_enter_container(msg, 'v', type);
113 if (ret < 0) { 117 if (ret < 0) {
114 wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret)); 118 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
115 goto cleanup; 119 goto cleanup;
116 } 120 }
117 121
@@ -121,14 +125,23 @@ static int get_property_callback(sd_bus_message *msg, void *data,
121 goto cleanup; 125 goto cleanup;
122 } 126 }
123 } else { 127 } else {
128 if (*type == 's' || *type == 'o') {
129 free(*(char **)dest);
130 }
131
124 ret = sd_bus_message_read(msg, type, dest); 132 ret = sd_bus_message_read(msg, type, dest);
125 if (ret < 0) { 133 if (ret < 0) {
126 wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, 134 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
127 strerror(-ret));
128 goto cleanup; 135 goto cleanup;
129 } else if (*type == 's' || *type == 'o') { 136 }
137
138 if (*type == 's' || *type == 'o') {
130 char **str = dest; 139 char **str = dest;
131 *str = strdup(*str); 140 *str = strdup(*str);
141 wlr_log(WLR_DEBUG, "%s %s = '%s'", sni->watcher_id, prop, *str);
142 } else if (*type == 'b') {
143 wlr_log(WLR_DEBUG, "%s %s = %s", sni->watcher_id, prop,
144 *(bool *)dest ? "true" : "false");
132 } 145 }
133 } 146 }
134 147
@@ -152,62 +165,80 @@ static void sni_get_property_async(struct swaybar_sni *sni, const char *prop,
152 sni->path, "org.freedesktop.DBus.Properties", "Get", 165 sni->path, "org.freedesktop.DBus.Properties", "Get",
153 get_property_callback, data, "ss", sni->interface, prop); 166 get_property_callback, data, "ss", sni->interface, prop);
154 if (ret < 0) { 167 if (ret < 0) {
155 wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, strerror(-ret)); 168 wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
169 }
170}
171
172/*
173 * There is a quirk in sd-bus that in some systems, it is unable to get the
174 * well-known names on the bus, so it cannot identify if an incoming signal,
175 * which uses the sender's unique name, actually matches the callback's matching
176 * sender if the callback uses a well-known name, in which case it just calls
177 * the callback and hopes for the best, resulting in false positives. In the
178 * case of NewIcon & NewAttentionIcon, this doesn't affect anything, but it
179 * means that for NewStatus, if the SNI does not definitely match the sender,
180 * then the safe thing to do is to query the status independently.
181 * This function returns 1 if the SNI definitely matches the signal sender,
182 * which is returned by the calling function to indicate that signal matching
183 * can stop since it has already found the required callback, otherwise, it
184 * returns 0, which allows matching to continue.
185 */
186static int sni_check_msg_sender(struct swaybar_sni *sni, sd_bus_message *msg,
187 const char *signal) {
188 bool has_well_known_names =
189 sd_bus_creds_get_mask(sd_bus_message_get_creds(msg)) & SD_BUS_CREDS_WELL_KNOWN_NAMES;
190 if (sni->service[0] == ':' || has_well_known_names) {
191 wlr_log(WLR_DEBUG, "%s has new %s", sni->watcher_id, signal);
192 return 1;
193 } else {
194 wlr_log(WLR_DEBUG, "%s may have new %s", sni->watcher_id, signal);
195 return 0;
156 } 196 }
157} 197}
158 198
159static int handle_new_icon(sd_bus_message *msg, void *data, sd_bus_error *error) { 199static int handle_new_icon(sd_bus_message *msg, void *data, sd_bus_error *error) {
160 struct swaybar_sni *sni = data; 200 struct swaybar_sni *sni = data;
161 wlr_log(WLR_DEBUG, "%s has new IconName", sni->watcher_id);
162
163 free(sni->icon_name);
164 sni->icon_name = NULL;
165 sni_get_property_async(sni, "IconName", "s", &sni->icon_name); 201 sni_get_property_async(sni, "IconName", "s", &sni->icon_name);
166
167 list_free_items_and_destroy(sni->icon_pixmap);
168 sni->icon_pixmap = NULL;
169 sni_get_property_async(sni, "IconPixmap", NULL, &sni->icon_pixmap); 202 sni_get_property_async(sni, "IconPixmap", NULL, &sni->icon_pixmap);
170 203 return sni_check_msg_sender(sni, msg, "icon");
171 return 0;
172} 204}
173 205
174static int handle_new_attention_icon(sd_bus_message *msg, void *data, 206static int handle_new_attention_icon(sd_bus_message *msg, void *data,
175 sd_bus_error *error) { 207 sd_bus_error *error) {
176 struct swaybar_sni *sni = data; 208 struct swaybar_sni *sni = data;
177 wlr_log(WLR_DEBUG, "%s has new AttentionIconName", sni->watcher_id);
178
179 free(sni->attention_icon_name);
180 sni->attention_icon_name = NULL;
181 sni_get_property_async(sni, "AttentionIconName", "s", &sni->attention_icon_name); 209 sni_get_property_async(sni, "AttentionIconName", "s", &sni->attention_icon_name);
182
183 list_free_items_and_destroy(sni->attention_icon_pixmap);
184 sni->attention_icon_pixmap = NULL;
185 sni_get_property_async(sni, "AttentionIconPixmap", NULL, &sni->attention_icon_pixmap); 210 sni_get_property_async(sni, "AttentionIconPixmap", NULL, &sni->attention_icon_pixmap);
186 211 return sni_check_msg_sender(sni, msg, "attention icon");
187 return 0;
188} 212}
189 213
190static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *error) { 214static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *error) {
191 char *status; 215 struct swaybar_sni *sni = data;
192 int ret = sd_bus_message_read(msg, "s", &status); 216 int ret = sni_check_msg_sender(sni, msg, "status");
193 if (ret < 0) { 217 if (ret == 1) {
194 wlr_log(WLR_DEBUG, "Failed to read new status message: %s", strerror(-ret)); 218 char *status;
219 int r = sd_bus_message_read(msg, "s", &status);
220 if (r < 0) {
221 wlr_log(WLR_ERROR, "%s new status error: %s", sni->watcher_id, strerror(-ret));
222 ret = r;
223 } else {
224 free(sni->status);
225 sni->status = strdup(status);
226 wlr_log(WLR_DEBUG, "%s has new status = '%s'", sni->watcher_id, status);
227 set_sni_dirty(sni);
228 }
195 } else { 229 } else {
196 struct swaybar_sni *sni = data; 230 sni_get_property_async(sni, "Status", "s", &sni->status);
197 free(sni->status);
198 sni->status = strdup(status);
199 wlr_log(WLR_DEBUG, "%s has new Status '%s'", sni->watcher_id, status);
200 set_sni_dirty(sni);
201 } 231 }
232
202 return ret; 233 return ret;
203} 234}
204 235
205static void sni_match_signal(struct swaybar_sni *sni, char *signal, 236static void sni_match_signal(struct swaybar_sni *sni, sd_bus_slot **slot,
206 sd_bus_message_handler_t callback) { 237 char *signal, sd_bus_message_handler_t callback) {
207 int ret = sd_bus_match_signal(sni->tray->bus, NULL, sni->service, sni->path, 238 int ret = sd_bus_match_signal(sni->tray->bus, slot, sni->service, sni->path,
208 sni->interface, signal, callback, sni); 239 sni->interface, signal, callback, sni);
209 if (ret < 0) { 240 if (ret < 0) {
210 wlr_log(WLR_DEBUG, "Failed to subscribe to signal %s: %s", signal, 241 wlr_log(WLR_ERROR, "Failed to subscribe to signal %s: %s", signal,
211 strerror(-ret)); 242 strerror(-ret));
212 } 243 }
213} 244}
@@ -241,9 +272,10 @@ struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray) {
241 sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu); 272 sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu);
242 sni_get_property_async(sni, "Menu", "o", &sni->menu); 273 sni_get_property_async(sni, "Menu", "o", &sni->menu);
243 274
244 sni_match_signal(sni, "NewIcon", handle_new_icon); 275 sni_match_signal(sni, &sni->new_icon_slot, "NewIcon", handle_new_icon);
245 sni_match_signal(sni, "NewAttentionIcon", handle_new_attention_icon); 276 sni_match_signal(sni, &sni->new_attention_icon_slot, "NewAttentionIcon",
246 sni_match_signal(sni, "NewStatus", handle_new_status); 277 handle_new_attention_icon);
278 sni_match_signal(sni, &sni->new_status_slot, "NewStatus", handle_new_status);
247 279
248 return sni; 280 return sni;
249} 281}
@@ -253,6 +285,10 @@ void destroy_sni(struct swaybar_sni *sni) {
253 return; 285 return;
254 } 286 }
255 287
288 sd_bus_slot_unref(sni->new_icon_slot);
289 sd_bus_slot_unref(sni->new_attention_icon_slot);
290 sd_bus_slot_unref(sni->new_status_slot);
291
256 free(sni->watcher_id); 292 free(sni->watcher_id);
257 free(sni->service); 293 free(sni->service);
258 free(sni->path); 294 free(sni->path);
@@ -294,18 +330,11 @@ static void handle_click(struct swaybar_sni *sni, int x, int y,
294 char *orientation = (dir = 'U' || dir == 'D') ? "vertical" : "horizontal"; 330 char *orientation = (dir = 'U' || dir == 'D') ? "vertical" : "horizontal";
295 int sign = (dir == 'U' || dir == 'L') ? -1 : 1; 331 int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
296 332
297 int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, 333 sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, sni->path,
298 sni->path, sni->interface, "Scroll", NULL, NULL, "is", 334 sni->interface, "Scroll", NULL, NULL, "is", delta*sign, orientation);
299 delta*sign, orientation);
300 if (ret < 0) {
301 wlr_log(WLR_DEBUG, "Failed to scroll on SNI: %s", strerror(-ret));
302 }
303 } else { 335 } else {
304 int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, 336 sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, sni->path,
305 sni->path, sni->interface, method, NULL, NULL, "ii", x, y); 337 sni->interface, method, NULL, NULL, "ii", x, y);
306 if (ret < 0) {
307 wlr_log(WLR_DEBUG, "Failed to click on SNI: %s", strerror(-ret));
308 }
309 } 338 }
310} 339}
311 340
@@ -317,7 +346,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
317static enum hotspot_event_handling icon_hotspot_callback( 346static enum hotspot_event_handling icon_hotspot_callback(
318 struct swaybar_output *output, struct swaybar_hotspot *hotspot, 347 struct swaybar_output *output, struct swaybar_hotspot *hotspot,
319 int x, int y, enum x11_button button, void *data) { 348 int x, int y, enum x11_button button, void *data) {
320 wlr_log(WLR_DEBUG, "Clicked on Status Notifier Item '%s'", (char *)data); 349 wlr_log(WLR_DEBUG, "Clicked on %s", (char *)data);
321 350
322 struct swaybar_tray *tray = output->bar->tray; 351 struct swaybar_tray *tray = output->bar->tray;
323 int idx = list_seq_find(tray->items, cmp_sni_id, data); 352 int idx = list_seq_find(tray->items, cmp_sni_id, data);
@@ -331,7 +360,7 @@ static enum hotspot_event_handling icon_hotspot_callback(
331 int global_y = output->output_y + (top_bar ? config->gaps.top + y: 360 int global_y = output->output_y + (top_bar ? config->gaps.top + y:
332 (int) output->output_height - config->gaps.bottom - y); 361 (int) output->output_height - config->gaps.bottom - y);
333 362
334 wlr_log(WLR_DEBUG, "Guessing click at (%d, %d)", global_x, global_y); 363 wlr_log(WLR_DEBUG, "Guessing click position at (%d, %d)", global_x, global_y);
335 handle_click(sni, global_x, global_y, button, 1); // TODO get delta from event 364 handle_click(sni, global_x, global_y, button, 1); // TODO get delta from event
336 return HOTSPOT_IGNORE; 365 return HOTSPOT_IGNORE;
337 } else { 366 } else {
@@ -396,7 +425,7 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
396 icon_size = actual_size < ideal_size ? 425 icon_size = actual_size < ideal_size ?
397 actual_size*(ideal_size/actual_size) : ideal_size; 426 actual_size*(ideal_size/actual_size) : ideal_size;
398 icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size); 427 icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size);
399 } else { // draw a sad face 428 } else { // draw a :(
400 icon_size = ideal_size*0.8; 429 icon_size = ideal_size*0.8;
401 icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size); 430 icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size);
402 cairo_t *cairo_icon = cairo_create(icon); 431 cairo_t *cairo_icon = cairo_create(icon);
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c
index acc300af..0c3517cb 100644
--- a/swaybar/tray/tray.c
+++ b/swaybar/tray/tray.c
@@ -79,7 +79,7 @@ void destroy_tray(struct swaybar_tray *tray) {
79 finish_host(&tray->host_xdg); 79 finish_host(&tray->host_xdg);
80 finish_host(&tray->host_kde); 80 finish_host(&tray->host_kde);
81 for (int i = 0; i < tray->items->length; ++i) { 81 for (int i = 0; i < tray->items->length; ++i) {
82 destroy_sni(tray->items->items[0]); 82 destroy_sni(tray->items->items[i]);
83 } 83 }
84 list_free(tray->items); 84 list_free(tray->items);
85 destroy_watcher(tray->watcher_xdg); 85 destroy_watcher(tray->watcher_xdg);