mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	ipc: add binding event
This commit is contained in:
		
							parent
							
								
									e0e638281e
								
							
						
					
					
						commit
						6865b8aae9
					
				
					 4 changed files with 128 additions and 3 deletions
				
			
		| 
						 | 
					@ -488,8 +488,6 @@ int sway_binding_cmp_keys(const void *a, const void *b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void free_sway_binding(struct sway_binding *sb);
 | 
					void free_sway_binding(struct sway_binding *sb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_binding *sway_binding_dup(struct sway_binding *sb);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding);
 | 
					void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void load_swaybars();
 | 
					void load_swaybars();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,5 +17,6 @@ void ipc_event_window(struct sway_container *window, const char *change);
 | 
				
			||||||
void ipc_event_barconfig_update(struct bar_config *bar);
 | 
					void ipc_event_barconfig_update(struct bar_config *bar);
 | 
				
			||||||
void ipc_event_mode(const char *mode, bool pango);
 | 
					void ipc_event_mode(const char *mode, bool pango);
 | 
				
			||||||
void ipc_event_shutdown(const char *reason);
 | 
					void ipc_event_shutdown(const char *reason);
 | 
				
			||||||
 | 
					void ipc_event_binding(struct sway_binding *binding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
#ifdef __linux__
 | 
					#ifdef __linux__
 | 
				
			||||||
#include <linux/input-event-codes.h>
 | 
					#include <linux/input-event-codes.h>
 | 
				
			||||||
#elif __FreeBSD__
 | 
					#elif __FreeBSD__
 | 
				
			||||||
| 
						 | 
					@ -5,9 +6,11 @@
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <xkbcommon/xkbcommon.h>
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
#include <xkbcommon/xkbcommon-names.h>
 | 
					#include <xkbcommon/xkbcommon-names.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
#include <strings.h>
 | 
					#include <strings.h>
 | 
				
			||||||
#include "sway/commands.h"
 | 
					#include "sway/commands.h"
 | 
				
			||||||
#include "sway/config.h"
 | 
					#include "sway/config.h"
 | 
				
			||||||
 | 
					#include "sway/ipc-server.h"
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
| 
						 | 
					@ -27,6 +30,33 @@ void free_sway_binding(struct sway_binding *binding) {
 | 
				
			||||||
	free(binding);
 | 
						free(binding);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct sway_binding *sway_binding_dup(struct sway_binding *sb) {
 | 
				
			||||||
 | 
						struct sway_binding *new_sb = calloc(1, sizeof(struct sway_binding));
 | 
				
			||||||
 | 
						if (!new_sb) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new_sb->type = sb->type;
 | 
				
			||||||
 | 
						new_sb->order = sb->order;
 | 
				
			||||||
 | 
						new_sb->flags = sb->flags;
 | 
				
			||||||
 | 
						new_sb->modifiers = sb->modifiers;
 | 
				
			||||||
 | 
						new_sb->command = strdup(sb->command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new_sb->keys = create_list();
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < sb->keys->length; ++i) {
 | 
				
			||||||
 | 
							xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
 | 
				
			||||||
 | 
							if (!key) {
 | 
				
			||||||
 | 
								free_sway_binding(new_sb);
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*key = *(xkb_keysym_t *)sb->keys->items[i];
 | 
				
			||||||
 | 
							list_add(new_sb->keys, key);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return new_sb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Returns true if the bindings have the same key and modifier combinations.
 | 
					 * Returns true if the bindings have the same key and modifier combinations.
 | 
				
			||||||
 * Note that keyboard layout is not considered, so the bindings might actually
 | 
					 * Note that keyboard layout is not considered, so the bindings might actually
 | 
				
			||||||
| 
						 | 
					@ -275,11 +305,31 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) {
 | 
				
			||||||
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
 | 
					void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "running command for binding: %s",
 | 
						wlr_log(WLR_DEBUG, "running command for binding: %s",
 | 
				
			||||||
		binding->command);
 | 
							binding->command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sway_binding *binding_copy = binding;
 | 
				
			||||||
 | 
						bool reload = false;
 | 
				
			||||||
 | 
						// if this is a reload command we need to make a duplicate of the
 | 
				
			||||||
 | 
						// binding since it will be gone after the reload has completed.
 | 
				
			||||||
 | 
						if (strcasecmp(binding->command, "reload") == 0) {
 | 
				
			||||||
 | 
							reload = true;
 | 
				
			||||||
 | 
							binding_copy = sway_binding_dup(binding);
 | 
				
			||||||
 | 
							if (!binding_copy) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "Failed to duplicate binding during reload");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config->handler_context.seat = seat;
 | 
						config->handler_context.seat = seat;
 | 
				
			||||||
	struct cmd_results *results = execute_command(binding->command, NULL);
 | 
						struct cmd_results *results = execute_command(binding->command, NULL);
 | 
				
			||||||
	if (results->status != CMD_SUCCESS) {
 | 
						if (results->status == CMD_SUCCESS) {
 | 
				
			||||||
 | 
							ipc_event_binding(binding_copy);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
 | 
							wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
 | 
				
			||||||
			binding->command, results->error);
 | 
								binding->command, results->error);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reload) { // free the binding if we made a copy
 | 
				
			||||||
 | 
							free_sway_binding(binding_copy);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	free_cmd_results(results);
 | 
						free_cmd_results(results);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,12 +3,18 @@
 | 
				
			||||||
// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
 | 
					// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
 | 
				
			||||||
#define _XOPEN_SOURCE 700
 | 
					#define _XOPEN_SOURCE 700
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef __linux__
 | 
				
			||||||
 | 
					#include <linux/input-event-codes.h>
 | 
				
			||||||
 | 
					#elif __FreeBSD__
 | 
				
			||||||
 | 
					#include <dev/evdev/input-event-codes.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <json-c/json.h>
 | 
					#include <json-c/json.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
| 
						 | 
					@ -28,6 +34,7 @@
 | 
				
			||||||
#include "sway/tree/view.h"
 | 
					#include "sway/tree/view.h"
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ipc_socket = -1;
 | 
					static int ipc_socket = -1;
 | 
				
			||||||
static struct wl_event_source *ipc_event_source =  NULL;
 | 
					static struct wl_event_source *ipc_event_source =  NULL;
 | 
				
			||||||
| 
						 | 
					@ -367,6 +374,75 @@ void ipc_event_shutdown(const char *reason) {
 | 
				
			||||||
	json_object_put(json);
 | 
						json_object_put(json);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_event_binding(struct sway_binding *binding) {
 | 
				
			||||||
 | 
						if (!ipc_has_event_listeners(IPC_EVENT_BINDING)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "Sending binding event");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *json_binding = json_object_new_object();
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "command", json_object_new_string(binding->command));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *names[10];
 | 
				
			||||||
 | 
						int len = get_modifier_names(names, binding->modifiers);
 | 
				
			||||||
 | 
						json_object *modifiers = json_object_new_array();
 | 
				
			||||||
 | 
						for (int i = 0; i < len; ++i) {
 | 
				
			||||||
 | 
							json_object_array_add(modifiers, json_object_new_string(names[i]));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "event_state_mask", modifiers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *input_codes = json_object_new_array();
 | 
				
			||||||
 | 
						int input_code = 0;
 | 
				
			||||||
 | 
						json_object *symbols = json_object_new_array();
 | 
				
			||||||
 | 
						json_object *symbol = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (binding->type == BINDING_KEYCODE) { // bindcode: populate input_codes
 | 
				
			||||||
 | 
							uint32_t keycode;
 | 
				
			||||||
 | 
							for (int i = 0; i < binding->keys->length; ++i) {
 | 
				
			||||||
 | 
								keycode = *(uint32_t *)binding->keys->items[i];
 | 
				
			||||||
 | 
								json_object_array_add(input_codes, json_object_new_int(keycode));
 | 
				
			||||||
 | 
								if (i == 0) {
 | 
				
			||||||
 | 
									input_code = keycode;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else { // bindsym/mouse: populate symbols
 | 
				
			||||||
 | 
							uint32_t keysym;
 | 
				
			||||||
 | 
							char buffer[64];
 | 
				
			||||||
 | 
							for (int i = 0; i < binding->keys->length; ++i) {
 | 
				
			||||||
 | 
								keysym = *(uint32_t *)binding->keys->items[i];
 | 
				
			||||||
 | 
								if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) {
 | 
				
			||||||
 | 
									snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1);
 | 
				
			||||||
 | 
								} else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) {
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								json_object *str = json_object_new_string(buffer);
 | 
				
			||||||
 | 
								if (i == 0) {
 | 
				
			||||||
 | 
									// str is owned by both symbol and symbols. Make sure
 | 
				
			||||||
 | 
									// to bump the ref count.
 | 
				
			||||||
 | 
									json_object_array_add(symbols, json_object_get(str));
 | 
				
			||||||
 | 
									symbol = str;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									json_object_array_add(symbols, str);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "input_codes", input_codes);
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "symbols", symbols);
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "symbol", symbol);
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ?
 | 
				
			||||||
 | 
								json_object_new_string("mouse") : json_object_new_string("keyboard"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *json = json_object_new_object();
 | 
				
			||||||
 | 
						json_object_object_add(json, "change", json_object_new_string("run"));
 | 
				
			||||||
 | 
						json_object_object_add(json, "binding", json_binding);
 | 
				
			||||||
 | 
						const char *json_string = json_object_to_json_string(json);
 | 
				
			||||||
 | 
						ipc_send_event(json_string, IPC_EVENT_BINDING);
 | 
				
			||||||
 | 
						json_object_put(json);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
 | 
					int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
 | 
				
			||||||
	struct ipc_client *client = data;
 | 
						struct ipc_client *client = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue