mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Merge branch 'master' into feature/wlr-seat-touch
This commit is contained in:
		
						commit
						584ff1df4c
					
				
					 16 changed files with 196 additions and 93 deletions
				
			
		
							
								
								
									
										14
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -33,3 +33,17 @@ Run these commands:
 | 
			
		|||
    ninja -C build
 | 
			
		||||
 | 
			
		||||
(On FreeBSD, you need to pass an extra flag to prevent a linking error: `meson build -D b_lundef=false`)
 | 
			
		||||
 | 
			
		||||
## Running the Reference Compositor
 | 
			
		||||
 | 
			
		||||
wlroots comes with a reference compositor called rootston that demonstrates the
 | 
			
		||||
features of the library.
 | 
			
		||||
 | 
			
		||||
After building, run rootston from a terminal or VT with:
 | 
			
		||||
 | 
			
		||||
    ./build/rootston/rootston
 | 
			
		||||
 | 
			
		||||
Now you can run windows in the compositor from the command line or by
 | 
			
		||||
configuring bindings in your
 | 
			
		||||
[`rootston.ini`](https://github.com/swaywm/wlroots/blob/master/rootston/rootston.ini.example)
 | 
			
		||||
file. 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,10 +66,11 @@ static void handle_device_added(struct wlr_libinput_backend *backend,
 | 
			
		|||
	int product = libinput_device_get_id_product(libinput_dev);
 | 
			
		||||
	const char *name = libinput_device_get_name(libinput_dev);
 | 
			
		||||
	struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list));
 | 
			
		||||
	wl_list_init(wlr_devices);
 | 
			
		||||
	if (!wlr_devices) {
 | 
			
		||||
		goto fail;
 | 
			
		||||
		wlr_log(L_ERROR, "Allocation failed");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	wl_list_init(wlr_devices);
 | 
			
		||||
	wlr_log(L_DEBUG, "Added %s [%d:%d]", name, vendor, product);
 | 
			
		||||
 | 
			
		||||
	if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -249,7 +249,7 @@ static size_t explicit_find_gpus(struct wlr_session *session,
 | 
			
		|||
		}
 | 
			
		||||
	} while ((ptr = strtok_r(NULL, ":", &save)));
 | 
			
		||||
 | 
			
		||||
	free(ptr);
 | 
			
		||||
	free(gpus);
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,10 +12,15 @@
 | 
			
		|||
#include "backend/wayland.h"
 | 
			
		||||
#include "xdg-shell-unstable-v6-client-protocol.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int dispatch_events(int fd, uint32_t mask, void *data) {
 | 
			
		||||
	struct wlr_wl_backend *backend = data;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
 | 
			
		||||
	if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
 | 
			
		||||
		wl_display_terminate(backend->local_display);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mask & WL_EVENT_READABLE) {
 | 
			
		||||
		count = wl_display_dispatch(backend->remote_display);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +41,7 @@ static bool wlr_wl_backend_start(struct wlr_backend *_backend) {
 | 
			
		|||
	wlr_log(L_INFO, "Initializating wayland backend");
 | 
			
		||||
 | 
			
		||||
	wlr_wl_registry_poll(backend);
 | 
			
		||||
	if (!(backend->compositor) || (!(backend->shell))) {
 | 
			
		||||
	if (!backend->compositor || !backend->shell) {
 | 
			
		||||
		wlr_log_errno(L_ERROR, "Could not obtain retrieve required globals");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -49,8 +54,7 @@ static bool wlr_wl_backend_start(struct wlr_backend *_backend) {
 | 
			
		|||
 | 
			
		||||
	struct wl_event_loop *loop = wl_display_get_event_loop(backend->local_display);
 | 
			
		||||
	int fd = wl_display_get_fd(backend->remote_display);
 | 
			
		||||
	int events = WL_EVENT_READABLE | WL_EVENT_ERROR |
 | 
			
		||||
		WL_EVENT_HANGUP;
 | 
			
		||||
	int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
 | 
			
		||||
	backend->remote_display_src = wl_event_loop_add_fd(loop, fd, events,
 | 
			
		||||
		dispatch_events, backend);
 | 
			
		||||
	wl_event_source_check(backend->remote_display_src);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,9 +155,14 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e
 | 
			
		|||
 | 
			
		||||
static int x11_event(int fd, uint32_t mask, void *data) {
 | 
			
		||||
	struct wlr_x11_backend *x11 = data;
 | 
			
		||||
 | 
			
		||||
	if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
 | 
			
		||||
		wl_display_terminate(x11->wl_display);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xcb_generic_event_t *e;
 | 
			
		||||
	bool quit = false;
 | 
			
		||||
 | 
			
		||||
	while (!quit && (e = xcb_poll_for_event(x11->xcb_conn))) {
 | 
			
		||||
		quit = handle_x11_event(x11, e);
 | 
			
		||||
		free(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +210,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
 | 
			
		|||
 | 
			
		||||
	int fd = xcb_get_file_descriptor(x11->xcb_conn);
 | 
			
		||||
	struct wl_event_loop *ev = wl_display_get_event_loop(display);
 | 
			
		||||
	x11->event_source = wl_event_loop_add_fd(ev, fd, WL_EVENT_READABLE, x11_event, x11);
 | 
			
		||||
	int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
 | 
			
		||||
	x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11);
 | 
			
		||||
	if (!x11->event_source) {
 | 
			
		||||
		wlr_log(L_ERROR, "Could not create event source");
 | 
			
		||||
		goto error_x11;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,8 @@ struct roots_keyboard {
 | 
			
		|||
	struct wl_listener keyboard_key;
 | 
			
		||||
	struct wl_listener keyboard_modifiers;
 | 
			
		||||
 | 
			
		||||
	xkb_keysym_t pressed_keysyms[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
 | 
			
		||||
	xkb_keysym_t pressed_keysyms_translated[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
 | 
			
		||||
	xkb_keysym_t pressed_keysyms_raw[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct roots_keyboard *roots_keyboard_create(struct wlr_input_device *device,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -405,7 +405,7 @@ void roots_config_destroy(struct roots_config *config) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	struct roots_keyboard_config *kc, *ktmp = NULL;
 | 
			
		||||
	wl_list_for_each_safe(kc, ktmp, &config->bindings, link) {
 | 
			
		||||
	wl_list_for_each_safe(kc, ktmp, &config->keyboards, link) {
 | 
			
		||||
		free(kc->name);
 | 
			
		||||
		free(kc->rules);
 | 
			
		||||
		free(kc->model);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,9 @@ struct roots_cursor *roots_cursor_create(struct roots_seat *seat) {
 | 
			
		|||
	}
 | 
			
		||||
	cursor->cursor = wlr_cursor_create();
 | 
			
		||||
	if (!cursor->cursor) {
 | 
			
		||||
		free(cursor);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,16 +13,76 @@
 | 
			
		|||
#include "rootston/seat.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) {
 | 
			
		||||
	for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; i++) {
 | 
			
		||||
		if (keyboard->pressed_keysyms[i] == keysym) {
 | 
			
		||||
	for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) {
 | 
			
		||||
		if (pressed_keysyms[i] == keysym) {
 | 
			
		||||
			return i;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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 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
 | 
			
		||||
 * 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) {
 | 
			
		||||
	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 &&
 | 
			
		||||
			keysym <= XKB_KEY_XF86Switch_VT_12) {
 | 
			
		||||
		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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 roots_binding_config *bc;
 | 
			
		||||
	wl_list_for_each(bc, bindings, link) {
 | 
			
		||||
		if (modifiers ^ bc->modifiers) {
 | 
			
		||||
		if (modifiers ^ bc->modifiers || n != bc->keysyms_len) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool ok = true;
 | 
			
		||||
		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) {
 | 
			
		||||
				ok = false;
 | 
			
		||||
				break;
 | 
			
		||||
| 
						 | 
				
			
			@ -116,85 +189,75 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
 | 
			
		|||
	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
 | 
			
		||||
 * the consumed modifiers from the list of modifiers passed to keybind
 | 
			
		||||
 * 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,
 | 
			
		||||
		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(
 | 
			
		||||
static size_t keyboard_keysyms_translated(struct roots_keyboard *keyboard,
 | 
			
		||||
		xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
 | 
			
		||||
		uint32_t *modifiers) {
 | 
			
		||||
	*modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
 | 
			
		||||
	xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2(
 | 
			
		||||
		keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB);
 | 
			
		||||
	*modifiers = *modifiers & ~consumed;
 | 
			
		||||
 | 
			
		||||
	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]);
 | 
			
		||||
			handled = handled || keysym_handled;
 | 
			
		||||
		} else { // WLR_KEY_RELEASED
 | 
			
		||||
			keyboard_keysym_release(keyboard, syms[i]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return handled;
 | 
			
		||||
	return xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
 | 
			
		||||
		keycode, keysyms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
 * 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,
 | 
			
		||||
		uint32_t keycode, enum wlr_key_state state) {
 | 
			
		||||
	const xkb_keysym_t *syms;
 | 
			
		||||
static size_t keyboard_keysyms_raw(struct roots_keyboard *keyboard,
 | 
			
		||||
		xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
 | 
			
		||||
		uint32_t *modifiers) {
 | 
			
		||||
	*modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
 | 
			
		||||
 | 
			
		||||
	xkb_layout_index_t layout_index = xkb_state_key_get_layout(
 | 
			
		||||
		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;
 | 
			
		||||
	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;
 | 
			
		||||
	return xkb_keymap_key_get_syms_by_level(keyboard->device->keyboard->keymap,
 | 
			
		||||
		keycode, layout_index, 0, keysyms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void roots_keyboard_handle_key(struct roots_keyboard *keyboard,
 | 
			
		||||
		struct wlr_event_keyboard_key *event) {
 | 
			
		||||
	uint32_t keycode = event->keycode + 8;
 | 
			
		||||
	xkb_keycode_t keycode = event->keycode + 8;
 | 
			
		||||
 | 
			
		||||
	bool handled = keyboard_keysyms_xkb(keyboard, keycode, event->state);
 | 
			
		||||
	bool handled = false;
 | 
			
		||||
	uint32_t modifiers;
 | 
			
		||||
	const xkb_keysym_t *keysyms;
 | 
			
		||||
	size_t keysyms_len;
 | 
			
		||||
 | 
			
		||||
	if (!handled) {
 | 
			
		||||
		bool key_handled = keyboard_keysyms_simple(keyboard, keycode,
 | 
			
		||||
	// Handle translated keysyms
 | 
			
		||||
 | 
			
		||||
	keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms,
 | 
			
		||||
		&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);
 | 
			
		||||
		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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,6 @@ meta-key = Logo
 | 
			
		|||
# - "close" to close the current view
 | 
			
		||||
# - "next_window" to cycle through windows
 | 
			
		||||
[bindings]
 | 
			
		||||
Logo+Shift+E = exit
 | 
			
		||||
Logo+Shift+e = exit
 | 
			
		||||
Logo+q = close
 | 
			
		||||
Alt+Tab = next_window
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,7 +274,6 @@ struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
 | 
			
		|||
	seat->seat = wlr_seat_create(input->server->wl_display, name);
 | 
			
		||||
	if (!seat->seat) {
 | 
			
		||||
		free(seat);
 | 
			
		||||
		roots_cursor_destroy(seat->cursor);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -713,7 +713,10 @@ static void data_device_start_drag(struct wl_client *client,
 | 
			
		|||
 | 
			
		||||
	if (!seat_client_start_drag(seat_client, source, icon, origin, serial)) {
 | 
			
		||||
		wl_resource_post_no_memory(device_resource);
 | 
			
		||||
	} else {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (source) {
 | 
			
		||||
		source->seat_client = seat_client;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,7 +105,10 @@ void wlr_keyboard_init(struct wlr_keyboard *kb,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
 | 
			
		||||
	if (kb && kb->impl && kb->impl->destroy) {
 | 
			
		||||
	if (kb == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (kb->impl && kb->impl->destroy) {
 | 
			
		||||
		kb->impl->destroy(kb);
 | 
			
		||||
	} else {
 | 
			
		||||
		wl_list_remove(&kb->events.key.listener_list);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,8 +29,7 @@ static void wl_output_send_to_resource(struct wl_resource *resource) {
 | 
			
		|||
	if (version >= WL_OUTPUT_MODE_SINCE_VERSION) {
 | 
			
		||||
		struct wlr_output_mode *mode;
 | 
			
		||||
		wl_list_for_each(mode, &output->modes, link) {
 | 
			
		||||
			// TODO: mode->flags should just be preferred
 | 
			
		||||
			uint32_t flags = mode->flags;
 | 
			
		||||
			uint32_t flags = mode->flags & WL_OUTPUT_MODE_PREFERRED;
 | 
			
		||||
			if (output->current_mode == mode) {
 | 
			
		||||
				flags |= WL_OUTPUT_MODE_CURRENT;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -62,13 +61,17 @@ static void wlr_output_send_current_mode_to_resource(
 | 
			
		|||
	}
 | 
			
		||||
	if (output->current_mode != NULL) {
 | 
			
		||||
		struct wlr_output_mode *mode = output->current_mode;
 | 
			
		||||
		wl_output_send_mode(resource, mode->flags | WL_OUTPUT_MODE_CURRENT,
 | 
			
		||||
		uint32_t flags = mode->flags & WL_OUTPUT_MODE_PREFERRED;
 | 
			
		||||
		wl_output_send_mode(resource, flags | WL_OUTPUT_MODE_CURRENT,
 | 
			
		||||
			mode->width, mode->height, mode->refresh);
 | 
			
		||||
	} else {
 | 
			
		||||
		// Output has no mode, send the current width/height
 | 
			
		||||
		wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT, output->width,
 | 
			
		||||
			output->height, 0);
 | 
			
		||||
	}
 | 
			
		||||
	if (version >= WL_OUTPUT_DONE_SINCE_VERSION) {
 | 
			
		||||
		wl_output_send_done(resource);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void wl_output_destroy(struct wl_resource *resource) {
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +166,9 @@ bool wlr_output_set_mode(struct wlr_output *output,
 | 
			
		|||
 | 
			
		||||
void wlr_output_update_size(struct wlr_output *output, int32_t width,
 | 
			
		||||
		int32_t height) {
 | 
			
		||||
	if (output->width == width && output->height == height) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	output->width = width;
 | 
			
		||||
	output->height = height;
 | 
			
		||||
	wlr_output_update_matrix(output);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,6 +85,7 @@ static void screenshooter_shoot(struct wl_client *client,
 | 
			
		|||
	struct wlr_screenshot *screenshot =
 | 
			
		||||
		calloc(1, sizeof(struct wlr_screenshot));
 | 
			
		||||
	if (!screenshot) {
 | 
			
		||||
		free(pixels);
 | 
			
		||||
		wl_resource_post_no_memory(screenshooter_resource);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +97,7 @@ static void screenshooter_shoot(struct wl_client *client,
 | 
			
		|||
		wl_resource_get_version(screenshooter_resource), id);
 | 
			
		||||
	if (screenshot->resource == NULL) {
 | 
			
		||||
		free(screenshot);
 | 
			
		||||
		free(pixels);
 | 
			
		||||
		wl_resource_post_no_memory(screenshooter_resource);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +111,7 @@ static void screenshooter_shoot(struct wl_client *client,
 | 
			
		|||
	if (!state) {
 | 
			
		||||
		wl_resource_destroy(screenshot->resource);
 | 
			
		||||
		free(screenshot);
 | 
			
		||||
		free(pixels);
 | 
			
		||||
		wl_resource_post_no_memory(screenshooter_resource);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -347,7 +347,7 @@ static void shell_surface_protocol_set_popup(struct wl_client *client,
 | 
			
		|||
	transient_state->flags = flags;
 | 
			
		||||
 | 
			
		||||
	struct wlr_wl_shell_surface_popup_state *popup_state =
 | 
			
		||||
		calloc(1, sizeof(struct wlr_wl_shell_surface_transient_state));
 | 
			
		||||
		calloc(1, sizeof(struct wlr_wl_shell_surface_popup_state));
 | 
			
		||||
	if (popup_state == NULL) {
 | 
			
		||||
		free(transient_state);
 | 
			
		||||
		wl_client_post_no_memory(client);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue