]> git.decadent.org.uk Git - ion3.git/blob - ioncore/pholder.c
018de2ba3d1aae2011b52425b75b4ee4c141a285
[ion3.git] / ioncore / pholder.c
1 /*
2  * ion/ioncore/pholder.c
3  *
4  * Copyright (c) Tuomo Valkonen 2005-2007. 
5  *
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.
10  */
11
12 #include <libtu/objp.h>
13 #include "common.h"
14 #include "attach.h"
15 #include "pholder.h"
16 #include "focus.h"
17
18
19 bool pholder_init(WPHolder *ph)
20 {
21     ph->redirect=NULL;
22     return TRUE;
23 }
24
25
26 void pholder_deinit(WPHolder *ph)
27 {
28     if(ph->redirect!=NULL)
29         destroy_obj((Obj*)ph->redirect);
30 }
31
32
33 WRegion *pholder_do_attach(WPHolder *ph, int flags,
34                            WRegionAttachData *data)
35
36 {
37     WRegion *ret=NULL;
38     CALL_DYN_RET(ret, WRegion*, pholder_do_attach, ph, (ph, flags, data));
39     return ret;
40 }
41
42
43 WRegion *pholder_attach_(WPHolder *ph, int flags, WRegionAttachData *data)
44 {
45     WPHolder *root=pholder_root(ph);
46     
47     /* Use the root, so that extra containers are not added from
48      * stale chains.
49      */
50     
51     return (root==NULL
52             ? NULL
53             : pholder_do_attach(root, flags, data));
54 }
55
56
57 bool pholder_attach(WPHolder *ph, int flags, WRegion *reg)
58 {
59     WRegionAttachData data;
60         
61     data.type=REGION_ATTACH_REPARENT;
62     data.u.reg=reg;
63     
64     return (pholder_attach_(ph, flags, &data)!=NULL);
65 }
66
67
68 bool pholder_attach_mcfgoto(WPHolder *ph, int flags, WRegion *reg)
69 {
70     bool cf=region_may_control_focus(reg);
71     
72     if(!pholder_attach(ph, flags, reg))
73         return FALSE;
74         
75     if(cf)
76         region_goto(reg);
77     
78     return TRUE;
79 }
80
81
82 WRegion *pholder_do_target(WPHolder *ph)
83 {
84     WRegion *ret=NULL;
85     CALL_DYN_RET(ret, WRegion*, pholder_do_target, ph, (ph));
86     return ret;
87 }
88
89
90 WRegion *pholder_target(WPHolder *ph)
91 {
92     return (ph->redirect!=NULL
93             ? pholder_target(ph->redirect)
94             : pholder_do_target(ph));
95 }
96
97
98 static bool pholder_do_check_reparent_default(WPHolder *ph, WRegion *reg)
99 {
100     WRegion *target=pholder_do_target(ph);
101     
102     return (target==NULL 
103             ? FALSE
104             : region_ancestor_check(target, reg));
105 }
106
107
108 DYNFUN bool pholder_do_check_reparent(WPHolder *ph, WRegion *reg)
109 {
110     bool ret=FALSE;
111     CALL_DYN_RET(ret, bool, pholder_do_check_reparent, ph, (ph, reg));
112     return ret;
113 }
114
115
116 bool pholder_check_reparent(WPHolder *ph, WRegion *reg)
117 {
118     if(ph->redirect!=NULL)
119         return pholder_check_reparent(ph->redirect, reg);
120     else
121         return pholder_do_check_reparent(ph, reg);
122 }
123     
124
125 bool pholder_do_goto(WPHolder *ph)
126 {
127     bool ret=FALSE;
128     CALL_DYN_RET(ret, bool, pholder_do_goto, ph, (ph));
129     return ret;
130 }
131
132
133 bool pholder_goto(WPHolder *ph)
134 {
135     return (ph->redirect!=NULL
136             ? pholder_goto(ph->redirect)
137             : pholder_do_goto(ph));
138 }
139
140
141 WPHolder *pholder_do_root_default(WPHolder *ph)
142 {
143     return ph;
144 }
145
146
147 WPHolder *pholder_do_root(WPHolder *ph)
148 {
149     WPHolder *ret=NULL;
150     CALL_DYN_RET(ret, WPHolder*, pholder_do_root, ph, (ph));
151     return ret;
152 }
153
154
155 WPHolder *pholder_root(WPHolder *ph)
156 {
157     return (ph->redirect!=NULL
158             ? pholder_root(ph->redirect)
159             : pholder_do_root(ph));
160 }
161
162
163 bool pholder_stale(WPHolder *ph)
164 {
165     return (pholder_root(ph)!=ph);
166 }
167
168
169 bool pholder_redirect(WPHolder *ph, WRegion *old_target)
170 {
171     WPHolder *ph2=region_get_rescue_pholder(old_target);
172     
173     if(ph2==NULL)
174         return FALSE;
175     
176     if(ph->redirect!=NULL)
177         destroy_obj((Obj*)ph->redirect);
178
179     ph->redirect=ph2;
180     
181     return TRUE;
182 }
183
184
185 WPHolder *region_managed_get_pholder(WRegion *reg, WRegion *mgd)
186 {
187     WPHolder *ret=NULL;
188     CALL_DYN_RET(ret, WPHolder*, region_managed_get_pholder, 
189                  reg, (reg, mgd));
190     return ret;
191 }
192
193
194 WPHolder *region_get_rescue_pholder_for(WRegion *reg, WRegion *mgd)
195 {
196     if(OBJ_IS_BEING_DESTROYED(reg) || reg->flags&REGION_CWINS_BEING_RESCUED){
197         return FALSE;
198     }else{
199         WPHolder *ret=NULL;
200     
201         CALL_DYN_RET(ret, WPHolder*, region_get_rescue_pholder_for,
202                      reg, (reg, mgd));
203         return ret;
204     }
205 }
206
207
208 WPHolder *region_get_rescue_pholder(WRegion *reg)
209 {
210     WRegion *mgr;
211     WPHolder *ph=NULL;
212
213     while(1){
214         mgr=region_manager_or_parent(reg);
215         if(mgr==NULL)
216             break;
217         ph=region_get_rescue_pholder_for(mgr, reg);
218         if(ph!=NULL)
219             break;
220         reg=mgr;
221     }
222     
223     return ph;
224 }
225
226
227 WPHolder *pholder_either(WPHolder *a, WPHolder *b)
228 {
229     return (a!=NULL ? a : b);
230 }
231
232
233 static DynFunTab pholder_dynfuntab[]={
234     {(DynFun*)pholder_do_check_reparent, 
235      (DynFun*)pholder_do_check_reparent_default},
236      
237     {(DynFun*)pholder_do_root, 
238      (DynFun*)pholder_do_root_default},
239
240     END_DYNFUNTAB
241 };
242
243
244 IMPLCLASS(WPHolder, Obj, pholder_deinit, pholder_dynfuntab);
245