From 278aa846195ceb8ea85c181aba21e0befbcce5de Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 14 Apr 2018 20:36:01 -0400 Subject: Basic layer popup rendering --- rootston/output.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'rootston') diff --git a/rootston/output.c b/rootston/output.c index 791b2819..48b20466 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -366,6 +366,8 @@ static void render_layer(struct roots_output *output, roots_surface->geo.x + output_layout_box->x, roots_surface->geo.y + output_layout_box->y, 0, &data->layout, render_surface, data); + + wlr_layer_surface_for_each_surface(layer, render_surface, data); } } -- cgit v1.2.3 From 0a0627f5d03afdaef2251e2442a3ff3285cd8356 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 14 Apr 2018 21:34:50 -0400 Subject: Finish forward-porting @acrisci's positioner work --- examples/layer-shell.c | 5 +- include/wlr/types/wlr_xdg_shell.h | 40 ++++++ rootston/xdg_shell.c | 56 ++++++++ types/wlr_xdg_shell.c | 262 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 360 insertions(+), 3 deletions(-) (limited to 'rootston') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index ac6e8a9e..56fa28f7 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -145,7 +145,8 @@ static const struct xdg_surface_listener xdg_surface_listener = { static void xdg_popup_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { - // Meh. + wlr_log(L_DEBUG, "Popup configured %dx%d@%d,%d", + width, height, x, y); } static void xdg_popup_done(void *data, struct xdg_popup *xdg_popup) { @@ -176,8 +177,6 @@ static void create_popup() { xdg_positioner_set_anchor_rect(xdg_positioner, cur_x, cur_y, 1, 1); xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT); xdg_positioner_set_gravity(xdg_positioner, XDG_POSITIONER_GRAVITY_TOP_LEFT); - xdg_positioner_set_constraint_adjustment(xdg_positioner, - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE); popup = xdg_surface_get_popup(xdg_surface, NULL, xdg_positioner); assert(popup); diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 809d6390..ead4613a 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -258,6 +258,46 @@ void wlr_xdg_surface_send_close(struct wlr_xdg_surface *surface); void wlr_xdg_surface_popup_get_position(struct wlr_xdg_surface *surface, double *popup_sx, double *popup_sy); +/** + * Get the geometry for this positioner based on the anchor rect, gravity, and + * size of this positioner. + */ +struct wlr_box wlr_xdg_positioner_get_geometry( + struct wlr_xdg_positioner *positioner); + +/** + * Get the anchor point for this popup in the toplevel parent's coordinate system. + */ +void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup, + int *toplevel_sx, int *toplevel_sy); + +/** + * Convert the given coordinates in the popup coordinate system to the toplevel + * surface coordinate system. + */ +void wlr_xdg_popup_get_toplevel_coords(struct wlr_xdg_popup *popup, + int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy); + +/** + * Set the geometry of this popup to unconstrain it according to its + * xdg-positioner rules. The box should be in the popup's root toplevel parent + * surface coordinate system. + */ +void wlr_xdg_popup_unconstrain_from_box(struct wlr_xdg_popup *popup, + struct wlr_box *toplevel_sx_box); + +/** + Invert the right/left anchor and gravity for this positioner. This can be + used to "flip" the positioner around the anchor rect in the x direction. + */ +void wlr_positioner_invert_x(struct wlr_xdg_positioner *positioner); + +/** + Invert the top/bottom anchor and gravity for this positioner. This can be + used to "flip" the positioner around the anchor rect in the y direction. + */ +void wlr_positioner_invert_y(struct wlr_xdg_positioner *positioner); + /** * Find a surface within this xdg-surface tree at the given surface-local * coordinates. Returns the surface and coordinates in the leaf surface diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c index 927bd018..bd670a87 100644 --- a/rootston/xdg_shell.c +++ b/rootston/xdg_shell.c @@ -48,6 +48,59 @@ 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 *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 *wlr_popup = popup->wlr_popup; + + int anchor_lx, anchor_ly; + wlr_xdg_popup_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + + int popup_lx, popup_ly; + wlr_xdg_popup_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_unconstrain_from_box( + popup->wlr_popup, &output_toplevel_sx_box); +} + static struct roots_xdg_popup *popup_create(struct roots_view *view, struct wlr_xdg_popup *wlr_popup) { struct roots_xdg_popup *popup = @@ -66,6 +119,9 @@ static struct roots_xdg_popup *popup_create(struct roots_view *view, 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; } diff --git a/types/wlr_xdg_shell.c b/types/wlr_xdg_shell.c index 22d404a7..78b18563 100644 --- a/types/wlr_xdg_shell.c +++ b/types/wlr_xdg_shell.c @@ -1608,6 +1608,268 @@ struct wlr_surface *wlr_xdg_surface_surface_at( return wlr_surface_surface_at(surface->surface, sx, sy, sub_x, sub_y); } +void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup, + int *root_sx, int *root_sy) { + struct wlr_box rect = popup->positioner.anchor_rect; + enum xdg_positioner_anchor anchor = popup->positioner.anchor; + int sx = 0, sy = 0; + + if (anchor == XDG_POSITIONER_ANCHOR_NONE) { + sx = (rect.x + rect.width) / 2; + sy = (rect.y + rect.height) / 2; + } else if (anchor == XDG_POSITIONER_ANCHOR_TOP) { + sx = (rect.x + rect.width) / 2; + sy = rect.y; + } else if (anchor == XDG_POSITIONER_ANCHOR_BOTTOM) { + sx = (rect.x + rect.width) / 2; + sy = rect.y + rect.height; + } else if (anchor == XDG_POSITIONER_ANCHOR_LEFT) { + sx = rect.x; + sy = (rect.y + rect.height) / 2; + } else if (anchor == XDG_POSITIONER_ANCHOR_RIGHT) { + sx = rect.x + rect.width; + sy = (rect.y + rect.height) / 2; + } else if (anchor == (XDG_POSITIONER_ANCHOR_TOP | + XDG_POSITIONER_ANCHOR_LEFT)) { + sx = rect.x; + sy = rect.y; + } else if (anchor == (XDG_POSITIONER_ANCHOR_TOP | + XDG_POSITIONER_ANCHOR_RIGHT)) { + sx = rect.x + rect.width; + sy = rect.y; + } else if (anchor == (XDG_POSITIONER_ANCHOR_BOTTOM | + XDG_POSITIONER_ANCHOR_LEFT)) { + sx = rect.x; + sy = rect.y + rect.height; + } else if (anchor == (XDG_POSITIONER_ANCHOR_BOTTOM | + XDG_POSITIONER_ANCHOR_RIGHT)) { + sx = rect.x + rect.width; + sy = rect.y + rect.height; + } + + *root_sx = sx; + *root_sy = sy; +} + +void wlr_xdg_popup_get_toplevel_coords(struct wlr_xdg_popup *popup, + int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy) { + assert(strcmp(popup->parent->role, wlr_desktop_xdg_toplevel_role) == 0 + || strcmp(popup->parent->role, wlr_desktop_xdg_popup_role) == 0); + struct wlr_xdg_surface *parent = popup->parent->role_data; + while (parent != NULL && parent->role == WLR_XDG_SURFACE_ROLE_POPUP) { + popup_sx += parent->popup->geometry.x; + popup_sy += parent->popup->geometry.y; + parent = parent->popup->parent->role_data; + } + + assert(parent); + + *toplevel_sx = popup_sx + parent->geometry.x; + *toplevel_sy = popup_sy + parent->geometry.y; + +} + +static void wlr_xdg_popup_box_constraints(struct wlr_xdg_popup *popup, + struct wlr_box *toplevel_sx_box, int *offset_x, int *offset_y) { + int popup_width = popup->geometry.width; + int popup_height = popup->geometry.height; + int anchor_sx = 0, anchor_sy = 0; + wlr_xdg_popup_get_anchor_point(popup, &anchor_sx, &anchor_sy); + int popup_sx = 0, popup_sy = 0; + wlr_xdg_popup_get_toplevel_coords(popup, popup->geometry.x, + popup->geometry.y, &popup_sx, &popup_sy); + *offset_x = 0, *offset_y = 0; + + if (popup_sx < toplevel_sx_box->x) { + *offset_x = toplevel_sx_box->x - popup_sx; + } else if (popup_sx + popup_width > + toplevel_sx_box->x + toplevel_sx_box->width) { + *offset_x = toplevel_sx_box->x + toplevel_sx_box->width - + (popup_sx + popup_width); + } + + if (popup_sy < toplevel_sx_box->y) { + *offset_y = toplevel_sx_box->y - popup_sy; + } else if (popup_sy + popup_height > + toplevel_sx_box->y + toplevel_sx_box->height) { + *offset_y = toplevel_sx_box->y + toplevel_sx_box->height - + (popup_sy + popup_height); + } +} + +static bool wlr_xdg_popup_unconstrain_flip(struct wlr_xdg_popup *popup, + struct wlr_box *toplevel_sx_box) { + int offset_x = 0, offset_y = 0; + wlr_xdg_popup_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + return true; + } + + bool flip_x = offset_x && + (popup->positioner.constraint_adjustment & + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X); + + bool flip_y = offset_y && + (popup->positioner.constraint_adjustment & + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y); + + if (flip_x) { + wlr_positioner_invert_x(&popup->positioner); + } + if (flip_y) { + wlr_positioner_invert_y(&popup->positioner); + } + + popup->geometry = + wlr_xdg_positioner_get_geometry(&popup->positioner); + + wlr_xdg_popup_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + // no longer constrained + return true; + } + + // revert the positioner back if it didn't fix it and go to the next part + if (flip_x) { + wlr_positioner_invert_x(&popup->positioner); + } + if (flip_y) { + wlr_positioner_invert_y(&popup->positioner); + } + + popup->geometry = + wlr_xdg_positioner_get_geometry(&popup->positioner); + + return false; +} + +static bool wlr_xdg_popup_unconstrain_slide(struct wlr_xdg_popup *popup, + struct wlr_box *toplevel_sx_box) { + int offset_x = 0, offset_y = 0; + wlr_xdg_popup_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + return true; + } + + bool slide_x = offset_x && + (popup->positioner.constraint_adjustment & + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X); + + bool slide_y = offset_x && + (popup->positioner.constraint_adjustment & + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y); + + if (slide_x) { + popup->geometry.x += offset_x; + } + + if (slide_y) { + popup->geometry.y += offset_y; + } + + int toplevel_x = 0, toplevel_y = 0; + wlr_xdg_popup_get_toplevel_coords(popup, popup->geometry.x, + popup->geometry.y, &toplevel_x, &toplevel_y); + + if (slide_x && toplevel_x < toplevel_sx_box->x) { + popup->geometry.x += toplevel_sx_box->x - toplevel_x; + } + if (slide_y && toplevel_y < toplevel_sx_box->y) { + popup->geometry.y += toplevel_sx_box->y - toplevel_y; + } + + wlr_xdg_popup_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); + + return !offset_x && !offset_y; +} + +static bool wlr_xdg_popup_unconstrain_resize(struct wlr_xdg_popup *popup, + struct wlr_box *toplevel_sx_box) { + int offset_x, offset_y; + wlr_xdg_popup_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + return true; + } + + bool resize_x = offset_x && + (popup->positioner.constraint_adjustment & + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X); + + bool resize_y = offset_x && + (popup->positioner.constraint_adjustment & + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y); + + if (resize_x) { + popup->geometry.width -= offset_x; + } + if (resize_y) { + popup->geometry.height -= offset_y; + } + + wlr_xdg_popup_box_constraints(popup, toplevel_sx_box, + &offset_y, &offset_y); + + return !offset_x && !offset_y; +} + +void wlr_xdg_popup_unconstrain_from_box(struct wlr_xdg_popup *popup, + struct wlr_box *toplevel_sx_box) { + if (wlr_xdg_popup_unconstrain_flip(popup, toplevel_sx_box)) { + return; + } + if (wlr_xdg_popup_unconstrain_slide(popup, toplevel_sx_box)) { + return; + } + if (wlr_xdg_popup_unconstrain_resize(popup, toplevel_sx_box)) { + return; + } +} + +void wlr_positioner_invert_x(struct wlr_xdg_positioner *positioner) { + if (positioner->anchor & XDG_POSITIONER_ANCHOR_LEFT) { + positioner->anchor &= ~XDG_POSITIONER_ANCHOR_LEFT; + positioner->anchor |= XDG_POSITIONER_ANCHOR_RIGHT; + } else if (positioner->anchor & XDG_POSITIONER_ANCHOR_RIGHT) { + positioner->anchor &= ~XDG_POSITIONER_ANCHOR_RIGHT; + positioner->anchor |= XDG_POSITIONER_ANCHOR_LEFT; + } + + if (positioner->gravity & XDG_POSITIONER_GRAVITY_RIGHT) { + positioner->gravity &= ~XDG_POSITIONER_GRAVITY_RIGHT; + positioner->gravity |= XDG_POSITIONER_GRAVITY_LEFT; + } else if (positioner->gravity & XDG_POSITIONER_GRAVITY_LEFT) { + positioner->gravity &= ~XDG_POSITIONER_GRAVITY_LEFT; + positioner->gravity |= XDG_POSITIONER_GRAVITY_RIGHT; + } +} + +void wlr_positioner_invert_y( + struct wlr_xdg_positioner *positioner) { + if (positioner->anchor & XDG_POSITIONER_ANCHOR_TOP) { + positioner->anchor &= ~XDG_POSITIONER_ANCHOR_TOP; + positioner->anchor |= XDG_POSITIONER_ANCHOR_BOTTOM; + } else if (positioner->anchor & XDG_POSITIONER_ANCHOR_BOTTOM) { + positioner->anchor &= ~XDG_POSITIONER_ANCHOR_BOTTOM; + positioner->anchor |= XDG_POSITIONER_ANCHOR_TOP; + } + + if (positioner->gravity & XDG_POSITIONER_GRAVITY_TOP) { + positioner->gravity &= ~XDG_POSITIONER_GRAVITY_TOP; + positioner->gravity |= XDG_POSITIONER_GRAVITY_BOTTOM; + } else if (positioner->gravity & XDG_POSITIONER_GRAVITY_BOTTOM) { + positioner->gravity &= ~XDG_POSITIONER_GRAVITY_BOTTOM; + positioner->gravity |= XDG_POSITIONER_GRAVITY_TOP; + } +} struct xdg_surface_iterator_data { wlr_surface_iterator_func_t user_iterator; -- cgit v1.2.3 From d4cb33c9fccc219c7d66e634618fe07c6daaf18d Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Thu, 19 Apr 2018 15:30:39 +0200 Subject: rootston: Let layer_surface_at look at popups This allows them to receive input as well. --- rootston/desktop.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'rootston') diff --git a/rootston/desktop.c b/rootston/desktop.c index 0949b5db..6ac665bc 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -641,11 +641,24 @@ static struct wlr_surface *layer_surface_at(struct roots_output *output, struct wl_list *layer, double ox, double oy, double *sx, double *sy) { struct roots_layer_surface *roots_surface; wl_list_for_each_reverse(roots_surface, layer, link) { - struct wlr_surface *wlr_surface = - roots_surface->layer_surface->surface; - double _sx = ox - roots_surface->geo.x; - double _sy = oy - roots_surface->geo.y; - // TODO: Test popups/subsurfaces + struct wlr_surface *wlr_surface; + double _sx, _sy; + struct wlr_xdg_popup *popup; + wl_list_for_each(popup, &roots_surface->layer_surface->popups, link) { + wlr_surface = popup->base->surface; + _sx = ox - roots_surface->geo.x - popup->geometry.x; + _sy = oy - roots_surface->geo.y - popup->geometry.y; + if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) { + *sx = _sx; + *sy = _sy; + return wlr_surface; + } + // TODO: popups can have popups + } + // TODO: Test subsurfaces + wlr_surface = roots_surface->layer_surface->surface; + _sx = ox - roots_surface->geo.x; + _sy = oy - roots_surface->geo.y; if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) { *sx = _sx; *sy = _sy; -- cgit v1.2.3 From ad22e023103fc737188cac0bb468eedbc4d3982e Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Thu, 19 Apr 2018 18:25:19 +0200 Subject: rootston: Damage layer-shell popups --- include/rootston/layers.h | 10 ++++++ rootston/layer_shell.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) (limited to 'rootston') diff --git a/include/rootston/layers.h b/include/rootston/layers.h index 0e5164bb..9eab53ca 100644 --- a/include/rootston/layers.h +++ b/include/rootston/layers.h @@ -14,11 +14,21 @@ struct roots_layer_surface { struct wl_listener unmap; struct wl_listener surface_commit; struct wl_listener output_destroy; + struct wl_listener new_popup; bool configured; struct wlr_box geo; }; +struct roots_layer_popup { + struct roots_layer_surface *parent; + struct wlr_xdg_popup *wlr_popup; + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener destroy; + struct wl_listener commit; +}; + struct roots_output; void arrange_layers(struct roots_output *output); diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index b6f7ba4c..071467e0 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -292,6 +292,82 @@ static void handle_unmap(struct wl_listener *listener, void *data) { unmap(layer->layer_surface); } +static void popup_handle_map(struct wl_listener *listener, void *data) { + struct roots_layer_popup *popup = wl_container_of(listener, popup, map); + struct roots_layer_surface *layer = popup->parent; + struct wlr_output *wlr_output = layer->layer_surface->output; + struct roots_output *output = wlr_output->data; + struct wlr_box geom; + memcpy(&geom, &popup->wlr_popup->geometry, sizeof(struct wlr_box)); + geom.x += layer->geo.x; + geom.y += layer->geo.y; + wlr_output_damage_add_box(output->damage, &geom); +} + +static void popup_handle_unmap(struct wl_listener *listener, void *data) { + struct roots_layer_popup *popup = wl_container_of(listener, popup, unmap); + struct roots_layer_surface *layer = popup->parent; + struct wlr_output *wlr_output = layer->layer_surface->output; + struct roots_output *output = wlr_output->data; + struct wlr_box geom; + memcpy(&geom, &popup->wlr_popup->geometry, sizeof(struct wlr_box)); + geom.x += layer->geo.x; + geom.y += layer->geo.y; + wlr_output_damage_add_box(output->damage, &geom); +} + +static void popup_handle_commit(struct wl_listener *listener, void *data) { + struct roots_layer_popup *popup = wl_container_of(listener, popup, commit); + struct roots_layer_surface *layer = popup->parent; + struct wlr_output *wlr_output = layer->layer_surface->output; + struct roots_output *output = wlr_output->data; + struct wlr_box geom; + memcpy(&geom, &popup->wlr_popup->geometry, sizeof(struct wlr_box)); + geom.x += layer->geo.x; + geom.y += layer->geo.y; + wlr_output_damage_add_box(output->damage, &geom); +} + +static void popup_handle_destroy(struct wl_listener *listener, void *data) { + struct roots_layer_popup *popup = + wl_container_of(listener, popup, destroy); + + wl_list_remove(&popup->map.link); + wl_list_remove(&popup->unmap.link); + wl_list_remove(&popup->destroy.link); + wl_list_remove(&popup->commit.link); + free(popup); +} + +static struct roots_layer_popup *popup_create(struct roots_layer_surface *parent, + struct wlr_xdg_popup *wlr_popup) { + struct roots_layer_popup *popup = + calloc(1, sizeof(struct roots_layer_popup)); + if (popup == NULL) { + return NULL; + } + popup->wlr_popup = wlr_popup; + popup->parent = parent; + 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->destroy.notify = popup_handle_destroy; + wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); + popup->commit.notify = popup_handle_commit; + wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit); + /* TODO: popups can have popups, see xdg_shell::popup_create */ + + return popup; +} + +static void handle_new_popup(struct wl_listener *listener, void *data) { + struct roots_layer_surface *roots_layer_surface = + wl_container_of(listener, roots_layer_surface, new_popup); + struct wlr_xdg_popup *wlr_popup = data; + popup_create(roots_layer_surface, wlr_popup); +} + void handle_layer_shell_surface(struct wl_listener *listener, void *data) { struct wlr_layer_surface *layer_surface = data; struct roots_desktop *desktop = @@ -338,6 +414,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->events.map, &roots_surface->map); roots_surface->unmap.notify = handle_unmap; wl_signal_add(&layer_surface->events.unmap, &roots_surface->unmap); + roots_surface->new_popup.notify = handle_new_popup; + wl_signal_add(&layer_surface->events.new_popup, &roots_surface->new_popup); // TODO: Listen for subsurfaces roots_surface->layer_surface = layer_surface; -- cgit v1.2.3 From 57cc4c319d1d7002dc281e623c6716e619e21fdf Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Fri, 20 Apr 2018 17:48:50 +0200 Subject: rootston: Send frame_done for popups too Thanks @emersion --- rootston/output.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'rootston') diff --git a/rootston/output.c b/rootston/output.c index 48b20466..225b7213 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -379,6 +379,10 @@ static void layers_send_done( wl_list_for_each(roots_surface, &output->layers[i], link) { struct wlr_layer_surface *layer = roots_surface->layer_surface; wlr_surface_send_frame_done(layer->surface, when); + struct wlr_xdg_popup *popup; + wl_list_for_each(popup, &roots_surface->layer_surface->popups, link) { + wlr_surface_send_frame_done(popup->base->surface, when); + } } } } -- cgit v1.2.3