From e003296c23fb0a974a13121cd940d6bf3fe63fac Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 2 Oct 2017 09:15:21 -0400 Subject: [PATCH] xdg-popup: render popups in the right place --- include/wlr/types/wlr_xdg_shell_v6.h | 3 +++ rootston/output.c | 23 +++++++++++++++++++++++ rootston/xdg_shell_v6.c | 11 +++++++++-- types/wlr_xdg_shell_v6.c | 4 ++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 2d38dba0..b7acc2c4 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -89,6 +89,9 @@ struct wlr_xdg_surface_v6 { struct wlr_xdg_popup_v6 *popup_state; }; + struct wl_list popups; + struct wl_list popup_link; + bool configured; struct wl_event_source *configure_idle; struct wl_list configure_list; diff --git a/rootston/output.c b/rootston/output.c index 14d1783e..06786395 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -53,10 +53,33 @@ static void render_surface(struct wlr_surface *surface, } } +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 wlr_xdg_surface_v6 *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + if (!popup->configured) { + continue; + } + + double popup_x = base_x + surface->geometry->x + + popup->popup_state->geometry.x - popup->geometry->x; + 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); + } +} + 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); + if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { + render_xdg_v6_popups(view->xdg_surface_v6, desktop, wlr_output, + when, view->x, view->y); + } } static void output_frame_notify(struct wl_listener *listener, void *data) { diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index ab34f52a..ff0dd090 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -73,11 +73,18 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { + struct wlr_xdg_surface_v6 *surface = data; + assert(surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE); + + if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + wlr_log(L_DEBUG, "new xdg popup"); + return; + } + struct roots_desktop *desktop = wl_container_of(listener, desktop, xdg_shell_v6_surface); - struct wlr_xdg_surface_v6 *surface = data; - wlr_log(L_DEBUG, "new xdg surface: title=%s, app_id=%s", + wlr_log(L_DEBUG, "new xdg toplevel: title=%s, app_id=%s", surface->title, surface->app_id); wlr_xdg_surface_v6_ping(surface); diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 718e12fe..6e32ebdf 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -57,6 +57,7 @@ static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) { if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { wl_resource_set_user_data(surface->popup_state->resource, NULL); + wl_list_remove(&surface->popup_link); free(surface->popup_state); } @@ -317,6 +318,8 @@ static void xdg_surface_get_popup(struct wl_client *client, surface->popup_state->parent = parent; surface->popup_state->geometry = xdg_positioner_get_geometry(positioner, surface, parent); + wl_list_insert(&surface->popup_state->parent->popups, + &surface->popup_link); wl_resource_set_implementation(surface->popup_state->resource, &zxdg_popup_v6_implementation, surface, @@ -914,6 +917,7 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client, } wl_list_init(&surface->configure_list); + wl_list_init(&surface->popups); wl_signal_init(&surface->events.request_minimize); wl_signal_init(&surface->events.request_move);