aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/config.c16
-rw-r--r--rootston/cursor.c7
-rw-r--r--rootston/keyboard.c47
-rw-r--r--rootston/output.c23
-rw-r--r--rootston/xdg_shell_v6.c15
-rw-r--r--rootston/xwayland.c18
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);
}