WINGs/wview_wl: prevent re-entrant wl_redisplay from wl_map
When a panel's createWidgets callback maps child widgets, each WMMapWidget triggered wl_redisplay which sent expose events. Those expose handlers could create/destroy more widgets, causing re-entrant modification of the view tree during iteration — segfault. Fix: track wl_redisplay call depth. wl_map only triggers wl_redisplay when depth==0 (not already inside a redisplay). Child views mapped during a redisplay cycle will be painted by the parent's recursive child iteration instead. Also save nextSister before recursing into children to handle list modifications during iteration.
This commit is contained in:
parent
8d77acc349
commit
50bc0d35aa
|
|
@ -261,11 +261,13 @@ static void wl_lower(void *vctx, W_View *view)
|
|||
|
||||
static void wl_map_subviews(void *vctx, W_View *view);
|
||||
|
||||
static int wl_redisplay_depth = 0;
|
||||
|
||||
static void wl_map(void *vctx, W_View *view)
|
||||
{
|
||||
(void)vctx;
|
||||
view->flags.mapped = 1;
|
||||
if (view->flags.realized) {
|
||||
if (view->flags.realized && wl_redisplay_depth == 0) {
|
||||
wl_redisplay(vctx, view);
|
||||
}
|
||||
}
|
||||
|
|
@ -387,6 +389,8 @@ static void wl_redisplay(void *vctx, W_View *view)
|
|||
if (!view->flags.mapped || view->flags.alreadyDead)
|
||||
return;
|
||||
|
||||
wl_redisplay_depth++;
|
||||
|
||||
/* Fill background color */
|
||||
pixman_image_t *backing = (pixman_image_t *)W_GetViewBacking(view->window);
|
||||
if (backing && view->backColor) {
|
||||
|
|
@ -417,10 +421,11 @@ static void wl_redisplay(void *vctx, W_View *view)
|
|||
/* Re-composite all mapped children into this view's backing */
|
||||
W_View *child = view->childrenList;
|
||||
while (child) {
|
||||
W_View *next = child->nextSister;
|
||||
if (child->flags.mapped && child->flags.realized && !child->flags.alreadyDead) {
|
||||
wl_redisplay(vctx, child);
|
||||
}
|
||||
child = child->nextSister;
|
||||
child = next;
|
||||
}
|
||||
|
||||
/* Composite this view's backing into its parent's backing */
|
||||
|
|
@ -444,6 +449,8 @@ static void wl_redisplay(void *vctx, W_View *view)
|
|||
extern void (*W_ViewCommitBackingFn)(unsigned long id);
|
||||
if (W_ViewCommitBackingFn)
|
||||
W_ViewCommitBackingFn((unsigned long)top->window);
|
||||
|
||||
wl_redisplay_depth--;
|
||||
}
|
||||
|
||||
/* Find the deepest child view at (x, y) relative to the given view. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue