aboutsummaryrefslogtreecommitdiff
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(
${XKBCOMMON_INCLUDE_DIRS}
${DBUS_INCLUDE_DIRS}
)
-if (enable-tray)
+if (ENABLE_TRAY)
file(GLOB tray
tray/*.c
)
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 @@
#include <sys/wait.h>
#include <signal.h>
#include <poll.h>
+#include <linux/input-event-codes.h>
#ifdef ENABLE_TRAY
#include <dbus/dbus.h>
#include "swaybar/tray/sni_watcher.h"
@@ -31,16 +32,30 @@ static void bar_init(struct bar *bar) {
static void spawn_status_cmd_proc(struct bar *bar) {
if (bar->config->status_command) {
- int pipefd[2];
- if (pipe(pipefd) != 0) {
- sway_log(L_ERROR, "Unable to create pipe for status_command fork");
+ int pipe_read_fd[2];
+ int pipe_write_fd[2];
+
+ if (pipe(pipe_read_fd) != 0) {
+ sway_log(L_ERROR, "Unable to create pipes for status_command fork");
+ return;
+ }
+ if (pipe(pipe_write_fd) != 0) {
+ sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)");
+ close(pipe_read_fd[0]);
+ close(pipe_read_fd[1]);
return;
}
+
bar->status_command_pid = fork();
if (bar->status_command_pid == 0) {
- close(pipefd[0]);
- dup2(pipefd[1], STDOUT_FILENO);
- close(pipefd[1]);
+ close(pipe_read_fd[0]);
+ dup2(pipe_read_fd[1], STDOUT_FILENO);
+ close(pipe_read_fd[1]);
+
+ dup2(pipe_write_fd[0], STDIN_FILENO);
+ close(pipe_write_fd[0]);
+ close(pipe_write_fd[1]);
+
char *const cmd[] = {
"sh",
"-c",
@@ -51,9 +66,13 @@ static void spawn_status_cmd_proc(struct bar *bar) {
return;
}
- close(pipefd[1]);
- bar->status_read_fd = pipefd[0];
+ close(pipe_read_fd[1]);
+ bar->status_read_fd = pipe_read_fd[0];
fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK);
+
+ close(pipe_write_fd[0]);
+ bar->status_write_fd = pipe_write_fd[1];
+ fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK);
}
}
@@ -103,14 +122,46 @@ static void mouse_button_notify(struct window *window, int x, int y,
}
}
+ switch (button) {
+ case BTN_LEFT:
+ status_line_mouse_event(&swaybar, x, y, 1);
+ break;
+ case BTN_MIDDLE:
+ status_line_mouse_event(&swaybar, x, y, 2);
+ break;
+ case BTN_RIGHT:
+ status_line_mouse_event(&swaybar, x, y, 3);
+ break;
+ }
+
#ifdef ENABLE_TRAY
tray_mouse_event(clicked_output, x, y, button, state_w);
#endif
+
}
static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) {
sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down");
+ // If there are status blocks and click_events are enabled
+ // check if the position is within the status area and if so
+ // tell the status line to output the event and skip workspace
+ // switching below.
+ int num_blocks = swaybar.status->block_line->length;
+ if (swaybar.status->click_events && num_blocks > 0) {
+ struct status_block *first_block = swaybar.status->block_line->items[0];
+ int x = window->pointer_input.last_x;
+ int y = window->pointer_input.last_y;
+ if (x > first_block->x) {
+ if (direction == SCROLL_UP) {
+ status_line_mouse_event(&swaybar, x, y, 4);
+ } else {
+ status_line_mouse_event(&swaybar, x, y, 5);
+ }
+ return;
+ }
+ }
+
if (!swaybar.config->wrap_scroll) {
// Find output this window lives on
int i;
@@ -318,6 +369,10 @@ void bar_teardown(struct bar *bar) {
close(bar->status_read_fd);
}
+ if (bar->status_write_fd) {
+ close(bar->status_write_fd);
+ }
+
if (bar->ipc_socketfd) {
close(bar->ipc_socketfd);
}
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 @@
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 700
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
@@ -96,7 +96,7 @@ bool remove_event(int fd) {
static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
const struct timer_item *timer_item = _timer_item;
const timer_t *timer = _timer;
- if (timer_item->timer == timer) {
+ if (timer_item->timer == *timer) {
return 0;
} else {
return -1;
@@ -105,6 +105,7 @@ static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
bool remove_timer(timer_t timer) {
int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer);
if (index != -1) {
+ free(event_loop.timers->items[index]);
list_del(event_loop.timers, index);
return true;
}
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
double pos = *x;
+ block->x = (int)pos;
+ block->width = (int)block_width;
+
// render background
if (block->background != 0x0) {
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 {
static char line[1024];
static char line_rest[1024];
+static char event_buff[1024];
+
static void free_status_block(void *item) {
if (!item) {
return;
@@ -391,6 +393,66 @@ static int i3json_handle_fd(struct bar *bar) {
return i3json_parse(bar);
}
+bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button) {
+ sway_log(L_DEBUG, "status_line_mouse_event.");
+ if (!bar->status->click_events) {
+ sway_log(L_DEBUG, "click_events are not enabled.");
+ return false;
+ }
+
+ if (bar->status->protocol == I3BAR) {
+ sway_log(L_DEBUG, "Sending click event.");
+
+ // find clicked block
+ struct status_block *clicked_block = NULL;
+ struct status_block *current_block = NULL;
+ int num_blocks = bar->status->block_line->length;
+
+ if (num_blocks == 0) {
+ return false;
+ } else {
+ current_block = bar->status->block_line->items[0];
+ if (x < current_block->x) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < num_blocks; i++) {
+ current_block = bar->status->block_line->items[i];
+ if (x < (current_block->x + current_block->width)) {
+ clicked_block = current_block;
+ break;
+ }
+ }
+
+ if (!clicked_block || !clicked_block->name) {
+ return false;
+ }
+
+ // event example {"name":"capture","instance":"label","button":1,"x":3431,"y":18}
+
+ struct json_object *event_json = json_object_new_object();
+ json_object_object_add(event_json, "name", json_object_new_string(clicked_block->name));
+ if (clicked_block->instance) {
+ json_object_object_add(event_json, "instance", json_object_new_string(clicked_block->instance));
+ }
+ json_object_object_add(event_json, "button", json_object_new_int(button));
+ json_object_object_add(event_json, "x", json_object_new_int(x));
+ json_object_object_add(event_json, "y", json_object_new_int(y));
+
+ int len = snprintf(event_buff, sizeof(event_buff), "%s,\n", json_object_to_json_string(event_json));
+
+ json_object_put(event_json);
+
+ if (len <= (int)sizeof(event_buff)) { // if not truncated
+ write(bar->status_write_fd, event_buff, len);
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool handle_status_line(struct bar *bar) {
bool dirty = false;
@@ -418,15 +480,29 @@ bool handle_status_line(struct bar *bar) {
if (line[0] == '{') {
// detect i3bar json protocol
json_object *proto = json_tokener_parse(line);
- json_object *version;
if (proto) {
+
+ json_object *version;
if (json_object_object_get_ex(proto, "version", &version)
&& json_object_get_int(version) == 1
) {
sway_log(L_DEBUG, "Switched to i3bar protocol.");
bar->status->protocol = I3BAR;
- i3json_handle_data(bar, line_rest);
}
+
+ json_object *click_events;
+ if (json_object_object_get_ex(proto, "click_events", &click_events)
+ && json_object_get_boolean(click_events)) {
+
+ sway_log(L_DEBUG, "Enabling click events.");
+ bar->status->click_events = true;
+
+ const char *events_array = "[\n";
+ write(bar->status_write_fd, events_array, strlen(events_array));
+ }
+
+ i3json_handle_data(bar, line_rest);
+
json_object_put(proto);
}
}
@@ -441,6 +517,7 @@ struct status_line *init_status_line() {
line->block_line = create_list();
line->text_line = NULL;
line->protocol = UNDEF;
+ line->click_events = false;
return line;
}
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 @@
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -108,7 +108,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) {
timer_settime(*timer, 0, &time, NULL);
- dbus_timeout_set_data(timeout, timer, free);
+ dbus_timeout_set_data(timeout, timer, NULL);
sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec);
add_timer(*timer, dispatch_timeout, timeout);
@@ -121,6 +121,8 @@ static void remove_timeout(DBusTimeout *timeout, void *_data) {
if (timer) {
remove_timer(*timer);
+ timer_delete(*timer);
+ free(timer);
}
}
@@ -136,7 +138,7 @@ static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_s
/* Public functions below */
void dispatch_dbus() {
- if (!should_dispatch) {
+ if (!should_dispatch || !conn) {
return;
}
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 @@
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 700
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#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) {
dirty = true;
dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
return;
} else {
sway_log(L_ERROR, "Could not create image surface");
@@ -170,6 +171,7 @@ bail:
if (reply) {
dbus_message_unref(reply);
}
+ dbus_pending_call_unref(pending);
sway_log(L_ERROR, "Could not get icon from item");
return;
}
@@ -266,6 +268,7 @@ static void reply_icon_name(DBusPendingCall *pending, void *_data) {
dirty = true;
dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
return;
}
@@ -273,6 +276,7 @@ bail:
if (reply) {
dbus_message_unref(reply);
}
+ dbus_pending_call_unref(pending);
// Now try the pixmap
send_icon_msg(item);
return;
@@ -413,6 +417,12 @@ static void get_unique_name(struct StatusNotifierItem *item) {
}
struct StatusNotifierItem *sni_create(const char *name) {
+ // Make sure `name` is well formed
+ if (!dbus_validate_bus_name(name, NULL)) {
+ sway_log(L_INFO, "Name (%s) is not a bus name. We cannot create an item.", name);
+ return NULL;
+ }
+
struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem));
item->name = strdup(name);
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) {
sway_log(L_ERROR, "Error parsing method args: %s\n", error.message);
}
- name = strdup(name);
sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name);
// Don't add duplicate or not real item
+ if (!dbus_validate_bus_name(name, NULL)) {
+ sway_log(L_INFO, "This item is not valid, we cannot keep track of it.");
+ return;
+ }
+
if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) {
return;
}
@@ -161,7 +165,7 @@ static void register_item(DBusConnection *connection, DBusMessage *message) {
return;
}
- list_add(items, name);
+ list_add(items, strdup(name));
item_registered_signal(connection, name);
// It's silly, but xembedsniproxy wants a reply for this function
@@ -184,6 +188,12 @@ static void register_host(DBusConnection *connection, DBusMessage *message) {
sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name);
// Don't add duplicate or not real host
+ if (!dbus_validate_bus_name(name, NULL)) {
+ sway_log(L_INFO, "This item is not valid, we cannot keep track of it.");
+ return;
+ }
+
+
if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) {
return;
}
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 @@
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 700
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@@ -90,13 +90,16 @@ static void get_items_reply(DBusPendingCall *pending, void *_data) {
struct StatusNotifierItem *item = sni_create(name);
- sway_log(L_DEBUG, "Item registered with host: %s", name);
- list_add(tray->items, item);
- dirty = true;
+ if (item) {
+ sway_log(L_DEBUG, "Item registered with host: %s", name);
+ list_add(tray->items, item);
+ dirty = true;
+ }
}
bail:
dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
return;
}
static void get_items() {
@@ -141,8 +144,10 @@ static DBusHandlerResult signal_handler(DBusConnection *connection,
if (list_seq_find(tray->items, sni_str_cmp, name) == -1) {
struct StatusNotifierItem *item = sni_create(name);
- list_add(tray->items, item);
- dirty = true;
+ if (item) {
+ list_add(tray->items, item);
+ dirty = true;
+ }
}
return DBUS_HANDLER_RESULT_HANDLED;