mirror of
https://github.com/swaywm/sway.git
synced 2024-11-30 03:41:27 +00:00
Merge pull request #2303 from frsfnrrg/mouse-bindings
Implement mouse bindings
This commit is contained in:
commit
1a9179dbab
|
@ -22,14 +22,28 @@ struct sway_variable {
|
||||||
char *value;
|
char *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum binding_input_type {
|
||||||
|
BINDING_KEYCODE,
|
||||||
|
BINDING_KEYSYM,
|
||||||
|
BINDING_MOUSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum binding_flags {
|
||||||
|
BINDING_RELEASE=1,
|
||||||
|
BINDING_LOCKED=2, // keyboard only
|
||||||
|
BINDING_BORDER=4, // mouse only; trigger on container border
|
||||||
|
BINDING_CONTENTS=8, // mouse only; trigger on container contents
|
||||||
|
BINDING_TITLEBAR=16 // mouse only; trigger on container titlebar
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key binding and an associated command.
|
* A key binding and an associated command.
|
||||||
*/
|
*/
|
||||||
struct sway_binding {
|
struct sway_binding {
|
||||||
|
enum binding_input_type type;
|
||||||
int order;
|
int order;
|
||||||
bool release;
|
uint32_t flags;
|
||||||
bool locked;
|
|
||||||
bool bindcode;
|
|
||||||
list_t *keys; // sorted in ascending order
|
list_t *keys; // sorted in ascending order
|
||||||
uint32_t modifiers;
|
uint32_t modifiers;
|
||||||
char *command;
|
char *command;
|
||||||
|
@ -50,6 +64,7 @@ struct sway_mode {
|
||||||
char *name;
|
char *name;
|
||||||
list_t *keysym_bindings;
|
list_t *keysym_bindings;
|
||||||
list_t *keycode_bindings;
|
list_t *keycode_bindings;
|
||||||
|
list_t *mouse_bindings;
|
||||||
bool pango;
|
bool pango;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -482,6 +497,8 @@ void free_sway_binding(struct sway_binding *sb);
|
||||||
|
|
||||||
struct sway_binding *sway_binding_dup(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();
|
void load_swaybars();
|
||||||
|
|
||||||
void invoke_swaybar(struct bar_config *bar);
|
void invoke_swaybar(struct bar_config *bar);
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "sway/input/seat.h"
|
#include "sway/input/seat.h"
|
||||||
|
|
||||||
|
#define SWAY_CURSOR_PRESSED_BUTTONS_CAP 32
|
||||||
|
|
||||||
struct sway_cursor {
|
struct sway_cursor {
|
||||||
struct sway_seat *seat;
|
struct sway_seat *seat;
|
||||||
struct wlr_cursor *cursor;
|
struct wlr_cursor *cursor;
|
||||||
|
@ -29,6 +31,10 @@ struct sway_cursor {
|
||||||
uint32_t tool_buttons;
|
uint32_t tool_buttons;
|
||||||
|
|
||||||
struct wl_listener request_set_cursor;
|
struct wl_listener request_set_cursor;
|
||||||
|
|
||||||
|
// Mouse binding state
|
||||||
|
uint32_t pressed_buttons[SWAY_CURSOR_PRESSED_BUTTONS_CAP];
|
||||||
|
size_t pressed_button_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sway_cursor_destroy(struct sway_cursor *cursor);
|
void sway_cursor_destroy(struct sway_cursor *cursor);
|
||||||
|
|
|
@ -34,11 +34,14 @@ void free_sway_binding(struct sway_binding *binding) {
|
||||||
*/
|
*/
|
||||||
static bool binding_key_compare(struct sway_binding *binding_a,
|
static bool binding_key_compare(struct sway_binding *binding_a,
|
||||||
struct sway_binding *binding_b) {
|
struct sway_binding *binding_b) {
|
||||||
if (binding_a->release != binding_b->release) {
|
if (binding_a->type != binding_b->type) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binding_a->bindcode != binding_b->bindcode) {
|
uint32_t conflict_generating_flags = BINDING_RELEASE | BINDING_BORDER
|
||||||
|
| BINDING_CONTENTS | BINDING_TITLEBAR;
|
||||||
|
if ((binding_a->flags & conflict_generating_flags) !=
|
||||||
|
(binding_b->flags & conflict_generating_flags)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +72,66 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) {
|
||||||
return (key_a < key_b) ? -1 : ((key_a > key_b) ? 1 : 0);
|
return (key_a < key_b) ? -1 : ((key_a > key_b) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From a keycode, bindcode, or bindsym name and the most likely binding type,
|
||||||
|
* identify the appropriate numeric value corresponding to the key. Return NULL
|
||||||
|
* and set *key_val if successful, otherwise return a specific error. Change
|
||||||
|
* the value of *type if the initial type guess was incorrect and if this
|
||||||
|
* was the first identified key.
|
||||||
|
*/
|
||||||
|
static struct cmd_results *identify_key(const char* name, bool first_key,
|
||||||
|
uint32_t* key_val, enum binding_input_type* type) {
|
||||||
|
if (*type == BINDING_KEYCODE) {
|
||||||
|
// check for keycode
|
||||||
|
xkb_keycode_t keycode = strtol(name, NULL, 10);
|
||||||
|
if (!xkb_keycode_is_legal_ext(keycode)) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "bindcode",
|
||||||
|
"Invalid keycode '%s'", name);
|
||||||
|
}
|
||||||
|
*key_val = keycode;
|
||||||
|
} else {
|
||||||
|
// check for keysym
|
||||||
|
xkb_keysym_t keysym = xkb_keysym_from_name(name,
|
||||||
|
XKB_KEYSYM_CASE_INSENSITIVE);
|
||||||
|
|
||||||
|
// Check for mouse binding
|
||||||
|
uint32_t button = 0;
|
||||||
|
if (strncasecmp(name, "button", strlen("button")) == 0 &&
|
||||||
|
strlen(name) == strlen("button0")) {
|
||||||
|
button = name[strlen("button")] - '1' + BTN_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*type == BINDING_KEYSYM) {
|
||||||
|
if (button) {
|
||||||
|
if (first_key) {
|
||||||
|
*type = BINDING_MOUSE;
|
||||||
|
*key_val = button;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "bindsym",
|
||||||
|
"Mixed button '%s' into key sequence", name);
|
||||||
|
}
|
||||||
|
} else if (keysym) {
|
||||||
|
*key_val = keysym;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "bindsym",
|
||||||
|
"Unknown key '%s'", name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (button) {
|
||||||
|
*key_val = button;
|
||||||
|
} else if (keysym) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "bindsym",
|
||||||
|
"Mixed keysym '%s' into button sequence", name);
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "bindsym",
|
||||||
|
"Unknown button '%s'", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
||||||
bool bindcode) {
|
bool bindcode) {
|
||||||
const char *bindtype = bindcode ? "bindcode" : "bindsym";
|
const char *bindtype = bindcode ? "bindcode" : "bindsym";
|
||||||
|
@ -85,22 +148,34 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
||||||
}
|
}
|
||||||
binding->keys = create_list();
|
binding->keys = create_list();
|
||||||
binding->modifiers = 0;
|
binding->modifiers = 0;
|
||||||
binding->release = false;
|
binding->flags = 0;
|
||||||
binding->locked = false;
|
binding->type = bindcode ? BINDING_KEYCODE : BINDING_KEYSYM;
|
||||||
binding->bindcode = bindcode;
|
|
||||||
|
bool exclude_titlebar = false;
|
||||||
|
|
||||||
// Handle --release and --locked
|
// Handle --release and --locked
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (strcmp("--release", argv[0]) == 0) {
|
if (strcmp("--release", argv[0]) == 0) {
|
||||||
binding->release = true;
|
binding->flags |= BINDING_RELEASE;
|
||||||
} else if (strcmp("--locked", argv[0]) == 0) {
|
} else if (strcmp("--locked", argv[0]) == 0) {
|
||||||
binding->locked = true;
|
binding->flags |= BINDING_LOCKED;
|
||||||
|
} else if (strcmp("--whole-window", argv[0]) == 0) {
|
||||||
|
binding->flags |= BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR;
|
||||||
|
} else if (strcmp("--border", argv[0]) == 0) {
|
||||||
|
binding->flags |= BINDING_BORDER;
|
||||||
|
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
||||||
|
exclude_titlebar = true;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
argv++;
|
argv++;
|
||||||
argc--;
|
argc--;
|
||||||
}
|
}
|
||||||
|
if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR)
|
||||||
|
|| exclude_titlebar) {
|
||||||
|
binding->type = BINDING_MOUSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
free_sway_binding(binding);
|
free_sway_binding(binding);
|
||||||
return cmd_results_new(CMD_FAILURE, bindtype,
|
return cmd_results_new(CMD_FAILURE, bindtype,
|
||||||
|
@ -119,64 +194,47 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
xkb_keycode_t keycode;
|
// Identify the key and possibly change binding->type
|
||||||
xkb_keysym_t keysym;
|
uint32_t key_val = 0;
|
||||||
if (bindcode) {
|
error = identify_key(split->items[i], binding->keys->length == 0,
|
||||||
// parse keycode
|
&key_val, &binding->type);
|
||||||
keycode = (int)strtol(split->items[i], NULL, 10);
|
if (error) {
|
||||||
if (!xkb_keycode_is_legal_ext(keycode)) {
|
free_sway_binding(binding);
|
||||||
error =
|
list_free(split);
|
||||||
cmd_results_new(CMD_INVALID, "bindcode",
|
return error;
|
||||||
"Invalid keycode '%s'", (char *)split->items[i]);
|
|
||||||
free_sway_binding(binding);
|
|
||||||
list_free(split);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Check for xkb key
|
|
||||||
keysym = xkb_keysym_from_name(split->items[i],
|
|
||||||
XKB_KEYSYM_CASE_INSENSITIVE);
|
|
||||||
|
|
||||||
// Check for mouse binding
|
|
||||||
if (strncasecmp(split->items[i], "button", strlen("button")) == 0 &&
|
|
||||||
strlen(split->items[i]) == strlen("button0")) {
|
|
||||||
keysym = ((char *)split->items[i])[strlen("button")] - '1' + BTN_LEFT;
|
|
||||||
}
|
|
||||||
if (!keysym) {
|
|
||||||
struct cmd_results *ret = cmd_results_new(CMD_INVALID, "bindsym",
|
|
||||||
"Unknown key '%s'", (char *)split->items[i]);
|
|
||||||
free_sway_binding(binding);
|
|
||||||
free_flat_list(split);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *key = calloc(1, sizeof(uint32_t));
|
uint32_t *key = calloc(1, sizeof(uint32_t));
|
||||||
if (!key) {
|
if (!key) {
|
||||||
free_sway_binding(binding);
|
free_sway_binding(binding);
|
||||||
free_flat_list(split);
|
free_flat_list(split);
|
||||||
return cmd_results_new(CMD_FAILURE, bindtype,
|
return cmd_results_new(CMD_FAILURE, bindtype,
|
||||||
"Unable to allocate binding");
|
"Unable to allocate binding key");
|
||||||
}
|
}
|
||||||
|
*key = key_val;
|
||||||
if (bindcode) {
|
|
||||||
*key = (uint32_t)keycode;
|
|
||||||
} else {
|
|
||||||
*key = (uint32_t)keysym;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add(binding->keys, key);
|
list_add(binding->keys, key);
|
||||||
}
|
}
|
||||||
free_flat_list(split);
|
free_flat_list(split);
|
||||||
binding->order = binding_order++;
|
binding->order = binding_order++;
|
||||||
|
|
||||||
|
// refine region of interest for mouse binding once we are certain
|
||||||
|
// that this is one
|
||||||
|
if (exclude_titlebar) {
|
||||||
|
binding->flags &= ~BINDING_TITLEBAR;
|
||||||
|
} else if (binding->type == BINDING_MOUSE) {
|
||||||
|
binding->flags |= BINDING_TITLEBAR;
|
||||||
|
}
|
||||||
|
|
||||||
// sort ascending
|
// sort ascending
|
||||||
list_qsort(binding->keys, key_qsort_cmp);
|
list_qsort(binding->keys, key_qsort_cmp);
|
||||||
|
|
||||||
list_t *mode_bindings;
|
list_t *mode_bindings;
|
||||||
if (bindcode) {
|
if (binding->type == BINDING_KEYCODE) {
|
||||||
mode_bindings = config->current_mode->keycode_bindings;
|
mode_bindings = config->current_mode->keycode_bindings;
|
||||||
} else {
|
} else if (binding->type == BINDING_KEYSYM) {
|
||||||
mode_bindings = config->current_mode->keysym_bindings;
|
mode_bindings = config->current_mode->keysym_bindings;
|
||||||
|
} else {
|
||||||
|
mode_bindings = config->current_mode->mouse_bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite the binding if it already exists
|
// overwrite the binding if it already exists
|
||||||
|
@ -209,3 +267,19 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) {
|
||||||
struct cmd_results *cmd_bindcode(int argc, char **argv) {
|
struct cmd_results *cmd_bindcode(int argc, char **argv) {
|
||||||
return cmd_bindsym_or_bindcode(argc, argv, true);
|
return cmd_bindsym_or_bindcode(argc, argv, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command associated to a binding
|
||||||
|
*/
|
||||||
|
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
|
||||||
|
wlr_log(WLR_DEBUG, "running command for binding: %s",
|
||||||
|
binding->command);
|
||||||
|
config->handler_context.seat = seat;
|
||||||
|
struct cmd_results *results = execute_command(binding->command, NULL);
|
||||||
|
if (results->status != CMD_SUCCESS) {
|
||||||
|
wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
|
||||||
|
binding->command, results->error);
|
||||||
|
}
|
||||||
|
free_cmd_results(results);
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,12 @@ static void free_mode(struct sway_mode *mode) {
|
||||||
}
|
}
|
||||||
list_free(mode->keycode_bindings);
|
list_free(mode->keycode_bindings);
|
||||||
}
|
}
|
||||||
|
if (mode->mouse_bindings) {
|
||||||
|
for (i = 0; i < mode->mouse_bindings->length; i++) {
|
||||||
|
free_sway_binding(mode->mouse_bindings->items[i]);
|
||||||
|
}
|
||||||
|
list_free(mode->mouse_bindings);
|
||||||
|
}
|
||||||
free(mode);
|
free(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +178,7 @@ static void config_defaults(struct sway_config *config) {
|
||||||
strcpy(config->current_mode->name, "default");
|
strcpy(config->current_mode->name, "default");
|
||||||
if (!(config->current_mode->keysym_bindings = create_list())) goto cleanup;
|
if (!(config->current_mode->keysym_bindings = create_list())) goto cleanup;
|
||||||
if (!(config->current_mode->keycode_bindings = create_list())) goto cleanup;
|
if (!(config->current_mode->keycode_bindings = create_list())) goto cleanup;
|
||||||
|
if (!(config->current_mode->mouse_bindings = create_list())) goto cleanup;
|
||||||
list_add(config->modes, config->current_mode);
|
list_add(config->modes, config->current_mode);
|
||||||
|
|
||||||
config->floating_mod = 0;
|
config->floating_mod = 0;
|
||||||
|
|
|
@ -469,6 +469,83 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor,
|
||||||
seat_pointer_notify_button(seat, time_msec, button, state);
|
seat_pointer_notify_button(seat, time_msec, button, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a button (and duplicates) to the sorted list of currently pressed buttons
|
||||||
|
*/
|
||||||
|
static void state_erase_button(struct sway_cursor *cursor, uint32_t button) {
|
||||||
|
size_t j = 0;
|
||||||
|
for (size_t i = 0; i < cursor->pressed_button_count; ++i) {
|
||||||
|
if (i > j) {
|
||||||
|
cursor->pressed_buttons[j] = cursor->pressed_buttons[i];
|
||||||
|
}
|
||||||
|
if (cursor->pressed_buttons[i] != button) {
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (cursor->pressed_button_count > j) {
|
||||||
|
--cursor->pressed_button_count;
|
||||||
|
cursor->pressed_buttons[cursor->pressed_button_count] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a button to the sorted list of currently pressed buttons, if there
|
||||||
|
* is space.
|
||||||
|
*/
|
||||||
|
static void state_add_button(struct sway_cursor *cursor, uint32_t button) {
|
||||||
|
if (cursor->pressed_button_count >= SWAY_CURSOR_PRESSED_BUTTONS_CAP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < cursor->pressed_button_count && cursor->pressed_buttons[i] < button) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
size_t j = cursor->pressed_button_count;
|
||||||
|
while (j > i) {
|
||||||
|
cursor->pressed_buttons[j] = cursor->pressed_buttons[j - 1];
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
cursor->pressed_buttons[i] = button;
|
||||||
|
cursor->pressed_button_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the mouse binding which matches modifier, click location, release,
|
||||||
|
* and pressed button state, otherwise return null.
|
||||||
|
*/
|
||||||
|
static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *cursor,
|
||||||
|
list_t *bindings, uint32_t modifiers, bool release, bool on_titlebar,
|
||||||
|
bool on_border, bool on_content) {
|
||||||
|
uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) |
|
||||||
|
(on_border ? BINDING_BORDER : 0) |
|
||||||
|
(on_content ? BINDING_CONTENTS : 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < bindings->length; ++i) {
|
||||||
|
struct sway_binding *binding = bindings->items[i];
|
||||||
|
if (modifiers ^ binding->modifiers ||
|
||||||
|
cursor->pressed_button_count != (size_t)binding->keys->length ||
|
||||||
|
release != (binding->flags & BINDING_RELEASE) ||
|
||||||
|
!(click_region & binding->flags)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
for (size_t j = 0; j < cursor->pressed_button_count; j++) {
|
||||||
|
uint32_t key = *(uint32_t *)binding->keys->items[j];
|
||||||
|
if (key != cursor->pressed_buttons[j]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void dispatch_cursor_button(struct sway_cursor *cursor,
|
void dispatch_cursor_button(struct sway_cursor *cursor,
|
||||||
uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
|
uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
|
||||||
if (cursor->seat->operation != OP_NONE &&
|
if (cursor->seat->operation != OP_NONE &&
|
||||||
|
@ -485,6 +562,31 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
struct sway_container *cont = container_at_coords(cursor->seat,
|
struct sway_container *cont = container_at_coords(cursor->seat,
|
||||||
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
||||||
|
|
||||||
|
// Handle mouse bindings
|
||||||
|
bool on_border = find_resize_edge(cont, cursor) != WLR_EDGE_NONE;
|
||||||
|
bool on_contents = !on_border && surface;
|
||||||
|
bool on_titlebar = !on_border && !surface;
|
||||||
|
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
|
||||||
|
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||||
|
|
||||||
|
struct sway_binding *binding = NULL;
|
||||||
|
if (state == WLR_BUTTON_PRESSED) {
|
||||||
|
state_add_button(cursor, button);
|
||||||
|
binding = get_active_mouse_binding(cursor,
|
||||||
|
config->current_mode->mouse_bindings, modifiers, false,
|
||||||
|
on_titlebar, on_border, on_contents);
|
||||||
|
} else {
|
||||||
|
binding = get_active_mouse_binding(cursor,
|
||||||
|
config->current_mode->mouse_bindings, modifiers, true,
|
||||||
|
on_titlebar, on_border, on_contents);
|
||||||
|
state_erase_button(cursor, button);
|
||||||
|
}
|
||||||
|
if (binding) {
|
||||||
|
seat_execute_command(cursor->seat, binding);
|
||||||
|
// TODO: do we want to pass on the event?
|
||||||
|
}
|
||||||
|
|
||||||
if (surface && wlr_surface_is_layer_surface(surface)) {
|
if (surface && wlr_surface_is_layer_surface(surface)) {
|
||||||
struct wlr_layer_surface *layer =
|
struct wlr_layer_surface *layer =
|
||||||
wlr_layer_surface_from_wlr_surface(surface);
|
wlr_layer_surface_from_wlr_surface(surface);
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
#include <wlr/backend/multi.h>
|
#include <wlr/backend/multi.h>
|
||||||
#include <wlr/backend/session.h>
|
#include <wlr/backend/session.h>
|
||||||
#include <wlr/types/wlr_idle.h>
|
#include <wlr/types/wlr_idle.h>
|
||||||
#include "sway/desktop/transaction.h"
|
|
||||||
#include "sway/input/seat.h"
|
|
||||||
#include "sway/input/keyboard.h"
|
|
||||||
#include "sway/input/input-manager.h"
|
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
|
#include "sway/desktop/transaction.h"
|
||||||
|
#include "sway/input/input-manager.h"
|
||||||
|
#include "sway/input/keyboard.h"
|
||||||
|
#include "sway/input/seat.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,11 +88,13 @@ static void get_active_binding(const struct sway_shortcut_state *state,
|
||||||
uint32_t modifiers, bool release, bool locked) {
|
uint32_t modifiers, bool release, bool locked) {
|
||||||
for (int i = 0; i < bindings->length; ++i) {
|
for (int i = 0; i < bindings->length; ++i) {
|
||||||
struct sway_binding *binding = bindings->items[i];
|
struct sway_binding *binding = bindings->items[i];
|
||||||
|
bool binding_locked = binding->flags & BINDING_LOCKED;
|
||||||
|
bool binding_release = binding->flags & BINDING_RELEASE;
|
||||||
|
|
||||||
if (modifiers ^ binding->modifiers ||
|
if (modifiers ^ binding->modifiers ||
|
||||||
state->npressed != (size_t)binding->keys->length ||
|
state->npressed != (size_t)binding->keys->length ||
|
||||||
locked > binding->locked ||
|
release != binding_release ||
|
||||||
release != binding->release) {
|
locked > binding_locked) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,23 +120,6 @@ static void get_active_binding(const struct sway_shortcut_state *state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the command associated to a binding
|
|
||||||
*/
|
|
||||||
static void keyboard_execute_command(struct sway_keyboard *keyboard,
|
|
||||||
struct sway_binding *binding) {
|
|
||||||
wlr_log(WLR_DEBUG, "running command for binding: %s",
|
|
||||||
binding->command);
|
|
||||||
config->handler_context.seat = keyboard->seat_device->sway_seat;
|
|
||||||
struct cmd_results *results = execute_command(binding->command, NULL);
|
|
||||||
transaction_commit_dirty();
|
|
||||||
if (results->status != CMD_SUCCESS) {
|
|
||||||
wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
|
|
||||||
binding->command, results->error);
|
|
||||||
}
|
|
||||||
free_cmd_results(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a built-in, hardcoded compositor binding. These are triggered from a
|
* Execute a built-in, hardcoded compositor binding. These are triggered from a
|
||||||
* single keysym.
|
* single keysym.
|
||||||
|
@ -211,12 +196,13 @@ static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard,
|
||||||
static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
struct sway_keyboard *keyboard =
|
struct sway_keyboard *keyboard =
|
||||||
wl_container_of(listener, keyboard, keyboard_key);
|
wl_container_of(listener, keyboard, keyboard_key);
|
||||||
struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
|
struct sway_seat* seat = keyboard->seat_device->sway_seat;
|
||||||
|
struct wlr_seat *wlr_seat = seat->wlr_seat;
|
||||||
struct wlr_input_device *wlr_device =
|
struct wlr_input_device *wlr_device =
|
||||||
keyboard->seat_device->input_device->wlr_device;
|
keyboard->seat_device->input_device->wlr_device;
|
||||||
wlr_idle_notify_activity(keyboard->seat_device->sway_seat->input->server->idle, wlr_seat);
|
wlr_idle_notify_activity(seat->input->server->idle, wlr_seat);
|
||||||
struct wlr_event_keyboard_key *event = data;
|
struct wlr_event_keyboard_key *event = data;
|
||||||
bool input_inhibited = keyboard->seat_device->sway_seat->exclusive_client != NULL;
|
bool input_inhibited = seat->exclusive_client != NULL;
|
||||||
|
|
||||||
// Identify new keycode, raw keysym(s), and translated keysym(s)
|
// Identify new keycode, raw keysym(s), and translated keysym(s)
|
||||||
xkb_keycode_t keycode = event->keycode + 8;
|
xkb_keycode_t keycode = event->keycode + 8;
|
||||||
|
@ -266,7 +252,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
// Execute stored release binding once no longer active
|
// Execute stored release binding once no longer active
|
||||||
if (keyboard->held_binding && binding_released != keyboard->held_binding &&
|
if (keyboard->held_binding && binding_released != keyboard->held_binding &&
|
||||||
event->state == WLR_KEY_RELEASED) {
|
event->state == WLR_KEY_RELEASED) {
|
||||||
keyboard_execute_command(keyboard, keyboard->held_binding);
|
seat_execute_command(seat, keyboard->held_binding);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
if (binding_released != keyboard->held_binding) {
|
if (binding_released != keyboard->held_binding) {
|
||||||
|
@ -290,7 +276,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
raw_modifiers, false, input_inhibited);
|
raw_modifiers, false, input_inhibited);
|
||||||
|
|
||||||
if (binding_pressed) {
|
if (binding_pressed) {
|
||||||
keyboard_execute_command(keyboard, binding_pressed);
|
seat_execute_command(seat, binding_pressed);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,6 +298,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
|
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
|
||||||
event->keycode, event->state);
|
event->keycode, event->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transaction_commit_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_keyboard_modifiers(struct wl_listener *listener,
|
static void handle_keyboard_modifiers(struct wl_listener *listener,
|
||||||
|
|
Loading…
Reference in a new issue