-
Notifications
You must be signed in to change notification settings - Fork 666
Description
There's a issue when you set a window hidden (either manually set its NK_WINDOW_HIDDEN flag or do nk_window_show() ), it will only be hidden only for a period, only then to be reinitialized, which defeats the purpose of hiding and it being a flag in the first place
So this line of code in nk_clear function (defined in nuklear_context.c, is called everytime you render a frame)
Lines 137 to 147 in a329721
| /* remove hotness from hidden or closed windows*/ | |
| if (((iter->flags & NK_WINDOW_HIDDEN) || | |
| (iter->flags & NK_WINDOW_CLOSED)) && | |
| iter == ctx->active) { | |
| ctx->active = iter->prev; | |
| ctx->end = iter->prev; | |
| if (!ctx->end) | |
| ctx->begin = 0; | |
| if (ctx->active) | |
| ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM; | |
| } |
(do cleanups for 'active' window that isn't really active)
specifically the line
ctx->begin = 0; (reset the start pointer of a linked list of windows)the problem here is it assumes that the hidden window isn't at the 'ctx->begin' (where the 'win->prev' doesnt exist), which isn't always the case, but it set to that anyway without checking
then it choose the window before the hidden one, which may not exist, so it trigger the code and make Nuklear completely forget the window list,
and what worse is that the forgotten window (and the ones after it) won't be freed from memory by the later section of the code since its win->seq (I guess this is like its heartbeat) is valid with the ctx's
Lines 165 to 171 in a329721
| /* window itself is not used anymore so free */ | |
| if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { | |
| next = iter->next; | |
| nk_remove_window(ctx, iter); | |
| nk_free_window(ctx, iter); | |
| iter = next; | |
| } else iter = iter->next; |
since the reference is gone, the windows will live in the memory with the program, causing memory leak (thank you sleeptightAnsiC for clearing)
and in the next frame, nk_begin (how you start to draw things) can't find the existing window you're talkiing about (since the list reference is gone) so it will create new one with your spec, that means your hidden window is now reseted and live somewhere else in the memory, and when it's hidden and its 'win->prev' gets invalid (due to some internal reorder for Z indexing or something), that cleanup code (for invalid active window) will be triggered, now you're stuck in a loop where you hide window just to see it popup again
Solution?
because i have no idea how do you edit someone's code on github, i've some suggestions:
-
nk_window_show()should clearctx->activeif it is the target window about to be hidden -
maybe 'nk_end' should clearctx->activeby default? -
nk_clearshould have some more considerations before doingctx->begin = 0;, and free the unused -
or use other approach on finding active window (I have a example code in comment)
-
automatically set
ctx->activeto0if current is hidden and letnk_beginin the next frame handles it?
(this is my first time doing this, im sorry for any mistakes or English errors, thank!)