diff options
Diffstat (limited to 'rootston')
-rw-r--r-- | rootston/config.c | 50 | ||||
-rw-r--r-- | rootston/cursor.c | 100 | ||||
-rw-r--r-- | rootston/desktop.c | 22 | ||||
-rw-r--r-- | rootston/input.c | 5 | ||||
-rw-r--r-- | rootston/main.c | 1 | ||||
-rw-r--r-- | rootston/output.c | 47 | ||||
-rw-r--r-- | rootston/rootston.ini.example | 5 |
7 files changed, 177 insertions, 53 deletions
diff --git a/rootston/config.c b/rootston/config.c index 3a21aff3..d454c2d9 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -86,6 +86,28 @@ invalid_input: return NULL; } +static uint32_t parse_modifier(const char *symname) { + if (strcmp(symname, "Shift") == 0) { + return WLR_MODIFIER_SHIFT; + } else if (strcmp(symname, "Caps") == 0) { + return WLR_MODIFIER_CAPS; + } else if (strcmp(symname, "Ctrl") == 0) { + return WLR_MODIFIER_CTRL; + } else if (strcmp(symname, "Alt") == 0) { + return WLR_MODIFIER_ALT; + } else if (strcmp(symname, "Mod2") == 0) { + return WLR_MODIFIER_MOD2; + } else if (strcmp(symname, "Mod3") == 0) { + return WLR_MODIFIER_MOD3; + } else if (strcmp(symname, "Logo") == 0) { + return WLR_MODIFIER_LOGO; + } else if (strcmp(symname, "Mod5") == 0) { + return WLR_MODIFIER_MOD5; + } else { + return 0; + } +} + static const char *output_prefix = "output:"; static const char *device_prefix = "device:"; @@ -171,6 +193,15 @@ static int config_ini_handler(void *user, const char *section, const char *name, } else { wlr_log(L_ERROR, "got unknown device config: %s", name); } + } else if (strcmp(section, "keyboard") == 0) { + if (strcmp(name, "meta-key") == 0) { + config->keyboard.meta_key = parse_modifier(value); + if (config->keyboard.meta_key == 0) { + wlr_log(L_ERROR, "got unknown meta key: %s", name); + } + } else { + wlr_log(L_ERROR, "got unknown keyboard config: %s", name); + } } else if (strcmp(section, "bindings") == 0) { struct binding_config *bc = calloc(1, sizeof(struct binding_config)); wl_list_insert(&config->bindings, &bc->link); @@ -190,22 +221,9 @@ static int config_ini_handler(void *user, const char *section, const char *name, bc->keysyms = calloc(1, keysyms_len * sizeof(xkb_keysym_t)); char *symname = symnames; for (size_t i = 0; i < keysyms_len; i++) { - if (strcmp(symname, "Shift") == 0) { - bc->modifiers |= WLR_MODIFIER_SHIFT; - } else if (strcmp(symname, "Caps") == 0) { - bc->modifiers |= WLR_MODIFIER_CAPS; - } else if (strcmp(symname, "Ctrl") == 0) { - bc->modifiers |= WLR_MODIFIER_CTRL; - } else if (strcmp(symname, "Alt") == 0) { - bc->modifiers |= WLR_MODIFIER_ALT; - } else if (strcmp(symname, "Mod2") == 0) { - bc->modifiers |= WLR_MODIFIER_MOD2; - } else if (strcmp(symname, "Mod3") == 0) { - bc->modifiers |= WLR_MODIFIER_MOD3; - } else if (strcmp(symname, "Logo") == 0) { - bc->modifiers |= WLR_MODIFIER_LOGO; - } else if (strcmp(symname, "Mod5") == 0) { - bc->modifiers |= WLR_MODIFIER_MOD5; + uint32_t modifier = parse_modifier(symname); + if (modifier != 0) { + bc->modifiers |= modifier; } else { xkb_keysym_t sym = xkb_keysym_from_name(symname, XKB_KEYSYM_NO_FLAGS); diff --git a/rootston/cursor.c b/rootston/cursor.c index 531d82cc..7ea1ed4d 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -1,5 +1,8 @@ +#define _XOPEN_SOURCE 500 +#include <stdbool.h> #include <stdint.h> #include <string.h> +#include <math.h> // TODO: BSD et al #include <linux/input-event-codes.h> #include <wayland-server.h> @@ -24,15 +27,16 @@ const struct roots_input_event *get_input_event(struct roots_input *input, void view_begin_move(struct roots_input *input, struct wlr_cursor *cursor, struct roots_view *view) { input->mode = ROOTS_CURSOR_MOVE; - input->offs_x = cursor->x - view->x; - input->offs_y = cursor->y - view->y; + input->offs_x = cursor->x; + input->offs_y = cursor->y; + input->view_x = view->x; + input->view_y = view->y; wlr_seat_pointer_clear_focus(input->wl_seat); } void view_begin_resize(struct roots_input *input, struct wlr_cursor *cursor, struct roots_view *view, uint32_t edges) { input->mode = ROOTS_CURSOR_RESIZE; - wlr_log(L_DEBUG, "begin resize"); input->offs_x = cursor->x; input->offs_y = cursor->y; input->view_x = view->x; @@ -45,6 +49,15 @@ void view_begin_resize(struct roots_input *input, struct wlr_cursor *cursor, wlr_seat_pointer_clear_focus(input->wl_seat); } +void view_begin_rotate(struct roots_input *input, struct wlr_cursor *cursor, + struct roots_view *view) { + input->mode = ROOTS_CURSOR_ROTATE; + input->offs_x = cursor->x; + input->offs_y = cursor->y; + input->view_rotation = view->rotation; + wlr_seat_pointer_clear_focus(input->wl_seat); +} + void cursor_update_position(struct roots_input *input, uint32_t time) { struct roots_desktop *desktop = input->server->desktop; struct roots_view *view; @@ -63,16 +76,18 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { break; case ROOTS_CURSOR_MOVE: if (input->active_view) { - input->active_view->x = input->cursor->x - input->offs_x; - input->active_view->y = input->cursor->y - input->offs_y; + int dx = input->cursor->x - input->offs_x, + dy = input->cursor->y - input->offs_y; + input->active_view->x = input->view_x + dx; + input->active_view->y = input->view_y + dy; } break; case ROOTS_CURSOR_RESIZE: if (input->active_view) { - int dx = input->cursor->x - input->offs_x; - int dy = input->cursor->y - input->offs_y; - int width = input->view_width; - int height = input->view_height; + int dx = input->cursor->x - input->offs_x, + dy = input->cursor->y - input->offs_y; + int width = input->view_width, + height = input->view_height; if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) { input->active_view->y = input->view_y + dy; height -= dy; @@ -91,6 +106,19 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { } break; case ROOTS_CURSOR_ROTATE: + if (input->active_view) { + struct roots_view *view = input->active_view; + int ox = view->x + view->wlr_surface->current->width/2, + oy = view->y + view->wlr_surface->current->height/2; + int ux = input->offs_x - ox, + uy = input->offs_y - oy; + int vx = input->cursor->x - ox, + vy = input->cursor->y - oy; + float angle = atan2(vx*uy - vy*ux, vx*ux + vy*uy); + int steps = 12; + angle = round(angle/M_PI*steps) / (steps/M_PI); + view->rotation = input->view_rotation + angle; + } break; } } @@ -100,6 +128,12 @@ static void set_view_focus(struct roots_input *input, if (input->active_view == view) { return; } + input->active_view = view; + input->mode = ROOTS_CURSOR_PASSTHROUGH; + if (!view) { + return; + } + size_t index = 0; for (size_t i = 0; i < desktop->views->length; ++i) { struct roots_view *_view = desktop->views->items[i]; @@ -108,8 +142,6 @@ static void set_view_focus(struct roots_input *input, index = i; } } - input->active_view = view; - input->mode = ROOTS_CURSOR_PASSTHROUGH; // TODO: list_swap list_del(desktop->views, index); list_add(desktop->views, view); @@ -141,6 +173,23 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { event->orientation, event->delta); } +static bool is_meta_pressed(struct roots_input *input) { + uint32_t meta_key = input->server->config->keyboard.meta_key; + if (meta_key == 0) { + return false; + } + + struct roots_keyboard *keyboard; + wl_list_for_each(keyboard, &input->keyboards, link) { + uint32_t modifiers = + wlr_keyboard_get_modifiers(keyboard->device->keyboard); + if ((modifiers ^ meta_key) == 0) { + return true; + } + } + return false; +} + static void do_cursor_button_press(struct roots_input *input, struct wlr_cursor *cursor, struct wlr_input_device *device, uint32_t time, uint32_t button, uint32_t state) { @@ -148,14 +197,33 @@ static void do_cursor_button_press(struct roots_input *input, struct wlr_surface *surface; double sx, sy; struct roots_view *view = view_at(desktop, - input->cursor->x, input->cursor->y, &surface, &sx, &sy); - uint32_t serial = wlr_seat_pointer_notify_button( - input->wl_seat, time, button, state); + input->cursor->x, input->cursor->y, &surface, &sx, &sy); + + if (state == WLR_BUTTON_PRESSED && view && is_meta_pressed(input)) { + set_view_focus(input, desktop, view); + + switch (button) { + case BTN_LEFT: + view_begin_move(input, cursor, view); + break; + case BTN_RIGHT: + view_begin_resize(input, cursor, view, + ROOTS_CURSOR_RESIZE_EDGE_RIGHT | + ROOTS_CURSOR_RESIZE_EDGE_BOTTOM); + break; + case BTN_MIDDLE: + view_begin_rotate(input, cursor, view); + } + return; + } + + uint32_t serial = wlr_seat_pointer_notify_button(input->wl_seat, time, button, + state); + int i; switch (state) { case WLR_BUTTON_RELEASED: - input->active_view = NULL; - input->mode = ROOTS_CURSOR_PASSTHROUGH; + set_view_focus(input, desktop, NULL); break; case WLR_BUTTON_PRESSED: i = input->input_events_idx; diff --git a/rootston/desktop.c b/rootston/desktop.c index 2c4611a8..d5a61f2a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -2,6 +2,7 @@ #include <assert.h> #include <time.h> #include <stdlib.h> +#include <math.h> #include <wlr/types/wlr_box.h> #include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_cursor.h> @@ -131,7 +132,21 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, double view_sx = lx - view->x; double view_sy = ly - view->y; + struct wlr_box box; + view_get_input_bounds(view, &box); + if (view->rotation != 0.0) { + // Coordinates relative to the center of the view + double ox = view_sx - (double)box.width/2, + oy = view_sy - (double)box.height/2; + // Rotated coordinates + double rx = cos(view->rotation)*ox - sin(view->rotation)*oy, + ry = cos(view->rotation)*oy + sin(view->rotation)*ox; + view_sx = rx + (double)box.width/2; + view_sy = ry + (double)box.height/2; + } + if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { + // TODO: test if this works with rotated views double popup_sx, popup_sy; struct wlr_xdg_surface_v6 *popup = xdg_v6_popup_at(view->xdg_surface_v6, view_sx, view_sy, @@ -148,7 +163,6 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, double sub_x, sub_y; struct wlr_subsurface *subsurface = subsurface_at(view->wlr_surface, view_sx, view_sy, &sub_x, &sub_y); - if (subsurface) { *sx = view_sx - sub_x; *sy = view_sy - sub_y; @@ -156,11 +170,7 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, return view; } - struct wlr_box box; - view_get_input_bounds(view, &box); - box.x += view->x; - box.y += view->y; - if (wlr_box_contains_point(&box, lx, ly)) { + if (wlr_box_contains_point(&box, view_sx, view_sy)) { *sx = view_sx; *sy = view_sy; *surface = view->wlr_surface; diff --git a/rootston/input.c b/rootston/input.c index 9700b840..86a87e24 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -79,9 +79,8 @@ struct roots_input *input_create(struct roots_server *server, input->config = config; input->server = server; - struct wlr_xcursor_theme *theme; - assert(theme = wlr_xcursor_theme_load("default", 16)); - assert(input->xcursor = wlr_xcursor_theme_get_cursor(theme, "left_ptr")); + assert(input->theme = wlr_xcursor_theme_load("default", 16)); + assert(input->xcursor = wlr_xcursor_theme_get_cursor(input->theme, "left_ptr")); assert(input->wl_seat = wlr_seat_create(server->wl_display, "seat0")); wlr_seat_set_capabilities(input->wl_seat, WL_SEAT_CAPABILITY_KEYBOARD diff --git a/rootston/main.c b/rootston/main.c index 65a06a2f..5a60000c 100644 --- a/rootston/main.c +++ b/rootston/main.c @@ -43,5 +43,6 @@ int main(int argc, char **argv) { setenv("WAYLAND_DISPLAY", socket, true); wl_display_run(server.wl_display); + wlr_backend_destroy(server.backend); return 0; } diff --git a/rootston/output.c b/rootston/output.c index 06786395..32923042 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -18,7 +18,7 @@ static inline int64_t timespec_to_msec(const struct timespec *a) { static void render_surface(struct wlr_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, - struct timespec *when, double lx, double ly) { + struct timespec *when, double lx, double ly, float rotation) { wlr_surface_flush_damage(surface); if (surface->texture->valid) { int width = surface->current->buffer_width; @@ -27,10 +27,19 @@ static void render_surface(struct wlr_surface *surface, wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); if (wlr_output_layout_intersects(desktop->layout, wlr_output, - lx, ly, lx + width, ly + height)) { + lx, ly, lx + width, ly + height)) { float matrix[16]; + + float translate_origin[16]; + wlr_matrix_translate(&translate_origin, + (int)ox + width / 2, (int)oy + height / 2, 0); + float rotate[16]; + wlr_matrix_rotate(&rotate, rotation); + float translate_center[16]; + wlr_matrix_translate(&translate_center, -width / 2, -height / 2, 0); float transform[16]; - wlr_matrix_translate(&transform, ox, oy, 0); + wlr_matrix_mul(&translate_origin, &rotate, &transform); + wlr_matrix_mul(&transform, &translate_center, &transform); wlr_surface_get_matrix(surface, &matrix, &wlr_output->transform_matrix, &transform); wlr_render_with_matrix(desktop->server->renderer, @@ -46,16 +55,33 @@ static void render_surface(struct wlr_surface *surface, struct wlr_subsurface *subsurface; wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { + double sx = subsurface->surface->current->subsurface_position.x, + sy = subsurface->surface->current->subsurface_position.y; + double sw = subsurface->surface->current->buffer_width, + sh = subsurface->surface->current->buffer_height; + if (rotation != 0.0) { + // Coordinates relative to the center of the subsurface + double ox = sx - (double)width/2 + sw/2, + oy = sy - (double)height/2 + sh/2; + // Rotated coordinates + double rx = cos(-rotation)*ox - sin(-rotation)*oy, + ry = cos(-rotation)*oy + sin(-rotation)*ox; + sx = rx + (double)width/2 - sw/2; + sy = ry + (double)height/2 - sh/2; + } + render_surface(subsurface->surface, desktop, wlr_output, when, - lx + subsurface->surface->current->subsurface_position.x, - ly + subsurface->surface->current->subsurface_position.y); + lx + sx, + ly + sy, + rotation); } } } static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, - struct timespec *when, double base_x, double base_y) { + struct timespec *when, double base_x, double base_y, float rotation) { + // TODO: make sure this works with view rotation struct wlr_xdg_surface_v6 *popup; wl_list_for_each(popup, &surface->popups, popup_link) { if (!popup->configured) { @@ -67,18 +93,18 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, double popup_y = base_y + surface->geometry->y + popup->popup_state->geometry.y - popup->geometry->y; render_surface(popup->surface, desktop, wlr_output, when, popup_x, - popup_y); - render_xdg_v6_popups(popup, desktop, wlr_output, when, popup_x, popup_y); + popup_y, rotation); + render_xdg_v6_popups(popup, desktop, wlr_output, when, popup_x, popup_y, rotation); } } static void render_view(struct roots_view *view, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when) { render_surface(view->wlr_surface, desktop, wlr_output, when, - view->x, view->y); + view->x, view->y, view->rotation); if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { render_xdg_v6_popups(view->xdg_surface_v6, desktop, wlr_output, - when, view->x, view->y); + when, view->x, view->y, view->rotation); } } @@ -170,6 +196,5 @@ void output_remove_notify(struct wl_listener *listener, void *data) { // sample->compositor); wl_list_remove(&output->link); wl_list_remove(&output->frame.link); - wl_list_remove(&output->resolution.link); free(output); } diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example index 8dd51ea2..9960cae1 100644 --- a/rootston/rootston.ini.example +++ b/rootston/rootston.ini.example @@ -25,8 +25,11 @@ map-to-output = VGA-1 # Restrict cursor movements for this mouse to concrete rectangle geometry = 2500x800 +[keyboard] +meta-key = Logo + # Keybindings # Maps key combinations with commands to execute # The special command "exit" stops the compositor [bindings] -Logo+q=exit +Logo+q = exit |