From adea7b67289fad4caa1def47c56efa0b45e41c96 Mon Sep 17 00:00:00 2001 From: Jente Hidskes Date: Wed, 13 Feb 2019 18:14:20 +0100 Subject: [PATCH] xdg_shell: implement xdg_popup --- xdg_shell.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ xdg_shell.h | 10 +++++++ 2 files changed, 91 insertions(+) diff --git a/xdg_shell.c b/xdg_shell.c index e7432bc..05bc59f 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -17,6 +17,84 @@ #include "view.h" #include "xdg_shell.h" +static void +xdg_popup_destroy(struct cg_view_child *child) +{ + if (!child) { + return; + } + + struct cg_xdg_popup *popup = (struct cg_xdg_popup *) child; + wl_list_remove(&popup->destroy.link); + wl_list_remove(&popup->new_popup.link); + view_child_finish(&popup->view_child); + free(popup); +} + +static void +handle_xdg_popup_destroy(struct wl_listener *listener, void *data) +{ + struct cg_xdg_popup *popup = wl_container_of(listener, popup, destroy); + struct cg_view_child *view_child = (struct cg_view_child *) popup + xdg_popup_destroy(view_child); +} + +static void xdg_popup_create(struct cg_view *view, struct wlr_xdg_popup *wlr_popup); + +static void +popup_handle_new_xdg_popup(struct wl_listener *listener, void *data) +{ + struct cg_xdg_popup *popup = wl_container_of(listener, popup, new_popup); + struct wlr_xdg_popup *wlr_popup = data; + xdg_popup_create(popup->view_child.view, wlr_popup); +} + +static void +popup_unconstrain(struct cg_xdg_popup *popup) +{ + struct cg_view *view = popup->view_child.view; + struct wlr_output *output = view->server->output->wlr_output; + + int width, height; + wlr_output_effective_resolution(output, &width, &height); + + struct wlr_box output_toplevel_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_box); +} + +static void +xdg_popup_create(struct cg_view *view, struct wlr_xdg_popup *wlr_popup) +{ + struct cg_xdg_popup *popup = calloc(1, sizeof(struct cg_xdg_popup)); + if (!popup) { + return; + } + + popup->wlr_popup = wlr_popup; + view_child_init(&popup->view_child, view, wlr_popup->base->surface); + popup->view_child.destroy = xdg_popup_destroy; + popup->destroy.notify = handle_xdg_popup_destroy; + wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); + popup->new_popup.notify = popup_handle_new_xdg_popup; + wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); + + popup_unconstrain(popup); +} + +static void +handle_new_xdg_popup(struct wl_listener *listener, void *data) +{ + struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, new_popup); + struct wlr_xdg_popup *wlr_popup = data; + xdg_popup_create(&xdg_shell_view->view, wlr_popup); +} + static struct cg_xdg_shell_view * xdg_shell_view_from_view(struct cg_view *view) { @@ -145,6 +223,7 @@ handle_xdg_shell_surface_destroy(struct wl_listener *listener, void *data) wl_list_remove(&xdg_shell_view->map.link); wl_list_remove(&xdg_shell_view->unmap.link); wl_list_remove(&xdg_shell_view->destroy.link); + wl_list_remove(&xdg_shell_view->new_popup.link); xdg_shell_view->xdg_surface = NULL; view_destroy(view); @@ -187,4 +266,6 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap); xdg_shell_view->destroy.notify = handle_xdg_shell_surface_destroy; wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); + xdg_shell_view->new_popup.notify = handle_new_xdg_popup; + wl_signal_add(&xdg_surface->events.new_popup, &xdg_shell_view->new_popup); } diff --git a/xdg_shell.h b/xdg_shell.h index 7214aae..2baf596 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -16,6 +16,16 @@ struct cg_xdg_shell_view { struct wl_listener commit; // TODO: allow applications to go to fullscreen from maximized? // struct wl_listener request_fullscreen; + + struct wl_listener new_popup; +}; + +struct cg_xdg_popup { + struct cg_view_child view_child; + struct wlr_xdg_popup *wlr_popup; + + struct wl_listener destroy; + struct wl_listener new_popup; }; void handle_xdg_shell_surface_new(struct wl_listener *listener, void *data);