mirror of
				https://github.com/wizbright/waybox.git
				synced 2025-10-29 05:40:20 -04:00 
			
		
		
		
	Lifted support for keys from tinywl; TODO: don't have all the code in server.c
This commit is contained in:
		
							parent
							
								
									1cd178e9ce
								
							
						
					
					
						commit
						64db394085
					
				
					 6 changed files with 142 additions and 3 deletions
				
			
		|  | @ -1,16 +1,28 @@ | ||||||
| #ifndef _WB_SEAT_H | #ifndef _WB_SEAT_H | ||||||
| #define _WB_SEAT_H | #define _WB_SEAT_H | ||||||
| 
 | 
 | ||||||
|  | #include <wlr/types/wlr_keyboard.h> | ||||||
| #include <wlr/types/wlr_seat.h> | #include <wlr/types/wlr_seat.h> | ||||||
| 
 | 
 | ||||||
| #include "waybox/server.h" | #include "waybox/server.h" | ||||||
| 
 | 
 | ||||||
| struct wb_seat { | struct wb_seat { | ||||||
| 	struct wlr_seat * seat; | 	struct wlr_seat * seat; | ||||||
|  | 
 | ||||||
|  | 	struct wl_list keyboards; | ||||||
|  | 	struct wl_listener new_input; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct wb_keyboard { | ||||||
|  | 	struct wl_list link; | ||||||
|  | 	struct wb_server * server; | ||||||
|  | 	struct wlr_input_device * device; | ||||||
|  | 
 | ||||||
|  | 	struct wl_listener modifiers; | ||||||
|  | 	struct wl_listener key; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct wb_server; | struct wb_server; | ||||||
| struct wb_seat * wb_seat_create(struct wb_server * server); | struct wb_seat * wb_seat_create(struct wb_server * server); | ||||||
| 
 |  | ||||||
| void wb_seat_destroy(struct wb_seat * seat); | void wb_seat_destroy(struct wb_seat * seat); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ wlroots = dependency('wlroots', version: '>=0.6.0') | ||||||
| wayland_server = dependency('wayland-server') | wayland_server = dependency('wayland-server') | ||||||
| wayland_client = dependency('wayland-client') | wayland_client = dependency('wayland-client') | ||||||
| wayland_protos  = dependency('wayland-protocols', version: '>=1.12') | wayland_protos  = dependency('wayland-protocols', version: '>=1.12') | ||||||
|  | xkbcommon  = dependency('xkbcommon') | ||||||
| 
 | 
 | ||||||
| subdir('protocol') | subdir('protocol') | ||||||
| subdir('waybox') | subdir('waybox') | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ protocols = [ | ||||||
| 	[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | 	[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | ||||||
| 	[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], | 	[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], | ||||||
| 	[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], | 	[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], | ||||||
| 	[wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], |  | ||||||
| 	'wlr-gamma-control-unstable-v1.xml', | 	'wlr-gamma-control-unstable-v1.xml', | ||||||
| 	'gtk-primary-selection.xml', | 	'gtk-primary-selection.xml', | ||||||
| 	'idle.xml', | 	'idle.xml', | ||||||
|  | @ -34,7 +33,6 @@ protocols = [ | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| client_protocols = [ | client_protocols = [ | ||||||
| 	[wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], |  | ||||||
| 	[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | 	[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | ||||||
| 	[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], | 	[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], | ||||||
| 	'idle.xml', | 	'idle.xml', | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ wb_dep = [ | ||||||
|   wayland_server, |   wayland_server, | ||||||
|   wlroots, |   wlroots, | ||||||
|   pixman, |   pixman, | ||||||
|  |   xkbcommon, | ||||||
|   ] |   ] | ||||||
| 
 | 
 | ||||||
| executable( | executable( | ||||||
|  |  | ||||||
|  | @ -4,8 +4,13 @@ | ||||||
| 
 | 
 | ||||||
| struct wb_seat * wb_seat_create(struct wb_server * server) { | struct wb_seat * wb_seat_create(struct wb_server * server) { | ||||||
| 	struct wb_seat * seat = malloc(sizeof(struct wb_seat)); | 	struct wb_seat * seat = malloc(sizeof(struct wb_seat)); | ||||||
|  | 
 | ||||||
|  | 	wl_list_init(&seat->keyboards); | ||||||
|  | 	//seat->new_input.notify = new_input_notify;
 | ||||||
|  | 	//wl_signal_add(&server->backend->events.new_input, &server->new_input);
 | ||||||
| 	seat->seat = wlr_seat_create(server->wl_display, "seat0"); | 	seat->seat = wlr_seat_create(server->wl_display, "seat0"); | ||||||
| 	wlr_seat_set_capabilities(seat->seat, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD); | 	wlr_seat_set_capabilities(seat->seat, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD); | ||||||
|  | 
 | ||||||
| 	return seat; | 	return seat; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										122
									
								
								waybox/server.c
									
										
									
									
									
								
							
							
						
						
									
										122
									
								
								waybox/server.c
									
										
									
									
									
								
							|  | @ -1,9 +1,131 @@ | ||||||
| #include "waybox/server.h" | #include "waybox/server.h" | ||||||
|  | #include "waybox/seat.h" | ||||||
|  | 
 | ||||||
|  | /* Stolen from wltiny.  Customizations will come later. */ | ||||||
|  | static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym) { | ||||||
|  | 	/*
 | ||||||
|  | 	 * Here we handle compositor keybindings. This is when the compositor is | ||||||
|  | 	 * processing keys, rather than passing them on to the client for its own | ||||||
|  | 	 * processing. | ||||||
|  | 	 * | ||||||
|  | 	 * This function assumes Alt is held down. | ||||||
|  | 	 */ | ||||||
|  | 	switch (sym) { | ||||||
|  | 	case XKB_KEY_Escape: | ||||||
|  | 		wl_display_terminate(server->wl_display); | ||||||
|  | 		break; | ||||||
|  | 	case XKB_KEY_F1: | ||||||
|  | #if 0 | ||||||
|  | 		/* Cycle to the next view */ | ||||||
|  | 		if (wl_list_length(&server->views) < 2) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		struct tinywl_view *current_view = wl_container_of( | ||||||
|  | 			server->views.next, current_view, link); | ||||||
|  | 		struct tinywl_view *next_view = wl_container_of( | ||||||
|  | 			current_view->link.next, next_view, link); | ||||||
|  | 		focus_view(next_view, next_view->xdg_surface->surface); | ||||||
|  | 		/* Move the previous view to the end of the list */ | ||||||
|  | 		wl_list_remove(¤t_view->link); | ||||||
|  | 		wl_list_insert(server->views.prev, ¤t_view->link); | ||||||
|  | #endif | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void keyboard_handle_modifiers( | ||||||
|  | 		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. */ | ||||||
|  | 	struct wb_keyboard *keyboard = | ||||||
|  | 		wl_container_of(listener, keyboard, 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(keyboard->server->seat->seat, keyboard->device); | ||||||
|  | 	/* Send modifiers to the client. */ | ||||||
|  | 	wlr_seat_keyboard_notify_modifiers(keyboard->server->seat->seat, | ||||||
|  | 		&keyboard->device->keyboard->modifiers); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void keyboard_handle_key( | ||||||
|  | 		struct wl_listener *listener, void *data) { | ||||||
|  | 	/* This event is raised when a key is pressed or released. */ | ||||||
|  | 	struct wb_keyboard *keyboard = | ||||||
|  | 		wl_container_of(listener, keyboard, key); | ||||||
|  | 	struct wb_server *server = keyboard->server; | ||||||
|  | 	struct wlr_event_keyboard_key *event = data; | ||||||
|  | 	struct wlr_seat *seat = server->seat->seat; | ||||||
|  | 
 | ||||||
|  | 	/* Translate libinput keycode -> xkbcommon */ | ||||||
|  | 	uint32_t keycode = event->keycode + 8; | ||||||
|  | 	/* Get a list of keysyms based on the keymap for this keyboard */ | ||||||
|  | 	const xkb_keysym_t *syms; | ||||||
|  | 	int nsyms = xkb_state_key_get_syms( | ||||||
|  | 			keyboard->device->keyboard->xkb_state, keycode, &syms); | ||||||
|  | 
 | ||||||
|  | 	bool handled = false; | ||||||
|  | 	uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); | ||||||
|  | 	if ((modifiers & WLR_MODIFIER_ALT) && event->state == WLR_KEY_PRESSED) { | ||||||
|  | 		/* If alt is held down and this button was _pressed_, we attempt to
 | ||||||
|  | 		 * process it as a compositor keybinding. */ | ||||||
|  | 		for (int i = 0; i < nsyms; i++) { | ||||||
|  | 			handled = handle_keybinding(server, syms[i]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!handled) { | ||||||
|  | 		/* Otherwise, we pass it along to the client. */ | ||||||
|  | 		wlr_seat_set_keyboard(seat, keyboard->device); | ||||||
|  | 		wlr_seat_keyboard_notify_key(seat, event->time_msec, | ||||||
|  | 			event->keycode, event->state); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void server_new_keyboard(struct wb_server *server, | ||||||
|  | 		struct wlr_input_device *device) { | ||||||
|  | 	struct wb_keyboard *keyboard = | ||||||
|  | 		calloc(1, sizeof(struct wb_keyboard)); | ||||||
|  | 	keyboard->server = server; | ||||||
|  | 	keyboard->device = device; | ||||||
|  | 
 | ||||||
|  | 	/* We need to prepare an XKB keymap and assign it to the keyboard. This
 | ||||||
|  | 	 * assumes the defaults (e.g. layout = "us"). */ | ||||||
|  | 	struct xkb_rule_names rules = { 0 }; | ||||||
|  | 	struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | ||||||
|  | 	struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules, | ||||||
|  | 		XKB_KEYMAP_COMPILE_NO_FLAGS); | ||||||
|  | 
 | ||||||
|  | 	wlr_keyboard_set_keymap(device->keyboard, keymap); | ||||||
|  | 	xkb_keymap_unref(keymap); | ||||||
|  | 	xkb_context_unref(context); | ||||||
|  | 	wlr_keyboard_set_repeat_info(device->keyboard, 25, 600); | ||||||
|  | 
 | ||||||
|  | 	/* Here we set up listeners for keyboard events. */ | ||||||
|  | 	keyboard->modifiers.notify = keyboard_handle_modifiers; | ||||||
|  | 	wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifiers); | ||||||
|  | 	keyboard->key.notify = keyboard_handle_key; | ||||||
|  | 	wl_signal_add(&device->keyboard->events.key, &keyboard->key); | ||||||
|  | 
 | ||||||
|  | 	wlr_seat_set_keyboard(server->seat->seat, device); | ||||||
|  | 
 | ||||||
|  | 	/* And add the keyboard to our list of keyboards */ | ||||||
|  | 	wl_list_insert(&server->seat->keyboards, &keyboard->link); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static void new_input_notify(struct wl_listener *listener, void *data) { | static void new_input_notify(struct wl_listener *listener, void *data) { | ||||||
| 	struct wlr_input_device *device = data; | 	struct wlr_input_device *device = data; | ||||||
| 	struct wb_server *server = wl_container_of(listener, server, new_input); | 	struct wb_server *server = wl_container_of(listener, server, new_input); | ||||||
| 	switch (device->type) { | 	switch (device->type) { | ||||||
|  | 		case WLR_INPUT_DEVICE_KEYBOARD: | ||||||
|  | 			server_new_keyboard(server, device); | ||||||
|  | 			break; | ||||||
| 		case WLR_INPUT_DEVICE_POINTER: | 		case WLR_INPUT_DEVICE_POINTER: | ||||||
| 			wlr_cursor_attach_input_device(server->cursor->cursor, device); | 			wlr_cursor_attach_input_device(server->cursor->cursor, device); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Keith Bowes
						Keith Bowes