diff options
Diffstat (limited to 'sway')
| -rw-r--r-- | sway/commands/bind.c | 16 | ||||
| -rw-r--r-- | sway/input/cursor.c | 102 | ||||
| -rw-r--r-- | sway/input/keyboard.c | 40 | 
3 files changed, 131 insertions, 27 deletions
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 6910237f..133fd089 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -267,3 +267,19 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) {  struct cmd_results *cmd_bindcode(int argc, char **argv) {  	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); +} diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 65d04cac..f1481936 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -469,6 +469,83 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor,  	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,  		uint32_t time_msec, uint32_t button, enum wlr_button_state state) {  	if (cursor->seat->operation != OP_NONE && @@ -485,6 +562,31 @@ void dispatch_cursor_button(struct sway_cursor *cursor,  	double sx, sy;  	struct sway_container *cont = container_at_coords(cursor->seat,  			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)) {  		struct wlr_layer_surface *layer =  			wlr_layer_surface_from_wlr_surface(surface); diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index e6c5c335..49241db8 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -3,11 +3,11 @@  #include <wlr/backend/multi.h>  #include <wlr/backend/session.h>  #include <wlr/types/wlr_idle.h> +#include "sway/commands.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/input/keyboard.h" +#include "sway/input/seat.h"  #include "log.h"  /** @@ -88,8 +88,8 @@ static void get_active_binding(const struct sway_shortcut_state *state,  		uint32_t modifiers, bool release, bool locked) {  	for (int i = 0; i < bindings->length; ++i) {  		struct sway_binding *binding = bindings->items[i]; -		bool binding_locked = binding->flags | BINDING_LOCKED; -		bool binding_release = binding->flags | BINDING_RELEASE; +		bool binding_locked = binding->flags & BINDING_LOCKED; +		bool binding_release = binding->flags & BINDING_RELEASE;  		if (modifiers ^ binding->modifiers ||  				state->npressed != (size_t)binding->keys->length || @@ -121,23 +121,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   * single keysym.   * @@ -213,12 +196,13 @@ static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard,  static void handle_keyboard_key(struct wl_listener *listener, void *data) {  	struct sway_keyboard *keyboard =  		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 =  		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; -	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)  	xkb_keycode_t keycode = event->keycode + 8; @@ -268,7 +252,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {  	// Execute stored release binding once no longer active  	if (keyboard->held_binding && binding_released != keyboard->held_binding &&  			event->state == WLR_KEY_RELEASED) { -		keyboard_execute_command(keyboard, keyboard->held_binding); +		seat_execute_command(seat, keyboard->held_binding);  		handled = true;  	}  	if (binding_released != keyboard->held_binding) { @@ -292,7 +276,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {  				raw_modifiers, false, input_inhibited);  		if (binding_pressed) { -			keyboard_execute_command(keyboard, binding_pressed); +			seat_execute_command(seat, binding_pressed);  			handled = true;  		}  	} @@ -314,6 +298,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {  		wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,  				event->keycode, event->state);  	} + +	transaction_commit_dirty();  }  static void handle_keyboard_modifiers(struct wl_listener *listener,  | 
