]> git.decadent.org.uk Git - ion3.git/blob - mod_tiling/ops.c
[svn-inject] Installing original source of ion3
[ion3.git] / mod_tiling / ops.c
1 /*
2  * ion/mod_tiling/ops.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2006. 
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
14 #include <ioncore/common.h>
15 #include <ioncore/mplex.h>
16 #include <ioncore/focus.h>
17 #include <ioncore/group.h>
18 #include <ioncore/group-ws.h>
19 #include <ioncore/framedpholder.h>
20 #include "tiling.h"
21
22
23 static WGroup *find_group(WRegion *reg, bool *detach_framed)
24 {
25     WRegion *mgr=REGION_MANAGER(reg);
26     bool was_grouped=FALSE;
27     
28     if(OBJ_IS(mgr, WMPlex)){
29         WMPlex *mplex=(WMPlex*)mgr;
30         *detach_framed=TRUE;
31         mgr=REGION_MANAGER(mgr);
32         if(OBJ_IS(mgr, WGroup)){
33             assert(mplex->mgd!=NULL);
34             if(mplex->mgd->reg==reg && mplex->mgd->mgr_next==NULL){
35                 /* Nothing to detach */
36                 return NULL;
37             }
38         }
39     }else{
40         was_grouped=OBJ_IS(mgr, WGroup);
41         *detach_framed=FALSE;
42     }
43     
44     while(mgr!=NULL){
45         mgr=REGION_MANAGER(mgr);
46         if(OBJ_IS(mgr, WGroup))
47             break;
48     }
49
50     if(mgr==NULL && was_grouped)
51         warn(TR("Already detached."));
52     
53     return (WGroup*)mgr;
54 }
55
56
57 static void get_relative_geom(WRectangle *g, WRegion *reg, WRegion *mgr)
58 {
59     WWindow *rel=REGION_PARENT(mgr), *w;
60     
61     *g=REGION_GEOM(reg);
62     
63     for(w=REGION_PARENT(reg); 
64         w!=rel && (WRegion*)w!=mgr; 
65         w=REGION_PARENT(w)){
66         
67         g->x+=REGION_GEOM(w).x;
68         g->y+=REGION_GEOM(w).y;
69     }
70 }
71
72
73 /*EXTL_DOC
74  * Detach \var{reg}, i.e. make it managed by its nearest ancestor
75  * \type{WGroup}, framed if \var{reg} is not itself \type{WFrame}.
76  */
77 EXTL_EXPORT
78 bool mod_tiling_detach(WRegion *reg)
79 {
80     bool detach_framed=!OBJ_IS(reg, WFrame);
81     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
82     WRegionAttachData data;
83     WGroup *grp;
84     
85     grp=find_group(reg, &detach_framed);
86     
87     if(grp==NULL)
88         return FALSE;
89     
90     ap.switchto_set=TRUE;
91     ap.switchto=region_may_control_focus(reg);
92     
93     ap.geom_set=TRUE;
94     get_relative_geom(&ap.geom, reg, (WRegion*)grp);
95     
96     /* TODO: Retain (root-relative) geometry of reg for framed 
97      * detach instead of making a frame of this size?
98      */
99     
100     data.type=REGION_ATTACH_REPARENT;
101     data.u.reg=reg;
102     
103     if(detach_framed){
104         WFramedParam fp=FRAMEDPARAM_INIT;
105         
106         return (region_attach_framed((WRegion*)grp, &fp,
107                                      (WRegionAttachFn*)group_do_attach,
108                                      &ap, &data)!=NULL);
109     }else{
110         return (group_do_attach(grp, &ap, &data)!=NULL);
111     }
112 }
113
114
115 static WRegion *mkbottom_fn(WWindow *parent, const WFitParams *fp, 
116                             void *param)
117 {
118     WRegion *reg=(WRegion*)param;
119     WTiling *tiling;
120     WSplitRegion *node=NULL;
121     
122     if(!region_fitrep(reg, parent, fp))
123         return NULL;
124     
125     tiling=create_tiling(parent, fp, NULL, FALSE);
126     
127     if(tiling==NULL)
128         return NULL;
129     
130     node=create_splitregion(&REGION_GEOM(tiling), reg);
131     if(node!=NULL){
132         tiling->split_tree=(WSplit*)node;
133         tiling->split_tree->ws_if_root=tiling;
134         
135         region_detach_manager(reg);
136         
137         if(tiling_managed_add(tiling, reg))
138             return (WRegion*)tiling;
139         
140         #warning "TODO: reattach?"
141         
142         destroy_obj((Obj*)tiling->split_tree);
143         tiling->split_tree=NULL;
144     }
145     
146     destroy_obj((Obj*)tiling);
147     return NULL;
148 }
149
150
151 /*EXTL_DOC
152  * Create a new \type{WTiling} 'bottom' for the group of \var{reg},
153  * consisting of \var{reg}.
154  */
155 EXTL_EXPORT
156 bool mod_tiling_mkbottom(WRegion *reg)
157 {
158     WGroup *grp=REGION_MANAGER_CHK(reg, WGroup);
159     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
160     WRegionAttachData data;
161     WRegion *tiling;
162     
163     if(grp==NULL){
164         warn(TR("Not member of a group"));
165         return FALSE;
166     }
167     
168     if(grp->bottom!=NULL){
169         warn(TR("Manager group already has bottom"));
170         return FALSE;
171     }
172     
173     ap.level_set=TRUE;
174     ap.level=STACKING_LEVEL_BOTTOM;
175     
176     ap.szplcy_set=TRUE;
177     ap.szplcy=SIZEPOLICY_FULL_EXACT;
178     
179     ap.switchto_set=TRUE;
180     ap.switchto=region_may_control_focus(reg);
181     
182     ap.bottom=TRUE;
183
184     data.type=REGION_ATTACH_NEW;
185     data.u.n.fn=mkbottom_fn;
186     data.u.n.param=reg;
187     
188     /* kele... poisto samalla kuin attach */
189     return (group_do_attach(grp, &ap, &data)!=NULL);
190 }