diff --git a/include/rootston/seat.h b/include/rootston/seat.h index b5593651..bef515a4 100644 --- a/include/rootston/seat.h +++ b/include/rootston/seat.h @@ -1,8 +1,6 @@ #ifndef _ROOTSTON_SEAT_H #define _ROOTSTON_SEAT_H - #include - #include "rootston/input.h" #include "rootston/keyboard.h" diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index 09d3e282..a5f00402 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -1,6 +1,6 @@ #ifndef WLR_TYPES_WLR_SEAT_H #define WLR_TYPES_WLR_SEAT_H - +#include #include #include #include @@ -109,6 +109,7 @@ struct wlr_seat { struct wl_list clients; char *name; uint32_t capabilities; + struct timespec last_event; struct wlr_data_device *data_device; // TODO needed? struct wlr_data_source *selection_source; diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index bea97394..6518b703 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -29,6 +29,7 @@ struct wlr_xwayland { struct wlr_xwayland_cursor *cursor; struct { + struct wl_signal ready; struct wl_signal new_surface; } events; diff --git a/rootston/desktop.c b/rootston/desktop.c index 51bb0e2a..1695d007 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -167,9 +167,22 @@ bool view_center(struct roots_view *view) { view_get_box(view, &box); struct roots_desktop *desktop = view->desktop; + struct roots_input *input = desktop->server->input; + struct roots_seat *seat = NULL, *_seat; + wl_list_for_each(_seat, &input->seats, link) { + if (!seat || (seat->seat->last_event.tv_sec > _seat->seat->last_event.tv_sec && + seat->seat->last_event.tv_nsec > _seat->seat->last_event.tv_nsec)) { + seat = _seat; + } + } + if (!seat) { + return false; + } struct wlr_output *output = - wlr_output_layout_get_center_output(desktop->layout); + wlr_output_layout_output_at(desktop->layout, + seat->cursor->cursor->x, + seat->cursor->cursor->y); if (!output) { // empty layout return false; @@ -218,7 +231,7 @@ void view_teardown(struct roots_view *view) { struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - for (int i = desktop->views->length - 1; i >= 0; --i) { + for (ssize_t i = desktop->views->length - 1; i >= 0; --i) { struct roots_view *view = desktop->views->items[i]; if (view->type == ROOTS_WL_SHELL_VIEW && @@ -230,11 +243,12 @@ 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_surface_state *state = view->wlr_surface->current; struct wlr_box box = { .x = 0, .y = 0, - .width = view->wlr_surface->current->buffer_width, - .height = view->wlr_surface->current->buffer_height, + .width = state->buffer_width / state->scale, + .height = state->buffer_height / state->scale, }; if (view->rotation != 0.0) { // Coordinates relative to the center of the view @@ -248,7 +262,6 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, } 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 = wlr_xdg_surface_v6_popup_at(view->xdg_surface_v6, @@ -263,7 +276,6 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, } if (view->type == ROOTS_WL_SHELL_VIEW) { - // TODO: test if this works with rotated views double popup_sx, popup_sy; struct wlr_wl_shell_surface *popup = wlr_wl_shell_surface_popup_at(view->wl_shell_surface, diff --git a/rootston/main.c b/rootston/main.c index d55bc682..365ff6e0 100644 --- a/rootston/main.c +++ b/rootston/main.c @@ -12,6 +12,18 @@ struct roots_server server = { 0 }; +static void ready(struct wl_listener *listener, void *data) { + if (server.config->startup_cmd != NULL) { + const char *cmd = server.config->startup_cmd; + pid_t pid = fork(); + if (pid < 0) { + wlr_log(L_ERROR, "cannot execute binding command: fork() failed"); + } else if (pid == 0) { + execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); + } + } +} + int main(int argc, char **argv) { assert(server.config = roots_config_create_from_args(argc, argv)); assert(server.wl_display = wl_display_create()); @@ -43,17 +55,12 @@ int main(int argc, char **argv) { } setenv("WAYLAND_DISPLAY", socket, true); - - if (server.config->startup_cmd != NULL) { - const char *cmd = server.config->startup_cmd; - pid_t pid = fork(); - if (pid < 0) { - wlr_log(L_ERROR, "cannot execute binding command: fork() failed"); - return 1; - } else if (pid == 0) { - execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); - } - } +#ifndef HAS_XWAYLAND + ready(NULL, NULL); +#else + struct wl_listener xwayland_ready = { .notify = ready }; + wl_signal_add(&server.desktop->xwayland->events.ready, &xwayland_ready); +#endif wl_display_run(server.wl_display); wlr_backend_destroy(server.backend); diff --git a/rootston/output.c b/rootston/output.c index 3ed5a02c..145016b3 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -21,30 +21,33 @@ static void render_surface(struct wlr_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { if (surface->texture->valid) { - float scale_factor = (float)wlr_output->scale / surface->current->scale; - int width = surface->current->buffer_width * scale_factor; - int height = surface->current->buffer_height * scale_factor; + double surface_scale = surface->current->scale; + double width = (double)surface->current->buffer_width / surface_scale; + double height = (double)surface->current->buffer_height / surface_scale; + int render_width = width * wlr_output->scale; + int render_height = height * wlr_output->scale; double ox = lx, oy = ly; wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); ox *= wlr_output->scale; oy *= wlr_output->scale; if (wlr_output_layout_intersects(desktop->layout, wlr_output, - lx, ly, lx + width, ly + height)) { + lx, ly, lx + render_width, ly + render_height)) { float matrix[16]; float translate_origin[16]; wlr_matrix_translate(&translate_origin, - (int)ox + width / 2, (int)oy + height / 2, 0); + (int)ox + render_width / 2, (int)oy + render_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); + wlr_matrix_translate(&translate_center, -render_width / 2, + -render_height / 2, 0); float scale[16]; - wlr_matrix_scale(&scale, width, height, 1); + wlr_matrix_scale(&scale, render_width, render_height, 1); float transform[16]; wlr_matrix_mul(&translate_origin, &rotate, &transform); @@ -52,12 +55,12 @@ static void render_surface(struct wlr_surface *surface, wlr_matrix_mul(&transform, &scale, &transform); wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); - wlr_render_with_matrix(desktop->server->renderer, - surface->texture, &matrix); + wlr_render_with_matrix(desktop->server->renderer, surface->texture, + &matrix); struct wlr_frame_callback *cb, *cnext; wl_list_for_each_safe(cb, cnext, - &surface->current->frame_callback_list, link) { + &surface->current->frame_callback_list, link) { wl_callback_send_done(cb->resource, timespec_to_msec(when)); wl_resource_destroy(cb->resource); } @@ -65,19 +68,20 @@ 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; + struct wlr_surface_state *state = subsurface->surface->current; + double sx = state->subsurface_position.x; + double sy = state->subsurface_position.y; + double sw = state->buffer_width / state->scale; + double sh = state->buffer_height / state->scale; 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; + double ox = sx - width/2 + sw/2, + oy = sy - 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; + sx = rx + width/2 - sw/2; + sy = ry + height/2 - sh/2; } render_surface(subsurface->surface, desktop, wlr_output, when, @@ -104,7 +108,8 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, popup->popup_state->geometry.y - popup->geometry->y; render_surface(popup->surface, desktop, wlr_output, when, popup_x, popup_y, rotation); - render_xdg_v6_popups(popup, desktop, wlr_output, when, popup_x, popup_y, rotation); + render_xdg_v6_popups(popup, desktop, wlr_output, when, popup_x, popup_y, + rotation); } } diff --git a/rootston/seat.c b/rootston/seat.c index 3ec6f1b7..6d8dc749 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -1,11 +1,9 @@ -#include +#include #include #include -#include - +#include #include #include - #include "rootston/xcursor.h" #include "rootston/input.h" #include "rootston/seat.h" @@ -298,6 +296,8 @@ static void seat_add_keyboard(struct roots_seat *seat, struct wlr_input_device * keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; wl_signal_add(&keyboard->device->keyboard->events.modifiers, &keyboard->keyboard_modifiers); + + wlr_seat_set_keyboard(seat->seat, device); } static void seat_add_pointer(struct roots_seat *seat, struct wlr_input_device *device) { diff --git a/types/wlr_seat.c b/types/wlr_seat.c index 9de1b3a0..dad88354 100644 --- a/types/wlr_seat.c +++ b/types/wlr_seat.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -574,12 +575,14 @@ void wlr_seat_pointer_notify_enter(struct wlr_seat *wlr_seat, void wlr_seat_pointer_notify_motion(struct wlr_seat *wlr_seat, uint32_t time, double sx, double sy) { + clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event); struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab; grab->interface->motion(grab, time, sx, sy); } uint32_t wlr_seat_pointer_notify_button(struct wlr_seat *wlr_seat, uint32_t time, uint32_t button, uint32_t state) { + clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event); if (state == WL_POINTER_BUTTON_STATE_PRESSED) { if (wlr_seat->pointer_state.button_count == 0) { wlr_seat->pointer_state.grab_button = button; @@ -602,6 +605,7 @@ uint32_t wlr_seat_pointer_notify_button(struct wlr_seat *wlr_seat, void wlr_seat_pointer_notify_axis(struct wlr_seat *wlr_seat, uint32_t time, enum wlr_axis_orientation orientation, double value) { + clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event); struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab; grab->interface->axis(grab, time, orientation, value); } @@ -804,12 +808,14 @@ void wlr_seat_keyboard_clear_focus(struct wlr_seat *seat) { } void wlr_seat_keyboard_notify_modifiers(struct wlr_seat *seat) { + clock_gettime(CLOCK_MONOTONIC, &seat->last_event); struct wlr_seat_keyboard_grab *grab = seat->keyboard_state.grab; grab->interface->modifiers(grab); } void wlr_seat_keyboard_notify_key(struct wlr_seat *seat, uint32_t time, uint32_t key, uint32_t state) { + clock_gettime(CLOCK_MONOTONIC, &seat->last_event); struct wlr_seat_keyboard_grab *grab = seat->keyboard_state.grab; grab->interface->key(grab, time, key, state); } diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index 0452f04c..ecec785c 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -211,6 +211,8 @@ static int xserver_handle_ready(int signal_number, void *data) { snprintf(display_name, sizeof(display_name), ":%d", wlr_xwayland->display); setenv("DISPLAY", display_name, true); + wl_signal_emit(&wlr_xwayland->events.ready, wlr_xwayland); + return 1; /* wayland event loop dispatcher's count */ } @@ -223,6 +225,7 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland, wlr_xwayland->wl_fd[0] = wlr_xwayland->wl_fd[1] = -1; wlr_xwayland->wm_fd[0] = wlr_xwayland->wm_fd[1] = -1; wl_signal_init(&wlr_xwayland->events.new_surface); + wl_signal_init(&wlr_xwayland->events.ready); wlr_xwayland->display = open_display_sockets(wlr_xwayland->x_fd); if (wlr_xwayland->display < 0) {