diff options
| author | David Donahue <david.donahue2996@gmail.com> | 2023-12-12 18:04:38 -0700 | 
|---|---|---|
| committer | Leonardo Hernández Hernández <leohdz172@proton.me> | 2023-12-17 21:41:39 +0000 | 
| commit | 023efce6eb26a7a1be974dfc6c932834bfc260e2 (patch) | |
| tree | 7adb014db0b8662fd6616d8989d28178239fdca4 /dwl.c | |
| parent | fa660fb61e9c883901c43afaf3056af9a8b4736e (diff) | |
use wlr_keyboard_group to manage all keyboards
Diffstat (limited to 'dwl.c')
| -rw-r--r-- | dwl.c | 145 | 
1 files changed, 71 insertions, 74 deletions
@@ -28,6 +28,7 @@  #include <wlr/types/wlr_idle_notify_v1.h>  #include <wlr/types/wlr_input_device.h>  #include <wlr/types/wlr_keyboard.h> +#include <wlr/types/wlr_keyboard_group.h>  #include <wlr/types/wlr_layer_shell_v1.h>  #include <wlr/types/wlr_linux_dmabuf_v1.h>  #include <wlr/types/wlr_output.h> @@ -141,7 +142,7 @@ typedef struct {  typedef struct {  	struct wl_list link; -	struct wlr_keyboard *wlr_keyboard; +	struct wlr_keyboard_group *wlr_group;  	int nsyms;  	const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */ @@ -150,8 +151,7 @@ typedef struct {  	struct wl_listener modifiers;  	struct wl_listener key; -	struct wl_listener destroy; -} Keyboard; +} KeyboardGroup;  typedef struct {  	/* Must keep these three elements in this order */ @@ -238,7 +238,6 @@ static void buttonpress(struct wl_listener *listener, void *data);  static void chvt(const Arg *arg);  static void checkidleinhibitor(struct wlr_surface *exclude);  static void cleanup(void); -static void cleanupkeyboard(struct wl_listener *listener, void *data);  static void cleanupmon(struct wl_listener *listener, void *data);  static void closemon(Monitor *m);  static void commitlayersurfacenotify(struct wl_listener *listener, void *data); @@ -368,7 +367,7 @@ static struct wlr_session_lock_v1 *cur_lock;  static struct wl_listener lock_listener = {.notify = locksession};  static struct wlr_seat *seat; -static struct wl_list keyboards; +static KeyboardGroup kb_group;  static struct wlr_surface *held_grab;  static unsigned int cursor_mode;  static Client *grabc; @@ -636,6 +635,10 @@ cleanup(void)  	}  	wlr_xcursor_manager_destroy(cursor_mgr);  	wlr_output_layout_destroy(output_layout); + +	/* Remove event source that use the dpy event loop before destroying dpy */ +	wl_event_source_remove(kb_group.key_repeat_source); +  	wl_display_destroy(dpy);  	/* Destroy after the wayland display (when the monitors are already destroyed)  	   to avoid destroying them with an invalid scene output. */ @@ -643,19 +646,6 @@ cleanup(void)  }  void -cleanupkeyboard(struct wl_listener *listener, void *data) -{ -	Keyboard *kb = wl_container_of(listener, kb, destroy); - -	wl_event_source_remove(kb->key_repeat_source); -	wl_list_remove(&kb->link); -	wl_list_remove(&kb->modifiers.link); -	wl_list_remove(&kb->key.link); -	wl_list_remove(&kb->destroy.link); -	free(kb); -} - -void  cleanupmon(struct wl_listener *listener, void *data)  {  	Monitor *m = wl_container_of(listener, m, destroy); @@ -761,35 +751,12 @@ createidleinhibitor(struct wl_listener *listener, void *data)  void  createkeyboard(struct wlr_keyboard *keyboard)  { -	struct xkb_context *context; -	struct xkb_keymap *keymap; -	Keyboard *kb = keyboard->data = ecalloc(1, sizeof(*kb)); -	kb->wlr_keyboard = keyboard; - -	/* Prepare an XKB keymap and assign it to the keyboard. */ -	context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); -	keymap = xkb_keymap_new_from_names(context, &xkb_rules, -		XKB_KEYMAP_COMPILE_NO_FLAGS); -	if (!keymap) -		die("createkeyboard: failed to compile keymap"); - -	wlr_keyboard_set_keymap(keyboard, keymap); -	xkb_keymap_unref(keymap); -	xkb_context_unref(context); +	/* Set the keymap to match the group keymap */ +	wlr_keyboard_set_keymap(keyboard, kb_group.wlr_group->keyboard.keymap);  	wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay); -	/* Here we set up listeners for keyboard events. */ -	LISTEN(&keyboard->events.modifiers, &kb->modifiers, keypressmod); -	LISTEN(&keyboard->events.key, &kb->key, keypress); -	LISTEN(&keyboard->base.events.destroy, &kb->destroy, cleanupkeyboard); - -	wlr_seat_set_keyboard(seat, keyboard); - -	kb->key_repeat_source = wl_event_loop_add_timer( -			wl_display_get_event_loop(dpy), keyrepeat, kb); - -	/* And add the keyboard to our list of keyboards */ -	wl_list_insert(&keyboards, &kb->link); +	/* Add the new keyboard to the group */ +	wlr_keyboard_group_add_keyboard(kb_group.wlr_group, keyboard);  }  void @@ -1353,7 +1320,7 @@ inputdevice(struct wl_listener *listener, void *data)  	 * there are no pointer devices, so we always include that capability. */  	/* TODO do we actually require a cursor? */  	caps = WL_SEAT_CAPABILITY_POINTER; -	if (!wl_list_empty(&keyboards)) +	if (!wl_list_empty(&kb_group.wlr_group->devices))  		caps |= WL_SEAT_CAPABILITY_KEYBOARD;  	wlr_seat_set_capabilities(seat, caps);  } @@ -1383,7 +1350,7 @@ keypress(struct wl_listener *listener, void *data)  {  	int i;  	/* This event is raised when a key is pressed or released. */ -	Keyboard *kb = wl_container_of(listener, kb, key); +	KeyboardGroup *group = wl_container_of(listener, group, key);  	struct wlr_keyboard_key_event *event = data;  	/* Translate libinput keycode -> xkbcommon */ @@ -1391,10 +1358,10 @@ keypress(struct wl_listener *listener, void *data)  	/* Get a list of keysyms based on the keymap for this keyboard */  	const xkb_keysym_t *syms;  	int nsyms = xkb_state_key_get_syms( -			kb->wlr_keyboard->xkb_state, keycode, &syms); +			group->wlr_group->keyboard.xkb_state, keycode, &syms);  	int handled = 0; -	uint32_t mods = wlr_keyboard_get_modifiers(kb->wlr_keyboard); +	uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);  	wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); @@ -1404,22 +1371,21 @@ keypress(struct wl_listener *listener, void *data)  		for (i = 0; i < nsyms; i++)  			handled = keybinding(mods, syms[i]) || handled; -	if (handled && kb->wlr_keyboard->repeat_info.delay > 0) { -		kb->mods = mods; -		kb->keysyms = syms; -		kb->nsyms = nsyms; -		wl_event_source_timer_update(kb->key_repeat_source, -				kb->wlr_keyboard->repeat_info.delay); +	if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { +		group->mods = mods; +		group->keysyms = syms; +		group->nsyms = nsyms; +		wl_event_source_timer_update(group->key_repeat_source, +				group->wlr_group->keyboard.repeat_info.delay);  	} else { -		kb->nsyms = 0; -		wl_event_source_timer_update(kb->key_repeat_source, 0); +		group->nsyms = 0; +		wl_event_source_timer_update(group->key_repeat_source, 0);  	}  	if (handled)  		return;  	/* Pass unhandled keycodes along to the client. */ -	wlr_seat_set_keyboard(seat, kb->wlr_keyboard);  	wlr_seat_keyboard_notify_key(seat, event->time_msec,  		event->keycode, event->state);  } @@ -1429,32 +1395,26 @@ keypressmod(struct wl_listener *listener, void *data)  {  	/* This event is raised when a modifier key, such as shift or alt, is  	 * pressed. We simply communicate this to the client. */ -	Keyboard *kb = wl_container_of(listener, kb, modifiers); -	/* -	 * A seat can only have one keyboard, but this is a limitation of the -	 * Wayland protocol - not wlroots. We assign all connected keyboards to the -	 * same seat. You can swap out the underlying wlr_keyboard like this and -	 * wlr_seat handles this transparently. -	 */ -	wlr_seat_set_keyboard(seat, kb->wlr_keyboard); +	KeyboardGroup *group = wl_container_of(listener, group, modifiers); +  	/* Send modifiers to the client. */  	wlr_seat_keyboard_notify_modifiers(seat, -		&kb->wlr_keyboard->modifiers); +		&group->wlr_group->keyboard.modifiers);  }  int  keyrepeat(void *data)  { -	Keyboard *kb = data; +	KeyboardGroup *group = data;  	int i; -	if (!kb->nsyms || kb->wlr_keyboard->repeat_info.rate <= 0) +	if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0)  		return 0; -	wl_event_source_timer_update(kb->key_repeat_source, -			1000 / kb->wlr_keyboard->repeat_info.rate); +	wl_event_source_timer_update(group->key_repeat_source, +			1000 / group->wlr_group->keyboard.repeat_info.rate); -	for (i = 0; i < kb->nsyms; i++) -		keybinding(kb->mods, kb->keysyms[i]); +	for (i = 0; i < group->nsyms; i++) +		keybinding(group->mods, group->keysyms[i]);  	return 0;  } @@ -2160,6 +2120,9 @@ setsel(struct wl_listener *listener, void *data)  void  setup(void)  { +	struct xkb_context *context; +	struct xkb_keymap *keymap; +  	int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};  	struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};  	sigemptyset(&sa.sa_mask); @@ -2323,7 +2286,6 @@ setup(void)  	 * pointer, touch, and drawing tablet device. We also rig up a listener to  	 * let us know when new input devices are available on the backend.  	 */ -	wl_list_init(&keyboards);  	LISTEN_STATIC(&backend->events.new_input, inputdevice);  	virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);  	LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); @@ -2334,6 +2296,41 @@ setup(void)  	LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);  	LISTEN_STATIC(&seat->events.start_drag, startdrag); +	/* +	 * Configures a keyboard group, which will keep track of all connected +	 * keyboards, keep their modifier and LED states in sync, and handle +	 * keypresses +	 */ +	kb_group.wlr_group = wlr_keyboard_group_create(); +	kb_group.wlr_group->data = &kb_group; + +	/* Prepare an XKB keymap and assign it to the keyboard group. */ +	context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); +	keymap = xkb_keymap_new_from_names(context, &xkb_rules, +		XKB_KEYMAP_COMPILE_NO_FLAGS); +	if (!keymap) +		die("failed to compile keymap"); + +	wlr_keyboard_set_keymap(&kb_group.wlr_group->keyboard, keymap); +	xkb_keymap_unref(keymap); +	xkb_context_unref(context); + +	wlr_keyboard_set_repeat_info(&kb_group.wlr_group->keyboard, repeat_rate, repeat_delay); + +	/* Set up listeners for keyboard events */ +	LISTEN(&kb_group.wlr_group->keyboard.events.key, &kb_group.key, keypress); +	LISTEN(&kb_group.wlr_group->keyboard.events.modifiers, &kb_group.modifiers, keypressmod); + +	kb_group.key_repeat_source = wl_event_loop_add_timer( +			wl_display_get_event_loop(dpy), keyrepeat, &kb_group); + +	/* A seat can only have one keyboard, but this is a limitation of the +	 * Wayland protocol - not wlroots. We assign all connected keyboards to the +	 * same wlr_keyboard_group, which provides a single wlr_keyboard interface for +	 * all of them. Set this combined wlr_keyboard as the seat keyboard. +	 */ +	wlr_seat_set_keyboard(seat, &kb_group.wlr_group->keyboard); +  	output_mgr = wlr_output_manager_v1_create(dpy);  	LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);  	LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);  | 
