mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	
						commit
						82d6afc91d
					
				
					 5 changed files with 137 additions and 10 deletions
				
			
		| 
						 | 
					@ -14,6 +14,7 @@ struct bar {
 | 
				
			||||||
	int ipc_event_socketfd;
 | 
						int ipc_event_socketfd;
 | 
				
			||||||
	int ipc_socketfd;
 | 
						int ipc_socketfd;
 | 
				
			||||||
	int status_read_fd;
 | 
						int status_read_fd;
 | 
				
			||||||
 | 
						int status_write_fd;
 | 
				
			||||||
	pid_t status_command_pid;
 | 
						pid_t status_command_pid;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ struct status_line {
 | 
				
			||||||
	list_t *block_line;
 | 
						list_t *block_line;
 | 
				
			||||||
	const char *text_line;
 | 
						const char *text_line;
 | 
				
			||||||
	command_protocol protocol;
 | 
						command_protocol protocol;
 | 
				
			||||||
 | 
						bool click_events;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct status_block {
 | 
					struct status_block {
 | 
				
			||||||
| 
						 | 
					@ -31,6 +32,10 @@ struct status_block {
 | 
				
			||||||
	int border_bottom;
 | 
						int border_bottom;
 | 
				
			||||||
	int border_left;
 | 
						int border_left;
 | 
				
			||||||
	int border_right;
 | 
						int border_right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set during rendering
 | 
				
			||||||
 | 
						int x;
 | 
				
			||||||
 | 
						int width;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -43,6 +48,11 @@ struct status_line *init_status_line();
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool handle_status_line(struct bar *bar);
 | 
					bool handle_status_line(struct bar *bar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Handle mouse clicks.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Free status line struct.
 | 
					 * Free status line struct.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <sys/wait.h>
 | 
					#include <sys/wait.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
#include <poll.h>
 | 
					#include <poll.h>
 | 
				
			||||||
 | 
					#include <linux/input-event-codes.h>
 | 
				
			||||||
#ifdef ENABLE_TRAY
 | 
					#ifdef ENABLE_TRAY
 | 
				
			||||||
#include <dbus/dbus.h>
 | 
					#include <dbus/dbus.h>
 | 
				
			||||||
#include "swaybar/tray/sni_watcher.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) {
 | 
					static void spawn_status_cmd_proc(struct bar *bar) {
 | 
				
			||||||
	if (bar->config->status_command) {
 | 
						if (bar->config->status_command) {
 | 
				
			||||||
		int pipefd[2];
 | 
							int pipe_read_fd[2];
 | 
				
			||||||
		if (pipe(pipefd) != 0) {
 | 
							int pipe_write_fd[2];
 | 
				
			||||||
			sway_log(L_ERROR, "Unable to create pipe for status_command fork");
 | 
					
 | 
				
			||||||
 | 
							if (pipe(pipe_read_fd) != 0) {
 | 
				
			||||||
 | 
								sway_log(L_ERROR, "Unable to create pipes for status_command fork");
 | 
				
			||||||
			return;
 | 
								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();
 | 
							bar->status_command_pid = fork();
 | 
				
			||||||
		if (bar->status_command_pid == 0) {
 | 
							if (bar->status_command_pid == 0) {
 | 
				
			||||||
			close(pipefd[0]);
 | 
								close(pipe_read_fd[0]);
 | 
				
			||||||
			dup2(pipefd[1], STDOUT_FILENO);
 | 
								dup2(pipe_read_fd[1], STDOUT_FILENO);
 | 
				
			||||||
			close(pipefd[1]);
 | 
								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[] = {
 | 
								char *const cmd[] = {
 | 
				
			||||||
				"sh",
 | 
									"sh",
 | 
				
			||||||
				"-c",
 | 
									"-c",
 | 
				
			||||||
| 
						 | 
					@ -51,9 +66,13 @@ static void spawn_status_cmd_proc(struct bar *bar) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		close(pipefd[1]);
 | 
							close(pipe_read_fd[1]);
 | 
				
			||||||
		bar->status_read_fd = pipefd[0];
 | 
							bar->status_read_fd = pipe_read_fd[0];
 | 
				
			||||||
		fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK);
 | 
							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,9 +122,22 @@ 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
 | 
					#ifdef ENABLE_TRAY
 | 
				
			||||||
	tray_mouse_event(clicked_output, x, y, button, state_w);
 | 
						tray_mouse_event(clicked_output, x, y, button, state_w);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) {
 | 
					static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) {
 | 
				
			||||||
| 
						 | 
					@ -318,6 +350,10 @@ void bar_teardown(struct bar *bar) {
 | 
				
			||||||
		close(bar->status_read_fd);
 | 
							close(bar->status_read_fd);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bar->status_write_fd) {
 | 
				
			||||||
 | 
							close(bar->status_write_fd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bar->ipc_socketfd) {
 | 
						if (bar->ipc_socketfd) {
 | 
				
			||||||
		close(bar->ipc_socketfd);
 | 
							close(bar->ipc_socketfd);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,6 +94,9 @@ static void render_block(struct window *window, struct config *config, struct st
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	double pos = *x;
 | 
						double pos = *x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						block->x = (int)pos;
 | 
				
			||||||
 | 
						block->width = (int)block_width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// render background
 | 
						// render background
 | 
				
			||||||
	if (block->background != 0x0) {
 | 
						if (block->background != 0x0) {
 | 
				
			||||||
		cairo_set_source_u32(window->cairo, block->background);
 | 
							cairo_set_source_u32(window->cairo, block->background);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,8 @@ struct {
 | 
				
			||||||
static char line[1024];
 | 
					static char line[1024];
 | 
				
			||||||
static char line_rest[1024];
 | 
					static char line_rest[1024];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char event_buff[1024];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void free_status_block(void *item) {
 | 
					static void free_status_block(void *item) {
 | 
				
			||||||
	if (!item) {
 | 
						if (!item) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -391,6 +393,66 @@ static int i3json_handle_fd(struct bar *bar) {
 | 
				
			||||||
	return i3json_parse(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 handle_status_line(struct bar *bar) {
 | 
				
			||||||
	bool dirty = false;
 | 
						bool dirty = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -418,15 +480,29 @@ bool handle_status_line(struct bar *bar) {
 | 
				
			||||||
		if (line[0] == '{') {
 | 
							if (line[0] == '{') {
 | 
				
			||||||
			// detect i3bar json protocol
 | 
								// detect i3bar json protocol
 | 
				
			||||||
			json_object *proto = json_tokener_parse(line);
 | 
								json_object *proto = json_tokener_parse(line);
 | 
				
			||||||
			json_object *version;
 | 
					 | 
				
			||||||
			if (proto) {
 | 
								if (proto) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									json_object *version;
 | 
				
			||||||
				if (json_object_object_get_ex(proto, "version", &version)
 | 
									if (json_object_object_get_ex(proto, "version", &version)
 | 
				
			||||||
							&& json_object_get_int(version) == 1
 | 
												&& json_object_get_int(version) == 1
 | 
				
			||||||
				) {
 | 
									) {
 | 
				
			||||||
					sway_log(L_DEBUG, "Switched to i3bar protocol.");
 | 
										sway_log(L_DEBUG, "Switched to i3bar protocol.");
 | 
				
			||||||
					bar->status->protocol = I3BAR;
 | 
										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);
 | 
									json_object_put(proto);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -441,6 +517,7 @@ struct status_line *init_status_line() {
 | 
				
			||||||
	line->block_line = create_list();
 | 
						line->block_line = create_list();
 | 
				
			||||||
	line->text_line = NULL;
 | 
						line->text_line = NULL;
 | 
				
			||||||
	line->protocol = UNDEF;
 | 
						line->protocol = UNDEF;
 | 
				
			||||||
 | 
						line->click_events = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return line;
 | 
						return line;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue