2 * ion/ioncore/stacking.c
4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
10 #include <libtu/minmax.h>
16 #include "sizepolicy.h"
22 WStacking *create_stacking()
24 WStacking *st=ALLOC(WStacking);
30 st->szplcy=SIZEPOLICY_DEFAULT;
33 st->pseudomodal=FALSE;
40 void stacking_free(WStacking *st)
42 assert(st->mgr_next==NULL && st->mgr_prev==NULL &&
43 st->next==NULL && st->prev==NULL &&
44 /*st->above==NULL &&*/
58 static Rb_node stacking_of_reg=NULL;
61 WStacking *ioncore_find_stacking(WRegion *reg)
66 if(stacking_of_reg!=NULL)
67 node=rb_find_pkey_n(stacking_of_reg, reg, &found);
69 return (found ? (WStacking*)node->v.val : NULL);
73 void stacking_unassoc(WStacking *st)
81 if(stacking_of_reg!=NULL)
82 node=rb_find_pkey_n(stacking_of_reg, st->reg, &found);
91 bool stacking_assoc(WStacking *st, WRegion *reg)
93 assert(st->reg==NULL);
95 if(stacking_of_reg==NULL){
96 stacking_of_reg=make_rb();
97 if(stacking_of_reg==NULL)
101 if(rb_insertp(stacking_of_reg, reg, st)==NULL)
113 /*{{{ List processing */
116 static WStacking *link_lists(WStacking *l1, WStacking *l2)
118 /* As everywhere, doubly-linked lists without the forward
121 WStacking *tmp=l2->prev;
129 static WStacking *link_list_before(WStacking *l1,
136 return link_lists(l2, l1);
148 static WStacking *link_list_after(WStacking *l1,
155 return link_lists(l1, l2);
157 i1->next->prev=l2->prev;
158 l2->prev->next=i1->next;
166 WStacking *stacking_unstack(WWindow *par, WStacking *regst)
168 WStacking *nxt=NULL, *st;
172 UNLINK_ITEM(par->stacking, regst, next, prev);
175 for(st=par->stacking; st!=NULL; st=st->next){
176 if(st->above==regst){
186 if(regst->above==NULL)
193 static bool cf(WStackingFilter *filt, void *filt_data, WStacking *st)
195 return (filt==NULL || filt(st, filt_data));
199 static bool check_unweave(WStacking *st)
201 /* 2: unknown, 1: yes, 0: no */
203 if(st->to_unweave==2){
205 st->to_unweave=check_unweave(st->above);
210 return st->to_unweave;
214 WStacking *stacking_unweave(WStacking **stacking,
215 WStackingFilter *filt, void *filt_data)
218 WStacking *st, *next;
220 for(st=*stacking; st!=NULL; st=st->next){
222 if(st->above==NULL && cf(filt, filt_data, st))
226 for(st=*stacking; st!=NULL; st=st->next)
229 for(st=*stacking; st!=NULL; st=next){
231 if(st->to_unweave==1){
232 UNLINK_ITEM(*stacking, st, next, prev);
233 LINK_ITEM(np, st, next, prev);
241 static int check_above_lvl(WStacking *st)
245 st->level=check_above_lvl(st->above);
250 static void enforce_level_sanity(WStacking **np)
254 /* Make sure that the levels of stuff stacked 'above' match
255 * the level of the thing stacked above.
257 for(st=*np; st!=NULL; st=st->next)
260 /* And now make sure things are ordered by levels. */
262 while(st->next!=NULL){
263 if(st->next->level < st->level){
264 WStacking *st2=st->next;
265 UNLINK_ITEM(*np, st2, next, prev);
266 LINK_ITEM_BEFORE(*np, st2, st, next, prev);
276 static void get_bottom(WStacking *st, Window fb_win,
277 Window *other, int *mode)
279 Window bottom=None, top=None;
283 region_stacking(st->reg, &bottom, &top);
298 static void stacking_do_weave(WStacking **stacking, WStacking **np,
299 bool below, Window fb_win)
309 /* Should do nothing.. */
310 enforce_level_sanity(np);
318 if(ab->level>lvl || (below && ab->level==lvl))
322 get_bottom(ab, fb_win, &other, &mode);
326 UNLINK_ITEM(*np, st, next, prev);
328 region_restack(st->reg, other, mode);
331 LINK_ITEM_BEFORE(*stacking, ab, st, next, prev);
333 LINK_ITEM_LAST(*stacking, st, next, prev);
339 void stacking_weave(WStacking **stacking, WStacking **np, bool below)
341 stacking_do_weave(stacking, np, below, None);
351 static bool is_above(WStacking *st, WStacking *p)
355 else if(st->above==p)
358 return is_above(st->above, p);
362 static void collect_first(WStacking **dst, WStacking **src, WStacking *st)
364 UNLINK_ITEM(*src, st, next, prev);
365 LINK_ITEM_FIRST(*dst, st, next, prev);
369 static void collect_last(WStacking **dst, WStacking **src, WStacking *st)
371 UNLINK_ITEM(*src, st, next, prev);
372 LINK_ITEM_LAST(*dst, st, next, prev);
376 static void collect_above(WStacking **dst, WStacking **src, WStacking *regst)
378 WStacking *stabove, *stnext;
380 for(stabove=*src; stabove!=NULL; stabove=stnext){
381 stnext=stabove->next;
383 if(is_above(stabove, regst))
384 collect_last(dst, src, stabove);
389 static WStacking *unweave_subtree(WStacking **stacking, WStacking *regst,
397 collect_first(&tmp, stacking, st);
401 collect_first(&tmp, stacking, regst);
404 collect_above(&tmp, stacking, regst);
410 void stacking_restack(WStacking **stacking, WStacking *st, Window fb_win,
411 WStackingFilter *filt, void *filt_data, bool lower)
413 WStacking *tmp=unweave_subtree(stacking, st, lower);
415 stacking_do_weave(stacking, &tmp, lower, fb_win);
424 /*{{{ Stacking lists */
427 WStacking **window_get_stackingp(WWindow *wwin)
429 return &(wwin->stacking);
433 WStacking *window_get_stacking(WWindow *wwin)
435 return wwin->stacking;
442 /*{{{ Stacking list iteration */
445 void stacking_iter_init(WStackingIterTmp *tmp,
447 WStackingFilter *filt,
452 tmp->filt_data=filt_data;
456 WStacking *stacking_iter_nodes(WStackingIterTmp *tmp)
458 WStacking *next=NULL;
460 while(tmp->st!=NULL){
462 tmp->st=tmp->st->next;
463 if(cf(tmp->filt, tmp->filt_data, next))
472 WRegion *stacking_iter(WStackingIterTmp *tmp)
474 WStacking *st=stacking_iter_nodes(tmp);
475 return (st!=NULL ? st->reg : NULL);
479 void stacking_iter_mgr_init(WStackingIterTmp *tmp,
481 WStackingFilter *filt,
486 tmp->filt_data=filt_data;
490 WStacking *stacking_iter_mgr_nodes(WStackingIterTmp *tmp)
492 WStacking *next=NULL;
494 while(tmp->st!=NULL){
496 tmp->st=tmp->st->mgr_next;
497 if(cf(tmp->filt, tmp->filt_data, next))
506 WRegion *stacking_iter_mgr(WStackingIterTmp *tmp)
508 WStacking *st=stacking_iter_mgr_nodes(tmp);
509 return (st!=NULL ? st->reg : NULL);
519 uint stacking_min_level(WStacking *stacking,
520 WStackingFilter *include_filt,
523 uint min_level=STACKING_LEVEL_BOTTOM;
527 return STACKING_LEVEL_BOTTOM;
534 && !(st->reg->flags®ION_SKIP_FOCUS)
535 && cf(include_filt, filt_data, st)){
537 if(st->level>=STACKING_LEVEL_MODAL1)
542 }while(st!=stacking);
548 WStacking *stacking_find_to_focus(WStacking *stacking,
550 WStackingFilter *include_filt,
551 WStackingFilter *approve_filt,
554 uint min_level=STACKING_LEVEL_BOTTOM;
567 if(st!=to_try && (st->reg->flags®ION_SKIP_FOCUS ||
568 !cf(include_filt, filt_data, st))){
573 if(st->level<min_level)
576 if(st==to_try || cf(approve_filt, filt_data, st))
579 if(st->level>=STACKING_LEVEL_MODAL1)
580 min_level=maxof(min_level, st->level);
581 }while(st!=stacking);
587 static bool mapped_filt(WStacking *st, void *unused)
589 return (st->reg!=NULL && REGION_IS_MAPPED(st->reg));
593 static bool mgr_filt(WStacking *st, void *mgr_)
595 return (st->reg!=NULL && REGION_MANAGER(st->reg)==(WRegion*)mgr_);
599 WStacking *stacking_find_to_focus_mapped(WStacking *stacking,
604 return stacking_find_to_focus(stacking, to_try, mapped_filt,
607 return stacking_find_to_focus(stacking, to_try, mapped_filt,
613 uint stacking_min_level_mapped(WStacking *stacking)
615 return stacking_min_level(stacking, mapped_filt, NULL);