diff options
Diffstat (limited to 'rootston/desktop.c')
-rw-r--r-- | rootston/desktop.c | 153 |
1 files changed, 129 insertions, 24 deletions
diff --git a/rootston/desktop.c b/rootston/desktop.c index f0f8320d..001cefe0 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -16,6 +16,16 @@ 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; + } + if (input->last_active_view == view) { + input->last_active_view = NULL; + } + for (size_t i = 0; i < desktop->views->length; ++i) { struct roots_view *_view = desktop->views->items[i]; if (view == _view) { @@ -36,16 +46,6 @@ void view_get_size(struct roots_view *view, struct wlr_box *box) { box->height = view->wlr_surface->current->height; } -void view_get_input_bounds(struct roots_view *view, struct wlr_box *box) { - if (view->get_input_bounds) { - view->get_input_bounds(view, box); - return; - } - 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); @@ -58,6 +58,46 @@ void view_resize(struct roots_view *view, uint32_t width, uint32_t height) { } } +void view_close(struct roots_view *view) { + if (view->close) { + view->close(view); + } +} + +bool view_center(struct roots_view *view) { + struct wlr_box size; + view_get_size(view, &size); + if (size.width == 0 && size.height == 0) { + return false; + } + + 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); + const struct wlr_output_layout_output *output_layout = + wlr_output_layout_get(desktop->layout, output); + if (!output) { + return false; + } + + view->x = (double)(output->width - size.width) / 2 + + output_layout->x; + view->y = (double)(output->height - size.height) / 2 + + output_layout->y; + return true; +} + +bool view_initialize(struct roots_view *view) { + bool centered = view_center(view); + if (centered) { + struct roots_input *input = view->desktop->server->input; + set_view_focus(input, view->desktop, view); + wlr_seat_keyboard_notify_enter(input->wl_seat, view->wlr_surface); + } + return centered; +} + static struct wlr_subsurface *subsurface_at(struct wlr_surface *surface, double sx, double sy, double *sub_x, double *sub_y) { struct wlr_subsurface *subsurface; @@ -68,17 +108,59 @@ static struct wlr_subsurface *subsurface_at(struct wlr_surface *surface, subsurface_at(subsurface->surface, _sub_x + sx, _sub_y + sy, sub_x, sub_y); if (sub) { - // TODO: convert sub_x and sub_y to the parent coordinate system + // TODO: This won't work for nested subsurfaces. Convert sub_x and + // sub_y to the parent coordinate system return sub; } int sub_width = subsurface->surface->current->buffer_width; int sub_height = subsurface->surface->current->buffer_height; if ((sx > _sub_x && sx < _sub_x + sub_width) && - (sy > _sub_y && sub_y < sub_y + sub_height)) { - *sub_x = _sub_x; - *sub_y = _sub_y; - return subsurface; + (sy > _sub_y && sy < _sub_y + sub_height)) { + if (pixman_region32_contains_point( + &subsurface->surface->current->input, + sx - _sub_x, sy - _sub_y, NULL)) { + *sub_x = _sub_x; + *sub_y = _sub_y; + return subsurface; + } + } + } + + return NULL; +} + +static struct wlr_xdg_surface_v6 *xdg_v6_popup_at( + struct wlr_xdg_surface_v6 *surface, double sx, double sy, + double *popup_sx, double *popup_sy) { + // XXX: I think this is so complicated because we're mixing geometry + // coordinates with surface coordinates. Input handling should only deal + // with surface coordinates. + struct wlr_xdg_surface_v6 *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + double _popup_sx = surface->geometry->x + popup->popup_state->geometry.x; + double _popup_sy = surface->geometry->y + popup->popup_state->geometry.y; + int popup_width = popup->popup_state->geometry.width; + int popup_height = popup->popup_state->geometry.height; + + struct wlr_xdg_surface_v6 *_popup = + xdg_v6_popup_at(popup, sx - _popup_sx + popup->geometry->x, + sy - _popup_sy + popup->geometry->y, popup_sx, popup_sy); + if (_popup) { + *popup_sx = *popup_sx + _popup_sx - popup->geometry->x; + *popup_sy = *popup_sy + _popup_sy - popup->geometry->y; + return _popup; + } + + if ((sx > _popup_sx && sx < _popup_sx + popup_width) && + (sy > _popup_sy && sy < _popup_sy + popup_height)) { + if (pixman_region32_contains_point(&popup->surface->current->input, + sx - _popup_sx + popup->geometry->x, + sy - _popup_sy + popup->geometry->y, NULL)) { + *popup_sx = _popup_sx - popup->geometry->x; + *popup_sy = _popup_sy - popup->geometry->y; + return popup; + } } } @@ -93,8 +175,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_box box; - view_get_input_bounds(view, &box); + struct wlr_box box = { + .x = 0, + .y = 0, + .width = view->wlr_surface->current->buffer_width, + .height = view->wlr_surface->current->buffer_height, + }; if (view->rotation != 0.0) { // Coordinates relative to the center of the view double ox = view_sx - (double)box.width/2, @@ -106,6 +192,21 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, 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, + &popup_sx, &popup_sy); + + if (popup) { + *sx = view_sx - popup_sx; + *sy = view_sy - popup_sy; + *surface = popup->surface; + return view; + } + } + double sub_x, sub_y; struct wlr_subsurface *subsurface = subsurface_at(view->wlr_surface, view_sx, view_sy, &sub_x, &sub_y); @@ -116,7 +217,10 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, return view; } - if (wlr_box_contains_point(&box, view_sx, view_sy)) { + if (wlr_box_contains_point(&box, view_sx, view_sy) && + pixman_region32_contains_point( + &view->wlr_surface->current->input, + view_sx, view_sy, NULL)) { *sx = view_sx; *sy = view_sy; *surface = view->wlr_surface; @@ -138,16 +242,15 @@ struct roots_desktop *desktop_create(struct roots_server *server, wl_list_init(&desktop->output_remove.link); desktop->output_remove.notify = output_remove_notify; - wl_signal_add(&server->backend->events.output_add, - &desktop->output_add); + wl_signal_add(&server->backend->events.output_add, &desktop->output_add); wl_signal_add(&server->backend->events.output_remove, - &desktop->output_remove); + &desktop->output_remove); desktop->server = server; desktop->config = config; desktop->layout = wlr_output_layout_create(); - desktop->compositor = wlr_compositor_create( - server->wl_display, server->renderer); + desktop->compositor = wlr_compositor_create(server->wl_display, + server->renderer); desktop->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); wl_signal_add(&desktop->xdg_shell_v6->events.new_surface, @@ -170,7 +273,9 @@ struct roots_desktop *desktop_create(struct roots_server *server, #endif desktop->gamma_control_manager = wlr_gamma_control_manager_create( - server->wl_display); + server->wl_display); + desktop->screenshooter = wlr_screenshooter_create(server->wl_display, + server->renderer); return desktop; } |