diff options
Diffstat (limited to 'rootston')
-rw-r--r-- | rootston/config.c | 16 | ||||
-rw-r--r-- | rootston/cursor.c | 7 | ||||
-rw-r--r-- | rootston/keyboard.c | 47 | ||||
-rw-r--r-- | rootston/output.c | 23 | ||||
-rw-r--r-- | rootston/xdg_shell_v6.c | 15 | ||||
-rw-r--r-- | rootston/xwayland.c | 18 |
6 files changed, 120 insertions, 6 deletions
diff --git a/rootston/config.c b/rootston/config.c index 6f81170b..b3fd4f01 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -1,6 +1,7 @@ #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L #endif +#include <assert.h> #include <stdlib.h> #include <limits.h> #include <getopt.h> @@ -244,6 +245,21 @@ static int config_ini_handler(void *user, const char *section, const char *name, } else { wlr_log(L_ERROR, "got unknown transform value: %s", value); } + } else if (strcmp(name, "mode") == 0) { + char *end; + oc->mode.width = strtol(value, &end, 10); + assert(*end == 'x'); + ++end; + oc->mode.height = strtol(end, &end, 10); + if (*end) { + assert(*end == '@'); + ++end; + oc->mode.refresh_rate = strtof(end, &end); + assert(strcmp("Hz", end) == 0); + } + wlr_log(L_DEBUG, "Configured output %s with mode %dx%d@%f", + oc->name, oc->mode.width, oc->mode.height, + oc->mode.refresh_rate); } } else if (strcmp(section, "cursor") == 0) { if (strcmp(name, "map-to-output") == 0) { diff --git a/rootston/cursor.c b/rootston/cursor.c index 2cf90539..917e876c 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -160,6 +160,13 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { width += dx; } + if (width < 0) { + width = 0; + } + if (height < 0) { + height = 0; + } + // TODO we might need one configure event for this if (active_x != input->active_view->x || active_y != input->active_view->y) { diff --git a/rootston/keyboard.c b/rootston/keyboard.c index ed0ca135..f513f753 100644 --- a/rootston/keyboard.c +++ b/rootston/keyboard.c @@ -53,7 +53,13 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard, } } -static void keyboard_keysym_press(struct roots_keyboard *keyboard, +/** + * Process a keypress from the keyboard. + * + * 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, xkb_keysym_t keysym) { ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym); if (i < 0) { @@ -74,7 +80,7 @@ static void keyboard_keysym_press(struct roots_keyboard *keyboard, wlr_session_change_vt(session, vt); } } - return; + return true; } uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); @@ -96,8 +102,11 @@ static void keyboard_keysym_press(struct roots_keyboard *keyboard, if (ok) { keyboard_binding_execute(keyboard, bc->command); + return true; } } + + return false; } static void keyboard_keysym_release(struct roots_keyboard *keyboard, @@ -116,13 +125,36 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { const xkb_keysym_t *syms; int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, keycode, &syms); + + bool handled = false; for (int i = 0; i < syms_len; i++) { if (event->state == WLR_KEY_PRESSED) { - keyboard_keysym_press(keyboard, syms[i]); + bool keysym_handled = keyboard_keysym_press(keyboard, syms[i]); + handled = handled || keysym_handled; } else { // WLR_KEY_RELEASED keyboard_keysym_release(keyboard, syms[i]); } } + + if (!handled) { + wlr_seat_set_keyboard(keyboard->input->wl_seat, keyboard->device); + wlr_seat_keyboard_notify_key(keyboard->input->wl_seat, + (uint32_t)(event->time_usec / 1000), event->keycode, event->state); + } +} + +static void keyboard_modifiers_notify(struct wl_listener *listener, void *data) { + struct roots_keyboard *r_keyboard = + wl_container_of(listener, r_keyboard, modifiers); + struct wlr_seat *seat = r_keyboard->input->wl_seat; + struct wlr_keyboard *keyboard = r_keyboard->device->keyboard; + wlr_seat_set_keyboard(seat, r_keyboard->device); + wlr_seat_keyboard_notify_modifiers(seat, + keyboard->modifiers.depressed, + keyboard->modifiers.latched, + keyboard->modifiers.locked, + keyboard->modifiers.group); + } static void keyboard_config_merge(struct keyboard_config *config, @@ -155,8 +187,13 @@ void keyboard_add(struct wlr_input_device *device, struct roots_input *input) { device->data = keyboard; keyboard->device = device; keyboard->input = input; + keyboard->key.notify = keyboard_key_notify; wl_signal_add(&device->keyboard->events.key, &keyboard->key); + + keyboard->modifiers.notify = keyboard_modifiers_notify; + wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifiers); + wl_list_insert(&input->keyboards, &keyboard->link); struct keyboard_config config; @@ -188,14 +225,12 @@ void keyboard_add(struct wlr_input_device *device, struct roots_input *input) { wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS)); xkb_context_unref(context); - - wlr_seat_attach_keyboard(input->wl_seat, device); } void keyboard_remove(struct wlr_input_device *device, struct roots_input *input) { struct roots_keyboard *keyboard = device->data; - wlr_seat_detach_keyboard(input->wl_seat, device->keyboard); wl_list_remove(&keyboard->key.link); + wl_list_remove(&keyboard->modifiers.link); wl_list_remove(&keyboard->link); free(keyboard); } diff --git a/rootston/output.c b/rootston/output.c index 5fcd02a2..6bc28996 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -165,6 +165,26 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { output->last_frame = desktop->last_frame = now; } +static void set_mode(struct wlr_output *output, struct output_config *oc) { + struct wlr_output_mode *mode, *best = NULL; + int mhz = (int)(oc->mode.refresh_rate * 1000); + wl_list_for_each(mode, &output->modes, link) { + if (mode->width == oc->mode.width && mode->height == oc->mode.height) { + if (mode->refresh == mhz) { + best = mode; + break; + } + best = mode; + } + } + if (!best) { + wlr_log(L_ERROR, "Configured mode for %s not available", output->name); + } else { + wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); + wlr_output_set_mode(output, best); + } +} + void output_add_notify(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; struct roots_desktop *desktop = wl_container_of(listener, desktop, output_add); @@ -191,6 +211,9 @@ void output_add_notify(struct wl_listener *listener, void *data) { struct output_config *output_config = config_get_output(config, wlr_output); if (output_config) { + if (output_config->mode.width) { + set_mode(wlr_output, output_config); + } wlr_output_transform(wlr_output, output_config->transform); wlr_output_layout_add(desktop->layout, wlr_output, output_config->x, output_config->y); diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 85871144..4f284851 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -29,6 +29,21 @@ static void resize(struct roots_view *view, uint32_t width, uint32_t height) { assert(view->type == ROOTS_XDG_SHELL_V6_VIEW); struct wlr_xdg_surface_v6 *surf = view->xdg_surface_v6; if (surf->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { + struct wlr_xdg_toplevel_v6_state *state = + &surf->toplevel_state->current; + if (width < state->min_width) { + width = state->min_width; + } else if (state->max_width > 0 && + width < state->max_width) { + width = state->max_width; + } + if (height < state->min_height) { + height = state->min_height; + } else if (state->max_height > 0 && + height < state->max_height) { + height = state->max_height; + } + wlr_xdg_toplevel_v6_set_size(surf, width, height); } } diff --git a/rootston/xwayland.c b/rootston/xwayland.c index 3d066093..2d7fe946 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -18,6 +18,24 @@ static void activate(struct roots_view *view, bool active) { static void resize(struct roots_view *view, uint32_t width, uint32_t height) { assert(view->type == ROOTS_XWAYLAND_VIEW); struct wlr_xwayland_surface *xwayland_surface = view->xwayland_surface; + + struct wlr_xwayland_surface_size_hints *size_hints = + xwayland_surface->size_hints; + if (size_hints != NULL) { + if (width < (uint32_t)size_hints->min_width) { + width = size_hints->min_width; + } else if (size_hints->max_width > 0 && + width > (uint32_t)size_hints->max_width) { + width = size_hints->max_width; + } + if (height < (uint32_t)size_hints->min_height) { + height = size_hints->min_height; + } else if (size_hints->max_height > 0 && + height > (uint32_t)size_hints->max_height) { + height = size_hints->max_height; + } + } + wlr_xwayland_surface_configure(view->desktop->xwayland, xwayland_surface, xwayland_surface->x, xwayland_surface->y, width, height); } |