This update includes the 0.20.3pre3 code
[wmaker-crm.git] / src / defaults.c
blobbc8a32e8db530411cf459167e6c3098a66bf9560
1 /* defaults.c - manage configuration through defaults db
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 *
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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
23 #include "wconfig.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <time.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <limits.h>
35 #ifndef PATH_MAX
36 #define PATH_MAX DEFAULT_PATH_MAX
37 #endif
39 #include <X11/Xlib.h>
40 #include <X11/Xutil.h>
41 #include <X11/keysym.h>
43 #include <wraster.h>
46 #include "WindowMaker.h"
47 #include "wcore.h"
48 #include "framewin.h"
49 #include "window.h"
50 #include "texture.h"
51 #include "screen.h"
52 #include "resources.h"
53 #include "defaults.h"
54 #include "keybind.h"
55 #include "xmodifier.h"
56 #include "icon.h"
57 #include "funcs.h"
58 #include "actions.h"
59 #include "dock.h"
60 #include "workspace.h"
64 * Our own proplist reader parser. This one will not accept any
65 * syntax errors and is more descriptive in the error messages.
66 * It also doesn't seem to crash.
68 extern proplist_t ReadProplistFromFile(char *file);
71 /***** Global *****/
73 extern WDDomain *WDWindowMaker;
74 extern WDDomain *WDWindowAttributes;
75 extern WDDomain *WDRootMenu;
77 extern int wScreenCount;
80 extern proplist_t wDomainName;
81 extern proplist_t wAttributeDomainName;
83 extern WPreferences wPreferences;
85 extern WShortKey wKeyBindings[WKBD_LAST];
87 typedef struct {
88 char *key;
89 char *default_value;
90 void *extra_data;
91 void *addr;
92 int (*convert)();
93 int (*update)();
94 proplist_t plkey;
95 proplist_t plvalue;
96 } WDefaultEntry;
99 /* used to map strings to integers */
100 typedef struct {
101 char *string;
102 short value;
103 char is_alias;
104 } WOptionEnumeration;
108 /* type converters */
109 static int getBool();
110 static int getInt();
111 static int getCoord();
112 #if 0
113 /* this is not used yet */
114 static int getString();
115 #endif
116 static int getPathList();
117 static int getEnum();
118 static int getTexture();
119 static int getWSBackground();
120 static int getFont();
121 static int getColor();
122 static int getKeybind();
123 static int getModMask();
126 /* value setting functions */
127 static int setJustify();
128 static int setIfDockPresent();
129 static int setStickyIcons();
131 static int setPositive();
133 static int setWidgetColor();
134 static int setIconTile();
135 static int setWinTitleFont();
136 static int setMenuTitleFont();
137 static int setMenuTextFont();
138 static int setIconTitleFont();
139 static int setDisplayFont();
140 static int setWTitleColor();
141 static int setFTitleBack();
142 static int setPTitleBack();
143 static int setUTitleBack();
144 static int setWorkspaceBack();
145 static int setMenuTitleColor();
146 static int setMenuTextColor();
147 static int setMenuDisabledColor();
148 static int setMenuTitleBack();
149 static int setMenuTextBack();
150 static int setHightlight();
151 static int setHightlightText();
152 static int setKeyGrab();
153 static int setDoubleClick();
154 static int setIconPosition();
156 static int setClipTitleFont();
157 static int setClipTitleColor();
162 * Tables to convert strings to enumeration values.
163 * Values stored are char
167 /* WARNING: sum of length of all value strings must not exceed
168 * this value */
169 #define TOTAL_VALUES_LENGTH 80
173 static WOptionEnumeration seFocusModes[] = {
174 {"Manual", WKF_CLICK, 0}, {"ClickToFocus", WKF_CLICK, 1},
175 {"Auto", WKF_POINTER, 0}, {"FocusFollowMouse", WKF_POINTER, 1},
176 {"Sloppy", WKF_SLOPPY, 0}, {"SemiAuto", WKF_SLOPPY, 1},
177 {NULL, 0, 0}
180 static WOptionEnumeration seColormapModes[] = {
181 {"Manual", WKF_CLICK, 0}, {"ClickToFocus", WKF_CLICK, 1},
182 {"Auto", WKF_POINTER, 0}, {"FocusFollowMouse", WKF_POINTER, 1},
183 {NULL, 0, 0}
186 static WOptionEnumeration sePlacements[] = {
187 {"Auto", WPM_SMART, 0}, {"Smart", WPM_SMART, 1},
188 {"Cascade", WPM_CASCADE, 0},
189 {"Random", WPM_RANDOM, 0},
190 {"Manual", WPM_MANUAL, 0},
191 {NULL, 0, 0}
194 static WOptionEnumeration seGeomDisplays[] = {
195 {"Center", WDIS_CENTER, 0},
196 {"Corner", WDIS_TOPLEFT, 0},
197 {"Floating", WDIS_FRAME_CENTER, 0},
198 {"Line", WDIS_NEW, 0},
199 {NULL, 0, 0}
202 static WOptionEnumeration seSpeeds[] = {
203 {"UltraFast", SPEED_ULTRAFAST, 0},
204 {"Fast", SPEED_FAST, 0},
205 {"Medium", SPEED_MEDIUM, 0},
206 {"Slow", SPEED_SLOW, 0},
207 {"UltraSlow", SPEED_ULTRASLOW, 0},
208 {NULL, 0, 0}
211 static WOptionEnumeration seMouseButtons[] = {
212 {"Left", Button1, 0}, {"Button1", Button1, 1},
213 {"Middle", Button2, 0}, {"Button2", Button2, 1},
214 {"Right", Button3, 0}, {"Button3", Button3, 1},
215 {"Button4", Button4, 0},
216 {"Button5", Button5, 0},
217 {NULL, 0, 0}
220 static WOptionEnumeration seIconificationStyles[] = {
221 {"Zoom", WIS_ZOOM, 0},
222 {"Twist", WIS_TWIST, 0},
223 {"Flip", WIS_FLIP, 0},
224 {"None", WIS_NONE, 0},
225 {NULL, 0, 0}
228 static WOptionEnumeration seJustifications[] = {
229 {"Left", WTJ_LEFT, 0},
230 {"Center", WTJ_CENTER, 0},
231 {"Right", WTJ_RIGHT, 0},
232 {NULL, 0, 0}
235 static WOptionEnumeration seIconPositions[] = {
236 {"blv", IY_BOTTOM|IY_LEFT|IY_VERT, 0},
237 {"blh", IY_BOTTOM|IY_LEFT|IY_HORIZ, 0},
238 {"brv", IY_BOTTOM|IY_RIGHT|IY_VERT, 0},
239 {"brh", IY_BOTTOM|IY_RIGHT|IY_HORIZ, 0},
240 {"tlv", IY_TOP|IY_LEFT|IY_VERT, 0},
241 {"tlh", IY_TOP|IY_LEFT|IY_HORIZ, 0},
242 {"trv", IY_TOP|IY_RIGHT|IY_VERT, 0},
243 {"trh", IY_TOP|IY_RIGHT|IY_HORIZ, 0},
244 {NULL, 0, 0}
250 * All entries in the tables bellow, NEED to have a default value
251 * defined, and this value needs to be correct.
254 /* these options will only affect the window manager on startup
256 * static defaults can't access the screen data, because it is
257 * created after these defaults are read
259 WDefaultEntry staticOptionList[] = {
261 {"DisableDithering", "NO", NULL,
262 &wPreferences.no_dithering, getBool, NULL
264 {"ColormapSize", "4", NULL,
265 &wPreferences.cmap_size, getInt, NULL
267 /* static by laziness */
268 {"IconSize", "64", NULL,
269 &wPreferences.icon_size, getInt, NULL
271 {"ModifierKey", "Mod1", NULL,
272 &wPreferences.modifier_mask, getModMask, NULL
274 {"DisableWSMouseActions", "NO", NULL,
275 &wPreferences.disable_root_mouse, getBool, NULL
277 {"FocusMode", "manual", seFocusModes,
278 &wPreferences.focus_mode, getEnum, NULL
279 }, /* have a problem when switching from manual to sloppy without restart */
280 {"NewStyle", "NO", NULL,
281 &wPreferences.new_style, getBool, NULL
283 {"DisableDock", "NO", (void*) WM_DOCK,
284 NULL, getBool, setIfDockPresent
286 {"DisableClip", "NO", (void*) WM_CLIP,
287 NULL, getBool, setIfDockPresent
293 WDefaultEntry optionList[] = {
294 /* dynamic options */
295 {"IconPosition", "blh", seIconPositions,
296 &wPreferences.icon_yard, getEnum, setIconPosition
298 {"IconificationStyle", "Zoom", seIconificationStyles,
299 &wPreferences.iconification_style, getEnum, NULL
301 {"SelectWindowsMouseButton", "Left", seMouseButtons,
302 &wPreferences.select_button, getEnum, NULL
304 {"WindowListMouseButton", "Middle", seMouseButtons,
305 &wPreferences.windowl_button, getEnum, NULL
307 {"ApplicationMenuMouseButton", "Right", seMouseButtons,
308 &wPreferences.menu_button, getEnum, NULL
310 {"PixmapPath", DEF_PIXMAP_PATHS, NULL,
311 &wPreferences.pixmap_path, getPathList, NULL
313 {"IconPath", DEF_ICON_PATHS, NULL,
314 &wPreferences.icon_path, getPathList, NULL
316 {"ColormapMode", "auto", seColormapModes,
317 &wPreferences.colormap_mode, getEnum, NULL
319 {"AutoFocus", "NO", NULL,
320 &wPreferences.auto_focus, getBool, NULL
322 {"RaiseDelay", "0", NULL,
323 &wPreferences.raise_delay, getInt, NULL
325 {"CirculateRaise", "NO", NULL,
326 &wPreferences.circ_raise, getBool, NULL
328 {"Superfluous", "NO", NULL,
329 &wPreferences.superfluous, getBool, NULL
331 {"AdvanceToNewWorkspace", "NO", NULL,
332 &wPreferences.ws_advance, getBool, NULL
334 {"CycleWorkspaces", "NO", NULL,
335 &wPreferences.ws_cycle, getBool, NULL
337 {"StickyIcons", "NO", NULL,
338 &wPreferences.sticky_icons, getBool, setStickyIcons
340 {"SaveSessionOnExit", "NO", NULL,
341 &wPreferences.save_session_on_exit, getBool, NULL
343 {"WrapMenus", "NO", NULL,
344 &wPreferences.wrap_menus, getBool, NULL
346 {"ScrollableMenus", "NO", NULL,
347 &wPreferences.scrollable_menus, getBool, NULL
349 {"MenuScrollSpeed", "medium", seSpeeds,
350 &wPreferences.menu_scroll_speed, getEnum, NULL
352 {"IconSlideSpeed", "medium", seSpeeds,
353 &wPreferences.icon_slide_speed, getEnum, NULL
355 {"ShadeSpeed", "medium", seSpeeds,
356 &wPreferences.shade_speed, getEnum, NULL
358 {"DoubleClickTime", "250", (void*) &wPreferences.dblclick_time,
359 &wPreferences.dblclick_time, getInt, setDoubleClick,
361 {"AlignSubmenus", "NO", NULL,
362 &wPreferences.align_menus, getBool, NULL
364 {"OnTopTransients", "NO", NULL,
365 &wPreferences.on_top_transients, getBool, NULL
367 {"WindowPlacement", "auto", sePlacements,
368 &wPreferences.window_placement, getEnum, NULL
370 {"IgnoreFocusClick","NO", NULL,
371 &wPreferences.ignore_focus_click, getBool, NULL
373 {"UseSaveUnders", "NO", NULL,
374 &wPreferences.use_saveunders, getBool, NULL
376 {"OpaqueMove", "NO", NULL,
377 &wPreferences.opaque_move, getBool, NULL
379 {"DisableSound", "NO", NULL,
380 &wPreferences.no_sound, getBool, NULL
382 {"DisableAnimations", "NO", NULL,
383 &wPreferences.no_animations, getBool, NULL
385 {"DontLinkWorkspaces","NO", NULL,
386 &wPreferences.no_autowrap, getBool, NULL
388 {"EdgeResistance", "0", NULL,
389 &wPreferences.edge_resistance,getInt, NULL
391 {"AutoArrangeIcons", "NO", NULL,
392 &wPreferences.auto_arrange_icons, getBool, NULL
394 {"NoWindowUnderDock", "NO", NULL,
395 &wPreferences.no_window_under_dock, getBool, NULL
397 {"NoWindowOverIcons", "NO", NULL,
398 &wPreferences.no_window_over_icons, getBool, NULL
400 {"WindowPlaceOrigin", "(0, 0)", NULL,
401 &wPreferences.window_place_origin, getCoord, NULL
403 {"ResizeDisplay", "corner", seGeomDisplays,
404 &wPreferences.size_display, getEnum, NULL
406 {"MoveDisplay", "corner", seGeomDisplays,
407 &wPreferences.move_display, getEnum, NULL
409 {"DontConfirmKill", "NO", NULL,
410 &wPreferences.dont_confirm_kill, getBool,NULL
412 {"WindowTitleBalloons", "NO", NULL,
413 &wPreferences.window_balloon, getBool, NULL
415 {"MiniwindowTitleBalloons", "NO", NULL,
416 &wPreferences.miniwin_balloon,getBool, NULL
418 {"AppIconBalloons", "NO", NULL,
419 &wPreferences.appicon_balloon,getBool, NULL
421 {"DisableBlinking", "NO", NULL,
422 &wPreferences.dont_blink, getBool, NULL
424 /* style options */
425 {"WidgetColor", "(solid, gray)", NULL,
426 NULL, getTexture, setWidgetColor,
428 {"WorkspaceBack", "(solid, black)", NULL,
429 NULL, getWSBackground,setWorkspaceBack
431 {"IconBack", "(solid, gray)", NULL,
432 NULL, getTexture, setIconTile
434 {"TitleJustify", "center", seJustifications,
435 &wPreferences.title_justification, getEnum, setJustify
437 {"WindowTitleFont", DEF_TITLE_FONT, NULL,
438 NULL, getFont, setWinTitleFont
440 {"MenuTitleFont", DEF_MENU_TITLE_FONT, NULL,
441 NULL, getFont, setMenuTitleFont
443 {"MenuTextFont", DEF_MENU_ENTRY_FONT, NULL,
444 NULL, getFont, setMenuTextFont
446 {"IconTitleFont", DEF_ICON_TITLE_FONT, NULL,
447 NULL, getFont, setIconTitleFont
449 {"ClipTitleFont", DEF_CLIP_TITLE_FONT, NULL,
450 NULL, getFont, setClipTitleFont
452 {"DisplayFont", DEF_INFO_TEXT_FONT, NULL,
453 NULL, getFont, setDisplayFont
455 {"HighlightColor", "white", NULL,
456 NULL, getColor, setHightlight
458 {"HighlightTextColor", "black", NULL,
459 NULL, getColor, setHightlightText
461 {"ClipTitleColor", "black", (void*)CLIP_NORMAL,
462 NULL, getColor, setClipTitleColor
464 {"CClipTitleColor", "\"#454045\"", (void*)CLIP_COLLAPSED,
465 NULL, getColor, setClipTitleColor
467 {"FTitleColor", "white", (void*)WS_FOCUSED,
468 NULL, getColor, setWTitleColor
470 {"PTitleColor", "white", (void*)WS_PFOCUSED,
471 NULL, getColor, setWTitleColor
473 {"UTitleColor", "black", (void*)WS_UNFOCUSED,
474 NULL, getColor, setWTitleColor
476 {"FTitleBack", "(solid, black)", NULL,
477 NULL, getTexture, setFTitleBack
479 {"PTitleBack", "(solid, \"#616161\")", NULL,
480 NULL, getTexture, setPTitleBack
482 {"UTitleBack", "(solid, gray)", NULL,
483 NULL, getTexture, setUTitleBack
485 {"MenuTitleColor", "white", NULL,
486 NULL, getColor, setMenuTitleColor
488 {"MenuTextColor", "black", NULL,
489 NULL, getColor, setMenuTextColor
491 {"MenuDisabledColor", "\"#616161\"", NULL,
492 NULL, getColor, setMenuDisabledColor
494 {"MenuTitleBack", "(solid, black)", NULL,
495 NULL, getTexture, setMenuTitleBack
497 {"MenuTextBack", "(solid, gray)", NULL,
498 NULL, getTexture, setMenuTextBack
501 /* keybindings */
502 {"RootMenuKey", "None", (void*)WKBD_ROOTMENU,
503 NULL, getKeybind, setKeyGrab
505 {"WindowListKey", "None", (void*)WKBD_WINDOWLIST,
506 NULL, getKeybind, setKeyGrab
508 {"WindowMenuKey", "None", (void*)WKBD_WINDOWMENU,
509 NULL, getKeybind, setKeyGrab
511 {"ClipLowerKey", "None", (void*)WKBD_CLIPLOWER,
512 NULL, getKeybind, setKeyGrab
514 {"ClipRaiseKey", "None", (void*)WKBD_CLIPRAISE,
515 NULL, getKeybind, setKeyGrab
517 {"ClipRaiseLowerKey", "None", (void*)WKBD_CLIPRAISELOWER,
518 NULL, getKeybind, setKeyGrab
520 {"MiniaturizeKey", "None", (void*)WKBD_MINIATURIZE,
521 NULL, getKeybind, setKeyGrab
523 {"HideKey", "None", (void*)WKBD_HIDE,
524 NULL, getKeybind, setKeyGrab
526 {"CloseKey", "None", (void*)WKBD_CLOSE,
527 NULL, getKeybind, setKeyGrab
529 {"MaximizeKey", "None", (void*)WKBD_MAXIMIZE,
530 NULL, getKeybind, setKeyGrab
532 {"VMaximizeKey", "None", (void*)WKBD_VMAXIMIZE,
533 NULL, getKeybind, setKeyGrab
535 {"RaiseKey", "Meta+Up", (void*)WKBD_RAISE,
536 NULL, getKeybind, setKeyGrab
538 {"LowerKey", "Meta+Down", (void*)WKBD_LOWER,
539 NULL, getKeybind, setKeyGrab
541 {"RaiseLowerKey", "None", (void*)WKBD_RAISELOWER,
542 NULL, getKeybind, setKeyGrab
544 {"ShadeKey", "None", (void*)WKBD_SHADE,
545 NULL, getKeybind, setKeyGrab
547 {"SelectKey", "None", (void*)WKBD_SELECT,
548 NULL, getKeybind, setKeyGrab
550 {"FocusNextKey", "None", (void*)WKBD_FOCUSNEXT,
551 NULL, getKeybind, setKeyGrab
553 {"FocusPrevKey", "None", (void*)WKBD_FOCUSPREV,
554 NULL, getKeybind, setKeyGrab
556 {"NextWorkspaceKey", "None", (void*)WKBD_NEXTWORKSPACE,
557 NULL, getKeybind, setKeyGrab
559 {"PrevWorkspaceKey", "None", (void*)WKBD_PREVWORKSPACE,
560 NULL, getKeybind, setKeyGrab
562 {"NextWorkspaceLayerKey", "None", (void*)WKBD_NEXTWSLAYER,
563 NULL, getKeybind, setKeyGrab
565 {"PrevWorkspaceLayerKey", "None", (void*)WKBD_PREVWSLAYER,
566 NULL, getKeybind, setKeyGrab
568 {"Workspace1Key", "None", (void*)WKBD_WORKSPACE1,
569 NULL, getKeybind, setKeyGrab
571 {"Workspace2Key", "None", (void*)WKBD_WORKSPACE2,
572 NULL, getKeybind, setKeyGrab
574 {"Workspace3Key", "None", (void*)WKBD_WORKSPACE3,
575 NULL, getKeybind, setKeyGrab
577 {"Workspace4Key", "None", (void*)WKBD_WORKSPACE4,
578 NULL, getKeybind, setKeyGrab
580 {"Workspace5Key", "None", (void*)WKBD_WORKSPACE5,
581 NULL, getKeybind, setKeyGrab
583 {"Workspace6Key", "None", (void*)WKBD_WORKSPACE6,
584 NULL, getKeybind, setKeyGrab
586 {"Workspace7Key", "None", (void*)WKBD_WORKSPACE7,
587 NULL, getKeybind, setKeyGrab
589 {"Workspace8Key", "None", (void*)WKBD_WORKSPACE8,
590 NULL, getKeybind, setKeyGrab
592 {"Workspace9Key", "None", (void*)WKBD_WORKSPACE9,
593 NULL, getKeybind, setKeyGrab
595 {"Workspace10Key", "None", (void*)WKBD_WORKSPACE10,
596 NULL, getKeybind, setKeyGrab
598 {"WindowShortcut1Key","None", (void*)WKBD_WINDOW1,
599 NULL, getKeybind, setKeyGrab
601 {"WindowShortcut2Key","None", (void*)WKBD_WINDOW2,
602 NULL, getKeybind, setKeyGrab
604 {"WindowShortcut3Key","None", (void*)WKBD_WINDOW3,
605 NULL, getKeybind, setKeyGrab
607 {"WindowShortcut4Key","None", (void*)WKBD_WINDOW4,
608 NULL, getKeybind, setKeyGrab
610 #ifdef KEEP_XKB_LOCK_STATUS
611 {"ToggleKbdModeKey", "None", (void*)WKBD_TOGGLE,
612 NULL, getKeybind, setKeyGrab
614 {"KbdModeLock", "NO", NULL,
615 &wPreferences.modelock, getBool, NULL
617 #endif /* KEEP_XKB_LOCK_STATUS */
621 #if 0
622 static void rereadDefaults(void);
623 #endif
625 #if 0
626 static void
627 rereadDefaults(void)
629 /* must defer the update because accessing X data from a
630 * signal handler can mess up Xlib */
633 #endif
635 static void
636 initDefaults()
638 int i;
639 WDefaultEntry *entry;
641 PLSetStringCmpHook(StringCompareHook);
643 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
644 entry = &optionList[i];
646 entry->plkey = PLMakeString(entry->key);
647 if (entry->default_value)
648 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
649 else
650 entry->plvalue = NULL;
653 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
654 entry = &staticOptionList[i];
656 entry->plkey = PLMakeString(entry->key);
657 if (entry->default_value)
658 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
659 else
660 entry->plvalue = NULL;
664 wDomainName = PLMakeString(WMDOMAIN_NAME);
665 wAttributeDomainName = PLMakeString(WMATTRIBUTE_DOMAIN_NAME);
667 PLRegister(wDomainName, rereadDefaults);
668 PLRegister(wAttributeDomainName, rereadDefaults);
675 #if 0
676 proplist_t
677 wDefaultsInit(int screen_number)
679 static int defaults_inited = 0;
680 proplist_t dict;
682 if (!defaults_inited) {
683 initDefaults();
686 dict = PLGetDomain(wDomainName);
687 if (!dict) {
688 wwarning(_("could not read domain \"%s\" from defaults database"),
689 PLGetString(wDomainName));
692 return dict;
694 #endif
697 void
698 wDefaultsDestroyDomain(WDDomain *domain)
700 if (domain->dictionary)
701 PLRelease(domain->dictionary);
702 free(domain->path);
703 free(domain);
707 WDDomain*
708 wDefaultsInitDomain(char *domain, Bool requireDictionary)
710 WDDomain *db;
711 struct stat stbuf;
712 static int inited = 0;
713 char path[PATH_MAX];
714 char *the_path;
715 proplist_t shared_dict=NULL;
717 if (!inited) {
718 inited = 1;
719 initDefaults();
722 db = wmalloc(sizeof(WDDomain));
723 memset(db, 0, sizeof(WDDomain));
724 db->domain_name = domain;
725 db->path = wdefaultspathfordomain(domain);
726 the_path = db->path;
728 if (the_path && stat(the_path, &stbuf)>=0) {
729 db->dictionary = ReadProplistFromFile(the_path);
730 if (db->dictionary) {
731 if (requireDictionary && !PLIsDictionary(db->dictionary)) {
732 PLRelease(db->dictionary);
733 db->dictionary = NULL;
734 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
735 domain, the_path);
737 db->timestamp = stbuf.st_mtime;
738 } else {
739 wwarning(_("could not load domain %s from user defaults database"),
740 domain);
744 /* global system dictionary */
745 sprintf(path, "%s/%s/%s", PKGDATADIR, DEFAULTS_DIR, domain);
746 if (stat(path, &stbuf)>=0) {
747 shared_dict = ReadProplistFromFile(path);
748 if (shared_dict) {
749 if (requireDictionary && !PLIsDictionary(shared_dict)) {
750 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
751 domain, path);
752 PLRelease(shared_dict);
753 shared_dict = NULL;
754 } else {
755 if (db->dictionary && PLIsDictionary(shared_dict) &&
756 PLIsDictionary(db->dictionary)) {
757 PLMergeDictionaries(shared_dict, db->dictionary);
758 PLRelease(db->dictionary);
759 db->dictionary = shared_dict;
760 if (stbuf.st_mtime > db->timestamp)
761 db->timestamp = stbuf.st_mtime;
762 } else if (!db->dictionary) {
763 db->dictionary = shared_dict;
764 if (stbuf.st_mtime > db->timestamp)
765 db->timestamp = stbuf.st_mtime;
768 } else {
769 wwarning(_("could not load domain %s from global defaults database"),
770 domain);
774 /* set to save it in user's directory, no matter from where it was read */
775 if (db->dictionary) {
776 proplist_t tmp = PLMakeString(db->path);
778 PLSetFilename(db->dictionary, tmp);
779 PLRelease(tmp);
782 return db;
786 void
787 wReadStaticDefaults(proplist_t dict)
789 proplist_t plvalue;
790 WDefaultEntry *entry;
791 int i;
792 void *tdata;
795 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
796 entry = &staticOptionList[i];
798 if (dict)
799 plvalue = PLGetDictionaryEntry(dict, entry->plkey);
800 else
801 plvalue = NULL;
803 if (!plvalue) {
804 /* no default in the DB. Use builtin default */
805 plvalue = entry->plvalue;
808 if (plvalue) {
809 /* convert data */
810 (*entry->convert)(NULL, entry, plvalue, entry->addr, &tdata);
811 if (entry->update) {
812 (*entry->update)(NULL, entry, tdata, entry->extra_data);
818 void
819 wDefaultsCheckDomains(void *foo)
821 WScreen *scr;
822 struct stat stbuf;
823 proplist_t dict;
824 int i;
825 char path[PATH_MAX];
827 #ifdef HEARTBEAT
828 puts("Checking domains...");
829 #endif
830 if (stat(WDWindowMaker->path, &stbuf)>=0
831 && WDWindowMaker->timestamp < stbuf.st_mtime) {
832 proplist_t shared_dict = NULL;
833 #ifdef HEARTBEAT
834 puts("Checking WindowMaker domain");
835 #endif
836 WDWindowMaker->timestamp = stbuf.st_mtime;
838 /* global dictionary */
839 sprintf(path, "%s/%s/WindowMaker", PKGDATADIR, DEFAULTS_DIR);
840 if (stat(path, &stbuf)>=0) {
841 shared_dict = ReadProplistFromFile(path);
842 if (shared_dict && !PLIsDictionary(shared_dict)) {
843 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
844 "WindowMaker", path);
845 PLRelease(shared_dict);
846 shared_dict = NULL;
847 } else if (!shared_dict) {
848 wwarning(_("could not load domain %s from global defaults database"),
849 "WindowMaker");
852 /* user dictionary */
853 dict = ReadProplistFromFile(WDWindowMaker->path);
854 if (dict) {
855 if (!PLIsDictionary(dict)) {
856 PLRelease(dict);
857 dict = NULL;
858 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
859 "WindowMaker", WDWindowMaker->path);
860 } else {
861 if (shared_dict) {
862 PLSetFilename(shared_dict, PLGetFilename(dict));
863 PLMergeDictionaries(shared_dict, dict);
864 PLRelease(dict);
865 dict = shared_dict;
866 shared_dict = NULL;
868 for (i=0; i<wScreenCount; i++) {
869 scr = wScreenWithNumber(i);
870 if (scr)
871 wReadDefaults(scr, dict);
873 if (WDWindowMaker->dictionary) {
874 PLRelease(WDWindowMaker->dictionary);
876 WDWindowMaker->dictionary = dict;
878 } else {
879 wwarning(_("could not load domain %s from user defaults database"),
880 "WindowMaker");
882 if (shared_dict) {
883 PLRelease(shared_dict);
887 if (stat(WDWindowAttributes->path, &stbuf)>=0
888 && WDWindowAttributes->timestamp < stbuf.st_mtime) {
889 #ifdef HEARTBEAT
890 puts("Checking WMWindowAttributes domain");
891 #endif
892 dict = ReadProplistFromFile(WDWindowAttributes->path);
893 if (dict) {
894 if (!PLIsDictionary(dict)) {
895 PLRelease(dict);
896 dict = NULL;
897 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
898 "WMWindowAttributes", WDWindowAttributes->path);
899 } else {
900 if (WDWindowAttributes->dictionary)
901 PLRelease(WDWindowAttributes->dictionary);
902 WDWindowAttributes->dictionary = dict;
903 for (i=0; i<wScreenCount; i++) {
904 scr = wScreenWithNumber(i);
905 if (scr)
906 wDefaultUpdateIcons(scr);
909 } else {
910 wwarning(_("could not load domain %s from user defaults database"),
911 "WMWindowAttributes");
913 WDWindowAttributes->timestamp = stbuf.st_mtime;
917 if (stat(WDRootMenu->path, &stbuf)>=0
918 && WDRootMenu->timestamp < stbuf.st_mtime) {
919 dict = ReadProplistFromFile(WDRootMenu->path);
920 #ifdef HEARTBEAT
921 puts("Checking WMRootMenu domain");
922 #endif
923 if (dict) {
924 if (!PLIsArray(dict) && !PLIsString(dict)) {
925 PLRelease(dict);
926 dict = NULL;
927 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
928 "WMRootMenu", WDRootMenu->path);
929 } else {
930 if (WDRootMenu->dictionary) {
931 PLRelease(WDRootMenu->dictionary);
933 WDRootMenu->dictionary = dict;
935 } else {
936 wwarning(_("could not load domain %s from user defaults database"),
937 "WMRootMenu");
939 WDRootMenu->timestamp = stbuf.st_mtime;
942 WMAddTimerHandler(DEFAULTS_CHECK_INTERVAL, wDefaultsCheckDomains, foo);
947 #define REFRESH_WINDOW_TEXTURES (1<<0)
948 #define REFRESH_MENU_TEXTURES (1<<1)
949 #define REFRESH_WINDOW_FONT (1<<2)
950 #define REFRESH_MENU_TITLE_FONT (1<<3)
951 #define REFRESH_MENU_FONT (1<<4)
952 #define REFRESH_FORE_COLOR (1<<5)
953 #define REFRESH_ICON_TILE (1<<6)
954 #define REFRESH_ICON_FONT (1<<7)
955 #define REFRESH_WORKSPACE_BACK (1<<8)
957 static void
958 refreshMenus(WScreen *scr, int flags)
960 WMenu *menu;
962 menu = scr->root_menu;
963 if (menu)
964 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
966 menu = scr->workspace_menu;
967 if (menu)
968 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
970 menu = scr->switch_menu;
971 if (menu)
972 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
974 menu = scr->window_menu;
975 if (menu)
976 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
978 menu = scr->icon_menu;
979 if (menu)
980 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
982 if (scr->dock) {
983 menu = scr->dock->menu;
984 if (menu)
985 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
987 menu = scr->clip_menu;
988 if (menu)
989 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
991 menu = scr->clip_submenu;
992 if (menu)
993 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
995 menu = scr->clip_options;
996 if (menu)
997 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
1001 static void
1002 refreshAppIcons(WScreen *scr, int flags)
1004 WAppIcon *aicon = scr->app_icon_list;
1006 while (aicon) {
1007 if (aicon->icon) {
1008 aicon->icon->force_paint = 1;
1010 aicon = aicon->next;
1015 static void
1016 refreshWindows(WScreen *scr, int flags)
1018 WWindow *wwin;
1020 wwin = scr->focused_window;
1021 while (wwin) {
1022 if (flags & REFRESH_WINDOW_FONT) {
1023 wWindowConfigureBorders(wwin);
1025 if ((flags & (REFRESH_ICON_TILE|REFRESH_WINDOW_TEXTURES)) &&
1026 wwin->flags.miniaturized && wwin->icon) {
1027 wwin->icon->force_paint = 1;
1029 if (flags & REFRESH_WINDOW_TEXTURES) {
1030 wwin->frame->flags.need_texture_remake = 1;
1032 wwin = wwin->prev;
1037 void
1038 wReadDefaults(WScreen *scr, proplist_t new_dict)
1040 proplist_t plvalue, old_value;
1041 WDefaultEntry *entry;
1042 int i, changed, must_update;
1043 int needs_refresh;
1044 void *tdata;
1045 proplist_t old_dict = (WDWindowMaker->dictionary!=new_dict
1046 ? WDWindowMaker->dictionary : NULL);
1048 changed = 0;
1049 must_update = 0;
1051 needs_refresh = 0;
1053 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
1054 entry = &optionList[i];
1056 if (new_dict)
1057 plvalue = PLGetDictionaryEntry(new_dict, entry->plkey);
1058 else
1059 plvalue = NULL;
1061 if (!old_dict)
1062 old_value = NULL;
1063 else
1064 old_value = PLGetDictionaryEntry(old_dict, entry->plkey);
1067 if (!plvalue && !old_value) {
1068 /* no default in the DB. Use builtin default */
1069 plvalue = entry->plvalue;
1070 if (plvalue && new_dict) {
1071 PLInsertDictionaryEntry(new_dict, entry->plkey, plvalue);
1072 changed = 1;
1073 must_update = 1;
1075 } else if (!plvalue) {
1076 /* value was deleted from DB. Keep current value */
1077 continue;
1078 } else if (!old_value) {
1079 /* set value for the 1st time */
1080 changed = 1;
1081 } else if (!PLIsEqual(plvalue, old_value)) {
1082 /* value has changed */
1083 changed = 1;
1084 } else {
1085 /* value was not changed since last time */
1086 continue;
1089 if (plvalue) {
1090 #ifdef DEBUG
1091 printf("Updating %s to %s\n", entry->key, PLGetDescription(plvalue));
1092 #endif
1093 /* convert data */
1094 if ((*entry->convert)(scr, entry, plvalue, entry->addr, &tdata)) {
1095 if (entry->update) {
1096 needs_refresh |=
1097 (*entry->update)(scr, entry, tdata, entry->extra_data);
1103 if (needs_refresh!=0) {
1104 int foo;
1106 foo = 0;
1107 if (needs_refresh & REFRESH_MENU_TEXTURES)
1108 foo |= MR_TEXT_BACK;
1109 if (needs_refresh & REFRESH_MENU_FONT)
1110 foo |= MR_RESIZED;
1111 if (needs_refresh & REFRESH_MENU_TITLE_FONT)
1112 foo |= MR_TITLE_TEXT;
1114 if (foo)
1115 refreshMenus(scr, foo);
1117 if (needs_refresh & (REFRESH_WINDOW_TEXTURES|REFRESH_WINDOW_FONT|
1118 REFRESH_ICON_TILE))
1119 refreshWindows(scr, needs_refresh);
1121 if (needs_refresh & REFRESH_ICON_TILE)
1122 refreshAppIcons(scr, needs_refresh);
1124 #ifdef EXPERIMENTAL
1125 if (needs_refresh & REFRESH_WORKSPACE_BACK) {
1126 WWorkspaceTexture *wsback;
1128 /* update the background for the workspace */
1129 if (scr->current_workspace < scr->wspaceTextureCount
1130 && scr->wspaceTextures[scr->current_workspace]) {
1131 wsback = scr->wspaceTextures[scr->current_workspace];
1132 } else {
1133 wsback = scr->defaultTexure;
1135 if (wsback) {
1136 if (wsback->pixmap!=None) {
1137 XSetWindowBackgroundPixmap(dpy, scr->root_win,
1138 wsback->pixmap);
1139 } else {
1140 XSetWindowBackground(dpy, scr->root_win, wsback->solid);
1142 XClearWindow(dpy, scr->root_win);
1143 XFlush(dpy);
1146 #endif /* !EXPERIMENTAL */
1147 wRefreshDesktop(scr);
1152 void
1153 wDefaultUpdateIcons(WScreen *scr)
1155 WAppIcon *aicon = scr->app_icon_list;
1156 WWindow *wwin = scr->focused_window;
1157 char *file;
1159 while(aicon) {
1160 file = wDefaultGetIconFile(scr, aicon->wm_instance, aicon->wm_class,
1161 False);
1162 if ((file && aicon->icon->file && strcmp(file, aicon->icon->file)!=0)
1163 || (file && !aicon->icon->file)) {
1164 RImage *new_image;
1166 if (aicon->icon->file)
1167 free(aicon->icon->file);
1168 aicon->icon->file = wstrdup(file);
1170 new_image = wDefaultGetImage(scr, aicon->wm_instance,
1171 aicon->wm_class);
1172 if (new_image) {
1173 wIconChangeImage(aicon->icon, new_image);
1174 wAppIconPaint(aicon);
1177 aicon = aicon->next;
1180 if (!wPreferences.flags.noclip)
1181 wClipIconPaint(scr->clip_icon);
1183 while (wwin) {
1184 if (wwin->icon && wwin->flags.miniaturized) {
1185 file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
1186 False);
1187 if ((file && wwin->icon->file && strcmp(file, wwin->icon->file)!=0)
1188 || (file && !wwin->icon->file)) {
1189 RImage *new_image;
1191 if (wwin->icon->file)
1192 free(wwin->icon->file);
1193 wwin->icon->file = wstrdup(file);
1195 new_image = wDefaultGetImage(scr, wwin->wm_instance,
1196 wwin->wm_class);
1197 if (new_image)
1198 wIconChangeImage(wwin->icon, new_image);
1201 wwin = wwin->prev;
1206 /* --------------------------- Local ----------------------- */
1208 #define STRINGP(x) if (!PLIsString(value)) { \
1209 wwarning(_("Wrong option format for key \"%s\". Should be %s."), \
1210 entry->key, x); \
1211 return False; }
1215 static int
1216 string2index(proplist_t key, proplist_t val, proplist_t def,
1217 WOptionEnumeration *values)
1219 char *str;
1220 WOptionEnumeration *v;
1221 char buffer[TOTAL_VALUES_LENGTH];
1223 if (PLIsString(val) && (str = PLGetString(val))) {
1224 for (v=values; v->string!=NULL; v++) {
1225 if (strcasecmp(v->string, str)==0)
1226 return v->value;
1230 buffer[0] = 0;
1231 for (v=values; v->string!=NULL; v++) {
1232 if (!v->is_alias) {
1233 if (buffer[0]!=0)
1234 strcat(buffer, ", ");
1235 strcat(buffer, v->string);
1238 wwarning(_("wrong option value for key \"%s\". Should be one of %s"),
1239 PLGetString(key), buffer);
1241 if (def) {
1242 return string2index(key, val, NULL, values);
1245 return -1;
1252 * value - is the value in the defaults DB
1253 * addr - is the address to store the data
1254 * ret - is the address to store a pointer to a temporary buffer. ret
1255 * must not be freed and is used by the set functions
1257 static int
1258 getBool(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1259 void **ret)
1261 static char data;
1262 char *val;
1263 int second_pass=0;
1265 STRINGP("Boolean");
1267 val = PLGetString(value);
1269 again:
1270 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
1271 || strcasecmp(val, "YES")==0) {
1273 data = 1;
1274 } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
1275 || strcasecmp(val, "NO")==0) {
1276 data = 0;
1277 } else {
1278 int i;
1279 if (sscanf(val, "%i", &i)==1) {
1280 if (i!=0)
1281 data = 1;
1282 else
1283 data = 0;
1284 } else {
1285 wwarning(_("can't convert \"%s\" to boolean for key \"%s\""),
1286 val, entry->key);
1287 if (second_pass==0) {
1288 val = PLGetString(entry->plvalue);
1289 second_pass = 1;
1290 wwarning(_("using default \"%s\" instead"), val);
1291 goto again;
1293 return False;
1297 if (ret)
1298 *ret = &data;
1300 if (addr) {
1301 *(char*)addr = data;
1304 return True;
1308 static int
1309 getInt(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1310 void **ret)
1312 static int data;
1313 char *val;
1316 STRINGP("Integer");
1318 val = PLGetString(value);
1320 if (sscanf(val, "%i", &data)!=1) {
1321 wwarning(_("can't convert \"%s\" to integer for key \"%s\""),
1322 val, entry->key);
1323 val = PLGetString(entry->plvalue);
1324 wwarning(_("using default \"%s\" instead"), val);
1325 if (sscanf(val, "%i", &data)!=1) {
1326 return False;
1330 if (ret)
1331 *ret = &data;
1333 if (addr) {
1334 *(int*)addr = data;
1336 return True;
1340 static int
1341 getCoord(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1342 void **ret)
1344 static WCoord data;
1345 char *val_x, *val_y;
1346 int nelem, changed=0;
1347 proplist_t elem_x, elem_y;
1349 again:
1350 if (!PLIsArray(value)) {
1351 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1352 entry->key, "Coordinate");
1353 if (changed==0) {
1354 value = entry->plvalue;
1355 changed = 1;
1356 wwarning(_("using default \"%s\" instead"), entry->default_value);
1357 goto again;
1359 return False;
1362 nelem = PLGetNumberOfElements(value);
1363 if (nelem != 2) {
1364 wwarning(_("Incorrect number of elements in array for key \"%s\"."),
1365 entry->key);
1366 if (changed==0) {
1367 value = entry->plvalue;
1368 changed = 1;
1369 wwarning(_("using default \"%s\" instead"), entry->default_value);
1370 goto again;
1372 return False;
1375 elem_x = PLGetArrayElement(value, 0);
1376 elem_y = PLGetArrayElement(value, 1);
1378 if (!elem_x || !elem_y || !PLIsString(elem_x) || !PLIsString(elem_y)) {
1379 wwarning(_("Wrong value for key \"%s\". Should be Coordinate."),
1380 entry->key);
1381 if (changed==0) {
1382 value = entry->plvalue;
1383 changed = 1;
1384 wwarning(_("using default \"%s\" instead"), entry->default_value);
1385 goto again;
1387 return False;
1390 val_x = PLGetString(elem_x);
1391 val_y = PLGetString(elem_y);
1393 if (sscanf(val_x, "%i", &data.x)!=1 || sscanf(val_y, "%i", &data.y)!=1) {
1394 wwarning(_("can't convert array to integers for \"%s\"."), entry->key);
1395 if (changed==0) {
1396 value = entry->plvalue;
1397 changed = 1;
1398 wwarning(_("using default \"%s\" instead"), entry->default_value);
1399 goto again;
1401 return False;
1404 if (data.x < 0)
1405 data.x = 0;
1406 else if (data.x > scr->scr_width/3)
1407 data.x = scr->scr_width/3;
1408 if (data.y < 0)
1409 data.y = 0;
1410 else if (data.y > scr->scr_height/3)
1411 data.y = scr->scr_height/3;
1413 if (ret)
1414 *ret = &data;
1416 if (addr) {
1417 *(WCoord*)addr = data;
1420 return True;
1424 #if 0
1425 /* This function is not used at the moment. */
1426 static int
1427 getString(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1428 void **ret)
1430 static char *data;
1432 STRINGP("String");
1434 data = PLGetString(value);
1436 if (!data) {
1437 data = PLGetString(entry->plvalue);
1438 if (!data)
1439 return False;
1442 if (ret)
1443 *ret = &data;
1445 if (addr)
1446 *(char**)addr = wstrdup(data);
1448 return True;
1450 #endif
1453 static int
1454 getPathList(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1455 void **ret)
1457 static char **data;
1458 int i, count;
1459 proplist_t d;
1460 int changed=0;
1462 again:
1463 if (!PLIsArray(value)) {
1464 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1465 entry->key, "an array of paths");
1466 if (changed==0) {
1467 value = entry->plvalue;
1468 changed = 1;
1469 wwarning(_("using default \"%s\" instead"), entry->default_value);
1470 goto again;
1472 return False;
1475 i = 0;
1476 count = PLGetNumberOfElements(value);
1477 if (count < 1) {
1478 if (changed==0) {
1479 value = entry->plvalue;
1480 changed = 1;
1481 wwarning(_("using default \"%s\" instead"), entry->default_value);
1482 goto again;
1484 return False;
1487 data = wmalloc(sizeof(char*)*(count+1));
1488 for (i=0; i<count; i++) {
1489 d = PLGetArrayElement(value, i);
1490 if (!d || !PLIsString(d)) {
1491 break;
1493 data[i] = wstrdup(PLGetString(d));
1495 data[i]=NULL;
1497 if (*(char***)addr!=NULL) {
1498 char **tmp = *(char***)addr;
1499 for (i=0; tmp[i]!=NULL; i++) {
1500 free(tmp[i]);
1502 free(tmp);
1504 *(char***)addr = data;
1506 return True;
1510 static int
1511 getEnum(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1512 void **ret)
1514 static char data;
1516 data = string2index(entry->plkey, value, entry->default_value,
1517 (WOptionEnumeration*)entry->extra_data);
1518 if (data < 0)
1519 return False;
1521 if (ret)
1522 *ret = &data;
1524 if (addr)
1525 *(char*)addr = data;
1527 return True;
1533 * (solid <color>)
1534 * (hgradient <color> <color>)
1535 * (vgradient <color> <color>)
1536 * (dgradient <color> <color>)
1537 * (mhgradient <color> <color> ...)
1538 * (mvgradient <color> <color> ...)
1539 * (tpixmap <file> <color>)
1540 * (spixmap <file> <color>)
1541 * (cpixmap <file> <color>)
1544 static WTexture*
1545 parse_texture(WScreen *scr, proplist_t pl)
1547 proplist_t elem;
1548 char *val;
1549 int nelem;
1550 WTexture *texture=NULL;
1552 nelem = PLGetNumberOfElements(pl);
1553 if (nelem < 1)
1554 return NULL;
1557 elem = PLGetArrayElement(pl, 0);
1558 if (!elem || !PLIsString(elem))
1559 return NULL;
1560 val = PLGetString(elem);
1563 if (strcasecmp(val, "solid")==0) {
1564 XColor color;
1566 if (nelem != 2)
1567 return NULL;
1569 /* get color */
1571 elem = PLGetArrayElement(pl, 1);
1572 if (!elem || !PLIsString(elem))
1573 return NULL;
1574 val = PLGetString(elem);
1576 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1577 wwarning(_("\"%s\" is not a valid color name"), val);
1578 return NULL;
1581 texture = (WTexture*)wTextureMakeSolid(scr, &color);
1582 } else if (strcasecmp(val, "dgradient")==0
1583 || strcasecmp(val, "vgradient")==0
1584 || strcasecmp(val, "hgradient")==0) {
1585 XColor color1, color2;
1586 int type;
1588 if (nelem != 3) {
1589 wwarning(_("bad number of arguments in gradient specification"));
1590 return NULL;
1593 if (val[0]=='d' || val[0]=='D')
1594 type = WTEX_DGRADIENT;
1595 else if (val[0]=='h' || val[0]=='H')
1596 type = WTEX_HGRADIENT;
1597 else
1598 type = WTEX_VGRADIENT;
1601 /* get from color */
1602 elem = PLGetArrayElement(pl, 1);
1603 if (!elem || !PLIsString(elem))
1604 return NULL;
1605 val = PLGetString(elem);
1607 if (!XParseColor(dpy, scr->colormap, val, &color1)) {
1608 wwarning(_("\"%s\" is not a valid color name"), val);
1609 return NULL;
1612 /* get to color */
1613 elem = PLGetArrayElement(pl, 2);
1614 if (!elem || !PLIsString(elem)) {
1615 return NULL;
1617 val = PLGetString(elem);
1619 if (!XParseColor(dpy, scr->colormap, val, &color2)) {
1620 wwarning(_("\"%s\" is not a valid color name"), val);
1621 return NULL;
1624 texture = (WTexture*)wTextureMakeGradient(scr, type, &color1, &color2);
1626 } else if (strcasecmp(val, "mhgradient")==0
1627 || strcasecmp(val, "mvgradient")==0
1628 || strcasecmp(val, "mdgradient")==0) {
1629 XColor color;
1630 RColor **colors;
1631 int i, count;
1632 int type;
1634 if (nelem < 3) {
1635 wwarning(_("too few arguments in multicolor gradient specification"));
1636 return NULL;
1639 if (val[1]=='h' || val[1]=='H')
1640 type = WTEX_MHGRADIENT;
1641 else if (val[1]=='v' || val[1]=='V')
1642 type = WTEX_MVGRADIENT;
1643 else
1644 type = WTEX_MDGRADIENT;
1646 count = nelem-1;
1648 colors = wmalloc(sizeof(RColor*)*(count+1));
1650 for (i=0; i<count; i++) {
1651 elem = PLGetArrayElement(pl, i+1);
1652 if (!elem || !PLIsString(elem)) {
1653 for (--i; i>=0; --i) {
1654 free(colors[i]);
1656 free(colors);
1657 return NULL;
1659 val = PLGetString(elem);
1661 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1662 wwarning(_("\"%s\" is not a valid color name"), val);
1663 for (--i; i>=0; --i) {
1664 free(colors[i]);
1666 free(colors);
1667 return NULL;
1668 } else {
1669 colors[i] = wmalloc(sizeof(RColor));
1670 colors[i]->red = color.red >> 8;
1671 colors[i]->green = color.green >> 8;
1672 colors[i]->blue = color.blue >> 8;
1675 colors[i] = NULL;
1677 texture = (WTexture*)wTextureMakeMGradient(scr, type, colors);
1678 } else if (strcasecmp(val, "spixmap")==0 ||
1679 strcasecmp(val, "cpixmap")==0 ||
1680 strcasecmp(val, "tpixmap")==0) {
1681 XColor color;
1682 int type;
1684 if (nelem != 3)
1685 return NULL;
1687 if (val[0] == 's' || val[0] == 'S')
1688 type = WTP_SCALE;
1689 else if (val[0] == 'c' || val[0] == 'C')
1690 type = WTP_CENTER;
1691 else
1692 type = WTP_TILE;
1694 /* get color */
1695 elem = PLGetArrayElement(pl, 2);
1696 if (!elem || !PLIsString(elem)) {
1697 return NULL;
1699 val = PLGetString(elem);
1701 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1702 wwarning(_("\"%s\" is not a valid color name"), val);
1703 return NULL;
1706 /* file name */
1707 elem = PLGetArrayElement(pl, 1);
1708 if (!elem || !PLIsString(elem))
1709 return NULL;
1710 val = PLGetString(elem);
1712 texture = (WTexture*)wTextureMakePixmap(scr, type, val, &color);
1714 } else {
1715 return NULL;
1717 return texture;
1722 static int
1723 getTexture(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1724 void **ret)
1726 static WTexture *texture;
1727 int changed=0;
1729 again:
1730 if (!PLIsArray(value)) {
1731 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1732 entry->key, "Texture");
1733 if (changed==0) {
1734 value = entry->plvalue;
1735 changed = 1;
1736 wwarning(_("using default \"%s\" instead"), entry->default_value);
1737 goto again;
1739 return False;
1742 if (strcmp(entry->key, "WidgetColor")==0 && !changed) {
1743 proplist_t pl;
1745 pl = PLGetArrayElement(value, 0);
1746 if (!pl || !PLIsString(pl) || !PLGetString(pl)
1747 || strcasecmp(PLGetString(pl), "solid")!=0) {
1748 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1749 entry->key, "Solid Texture");
1751 value = entry->plvalue;
1752 changed = 1;
1753 wwarning(_("using default \"%s\" instead"), entry->default_value);
1754 goto again;
1758 texture = parse_texture(scr, value);
1760 if (!texture) {
1761 wwarning(_("Error in texture specification for key \"%s\""),
1762 entry->key);
1763 if (changed==0) {
1764 value = entry->plvalue;
1765 changed = 1;
1766 wwarning(_("using default \"%s\" instead"), entry->default_value);
1767 goto again;
1769 return False;
1772 if (ret)
1773 *ret = &texture;
1775 if (addr)
1776 *(WTexture**)addr = texture;
1778 return True;
1783 #ifdef EXPERIMENTAL
1784 static int
1785 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1786 void *addr, void **ret)
1788 proplist_t elem;
1789 char *val;
1790 int nelem;
1791 static WTexture *texture=NULL;
1792 int changed=0;
1793 char *file = NULL;
1795 again:
1796 entry->extra_data = NULL;
1798 if (!PLIsArray(value)) {
1799 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1800 "WorkspaceBack", "Texture");
1801 if (changed==0) {
1802 value = entry->plvalue;
1803 changed = 1;
1804 wwarning(_("using default \"%s\" instead"), entry->default_value);
1805 goto again;
1807 return False;
1810 nelem = PLGetNumberOfElements(value);
1811 if (nelem < 1) {
1812 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1813 if (changed==0) {
1814 value = entry->plvalue;
1815 changed = 1;
1816 wwarning(_("using default \"%s\" instead"), entry->default_value);
1817 goto again;
1819 return False;
1822 elem = PLGetArrayElement(value, 0);
1823 if (!elem || !PLIsString(elem)) {
1824 wwarning(_("Wrong type for workspace background. Should be Texture."));
1825 if (changed==0) {
1826 value = entry->plvalue;
1827 changed = 1;
1828 wwarning(_("using default \"%s\" instead"), entry->default_value);
1829 goto again;
1831 return False;
1833 val = PLGetString(elem);
1835 if (strcasecmp(val, "None")==0)
1836 return False;
1838 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
1839 && strcasecmp(val, "cpixmap")!=0) {
1840 texture = parse_texture(scr, value);
1841 } else {
1842 /* spixmap || tpixmap || cpixmap */
1843 XColor color;
1844 int style;
1846 if (nelem != 3) {
1847 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1848 if (changed==0) {
1849 value = entry->plvalue;
1850 changed = 1;
1851 wwarning(_("using default \"%s\" instead"), entry->default_value);
1852 goto again;
1854 return False;
1857 switch (val[0]) {
1858 case 's':
1859 case 'S':
1860 style = WTP_SCALE;
1861 break;
1862 case 'C':
1863 case 'c':
1864 style = WTP_CENTER;
1865 break;
1866 default:
1867 style = WTP_TILE;
1868 break;
1871 /* get color */
1872 elem = PLGetArrayElement(value, 2);
1873 if (!elem || !PLIsString(elem)) {
1874 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
1875 if (changed==0) {
1876 value = entry->plvalue;
1877 changed = 1;
1878 wwarning(_("using default \"%s\" instead"), entry->default_value);
1879 goto again;
1881 return False;
1883 val = PLGetString(elem);
1885 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1886 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
1887 val);
1888 if (changed==0) {
1889 value = entry->plvalue;
1890 changed = 1;
1891 wwarning(_("using default \"%s\" instead"), entry->default_value);
1892 goto again;
1894 return False;
1897 /* file name */
1898 elem = PLGetArrayElement(value, 1);
1899 if (!elem || !PLIsString(elem)) {
1900 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
1901 if (changed==0) {
1902 value = entry->plvalue;
1903 changed = 1;
1904 wwarning(_("using default \"%s\" instead"), entry->default_value);
1905 goto again;
1907 return False;
1910 val = PLGetString(elem);
1911 file = FindImage(wPreferences.pixmap_path, val);
1912 if (!file) {
1913 wwarning(_("could not find background image \"%s\""), val);
1914 /*return False;*/
1917 /* create a dummy texture.
1918 * use free() to free this texture.
1920 texture = wmalloc(sizeof(WTexture));
1921 memset(texture, 0, sizeof(WTexture));
1922 texture->type = WTEX_PIXMAP;
1923 texture->subtype = style;
1924 texture->normal = color;
1927 if (!texture) {
1928 if (file)
1929 free(file);
1930 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
1931 if (changed==0) {
1932 value = entry->plvalue;
1933 changed = 1;
1934 wwarning(_("using default \"%s\" instead"), entry->default_value);
1935 goto again;
1937 return False;
1940 if (ret)
1941 *ret = &texture;
1943 if (addr)
1944 *(WTexture**)addr = texture;
1946 /* we use the extra_data field to pass the filename string
1947 * to the background setting function. We can't pass it with
1948 * WTexture because it holds a RImage, not a file name.
1949 * It also would be dirtier to cast the RImage to char* to make it
1950 * hold the file name. The extra_data must be freed by the
1951 * setting function.
1953 entry->extra_data = file;
1955 return True;
1957 #else /* !EXPERIMENTAL */
1958 static int
1959 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1960 void *addr, void **ret)
1962 proplist_t elem;
1963 char *val;
1964 int nelem;
1965 static WTexture *texture=NULL;
1966 int changed=0;
1968 again:
1969 if (!PLIsArray(value)) {
1970 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1971 "WorkspaceBack", "Texture");
1972 if (changed==0) {
1973 value = entry->plvalue;
1974 changed = 1;
1975 wwarning(_("using default \"%s\" instead"), entry->default_value);
1976 goto again;
1978 return False;
1981 nelem = PLGetNumberOfElements(value);
1982 if (nelem < 1) {
1983 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1984 if (changed==0) {
1985 value = entry->plvalue;
1986 changed = 1;
1987 wwarning(_("using default \"%s\" instead"), entry->default_value);
1988 goto again;
1990 return False;
1993 elem = PLGetArrayElement(value, 0);
1994 if (!elem || !PLIsString(elem)) {
1995 wwarning(_("Wrong type for workspace background. Should be Texture."));
1996 if (changed==0) {
1997 value = entry->plvalue;
1998 changed = 1;
1999 wwarning(_("using default \"%s\" instead"), entry->default_value);
2000 goto again;
2002 return False;
2004 val = PLGetString(elem);
2006 if (strcasecmp(val, "None")==0)
2007 return False;
2009 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
2010 && strcasecmp(val, "cpixmap")!=0) {
2011 texture = parse_texture(scr, value);
2013 else {
2014 /* spixmap || tpixmap || cpixmap */
2015 XColor color;
2016 char *file, cpc[30], *style = "-s";
2017 char *program = "wmsetbg";
2018 char *back;
2020 if (nelem != 3) {
2021 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
2022 if (changed==0) {
2023 value = entry->plvalue;
2024 changed = 1;
2025 wwarning(_("using default \"%s\" instead"), entry->default_value);
2026 goto again;
2028 return False;
2031 if (val[0] == 't' || val[0] == 'T')
2032 style = "-t";
2033 else if (val[0] == 'c' || val[0] == 'C')
2034 style = "-e";
2036 sprintf(cpc, "%i", wPreferences.cmap_size);
2038 /* get color */
2039 elem = PLGetArrayElement(value, 2);
2040 if (!elem || !PLIsString(elem)) {
2041 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
2042 if (changed==0) {
2043 value = entry->plvalue;
2044 changed = 1;
2045 wwarning(_("using default \"%s\" instead"), entry->default_value);
2046 goto again;
2048 return False;
2050 val = PLGetString(elem);
2052 if (!XParseColor(dpy, scr->colormap, val, &color)) {
2053 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
2054 val);
2055 if (changed==0) {
2056 value = entry->plvalue;
2057 changed = 1;
2058 wwarning(_("using default \"%s\" instead"), entry->default_value);
2059 goto again;
2061 return False;
2064 back = wstrdup(val);
2066 /* file name */
2067 elem = PLGetArrayElement(value, 1);
2068 if (!elem || !PLIsString(elem)) {
2069 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
2070 if (changed==0) {
2071 value = entry->plvalue;
2072 changed = 1;
2073 wwarning(_("using default \"%s\" instead"), entry->default_value);
2074 goto again;
2076 return False;
2079 val = PLGetString(elem);
2081 file = FindImage(wPreferences.pixmap_path, val);
2082 if (file) {
2083 if (fork()==0) {
2084 SetupEnvironment(scr);
2086 CloseDescriptors();
2088 execlp(program, program, style, "-c", cpc, "-b", back, file, NULL);
2089 wwarning(_("could not run \"%s\""), program);
2090 exit(-1);
2092 free(file);
2093 } else {
2094 wwarning(_("could not find background image \"%s\""), val);
2097 free(back);
2099 /* This is to let WindowMaker put a color in the background
2100 * until the pixmap is loaded, if the image is big and loads slow.
2101 * It assumes that the color will be set before the image is set
2102 * by the child. Is this true for very small images?
2104 texture = (WTexture*)wTextureMakeSolid(scr, &color);
2107 if (!texture) {
2108 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
2109 if (changed==0) {
2110 value = entry->plvalue;
2111 changed = 1;
2112 wwarning(_("using default \"%s\" instead"), entry->default_value);
2113 goto again;
2115 return False;
2118 if (ret)
2119 *ret = &texture;
2121 if (addr)
2122 *(WTexture**)addr = texture;
2124 return True;
2126 #endif /* !EXPERIMENTAL */
2129 static int
2130 getFont(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2131 void **ret)
2133 static WFont *font;
2134 char *val;
2136 STRINGP("Font");
2138 val = PLGetString(value);
2140 font = wLoadFont(val);
2141 if (!font) {
2142 wwarning(_("could not load any usable font"));
2143 return False;
2146 if (ret)
2147 *ret = font;
2149 if (addr) {
2150 wwarning("BUG:can't assign font value outside update function");
2153 return True;
2157 static int
2158 getColor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2159 void **ret)
2161 static unsigned long pixel;
2162 XColor color;
2163 char *val;
2164 int second_pass=0;
2166 STRINGP("Color");
2168 val = PLGetString(value);
2170 again:
2171 if (!wGetColor(scr, val, &color)) {
2172 wwarning(_("could not get color for key \"%s\""),
2173 entry->key);
2174 if (second_pass==0) {
2175 val = PLGetString(entry->plvalue);
2176 second_pass = 1;
2177 wwarning(_("using default \"%s\" instead"), val);
2178 goto again;
2180 return False;
2183 pixel = color.pixel;
2185 if (ret)
2186 *ret = &pixel;
2188 if (addr)
2189 *(unsigned long*)addr = pixel;
2191 return True;
2196 static int
2197 getKeybind(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2198 void **ret)
2200 static WShortKey shortcut;
2201 KeySym ksym;
2202 char *val;
2203 char *k;
2204 char buf[128], *b;
2207 STRINGP("Key spec");
2209 val = PLGetString(value);
2211 if (!val || strcasecmp(val, "NONE")==0) {
2212 shortcut.keycode = 0;
2213 shortcut.modifier = 0;
2214 if (ret)
2215 *ret = &shortcut;
2216 return True;
2219 strcpy(buf, val);
2221 b = (char*)buf;
2223 /* get modifiers */
2224 shortcut.modifier = 0;
2225 while ((k = strchr(b, '+'))!=NULL) {
2226 int mod;
2228 *k = 0;
2229 mod = wXModifierFromKey(b);
2230 if (mod<0) {
2231 wwarning(_("%s:invalid key modifier \"%s\""), entry->key, val);
2232 return False;
2234 shortcut.modifier |= mod;
2236 b = k+1;
2239 /* get key */
2240 ksym = XStringToKeysym(b);
2242 if (ksym==NoSymbol) {
2243 wwarning(_("%s:invalid kbd shortcut specification \"%s\""), entry->key,
2244 val);
2245 return False;
2248 shortcut.keycode = XKeysymToKeycode(dpy, ksym);
2249 if (shortcut.keycode==0) {
2250 wwarning(_("%s:invalid key in shortcut \"%s\""), entry->key, val);
2251 return False;
2254 if (ret)
2255 *ret = &shortcut;
2257 return True;
2261 static int
2262 getModMask(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2263 void **ret)
2265 unsigned int mask;
2266 char *str;
2268 STRINGP("Modifier Key");
2270 str = PLGetString(value);
2271 if (!str)
2272 return False;
2274 mask = wXModifierFromKey(str);
2275 if (mask < 0) {
2276 wwarning(_("%s: modifier key %s is not valid"), entry->key, str);
2277 mask = 0;
2278 return False;
2281 if (addr)
2282 *(unsigned int*)addr = mask;
2284 if (ret)
2285 *ret = &mask;
2287 return True;
2292 /* ---------------- value setting functions --------------- */
2293 static int
2294 setJustify(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2296 return REFRESH_FORE_COLOR;
2300 static int
2301 setIfDockPresent(WScreen *scr, WDefaultEntry *entry, int *flag, long which)
2303 switch (which) {
2304 case WM_DOCK:
2305 wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
2306 break;
2307 case WM_CLIP:
2308 wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
2309 break;
2310 default:
2311 break;
2313 return 0;
2317 static int
2318 setStickyIcons(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
2320 if (scr->workspaces) {
2321 wWorkspaceForceChange(scr, scr->current_workspace);
2322 wArrangeIcons(scr, False);
2324 return 0;
2327 #if not_used
2328 static int
2329 setPositive(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
2331 if (*value <= 0)
2332 *(int*)foo = 1;
2334 return 0;
2336 #endif
2340 static int
2341 setIconTile(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2343 Pixmap pixmap;
2344 RImage *img;
2345 int reset = 0;
2347 img = wTextureRenderImage(*texture, wPreferences.icon_size,
2348 wPreferences.icon_size,
2349 ((*texture)->any.type & WREL_BORDER_MASK)
2350 ? WREL_ICON : WREL_FLAT);
2351 if (!img) {
2352 wwarning(_("could not render texture for icon background"));
2353 if (!entry->addr)
2354 wTextureDestroy(scr, *texture);
2355 return 0;
2357 RConvertImage(scr->rcontext, img, &pixmap);
2359 if (scr->icon_tile) {
2360 reset = 1;
2361 RDestroyImage(scr->icon_tile);
2362 XFreePixmap(dpy, scr->icon_tile_pixmap);
2365 scr->icon_tile = img;
2367 if (!wPreferences.flags.noclip) {
2368 if (scr->clip_tile) {
2369 RDestroyImage(scr->clip_tile);
2371 scr->clip_tile = wClipMakeTile(scr, img);
2374 scr->icon_tile_pixmap = pixmap;
2376 if (scr->def_icon_pixmap) {
2377 XFreePixmap(dpy, scr->def_icon_pixmap);
2378 scr->def_icon_pixmap = None;
2380 if (scr->def_ticon_pixmap) {
2381 XFreePixmap(dpy, scr->def_ticon_pixmap);
2382 scr->def_ticon_pixmap = None;
2385 if (scr->icon_back_texture) {
2386 wTextureDestroy(scr, (WTexture*)scr->icon_back_texture);
2388 scr->icon_back_texture = wTextureMakeSolid(scr, &((*texture)->any.color));
2390 if (scr->clip_balloon)
2391 XSetWindowBackground(dpy, scr->clip_balloon,
2392 (*texture)->any.color.pixel);
2395 * Free the texture as nobody else will use it, nor refer to it.
2397 if (!entry->addr)
2398 wTextureDestroy(scr, *texture);
2400 return (reset ? REFRESH_ICON_TILE : 0);
2405 static int
2406 setWinTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2408 if (scr->title_font) {
2409 wFreeFont(scr->title_font);
2412 scr->title_font = font;
2414 #ifndef I18N_MB
2415 XSetFont(dpy, scr->window_title_gc, font->font->fid);
2416 #endif
2418 return REFRESH_WINDOW_FONT;
2422 static int
2423 setMenuTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2425 if (scr->menu_title_font) {
2426 wFreeFont(scr->menu_title_font);
2429 scr->menu_title_font = font;
2431 #ifndef I18N_MB
2432 XSetFont(dpy, scr->menu_title_gc, font->font->fid);
2433 #endif
2435 return REFRESH_MENU_TITLE_FONT;
2439 static int
2440 setMenuTextFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2442 if (scr->menu_entry_font) {
2443 wFreeFont(scr->menu_entry_font);
2446 scr->menu_entry_font = font;
2448 #ifndef I18N_MB
2449 XSetFont(dpy, scr->menu_entry_gc, font->font->fid);
2450 XSetFont(dpy, scr->disabled_menu_entry_gc, font->font->fid);
2451 XSetFont(dpy, scr->select_menu_gc, font->font->fid);
2452 #endif
2454 return REFRESH_MENU_FONT;
2459 static int
2460 setIconTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2462 if (scr->icon_title_font) {
2463 wFreeFont(scr->icon_title_font);
2466 scr->icon_title_font = font;
2468 #ifndef I18N_MB
2469 XSetFont(dpy, scr->icon_title_gc, font->font->fid);
2470 #endif
2472 return REFRESH_ICON_FONT;
2476 static int
2477 setClipTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2479 if (scr->clip_title_font) {
2480 wFreeFont(scr->clip_title_font);
2483 scr->clip_title_font = font;
2485 #ifndef I18N_MB
2486 XSetFont(dpy, scr->clip_title_gc, font->font->fid);
2487 #endif
2489 return REFRESH_ICON_FONT;
2493 static int
2494 setDisplayFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2496 if (scr->info_text_font) {
2497 wFreeFont(scr->info_text_font);
2500 scr->info_text_font = font;
2502 #ifndef I18N_MB
2503 XSetFont(dpy, scr->info_text_gc, font->font->fid);
2504 XSetFont(dpy, scr->line_gc, font->font->fid);
2505 #endif
2507 /* This test works because the scr structure is initially zeroed out
2508 and None = 0. Any other time, the window should be valid. */
2509 if (scr->geometry_display != None) {
2510 wGetGeometryWindowSize(scr, &scr->geometry_display_width,
2511 &scr->geometry_display_height);
2512 XResizeWindow(dpy, scr->geometry_display,
2513 scr->geometry_display_width, scr->geometry_display_height);
2516 return 0;
2520 static int
2521 setHightlight(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2523 if (scr->select_pixel!=scr->white_pixel &&
2524 scr->select_pixel!=scr->black_pixel) {
2525 wFreeColor(scr, scr->select_pixel);
2528 scr->select_pixel = color->pixel;
2530 return REFRESH_FORE_COLOR;
2534 static int
2535 setHightlightText(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2537 if (scr->select_text_pixel!=scr->white_pixel &&
2538 scr->select_text_pixel!=scr->black_pixel) {
2539 wFreeColor(scr, scr->select_text_pixel);
2542 scr->select_text_pixel = color->pixel;
2544 return REFRESH_FORE_COLOR;
2548 static int
2549 setClipTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2551 if (scr->clip_title_pixel[index]!=scr->white_pixel &&
2552 scr->clip_title_pixel[index]!=scr->black_pixel) {
2553 wFreeColor(scr, scr->clip_title_pixel[index]);
2556 scr->clip_title_pixel[index] = color->pixel;
2558 return REFRESH_FORE_COLOR;
2562 static int
2563 setWTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2565 if (scr->window_title_pixel[index]!=scr->white_pixel &&
2566 scr->window_title_pixel[index]!=scr->black_pixel) {
2567 wFreeColor(scr, scr->window_title_pixel[index]);
2570 scr->window_title_pixel[index] = color->pixel;
2572 if (index == WS_FOCUSED)
2573 XSetForeground(dpy, scr->icon_title_gc, color->pixel);
2574 else if (index == WS_UNFOCUSED)
2575 XSetForeground(dpy, scr->info_text_gc, color->pixel);
2577 return REFRESH_FORE_COLOR;
2581 static int
2582 setMenuTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2584 if (scr->menu_title_pixel[0]!=scr->white_pixel &&
2585 scr->menu_title_pixel[0]!=scr->black_pixel) {
2586 wFreeColor(scr, scr->menu_title_pixel[0]);
2589 scr->menu_title_pixel[0] = color->pixel;
2591 XSetForeground(dpy, scr->menu_title_gc, color->pixel);
2593 return REFRESH_FORE_COLOR;
2597 static int
2598 setMenuTextColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2600 XGCValues gcv;
2601 #define gcm (GCForeground|GCBackground|GCFillStyle)
2603 if (scr->mtext_pixel!=scr->white_pixel &&
2604 scr->mtext_pixel!=scr->black_pixel) {
2605 wFreeColor(scr, scr->mtext_pixel);
2608 scr->mtext_pixel = color->pixel;
2610 XSetForeground(dpy, scr->menu_entry_gc, color->pixel);
2613 if (scr->dtext_pixel == scr->mtext_pixel) {
2614 gcv.foreground = scr->white_pixel;
2615 gcv.background = scr->black_pixel;
2616 gcv.fill_style = FillStippled;
2617 } else {
2618 gcv.foreground = scr->dtext_pixel;
2619 gcv.fill_style = FillSolid;
2621 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2623 return REFRESH_FORE_COLOR;
2624 #undef gcm
2628 static int
2629 setMenuDisabledColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2631 XGCValues gcv;
2632 #define gcm (GCForeground|GCBackground|GCFillStyle)
2634 if (scr->dtext_pixel!=scr->white_pixel &&
2635 scr->dtext_pixel!=scr->black_pixel) {
2636 wFreeColor(scr, scr->dtext_pixel);
2639 scr->dtext_pixel = color->pixel;
2641 if (scr->dtext_pixel == scr->mtext_pixel) {
2642 gcv.foreground = scr->white_pixel;
2643 gcv.background = scr->black_pixel;
2644 gcv.fill_style = FillStippled;
2645 } else {
2646 gcv.foreground = scr->dtext_pixel;
2647 gcv.fill_style = FillSolid;
2649 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2651 return REFRESH_FORE_COLOR;
2652 #undef gcm
2658 * Implementation of workspace specific backgrounds.
2660 * WorkspaceBack is used as the default background.
2661 * WorkspaceSpecificBack supplies an array with the textures for
2662 * other workspaces.
2663 * WorkspaceSpecificBack = (ws1texture, ws2texture, "", ws4texture);
2664 * "" means that workspace3 should use the default texture.
2666 * struct WWorkspaceTexture {
2667 * Pixmap pixmap; // the pixmap for non-solid textures.
2668 * //None means the texture is solid
2669 * WPixel color; // color for solid texture
2670 * proplist_t texture; // for checking updates
2671 * };
2674 * All textures are rendered by wmsetbg. When it exits with status 0
2675 * it outputs the pixmap ID.
2676 * wmaker will monitor the fd and when it becomes available it reads the
2677 * pixmap ID and uses it in the texture. The data read from the fd
2678 * is the pixmap ID and the pid of the wmsetbg process, separated by
2679 * a space (the pid is to allow paralel wmsetbg processes).
2681 * The workspace background cant be set if the pid field of the
2682 * texture is 0. Otherwise, the texture is still being rendered
2683 * and cant be set.
2685 * If the workspace background is changed before wmsetbg finishes
2686 * the rendering, wmsetbg must be killed.
2688 * Optimizations:
2689 * Workspace specific textures are generated only when switching to
2690 * that workspace, unless #define SLOW_CONFIGURATION_UPDATE.
2692 * -readme
2694 #ifdef EXPERIMENTAL
2695 static void
2696 trackDeadProcess(pid_t pid, unsigned char status, WScreen *scr)
2698 WWorkspaceTexture *wsback;
2699 int setBackground = 0;
2701 /* find out to which wsback, this process belongs to */
2703 wsback->pid = 0;
2704 if (status != 123) {
2705 /* something went wrong during rendering */
2706 XFreePixmap(dpy, wsback->pixmap);
2707 wsback->pixmap = None;
2708 wwarning(_("background texture rendering was unsuccessfull"));
2711 if (setBackground) {
2715 WWorkspaceTexture*
2716 makeWorkspaceTexture(WScreen *scr, WTexture *texture, char *file, char *option)
2718 WWorkspaceTexture *wsback;
2720 wsback = wmalloc(sizeof(WWorkspaceTexture));
2721 wsback->pid = 0;
2723 wsback->solid = (*texture)->any.color.pixel;
2725 if (texture->any.type==WTEX_SOLID) {
2726 wsback->pixmap = None;
2727 } else if (texture->any.type == WTEX_PIXMAP) {
2728 Pixmap pixmap;
2729 if (texture->pixmap.subtype == WTP_TILE) {
2730 RImage *image;
2732 /* render ourseves */
2733 image = RLoadImage(scr->rcontext, file, 0);
2734 if (!image) {
2735 wwarning(_("could not load image %s for option %s:%s\n"),
2736 file, option, RErrorString);
2737 wsback->pixmap = None;
2738 } else {
2740 } else {
2741 /* create a empty pixmap... */
2742 pid_t pid;
2743 int style = texture->pixmap.subtype;
2745 pixmap = XCreatePixmap(dpy, scr->root_win, scr->scr_width,
2746 scr->scr_height, scr->depth);
2748 /* ...and let wmsetbg render it */
2749 pid = fork();
2750 if (pid < 0) {
2751 wsyserror(_("could not spawn texture rendering subprocess for option"));
2752 } else if (pid == 0) {
2753 char *colorn, *pix;
2755 SetupEnvironment(scr);
2757 CloseDescriptors();
2759 colorn = wmalloc(32);
2760 sprintf(colorn, "\"#%2x%2x%2x\"",
2761 texture->any.color.red,
2762 texture->any.color.green,
2763 texture->any.color.blue);
2764 pix = wmalloc(32);
2765 sprintf(pix, "%x", pixmap);
2766 execlp("wmsetbg", "wmsetbg", (style==WTP_SCALE ? "-s":"-e"),
2767 "-b", colorn, "-x", pix, file);
2768 exit(1);
2770 wsback->pixmap = pixmap;
2771 /* must add a death handler to detect when wmsetbg has
2772 * exited (with exit status 123) and refresh the background.
2774 wsback->pid = pid;
2776 } else {
2777 int w, h;
2778 Pixmap pixmap;
2780 switch (texture->any.type) {
2781 case WTEX_HGRADIENT:
2782 case WTEX_MHGRADIENT:
2783 w = scr->scr_width;
2784 h = 8;
2785 break;
2787 case WTEX_VGRADIENT:
2788 case WTEX_MVGRADIENT:
2789 w = 8;
2790 h = scr->scr_height;
2791 break;
2793 case WTEX_DGRADIENT:
2794 case WTEX_MDGRADIENT:
2795 w = scr->scr_width;
2796 h = scr->scr_height;
2797 break;
2799 default:
2800 return NULL;
2803 img = wTextureRenderImage(texture, w, h, WREL_FLAT);
2804 if (!img) {
2805 wwarning(_("could not render texture for workspace background"));
2806 free(wsback);
2807 return NULL;
2809 RConvertImage(scr->rcontext, img, &pixmap);
2810 RDestroyImage(img);
2811 wsback->pixmap = pixmap;
2814 return wsback;
2818 static int
2819 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
2820 char *file)
2822 Pixmap pixmap;
2823 RImage *img;
2825 if (scr->defaultTexture) {
2826 if (scr->defaultTexture->pixmap)
2827 XFreePixmap(dpy, scr->defaultTexture->pixmap);
2828 free(scr->defaultTexture);
2831 if (!*texture) {
2832 scr->defaultTexture = NULL;
2833 if (file)
2834 free(file);
2835 return 0;
2838 scr->defaultTexture = makeWorkspaceTexture(scr, *texture, file);
2840 if (!entry->addr)
2841 wTextureDestroy(scr, *texture);
2843 /* free the file name that was passed from the getWSBackground()
2844 * function and placed in entry->extra_data */
2845 if (file)
2846 free(file);
2847 entry->extra_data = NULL;
2849 return REFRESH_WORKSPACE_BACK;
2851 #else /* !EXPERIMENTAL */
2852 static int
2853 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
2854 void *foo)
2856 Pixmap pixmap;
2857 RImage *img;
2860 if ((*texture)->any.type==WTEX_SOLID) {
2861 XSetWindowBackground(dpy, scr->root_win, (*texture)->solid.normal.pixel);
2862 XClearWindow(dpy, scr->root_win);
2863 } else {
2864 int w, h;
2866 switch ((*texture)->any.type) {
2867 case WTEX_HGRADIENT:
2868 case WTEX_MHGRADIENT:
2869 w = scr->scr_width;
2870 h = 8;
2871 break;
2873 case WTEX_VGRADIENT:
2874 case WTEX_MVGRADIENT:
2875 w = 8;
2876 h = scr->scr_height;
2877 break;
2879 case WTEX_DGRADIENT:
2880 case WTEX_MDGRADIENT:
2881 w = scr->scr_width;
2882 h = scr->scr_height;
2883 break;
2885 default:
2886 if (!entry->addr)
2887 wTextureDestroy(scr, *texture);
2888 return 0;
2891 img = wTextureRenderImage(*texture, w, h, WREL_FLAT);
2892 if (!img) {
2893 wwarning(_("could not render texture for workspace background"));
2894 if (!entry->addr)
2895 wTextureDestroy(scr, *texture);
2896 return 0;
2898 RConvertImage(scr->rcontext, img, &pixmap);
2899 RDestroyImage(img);
2900 XSetWindowBackgroundPixmap(dpy, scr->root_win, pixmap);
2901 XClearWindow(dpy, scr->root_win);
2905 * Free the texture as nobody else will use it, nor refer to it.
2907 if (!entry->addr)
2908 wTextureDestroy(scr, *texture);
2910 return 0;
2912 #endif /* !EXPERIMENTAL */
2914 static int
2915 setWidgetColor(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2917 if (scr->widget_texture) {
2918 wTextureDestroy(scr, (WTexture*)scr->widget_texture);
2920 scr->widget_texture = *(WTexSolid**)texture;
2922 return 0;
2926 static int
2927 setFTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2929 if (scr->window_title_texture[WS_FOCUSED]) {
2930 wTextureDestroy(scr, scr->window_title_texture[WS_FOCUSED]);
2932 scr->window_title_texture[WS_FOCUSED] = *texture;
2934 if (scr->icon_title_texture) {
2935 wTextureDestroy(scr, (WTexture*)scr->icon_title_texture);
2937 scr->icon_title_texture
2938 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_FOCUSED]->any.color);
2940 return REFRESH_WINDOW_TEXTURES;
2944 static int
2945 setPTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2947 if (scr->window_title_texture[WS_PFOCUSED]) {
2948 wTextureDestroy(scr, scr->window_title_texture[WS_PFOCUSED]);
2950 scr->window_title_texture[WS_PFOCUSED] = *texture;
2952 return REFRESH_WINDOW_TEXTURES;
2956 static int
2957 setUTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2959 if (scr->window_title_texture[WS_UNFOCUSED]) {
2960 wTextureDestroy(scr, scr->window_title_texture[WS_UNFOCUSED]);
2962 scr->window_title_texture[WS_UNFOCUSED] = *texture;
2964 if (scr->resizebar_texture[0]) {
2965 wTextureDestroy(scr, (WTexture*)scr->resizebar_texture[0]);
2967 scr->resizebar_texture[0]
2968 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_UNFOCUSED]->any.color);
2970 if (scr->geometry_display != None)
2971 XSetWindowBackground(dpy, scr->geometry_display,
2972 scr->resizebar_texture[0]->normal.pixel);
2974 return REFRESH_WINDOW_TEXTURES;
2978 static int
2979 setMenuTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2981 if (scr->menu_title_texture[0]) {
2982 wTextureDestroy(scr, scr->menu_title_texture[0]);
2984 scr->menu_title_texture[0] = *texture;
2986 return REFRESH_MENU_TEXTURES;
2990 static int
2991 setMenuTextBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2993 if (scr->menu_item_texture) {
2994 wTextureDestroy(scr, scr->menu_item_texture);
2995 wTextureDestroy(scr, (WTexture*)scr->menu_item_auxtexture);
2997 scr->menu_item_texture = *texture;
2999 scr->menu_item_auxtexture
3000 = wTextureMakeSolid(scr, &scr->menu_item_texture->any.color);
3002 return REFRESH_MENU_TEXTURES;
3006 static int
3007 setKeyGrab(WScreen *scr, WDefaultEntry *entry, WShortKey *shortcut, long index)
3009 WWindow *wwin;
3010 wKeyBindings[index] = *shortcut;
3012 wwin = scr->focused_window;
3014 while (wwin!=NULL) {
3015 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
3017 if (!wwin->window_flags.no_bind_keys) {
3018 wWindowSetKeyGrabs(wwin);
3020 wwin = wwin->prev;
3023 return 0;
3027 static int
3028 setIconPosition(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
3030 wArrangeIcons(scr, True);
3032 return 0;
3038 * Very ugly kluge.
3039 * Need access to the double click variables, so that all widgets in
3040 * wmaker panels will have the same dbl-click values.
3041 * TODO: figure a better way of dealing with it.
3043 #include "WINGsP.h"
3045 static int
3046 setDoubleClick(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
3048 extern _WINGsConfiguration WINGsConfiguration;
3050 if (*value <= 0)
3051 *(int*)foo = 1;
3053 WINGsConfiguration.doubleClickDelay = *value;
3055 return 0;