References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4345
7HPLEFGATGAYG3O7EEGZ4UL4UOFXIJUQAKF377ZJXL3L5LQV3VIAC
65EUVCVN2KFRX4U6SASDU6GMUT2TKDQUGQQAE6V7OQKFERN3RSEQC
JCSC5VHJ3WGCG6ZLY3EJ6TGTCOT22AUMQ5B42LFVQBHHCVMGKEUQC
WGXD77AGAXYCNFRM3432KMWZSX4F37WL6MAHKD6TW7RF5IFTFABQC
DEWMVR6ZOXJDMECRB47RCED2QPVZWYWHLBB4KHYKXCPXKSLT7NWQC
D425ND7AT3F7QJ3CCSESMVDOC3J5C5P32M5SJDBHECZJXLHNQ2FAC
7B74AT3BXYB7PVW4F6SGQNPMHOU5TEV5TZ54CG6VSQI46XSEKWXQC
T5LZF6MAZN3S2CDRSWJTJRNOTM24DRE4NQBQI6F2ALYC5ZU74PTAC
MJZ6RCUUOK7R2RMXPXMLRWBAEM6234D2IS7RGPHAE5UN2S64GLGAC
WCMIXJB76ZXIXF4YV26URAV77N5GL7JLL4AFXSXBA7XHY5L33SUQC
K4WT3C2H7N7NXG7MYHKY2INKMLNUQYK5PHUVGZW5GS5T6Z3UKCFAC
AW7XCEBTLPKA5YP4T5P5SXX47QVPYETDFBSLV6KMJZNKN7BLO2EQC
34TOMU43GSVTGKBSPBPRFLQYCJZ35HV2BNHKUAJ6CPE4XZLADCLQC
EQRGODLKSVSPFSUZU7BV5ER72U4QS4ATSBKV544XXQVKKTOSC7EAC
/* This event is raised when wlr_xdg_shell receives a new xdg surface from a
* client, either a toplevel (application window) or popup,
* or when wlr_layer_shell receives a new popup from a layer.
* If you want to do something tricky with popups you should check if
* its parent is wlr_xdg_shell or wlr_layer_shell */
struct wlr_xdg_surface *xdg_surface = data;
/* This event is raised when a client creates a new toplevel (application window). */
struct wlr_xdg_toplevel *toplevel = data;
LayerSurface *l = NULL;
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
struct wlr_box box;
int type = toplevel_from_wlr_surface(xdg_surface->surface, &c, &l);
if (!xdg_surface->popup->parent || type < 0)
return;
xdg_surface->surface->data = wlr_scene_xdg_surface_create(
xdg_surface->popup->parent->data, xdg_surface);
if ((l && !l->mon) || (c && !c->mon))
return;
box = type == LayerShell ? l->mon->m : c->mon->w;
box.x -= (type == LayerShell ? l->geom.x : c->geom.x);
box.y -= (type == LayerShell ? l->geom.y : c->geom.y);
wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box);
return;
} else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE)
return;
LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify);
LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify);
LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify);
LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle);
LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen,
fullscreennotify);
LISTEN(&xdg_surface->toplevel->events.request_maximize, &c->maximize,
maximizenotify);
LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify);
LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify);
LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify);
LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify);
LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle);
}
void
createpopup(struct wl_listener *listener, void *data)
{
/* This event is raised when a client (either xdg-shell or layer-shell)
* creates a new popup. */
struct wlr_xdg_popup *popup = data;
LayerSurface *l = NULL;
Client *c = NULL;
struct wlr_box box;
int type = toplevel_from_wlr_surface(popup->base->surface, &c, &l);
if (!popup->parent || type < 0)
return;
popup->base->surface->data = wlr_scene_xdg_surface_create(
popup->parent->data, popup->base);
if ((l && !l->mon) || (c && !c->mon))
return;
box = type == LayerShell ? l->mon->m : c->mon->w;
box.x -= (type == LayerShell ? l->geom.x : c->geom.x);
box.y -= (type == LayerShell ? l->geom.y : c->geom.y);
/* FIXME: this send a configure event to a uninitialized wlr_xdg_surface */
wlr_xdg_popup_unconstrain_from_box(popup, &box);