aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/CMakeLists.txt2
-rw-r--r--swaybar/bar.c71
-rw-r--r--swaybar/event_loop.c5
-rw-r--r--swaybar/render.c3
-rw-r--r--swaybar/status_line.c81
-rw-r--r--swaybar/tray/dbus.c8
-rw-r--r--swaybar/tray/icon.c2
-rw-r--r--swaybar/tray/sni.c10
-rw-r--r--swaybar/tray/sni_watcher.c14
-rw-r--r--swaybar/tray/tray.c17
10 files changed, 188 insertions, 25 deletions
diff --git a/swaybar/CMakeLists.txt b/swaybar/CMakeLists.txt
index 373719de..48ededdd 100644
--- a/swaybar/CMakeLists.txt
+++ b/swaybar/CMakeLists.txt
@@ -7,7 +7,7 @@ include_directories(
7 ${XKBCOMMON_INCLUDE_DIRS} 7 ${XKBCOMMON_INCLUDE_DIRS}
8 ${DBUS_INCLUDE_DIRS} 8 ${DBUS_INCLUDE_DIRS}
9) 9)
10if (enable-tray) 10if (ENABLE_TRAY)
11 file(GLOB tray 11 file(GLOB tray
12 tray/*.c 12 tray/*.c
13 ) 13 )
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 5e87eac9..f8dc3a1f 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -7,6 +7,7 @@
7#include <sys/wait.h> 7#include <sys/wait.h>
8#include <signal.h> 8#include <signal.h>
9#include <poll.h> 9#include <poll.h>
10#include <linux/input-event-codes.h>
10#ifdef ENABLE_TRAY 11#ifdef ENABLE_TRAY
11#include <dbus/dbus.h> 12#include <dbus/dbus.h>
12#include "swaybar/tray/sni_watcher.h" 13#include "swaybar/tray/sni_watcher.h"
@@ -31,16 +32,30 @@ static void bar_init(struct bar *bar) {
31 32
32static void spawn_status_cmd_proc(struct bar *bar) { 33static void spawn_status_cmd_proc(struct bar *bar) {
33 if (bar->config->status_command) { 34 if (bar->config->status_command) {
34 int pipefd[2]; 35 int pipe_read_fd[2];
35 if (pipe(pipefd) != 0) { 36 int pipe_write_fd[2];
36 sway_log(L_ERROR, "Unable to create pipe for status_command fork"); 37
38 if (pipe(pipe_read_fd) != 0) {
39 sway_log(L_ERROR, "Unable to create pipes for status_command fork");
40 return;
41 }
42 if (pipe(pipe_write_fd) != 0) {
43 sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)");
44 close(pipe_read_fd[0]);
45 close(pipe_read_fd[1]);
37 return; 46 return;
38 } 47 }
48
39 bar->status_command_pid = fork(); 49 bar->status_command_pid = fork();
40 if (bar->status_command_pid == 0) { 50 if (bar->status_command_pid == 0) {
41 close(pipefd[0]); 51 close(pipe_read_fd[0]);
42 dup2(pipefd[1], STDOUT_FILENO); 52 dup2(pipe_read_fd[1], STDOUT_FILENO);
43 close(pipefd[1]); 53 close(pipe_read_fd[1]);
54
55 dup2(pipe_write_fd[0], STDIN_FILENO);
56 close(pipe_write_fd[0]);
57 close(pipe_write_fd[1]);
58
44 char *const cmd[] = { 59 char *const cmd[] = {
45 "sh", 60 "sh",
46 "-c", 61 "-c",
@@ -51,9 +66,13 @@ static void spawn_status_cmd_proc(struct bar *bar) {
51 return; 66 return;
52 } 67 }
53 68
54 close(pipefd[1]); 69 close(pipe_read_fd[1]);
55 bar->status_read_fd = pipefd[0]; 70 bar->status_read_fd = pipe_read_fd[0];
56 fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK); 71 fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK);
72
73 close(pipe_write_fd[0]);
74 bar->status_write_fd = pipe_write_fd[1];
75 fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK);
57 } 76 }
58} 77}
59 78
@@ -103,14 +122,46 @@ static void mouse_button_notify(struct window *window, int x, int y,
103 } 122 }
104 } 123 }
105 124
125 switch (button) {
126 case BTN_LEFT:
127 status_line_mouse_event(&swaybar, x, y, 1);
128 break;
129 case BTN_MIDDLE:
130 status_line_mouse_event(&swaybar, x, y, 2);
131 break;
132 case BTN_RIGHT:
133 status_line_mouse_event(&swaybar, x, y, 3);
134 break;
135 }
136
106#ifdef ENABLE_TRAY 137#ifdef ENABLE_TRAY
107 tray_mouse_event(clicked_output, x, y, button, state_w); 138 tray_mouse_event(clicked_output, x, y, button, state_w);
108#endif 139#endif
140
109} 141}
110 142
111static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { 143static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) {
112 sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); 144 sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down");
113 145
146 // If there are status blocks and click_events are enabled
147 // check if the position is within the status area and if so
148 // tell the status line to output the event and skip workspace
149 // switching below.
150 int num_blocks = swaybar.status->block_line->length;
151 if (swaybar.status->click_events && num_blocks > 0) {
152 struct status_block *first_block = swaybar.status->block_line->items[0];
153 int x = window->pointer_input.last_x;
154 int y = window->pointer_input.last_y;
155 if (x > first_block->x) {
156 if (direction == SCROLL_UP) {
157 status_line_mouse_event(&swaybar, x, y, 4);
158 } else {
159 status_line_mouse_event(&swaybar, x, y, 5);
160 }
161 return;
162 }
163 }
164
114 if (!swaybar.config->wrap_scroll) { 165 if (!swaybar.config->wrap_scroll) {
115 // Find output this window lives on 166 // Find output this window lives on
116 int i; 167 int i;
@@ -318,6 +369,10 @@ void bar_teardown(struct bar *bar) {
318 close(bar->status_read_fd); 369 close(bar->status_read_fd);
319 } 370 }
320 371
372 if (bar->status_write_fd) {
373 close(bar->status_write_fd);
374 }
375
321 if (bar->ipc_socketfd) { 376 if (bar->ipc_socketfd) {
322 close(bar->ipc_socketfd); 377 close(bar->ipc_socketfd);
323 } 378 }
diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c
index 80655d8b..0d1be1da 100644
--- a/swaybar/event_loop.c
+++ b/swaybar/event_loop.c
@@ -1,4 +1,4 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#include <stdlib.h> 2#include <stdlib.h>
3#include <stdbool.h> 3#include <stdbool.h>
4#include <string.h> 4#include <string.h>
@@ -96,7 +96,7 @@ bool remove_event(int fd) {
96static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { 96static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
97 const struct timer_item *timer_item = _timer_item; 97 const struct timer_item *timer_item = _timer_item;
98 const timer_t *timer = _timer; 98 const timer_t *timer = _timer;
99 if (timer_item->timer == timer) { 99 if (timer_item->timer == *timer) {
100 return 0; 100 return 0;
101 } else { 101 } else {
102 return -1; 102 return -1;
@@ -105,6 +105,7 @@ static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
105bool remove_timer(timer_t timer) { 105bool remove_timer(timer_t timer) {
106 int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); 106 int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer);
107 if (index != -1) { 107 if (index != -1) {
108 free(event_loop.timers->items[index]);
108 list_del(event_loop.timers, index); 109 list_del(event_loop.timers, index);
109 return true; 110 return true;
110 } 111 }
diff --git a/swaybar/render.c b/swaybar/render.c
index 6ec47e79..6fc09078 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -94,6 +94,9 @@ static void render_block(struct window *window, struct config *config, struct st
94 94
95 double pos = *x; 95 double pos = *x;
96 96
97 block->x = (int)pos;
98 block->width = (int)block_width;
99
97 // render background 100 // render background
98 if (block->background != 0x0) { 101 if (block->background != 0x0) {
99 cairo_set_source_u32(window->cairo, block->background); 102 cairo_set_source_u32(window->cairo, block->background);
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index 83e8ce2c..e0564c26 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -27,6 +27,8 @@ struct {
27static char line[1024]; 27static char line[1024];
28static char line_rest[1024]; 28static char line_rest[1024];
29 29
30static char event_buff[1024];
31
30static void free_status_block(void *item) { 32static void free_status_block(void *item) {
31 if (!item) { 33 if (!item) {
32 return; 34 return;
@@ -391,6 +393,66 @@ static int i3json_handle_fd(struct bar *bar) {
391 return i3json_parse(bar); 393 return i3json_parse(bar);
392} 394}
393 395
396bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button) {
397 sway_log(L_DEBUG, "status_line_mouse_event.");
398 if (!bar->status->click_events) {
399 sway_log(L_DEBUG, "click_events are not enabled.");
400 return false;
401 }
402
403 if (bar->status->protocol == I3BAR) {
404 sway_log(L_DEBUG, "Sending click event.");
405
406 // find clicked block
407 struct status_block *clicked_block = NULL;
408 struct status_block *current_block = NULL;
409 int num_blocks = bar->status->block_line->length;
410
411 if (num_blocks == 0) {
412 return false;
413 } else {
414 current_block = bar->status->block_line->items[0];
415 if (x < current_block->x) {
416 return false;
417 }
418 }
419
420 for (int i = 0; i < num_blocks; i++) {
421 current_block = bar->status->block_line->items[i];
422 if (x < (current_block->x + current_block->width)) {
423 clicked_block = current_block;
424 break;
425 }
426 }
427
428 if (!clicked_block || !clicked_block->name) {
429 return false;
430 }
431
432 // event example {"name":"capture","instance":"label","button":1,"x":3431,"y":18}
433
434 struct json_object *event_json = json_object_new_object();
435 json_object_object_add(event_json, "name", json_object_new_string(clicked_block->name));
436 if (clicked_block->instance) {
437 json_object_object_add(event_json, "instance", json_object_new_string(clicked_block->instance));
438 }
439 json_object_object_add(event_json, "button", json_object_new_int(button));
440 json_object_object_add(event_json, "x", json_object_new_int(x));
441 json_object_object_add(event_json, "y", json_object_new_int(y));
442
443 int len = snprintf(event_buff, sizeof(event_buff), "%s,\n", json_object_to_json_string(event_json));
444
445 json_object_put(event_json);
446
447 if (len <= (int)sizeof(event_buff)) { // if not truncated
448 write(bar->status_write_fd, event_buff, len);
449 return true;
450 }
451 }
452
453 return false;
454}
455
394bool handle_status_line(struct bar *bar) { 456bool handle_status_line(struct bar *bar) {
395 bool dirty = false; 457 bool dirty = false;
396 458
@@ -418,15 +480,29 @@ bool handle_status_line(struct bar *bar) {
418 if (line[0] == '{') { 480 if (line[0] == '{') {
419 // detect i3bar json protocol 481 // detect i3bar json protocol
420 json_object *proto = json_tokener_parse(line); 482 json_object *proto = json_tokener_parse(line);
421 json_object *version;
422 if (proto) { 483 if (proto) {
484
485 json_object *version;
423 if (json_object_object_get_ex(proto, "version", &version) 486 if (json_object_object_get_ex(proto, "version", &version)
424 && json_object_get_int(version) == 1 487 && json_object_get_int(version) == 1
425 ) { 488 ) {
426 sway_log(L_DEBUG, "Switched to i3bar protocol."); 489 sway_log(L_DEBUG, "Switched to i3bar protocol.");
427 bar->status->protocol = I3BAR; 490 bar->status->protocol = I3BAR;
428 i3json_handle_data(bar, line_rest);
429 } 491 }
492
493 json_object *click_events;
494 if (json_object_object_get_ex(proto, "click_events", &click_events)
495 && json_object_get_boolean(click_events)) {
496
497 sway_log(L_DEBUG, "Enabling click events.");
498 bar->status->click_events = true;
499
500 const char *events_array = "[\n";
501 write(bar->status_write_fd, events_array, strlen(events_array));
502 }
503
504 i3json_handle_data(bar, line_rest);
505
430 json_object_put(proto); 506 json_object_put(proto);
431 } 507 }
432 } 508 }
@@ -441,6 +517,7 @@ struct status_line *init_status_line() {
441 line->block_line = create_list(); 517 line->block_line = create_list();
442 line->text_line = NULL; 518 line->text_line = NULL;
443 line->protocol = UNDEF; 519 line->protocol = UNDEF;
520 line->click_events = false;
444 521
445 return line; 522 return line;
446} 523}
diff --git a/swaybar/tray/dbus.c b/swaybar/tray/dbus.c
index 22531aa6..8e719fd9 100644
--- a/swaybar/tray/dbus.c
+++ b/swaybar/tray/dbus.c
@@ -1,4 +1,4 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#include <stdio.h> 2#include <stdio.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <stdint.h> 4#include <stdint.h>
@@ -108,7 +108,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) {
108 108
109 timer_settime(*timer, 0, &time, NULL); 109 timer_settime(*timer, 0, &time, NULL);
110 110
111 dbus_timeout_set_data(timeout, timer, free); 111 dbus_timeout_set_data(timeout, timer, NULL);
112 112
113 sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec); 113 sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec);
114 add_timer(*timer, dispatch_timeout, timeout); 114 add_timer(*timer, dispatch_timeout, timeout);
@@ -121,6 +121,8 @@ static void remove_timeout(DBusTimeout *timeout, void *_data) {
121 121
122 if (timer) { 122 if (timer) {
123 remove_timer(*timer); 123 remove_timer(*timer);
124 timer_delete(*timer);
125 free(timer);
124 } 126 }
125} 127}
126 128
@@ -136,7 +138,7 @@ static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_s
136/* Public functions below */ 138/* Public functions below */
137 139
138void dispatch_dbus() { 140void dispatch_dbus() {
139 if (!should_dispatch) { 141 if (!should_dispatch || !conn) {
140 return; 142 return;
141 } 143 }
142 144
diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c
index 1c69ba72..c146bf32 100644
--- a/swaybar/tray/icon.c
+++ b/swaybar/tray/icon.c
@@ -1,4 +1,4 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#define _POSIX_C_SOURCE 200809L 2#define _POSIX_C_SOURCE 200809L
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
diff --git a/swaybar/tray/sni.c b/swaybar/tray/sni.c
index 0c46d5c0..c9d00657 100644
--- a/swaybar/tray/sni.c
+++ b/swaybar/tray/sni.c
@@ -160,6 +160,7 @@ static void reply_icon(DBusPendingCall *pending, void *_data) {
160 dirty = true; 160 dirty = true;
161 161
162 dbus_message_unref(reply); 162 dbus_message_unref(reply);
163 dbus_pending_call_unref(pending);
163 return; 164 return;
164 } else { 165 } else {
165 sway_log(L_ERROR, "Could not create image surface"); 166 sway_log(L_ERROR, "Could not create image surface");
@@ -170,6 +171,7 @@ bail:
170 if (reply) { 171 if (reply) {
171 dbus_message_unref(reply); 172 dbus_message_unref(reply);
172 } 173 }
174 dbus_pending_call_unref(pending);
173 sway_log(L_ERROR, "Could not get icon from item"); 175 sway_log(L_ERROR, "Could not get icon from item");
174 return; 176 return;
175} 177}
@@ -266,6 +268,7 @@ static void reply_icon_name(DBusPendingCall *pending, void *_data) {
266 dirty = true; 268 dirty = true;
267 269
268 dbus_message_unref(reply); 270 dbus_message_unref(reply);
271 dbus_pending_call_unref(pending);
269 return; 272 return;
270 } 273 }
271 274
@@ -273,6 +276,7 @@ bail:
273 if (reply) { 276 if (reply) {
274 dbus_message_unref(reply); 277 dbus_message_unref(reply);
275 } 278 }
279 dbus_pending_call_unref(pending);
276 // Now try the pixmap 280 // Now try the pixmap
277 send_icon_msg(item); 281 send_icon_msg(item);
278 return; 282 return;
@@ -413,6 +417,12 @@ static void get_unique_name(struct StatusNotifierItem *item) {
413} 417}
414 418
415struct StatusNotifierItem *sni_create(const char *name) { 419struct StatusNotifierItem *sni_create(const char *name) {
420 // Make sure `name` is well formed
421 if (!dbus_validate_bus_name(name, NULL)) {
422 sway_log(L_INFO, "Name (%s) is not a bus name. We cannot create an item.", name);
423 return NULL;
424 }
425
416 struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem)); 426 struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem));
417 item->name = strdup(name); 427 item->name = strdup(name);
418 item->unique_name = NULL; 428 item->unique_name = NULL;
diff --git a/swaybar/tray/sni_watcher.c b/swaybar/tray/sni_watcher.c
index 388e181d..86453e70 100644
--- a/swaybar/tray/sni_watcher.c
+++ b/swaybar/tray/sni_watcher.c
@@ -150,10 +150,14 @@ static void register_item(DBusConnection *connection, DBusMessage *message) {
150 sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); 150 sway_log(L_ERROR, "Error parsing method args: %s\n", error.message);
151 } 151 }
152 152
153 name = strdup(name);
154 sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name); 153 sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name);
155 154
156 // Don't add duplicate or not real item 155 // Don't add duplicate or not real item
156 if (!dbus_validate_bus_name(name, NULL)) {
157 sway_log(L_INFO, "This item is not valid, we cannot keep track of it.");
158 return;
159 }
160
157 if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) { 161 if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) {
158 return; 162 return;
159 } 163 }
@@ -161,7 +165,7 @@ static void register_item(DBusConnection *connection, DBusMessage *message) {
161 return; 165 return;
162 } 166 }
163 167
164 list_add(items, name); 168 list_add(items, strdup(name));
165 item_registered_signal(connection, name); 169 item_registered_signal(connection, name);
166 170
167 // It's silly, but xembedsniproxy wants a reply for this function 171 // It's silly, but xembedsniproxy wants a reply for this function
@@ -184,6 +188,12 @@ static void register_host(DBusConnection *connection, DBusMessage *message) {
184 sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name); 188 sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name);
185 189
186 // Don't add duplicate or not real host 190 // Don't add duplicate or not real host
191 if (!dbus_validate_bus_name(name, NULL)) {
192 sway_log(L_INFO, "This item is not valid, we cannot keep track of it.");
193 return;
194 }
195
196
187 if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) { 197 if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) {
188 return; 198 return;
189 } 199 }
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c
index 00f1a44f..91c3af06 100644
--- a/swaybar/tray/tray.c
+++ b/swaybar/tray/tray.c
@@ -1,4 +1,4 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#include <unistd.h> 2#include <unistd.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <string.h> 4#include <string.h>
@@ -90,13 +90,16 @@ static void get_items_reply(DBusPendingCall *pending, void *_data) {
90 90
91 struct StatusNotifierItem *item = sni_create(name); 91 struct StatusNotifierItem *item = sni_create(name);
92 92
93 sway_log(L_DEBUG, "Item registered with host: %s", name); 93 if (item) {
94 list_add(tray->items, item); 94 sway_log(L_DEBUG, "Item registered with host: %s", name);
95 dirty = true; 95 list_add(tray->items, item);
96 dirty = true;
97 }
96 } 98 }
97 99
98bail: 100bail:
99 dbus_message_unref(reply); 101 dbus_message_unref(reply);
102 dbus_pending_call_unref(pending);
100 return; 103 return;
101} 104}
102static void get_items() { 105static void get_items() {
@@ -141,8 +144,10 @@ static DBusHandlerResult signal_handler(DBusConnection *connection,
141 if (list_seq_find(tray->items, sni_str_cmp, name) == -1) { 144 if (list_seq_find(tray->items, sni_str_cmp, name) == -1) {
142 struct StatusNotifierItem *item = sni_create(name); 145 struct StatusNotifierItem *item = sni_create(name);
143 146
144 list_add(tray->items, item); 147 if (item) {
145 dirty = true; 148 list_add(tray->items, item);
149 dirty = true;
150 }
146 } 151 }
147 152
148 return DBUS_HANDLER_RESULT_HANDLED; 153 return DBUS_HANDLER_RESULT_HANDLED;