diff options
Diffstat (limited to 'swaybar')
| -rw-r--r-- | swaybar/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | swaybar/bar.c | 71 | ||||
| -rw-r--r-- | swaybar/event_loop.c | 5 | ||||
| -rw-r--r-- | swaybar/render.c | 3 | ||||
| -rw-r--r-- | swaybar/status_line.c | 81 | ||||
| -rw-r--r-- | swaybar/tray/dbus.c | 8 | ||||
| -rw-r--r-- | swaybar/tray/icon.c | 2 | ||||
| -rw-r--r-- | swaybar/tray/sni.c | 10 | ||||
| -rw-r--r-- | swaybar/tray/sni_watcher.c | 14 | ||||
| -rw-r--r-- | swaybar/tray/tray.c | 17 | 
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; | 
