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