|  |  | @ -13,16 +13,76 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "rootston/seat.h" |  |  |  | #include "rootston/seat.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "rootston/keyboard.h" |  |  |  | #include "rootston/keyboard.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static ssize_t keyboard_pressed_keysym_index(struct roots_keyboard *keyboard, |  |  |  | static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		xkb_keysym_t keysym) { |  |  |  | 		xkb_keysym_t keysym) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; i++) { |  |  |  | 	for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		if (keyboard->pressed_keysyms[i] == keysym) { |  |  |  | 		if (pressed_keysyms[i] == keysym) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			return i; |  |  |  | 			return i; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return -1; |  |  |  | 	return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	size_t n = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (pressed_keysyms[i] != XKB_KEY_NoSymbol) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			++n; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return n; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		xkb_keysym_t keysym) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (i < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (i >= 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			pressed_keysyms[i] = keysym; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		xkb_keysym_t keysym) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (i >= 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		pressed_keysyms[i] = XKB_KEY_NoSymbol; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static bool keysym_is_modifier(xkb_keysym_t keysym) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	switch (keysym) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Shift_L: case XKB_KEY_Shift_R: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Control_L: case XKB_KEY_Control_R: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Caps_Lock: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Shift_Lock: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Meta_L: case XKB_KEY_Meta_R: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Alt_L: case XKB_KEY_Alt_R: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Super_L: case XKB_KEY_Super_R: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return true; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	default: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		const xkb_keysym_t *keysyms, size_t keysyms_len, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		enum wlr_key_state state) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for (size_t i = 0; i < keysyms_len; ++i) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (keysym_is_modifier(keysyms[i])) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (state == WLR_KEY_PRESSED) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			pressed_keysyms_add(pressed_keysyms, keysyms[i]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} else { // WLR_KEY_RELEASED
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			pressed_keysyms_remove(pressed_keysyms, keysyms[i]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static const char *exec_prefix = "exec "; |  |  |  | static const char *exec_prefix = "exec "; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static void keyboard_binding_execute(struct roots_keyboard *keyboard, |  |  |  | static void keyboard_binding_execute(struct roots_keyboard *keyboard, | 
			
		
	
	
		
		
			
				
					|  |  | @ -56,21 +116,14 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /**
 |  |  |  | /**
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Process a keypress from the keyboard. |  |  |  |  * Execute a built-in, hardcoded compositor binding. These are triggered from a | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * single keysym. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Returns true if the keysym was handled by a binding and false if the event |  |  |  |  * Returns true if the keysym was handled by a binding and false if the event | 
			
		
	
		
		
			
				
					
					|  |  |  |  * should be propagated to clients. |  |  |  |  * should be propagated to clients. | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool keyboard_keysym_press(struct roots_keyboard *keyboard, |  |  |  | static bool keyboard_execute_compositor_binding(struct roots_keyboard *keyboard, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		xkb_keysym_t keysym) { |  |  |  | 		xkb_keysym_t keysym) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (i < 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		i = keyboard_pressed_keysym_index(keyboard, XKB_KEY_NoSymbol); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (i >= 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			keyboard->pressed_keysyms[i] = keysym; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (keysym >= XKB_KEY_XF86Switch_VT_1 && |  |  |  | 	if (keysym >= XKB_KEY_XF86Switch_VT_1 && | 
			
		
	
		
		
			
				
					
					|  |  |  | 			keysym <= XKB_KEY_XF86Switch_VT_12) { |  |  |  | 			keysym <= XKB_KEY_XF86Switch_VT_12) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		struct roots_server *server = keyboard->input->server; |  |  |  | 		struct roots_server *server = keyboard->input->server; | 
			
		
	
	
		
		
			
				
					|  |  | @ -90,17 +143,37 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		wlr_seat_keyboard_end_grab(keyboard->seat->seat); |  |  |  | 		wlr_seat_keyboard_end_grab(keyboard->seat->seat); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); |  |  |  | 	return false; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /**
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * Execute keyboard bindings. These include compositor bindings and user-defined | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * bindings. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * Returns true if the keysym was handled by a binding and false if the event | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * should be propagated to clients. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static bool keyboard_execute_binding(struct roots_keyboard *keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		xkb_keysym_t *pressed_keysyms, uint32_t modifiers, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		const xkb_keysym_t *keysyms, size_t keysyms_len) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for (size_t i = 0; i < keysyms_len; ++i) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (keyboard_execute_compositor_binding(keyboard, keysyms[i])) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return true; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	// User-defined bindings
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	size_t n = pressed_keysyms_length(pressed_keysyms); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct wl_list *bindings = &keyboard->input->server->config->bindings; |  |  |  | 	struct wl_list *bindings = &keyboard->input->server->config->bindings; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	struct roots_binding_config *bc; |  |  |  | 	struct roots_binding_config *bc; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	wl_list_for_each(bc, bindings, link) { |  |  |  | 	wl_list_for_each(bc, bindings, link) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (modifiers ^ bc->modifiers) { |  |  |  | 		if (modifiers ^ bc->modifiers || n != bc->keysyms_len) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			continue; |  |  |  | 			continue; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		bool ok = true; |  |  |  | 		bool ok = true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		for (size_t i = 0; i < bc->keysyms_len; i++) { |  |  |  | 		for (size_t i = 0; i < bc->keysyms_len; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			ssize_t j = keyboard_pressed_keysym_index(keyboard, bc->keysyms[i]); |  |  |  | 			ssize_t j = pressed_keysyms_index(pressed_keysyms, bc->keysyms[i]); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			if (j < 0) { |  |  |  | 			if (j < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				ok = false; |  |  |  | 				ok = false; | 
			
		
	
		
		
			
				
					
					|  |  |  | 				break; |  |  |  | 				break; | 
			
		
	
	
		
		
			
				
					|  |  | @ -116,85 +189,75 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return false; |  |  |  | 	return false; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static void keyboard_keysym_release(struct roots_keyboard *keyboard, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		xkb_keysym_t keysym) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (i >= 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		keyboard->pressed_keysyms[i] = XKB_KEY_NoSymbol; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | /*
 |  |  |  | /*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Process keypresses from the keyboard as xkb sees them. |  |  |  |  * Get keysyms and modifiers from the keyboard as xkb sees them. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * This uses the xkb keysyms translation based on pressed modifiers and clears |  |  |  |  * This uses the xkb keysyms translation based on pressed modifiers and clears | 
			
		
	
		
		
			
				
					
					|  |  |  |  * the consumed modifiers from the list of modifiers passed to keybind |  |  |  |  * the consumed modifiers from the list of modifiers passed to keybind | 
			
		
	
		
		
			
				
					
					|  |  |  |  * detection. |  |  |  |  * detection. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * (On US layout) this will trigger: [Alt]+[at] |  |  |  |  * On US layout, pressing Alt+Shift+2 will trigger Alt+@. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool keyboard_keysyms_xkb(struct roots_keyboard *keyboard, |  |  |  | static size_t keyboard_keysyms_translated(struct roots_keyboard *keyboard, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		uint32_t keycode, enum wlr_key_state state) { |  |  |  | 		xkb_keycode_t keycode, const xkb_keysym_t **keysyms, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); |  |  |  | 		uint32_t *modifiers) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	const xkb_keysym_t *syms; |  |  |  | 	*modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, |  |  |  | 	xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		keycode, &syms); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	uint32_t consumed = xkb_state_key_get_consumed_mods2( |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); |  |  |  | 		keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	*modifiers = *modifiers & ~consumed; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	modifiers = modifiers & ~consumed; |  |  |  | 	return xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		keycode, keysyms); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	bool handled = false; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for (int i = 0; i < syms_len; i++) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (state) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			bool keysym_handled = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				keyboard_keysym_press(keyboard, syms[i]); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			handled = handled || keysym_handled; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { // WLR_KEY_RELEASED
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			keyboard_keysym_release(keyboard, syms[i]); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return handled; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /*
 |  |  |  | /*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Process keypresses from the keyboard as if modifiers didn't change keysyms. |  |  |  |  * Get keysyms and modifiers from the keyboard as if modifiers didn't change | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * keysyms. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * This avoids the xkb keysym translation based on modifiers considered pressed |  |  |  |  * This avoids the xkb keysym translation based on modifiers considered pressed | 
			
		
	
		
		
			
				
					
					|  |  |  |  * in the state and uses the list of modifiers saved on the rootston side. |  |  |  |  * in the state. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * This will trigger the keybind: [Alt]+[Shift]+2 |  |  |  |  * This will trigger keybinds such as Alt+Shift+2. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool keyboard_keysyms_simple(struct roots_keyboard *keyboard, |  |  |  | static size_t keyboard_keysyms_raw(struct roots_keyboard *keyboard, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		uint32_t keycode, enum wlr_key_state state) { |  |  |  | 		xkb_keycode_t keycode, const xkb_keysym_t **keysyms, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	const xkb_keysym_t *syms; |  |  |  | 		uint32_t *modifiers) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	*modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	xkb_layout_index_t layout_index = xkb_state_key_get_layout( |  |  |  | 	xkb_layout_index_t layout_index = xkb_state_key_get_layout( | 
			
		
	
		
		
			
				
					
					|  |  |  | 		keyboard->device->keyboard->xkb_state, keycode); |  |  |  | 		keyboard->device->keyboard->xkb_state, keycode); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	int syms_len = xkb_keymap_key_get_syms_by_level( |  |  |  | 	return xkb_keymap_key_get_syms_by_level(keyboard->device->keyboard->keymap, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		keyboard->device->keyboard->keymap, keycode, layout_index, 0, &syms); |  |  |  | 		keycode, layout_index, 0, keysyms); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	bool handled = false; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for (int i = 0; i < syms_len; i++) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (state) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			bool keysym_handled = keyboard_keysym_press(keyboard, syms[i]); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			handled = handled || keysym_handled; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { // WLR_KEY_RELEASED
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			keyboard_keysym_release(keyboard, syms[i]); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return handled; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void roots_keyboard_handle_key(struct roots_keyboard *keyboard, |  |  |  | void roots_keyboard_handle_key(struct roots_keyboard *keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		struct wlr_event_keyboard_key *event) { |  |  |  | 		struct wlr_event_keyboard_key *event) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	uint32_t keycode = event->keycode + 8; |  |  |  | 	xkb_keycode_t keycode = event->keycode + 8; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	bool handled = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	uint32_t modifiers; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	const xkb_keysym_t *keysyms; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	size_t keysyms_len; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	bool handled = keyboard_keysyms_xkb(keyboard, keycode, event->state); |  |  |  | 	// Handle translated keysyms
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!handled) { |  |  |  | 	keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		bool key_handled = keyboard_keysyms_simple(keyboard, keycode, |  |  |  | 		&modifiers); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		keysyms_len, event->state); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (event->state == WLR_KEY_PRESSED) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		handled = keyboard_execute_binding(keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			keyboard->pressed_keysyms_translated, modifiers, keysyms, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			keysyms_len); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	// Handle raw keysyms
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &modifiers); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, keysyms_len, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		event->state); |  |  |  | 		event->state); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		handled = handled || key_handled; |  |  |  | 	if (event->state == WLR_KEY_PRESSED && !handled) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		handled = keyboard_execute_binding(keyboard, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			keyboard->pressed_keysyms_raw, modifiers, keysyms, keysyms_len); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!handled) { |  |  |  | 	if (!handled) { | 
			
		
	
	
		
		
			
				
					|  |  | 
 |