Released version 3-2015061300
[notion.git] / ioncore / conf.c
blob188c87487fad6f2de7286b4d2ebb9bbf7556a325
1 /*
2 * ion/ioncore/conf.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <stdlib.h>
10 #include <string.h>
12 #include <libtu/map.h>
13 #include <libtu/minmax.h>
14 #include <libtu/objp.h>
15 #include <libtu/map.h>
16 #include <libextl/readconfig.h>
18 #include "common.h"
19 #include "global.h"
20 #include "modules.h"
21 #include "rootwin.h"
22 #include "bindmaps.h"
23 #include "kbresize.h"
24 #include "reginfo.h"
25 #include "group-ws.h"
26 #include "llist.h"
29 StringIntMap frame_idxs[]={
30 {"last", LLIST_INDEX_LAST},
31 {"next", LLIST_INDEX_AFTER_CURRENT},
32 {"next-act", LLIST_INDEX_AFTER_CURRENT_ACT},
33 END_STRINGINTMAP
36 StringIntMap win_stackrq[]={
37 {"ignore", IONCORE_WINDOWSTACKINGREQUEST_IGNORE},
38 {"activate", IONCORE_WINDOWSTACKINGREQUEST_ACTIVATE},
39 END_STRINGINTMAP
42 static bool get_winprop_fn_set=FALSE;
43 static ExtlFn get_winprop_fn;
45 static bool get_layout_fn_set=FALSE;
46 static ExtlFn get_layout_fn;
49 /*EXTL_DOC
50 * Set ioncore basic settings. The table \var{tab} may contain the
51 * following fields.
53 * \begin{tabularx}{\linewidth}{lX}
54 * \tabhead{Field & Description}
55 * \var{opaque_resize} & (boolean) Controls whether interactive move and
56 * resize operations simply draw a rubberband during
57 * the operation (false) or immediately affect the
58 * object in question at every step (true). \\
59 * \var{warp} & (boolean) Should focusing operations move the
60 * pointer to the object to be focused? \\
61 * \var{switchto} & (boolean) Should a managing \type{WMPlex} switch
62 * to a newly mapped client window? \\
63 * \var{screen_notify} & (boolean) Should notification tooltips be displayed
64 * for hidden workspaces with activity? \\
65 * \var{frame_default_index} & (string) Specifies where to add new regions
66 * on the mutually exclusive list of a frame. One of
67 * \codestr{last}, \codestr{next}, (for after current),
68 * or \codestr{next-act}
69 * (for after current and anything with activity right
70 * after it). \\
71 * \var{dblclick_delay} & (integer) Delay between clicks of a double click.\\
72 * \var{kbresize_delay} & (integer) Delay in milliseconds for ending keyboard
73 * resize mode after inactivity. \\
74 * \var{kbresize_t_max} & (integer) Controls keyboard resize acceleration.
75 * See description below for details. \\
76 * \var{kbresize_t_min} & (integer) See below. \\
77 * \var{kbresize_step} & (floating point) See below. \\
78 * \var{kbresize_maxacc} & (floating point) See below. \\
79 * \var{edge_resistance} & (integer) Resize edge resistance in pixels. \\
80 * \var{framed_transients} & (boolean) Put transients in nested frames. \\
81 * \var{float_placement_method} & (string) How to place floating frames.
82 * One of \codestr{udlr} (up-down, then left-right),
83 * \codestr{lrud} (left-right, then up-down), or
84 * \codestr{random}. \\
85 * \var{float_placement_padding} & (integer) Pixels between frames when
86 * \var{float_placement_method} is \codestr{udlr} or
87 * \codestr{lrud}. \\
88 * \var{mousefocus} & (string) Mouse focus mode:
89 * \codestr{disabled} or \codestr{sloppy}. \\
90 * \var{unsqueeze} & (boolean) Auto-unsqueeze transients/menus/queries/etc. \\
91 * \var{autoraise} & (boolean) Autoraise regions in groups on goto. \\
92 * \var{usertime_diff_current} & (integer) Controls switchto timeout. \\
93 * \var{usertime_diff_new} & (integer) Controls switchto timeout. \\
94 * \var{autosave_layout} & (boolean) Automatically save layout on restart and exit. \\
95 * \var{window_stacking_request} & (string) How to respond to window-stacking
96 * requests. \codestr{ignore} to do nothing,
97 * \codestr{activate} to set the activity flag on a
98 * window requesting to be stacked Above. \\
99 * \var{focuslist_insert_delay} & (integer) Time (in ms) that a window must
100 * stay focused in order to be added to the focus list.
101 * If this value is set <=0, this logic is disabled:
102 * the focus list is updated immediately \\
103 * \var{activity_notification_on_all_screens} & (boolean) If enabled, activity
104 * notifiers are displayed on ALL the screens, not just
105 * the screen that contains the window producing the
106 * notification. This is only relevant on multi-head
107 * setups. By default this is disabled \\
108 * \var{workspace_indicator_timeout} & (integer) If enabled, a workspace
109 * indicator comes up at the bottom-left of the screen
110 * when a new workspace is selected. This indicator
111 * stays active for only as long as indicated by this
112 * variable (in ms). Timeout values <=0 disable the
113 * indicator altogether. This is disabled by default \\
114 * \end{tabularx}
116 * When a keyboard resize function is called, and at most \var{kbresize_t_max}
117 * milliseconds has passed from a previous call, acceleration factor is reset
118 * to 1.0. Otherwise, if at least \var{kbresize_t_min} milliseconds have
119 * passed from the from previous acceleration update or reset the squere root
120 * of the acceleration factor is incremented by \var{kbresize_step}. The
121 * maximum acceleration factor (pixels/call modulo size hints) is given by
122 * \var{kbresize_maxacc}. The default values are (200, 50, 30, 100).
124 EXTL_EXPORT
125 void ioncore_set(ExtlTab tab)
127 int dd;
128 char *tmp;
129 ExtlFn fn;
131 extl_table_gets_b(tab, "opaque_resize", &(ioncore_g.opaque_resize));
132 extl_table_gets_b(tab, "warp", &(ioncore_g.warp_enabled));
133 extl_table_gets_b(tab, "switchto", &(ioncore_g.switchto_new));
134 extl_table_gets_b(tab, "screen_notify", &(ioncore_g.screen_notify));
135 extl_table_gets_b(tab, "framed_transients", &(ioncore_g.framed_transients));
136 extl_table_gets_b(tab, "unsqueeze", &(ioncore_g.unsqueeze_enabled));
137 extl_table_gets_b(tab, "autoraise", &(ioncore_g.autoraise));
138 extl_table_gets_b(tab, "autosave_layout", &(ioncore_g.autosave_layout));
140 if(extl_table_gets_s(tab, "window_stacking_request", &tmp)){
141 ioncore_g.window_stacking_request=stringintmap_value(win_stackrq,
142 tmp,
143 ioncore_g.window_stacking_request);
144 free(tmp);
147 if(extl_table_gets_s(tab, "frame_default_index", &tmp)){
148 ioncore_g.frame_default_index=stringintmap_value(frame_idxs,
149 tmp,
150 ioncore_g.frame_default_index);
151 free(tmp);
154 if(extl_table_gets_s(tab, "mousefocus", &tmp)){
155 if(strcmp(tmp, "disabled")==0)
156 ioncore_g.no_mousefocus=TRUE;
157 else if(strcmp(tmp, "sloppy")==0)
158 ioncore_g.no_mousefocus=FALSE;
159 free(tmp);
162 if(extl_table_gets_i(tab, "dblclick_delay", &dd))
163 ioncore_g.dblclick_delay=MAXOF(0, dd);
165 if(extl_table_gets_i(tab, "usertime_diff_current", &dd))
166 ioncore_g.usertime_diff_current=MAXOF(0, dd);
168 if(extl_table_gets_i(tab, "usertime_diff_new", &dd))
169 ioncore_g.usertime_diff_new=MAXOF(0, dd);
171 if(extl_table_gets_i(tab, "focuslist_insert_delay", &dd))
172 ioncore_g.focuslist_insert_delay=MAXOF(0, dd);
174 if(extl_table_gets_i(tab, "workspace_indicator_timeout", &dd))
175 ioncore_g.workspace_indicator_timeout=MAXOF(0, dd);
177 extl_table_gets_b(tab, "activity_notification_on_all_screens",
178 &(ioncore_g.activity_notification_on_all_screens));
180 ioncore_set_moveres_accel(tab);
182 ioncore_groupws_set(tab);
184 /* Internal -- therefore undocumented above */
185 if(extl_table_gets_f(tab, "_get_winprop", &fn)){
186 if(get_winprop_fn_set)
187 extl_unref_fn(get_winprop_fn);
188 get_winprop_fn=fn;
189 get_winprop_fn_set=TRUE;
192 if(extl_table_gets_f(tab, "_get_layout", &fn)){
193 if(get_layout_fn_set)
194 extl_unref_fn(get_layout_fn);
195 get_layout_fn=fn;
196 get_layout_fn_set=TRUE;
202 /*EXTL_DOC
203 * Get ioncore basic settings. For details see \fnref{ioncore.set}.
205 EXTL_SAFE
206 EXTL_EXPORT
207 ExtlTab ioncore_get()
209 ExtlTab tab=extl_create_table();
211 extl_table_sets_b(tab, "opaque_resize", ioncore_g.opaque_resize);
212 extl_table_sets_b(tab, "warp", ioncore_g.warp_enabled);
213 extl_table_sets_b(tab, "switchto", ioncore_g.switchto_new);
214 extl_table_sets_i(tab, "dblclick_delay", ioncore_g.dblclick_delay);
215 extl_table_sets_b(tab, "screen_notify", ioncore_g.screen_notify);
216 extl_table_sets_b(tab, "framed_transients", ioncore_g.framed_transients);
217 extl_table_sets_b(tab, "unsqueeze", ioncore_g.unsqueeze_enabled);
218 extl_table_sets_b(tab, "autoraise", ioncore_g.autoraise);
219 extl_table_sets_b(tab, "autosave_layout", ioncore_g.autosave_layout);
220 extl_table_sets_i(tab, "focuslist_insert_delay", ioncore_g.focuslist_insert_delay);
221 extl_table_sets_i(tab, "workspace_indicator_timeout", ioncore_g.workspace_indicator_timeout);
222 extl_table_sets_b(tab, "activity_notification_on_all_screens",
223 ioncore_g.activity_notification_on_all_screens);
225 extl_table_sets_s(tab, "window_stacking_request",
226 stringintmap_key(win_stackrq,
227 ioncore_g.window_stacking_request,
228 NULL));
230 extl_table_sets_s(tab, "frame_default_index",
231 stringintmap_key(frame_idxs,
232 ioncore_g.frame_default_index,
233 NULL));
235 extl_table_sets_s(tab, "mousefocus", (ioncore_g.no_mousefocus
236 ? "disabled"
237 : "sloppy"));
239 ioncore_get_moveres_accel(tab);
241 ioncore_groupws_get(tab);
243 return tab;
247 ExtlTab ioncore_get_winprop(WClientWin *cwin)
249 ExtlTab tab=extl_table_none();
251 if(get_winprop_fn_set){
252 extl_protect(NULL);
253 extl_call(get_winprop_fn, "o", "t", cwin, &tab);
254 extl_unprotect(NULL);
257 return tab;
261 ExtlTab ioncore_get_layout(const char *layout)
263 ExtlTab tab=extl_table_none();
265 if(get_layout_fn_set){
266 extl_protect(NULL);
267 extl_call(get_layout_fn, "s", "t", layout, &tab);
268 extl_unprotect(NULL);
271 return tab;
275 /*EXTL_DOC
276 * Get important directories (the fields \var{userdir},
277 * \var{sessiondir}, \var{searchpath} in the returned table).
279 EXTL_SAFE
280 EXTL_EXPORT
281 ExtlTab ioncore_get_paths(ExtlTab tab)
283 tab=extl_create_table();
284 extl_table_sets_s(tab, "userdir", extl_userdir());
285 extl_table_sets_s(tab, "sessiondir", extl_sessiondir());
286 extl_table_sets_s(tab, "searchpath", extl_searchpath());
287 return tab;
291 /*EXTL_DOC
292 * Set important directories (the fields \var{sessiondir}, \var{searchpath}
293 * of \var{tab}).
295 EXTL_EXPORT
296 bool ioncore_set_paths(ExtlTab tab)
298 char *s;
300 if(extl_table_gets_s(tab, "userdir", &s)){
301 warn(TR("User directory can not be set."));
302 free(s);
303 return FALSE;
306 if(extl_table_gets_s(tab, "sessiondir", &s)){
307 extl_set_sessiondir(s);
308 free(s);
309 return FALSE;
312 if(extl_table_gets_s(tab, "searchpath", &s)){
313 extl_set_searchpath(s);
314 free(s);
315 return FALSE;
318 return TRUE;
322 /* Exports these in ioncore. */
324 /*EXTL_DOC
325 * Lookup script \var{file}. If \var{try_in_dir} is set, it is tried
326 * before the standard search path.
328 EXTL_SAFE
329 EXTL_EXPORT_AS(ioncore, lookup_script)
330 char *extl_lookup_script(const char *file, const char *sp);
333 /*EXTL_DOC
334 * Get a file name to save (session) data in. The string \var{basename}
335 * should contain no path or extension components.
337 EXTL_SAFE
338 EXTL_EXPORT_AS(ioncore, get_savefile)
339 char *extl_get_savefile(const char *basename);
342 /*EXTL_DOC
343 * Write \var{tab} in file with basename \var{basename} in the
344 * session directory.
346 EXTL_SAFE
347 EXTL_EXPORT_AS(ioncore, write_savefile)
348 bool extl_write_savefile(const char *basename, ExtlTab tab);
351 /*EXTL_DOC
352 * Read a savefile.
354 EXTL_SAFE
355 EXTL_EXPORT_AS(ioncore, read_savefile)
356 ExtlTab extl_extl_read_savefile(const char *basename);
360 bool ioncore_read_main_config(const char *cfgfile)
362 bool ret;
363 int unset=0;
365 if(cfgfile==NULL)
366 cfgfile="cfg_notion";
368 ret=extl_read_config(cfgfile, ".", TRUE);
370 unset+=(ioncore_screen_bindmap->nbindings==0);
371 unset+=(ioncore_mplex_bindmap->nbindings==0);
372 unset+=(ioncore_frame_bindmap->nbindings==0);
374 if(unset>0){
375 warn(TR("Some bindmaps were empty, loading ioncore_efbb."));
376 extl_read_config("ioncore_efbb", NULL, TRUE);
379 return (ret && unset==0);