diff options
Diffstat (limited to 'rootston/xdg_shell_v6.c')
-rw-r--r-- | rootston/xdg_shell_v6.c | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 001232ab..39e8a4b7 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -28,6 +28,18 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { popup_destroy((struct roots_view_child *)popup); } +static void popup_handle_map(struct wl_listener *listener, void *data) { + struct roots_xdg_popup_v6 *popup = + wl_container_of(listener, popup, map); + view_damage_whole(popup->view_child.view); +} + +static void popup_handle_unmap(struct wl_listener *listener, void *data) { + struct roots_xdg_popup_v6 *popup = + wl_container_of(listener, popup, unmap); + view_damage_whole(popup->view_child.view); +} + static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, struct wlr_xdg_popup_v6 *wlr_popup); @@ -38,6 +50,58 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) { popup_create(popup->view_child.view, wlr_popup); } +static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { + // get the output of the popup's positioner anchor point and convert it to + // the toplevel parent's coordinate system and then pass it to + // wlr_xdg_popup_v6_unconstrain_from_box + + // TODO: unconstrain popups for rotated windows + if (popup->view_child.view->rotation != 0.0) { + return; + } + + struct roots_view *view = popup->view_child.view; + struct wlr_output_layout *layout = view->desktop->layout; + struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; + + int anchor_lx, anchor_ly; + wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + + int popup_lx, popup_ly; + wlr_xdg_popup_v6_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x, + wlr_popup->geometry.y, &popup_lx, &popup_ly); + popup_lx += view->x; + popup_ly += view->y; + + anchor_lx += popup_lx; + anchor_ly += popup_ly; + + double dest_x = 0, dest_y = 0; + wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, + &dest_x, &dest_y); + + struct wlr_output *output = + wlr_output_layout_output_at(layout, dest_x, dest_y); + + if (output == NULL) { + return; + } + + int width = 0, height = 0; + wlr_output_effective_resolution(output, &width, &height); + + // the output box expressed in the coordinate system of the toplevel parent + // of the popup + struct wlr_box output_toplevel_sx_box = { + .x = output->lx - view->x, + .y = output->ly - view->y, + .width = width, + .height = height + }; + + wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &output_toplevel_sx_box); +} + static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, struct wlr_xdg_popup_v6 *wlr_popup) { struct roots_xdg_popup_v6 *popup = @@ -50,8 +114,15 @@ static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, view_child_init(&popup->view_child, view, wlr_popup->base->surface); popup->destroy.notify = popup_handle_destroy; wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); + popup->map.notify = popup_handle_map; + wl_signal_add(&wlr_popup->base->events.map, &popup->map); + popup->unmap.notify = popup_handle_unmap; + wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap); popup->new_popup.notify = popup_handle_new_popup; wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); + + popup_unconstrain(popup); + return popup; } @@ -238,7 +309,7 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) { return; } - view_maximize(view, surface->toplevel->next.maximized); + view_maximize(view, surface->toplevel->client_pending.maximized); } static void handle_request_fullscreen(struct wl_listener *listener, @@ -339,7 +410,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_container_of(listener, desktop, xdg_shell_v6_surface); wlr_log(L_DEBUG, "new xdg toplevel: title=%s, app_id=%s", - surface->title, surface->app_id); + surface->toplevel->title, surface->toplevel->app_id); wlr_xdg_surface_v6_ping(surface); struct roots_xdg_surface_v6 *roots_surface = @@ -357,15 +428,16 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { roots_surface->unmap.notify = handle_unmap; wl_signal_add(&surface->events.unmap, &roots_surface->unmap); roots_surface->request_move.notify = handle_request_move; - wl_signal_add(&surface->events.request_move, &roots_surface->request_move); + wl_signal_add(&surface->toplevel->events.request_move, + &roots_surface->request_move); roots_surface->request_resize.notify = handle_request_resize; - wl_signal_add(&surface->events.request_resize, + wl_signal_add(&surface->toplevel->events.request_resize, &roots_surface->request_resize); roots_surface->request_maximize.notify = handle_request_maximize; - wl_signal_add(&surface->events.request_maximize, + wl_signal_add(&surface->toplevel->events.request_maximize, &roots_surface->request_maximize); roots_surface->request_fullscreen.notify = handle_request_fullscreen; - wl_signal_add(&surface->events.request_fullscreen, + wl_signal_add(&surface->toplevel->events.request_fullscreen, &roots_surface->request_fullscreen); roots_surface->new_popup.notify = handle_new_popup; wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); @@ -388,10 +460,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { view->destroy = destroy; roots_surface->view = view; - if (surface->toplevel->next.maximized) { + if (surface->toplevel->client_pending.maximized) { view_maximize(view, true); } - if (surface->toplevel->next.fullscreen) { + if (surface->toplevel->client_pending.fullscreen) { view_set_fullscreen(view, true, NULL); } } |