improve type safety of toplevel_from_wlr_surface()

This commit is contained in:
Leonardo Hernández Hernández 2022-12-03 15:17:43 -06:00
parent 38bd00351a
commit 22336612ae
No known key found for this signature in database
GPG key ID: E538897EE11B9624
2 changed files with 56 additions and 40 deletions

View file

@ -51,29 +51,38 @@ client_surface(Client *c)
return c->surface.xdg->surface; return c->surface.xdg->surface;
} }
static inline void * static inline int
toplevel_from_wlr_surface(struct wlr_surface *s) toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
{ {
struct wlr_xdg_surface *xdg_surface; struct wlr_xdg_surface *xdg_surface;
struct wlr_surface *root_surface; struct wlr_surface *root_surface;
struct wlr_layer_surface_v1 *layer_surface; struct wlr_layer_surface_v1 *layer_surface;
Client *c = NULL;
LayerSurface *l = NULL;
int type = -1;
#ifdef XWAYLAND #ifdef XWAYLAND
struct wlr_xwayland_surface *xsurface; struct wlr_xwayland_surface *xsurface;
#endif #endif
if (!s) if (!s)
return NULL; return type;
root_surface = wlr_surface_get_root_surface(s); root_surface = wlr_surface_get_root_surface(s);
#ifdef XWAYLAND #ifdef XWAYLAND
if (wlr_surface_is_xwayland_surface(root_surface) if (wlr_surface_is_xwayland_surface(root_surface)
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(root_surface))) && (xsurface = wlr_xwayland_surface_from_wlr_surface(root_surface))) {
return xsurface->data; c = xsurface->data;
type = c->type;
goto end;
}
#endif #endif
if (wlr_surface_is_layer_surface(root_surface) if (wlr_surface_is_layer_surface(root_surface)
&& (layer_surface = wlr_layer_surface_v1_from_wlr_surface(root_surface))) && (layer_surface = wlr_layer_surface_v1_from_wlr_surface(root_surface))) {
return layer_surface->data; l = layer_surface->data;
type = LayerShell;
goto end;
}
if (wlr_surface_is_xdg_surface(root_surface) if (wlr_surface_is_xdg_surface(root_surface)
&& (xdg_surface = wlr_xdg_surface_from_wlr_surface(root_surface))) { && (xdg_surface = wlr_xdg_surface_from_wlr_surface(root_surface))) {
@ -81,21 +90,28 @@ toplevel_from_wlr_surface(struct wlr_surface *s)
switch (xdg_surface->role) { switch (xdg_surface->role) {
case WLR_XDG_SURFACE_ROLE_POPUP: case WLR_XDG_SURFACE_ROLE_POPUP:
if (!xdg_surface->popup->parent) if (!xdg_surface->popup->parent)
return NULL; return -1;
else if (!wlr_surface_is_xdg_surface(xdg_surface->popup->parent)) else if (!wlr_surface_is_xdg_surface(xdg_surface->popup->parent))
return toplevel_from_wlr_surface(xdg_surface->popup->parent); return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl);
xdg_surface = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent); xdg_surface = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent);
break; break;
case WLR_XDG_SURFACE_ROLE_TOPLEVEL: case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
return xdg_surface->data; c = xdg_surface->data;
type = c->type;
goto end;
case WLR_XDG_SURFACE_ROLE_NONE: case WLR_XDG_SURFACE_ROLE_NONE:
return NULL; return -1;
} }
} }
} }
return NULL; end:
if (pl)
*pl = l;
if (pc)
*pc = c;
return type;
} }
/* The others */ /* The others */
@ -169,14 +185,15 @@ client_get_geometry(Client *c, struct wlr_box *geom)
static inline Client * static inline Client *
client_get_parent(Client *c) client_get_parent(Client *c)
{ {
Client *p = NULL;
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c) && c->surface.xwayland->parent) if (client_is_x11(c) && c->surface.xwayland->parent)
return toplevel_from_wlr_surface(c->surface.xwayland->parent->surface); toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL);
#endif #endif
if (c->surface.xdg->toplevel->parent) if (c->surface.xdg->toplevel->parent)
return toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface); toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
return NULL; return p;
} }
static inline const char * static inline const char *

47
dwl.c
View file

@ -904,22 +904,21 @@ createnotify(struct wl_listener *listener, void *data)
* If you want to do something tricky with popups you should check if * If you want to do something tricky with popups you should check if
* its parent is wlr_xdg_shell or wlr_layer_shell */ * its parent is wlr_xdg_shell or wlr_layer_shell */
struct wlr_xdg_surface *xdg_surface = data; struct wlr_xdg_surface *xdg_surface = data;
Client *c; Client *c = NULL;
LayerSurface *l = NULL;
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
struct wlr_box box; struct wlr_box box;
LayerSurface *l = toplevel_from_wlr_surface(xdg_surface->surface); int type = toplevel_from_wlr_surface(xdg_surface->surface, &c, &l);
if (!xdg_surface->popup->parent) if (!xdg_surface->popup->parent)
return; return;
xdg_surface->surface->data = wlr_scene_xdg_surface_create( xdg_surface->surface->data = wlr_scene_xdg_surface_create(
xdg_surface->popup->parent->data, xdg_surface); xdg_surface->popup->parent->data, xdg_surface);
/* Probably the check of `l` is useless, the only thing that can be NULL if ((!l || !l->mon) || (!c || !c->mon))
* is its monitor */
if (!l || !l->mon)
return; return;
box = l->type == LayerShell ? l->mon->m : l->mon->w; box = type == LayerShell ? l->mon->m : c->mon->w;
box.x -= l->geom.x; box.x -= (type == LayerShell ? l->geom.x : c->geom.x);
box.y -= l->geom.y; box.y -= (type == LayerShell ? l->geom.y : c->geom.y);
wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box); wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box);
return; return;
} else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE) } else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE)
@ -1096,14 +1095,11 @@ focusclient(Client *c, int lift)
/* If an overlay is focused, don't focus or activate the client, /* If an overlay is focused, don't focus or activate the client,
* but only update its position in fstack to render its border with focuscolor * but only update its position in fstack to render its border with focuscolor
* and focus it after the overlay is closed. */ * and focus it after the overlay is closed. */
Client *w = toplevel_from_wlr_surface(old); Client *w = NULL;
if (wlr_surface_is_layer_surface(old)) { LayerSurface *l = NULL;
struct wlr_layer_surface_v1 *wlr_layer_surface = int type = toplevel_from_wlr_surface(old, &w, &l);
wlr_layer_surface_v1_from_wlr_surface(old); if (type == LayerShell && l->scene->node.enabled
&& l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
if (wlr_layer_surface && ((LayerSurface *)wlr_layer_surface->data)->mapped
&& (wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP
|| wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY))
return; return;
} else if (w && w == exclusive_focus && client_wants_focus(w)) { } else if (w && w == exclusive_focus && client_wants_focus(w)) {
return; return;
@ -1438,8 +1434,9 @@ void
motionnotify(uint32_t time) motionnotify(uint32_t time)
{ {
double sx = 0, sy = 0; double sx = 0, sy = 0;
Client *c = NULL; Client *c = NULL, *w = NULL;
LayerSurface *l; LayerSurface *l = NULL;
int type;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
struct wlr_drag_icon *icon; struct wlr_drag_icon *icon;
@ -1472,11 +1469,12 @@ motionnotify(uint32_t time)
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy); xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
if (cursor_mode == CurPressed && !seat->drag) { if (cursor_mode == CurPressed && !seat->drag) {
if ((l = toplevel_from_wlr_surface( if ((type = toplevel_from_wlr_surface(
seat->pointer_state.focused_surface))) { seat->pointer_state.focused_surface, &w, &l)) >= 0) {
c = w;
surface = seat->pointer_state.focused_surface; surface = seat->pointer_state.focused_surface;
sx = cursor->x - l->geom.x; sx = cursor->x - (type == LayerShell ? l->geom.x : w->geom.x);
sy = cursor->y - l->geom.y; sy = cursor->y - (type == LayerShell ? l->geom.y : w->geom.y);
} }
} }
@ -2357,8 +2355,9 @@ void
urgent(struct wl_listener *listener, void *data) urgent(struct wl_listener *listener, void *data)
{ {
struct wlr_xdg_activation_v1_request_activate_event *event = data; struct wlr_xdg_activation_v1_request_activate_event *event = data;
Client *c = toplevel_from_wlr_surface(event->surface); Client *c = NULL;
if (c && c->type != LayerShell && c != selclient()) { int type = toplevel_from_wlr_surface(event->surface, &c, NULL);
if (type >= 0 && type != LayerShell && c != selclient()) {
c->isurgent = 1; c->isurgent = 1;
printstatus(); printstatus();
} }