diff options
author | Calvin Lee <cyrus296@gmail.com> | 2017-06-07 21:32:48 -0700 |
---|---|---|
committer | Calvin Lee <cyrus296@gmail.com> | 2017-06-07 21:32:48 -0700 |
commit | 1451ee8fd13dd35227d11e393c80871c70ad90f0 (patch) | |
tree | 74a34de797c46c2734751d77b4dc4ac5694af9a7 /swaybar | |
parent | Fix cairo blending on tray icons (diff) | |
download | sway-1451ee8fd13dd35227d11e393c80871c70ad90f0.tar.gz sway-1451ee8fd13dd35227d11e393c80871c70ad90f0.tar.zst sway-1451ee8fd13dd35227d11e393c80871c70ad90f0.zip |
Reorganize Tray Code
Remove tray code from bar.c and render.c
Diffstat (limited to 'swaybar')
-rw-r--r-- | swaybar/bar.c | 60 | ||||
-rw-r--r-- | swaybar/render.c | 67 | ||||
-rw-r--r-- | swaybar/tray/tray.c | 131 |
3 files changed, 139 insertions, 119 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c index cdaf6a37..5d480b63 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -27,6 +27,9 @@ static void bar_init(struct bar *bar) { | |||
27 | bar->config = init_config(); | 27 | bar->config = init_config(); |
28 | bar->status = init_status_line(); | 28 | bar->status = init_status_line(); |
29 | bar->outputs = create_list(); | 29 | bar->outputs = create_list(); |
30 | #ifdef ENABLE_TRAY | ||
31 | bar->xembed_pid = 0; | ||
32 | #endif | ||
30 | } | 33 | } |
31 | 34 | ||
32 | static void spawn_status_cmd_proc(struct bar *bar) { | 35 | static void spawn_status_cmd_proc(struct bar *bar) { |
@@ -57,24 +60,6 @@ static void spawn_status_cmd_proc(struct bar *bar) { | |||
57 | } | 60 | } |
58 | } | 61 | } |
59 | 62 | ||
60 | #ifdef ENABLE_TRAY | ||
61 | static void spawn_xembed_sni_proxy() { | ||
62 | pid_t pid = fork(); | ||
63 | if (pid == 0) { | ||
64 | int wstatus; | ||
65 | do { | ||
66 | pid = fork(); | ||
67 | if (pid == 0) { | ||
68 | execlp("xembedsniproxy", "xembedsniproxy", NULL); | ||
69 | _exit(EXIT_FAILURE); | ||
70 | } | ||
71 | waitpid(pid, &wstatus, 0); | ||
72 | } while (!WIFEXITED(wstatus)); | ||
73 | _exit(EXIT_FAILURE); | ||
74 | } | ||
75 | } | ||
76 | #endif | ||
77 | |||
78 | struct output *new_output(const char *name) { | 63 | struct output *new_output(const char *name) { |
79 | struct output *output = malloc(sizeof(struct output)); | 64 | struct output *output = malloc(sizeof(struct output)); |
80 | output->name = strdup(name); | 65 | output->name = strdup(name); |
@@ -122,27 +107,7 @@ static void mouse_button_notify(struct window *window, int x, int y, | |||
122 | } | 107 | } |
123 | 108 | ||
124 | #ifdef ENABLE_TRAY | 109 | #ifdef ENABLE_TRAY |
125 | uint32_t tray_padding = swaybar.config->tray_padding; | 110 | tray_mouse_event(clicked_output, x, y, button, state_w); |
126 | int tray_width = window->width * window->scale; | ||
127 | |||
128 | for (int i = 0; i < clicked_output->items->length; ++i) { | ||
129 | struct sni_icon_ref *item = | ||
130 | clicked_output->items->items[i]; | ||
131 | int icon_width = cairo_image_surface_get_width(item->icon); | ||
132 | |||
133 | tray_width -= tray_padding; | ||
134 | if (x <= tray_width && x >= tray_width - icon_width) { | ||
135 | if (button == swaybar.config->activate_button) { | ||
136 | sni_activate(item->ref, x, y); | ||
137 | } else if (button == swaybar.config->context_button) { | ||
138 | sni_context_menu(item->ref, x, y); | ||
139 | } else if (button == swaybar.config->secondary_button) { | ||
140 | sni_secondary(item->ref, x, y); | ||
141 | } | ||
142 | break; | ||
143 | } | ||
144 | tray_width -= icon_width; | ||
145 | } | ||
146 | #endif | 111 | #endif |
147 | } | 112 | } |
148 | 113 | ||
@@ -235,20 +200,7 @@ void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { | |||
235 | spawn_status_cmd_proc(bar); | 200 | spawn_status_cmd_proc(bar); |
236 | 201 | ||
237 | #ifdef ENABLE_TRAY | 202 | #ifdef ENABLE_TRAY |
238 | // We should have at least one output to serve the tray to | 203 | init_tray(bar); |
239 | if (!swaybar.config->tray_output || strcmp(swaybar.config->tray_output, "none") != 0) { | ||
240 | /* Connect to the D-Bus */ | ||
241 | dbus_init(); | ||
242 | |||
243 | /* Start the SNI watcher */ | ||
244 | init_sni_watcher(); | ||
245 | |||
246 | /* Start the SNI host */ | ||
247 | init_tray(); | ||
248 | |||
249 | /* Start xembedsniproxy */ | ||
250 | spawn_xembed_sni_proxy(); | ||
251 | } | ||
252 | #endif | 204 | #endif |
253 | } | 205 | } |
254 | 206 | ||
@@ -300,6 +252,8 @@ void bar_run(struct bar *bar) { | |||
300 | 252 | ||
301 | event_loop_poll(); | 253 | event_loop_poll(); |
302 | #ifdef ENABLE_TRAY | 254 | #ifdef ENABLE_TRAY |
255 | tray_upkeep(bar); | ||
256 | |||
303 | dispatch_dbus(); | 257 | dispatch_dbus(); |
304 | #endif | 258 | #endif |
305 | } | 259 | } |
diff --git a/swaybar/render.c b/swaybar/render.c index d02ecbbb..6ec47e79 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -302,72 +302,9 @@ void render(struct output *output, struct config *config, struct status_line *li | |||
302 | cairo_paint(cairo); | 302 | cairo_paint(cairo); |
303 | 303 | ||
304 | #ifdef ENABLE_TRAY | 304 | #ifdef ENABLE_TRAY |
305 | // Tray icons | 305 | uint32_t tray_width = tray_render(output, config); |
306 | uint32_t tray_padding = config->tray_padding; | ||
307 | unsigned int tray_width = window->width * window->scale; | ||
308 | const int item_size = (window->height * window->scale) - (2 * tray_padding); | ||
309 | |||
310 | if (item_size < 0) { | ||
311 | // Can't render items if the padding is too large | ||
312 | goto no_tray; | ||
313 | } | ||
314 | |||
315 | if (config->tray_output && strcmp(config->tray_output, output->name) != 0) { | ||
316 | goto no_tray; | ||
317 | } | ||
318 | |||
319 | for (int i = 0; i < tray->items->length; ++i) { | ||
320 | struct StatusNotifierItem *item = | ||
321 | tray->items->items[i]; | ||
322 | if (!item->image) { | ||
323 | continue; | ||
324 | } | ||
325 | |||
326 | struct sni_icon_ref *render_item = NULL; | ||
327 | int j; | ||
328 | for (j = i; j < output->items->length; ++j) { | ||
329 | struct sni_icon_ref *ref = | ||
330 | output->items->items[j]; | ||
331 | if (ref->ref == item) { | ||
332 | render_item = ref; | ||
333 | break; | ||
334 | } else { | ||
335 | sni_icon_ref_free(ref); | ||
336 | list_del(output->items, j); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | if (!render_item) { | ||
341 | render_item = sni_icon_ref_create(item, item_size); | ||
342 | list_add(output->items, render_item); | ||
343 | } else if (item->dirty) { | ||
344 | // item needs re-render | ||
345 | sni_icon_ref_free(render_item); | ||
346 | output->items->items[j] = render_item = | ||
347 | sni_icon_ref_create(item, item_size); | ||
348 | } | ||
349 | |||
350 | tray_width -= tray_padding; | ||
351 | tray_width -= item_size; | ||
352 | |||
353 | cairo_operator_t op = cairo_get_operator(cairo); | ||
354 | cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); | ||
355 | cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); | ||
356 | cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); | ||
357 | cairo_fill(cairo); | ||
358 | cairo_set_operator(cairo, op); | ||
359 | |||
360 | item->dirty = false; | ||
361 | } | ||
362 | |||
363 | |||
364 | if (tray_width != window->width * window->scale) { | ||
365 | tray_width -= tray_padding; | ||
366 | } | ||
367 | |||
368 | no_tray: | ||
369 | #else | 306 | #else |
370 | const int tray_width = window->width * window->scale; | 307 | const uint32_t tray_width = window->width * window->scale; |
371 | #endif | 308 | #endif |
372 | 309 | ||
373 | // Command output | 310 | // Command output |
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c index 9a709fe4..ca8b1341 100644 --- a/swaybar/tray/tray.c +++ b/swaybar/tray/tray.c | |||
@@ -2,12 +2,15 @@ | |||
2 | #include <unistd.h> | 2 | #include <unistd.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include <sys/wait.h> | ||
5 | #include <dbus/dbus.h> | 6 | #include <dbus/dbus.h> |
6 | #include "swaybar/bar.h" | 7 | #include "swaybar/bar.h" |
7 | #include "swaybar/tray/tray.h" | 8 | #include "swaybar/tray/tray.h" |
8 | #include "swaybar/tray/dbus.h" | 9 | #include "swaybar/tray/dbus.h" |
9 | #include "swaybar/tray/sni.h" | 10 | #include "swaybar/tray/sni.h" |
11 | #include "swaybar/tray/sni_watcher.h" | ||
10 | #include "swaybar/bar.h" | 12 | #include "swaybar/bar.h" |
13 | #include "swaybar/config.h" | ||
11 | #include "list.h" | 14 | #include "list.h" |
12 | #include "log.h" | 15 | #include "log.h" |
13 | 16 | ||
@@ -184,7 +187,7 @@ static DBusHandlerResult signal_handler(DBusConnection *connection, | |||
184 | return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | 187 | return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
185 | } | 188 | } |
186 | 189 | ||
187 | int init_tray() { | 190 | static int init_host() { |
188 | tray = (struct tray *)malloc(sizeof(tray)); | 191 | tray = (struct tray *)malloc(sizeof(tray)); |
189 | 192 | ||
190 | tray->items = create_list(); | 193 | tray->items = create_list(); |
@@ -277,3 +280,129 @@ err: | |||
277 | free(name); | 280 | free(name); |
278 | return -1; | 281 | return -1; |
279 | } | 282 | } |
283 | |||
284 | void tray_mouse_event(struct output *output, int x, int y, | ||
285 | uint32_t button, uint32_t state) { | ||
286 | |||
287 | struct window *window = output->window; | ||
288 | uint32_t tray_padding = swaybar.config->tray_padding; | ||
289 | int tray_width = window->width * window->scale; | ||
290 | |||
291 | for (int i = 0; i < output->items->length; ++i) { | ||
292 | struct sni_icon_ref *item = | ||
293 | output->items->items[i]; | ||
294 | int icon_width = cairo_image_surface_get_width(item->icon); | ||
295 | |||
296 | tray_width -= tray_padding; | ||
297 | if (x <= tray_width && x >= tray_width - icon_width) { | ||
298 | if (button == swaybar.config->activate_button) { | ||
299 | sni_activate(item->ref, x, y); | ||
300 | } else if (button == swaybar.config->context_button) { | ||
301 | sni_context_menu(item->ref, x, y); | ||
302 | } else if (button == swaybar.config->secondary_button) { | ||
303 | sni_secondary(item->ref, x, y); | ||
304 | } | ||
305 | break; | ||
306 | } | ||
307 | tray_width -= icon_width; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | uint32_t tray_render(struct output *output, struct config *config) { | ||
312 | struct window *window = output->window; | ||
313 | cairo_t *cairo = window->cairo; | ||
314 | |||
315 | // Tray icons | ||
316 | uint32_t tray_padding = config->tray_padding; | ||
317 | uint32_t tray_width = window->width * window->scale; | ||
318 | const int item_size = (window->height * window->scale) - (2 * tray_padding); | ||
319 | |||
320 | if (item_size < 0) { | ||
321 | // Can't render items if the padding is too large | ||
322 | return tray_width; | ||
323 | } | ||
324 | |||
325 | if (config->tray_output && strcmp(config->tray_output, output->name) != 0) { | ||
326 | return tray_width; | ||
327 | } | ||
328 | |||
329 | for (int i = 0; i < tray->items->length; ++i) { | ||
330 | struct StatusNotifierItem *item = | ||
331 | tray->items->items[i]; | ||
332 | if (!item->image) { | ||
333 | continue; | ||
334 | } | ||
335 | |||
336 | struct sni_icon_ref *render_item = NULL; | ||
337 | int j; | ||
338 | for (j = i; j < output->items->length; ++j) { | ||
339 | struct sni_icon_ref *ref = | ||
340 | output->items->items[j]; | ||
341 | if (ref->ref == item) { | ||
342 | render_item = ref; | ||
343 | break; | ||
344 | } else { | ||
345 | sni_icon_ref_free(ref); | ||
346 | list_del(output->items, j); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | if (!render_item) { | ||
351 | render_item = sni_icon_ref_create(item, item_size); | ||
352 | list_add(output->items, render_item); | ||
353 | } else if (item->dirty) { | ||
354 | // item needs re-render | ||
355 | sni_icon_ref_free(render_item); | ||
356 | output->items->items[j] = render_item = | ||
357 | sni_icon_ref_create(item, item_size); | ||
358 | } | ||
359 | |||
360 | tray_width -= tray_padding; | ||
361 | tray_width -= item_size; | ||
362 | |||
363 | cairo_operator_t op = cairo_get_operator(cairo); | ||
364 | cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); | ||
365 | cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); | ||
366 | cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); | ||
367 | cairo_fill(cairo); | ||
368 | cairo_set_operator(cairo, op); | ||
369 | |||
370 | item->dirty = false; | ||
371 | } | ||
372 | |||
373 | |||
374 | if (tray_width != window->width * window->scale) { | ||
375 | tray_width -= tray_padding; | ||
376 | } | ||
377 | |||
378 | return tray_width; | ||
379 | } | ||
380 | |||
381 | void tray_upkeep(struct bar *bar) { | ||
382 | if (!bar->xembed_pid || | ||
383 | (bar->xembed_pid == waitpid(bar->xembed_pid, NULL, WNOHANG))) { | ||
384 | pid_t pid = fork(); | ||
385 | if (pid == 0) { | ||
386 | execlp("xembedsniproxy", "xembedsniproxy", NULL); | ||
387 | _exit(EXIT_FAILURE); | ||
388 | } else { | ||
389 | bar->xembed_pid = pid; | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | |||
394 | void init_tray(struct bar *bar) { | ||
395 | if (!bar->config->tray_output || strcmp(bar->config->tray_output, "none") != 0) { | ||
396 | /* Connect to the D-Bus */ | ||
397 | dbus_init(); | ||
398 | |||
399 | /* Start the SNI watcher */ | ||
400 | init_sni_watcher(); | ||
401 | |||
402 | /* Start the SNI host */ | ||
403 | init_host(); | ||
404 | |||
405 | /* Start xembedsniproxy */ | ||
406 | tray_upkeep(bar); | ||
407 | } | ||
408 | } | ||