mirror of
				https://github.com/swaywm/sway.git
				synced 2025-10-29 05:40:18 -04:00 
			
		
		
		
	Implement bar bindsym
This commit is contained in:
		
							parent
							
								
									e143c9613d
								
							
						
					
					
						commit
						1c969e86f5
					
				
					 10 changed files with 172 additions and 2 deletions
				
			
		|  | @ -239,6 +239,12 @@ struct bar_config { | ||||||
| 	} colors; | 	} colors; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct bar_binding { | ||||||
|  | 	uint32_t button; | ||||||
|  | 	bool release; | ||||||
|  | 	char *command; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct border_colors { | struct border_colors { | ||||||
| 	float border[4]; | 	float border[4]; | ||||||
| 	float background[4]; | 	float background[4]; | ||||||
|  | @ -527,6 +533,8 @@ struct bar_config *default_bar_config(void); | ||||||
| 
 | 
 | ||||||
| void free_bar_config(struct bar_config *bar); | void free_bar_config(struct bar_config *bar); | ||||||
| 
 | 
 | ||||||
|  | void free_bar_binding(struct bar_binding *binding); | ||||||
|  | 
 | ||||||
| void free_workspace_config(struct workspace_config *wsc); | void free_workspace_config(struct workspace_config *wsc); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <wayland-client.h> | #include <wayland-client.h> | ||||||
|  | #include "list.h" | ||||||
| #include "util.h" | #include "util.h" | ||||||
| 
 | 
 | ||||||
| struct box_colors { | struct box_colors { | ||||||
|  | @ -17,6 +18,12 @@ struct config_output { | ||||||
| 	size_t index; | 	size_t index; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct swaybar_binding { | ||||||
|  | 	uint32_t button; | ||||||
|  | 	char *command; | ||||||
|  | 	bool release; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct swaybar_config { | struct swaybar_config { | ||||||
| 	char *status_command; | 	char *status_command; | ||||||
| 	bool pango_markup; | 	bool pango_markup; | ||||||
|  | @ -29,6 +36,7 @@ struct swaybar_config { | ||||||
| 	bool binding_mode_indicator; | 	bool binding_mode_indicator; | ||||||
| 	bool wrap_scroll; | 	bool wrap_scroll; | ||||||
| 	bool workspace_buttons; | 	bool workspace_buttons; | ||||||
|  | 	list_t *bindings; | ||||||
| 	struct wl_list outputs; // config_output::link
 | 	struct wl_list outputs; // config_output::link
 | ||||||
| 	bool all_outputs; | 	bool all_outputs; | ||||||
| 	int height; | 	int height; | ||||||
|  |  | ||||||
|  | @ -7,5 +7,6 @@ bool ipc_initialize(struct swaybar *bar, const char *bar_id); | ||||||
| bool handle_ipc_readable(struct swaybar *bar); | bool handle_ipc_readable(struct swaybar *bar); | ||||||
| void ipc_get_workspaces(struct swaybar *bar); | void ipc_get_workspaces(struct swaybar *bar); | ||||||
| void ipc_send_workspace_command(struct swaybar *bar, const char *ws); | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); | ||||||
|  | void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
|  | #define _XOPEN_SOURCE 500 | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <strings.h> | ||||||
| #include "sway/commands.h" | #include "sway/commands.h" | ||||||
| #include "sway/config.h" | #include "sway/config.h" | ||||||
| #include "list.h" | #include "list.h" | ||||||
|  | @ -7,5 +9,61 @@ | ||||||
| #include "stringop.h" | #include "stringop.h" | ||||||
| 
 | 
 | ||||||
| struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { | struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { | ||||||
| 	return cmd_results_new(CMD_FAILURE, "bindsym", "TODO"); // TODO
 | 	struct cmd_results *error = NULL; | ||||||
|  | 	if ((error = checkarg(argc, "bar bindsym", EXPECTED_MORE_THAN, 1))) { | ||||||
|  | 		return error; | ||||||
|  | 	} | ||||||
|  | 	if (!config->current_bar) { | ||||||
|  | 		return cmd_results_new(CMD_FAILURE, "bar bindsym", "No bar defined."); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct bar_binding *binding = calloc(1, sizeof(struct bar_binding)); | ||||||
|  | 	if (!binding) { | ||||||
|  | 		return cmd_results_new(CMD_FAILURE, "bar bindsym", | ||||||
|  | 				"Unable to allocate bar binding"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	binding->release = false; | ||||||
|  | 	if (strcmp("--release", argv[0]) == 0) { | ||||||
|  | 		binding->release = true; | ||||||
|  | 		argv++; | ||||||
|  | 		argc--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	binding->button = 0; | ||||||
|  | 	if (strncasecmp(argv[0], "button", strlen("button")) == 0 && | ||||||
|  | 			strlen(argv[0]) == strlen("button0")) { | ||||||
|  | 		binding->button = argv[0][strlen("button")] - '1' + 1; | ||||||
|  | 	} | ||||||
|  | 	if (binding->button == 0) { | ||||||
|  | 		free_bar_binding(binding); | ||||||
|  | 		return cmd_results_new(CMD_FAILURE, "bar bindsym", | ||||||
|  | 				"Only button<n> is supported"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	binding->command = join_args(argv + 1, argc - 1); | ||||||
|  | 
 | ||||||
|  | 	list_t *bindings = config->current_bar->bindings; | ||||||
|  | 	bool overwritten = false; | ||||||
|  | 	for (int i = 0; i < bindings->length; i++) { | ||||||
|  | 		struct bar_binding *other = bindings->items[i]; | ||||||
|  | 		if (other->button == binding->button && | ||||||
|  | 				other->release == binding->release) { | ||||||
|  | 			overwritten = true; | ||||||
|  | 			bindings->items[i] = binding; | ||||||
|  | 			free_bar_binding(other); | ||||||
|  | 			wlr_log(WLR_DEBUG, "[bar %s] Updated binding for button%u%s", | ||||||
|  | 					config->current_bar->id, binding->button, | ||||||
|  | 					binding->release ? " (release)" : ""); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (!overwritten) { | ||||||
|  | 		list_add(bindings, binding); | ||||||
|  | 		wlr_log(WLR_DEBUG, "[bar %s] Added binding for button%u%s", | ||||||
|  | 				config->current_bar->id, binding->button, | ||||||
|  | 				binding->release ? " (release)" : ""); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -28,6 +28,16 @@ static void terminate_swaybar(pid_t pid) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void free_bar_binding(struct bar_binding *binding) { | ||||||
|  | 	if (!binding) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (binding->command) { | ||||||
|  | 		free(binding->command); | ||||||
|  | 	} | ||||||
|  | 	free(binding); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void free_bar_config(struct bar_config *bar) { | void free_bar_config(struct bar_config *bar) { | ||||||
| 	if (!bar) { | 	if (!bar) { | ||||||
| 		return; | 		return; | ||||||
|  | @ -39,7 +49,11 @@ void free_bar_config(struct bar_config *bar) { | ||||||
| 	free(bar->status_command); | 	free(bar->status_command); | ||||||
| 	free(bar->font); | 	free(bar->font); | ||||||
| 	free(bar->separator_symbol); | 	free(bar->separator_symbol); | ||||||
| 	// TODO: Free mouse bindings
 | 	while (bar->bindings->length) { | ||||||
|  | 		struct bar_binding *binding = bar->bindings->items[0]; | ||||||
|  | 		list_del(bar->bindings, 0); | ||||||
|  | 		free_bar_binding(binding); | ||||||
|  | 	} | ||||||
| 	list_free(bar->bindings); | 	list_free(bar->bindings); | ||||||
| 	if (bar->outputs) { | 	if (bar->outputs) { | ||||||
| 		free_flat_list(bar->outputs); | 		free_flat_list(bar->outputs); | ||||||
|  |  | ||||||
|  | @ -623,6 +623,22 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | ||||||
| 
 | 
 | ||||||
| 	json_object_object_add(json, "colors", colors); | 	json_object_object_add(json, "colors", colors); | ||||||
| 
 | 
 | ||||||
|  | 	if (bar->bindings->length > 0) { | ||||||
|  | 		json_object *bindings = json_object_new_array(); | ||||||
|  | 		for (int i = 0; i < bar->bindings->length; ++i) { | ||||||
|  | 			struct bar_binding *binding = bar->bindings->items[i]; | ||||||
|  | 			json_object *bind = json_object_new_object(); | ||||||
|  | 			json_object_object_add(bind, "input_code", | ||||||
|  | 					json_object_new_int(binding->button)); | ||||||
|  | 			json_object_object_add(bind, "command", | ||||||
|  | 					json_object_new_string(binding->command)); | ||||||
|  | 			json_object_object_add(bind, "release", | ||||||
|  | 					json_object_new_boolean(binding->release)); | ||||||
|  | 			json_object_array_add(bindings, bind); | ||||||
|  | 		} | ||||||
|  | 		json_object_object_add(json, "bindings", bindings); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// Add outputs if defined
 | 	// Add outputs if defined
 | ||||||
| 	if (bar->outputs && bar->outputs->length > 0) { | 	if (bar->outputs && bar->outputs->length > 0) { | ||||||
| 		json_object *outputs = json_object_new_array(); | 		json_object *outputs = json_object_new_array(); | ||||||
|  |  | ||||||
|  | @ -60,6 +60,11 @@ Sway allows configuring swaybar in the sway configuration file. | ||||||
| *height* <height> | *height* <height> | ||||||
| 	Sets the height of the bar. Default height will match the font size. | 	Sets the height of the bar. Default height will match the font size. | ||||||
| 
 | 
 | ||||||
|  | *bindsym* [--release] button<n> <command> | ||||||
|  | 	Executes _command_ when mouse button _n_ has been pressed (or if _released_ | ||||||
|  | 	is given, when mouse button _n_ has been released). To disable the default | ||||||
|  | 	behavior for a button, use the command _nop_. | ||||||
|  | 
 | ||||||
| ## TRAY | ## TRAY | ||||||
| 
 | 
 | ||||||
| Swaybar provides a system tray where third-party applications may place icons. | Swaybar provides a system tray where third-party applications may place icons. | ||||||
|  |  | ||||||
|  | @ -144,6 +144,22 @@ static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | ||||||
| 	bar->pointer.y = wl_fixed_to_int(surface_y); | 	bar->pointer.y = wl_fixed_to_int(surface_y); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static bool check_bindings(struct swaybar *bar, uint32_t x11_button, | ||||||
|  | 		uint32_t state) { | ||||||
|  | 	bool released = state == WL_POINTER_BUTTON_STATE_RELEASED; | ||||||
|  | 	for (int i = 0; i < bar->config->bindings->length; i++) { | ||||||
|  | 		struct swaybar_binding *binding = bar->config->bindings->items[i]; | ||||||
|  | 		wlr_log(WLR_DEBUG, "Checking [%u, %d] against [%u, %d, %s]", | ||||||
|  | 				x11_button, released, | ||||||
|  | 				binding->button, binding->release, binding->command); | ||||||
|  | 		if (binding->button == x11_button && binding->release == released) { | ||||||
|  | 			ipc_execute_binding(bar, binding); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | ||||||
| 		uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | 		uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | ||||||
| 	struct swaybar *bar = data; | 	struct swaybar *bar = data; | ||||||
|  | @ -152,6 +168,11 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | ||||||
| 	if (!sway_assert(output, "button with no active output")) { | 	if (!sway_assert(output, "button with no active output")) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if (check_bindings(bar, wl_button_to_x11_button(button), state)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (state != WL_POINTER_BUTTON_STATE_PRESSED) { | 	if (state != WL_POINTER_BUTTON_STATE_PRESSED) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -180,6 +201,11 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||||||
|  | 				WL_POINTER_BUTTON_STATE_PRESSED)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	struct swaybar_hotspot *hotspot; | 	struct swaybar_hotspot *hotspot; | ||||||
| 	wl_list_for_each(hotspot, &output->hotspots, link) { | 	wl_list_for_each(hotspot, &output->hotspots, link) { | ||||||
| 		double x = pointer->x * output->scale; | 		double x = pointer->x * output->scale; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include "swaybar/config.h" | #include "swaybar/config.h" | ||||||
| #include "wlr-layer-shell-unstable-v1-client-protocol.h" | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | ||||||
|  | #include "stringop.h" | ||||||
|  | #include "list.h" | ||||||
| 
 | 
 | ||||||
| uint32_t parse_position(const char *position) { | uint32_t parse_position(const char *position) { | ||||||
| 	uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | | 	uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | | ||||||
|  | @ -34,6 +36,7 @@ struct swaybar_config *init_config(void) { | ||||||
| 	config->binding_mode_indicator = true; | 	config->binding_mode_indicator = true; | ||||||
| 	config->wrap_scroll = false; | 	config->wrap_scroll = false; | ||||||
| 	config->workspace_buttons = true; | 	config->workspace_buttons = true; | ||||||
|  | 	config->bindings = create_list(); | ||||||
| 	wl_list_init(&config->outputs); | 	wl_list_init(&config->outputs); | ||||||
| 
 | 
 | ||||||
| 	/* height */ | 	/* height */ | ||||||
|  | @ -74,6 +77,13 @@ void free_config(struct swaybar_config *config) { | ||||||
| 	free(config->font); | 	free(config->font); | ||||||
| 	free(config->mode); | 	free(config->mode); | ||||||
| 	free(config->sep_symbol); | 	free(config->sep_symbol); | ||||||
|  | 	while (config->bindings->length) { | ||||||
|  | 		struct swaybar_binding *binding = config->bindings->items[0]; | ||||||
|  | 		list_del(config->bindings, 0); | ||||||
|  | 		free(binding->command); | ||||||
|  | 		free(binding); | ||||||
|  | 	} | ||||||
|  | 	list_free(config->bindings); | ||||||
| 	struct config_output *coutput, *tmp; | 	struct config_output *coutput, *tmp; | ||||||
| 	wl_list_for_each_safe(coutput, tmp, &config->outputs, link) { | 	wl_list_for_each_safe(coutput, tmp, &config->outputs, link) { | ||||||
| 		wl_list_remove(&coutput->link); | 		wl_list_remove(&coutput->link); | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include "swaybar/config.h" | #include "swaybar/config.h" | ||||||
| #include "swaybar/ipc.h" | #include "swaybar/ipc.h" | ||||||
| #include "ipc-client.h" | #include "ipc-client.h" | ||||||
|  | #include "list.h" | ||||||
| 
 | 
 | ||||||
| void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { | void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { | ||||||
| 	const char *fmt = "workspace \"%s\""; | 	const char *fmt = "workspace \"%s\""; | ||||||
|  | @ -154,6 +155,7 @@ static bool ipc_parse_config( | ||||||
| 	json_object *markup, *mode, *hidden_bar, *position, *status_command; | 	json_object *markup, *mode, *hidden_bar, *position, *status_command; | ||||||
| 	json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; | 	json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; | ||||||
| 	json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; | 	json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; | ||||||
|  | 	json_object *bindings; | ||||||
| 	json_object_object_get_ex(bar_config, "mode", &mode); | 	json_object_object_get_ex(bar_config, "mode", &mode); | ||||||
| 	json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); | 	json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); | ||||||
| 	json_object_object_get_ex(bar_config, "position", &position); | 	json_object_object_get_ex(bar_config, "position", &position); | ||||||
|  | @ -169,6 +171,7 @@ static bool ipc_parse_config( | ||||||
| 	json_object_object_get_ex(bar_config, "colors", &colors); | 	json_object_object_get_ex(bar_config, "colors", &colors); | ||||||
| 	json_object_object_get_ex(bar_config, "outputs", &outputs); | 	json_object_object_get_ex(bar_config, "outputs", &outputs); | ||||||
| 	json_object_object_get_ex(bar_config, "pango_markup", &markup); | 	json_object_object_get_ex(bar_config, "pango_markup", &markup); | ||||||
|  | 	json_object_object_get_ex(bar_config, "bindings", &bindings); | ||||||
| 	if (status_command) { | 	if (status_command) { | ||||||
| 		free(config->status_command); | 		free(config->status_command); | ||||||
| 		config->status_command = strdup(json_object_get_string(status_command)); | 		config->status_command = strdup(json_object_get_string(status_command)); | ||||||
|  | @ -202,6 +205,21 @@ static bool ipc_parse_config( | ||||||
| 	if (markup) { | 	if (markup) { | ||||||
| 		config->pango_markup = json_object_get_boolean(markup); | 		config->pango_markup = json_object_get_boolean(markup); | ||||||
| 	} | 	} | ||||||
|  | 	if (bindings) { | ||||||
|  | 		int length = json_object_array_length(bindings); | ||||||
|  | 		for (int i = 0; i < length; ++i) { | ||||||
|  | 			json_object *bindobj = json_object_array_get_idx(bindings, i); | ||||||
|  | 			struct swaybar_binding *binding = | ||||||
|  | 				calloc(1, sizeof(struct swaybar_binding)); | ||||||
|  | 			binding->button = json_object_get_int( | ||||||
|  | 					json_object_object_get(bindobj, "input_code")); | ||||||
|  | 			binding->command = strdup(json_object_get_string( | ||||||
|  | 					json_object_object_get(bindobj, "command"))); | ||||||
|  | 			binding->release = json_object_get_boolean( | ||||||
|  | 					json_object_object_get(bindobj, "release")); | ||||||
|  | 			list_add(config->bindings, binding); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	struct config_output *output, *tmp; | 	struct config_output *output, *tmp; | ||||||
| 	wl_list_for_each_safe(output, tmp, &config->outputs, link) { | 	wl_list_for_each_safe(output, tmp, &config->outputs, link) { | ||||||
|  | @ -319,6 +337,12 @@ static void ipc_get_outputs(struct swaybar *bar) { | ||||||
| 	free(res); | 	free(res); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) { | ||||||
|  | 	uint32_t len = strlen(bind->command); | ||||||
|  | 	free(ipc_single_command(bar->ipc_socketfd, | ||||||
|  | 			IPC_COMMAND, bind->command, &len)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool ipc_initialize(struct swaybar *bar, const char *bar_id) { | bool ipc_initialize(struct swaybar *bar, const char *bar_id) { | ||||||
| 	uint32_t len = strlen(bar_id); | 	uint32_t len = strlen(bar_id); | ||||||
| 	char *res = ipc_single_command(bar->ipc_socketfd, | 	char *res = ipc_single_command(bar->ipc_socketfd, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brian Ashworth
						Brian Ashworth