aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Calvin Lee <cyrus296@gmail.com>2017-06-07 21:32:48 -0700
committerLibravatar Calvin Lee <cyrus296@gmail.com>2017-06-07 21:32:48 -0700
commit1451ee8fd13dd35227d11e393c80871c70ad90f0 (patch)
tree74a34de797c46c2734751d77b4dc4ac5694af9a7
parentFix cairo blending on tray icons (diff)
downloadsway-1451ee8fd13dd35227d11e393c80871c70ad90f0.tar.gz
sway-1451ee8fd13dd35227d11e393c80871c70ad90f0.tar.zst
sway-1451ee8fd13dd35227d11e393c80871c70ad90f0.zip
Reorganize Tray Code
Remove tray code from bar.c and render.c
-rw-r--r--include/swaybar/bar.h3
-rw-r--r--include/swaybar/tray/tray.h14
-rw-r--r--swaybar/bar.c60
-rw-r--r--swaybar/render.c67
-rw-r--r--swaybar/tray/tray.c131
5 files changed, 152 insertions, 123 deletions
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h
index 010e1f84..9f5bf400 100644
--- a/include/swaybar/bar.h
+++ b/include/swaybar/bar.h
@@ -15,6 +15,9 @@ struct bar {
15 int ipc_socketfd; 15 int ipc_socketfd;
16 int status_read_fd; 16 int status_read_fd;
17 pid_t status_command_pid; 17 pid_t status_command_pid;
18#ifdef ENABLE_TRAY
19 pid_t xembed_pid;
20#endif
18}; 21};
19 22
20struct output { 23struct output {
diff --git a/include/swaybar/tray/tray.h b/include/swaybar/tray/tray.h
index 7d371008..b718e555 100644
--- a/include/swaybar/tray/tray.h
+++ b/include/swaybar/tray/tray.h
@@ -5,6 +5,7 @@
5#include <stdbool.h> 5#include <stdbool.h>
6#include "swaybar/tray/dbus.h" 6#include "swaybar/tray/dbus.h"
7#include "swaybar/tray/sni.h" 7#include "swaybar/tray/sni.h"
8#include "swaybar/bar.h"
8#include "list.h" 9#include "list.h"
9 10
10extern struct tray *tray; 11extern struct tray *tray;
@@ -14,13 +15,18 @@ struct tray {
14}; 15};
15 16
16/** 17/**
17 * Initializes the tray host with D-Bus 18 * Processes a mouse event on the bar
18 */ 19 */
19int init_tray(); 20void tray_mouse_event(struct output *output, int x, int y,
21 uint32_t button, uint32_t state);
22
23uint32_t tray_render(struct output *output, struct config *config);
24
25void tray_upkeep(struct bar *bar);
20 26
21/** 27/**
22 * Returns an item if `x` and `y` collide with it and NULL otherwise 28 * Initializes the tray with D-Bus
23 */ 29 */
24struct StatusNotifierItem *collides_with_sni(int x, int y); 30void init_tray();
25 31
26#endif /* _SWAYBAR_TRAY_H */ 32#endif /* _SWAYBAR_TRAY_H */
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
32static void spawn_status_cmd_proc(struct bar *bar) { 35static 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
61static 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
78struct output *new_output(const char *name) { 63struct 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
368no_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
187int init_tray() { 190static 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
284void 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
311uint32_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
381void 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
394void 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}