]> git.decadent.org.uk Git - ion3.git/blob - ioncore/saveload.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / ioncore / saveload.c
1 /*
2  * ion/ioncore/saveload.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <string.h>
10 #include <time.h>
11 #include <unistd.h>
12
13 #include <libtu/objp.h>
14 #include <libextl/readconfig.h>
15 #include <libextl/extl.h>
16
17 #include "common.h"
18 #include "global.h"
19 #include "region.h"
20 #include "screen.h"
21 #include "saveload.h"
22 #include "names.h"
23 #include "attach.h"
24 #include "reginfo.h"
25 #include "extlconv.h"
26 #include "group-ws.h"
27
28
29 static bool loading_layout=FALSE;
30 static bool layout_load_error=FALSE;
31
32
33 /*{{{ Session management module support */
34
35
36 static SMAddCallback *add_cb;
37 static SMCfgCallback *cfg_cb;
38 static SMPHolderCallback *ph_cb;
39 static bool clientwin_was_missing=FALSE;
40
41
42 void ioncore_set_sm_callbacks(SMAddCallback *add, SMCfgCallback *cfg)
43 {
44     add_cb=add;
45     cfg_cb=cfg;
46 }
47
48
49 void ioncore_get_sm_callbacks(SMAddCallback **add, SMCfgCallback **cfg)
50 {
51     *add=add_cb;
52     *cfg=cfg_cb;
53 }
54
55
56 void ioncore_set_sm_pholder_callback(SMPHolderCallback *phcb)
57 {
58     ph_cb=phcb;
59 }
60
61
62 void ioncore_clientwin_load_missing()
63 {
64     clientwin_was_missing=TRUE;
65 }
66
67
68 /*}}}*/
69
70
71 /*{{{ Load support functions */
72
73
74 WRegion *create_region_load(WWindow *par, const WFitParams *fp, 
75                             ExtlTab tab)
76 {
77     char *objclass=NULL, *name=NULL;
78     WRegionLoadCreateFn* fn=NULL;
79     WRegClassInfo *info=NULL;
80     WRegion *reg=NULL;
81     bool grouped=FALSE;
82     char *grouped_name=NULL;
83     
84     if(!extl_table_gets_s(tab, "type", &objclass))
85         return NULL;
86     
87     if(objclass==NULL)
88         return NULL;
89     
90     info=ioncore_lookup_regclass(objclass, FALSE);
91     if(info!=NULL)
92         fn=info->lc_fn;
93     
94     if(fn==NULL){
95         warn(TR("Unknown class \"%s\", cannot create region."),
96              objclass);
97         layout_load_error=loading_layout;
98         return NULL;
99     }
100
101     free(objclass);
102     
103     clientwin_was_missing=FALSE;
104     
105     reg=fn(par, fp, tab);
106     
107     if(reg==NULL){
108         if(clientwin_was_missing && add_cb!=NULL && ph_cb!=NULL){
109             WPHolder *ph=ph_cb();
110             if(ph!=NULL){
111                 if(!add_cb(ph, tab))
112                     destroy_obj((Obj*)ph);
113             }
114         }
115     }else{
116         if(!OBJ_IS(reg, WClientWin)){
117             if(extl_table_gets_s(tab, "name", &name)){
118                 region_set_name(reg, name);
119                 free(name);
120             }
121         }
122     }
123     
124     ph_cb=NULL;
125     
126     return reg;
127 }
128
129     
130 /*}}}*/
131
132
133 /*{{{ Save support functions */
134
135
136 bool region_supports_save(WRegion *reg)
137 {
138     return HAS_DYN(reg, region_get_configuration);
139 }
140
141
142 ExtlTab region_get_base_configuration(WRegion *reg)
143 {
144     const char *name;
145     ExtlTab tab;
146     
147     tab=extl_create_table();
148     
149     extl_table_sets_s(tab, "type", OBJ_TYPESTR(reg));
150     
151     name=region_name(reg);
152     
153     if(name!=NULL && !OBJ_IS(reg, WClientWin))
154         extl_table_sets_s(tab, "name", name);
155     
156     return tab;
157 }
158
159
160 static bool get_config_clientwins=TRUE;
161
162
163 ExtlTab region_get_configuration(WRegion *reg)
164 {
165     ExtlTab tab=extl_table_none();
166     if(get_config_clientwins || !OBJ_IS(reg, WClientWin)){
167         CALL_DYN_RET(tab, ExtlTab, region_get_configuration, reg, (reg));
168     }
169     return tab;
170 }
171
172
173 /*EXTL_DOC
174  * Get configuration tree. If \var{clientwins} is unset, client windows
175  * are filtered out.
176  */
177 EXTL_EXPORT_AS(WRegion, get_configuration)
178 ExtlTab region_get_configuration_extl(WRegion *reg, bool clientwins)
179 {
180     ExtlTab tab;
181     
182     get_config_clientwins=clientwins;
183     
184     tab=region_get_configuration(reg);
185     
186     get_config_clientwins=TRUE;
187     
188     return tab;
189 }
190
191
192 /*}}}*/
193
194
195 /*{{{ save_workspaces, load_workspaces */
196
197
198 static const char backup_msg[]=DUMMY_TR(
199 "There were errors loading layout. Backing up current layout savefile as\n"
200 "%s.\n"
201 "If you are _not_ running under a session manager and wish to restore your\n"
202 "old layout, copy this backup file over the layout savefile found in the\n"
203 "same directory while Ion is not running and after having fixed your other\n"
204 "configuration files that are causing this problem. (Maybe a missing\n"
205 "module?)");
206
207
208 bool ioncore_init_layout()
209 {
210     ExtlTab tab;
211     WScreen *scr;
212     bool ok;
213     int n=0;
214     
215     ok=extl_read_savefile("saved_layout", &tab);
216     
217     loading_layout=TRUE;
218     layout_load_error=FALSE;
219     
220     FOR_ALL_SCREENS(scr){
221         ExtlTab scrtab=extl_table_none();
222         bool scrok=FALSE;
223         
224         /* Potential Xinerama or such support should set the screen ID
225          * of the root window to less than zero, and number its own
226          * fake screens up from 0.
227          */
228         if(screen_id(scr)<0)
229             continue;
230
231         if(ok)
232             scrok=extl_table_geti_t(tab, screen_id(scr), &scrtab);
233         
234         n+=(TRUE==screen_init_layout(scr, scrtab));
235         
236         if(scrok)
237             extl_unref_table(scrtab);
238     }
239
240     loading_layout=FALSE;
241
242     if(layout_load_error){
243         time_t t=time(NULL);
244         char tm[]="saved_layout.backup-YYYYMMDDHHMMSS\0\0\0\0";
245         char *backup;
246         
247         strftime(tm+20, 15, "%Y%m%d%H%M%S", localtime(&t));
248         backup=extl_get_savefile(tm);
249         if(backup==NULL){
250             warn(TR("Unable to get file for layout backup."));
251             return FALSE;
252         }
253         if(access(backup, F_OK)==0){
254             warn(TR("Backup file %s already exists."), backup);
255             free(backup);
256             return FALSE;
257         }
258         warn(TR(backup_msg), backup);
259         if(!extl_serialise(backup, tab))
260             warn(TR("Failed backup."));
261         free(backup);
262     }
263         
264     if(n==0){
265         warn(TR("Unable to initialise layout on any screen."));
266         return FALSE;
267     }else{
268         return TRUE;
269     }
270 }
271
272
273 bool ioncore_save_layout()
274 {
275     WScreen *scr=NULL;
276     ExtlTab tab=extl_create_table();
277     bool ret;
278     
279     if(tab==extl_table_none())
280         return FALSE;
281     
282     FOR_ALL_SCREENS(scr){
283         ExtlTab scrtab;
284         
285         /* See note above */
286         if(screen_id(scr)<0)
287             continue;
288             
289         scrtab=region_get_configuration((WRegion*)scr);
290         
291         if(scrtab==extl_table_none()){
292             warn(TR("Unable to get configuration for screen %d."),
293                  screen_id(scr));
294         }else{
295             extl_table_seti_t(tab, screen_id(scr), scrtab);
296             extl_unref_table(scrtab);
297         }
298     }
299     
300     ret=extl_write_savefile("saved_layout", tab);
301     
302     extl_unref_table(tab);
303     
304     if(!ret)
305         warn(TR("Unable to save layout."));
306         
307     return ret;
308 }
309
310
311 /*}}}*/
312
313