532b19ec8c1b9c3f39873dba82cfa92132e702b0
[wmaker-crm.git] / src / wdefaults.c
blob532b19ec8c1b9c3f39873dba82cfa92132e702b0
1 /* wdefaults.c - window specific defaults
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "wconfig.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <ctype.h>
31 #include <X11/Xlib.h>
32 #include <X11/Xutil.h>
33 #include <X11/keysym.h>
35 #include <wraster.h>
37 #include "WindowMaker.h"
38 #include "window.h"
39 #include "appicon.h"
40 #include "screen.h"
41 #include "funcs.h"
42 #include "workspace.h"
43 #include "defaults.h"
44 #include "icon.h"
46 #define APPLY_VAL(value, flag, attrib) \
47 if (value) {attr->flag = getBool(attrib, value); \
48 if (mask) mask->flag = 1;}
50 /* Global stuff */
51 extern WPreferences wPreferences;
52 extern WDDomain *WDWindowAttributes;
54 /* Local stuff */
56 /* type converters */
57 static int getBool(WMPropList *, WMPropList *);
58 static char *getString(WMPropList *, WMPropList *);
59 static WMPropList *ANoTitlebar = NULL;
60 static WMPropList *ANoResizebar;
61 static WMPropList *ANoMiniaturizeButton;
62 static WMPropList *ANoMiniaturizable;
63 static WMPropList *ANoCloseButton;
64 static WMPropList *ANoBorder;
65 static WMPropList *ANoHideOthers;
66 static WMPropList *ANoMouseBindings;
67 static WMPropList *ANoKeyBindings;
68 static WMPropList *ANoAppIcon; /* app */
69 static WMPropList *AKeepOnTop;
70 static WMPropList *AKeepOnBottom;
71 static WMPropList *AOmnipresent;
72 static WMPropList *ASkipWindowList;
73 static WMPropList *ASkipSwitchPanel;
74 static WMPropList *AKeepInsideScreen;
75 static WMPropList *AUnfocusable;
76 static WMPropList *AAlwaysUserIcon;
77 static WMPropList *AStartMiniaturized;
78 static WMPropList *AStartMaximized;
79 static WMPropList *AStartHidden; /* app */
80 static WMPropList *ADontSaveSession; /* app */
81 static WMPropList *AEmulateAppIcon;
82 static WMPropList *AFocusAcrossWorkspace;
83 static WMPropList *AFullMaximize;
84 static WMPropList *ASharedAppIcon; /* app */
85 #ifdef XKB_BUTTON_HINT
86 static WMPropList *ANoLanguageButton;
87 #endif
88 static WMPropList *AStartWorkspace;
89 static WMPropList *AIcon;
90 static WMPropList *AnyWindow;
91 static WMPropList *No;
93 static void init_wdefaults(void)
95 AIcon = WMCreatePLString("Icon");
97 ANoTitlebar = WMCreatePLString("NoTitlebar");
98 ANoResizebar = WMCreatePLString("NoResizebar");
99 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
100 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
101 ANoCloseButton = WMCreatePLString("NoCloseButton");
102 ANoBorder = WMCreatePLString("NoBorder");
103 ANoHideOthers = WMCreatePLString("NoHideOthers");
104 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
105 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
106 ANoAppIcon = WMCreatePLString("NoAppIcon");
107 AKeepOnTop = WMCreatePLString("KeepOnTop");
108 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
109 AOmnipresent = WMCreatePLString("Omnipresent");
110 ASkipWindowList = WMCreatePLString("SkipWindowList");
111 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
112 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
113 AUnfocusable = WMCreatePLString("Unfocusable");
114 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
115 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
116 AStartHidden = WMCreatePLString("StartHidden");
117 AStartMaximized = WMCreatePLString("StartMaximized");
118 ADontSaveSession = WMCreatePLString("DontSaveSession");
119 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
120 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
121 AFullMaximize = WMCreatePLString("FullMaximize");
122 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
123 #ifdef XKB_BUTTON_HINT
124 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
125 #endif
127 AStartWorkspace = WMCreatePLString("StartWorkspace");
129 AnyWindow = WMCreatePLString("*");
130 No = WMCreatePLString("No");
133 /* Returns the correct WMPropList, using instance+class or instance, or class, or default */
134 static WMPropList *get_value(WMPropList * dict_win, WMPropList * dict_class, WMPropList * dict_name,
135 WMPropList * dict_any, WMPropList * option, WMPropList * default_value,
136 Bool useGlobalDefault)
138 WMPropList *value;
140 if (dict_win) {
141 value = WMGetFromPLDictionary(dict_win, option);
142 if (value)
143 return value;
146 if (dict_name) {
147 value = WMGetFromPLDictionary(dict_name, option);
148 if (value)
149 return value;
152 if (dict_class) {
153 value = WMGetFromPLDictionary(dict_class, option);
154 if (value)
155 return value;
158 if (!useGlobalDefault)
159 return NULL;
161 if (dict_any) {
162 value = WMGetFromPLDictionary(dict_any, option);
163 if (value)
164 return value;
167 return default_value;
170 static WMPropList *get_value_from_instanceclass(char *value)
172 WMPropList *key, *val = NULL;
174 if (!value)
175 return NULL;
177 key = WMCreatePLString(value);
179 WMPLSetCaseSensitive(True);
181 if (WDWindowAttributes->dictionary)
182 val = key ? WMGetFromPLDictionary(WDWindowAttributes->dictionary, key) : NULL;
184 if (key)
185 WMReleasePropList(key);
187 WMPLSetCaseSensitive(False);
189 return val;
193 *----------------------------------------------------------------------
194 * wDefaultFillAttributes--
195 * Retrieves attributes for the specified instance/class and
196 * fills attr with it. Values that are actually defined are also
197 * set in mask. If useGlobalDefault is True, the default for
198 * all windows ("*") will be used for when no values are found
199 * for that instance/class.
201 *----------------------------------------------------------------------
203 void wDefaultFillAttributes(char *instance, char *class,
204 WWindowAttributes *attr, WWindowAttributes *mask,
205 Bool useGlobalDefault)
207 WMPropList *value, *dw, *dc, *dn, *da;
208 char *buffer;
210 dw = dc = dn = da = NULL;
212 if (!ANoTitlebar)
213 init_wdefaults();
215 if (class && instance) {
216 buffer = StrConcatDot(instance, class);
217 dw = get_value_from_instanceclass(buffer);
218 wfree(buffer);
221 dn = get_value_from_instanceclass(instance);
222 dc = get_value_from_instanceclass(class);
224 WMPLSetCaseSensitive(True);
226 if ((WDWindowAttributes->dictionary) && (useGlobalDefault))
227 da = WMGetFromPLDictionary(WDWindowAttributes->dictionary, AnyWindow);
229 /* get the data */
230 value = get_value(dw, dc, dn, da, ANoTitlebar, No, useGlobalDefault);
231 APPLY_VAL(value, no_titlebar, ANoTitlebar);
233 value = get_value(dw, dc, dn, da, ANoResizebar, No, useGlobalDefault);
234 APPLY_VAL(value, no_resizebar, ANoResizebar);
236 value = get_value(dw, dc, dn, da, ANoMiniaturizeButton, No, useGlobalDefault);
237 APPLY_VAL(value, no_miniaturize_button, ANoMiniaturizeButton);
239 value = get_value(dw, dc, dn, da, ANoMiniaturizable, No, useGlobalDefault);
240 APPLY_VAL(value, no_miniaturizable, ANoMiniaturizable);
242 value = get_value(dw, dc, dn, da, ANoCloseButton, No, useGlobalDefault);
243 APPLY_VAL(value, no_close_button, ANoCloseButton);
245 value = get_value(dw, dc, dn, da, ANoBorder, No, useGlobalDefault);
246 APPLY_VAL(value, no_border, ANoBorder);
248 value = get_value(dw, dc, dn, da, ANoHideOthers, No, useGlobalDefault);
249 APPLY_VAL(value, no_hide_others, ANoHideOthers);
251 value = get_value(dw, dc, dn, da, ANoMouseBindings, No, useGlobalDefault);
252 APPLY_VAL(value, no_bind_mouse, ANoMouseBindings);
254 value = get_value(dw, dc, dn, da, ANoKeyBindings, No, useGlobalDefault);
255 APPLY_VAL(value, no_bind_keys, ANoKeyBindings);
257 value = get_value(dw, dc, dn, da, ANoAppIcon, No, useGlobalDefault);
258 APPLY_VAL(value, no_appicon, ANoAppIcon);
260 value = get_value(dw, dc, dn, da, ASharedAppIcon, No, useGlobalDefault);
261 APPLY_VAL(value, shared_appicon, ASharedAppIcon);
263 value = get_value(dw, dc, dn, da, AKeepOnTop, No, useGlobalDefault);
264 APPLY_VAL(value, floating, AKeepOnTop);
266 value = get_value(dw, dc, dn, da, AKeepOnBottom, No, useGlobalDefault);
267 APPLY_VAL(value, sunken, AKeepOnBottom);
269 value = get_value(dw, dc, dn, da, AOmnipresent, No, useGlobalDefault);
270 APPLY_VAL(value, omnipresent, AOmnipresent);
272 value = get_value(dw, dc, dn, da, ASkipWindowList, No, useGlobalDefault);
273 APPLY_VAL(value, skip_window_list, ASkipWindowList);
275 value = get_value(dw, dc, dn, da, ASkipSwitchPanel, No, useGlobalDefault);
276 APPLY_VAL(value, skip_switchpanel, ASkipSwitchPanel);
278 value = get_value(dw, dc, dn, da, AKeepInsideScreen, No, useGlobalDefault);
279 APPLY_VAL(value, dont_move_off, AKeepInsideScreen);
281 value = get_value(dw, dc, dn, da, AUnfocusable, No, useGlobalDefault);
282 APPLY_VAL(value, no_focusable, AUnfocusable);
284 value = get_value(dw, dc, dn, da, AAlwaysUserIcon, No, useGlobalDefault);
285 APPLY_VAL(value, always_user_icon, AAlwaysUserIcon);
287 value = get_value(dw, dc, dn, da, AStartMiniaturized, No, useGlobalDefault);
288 APPLY_VAL(value, start_miniaturized, AStartMiniaturized);
290 value = get_value(dw, dc, dn, da, AStartHidden, No, useGlobalDefault);
291 APPLY_VAL(value, start_hidden, AStartHidden);
293 value = get_value(dw, dc, dn, da, AStartMaximized, No, useGlobalDefault);
294 APPLY_VAL(value, start_maximized, AStartMaximized);
296 value = get_value(dw, dc, dn, da, ADontSaveSession, No, useGlobalDefault);
297 APPLY_VAL(value, dont_save_session, ADontSaveSession);
299 value = get_value(dw, dc, dn, da, AEmulateAppIcon, No, useGlobalDefault);
300 APPLY_VAL(value, emulate_appicon, AEmulateAppIcon);
302 value = get_value(dw, dc, dn, da, AFocusAcrossWorkspace, No, useGlobalDefault);
303 APPLY_VAL(value, focus_across_wksp, AFocusAcrossWorkspace);
305 value = get_value(dw, dc, dn, da, AFullMaximize, No, useGlobalDefault);
306 APPLY_VAL(value, full_maximize, AFullMaximize);
308 #ifdef XKB_BUTTON_HINT
309 value = get_value(dw, dc, dn, da, ANoLanguageButton, No, useGlobalDefault);
310 APPLY_VAL(value, no_language_button, ANoLanguageButton);
311 #endif
313 /* clean up */
314 WMPLSetCaseSensitive(False);
317 static WMPropList *get_generic_value(char *instance, char *class,
318 WMPropList *option, Bool default_icon)
320 WMPropList *value, *key, *dict;
322 value = NULL;
324 WMPLSetCaseSensitive(True);
326 /* Search the icon name using class and instance */
327 if (class && instance) {
328 char *buffer;
330 buffer = wmalloc(strlen(class) + strlen(instance) + 2);
331 sprintf(buffer, "%s.%s", instance, class);
332 key = WMCreatePLString(buffer);
333 wfree(buffer);
335 dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key);
336 WMReleasePropList(key);
338 if (dict)
339 value = WMGetFromPLDictionary(dict, option);
342 /* Search the icon name using instance */
343 if (!value && instance) {
344 key = WMCreatePLString(instance);
346 dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key);
347 WMReleasePropList(key);
349 if (dict)
350 value = WMGetFromPLDictionary(dict, option);
353 /* Search the icon name using class */
354 if (!value && class) {
355 key = WMCreatePLString(class);
357 dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key);
358 WMReleasePropList(key);
360 if (dict)
361 value = WMGetFromPLDictionary(dict, option);
364 /* Search the default icon name - See default_icon argument! */
365 if (!value && default_icon) {
366 /* AnyWindow is "*" - see wdefaults.c */
367 dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, AnyWindow);
369 if (dict)
370 value = WMGetFromPLDictionary(dict, option);
373 WMPLSetCaseSensitive(False);
375 return value;
378 /* Get the file name of the image, using instance and class */
379 char *get_default_icon_filename(WScreen *scr, char *winstance, char *wclass, char *command,
380 Bool default_icon)
382 char *file_name = NULL;
383 char *file_path = NULL;
385 /* Get the file name of the image, using instance and class */
386 file_name = wDefaultGetIconFile(winstance, wclass, default_icon);
388 /* Check if the file really exists in the disk */
389 if (file_name)
390 file_path = FindImage(wPreferences.icon_path, file_name);
392 /* If the specific (or generic if default_icon is True) icon filename
393 * is not found, and command is specified, then include the .app icons
394 * and re-do the search, but now always including the default icon
395 * so the icon is found always. The .app is selected before default */
396 if ((!file_name || !file_path ) && scr && command) {
397 wApplicationExtractDirPackIcon(scr, command, winstance, wclass);
398 file_name = wDefaultGetIconFile(winstance, wclass, True);
401 /* Get the full path for the image file */
402 if (file_name) {
403 file_path = FindImage(wPreferences.icon_path, file_name);
405 if (!file_path)
406 wwarning(_("could not find icon file \"%s\""), file_name);
408 /* FIXME: Here, if file_path don't exists, then the icon is in the
409 * "icon database" (WDWindowAttributes->dictionary), but the icon
410 * is not en disk. Therefore, we should remove it from the icon
411 * database.
412 * OTOH, probably the correct message should be "could not find the
413 * icon file %s, please, check your configuration files", because
414 * the icons are loaded in the icon database from the configuration
415 * files
418 /* Don't wfree(file_name) here, because is a pointer to the icon
419 * dictionary (WDWindowAttributes->dictionary) value.
423 if (!file_path && default_icon)
424 file_path = get_default_image_path(scr);
426 return file_path;
429 /* This function returns the image picture for the file_name file */
430 RImage *get_rimage_from_file(WScreen *scr, char *file_name, int max_size)
432 RImage *image = NULL;
434 if (!file_name)
435 return NULL;
437 image = RLoadImage(scr->rcontext, file_name, 0);
438 if (!image)
439 wwarning(_("error loading image file \"%s\": %s"), file_name,
440 RMessageForError(RErrorCode));
442 image = wIconValidateIconSize(image, max_size);
444 return image;
447 /* This function returns the default icon's full path
448 * If the path for an icon is not found, returns NULL */
449 char *get_default_image_path(WScreen *scr)
451 char *path = NULL, *file = NULL;
453 /* Get the default icon */
454 file = wDefaultGetIconFile(NULL, NULL, True);
455 if (file)
456 path = FindImage(wPreferences.icon_path, file);
458 return path;
461 /* This function creates the RImage using the default icon */
462 RImage *get_default_image(WScreen *scr)
464 RImage *image = NULL;
465 char *path = NULL;
467 /* Get the filename full path */
468 path = get_default_image_path(scr);
469 if (!path)
470 return NULL;
472 /* Get the default icon */
473 image = get_rimage_from_file(scr, path, wPreferences.icon_size);
474 if (!image)
475 wwarning(_("could not find default icon \"%s\""), path);
477 return image;
480 RImage *wDefaultGetImage(WScreen *scr, char *winstance, char *wclass, int max_size)
482 char *file_name = NULL;
484 /* Get the file name of the image, using instance and class */
485 file_name = get_default_icon_filename(scr, winstance, wclass, NULL, True);
487 /* If no filename, is because the winstance and wclass in the database
488 * returns a invalid icon (config file error), then should be removed FIXME! */
489 if (!file_name) {
490 wwarning(_("icon \"%s\" doesn't exist, check your config files"), file_name);
491 file_name = get_default_image_path(scr);
494 return get_rimage_from_file(scr, file_name, max_size);
497 int wDefaultGetStartWorkspace(WScreen * scr, char *instance, char *class)
499 WMPropList *value;
500 int w;
501 char *tmp;
503 if (!ANoTitlebar)
504 init_wdefaults();
506 if (!WDWindowAttributes->dictionary)
507 return -1;
509 value = get_generic_value(instance, class, AStartWorkspace, True);
511 if (!value)
512 return -1;
514 tmp = getString(AStartWorkspace, value);
516 if (!tmp || strlen(tmp) == 0)
517 return -1;
519 /* Get the workspace number for the workspace name */
520 w = wGetWorkspaceNumber(scr, tmp);
522 return w;
525 /* Get the name of the Icon File. If default_icon is True, then, default value included */
526 char *wDefaultGetIconFile(char *instance, char *class, Bool default_icon)
528 WMPropList *value;
529 char *tmp;
531 if (!ANoTitlebar)
532 init_wdefaults();
534 if (!WDWindowAttributes || !WDWindowAttributes->dictionary)
535 return NULL;
537 value = get_generic_value(instance, class, AIcon, default_icon);
539 if (!value)
540 return NULL;
542 tmp = getString(AIcon, value);
544 return tmp;
547 void wDefaultChangeIcon(WScreen * scr, char *instance, char *class, char *file)
549 WDDomain *db = WDWindowAttributes;
550 WMPropList *icon_value = NULL, *value, *attr, *key, *def_win, *def_icon = NULL;
551 WMPropList *dict = db->dictionary;
552 int same = 0;
554 if (!dict) {
555 dict = WMCreatePLDictionary(NULL, NULL);
556 if (dict)
557 db->dictionary = dict;
558 else
559 return;
562 WMPLSetCaseSensitive(True);
564 if (instance && class) {
565 char *buffer;
567 buffer = StrConcatDot(instance, class);
568 key = WMCreatePLString(buffer);
569 wfree(buffer);
570 } else if (instance) {
571 key = WMCreatePLString(instance);
572 } else if (class) {
573 key = WMCreatePLString(class);
574 } else {
575 key = WMRetainPropList(AnyWindow);
578 if (file) {
579 value = WMCreatePLString(file);
580 icon_value = WMCreatePLDictionary(AIcon, value, NULL);
581 WMReleasePropList(value);
583 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL)
584 def_icon = WMGetFromPLDictionary(def_win, AIcon);
586 if (def_icon && !strcmp(WMGetFromPLString(def_icon), file))
587 same = 1;
590 if ((attr = WMGetFromPLDictionary(dict, key)) != NULL) {
591 if (WMIsPLDictionary(attr)) {
592 if (icon_value != NULL && !same)
593 WMMergePLDictionaries(attr, icon_value, False);
594 else
595 WMRemoveFromPLDictionary(attr, AIcon);
597 } else if (icon_value != NULL && !same) {
598 WMPutInPLDictionary(dict, key, icon_value);
601 if (!wPreferences.flags.noupdates)
602 UpdateDomainFile(db);
604 WMReleasePropList(key);
605 if (icon_value)
606 WMReleasePropList(icon_value);
608 WMPLSetCaseSensitive(False);
611 /* --------------------------- Local ----------------------- */
613 static int getBool(WMPropList * key, WMPropList * value)
615 char *val;
617 if (!WMIsPLString(value)) {
618 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
619 WMGetFromPLString(key), "Boolean");
620 return 0;
622 val = WMGetFromPLString(value);
624 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
625 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
627 return 1;
628 } else if ((val[1] == '\0'
629 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
630 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
632 return 0;
633 } else {
634 wwarning(_("can't convert \"%s\" to boolean"), val);
635 /* We return False if we can't convert to BOOLEAN.
636 * This is because all options defaults to False.
637 * -1 is not checked and thus is interpreted as True,
638 * which is not good.*/
639 return 0;
643 /* WARNING: Do not free the value returned by this function!! */
644 static char *getString(WMPropList * key, WMPropList * value)
646 if (!WMIsPLString(value)) {
647 wwarning(_("Wrong option format for key \"%s\". Should be %s."), WMGetFromPLString(key), "String");
648 return NULL;
651 return WMGetFromPLString(value);