win: keep a `prev` pointer
Save us some iteration when updating the window stack Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
a68903b9ef
commit
166ec55778
|
@ -666,31 +666,27 @@ static void restack_win(session_t *ps, win *w, xcb_window_t new_above) {
|
|||
rc_region_unref(&w->next->reg_ignore);
|
||||
}
|
||||
|
||||
win **prev = NULL, **prev_old = NULL;
|
||||
win **prev = NULL, *tmp_w;
|
||||
HASH_FIND_INT(ps->windows, &new_above, tmp_w);
|
||||
|
||||
bool found = false;
|
||||
for (prev = &ps->window_stack; *prev; prev = &(*prev)->next) {
|
||||
if ((*prev)->id == new_above && (*prev)->state != WSTATE_DESTROYING) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_above && !found) {
|
||||
if (new_above && !tmp_w) {
|
||||
log_error("(%#010x, %#010x): Failed to found new above window.",
|
||||
w->id, new_above);
|
||||
return;
|
||||
}
|
||||
|
||||
for (prev_old = &ps->window_stack; *prev_old; prev_old = &(*prev_old)->next) {
|
||||
if ((*prev_old) == w) {
|
||||
break;
|
||||
}
|
||||
prev = tmp_w->prev;
|
||||
// Unlink from old position
|
||||
*w->prev = w->next;
|
||||
if (w->next) {
|
||||
w->next->prev = w->prev;
|
||||
}
|
||||
|
||||
*prev_old = w->next;
|
||||
// Link to new position
|
||||
w->next = *prev;
|
||||
*prev = w;
|
||||
if (w->next) {
|
||||
w->next->prev = &w->next;
|
||||
}
|
||||
w->prev = prev;
|
||||
*w->prev = w;
|
||||
|
||||
// add damage for this window
|
||||
add_damage_from_win(ps, w);
|
||||
|
@ -2132,8 +2128,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
|||
|
||||
free(reply);
|
||||
log_trace("Initial stack:");
|
||||
for (win *c = ps->window_stack; c; c = c->next) {
|
||||
log_trace("%#010x \"%s\"", c->id, c->name);
|
||||
WIN_STACK_ITER(ps, w) {
|
||||
log_trace("%#010x \"%s\"", w->id, w->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
51
src/win.c
51
src/win.c
|
@ -57,7 +57,7 @@
|
|||
* Clear leader cache of all windows.
|
||||
*/
|
||||
static inline void clear_cache_win_leaders(session_t *ps) {
|
||||
for (win *w = ps->window_stack; w; w = w->next) {
|
||||
WIN_STACK_ITER(ps, w) {
|
||||
w->cache_leader = XCB_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -1027,14 +1027,18 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
|
|||
// Find window insertion point
|
||||
win **p = NULL;
|
||||
if (prev) {
|
||||
for (p = &ps->window_stack; *p; p = &(*p)->next) {
|
||||
if ((*p)->id == prev && (*p)->state != WSTATE_DESTROYING)
|
||||
break;
|
||||
}
|
||||
win *w = NULL;
|
||||
HASH_FIND_INT(ps->windows, &prev, w);
|
||||
assert(w);
|
||||
p = w->prev;
|
||||
} else {
|
||||
p = &ps->window_stack;
|
||||
}
|
||||
new->next = *p;
|
||||
if (new->next) {
|
||||
new->next->prev = &new->next;
|
||||
}
|
||||
new->prev = p;
|
||||
*p = new;
|
||||
HASH_ADD_INT(ps->windows, id, new);
|
||||
|
||||
|
@ -1466,7 +1470,6 @@ static void finish_unmap_win(session_t *ps, win **_w) {
|
|||
|
||||
static void finish_destroy_win(session_t *ps, win **_w) {
|
||||
win *w = *_w;
|
||||
win **prev = NULL;
|
||||
|
||||
if (w->state != WSTATE_UNMAPPED) {
|
||||
// Only UNMAPPED state has window resources freed, otherwise
|
||||
|
@ -1487,30 +1490,28 @@ static void finish_destroy_win(session_t *ps, win **_w) {
|
|||
}
|
||||
|
||||
log_trace("Trying to destroy (%#010x)", w->id);
|
||||
for (prev = &ps->window_stack; *prev; prev = &(*prev)->next) {
|
||||
if (w == *prev) {
|
||||
log_trace("Found (%#010x \"%s\")", w->id, w->name);
|
||||
*prev = w->next;
|
||||
*w->prev = w->next;
|
||||
if (w->next) {
|
||||
w->next->prev = w->prev;
|
||||
}
|
||||
|
||||
if (w == ps->active_win) {
|
||||
ps->active_win = NULL;
|
||||
}
|
||||
if (w == ps->active_win) {
|
||||
ps->active_win = NULL;
|
||||
}
|
||||
|
||||
free_win_res(ps, w);
|
||||
free_win_res(ps, w);
|
||||
|
||||
// Drop w from all prev_trans to avoid accessing freed memory in
|
||||
// repair_win()
|
||||
// TODO there can only be one prev_trans pointing to w
|
||||
for (win *w2 = ps->window_stack; w2; w2 = w2->next) {
|
||||
if (w == w2->prev_trans) {
|
||||
w2->prev_trans = NULL;
|
||||
}
|
||||
}
|
||||
free(w);
|
||||
*_w = NULL;
|
||||
return;
|
||||
// Drop w from all prev_trans to avoid accessing freed memory in
|
||||
// repair_win()
|
||||
// TODO there can only be one prev_trans pointing to w
|
||||
WIN_STACK_ITER(ps, w2) {
|
||||
if (w == w2->prev_trans) {
|
||||
w2->prev_trans = NULL;
|
||||
}
|
||||
}
|
||||
free(w);
|
||||
*_w = NULL;
|
||||
return;
|
||||
log_warn("Destroyed window is not in window list");
|
||||
assert(false);
|
||||
}
|
||||
|
|
|
@ -137,6 +137,8 @@ struct win {
|
|||
void *shadow_image;
|
||||
/// Pointer to the next lower window in window stack.
|
||||
win *next;
|
||||
/// Pointer to a linked-list pointer that points to this window.
|
||||
win **prev;
|
||||
/// Pointer to the next higher window to paint.
|
||||
win *prev_trans;
|
||||
// TODO rethink reg_ignore
|
||||
|
|
Loading…
Reference in New Issue