diff options
Diffstat (limited to 'rootston/desktop.c')
-rw-r--r-- | rootston/desktop.c | 186 |
1 files changed, 150 insertions, 36 deletions
diff --git a/rootston/desktop.c b/rootston/desktop.c index 29f78ac7..1695d007 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -10,19 +10,25 @@ #include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_wl_shell.h> +#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xdg_shell_v6.h> #include <wlr/util/log.h> #include <server-decoration-protocol.h> #include "rootston/server.h" -#include "rootston/server.h" +#include "rootston/seat.h" +#include "rootston/xcursor.h" +// TODO replace me with a signal void view_destroy(struct roots_view *view) { struct roots_desktop *desktop = view->desktop; struct roots_input *input = desktop->server->input; - if (input->active_view == view) { - input->active_view = NULL; - input->mode = ROOTS_CURSOR_PASSTHROUGH; + struct roots_seat *seat; + wl_list_for_each(seat, &input->seats, link) { + if (seat->focus == view) { + seat->focus = NULL; + seat->cursor->mode = ROOTS_CURSOR_PASSTHROUGH; + } } for (size_t i = 0; i < desktop->views->length; ++i) { @@ -35,36 +41,64 @@ void view_destroy(struct roots_view *view) { free(view); } -void view_get_size(struct roots_view *view, struct wlr_box *box) { +void view_get_box(const struct roots_view *view, struct wlr_box *box) { + box->x = view->x; + box->y = view->y; if (view->get_size) { view->get_size(view, box); - return; + } else { + box->width = view->wlr_surface->current->width; + box->height = view->wlr_surface->current->height; } - box->x = box->y = 0; - box->width = view->wlr_surface->current->width; - box->height = view->wlr_surface->current->height; } -void view_activate(struct roots_view *view, bool activate) { - if (view->activate) { - view->activate(view, activate); +static void view_update_output(const struct roots_view *view, + const struct wlr_box *before) { + struct roots_desktop *desktop = view->desktop; + struct roots_output *output; + struct wlr_box box; + view_get_box(view, &box); + wl_list_for_each(output, &desktop->outputs, link) { + bool intersected = before->x != -1 && wlr_output_layout_intersects( + desktop->layout, output->wlr_output, + before->x, before->y, before->x + before->width, + before->y + before->height); + bool intersects = wlr_output_layout_intersects( + desktop->layout, output->wlr_output, + view->x, view->y, view->x + box.width, view->y + box.height); + if (intersected && !intersects) { + wlr_surface_send_leave(view->wlr_surface, output->wlr_output); + } + if (!intersected && intersects) { + wlr_surface_send_enter(view->wlr_surface, output->wlr_output); + } } } void view_move(struct roots_view *view, double x, double y) { + struct wlr_box before; + view_get_box(view, &before); if (view->move) { view->move(view, x, y); - return; + } else { + view->x = x; + view->y = y; } +} - view->x = x; - view->y = y; +void view_activate(struct roots_view *view, bool activate) { + if (view->activate) { + view->activate(view, activate); + } } void view_resize(struct roots_view *view, uint32_t width, uint32_t height) { + struct wlr_box before; + view_get_box(view, &before); if (view->resize) { view->resize(view, width, height); } + view_update_output(view, &before); } void view_move_resize(struct roots_view *view, double x, double y, @@ -78,6 +112,50 @@ void view_move_resize(struct roots_view *view, double x, double y, view_resize(view, width, height); } +void view_maximize(struct roots_view *view, bool maximized) { + if (view->maximized == maximized) { + return; + } + + if (view->maximize) { + view->maximize(view, maximized); + } + + if (!view->maximized && maximized) { + struct wlr_box view_box; + view_get_box(view, &view_box); + + view->maximized = true; + view->saved.x = view->x; + view->saved.y = view->y; + view->saved.rotation = view->rotation; + view->saved.width = view_box.width; + view->saved.height = view_box.height; + + double output_x, output_y; + wlr_output_layout_closest_point(view->desktop->layout, NULL, + view->x + (double)view_box.width/2, + view->y + (double)view_box.height/2, + &output_x, &output_y); + struct wlr_output *output = wlr_output_layout_output_at( + view->desktop->layout, output_x, output_y); + struct wlr_box *output_box = + wlr_output_layout_get_box(view->desktop->layout, output); + + view_move_resize(view, output_box->x, output_box->y, output_box->width, + output_box->height); + view->rotation = 0; + } + + if (view->maximized && !maximized) { + view->maximized = false; + + view_move_resize(view, view->saved.x, view->saved.y, view->saved.width, + view->saved.height); + view->rotation = view->saved.rotation; + } +} + void view_close(struct roots_view *view) { if (view->close) { view->close(view); @@ -85,19 +163,26 @@ void view_close(struct roots_view *view) { } bool view_center(struct roots_view *view) { - struct wlr_box size; - view_get_size(view, &size); + struct wlr_box box; + view_get_box(view, &box); struct roots_desktop *desktop = view->desktop; - struct wlr_cursor *cursor = desktop->server->input->cursor; - - struct wlr_output *output = - wlr_output_layout_output_at(desktop->layout, cursor->x, cursor->y); - - if (!output) { - output = wlr_output_layout_get_center_output(desktop->layout); + 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_output_at(desktop->layout, + seat->cursor->cursor->x, + seat->cursor->cursor->y); if (!output) { // empty layout return false; @@ -109,22 +194,30 @@ bool view_center(struct roots_view *view) { int width, height; wlr_output_effective_resolution(output, &width, &height); - double view_x = (double)(width - size.width) / 2 + l_output->x; - double view_y = (double)(height - size.height) / 2 + l_output->y; - + double view_x = (double)(width - box.width) / 2 + l_output->x; + double view_y = (double)(height - box.height) / 2 + l_output->y; view_move(view, view_x, view_y); return true; } void view_setup(struct roots_view *view) { - view_center(view); - struct roots_input *input = view->desktop->server->input; - set_view_focus(input, view->desktop, view); + // TODO what seat gets focus? the one with the last input event? + struct roots_seat *seat; + wl_list_for_each(seat, &input->seats, link) { + roots_seat_focus_view(seat, view); + } + + view_center(view); + struct wlr_box before; + view_get_box(view, &before); + view_update_output(view, &before); } void view_teardown(struct roots_view *view) { + // TODO replace me with a signal + /* struct wlr_list *views = view->desktop->views; if (views->length < 2 || views->items[views->length-1] != view) { return; @@ -133,12 +226,12 @@ void view_teardown(struct roots_view *view) { struct roots_view *prev_view = views->items[views->length-2]; struct roots_input *input = prev_view->desktop->server->input; set_view_focus(input, prev_view->desktop, prev_view); - wlr_seat_keyboard_notify_enter(input->wl_seat, prev_view->wlr_surface); + */ } 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 && @@ -150,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 @@ -168,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, @@ -183,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, @@ -245,6 +337,16 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->server = server; desktop->config = config; + + desktop->xcursor_manager = wlr_xcursor_manager_create(NULL, + ROOTS_XCURSOR_SIZE); + if (desktop->xcursor_manager == NULL) { + wlr_log(L_ERROR, "Cannot create XCursor manager"); + wlr_list_free(desktop->views); + free(desktop); + return NULL; + } + desktop->layout = wlr_output_layout_create(); desktop->compositor = wlr_compositor_create(server->wl_display, server->renderer); @@ -266,6 +368,18 @@ struct roots_desktop *desktop_create(struct roots_server *server, wl_signal_add(&desktop->xwayland->events.new_surface, &desktop->xwayland_surface); desktop->xwayland_surface.notify = handle_xwayland_surface; + + if (wlr_xcursor_manager_load(desktop->xcursor_manager, 1)) { + wlr_log(L_ERROR, "Cannot load XWayland XCursor theme"); + } + struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( + desktop->xcursor_manager, ROOTS_XCURSOR_DEFAULT, 1); + if (xcursor != NULL) { + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_xwayland_set_cursor(desktop->xwayland, image->buffer, + image->width, image->width, image->height, image->hotspot_x, + image->hotspot_y); + } } #endif |