2 * ion/ioncore/stacking.c
4 * Copyright (c) Tuomo Valkonen 1999-2006.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
18 #include "sizepolicy.h"
24 WStacking *create_stacking()
26 WStacking *st=ALLOC(WStacking);
32 st->szplcy=SIZEPOLICY_DEFAULT;
41 void stacking_free(WStacking *st)
43 assert(st->mgr_next==NULL && st->mgr_prev==NULL &&
44 st->next==NULL && st->prev==NULL &&
45 /*st->above==NULL &&*/
59 static Rb_node stacking_of_reg=NULL;
62 WStacking *ioncore_find_stacking(WRegion *reg)
67 if(stacking_of_reg!=NULL)
68 node=rb_find_pkey_n(stacking_of_reg, reg, &found);
70 return (found ? (WStacking*)node->v.val : NULL);
74 void stacking_unassoc(WStacking *st)
82 if(stacking_of_reg!=NULL)
83 node=rb_find_pkey_n(stacking_of_reg, st->reg, &found);
92 bool stacking_assoc(WStacking *st, WRegion *reg)
94 assert(st->reg==NULL);
96 if(stacking_of_reg==NULL){
97 stacking_of_reg=make_rb();
98 if(stacking_of_reg==NULL)
102 if(rb_insertp(stacking_of_reg, reg, st)==NULL)
114 /*{{{ List processing */
117 static WStacking *link_lists(WStacking *l1, WStacking *l2)
119 /* As everywhere, doubly-linked lists without the forward
122 WStacking *tmp=l2->prev;
130 static WStacking *link_list_before(WStacking *l1,
137 return link_lists(l2, l1);
149 static WStacking *link_list_after(WStacking *l1,
156 return link_lists(l1, l2);
158 i1->next->prev=l2->prev;
159 l2->prev->next=i1->next;
167 WStacking *stacking_unstack(WWindow *par, WStacking *regst)
169 WStacking *nxt=NULL, *st;
173 UNLINK_ITEM(par->stacking, regst, next, prev);
176 for(st=par->stacking; st!=NULL; st=st->next){
177 if(st->above==regst){
187 if(regst->above==NULL)
194 static bool cf(WStackingFilter *filt, void *filt_data, WStacking *st)
196 return (filt==NULL || filt(st, filt_data));
200 static bool check_unweave(WStacking *st)
202 /* 2: unknown, 1: yes, 0: no */
204 if(st->to_unweave==2){
206 st->to_unweave=check_unweave(st->above);
211 return st->to_unweave;
215 WStacking *stacking_unweave(WStacking **stacking,
216 WStackingFilter *filt, void *filt_data)
219 WStacking *st, *next;
221 for(st=*stacking; st!=NULL; st=st->next){
223 if(st->above==NULL && cf(filt, filt_data, st))
227 for(st=*stacking; st!=NULL; st=st->next)
230 for(st=*stacking; st!=NULL; st=next){
232 if(st->to_unweave==1){
233 UNLINK_ITEM(*stacking, st, next, prev);
234 LINK_ITEM(np, st, next, prev);
242 static int check_above_lvl(WStacking *st)
246 st->level=check_above_lvl(st->above);
251 static void enforce_level_sanity(WStacking **np)
255 /* Make sure that the levels of stuff stacked 'above' match
256 * the level of the thing stacked above.
258 for(st=*np; st!=NULL; st=st->next)
261 /* And now make sure things are ordered by levels. */
263 while(st->next!=NULL){
264 if(st->next->level < st->level){
265 WStacking *st2=st->next;
266 UNLINK_ITEM(*np, st2, next, prev);
267 LINK_ITEM_BEFORE(*np, st2, st, next, prev);
277 static void get_bottom(WStacking *st, Window fb_win,
278 Window *other, int *mode)
280 Window bottom=None, top=None;
284 region_stacking(st->reg, &bottom, &top);
299 static void stacking_do_weave(WStacking **stacking, WStacking **np,
300 bool below, Window fb_win)
310 /* Should do nothing.. */
311 enforce_level_sanity(np);
319 if(ab->level>lvl || (below && ab->level==lvl))
323 get_bottom(ab, fb_win, &other, &mode);
327 UNLINK_ITEM(*np, st, next, prev);
329 region_restack(st->reg, other, mode);
332 LINK_ITEM_BEFORE(*stacking, ab, st, next, prev);
334 LINK_ITEM_LAST(*stacking, st, next, prev);
340 void stacking_weave(WStacking **stacking, WStacking **np, bool below)
342 stacking_do_weave(stacking, np, below, None);
352 static bool is_above(WStacking *st, WStacking *p)
356 else if(st->above==p)
359 return is_above(st->above, p);
363 static void collect_first(WStacking **dst, WStacking **src, WStacking *st)
365 UNLINK_ITEM(*src, st, next, prev);
366 LINK_ITEM_FIRST(*dst, st, next, prev);
370 static void collect_last(WStacking **dst, WStacking **src, WStacking *st)
372 UNLINK_ITEM(*src, st, next, prev);
373 LINK_ITEM_LAST(*dst, st, next, prev);
377 static void collect_above(WStacking **dst, WStacking **src, WStacking *regst)
379 WStacking *stabove, *stnext;
381 for(stabove=*src; stabove!=NULL; stabove=stnext){
382 stnext=stabove->next;
384 if(is_above(stabove, regst))
385 collect_last(dst, src, stabove);
390 static WStacking *unweave_subtree(WStacking **stacking, WStacking *regst,
398 collect_first(&tmp, stacking, st);
402 collect_first(&tmp, stacking, regst);
405 collect_above(&tmp, stacking, regst);
411 void stacking_restack(WStacking **stacking, WStacking *st, Window fb_win,
412 WStackingFilter *filt, void *filt_data, bool lower)
414 WStacking *tmp=unweave_subtree(stacking, st, lower);
416 stacking_do_weave(stacking, &tmp, lower, fb_win);
425 /*{{{ Stacking lists */
428 WStacking **window_get_stackingp(WWindow *wwin)
430 return &(wwin->stacking);
434 WStacking *window_get_stacking(WWindow *wwin)
436 return wwin->stacking;
443 /*{{{ Stacking list iteration */
446 void stacking_iter_init(WStackingIterTmp *tmp,
448 WStackingFilter *filt,
453 tmp->filt_data=filt_data;
457 WStacking *stacking_iter_nodes(WStackingIterTmp *tmp)
459 WStacking *next=NULL;
461 while(tmp->st!=NULL){
463 tmp->st=tmp->st->next;
464 if(cf(tmp->filt, tmp->filt_data, next))
473 WRegion *stacking_iter(WStackingIterTmp *tmp)
475 WStacking *st=stacking_iter_nodes(tmp);
476 return (st!=NULL ? st->reg : NULL);
480 void stacking_iter_mgr_init(WStackingIterTmp *tmp,
482 WStackingFilter *filt,
487 tmp->filt_data=filt_data;
491 WStacking *stacking_iter_mgr_nodes(WStackingIterTmp *tmp)
493 WStacking *next=NULL;
495 while(tmp->st!=NULL){
497 tmp->st=tmp->st->mgr_next;
498 if(cf(tmp->filt, tmp->filt_data, next))
507 WRegion *stacking_iter_mgr(WStackingIterTmp *tmp)
509 WStacking *st=stacking_iter_mgr_nodes(tmp);
510 return (st!=NULL ? st->reg : NULL);
520 uint stacking_min_level(WStacking *stacking,
521 WStackingFilter *include_filt,
528 return STACKING_LEVEL_BOTTOM;
535 && !(st->reg->flags®ION_SKIP_FOCUS)
536 && cf(include_filt, filt_data, st)){
538 if(st->level>=STACKING_LEVEL_MODAL1)
543 }while(st!=stacking);
549 WStacking *stacking_find_to_focus(WStacking *stacking, WStacking *to_try,
550 WStackingFilter *include_filt,
551 WStackingFilter *approve_filt,
560 min_level=stacking_min_level(stacking, include_filt, filt_data);
562 if(to_try!=NULL && to_try->level>=min_level)
569 if(st->level<min_level)
573 && !(st->reg->flags®ION_SKIP_FOCUS)
574 && cf(include_filt, filt_data, st)
575 && cf(approve_filt, filt_data, st)){
578 }while(st!=stacking);
584 static bool mapped_filt(WStacking *st, void *unused)
586 return (st->reg!=NULL && REGION_IS_MAPPED(st->reg));
590 static bool mgr_filt(WStacking *st, void *mgr_)
592 return (st->reg!=NULL && REGION_MANAGER(st->reg)==(WRegion*)mgr_);
596 WStacking *stacking_find_to_focus_mapped(WStacking *stacking,
601 return stacking_find_to_focus(stacking, to_try, mapped_filt,
604 return stacking_find_to_focus(stacking, to_try, mapped_filt,
610 uint stacking_min_level_mapped(WStacking *stacking)
612 return stacking_min_level(stacking, mapped_filt, NULL);