aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h2
-rw-r--r--include/sway/ipc-server.h1
-rw-r--r--sway/commands/bind.c52
-rw-r--r--sway/ipc-server.c76
4 files changed, 128 insertions, 3 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index 0f74b439..909b6827 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -488,8 +488,6 @@ int sway_binding_cmp_keys(const void *a, const void *b);
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 load_swaybars();
diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h
index a11735cf..4b6d0e25 100644
--- a/include/sway/ipc-server.h
+++ b/include/sway/ipc-server.h
@@ -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_mode(const char *mode, bool pango);
void ipc_event_shutdown(const char *reason);
+void ipc_event_binding(struct sway_binding *binding);
#endif
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 133fd089..8270b958 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -1,3 +1,4 @@
+#define _XOPEN_SOURCE 500
#ifdef __linux__
#include <linux/input-event-codes.h>
#elif __FreeBSD__
@@ -5,9 +6,11 @@
#endif
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-names.h>
+#include <string.h>
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
+#include "sway/ipc-server.h"
#include "list.h"
#include "log.h"
#include "stringop.h"
@@ -27,6 +30,33 @@ void free_sway_binding(struct sway_binding *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.
* 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) {
wlr_log(WLR_DEBUG, "running command for binding: %s",
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;
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)",
binding->command, results->error);
}
+
+ if (reload) { // free the binding if we made a copy
+ free_sway_binding(binding_copy);
+ }
free_cmd_results(results);
}
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 72031e24..8fceafa2 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -3,12 +3,18 @@
// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
#define _XOPEN_SOURCE 700
#endif
+#ifdef __linux__
+#include <linux/input-event-codes.h>
+#elif __FreeBSD__
+#include <dev/evdev/input-event-codes.h>
+#endif
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <json-c/json.h>
#include <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
@@ -28,6 +34,7 @@
#include "sway/tree/view.h"
#include "list.h"
#include "log.h"
+#include "util.h"
static int ipc_socket = -1;
static struct wl_event_source *ipc_event_source = NULL;
@@ -367,6 +374,75 @@ void ipc_event_shutdown(const char *reason) {
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) {
struct ipc_client *client = data;