mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	fix the keybind handling in rootston.
As mentioned in https://github.com/swaywm/wlroots/issues/393 keybinds did't trigger / were checked with "odd" keys and modifiers. This commit sends the keycode through two paths, one to get the keycode and modifiers *after* xkb handles them, a secondary path to get a "raw" keysym without modifiers and then add the modifiers rootston knows about. This will result in the `[Alt]+[Shift]+2` combination I mention earlier going through the keybind detection twice. 1) `[Alt]+[at]` 2) `[Alt]+[Shift]+2` When either combination is found, the appropriate keybind is executed. The xkb handled version will be prefered over the "raw" version.
This commit is contained in:
		
							parent
							
								
									63a46c6550
								
							
						
					
					
						commit
						c88990d2c2
					
				
					 1 changed files with 55 additions and 11 deletions
				
			
		| 
						 | 
					@ -60,7 +60,7 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
 | 
				
			||||||
 * should be propagated to clients.
 | 
					 * should be propagated to clients.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
 | 
					static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
 | 
				
			||||||
		xkb_keysym_t keysym) {
 | 
							xkb_keysym_t keysym, uint32_t modifiers) {
 | 
				
			||||||
	ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym);
 | 
						ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym);
 | 
				
			||||||
	if (i < 0) {
 | 
						if (i < 0) {
 | 
				
			||||||
		i = keyboard_pressed_keysym_index(keyboard, XKB_KEY_NoSymbol);
 | 
							i = keyboard_pressed_keysym_index(keyboard, XKB_KEY_NoSymbol);
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,6 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
 | 
				
			||||||
		wlr_seat_keyboard_end_grab(keyboard->input->wl_seat);
 | 
							wlr_seat_keyboard_end_grab(keyboard->input->wl_seat);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
 | 
					 | 
				
			||||||
	struct wl_list *bindings = &keyboard->input->server->config->bindings;
 | 
						struct wl_list *bindings = &keyboard->input->server->config->bindings;
 | 
				
			||||||
	struct binding_config *bc;
 | 
						struct binding_config *bc;
 | 
				
			||||||
	wl_list_for_each(bc, bindings, link) {
 | 
						wl_list_for_each(bc, bindings, link) {
 | 
				
			||||||
| 
						 | 
					@ -122,25 +121,70 @@ static void keyboard_keysym_release(struct roots_keyboard *keyboard,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void keyboard_key_notify(struct wl_listener *listener, void *data) {
 | 
					static bool keyboard_keysyms_simple(struct roots_keyboard *keyboard,
 | 
				
			||||||
	struct wlr_event_keyboard_key *event = data;
 | 
							uint32_t keycode, enum wlr_key_state state)
 | 
				
			||||||
	struct roots_keyboard *keyboard = wl_container_of(listener, keyboard, key);
 | 
					{
 | 
				
			||||||
 | 
						uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
 | 
				
			||||||
	uint32_t keycode = event->keycode + 8;
 | 
					 | 
				
			||||||
	const xkb_keysym_t *syms;
 | 
						const xkb_keysym_t *syms;
 | 
				
			||||||
	int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
 | 
						xkb_layout_index_t layout_index = xkb_state_key_get_layout(
 | 
				
			||||||
		keycode, &syms);
 | 
							keyboard->device->keyboard->xkb_state,
 | 
				
			||||||
 | 
							keycode);
 | 
				
			||||||
 | 
						int syms_len = xkb_keymap_key_get_syms_by_level(keyboard->device->keyboard->keymap,
 | 
				
			||||||
 | 
							keycode, layout_index, 0, &syms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool handled = false;
 | 
						bool handled = false;
 | 
				
			||||||
	for (int i = 0; i < syms_len; i++) {
 | 
						for (int i = 0; i < syms_len; i++) {
 | 
				
			||||||
		if (event->state == WLR_KEY_PRESSED) {
 | 
							if (state) {
 | 
				
			||||||
			bool keysym_handled = keyboard_keysym_press(keyboard, syms[i]);
 | 
								bool keysym_handled = keyboard_keysym_press(keyboard,
 | 
				
			||||||
 | 
									syms[i], modifiers);
 | 
				
			||||||
			handled = handled || keysym_handled;
 | 
								handled = handled || keysym_handled;
 | 
				
			||||||
		} else { // WLR_KEY_RELEASED
 | 
							} else { // WLR_KEY_RELEASED
 | 
				
			||||||
			keyboard_keysym_release(keyboard, syms[i]);
 | 
								keyboard_keysym_release(keyboard, syms[i]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return handled;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool keyboard_keysyms_xkb(struct roots_keyboard *keyboard,
 | 
				
			||||||
 | 
							uint32_t keycode, enum wlr_key_state state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
 | 
				
			||||||
 | 
						const xkb_keysym_t *syms;
 | 
				
			||||||
 | 
						int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
 | 
				
			||||||
 | 
							keycode, &syms);
 | 
				
			||||||
 | 
						uint32_t consumed = xkb_state_key_get_consumed_mods2(
 | 
				
			||||||
 | 
							keyboard->device->keyboard->xkb_state,
 | 
				
			||||||
 | 
							keycode,
 | 
				
			||||||
 | 
							XKB_CONSUMED_MODE_XKB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						modifiers = modifiers & ~consumed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool handled = false;
 | 
				
			||||||
 | 
						for (int i = 0; i < syms_len; i++) {
 | 
				
			||||||
 | 
							if (state) {
 | 
				
			||||||
 | 
								bool keysym_handled = keyboard_keysym_press(keyboard,
 | 
				
			||||||
 | 
									syms[i], modifiers);
 | 
				
			||||||
 | 
								handled = handled || keysym_handled;
 | 
				
			||||||
 | 
							} else { // WLR_KEY_RELEASED
 | 
				
			||||||
 | 
								keyboard_keysym_release(keyboard, syms[i]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return handled;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void keyboard_key_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_event_keyboard_key *event = data;
 | 
				
			||||||
 | 
						struct roots_keyboard *keyboard = wl_container_of(listener, keyboard, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t keycode = event->keycode + 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool handled = keyboard_keysyms_xkb(keyboard, keycode, event->state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!handled)
 | 
				
			||||||
 | 
							handled |= keyboard_keysyms_simple(keyboard, keycode, event->state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!handled) {
 | 
						if (!handled) {
 | 
				
			||||||
		wlr_seat_set_keyboard(keyboard->input->wl_seat, keyboard->device);
 | 
							wlr_seat_set_keyboard(keyboard->input->wl_seat, keyboard->device);
 | 
				
			||||||
		wlr_seat_keyboard_notify_key(keyboard->input->wl_seat, event->time_msec,
 | 
							wlr_seat_keyboard_notify_key(keyboard->input->wl_seat, event->time_msec,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue