2 * ion/ioncore/mplexpholder.c
4 * Copyright (c) Tuomo Valkonen 2005-2009.
6 * See the included file LICENSE for details.
9 #include <libtu/objp.h>
10 #include <libtu/obj.h>
11 #include <libtu/pointer.h>
12 #include <libmainloop/defer.h>
16 #include "mplexpholder.h"
18 #include "framedpholder.h"
19 #include "basicpholder.h"
25 static bool on_ph_list(WMPlexPHolder
*ll
, WMPlexPHolder
*ph
)
27 return ph
->prev
!=NULL
;
31 static void mplexpholder_do_link(WMPlexPHolder
*ph
,
36 assert(mplex
==ph
->mplex
&& mplex
!=NULL
);
39 assert(after
->after
==or_after
);
41 if(after
->after
!=NULL
){
42 LINK_ITEM_AFTER(after
->after
->phs
, after
, ph
, next
, prev
);
44 assert(on_ph_list(mplex
->misc_phs
, after
));
45 LINK_ITEM_AFTER(mplex
->misc_phs
, after
, ph
, next
, prev
);
47 ph
->after
=after
->after
;
48 }else if(or_after
!=NULL
){
49 LINK_ITEM_FIRST(or_after
->phs
, ph
, next
, prev
);
52 LINK_ITEM_FIRST(mplex
->misc_phs
, ph
, next
, prev
);
58 static WMPlexPHolder
*get_head(WMPlexPHolder
*ph
)
61 /* ph->prev==NULL should not happen.. */
62 if(ph
->prev
==NULL
|| ph
->prev
->next
==NULL
)
71 void mplexpholder_do_unlink(WMPlexPHolder
*ph
, WMPlex
*mplex
)
73 if(ph
->recreate_pholder
!=NULL
){
75 ph
->next
->recreate_pholder
=ph
->recreate_pholder
;
77 /* It might be in use in attach chain! So defer. */
78 mainloop_defer_destroy((Obj
*)ph
->recreate_pholder
);
80 ph
->recreate_pholder
=NULL
;
84 UNLINK_ITEM(ph
->after
->phs
, ph
, next
, prev
);
85 }else if(mplex
!=NULL
&& on_ph_list(mplex
->misc_phs
, ph
)){
86 UNLINK_ITEM(mplex
->misc_phs
, ph
, next
, prev
);
87 }else if(ph
->prev
!=NULL
){
88 WMPlexPHolder
*next
=ph
->next
;
94 assert(next
->prev
==ph
);
98 /* ph should not be on a list, if prev pointer is NULL (whereas
99 * next alone can be NULL in our semi-doubly-linked lists).
101 assert(ph
->next
==NULL
);
116 static void mplex_get_attach_params(WMPlex
*mplex
, WStacking
*st
,
117 WMPlexAttachParams
*param
)
119 param
->flags
=(MPLEX_ATTACH_SIZEPOLICY
|
122 (st
->hidden
? MPLEX_ATTACH_HIDDEN
: 0)|
123 (st
->lnode
==NULL
? MPLEX_ATTACH_UNNUMBERED
: 0));
124 param
->szplcy
=st
->szplcy
;
125 param
->geom
=REGION_GEOM(st
->reg
);
126 param
->level
=st
->level
;
130 bool mplexpholder_init(WMPlexPHolder
*ph
, WMPlex
*mplex
, WStacking
*st
,
131 WMPlexAttachParams
*param
)
133 WLListNode
*or_after
=NULL
;
134 WMPlexPHolder
*after
=NULL
;
136 pholder_init(&(ph
->ph
));
143 ph
->recreate_pholder
=NULL
;
146 mplex_get_attach_params(mplex
, st
, &ph
->param
);
149 after
=LIST_LAST(st
->lnode
->phs
, next
, prev
);
153 static WMPlexAttachParams dummy_param
={0, 0, {0, 0, 0, 0}, 0, 0};
160 if(!(param
->flags
&MPLEX_ATTACH_UNNUMBERED
)){
161 int index
=(param
->flags
&MPLEX_ATTACH_INDEX
163 : mplex_default_index(mplex
));
164 or_after
=llist_index_to_after(mplex
->mx_list
,
165 mplex
->mx_current
, index
);
166 after
=(index
==LLIST_INDEX_LAST
168 ? LIST_LAST(or_after
->phs
, next
, prev
)
169 : LIST_LAST(mplex
->misc_phs
, next
, prev
))
174 mplexpholder_do_link(ph
, mplex
, after
, or_after
);
180 WMPlexPHolder
*create_mplexpholder(WMPlex
*mplex
,
182 WMPlexAttachParams
*param
)
184 CREATEOBJ_IMPL(WMPlexPHolder
, mplexpholder
, (p
, mplex
, st
, param
));
188 void mplexpholder_deinit(WMPlexPHolder
*ph
)
190 mplexpholder_do_unlink(ph
, ph
->mplex
);
191 pholder_deinit(&(ph
->ph
));
198 /*{{{ Move, attach */
202 WMPlexPHolder
*ph
, *ph_head
;
203 WRegionAttachData
*data
;
209 static WRegion
*recreate_handler(WWindow
*par
,
210 const WFitParams
*fp
,
214 WMPlexPHolder
*ph
=rp
->ph
, *ph_head
=rp
->ph_head
, *phtmp
;
215 WFramedParam
*param
=rp
->param
;
218 frame
=create_frame(par
, fp
, param
->mode
);
223 /* Move pholders to frame */
224 frame
->mplex
.misc_phs
=ph_head
;
226 for(phtmp
=frame
->mplex
.misc_phs
; phtmp
!=NULL
; phtmp
=phtmp
->next
)
227 phtmp
->mplex
=&frame
->mplex
;
230 if(fp
->mode
&(REGION_FIT_BOUNDS
|REGION_FIT_WHATEVER
))
231 ph
->param
.flags
|=MPLEX_ATTACH_WHATEVER
;
233 rp
->reg_ret
=mplex_do_attach_pholder(&frame
->mplex
, ph
, rp
->data
);
235 ph
->param
.flags
&=~MPLEX_ATTACH_WHATEVER
;
237 if(rp
->reg_ret
==NULL
){
239 for(phtmp
=frame
->mplex
.misc_phs
; phtmp
!=NULL
; phtmp
=phtmp
->next
)
242 frame
->mplex
.misc_phs
=NULL
;
244 destroy_obj((Obj
*)frame
);
248 frame_adjust_to_initial(frame
, fp
, param
, rp
->reg_ret
);
250 return (WRegion
*)frame
;
255 static WFramedPHolder
*get_recreate_ph(WMPlexPHolder
*ph
)
257 return get_head(ph
)->recreate_pholder
;
261 static WRegion
*mplexpholder_attach_recreate(WMPlexPHolder
*ph
, int flags
,
262 WRegionAttachData
*data
)
264 WRegionAttachData data2
;
270 rp
.ph_head
=get_head(ph
);
272 assert(rp
.ph_head
!=NULL
);
274 fph
=rp
.ph_head
->recreate_pholder
;
281 rp
.param
=&fph
->param
;
284 data2
.type
=REGION_ATTACH_NEW
;
285 data2
.u
.n
.fn
=recreate_handler
;
288 res
=pholder_do_attach(fph
->cont
, flags
, &data2
);
291 rp
.ph_head
->recreate_pholder
=NULL
;
292 /* It might be in use in attach chain! So defer. */
293 mainloop_defer_destroy((Obj
*)fph
);
296 return (flags
&PHOLDER_ATTACH_RETURN_CREATEROOT
302 WRegion
*mplexpholder_do_attach(WMPlexPHolder
*ph
, int flags
,
303 WRegionAttachData
*data
)
305 WMPlex
*mplex
=ph
->mplex
;
308 return mplexpholder_attach_recreate(ph
, flags
, data
);
310 if(flags
&PHOLDER_ATTACH_SWITCHTO
)
311 ph
->param
.flags
|=MPLEX_ATTACH_SWITCHTO
;
313 ph
->param
.flags
&=~MPLEX_ATTACH_SWITCHTO
;
315 return mplex_do_attach_pholder(mplex
, ph
, data
);
319 bool mplexpholder_move(WMPlexPHolder
*ph
, WMPlex
*mplex
,
320 WMPlexPHolder
*after
,
321 WLListNode
*or_after
)
323 mplexpholder_do_unlink(ph
, ph
->mplex
);
330 mplexpholder_do_link(ph
, mplex
, after
, or_after
);
336 bool mplexpholder_do_goto(WMPlexPHolder
*ph
)
338 WRegion
*reg
=(WRegion
*)ph
->mplex
;
341 return region_goto(reg
);
343 WFramedPHolder
*fph
=get_recreate_ph(ph
);
346 ? pholder_do_goto((WPHolder
*)fph
)
352 WRegion
*mplexpholder_do_target(WMPlexPHolder
*ph
)
354 WRegion
*reg
=(WRegion
*)ph
->mplex
;
359 WFramedPHolder
*fph
=get_recreate_ph(ph
);
362 ? pholder_do_target((WPHolder
*)fph
)
368 bool mplexpholder_stale(WMPlexPHolder
*ph
)
370 WRegion
*reg
=(WRegion
*)ph
->mplex
;
375 WFramedPHolder
*fph
=get_recreate_ph(ph
);
377 return (fph
==NULL
|| pholder_stale((WPHolder
*)fph
));
385 /*{{{ WMPlex routines */
388 void mplex_move_phs(WMPlex
*mplex
, WLListNode
*node
,
389 WMPlexPHolder
*after
,
390 WLListNode
*or_after
)
394 assert(node
!=or_after
);
396 while(node
->phs
!=NULL
){
399 mplexpholder_do_unlink(ph
, mplex
);
400 mplexpholder_do_link(ph
, mplex
, after
, or_after
);
406 void mplex_move_phs_before(WMPlex
*mplex
, WLListNode
*node
)
408 WMPlexPHolder
*after
=NULL
;
409 WLListNode
*or_after
;
411 or_after
=LIST_PREV(mplex
->mx_list
, node
, next
, prev
);
413 after
=(or_after
!=NULL
414 ? LIST_LAST(or_after
->phs
, next
, prev
)
415 : LIST_LAST(mplex
->misc_phs
, next
, prev
));
417 mplex_move_phs(mplex
, node
, after
, or_after
);
421 WMPlexPHolder
*mplex_managed_get_pholder(WMPlex
*mplex
, WRegion
*mgd
)
423 WStacking
*st
=mplex_find_stacking(mplex
, mgd
);
428 return create_mplexpholder(mplex
, st
, NULL
);
432 void mplex_flatten_phs(WMPlex
*mplex
)
437 FOR_ALL_NODES_ON_LLIST(node
, mplex
->mx_list
, tmp
){
438 WMPlexPHolder
*last
=(mplex
->misc_phs
==NULL
? NULL
: mplex
->misc_phs
->prev
);
439 mplex_move_phs(mplex
, node
, last
, NULL
);
444 void mplex_migrate_phs(WMPlex
*src
, WMPlex
*dst
)
446 WLListNode
*or_after
=LIST_LAST(dst
->mx_list
, next
, prev
);
447 WMPlexPHolder
*after
=(or_after
!=NULL
448 ? LIST_LAST(or_after
->phs
, next
, prev
)
449 : LIST_LAST(dst
->misc_phs
, next
, prev
));
451 while(src
->misc_phs
!=NULL
){
452 WMPlexPHolder
*ph
=src
->misc_phs
;
453 mplexpholder_move(ph
, dst
, after
, or_after
);
465 WRegion
*mplex_rescue_attach(WMPlex
*mplex
, int flags
, WRegionAttachData
*data
)
467 WMPlexAttachParams param
;
471 /* Improved attach parametrisation hack for WMPlex source */
472 if(data
->type
==REGION_ATTACH_REPARENT
){
473 WRegion
*reg
=data
->u
.reg
;
474 WMPlex
*src_mplex
=REGION_MANAGER_CHK(reg
, WMPlex
);
476 WStacking
*st
=ioncore_find_stacking(reg
);
478 mplex_get_attach_params(src_mplex
, st
, ¶m
);
482 param
.flags
|=(MPLEX_ATTACH_INDEX
|
483 (flags
&PHOLDER_ATTACH_SWITCHTO
? MPLEX_ATTACH_SWITCHTO
: 0));
484 param
.index
=LLIST_INDEX_LAST
;
486 return mplex_do_attach(mplex
, ¶m
, data
);
490 WPHolder
*mplex_get_rescue_pholder_for(WMPlex
*mplex
, WRegion
*mgd
)
493 WStacking
*st
=mplex_find_stacking(mplex
, mgd
);
494 WMPlexAttachParams param
;
496 param
.flags
=MPLEX_ATTACH_INDEX
;
497 param
.index
=LLIST_INDEX_LAST
;
499 return create_mplexpholder(mplex
, st
, ¶m
);
501 return (WPHolder
*)create_basicpholder((WRegion
*)mplex
,
502 (WBasicPHolderHandler
*)mplex_rescue_attach
);
510 /*{{{ Class information */
513 static DynFunTab mplexpholder_dynfuntab
[]={
514 {(DynFun
*)pholder_do_attach
,
515 (DynFun
*)mplexpholder_do_attach
},
517 {(DynFun
*)pholder_do_goto
,
518 (DynFun
*)mplexpholder_do_goto
},
520 {(DynFun
*)pholder_do_target
,
521 (DynFun
*)mplexpholder_do_target
},
523 {(DynFun
*)pholder_stale
,
524 (DynFun
*)mplexpholder_stale
},
530 IMPLCLASS(WMPlexPHolder
, WPHolder
, mplexpholder_deinit
,
531 mplexpholder_dynfuntab
);