Window Maker 0.20.3
[wmaker-crm.git] / src / defaults.c
blobb9e7c8b4ce523285146c5c6db6a5aaeb34ec2861
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 {"random", WIS_RANDOM, 0},
226 {NULL, 0, 0}
229 static WOptionEnumeration seJustifications[] = {
230 {"Left", WTJ_LEFT, 0},
231 {"Center", WTJ_CENTER, 0},
232 {"Right", WTJ_RIGHT, 0},
233 {NULL, 0, 0}
236 static WOptionEnumeration seIconPositions[] = {
237 {"blv", IY_BOTTOM|IY_LEFT|IY_VERT, 0},
238 {"blh", IY_BOTTOM|IY_LEFT|IY_HORIZ, 0},
239 {"brv", IY_BOTTOM|IY_RIGHT|IY_VERT, 0},
240 {"brh", IY_BOTTOM|IY_RIGHT|IY_HORIZ, 0},
241 {"tlv", IY_TOP|IY_LEFT|IY_VERT, 0},
242 {"tlh", IY_TOP|IY_LEFT|IY_HORIZ, 0},
243 {"trv", IY_TOP|IY_RIGHT|IY_VERT, 0},
244 {"trh", IY_TOP|IY_RIGHT|IY_HORIZ, 0},
245 {NULL, 0, 0}
251 * All entries in the tables bellow, NEED to have a default value
252 * defined, and this value needs to be correct.
255 /* these options will only affect the window manager on startup
257 * static defaults can't access the screen data, because it is
258 * created after these defaults are read
260 WDefaultEntry staticOptionList[] = {
262 {"DisableDithering", "NO", NULL,
263 &wPreferences.no_dithering, getBool, NULL
265 {"ColormapSize", "4", NULL,
266 &wPreferences.cmap_size, getInt, NULL
268 /* static by laziness */
269 {"IconSize", "64", NULL,
270 &wPreferences.icon_size, getInt, NULL
272 {"ModifierKey", "Mod1", NULL,
273 &wPreferences.modifier_mask, getModMask, NULL
275 {"DisableWSMouseActions", "NO", NULL,
276 &wPreferences.disable_root_mouse, getBool, NULL
278 {"FocusMode", "manual", seFocusModes,
279 &wPreferences.focus_mode, getEnum, NULL
280 }, /* have a problem when switching from manual to sloppy without restart */
281 {"NewStyle", "NO", NULL,
282 &wPreferences.new_style, getBool, NULL
284 {"DisableDock", "NO", (void*) WM_DOCK,
285 NULL, getBool, setIfDockPresent
287 {"DisableClip", "NO", (void*) WM_CLIP,
288 NULL, getBool, setIfDockPresent
294 WDefaultEntry optionList[] = {
295 /* dynamic options */
296 {"IconPosition", "blh", seIconPositions,
297 &wPreferences.icon_yard, getEnum, setIconPosition
299 {"IconificationStyle", "Zoom", seIconificationStyles,
300 &wPreferences.iconification_style, getEnum, NULL
302 {"SelectWindowsMouseButton", "Left", seMouseButtons,
303 &wPreferences.select_button, getEnum, NULL
305 {"WindowListMouseButton", "Middle", seMouseButtons,
306 &wPreferences.windowl_button, getEnum, NULL
308 {"ApplicationMenuMouseButton", "Right", seMouseButtons,
309 &wPreferences.menu_button, getEnum, NULL
311 {"PixmapPath", DEF_PIXMAP_PATHS, NULL,
312 &wPreferences.pixmap_path, getPathList, NULL
314 {"IconPath", DEF_ICON_PATHS, NULL,
315 &wPreferences.icon_path, getPathList, NULL
317 {"ColormapMode", "auto", seColormapModes,
318 &wPreferences.colormap_mode, getEnum, NULL
320 {"AutoFocus", "NO", NULL,
321 &wPreferences.auto_focus, getBool, NULL
323 {"RaiseDelay", "0", NULL,
324 &wPreferences.raise_delay, getInt, NULL
326 {"CirculateRaise", "NO", NULL,
327 &wPreferences.circ_raise, getBool, NULL
329 {"Superfluous", "NO", NULL,
330 &wPreferences.superfluous, getBool, NULL
332 {"AdvanceToNewWorkspace", "NO", NULL,
333 &wPreferences.ws_advance, getBool, NULL
335 {"CycleWorkspaces", "NO", NULL,
336 &wPreferences.ws_cycle, getBool, NULL
338 {"StickyIcons", "NO", NULL,
339 &wPreferences.sticky_icons, getBool, setStickyIcons
341 {"SaveSessionOnExit", "NO", NULL,
342 &wPreferences.save_session_on_exit, getBool, NULL
344 {"WrapMenus", "NO", NULL,
345 &wPreferences.wrap_menus, getBool, NULL
347 {"ScrollableMenus", "NO", NULL,
348 &wPreferences.scrollable_menus, getBool, NULL
350 {"MenuScrollSpeed", "medium", seSpeeds,
351 &wPreferences.menu_scroll_speed, getEnum, NULL
353 {"IconSlideSpeed", "medium", seSpeeds,
354 &wPreferences.icon_slide_speed, getEnum, NULL
356 {"ShadeSpeed", "medium", seSpeeds,
357 &wPreferences.shade_speed, getEnum, NULL
359 {"DoubleClickTime", "250", (void*) &wPreferences.dblclick_time,
360 &wPreferences.dblclick_time, getInt, setDoubleClick,
362 {"AlignSubmenus", "NO", NULL,
363 &wPreferences.align_menus, getBool, NULL
365 {"OnTopTransients", "NO", NULL,
366 &wPreferences.on_top_transients, getBool, NULL
368 {"WindowPlacement", "auto", sePlacements,
369 &wPreferences.window_placement, getEnum, NULL
371 {"IgnoreFocusClick","NO", NULL,
372 &wPreferences.ignore_focus_click, getBool, NULL
374 {"UseSaveUnders", "NO", NULL,
375 &wPreferences.use_saveunders, getBool, NULL
377 {"OpaqueMove", "NO", NULL,
378 &wPreferences.opaque_move, getBool, NULL
380 {"DisableSound", "NO", NULL,
381 &wPreferences.no_sound, getBool, NULL
383 {"DisableAnimations", "NO", NULL,
384 &wPreferences.no_animations, getBool, NULL
386 {"DontLinkWorkspaces","NO", NULL,
387 &wPreferences.no_autowrap, getBool, NULL
389 {"EdgeResistance", "0", NULL,
390 &wPreferences.edge_resistance,getInt, NULL
392 {"AutoArrangeIcons", "NO", NULL,
393 &wPreferences.auto_arrange_icons, getBool, NULL
395 {"NoWindowOverDock", "NO", NULL,
396 &wPreferences.no_window_over_dock, getBool, NULL
398 {"NoWindowOverIcons", "NO", NULL,
399 &wPreferences.no_window_over_icons, getBool, NULL
401 {"WindowPlaceOrigin", "(0, 0)", NULL,
402 &wPreferences.window_place_origin, getCoord, NULL
404 {"ResizeDisplay", "corner", seGeomDisplays,
405 &wPreferences.size_display, getEnum, NULL
407 {"MoveDisplay", "corner", seGeomDisplays,
408 &wPreferences.move_display, getEnum, NULL
410 {"DontConfirmKill", "NO", NULL,
411 &wPreferences.dont_confirm_kill, getBool,NULL
413 {"WindowTitleBalloons", "NO", NULL,
414 &wPreferences.window_balloon, getBool, NULL
416 {"MiniwindowTitleBalloons", "NO", NULL,
417 &wPreferences.miniwin_balloon,getBool, NULL
419 {"AppIconBalloons", "NO", NULL,
420 &wPreferences.appicon_balloon,getBool, NULL
422 {"DisableBlinking", "NO", NULL,
423 &wPreferences.dont_blink, getBool, NULL
425 /* style options */
426 {"WidgetColor", "(solid, gray)", NULL,
427 NULL, getTexture, setWidgetColor,
429 {"WorkspaceBack", "(solid, black)", NULL,
430 NULL, getWSBackground,setWorkspaceBack
432 {"IconBack", "(solid, gray)", NULL,
433 NULL, getTexture, setIconTile
435 {"TitleJustify", "center", seJustifications,
436 &wPreferences.title_justification, getEnum, setJustify
438 {"WindowTitleFont", DEF_TITLE_FONT, NULL,
439 NULL, getFont, setWinTitleFont
441 {"MenuTitleFont", DEF_MENU_TITLE_FONT, NULL,
442 NULL, getFont, setMenuTitleFont
444 {"MenuTextFont", DEF_MENU_ENTRY_FONT, NULL,
445 NULL, getFont, setMenuTextFont
447 {"IconTitleFont", DEF_ICON_TITLE_FONT, NULL,
448 NULL, getFont, setIconTitleFont
450 {"ClipTitleFont", DEF_CLIP_TITLE_FONT, NULL,
451 NULL, getFont, setClipTitleFont
453 {"DisplayFont", DEF_INFO_TEXT_FONT, NULL,
454 NULL, getFont, setDisplayFont
456 {"HighlightColor", "white", NULL,
457 NULL, getColor, setHightlight
459 {"HighlightTextColor", "black", NULL,
460 NULL, getColor, setHightlightText
462 {"ClipTitleColor", "black", (void*)CLIP_NORMAL,
463 NULL, getColor, setClipTitleColor
465 {"CClipTitleColor", "\"#454045\"", (void*)CLIP_COLLAPSED,
466 NULL, getColor, setClipTitleColor
468 {"FTitleColor", "white", (void*)WS_FOCUSED,
469 NULL, getColor, setWTitleColor
471 {"PTitleColor", "white", (void*)WS_PFOCUSED,
472 NULL, getColor, setWTitleColor
474 {"UTitleColor", "black", (void*)WS_UNFOCUSED,
475 NULL, getColor, setWTitleColor
477 {"FTitleBack", "(solid, black)", NULL,
478 NULL, getTexture, setFTitleBack
480 {"PTitleBack", "(solid, \"#616161\")", NULL,
481 NULL, getTexture, setPTitleBack
483 {"UTitleBack", "(solid, gray)", NULL,
484 NULL, getTexture, setUTitleBack
486 {"MenuTitleColor", "white", NULL,
487 NULL, getColor, setMenuTitleColor
489 {"MenuTextColor", "black", NULL,
490 NULL, getColor, setMenuTextColor
492 {"MenuDisabledColor", "\"#616161\"", NULL,
493 NULL, getColor, setMenuDisabledColor
495 {"MenuTitleBack", "(solid, black)", NULL,
496 NULL, getTexture, setMenuTitleBack
498 {"MenuTextBack", "(solid, gray)", NULL,
499 NULL, getTexture, setMenuTextBack
502 /* keybindings */
503 {"RootMenuKey", "None", (void*)WKBD_ROOTMENU,
504 NULL, getKeybind, setKeyGrab
506 {"WindowListKey", "None", (void*)WKBD_WINDOWLIST,
507 NULL, getKeybind, setKeyGrab
509 {"WindowMenuKey", "None", (void*)WKBD_WINDOWMENU,
510 NULL, getKeybind, setKeyGrab
512 {"ClipLowerKey", "None", (void*)WKBD_CLIPLOWER,
513 NULL, getKeybind, setKeyGrab
515 {"ClipRaiseKey", "None", (void*)WKBD_CLIPRAISE,
516 NULL, getKeybind, setKeyGrab
518 {"ClipRaiseLowerKey", "None", (void*)WKBD_CLIPRAISELOWER,
519 NULL, getKeybind, setKeyGrab
521 {"MiniaturizeKey", "None", (void*)WKBD_MINIATURIZE,
522 NULL, getKeybind, setKeyGrab
524 {"HideKey", "None", (void*)WKBD_HIDE,
525 NULL, getKeybind, setKeyGrab
527 {"CloseKey", "None", (void*)WKBD_CLOSE,
528 NULL, getKeybind, setKeyGrab
530 {"MaximizeKey", "None", (void*)WKBD_MAXIMIZE,
531 NULL, getKeybind, setKeyGrab
533 {"VMaximizeKey", "None", (void*)WKBD_VMAXIMIZE,
534 NULL, getKeybind, setKeyGrab
536 {"RaiseKey", "Meta+Up", (void*)WKBD_RAISE,
537 NULL, getKeybind, setKeyGrab
539 {"LowerKey", "Meta+Down", (void*)WKBD_LOWER,
540 NULL, getKeybind, setKeyGrab
542 {"RaiseLowerKey", "None", (void*)WKBD_RAISELOWER,
543 NULL, getKeybind, setKeyGrab
545 {"ShadeKey", "None", (void*)WKBD_SHADE,
546 NULL, getKeybind, setKeyGrab
548 {"SelectKey", "None", (void*)WKBD_SELECT,
549 NULL, getKeybind, setKeyGrab
551 {"FocusNextKey", "None", (void*)WKBD_FOCUSNEXT,
552 NULL, getKeybind, setKeyGrab
554 {"FocusPrevKey", "None", (void*)WKBD_FOCUSPREV,
555 NULL, getKeybind, setKeyGrab
557 {"NextWorkspaceKey", "None", (void*)WKBD_NEXTWORKSPACE,
558 NULL, getKeybind, setKeyGrab
560 {"PrevWorkspaceKey", "None", (void*)WKBD_PREVWORKSPACE,
561 NULL, getKeybind, setKeyGrab
563 {"NextWorkspaceLayerKey", "None", (void*)WKBD_NEXTWSLAYER,
564 NULL, getKeybind, setKeyGrab
566 {"PrevWorkspaceLayerKey", "None", (void*)WKBD_PREVWSLAYER,
567 NULL, getKeybind, setKeyGrab
569 {"Workspace1Key", "None", (void*)WKBD_WORKSPACE1,
570 NULL, getKeybind, setKeyGrab
572 {"Workspace2Key", "None", (void*)WKBD_WORKSPACE2,
573 NULL, getKeybind, setKeyGrab
575 {"Workspace3Key", "None", (void*)WKBD_WORKSPACE3,
576 NULL, getKeybind, setKeyGrab
578 {"Workspace4Key", "None", (void*)WKBD_WORKSPACE4,
579 NULL, getKeybind, setKeyGrab
581 {"Workspace5Key", "None", (void*)WKBD_WORKSPACE5,
582 NULL, getKeybind, setKeyGrab
584 {"Workspace6Key", "None", (void*)WKBD_WORKSPACE6,
585 NULL, getKeybind, setKeyGrab
587 {"Workspace7Key", "None", (void*)WKBD_WORKSPACE7,
588 NULL, getKeybind, setKeyGrab
590 {"Workspace8Key", "None", (void*)WKBD_WORKSPACE8,
591 NULL, getKeybind, setKeyGrab
593 {"Workspace9Key", "None", (void*)WKBD_WORKSPACE9,
594 NULL, getKeybind, setKeyGrab
596 {"Workspace10Key", "None", (void*)WKBD_WORKSPACE10,
597 NULL, getKeybind, setKeyGrab
599 {"WindowShortcut1Key","None", (void*)WKBD_WINDOW1,
600 NULL, getKeybind, setKeyGrab
602 {"WindowShortcut2Key","None", (void*)WKBD_WINDOW2,
603 NULL, getKeybind, setKeyGrab
605 {"WindowShortcut3Key","None", (void*)WKBD_WINDOW3,
606 NULL, getKeybind, setKeyGrab
608 {"WindowShortcut4Key","None", (void*)WKBD_WINDOW4,
609 NULL, getKeybind, setKeyGrab
611 #ifdef KEEP_XKB_LOCK_STATUS
612 {"ToggleKbdModeKey", "None", (void*)WKBD_TOGGLE,
613 NULL, getKeybind, setKeyGrab
615 {"KbdModeLock", "NO", NULL,
616 &wPreferences.modelock, getBool, NULL
618 #endif /* KEEP_XKB_LOCK_STATUS */
622 #if 0
623 static void rereadDefaults(void);
624 #endif
626 #if 0
627 static void
628 rereadDefaults(void)
630 /* must defer the update because accessing X data from a
631 * signal handler can mess up Xlib */
634 #endif
636 static void
637 initDefaults()
639 int i;
640 WDefaultEntry *entry;
642 PLSetStringCmpHook(StringCompareHook);
644 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
645 entry = &optionList[i];
647 entry->plkey = PLMakeString(entry->key);
648 if (entry->default_value)
649 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
650 else
651 entry->plvalue = NULL;
654 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
655 entry = &staticOptionList[i];
657 entry->plkey = PLMakeString(entry->key);
658 if (entry->default_value)
659 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
660 else
661 entry->plvalue = NULL;
665 wDomainName = PLMakeString(WMDOMAIN_NAME);
666 wAttributeDomainName = PLMakeString(WMATTRIBUTE_DOMAIN_NAME);
668 PLRegister(wDomainName, rereadDefaults);
669 PLRegister(wAttributeDomainName, rereadDefaults);
676 #if 0
677 proplist_t
678 wDefaultsInit(int screen_number)
680 static int defaults_inited = 0;
681 proplist_t dict;
683 if (!defaults_inited) {
684 initDefaults();
687 dict = PLGetDomain(wDomainName);
688 if (!dict) {
689 wwarning(_("could not read domain \"%s\" from defaults database"),
690 PLGetString(wDomainName));
693 return dict;
695 #endif
698 void
699 wDefaultsDestroyDomain(WDDomain *domain)
701 if (domain->dictionary)
702 PLRelease(domain->dictionary);
703 free(domain->path);
704 free(domain);
708 WDDomain*
709 wDefaultsInitDomain(char *domain, Bool requireDictionary)
711 WDDomain *db;
712 struct stat stbuf;
713 static int inited = 0;
714 char path[PATH_MAX];
715 char *the_path;
716 proplist_t shared_dict=NULL;
718 if (!inited) {
719 inited = 1;
720 initDefaults();
723 db = wmalloc(sizeof(WDDomain));
724 memset(db, 0, sizeof(WDDomain));
725 db->domain_name = domain;
726 db->path = wdefaultspathfordomain(domain);
727 the_path = db->path;
729 if (the_path && stat(the_path, &stbuf)>=0) {
730 db->dictionary = ReadProplistFromFile(the_path);
731 if (db->dictionary) {
732 if (requireDictionary && !PLIsDictionary(db->dictionary)) {
733 PLRelease(db->dictionary);
734 db->dictionary = NULL;
735 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
736 domain, the_path);
738 db->timestamp = stbuf.st_mtime;
739 } else {
740 wwarning(_("could not load domain %s from user defaults database"),
741 domain);
745 /* global system dictionary */
746 sprintf(path, "%s/%s/%s", PKGDATADIR, DEFAULTS_DIR, domain);
747 if (stat(path, &stbuf)>=0) {
748 shared_dict = ReadProplistFromFile(path);
749 if (shared_dict) {
750 if (requireDictionary && !PLIsDictionary(shared_dict)) {
751 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
752 domain, path);
753 PLRelease(shared_dict);
754 shared_dict = NULL;
755 } else {
756 if (db->dictionary && PLIsDictionary(shared_dict) &&
757 PLIsDictionary(db->dictionary)) {
758 PLMergeDictionaries(shared_dict, db->dictionary);
759 PLRelease(db->dictionary);
760 db->dictionary = shared_dict;
761 if (stbuf.st_mtime > db->timestamp)
762 db->timestamp = stbuf.st_mtime;
763 } else if (!db->dictionary) {
764 db->dictionary = shared_dict;
765 if (stbuf.st_mtime > db->timestamp)
766 db->timestamp = stbuf.st_mtime;
769 } else {
770 wwarning(_("could not load domain %s from global defaults database"),
771 domain);
775 /* set to save it in user's directory, no matter from where it was read */
776 if (db->dictionary) {
777 proplist_t tmp = PLMakeString(db->path);
779 PLSetFilename(db->dictionary, tmp);
780 PLRelease(tmp);
783 return db;
787 void
788 wReadStaticDefaults(proplist_t dict)
790 proplist_t plvalue;
791 WDefaultEntry *entry;
792 int i;
793 void *tdata;
796 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
797 entry = &staticOptionList[i];
799 if (dict)
800 plvalue = PLGetDictionaryEntry(dict, entry->plkey);
801 else
802 plvalue = NULL;
804 if (!plvalue) {
805 /* no default in the DB. Use builtin default */
806 plvalue = entry->plvalue;
809 if (plvalue) {
810 /* convert data */
811 (*entry->convert)(NULL, entry, plvalue, entry->addr, &tdata);
812 if (entry->update) {
813 (*entry->update)(NULL, entry, tdata, entry->extra_data);
819 void
820 wDefaultsCheckDomains(void *foo)
822 WScreen *scr;
823 struct stat stbuf;
824 proplist_t dict;
825 int i;
826 char path[PATH_MAX];
828 #ifdef HEARTBEAT
829 puts("Checking domains...");
830 #endif
831 if (stat(WDWindowMaker->path, &stbuf)>=0
832 && WDWindowMaker->timestamp < stbuf.st_mtime) {
833 proplist_t shared_dict = NULL;
834 #ifdef HEARTBEAT
835 puts("Checking WindowMaker domain");
836 #endif
837 WDWindowMaker->timestamp = stbuf.st_mtime;
839 /* global dictionary */
840 sprintf(path, "%s/%s/WindowMaker", PKGDATADIR, DEFAULTS_DIR);
841 if (stat(path, &stbuf)>=0) {
842 shared_dict = ReadProplistFromFile(path);
843 if (shared_dict && !PLIsDictionary(shared_dict)) {
844 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
845 "WindowMaker", path);
846 PLRelease(shared_dict);
847 shared_dict = NULL;
848 } else if (!shared_dict) {
849 wwarning(_("could not load domain %s from global defaults database"),
850 "WindowMaker");
853 /* user dictionary */
854 dict = ReadProplistFromFile(WDWindowMaker->path);
855 if (dict) {
856 if (!PLIsDictionary(dict)) {
857 PLRelease(dict);
858 dict = NULL;
859 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
860 "WindowMaker", WDWindowMaker->path);
861 } else {
862 if (shared_dict) {
863 PLSetFilename(shared_dict, PLGetFilename(dict));
864 PLMergeDictionaries(shared_dict, dict);
865 PLRelease(dict);
866 dict = shared_dict;
867 shared_dict = NULL;
869 for (i=0; i<wScreenCount; i++) {
870 scr = wScreenWithNumber(i);
871 if (scr)
872 wReadDefaults(scr, dict);
874 if (WDWindowMaker->dictionary) {
875 PLRelease(WDWindowMaker->dictionary);
877 WDWindowMaker->dictionary = dict;
879 } else {
880 wwarning(_("could not load domain %s from user defaults database"),
881 "WindowMaker");
883 if (shared_dict) {
884 PLRelease(shared_dict);
888 if (stat(WDWindowAttributes->path, &stbuf)>=0
889 && WDWindowAttributes->timestamp < stbuf.st_mtime) {
890 #ifdef HEARTBEAT
891 puts("Checking WMWindowAttributes domain");
892 #endif
893 dict = ReadProplistFromFile(WDWindowAttributes->path);
894 if (dict) {
895 if (!PLIsDictionary(dict)) {
896 PLRelease(dict);
897 dict = NULL;
898 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
899 "WMWindowAttributes", WDWindowAttributes->path);
900 } else {
901 if (WDWindowAttributes->dictionary)
902 PLRelease(WDWindowAttributes->dictionary);
903 WDWindowAttributes->dictionary = dict;
904 for (i=0; i<wScreenCount; i++) {
905 scr = wScreenWithNumber(i);
906 if (scr)
907 wDefaultUpdateIcons(scr);
910 } else {
911 wwarning(_("could not load domain %s from user defaults database"),
912 "WMWindowAttributes");
914 WDWindowAttributes->timestamp = stbuf.st_mtime;
918 if (stat(WDRootMenu->path, &stbuf)>=0
919 && WDRootMenu->timestamp < stbuf.st_mtime) {
920 dict = ReadProplistFromFile(WDRootMenu->path);
921 #ifdef HEARTBEAT
922 puts("Checking WMRootMenu domain");
923 #endif
924 if (dict) {
925 if (!PLIsArray(dict) && !PLIsString(dict)) {
926 PLRelease(dict);
927 dict = NULL;
928 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
929 "WMRootMenu", WDRootMenu->path);
930 } else {
931 if (WDRootMenu->dictionary) {
932 PLRelease(WDRootMenu->dictionary);
934 WDRootMenu->dictionary = dict;
936 } else {
937 wwarning(_("could not load domain %s from user defaults database"),
938 "WMRootMenu");
940 WDRootMenu->timestamp = stbuf.st_mtime;
943 WMAddTimerHandler(DEFAULTS_CHECK_INTERVAL, wDefaultsCheckDomains, foo);
948 #define REFRESH_WINDOW_TEXTURES (1<<0)
949 #define REFRESH_MENU_TEXTURES (1<<1)
950 #define REFRESH_WINDOW_FONT (1<<2)
951 #define REFRESH_MENU_TITLE_FONT (1<<3)
952 #define REFRESH_MENU_FONT (1<<4)
953 #define REFRESH_FORE_COLOR (1<<5)
954 #define REFRESH_ICON_TILE (1<<6)
955 #define REFRESH_ICON_FONT (1<<7)
956 #define REFRESH_WORKSPACE_BACK (1<<8)
958 static void
959 refreshMenus(WScreen *scr, int flags)
961 WMenu *menu;
963 menu = scr->root_menu;
964 if (menu)
965 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
967 menu = scr->workspace_menu;
968 if (menu)
969 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
971 menu = scr->switch_menu;
972 if (menu)
973 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
975 menu = scr->window_menu;
976 if (menu)
977 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
979 menu = scr->icon_menu;
980 if (menu)
981 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
983 if (scr->dock) {
984 menu = scr->dock->menu;
985 if (menu)
986 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
988 menu = scr->clip_menu;
989 if (menu)
990 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
992 menu = scr->clip_submenu;
993 if (menu)
994 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
996 menu = scr->clip_options;
997 if (menu)
998 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
1002 static void
1003 refreshAppIcons(WScreen *scr, int flags)
1005 WAppIcon *aicon = scr->app_icon_list;
1007 while (aicon) {
1008 if (aicon->icon) {
1009 aicon->icon->force_paint = 1;
1011 aicon = aicon->next;
1016 static void
1017 refreshWindows(WScreen *scr, int flags)
1019 WWindow *wwin;
1021 wwin = scr->focused_window;
1022 while (wwin) {
1023 if (flags & REFRESH_WINDOW_FONT) {
1024 wWindowConfigureBorders(wwin);
1026 if ((flags & (REFRESH_ICON_TILE|REFRESH_WINDOW_TEXTURES)) &&
1027 wwin->flags.miniaturized && wwin->icon) {
1028 wwin->icon->force_paint = 1;
1030 if (flags & REFRESH_WINDOW_TEXTURES) {
1031 wwin->frame->flags.need_texture_remake = 1;
1033 wwin = wwin->prev;
1038 void
1039 wReadDefaults(WScreen *scr, proplist_t new_dict)
1041 proplist_t plvalue, old_value;
1042 WDefaultEntry *entry;
1043 int i, changed, must_update;
1044 int needs_refresh;
1045 void *tdata;
1046 proplist_t old_dict = (WDWindowMaker->dictionary!=new_dict
1047 ? WDWindowMaker->dictionary : NULL);
1049 changed = 0;
1050 must_update = 0;
1052 needs_refresh = 0;
1054 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
1055 entry = &optionList[i];
1057 if (new_dict)
1058 plvalue = PLGetDictionaryEntry(new_dict, entry->plkey);
1059 else
1060 plvalue = NULL;
1062 if (!old_dict)
1063 old_value = NULL;
1064 else
1065 old_value = PLGetDictionaryEntry(old_dict, entry->plkey);
1068 if (!plvalue && !old_value) {
1069 /* no default in the DB. Use builtin default */
1070 plvalue = entry->plvalue;
1071 if (plvalue && new_dict) {
1072 PLInsertDictionaryEntry(new_dict, entry->plkey, plvalue);
1073 changed = 1;
1074 must_update = 1;
1076 } else if (!plvalue) {
1077 /* value was deleted from DB. Keep current value */
1078 continue;
1079 } else if (!old_value) {
1080 /* set value for the 1st time */
1081 changed = 1;
1082 } else if (!PLIsEqual(plvalue, old_value)) {
1083 /* value has changed */
1084 changed = 1;
1085 } else {
1086 /* value was not changed since last time */
1087 continue;
1090 if (plvalue) {
1091 #ifdef DEBUG
1092 printf("Updating %s to %s\n", entry->key, PLGetDescription(plvalue));
1093 #endif
1094 /* convert data */
1095 if ((*entry->convert)(scr, entry, plvalue, entry->addr, &tdata)) {
1096 if (entry->update) {
1097 needs_refresh |=
1098 (*entry->update)(scr, entry, tdata, entry->extra_data);
1104 if (needs_refresh!=0) {
1105 int foo;
1107 foo = 0;
1108 if (needs_refresh & REFRESH_MENU_TEXTURES)
1109 foo |= MR_TEXT_BACK;
1110 if (needs_refresh & REFRESH_MENU_FONT)
1111 foo |= MR_RESIZED;
1112 if (needs_refresh & REFRESH_MENU_TITLE_FONT)
1113 foo |= MR_TITLE_TEXT;
1115 if (foo)
1116 refreshMenus(scr, foo);
1118 if (needs_refresh & (REFRESH_WINDOW_TEXTURES|REFRESH_WINDOW_FONT|
1119 REFRESH_ICON_TILE))
1120 refreshWindows(scr, needs_refresh);
1122 if (needs_refresh & REFRESH_ICON_TILE)
1123 refreshAppIcons(scr, needs_refresh);
1125 #ifdef EXPERIMENTAL
1126 if (needs_refresh & REFRESH_WORKSPACE_BACK) {
1127 WWorkspaceTexture *wsback;
1129 /* update the background for the workspace */
1130 if (scr->current_workspace < scr->wspaceTextureCount
1131 && scr->wspaceTextures[scr->current_workspace]) {
1132 wsback = scr->wspaceTextures[scr->current_workspace];
1133 } else {
1134 wsback = scr->defaultTexure;
1136 if (wsback) {
1137 if (wsback->pixmap!=None) {
1138 XSetWindowBackgroundPixmap(dpy, scr->root_win,
1139 wsback->pixmap);
1140 } else {
1141 XSetWindowBackground(dpy, scr->root_win, wsback->solid);
1143 XClearWindow(dpy, scr->root_win);
1144 XFlush(dpy);
1147 #endif /* !EXPERIMENTAL */
1148 wRefreshDesktop(scr);
1153 void
1154 wDefaultUpdateIcons(WScreen *scr)
1156 WAppIcon *aicon = scr->app_icon_list;
1157 WWindow *wwin = scr->focused_window;
1158 char *file;
1160 while(aicon) {
1161 file = wDefaultGetIconFile(scr, aicon->wm_instance, aicon->wm_class,
1162 False);
1163 if ((file && aicon->icon->file && strcmp(file, aicon->icon->file)!=0)
1164 || (file && !aicon->icon->file)) {
1165 RImage *new_image;
1167 if (aicon->icon->file)
1168 free(aicon->icon->file);
1169 aicon->icon->file = wstrdup(file);
1171 new_image = wDefaultGetImage(scr, aicon->wm_instance,
1172 aicon->wm_class);
1173 if (new_image) {
1174 wIconChangeImage(aicon->icon, new_image);
1175 wAppIconPaint(aicon);
1178 aicon = aicon->next;
1181 if (!wPreferences.flags.noclip)
1182 wClipIconPaint(scr->clip_icon);
1184 while (wwin) {
1185 if (wwin->icon && wwin->flags.miniaturized) {
1186 file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
1187 False);
1188 if ((file && wwin->icon->file && strcmp(file, wwin->icon->file)!=0)
1189 || (file && !wwin->icon->file)) {
1190 RImage *new_image;
1192 if (wwin->icon->file)
1193 free(wwin->icon->file);
1194 wwin->icon->file = wstrdup(file);
1196 new_image = wDefaultGetImage(scr, wwin->wm_instance,
1197 wwin->wm_class);
1198 if (new_image)
1199 wIconChangeImage(wwin->icon, new_image);
1202 wwin = wwin->prev;
1207 /* --------------------------- Local ----------------------- */
1209 #define STRINGP(x) if (!PLIsString(value)) { \
1210 wwarning(_("Wrong option format for key \"%s\". Should be %s."), \
1211 entry->key, x); \
1212 return False; }
1216 static int
1217 string2index(proplist_t key, proplist_t val, proplist_t def,
1218 WOptionEnumeration *values)
1220 char *str;
1221 WOptionEnumeration *v;
1222 char buffer[TOTAL_VALUES_LENGTH];
1224 if (PLIsString(val) && (str = PLGetString(val))) {
1225 for (v=values; v->string!=NULL; v++) {
1226 if (strcasecmp(v->string, str)==0)
1227 return v->value;
1231 buffer[0] = 0;
1232 for (v=values; v->string!=NULL; v++) {
1233 if (!v->is_alias) {
1234 if (buffer[0]!=0)
1235 strcat(buffer, ", ");
1236 strcat(buffer, v->string);
1239 wwarning(_("wrong option value for key \"%s\". Should be one of %s"),
1240 PLGetString(key), buffer);
1242 if (def) {
1243 return string2index(key, val, NULL, values);
1246 return -1;
1253 * value - is the value in the defaults DB
1254 * addr - is the address to store the data
1255 * ret - is the address to store a pointer to a temporary buffer. ret
1256 * must not be freed and is used by the set functions
1258 static int
1259 getBool(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1260 void **ret)
1262 static char data;
1263 char *val;
1264 int second_pass=0;
1266 STRINGP("Boolean");
1268 val = PLGetString(value);
1270 again:
1271 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
1272 || strcasecmp(val, "YES")==0) {
1274 data = 1;
1275 } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
1276 || strcasecmp(val, "NO")==0) {
1277 data = 0;
1278 } else {
1279 int i;
1280 if (sscanf(val, "%i", &i)==1) {
1281 if (i!=0)
1282 data = 1;
1283 else
1284 data = 0;
1285 } else {
1286 wwarning(_("can't convert \"%s\" to boolean for key \"%s\""),
1287 val, entry->key);
1288 if (second_pass==0) {
1289 val = PLGetString(entry->plvalue);
1290 second_pass = 1;
1291 wwarning(_("using default \"%s\" instead"), val);
1292 goto again;
1294 return False;
1298 if (ret)
1299 *ret = &data;
1301 if (addr) {
1302 *(char*)addr = data;
1305 return True;
1309 static int
1310 getInt(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1311 void **ret)
1313 static int data;
1314 char *val;
1317 STRINGP("Integer");
1319 val = PLGetString(value);
1321 if (sscanf(val, "%i", &data)!=1) {
1322 wwarning(_("can't convert \"%s\" to integer for key \"%s\""),
1323 val, entry->key);
1324 val = PLGetString(entry->plvalue);
1325 wwarning(_("using default \"%s\" instead"), val);
1326 if (sscanf(val, "%i", &data)!=1) {
1327 return False;
1331 if (ret)
1332 *ret = &data;
1334 if (addr) {
1335 *(int*)addr = data;
1337 return True;
1341 static int
1342 getCoord(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1343 void **ret)
1345 static WCoord data;
1346 char *val_x, *val_y;
1347 int nelem, changed=0;
1348 proplist_t elem_x, elem_y;
1350 again:
1351 if (!PLIsArray(value)) {
1352 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1353 entry->key, "Coordinate");
1354 if (changed==0) {
1355 value = entry->plvalue;
1356 changed = 1;
1357 wwarning(_("using default \"%s\" instead"), entry->default_value);
1358 goto again;
1360 return False;
1363 nelem = PLGetNumberOfElements(value);
1364 if (nelem != 2) {
1365 wwarning(_("Incorrect number of elements in array for key \"%s\"."),
1366 entry->key);
1367 if (changed==0) {
1368 value = entry->plvalue;
1369 changed = 1;
1370 wwarning(_("using default \"%s\" instead"), entry->default_value);
1371 goto again;
1373 return False;
1376 elem_x = PLGetArrayElement(value, 0);
1377 elem_y = PLGetArrayElement(value, 1);
1379 if (!elem_x || !elem_y || !PLIsString(elem_x) || !PLIsString(elem_y)) {
1380 wwarning(_("Wrong value for key \"%s\". Should be Coordinate."),
1381 entry->key);
1382 if (changed==0) {
1383 value = entry->plvalue;
1384 changed = 1;
1385 wwarning(_("using default \"%s\" instead"), entry->default_value);
1386 goto again;
1388 return False;
1391 val_x = PLGetString(elem_x);
1392 val_y = PLGetString(elem_y);
1394 if (sscanf(val_x, "%i", &data.x)!=1 || sscanf(val_y, "%i", &data.y)!=1) {
1395 wwarning(_("can't convert array to integers for \"%s\"."), entry->key);
1396 if (changed==0) {
1397 value = entry->plvalue;
1398 changed = 1;
1399 wwarning(_("using default \"%s\" instead"), entry->default_value);
1400 goto again;
1402 return False;
1405 if (data.x < 0)
1406 data.x = 0;
1407 else if (data.x > scr->scr_width/3)
1408 data.x = scr->scr_width/3;
1409 if (data.y < 0)
1410 data.y = 0;
1411 else if (data.y > scr->scr_height/3)
1412 data.y = scr->scr_height/3;
1414 if (ret)
1415 *ret = &data;
1417 if (addr) {
1418 *(WCoord*)addr = data;
1421 return True;
1425 #if 0
1426 /* This function is not used at the moment. */
1427 static int
1428 getString(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1429 void **ret)
1431 static char *data;
1433 STRINGP("String");
1435 data = PLGetString(value);
1437 if (!data) {
1438 data = PLGetString(entry->plvalue);
1439 if (!data)
1440 return False;
1443 if (ret)
1444 *ret = &data;
1446 if (addr)
1447 *(char**)addr = wstrdup(data);
1449 return True;
1451 #endif
1454 static int
1455 getPathList(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1456 void **ret)
1458 static char **data;
1459 int i, count;
1460 proplist_t d;
1461 int changed=0;
1463 again:
1464 if (!PLIsArray(value)) {
1465 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1466 entry->key, "an array of paths");
1467 if (changed==0) {
1468 value = entry->plvalue;
1469 changed = 1;
1470 wwarning(_("using default \"%s\" instead"), entry->default_value);
1471 goto again;
1473 return False;
1476 i = 0;
1477 count = PLGetNumberOfElements(value);
1478 if (count < 1) {
1479 if (changed==0) {
1480 value = entry->plvalue;
1481 changed = 1;
1482 wwarning(_("using default \"%s\" instead"), entry->default_value);
1483 goto again;
1485 return False;
1488 data = wmalloc(sizeof(char*)*(count+1));
1489 for (i=0; i<count; i++) {
1490 d = PLGetArrayElement(value, i);
1491 if (!d || !PLIsString(d)) {
1492 break;
1494 data[i] = wstrdup(PLGetString(d));
1496 data[i]=NULL;
1498 if (*(char***)addr!=NULL) {
1499 char **tmp = *(char***)addr;
1500 for (i=0; tmp[i]!=NULL; i++) {
1501 free(tmp[i]);
1503 free(tmp);
1505 *(char***)addr = data;
1507 return True;
1511 static int
1512 getEnum(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1513 void **ret)
1515 static char data;
1517 data = string2index(entry->plkey, value, entry->default_value,
1518 (WOptionEnumeration*)entry->extra_data);
1519 if (data < 0)
1520 return False;
1522 if (ret)
1523 *ret = &data;
1525 if (addr)
1526 *(char*)addr = data;
1528 return True;
1534 * (solid <color>)
1535 * (hgradient <color> <color>)
1536 * (vgradient <color> <color>)
1537 * (dgradient <color> <color>)
1538 * (mhgradient <color> <color> ...)
1539 * (mvgradient <color> <color> ...)
1540 * (tpixmap <file> <color>)
1541 * (spixmap <file> <color>)
1542 * (cpixmap <file> <color>)
1545 static WTexture*
1546 parse_texture(WScreen *scr, proplist_t pl)
1548 proplist_t elem;
1549 char *val;
1550 int nelem;
1551 WTexture *texture=NULL;
1553 nelem = PLGetNumberOfElements(pl);
1554 if (nelem < 1)
1555 return NULL;
1558 elem = PLGetArrayElement(pl, 0);
1559 if (!elem || !PLIsString(elem))
1560 return NULL;
1561 val = PLGetString(elem);
1564 if (strcasecmp(val, "solid")==0) {
1565 XColor color;
1567 if (nelem != 2)
1568 return NULL;
1570 /* get color */
1572 elem = PLGetArrayElement(pl, 1);
1573 if (!elem || !PLIsString(elem))
1574 return NULL;
1575 val = PLGetString(elem);
1577 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1578 wwarning(_("\"%s\" is not a valid color name"), val);
1579 return NULL;
1582 texture = (WTexture*)wTextureMakeSolid(scr, &color);
1583 } else if (strcasecmp(val, "dgradient")==0
1584 || strcasecmp(val, "vgradient")==0
1585 || strcasecmp(val, "hgradient")==0) {
1586 XColor color1, color2;
1587 int type;
1589 if (nelem != 3) {
1590 wwarning(_("bad number of arguments in gradient specification"));
1591 return NULL;
1594 if (val[0]=='d' || val[0]=='D')
1595 type = WTEX_DGRADIENT;
1596 else if (val[0]=='h' || val[0]=='H')
1597 type = WTEX_HGRADIENT;
1598 else
1599 type = WTEX_VGRADIENT;
1602 /* get from color */
1603 elem = PLGetArrayElement(pl, 1);
1604 if (!elem || !PLIsString(elem))
1605 return NULL;
1606 val = PLGetString(elem);
1608 if (!XParseColor(dpy, scr->colormap, val, &color1)) {
1609 wwarning(_("\"%s\" is not a valid color name"), val);
1610 return NULL;
1613 /* get to color */
1614 elem = PLGetArrayElement(pl, 2);
1615 if (!elem || !PLIsString(elem)) {
1616 return NULL;
1618 val = PLGetString(elem);
1620 if (!XParseColor(dpy, scr->colormap, val, &color2)) {
1621 wwarning(_("\"%s\" is not a valid color name"), val);
1622 return NULL;
1625 texture = (WTexture*)wTextureMakeGradient(scr, type, &color1, &color2);
1627 } else if (strcasecmp(val, "mhgradient")==0
1628 || strcasecmp(val, "mvgradient")==0
1629 || strcasecmp(val, "mdgradient")==0) {
1630 XColor color;
1631 RColor **colors;
1632 int i, count;
1633 int type;
1635 if (nelem < 3) {
1636 wwarning(_("too few arguments in multicolor gradient specification"));
1637 return NULL;
1640 if (val[1]=='h' || val[1]=='H')
1641 type = WTEX_MHGRADIENT;
1642 else if (val[1]=='v' || val[1]=='V')
1643 type = WTEX_MVGRADIENT;
1644 else
1645 type = WTEX_MDGRADIENT;
1647 count = nelem-1;
1649 colors = wmalloc(sizeof(RColor*)*(count+1));
1651 for (i=0; i<count; i++) {
1652 elem = PLGetArrayElement(pl, i+1);
1653 if (!elem || !PLIsString(elem)) {
1654 for (--i; i>=0; --i) {
1655 free(colors[i]);
1657 free(colors);
1658 return NULL;
1660 val = PLGetString(elem);
1662 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1663 wwarning(_("\"%s\" is not a valid color name"), val);
1664 for (--i; i>=0; --i) {
1665 free(colors[i]);
1667 free(colors);
1668 return NULL;
1669 } else {
1670 colors[i] = wmalloc(sizeof(RColor));
1671 colors[i]->red = color.red >> 8;
1672 colors[i]->green = color.green >> 8;
1673 colors[i]->blue = color.blue >> 8;
1676 colors[i] = NULL;
1678 texture = (WTexture*)wTextureMakeMGradient(scr, type, colors);
1679 } else if (strcasecmp(val, "spixmap")==0 ||
1680 strcasecmp(val, "cpixmap")==0 ||
1681 strcasecmp(val, "tpixmap")==0) {
1682 XColor color;
1683 int type;
1685 if (nelem != 3)
1686 return NULL;
1688 if (val[0] == 's' || val[0] == 'S')
1689 type = WTP_SCALE;
1690 else if (val[0] == 'c' || val[0] == 'C')
1691 type = WTP_CENTER;
1692 else
1693 type = WTP_TILE;
1695 /* get color */
1696 elem = PLGetArrayElement(pl, 2);
1697 if (!elem || !PLIsString(elem)) {
1698 return NULL;
1700 val = PLGetString(elem);
1702 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1703 wwarning(_("\"%s\" is not a valid color name"), val);
1704 return NULL;
1707 /* file name */
1708 elem = PLGetArrayElement(pl, 1);
1709 if (!elem || !PLIsString(elem))
1710 return NULL;
1711 val = PLGetString(elem);
1713 texture = (WTexture*)wTextureMakePixmap(scr, type, val, &color);
1715 } else {
1716 return NULL;
1718 return texture;
1723 static int
1724 getTexture(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1725 void **ret)
1727 static WTexture *texture;
1728 int changed=0;
1730 again:
1731 if (!PLIsArray(value)) {
1732 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1733 entry->key, "Texture");
1734 if (changed==0) {
1735 value = entry->plvalue;
1736 changed = 1;
1737 wwarning(_("using default \"%s\" instead"), entry->default_value);
1738 goto again;
1740 return False;
1743 if (strcmp(entry->key, "WidgetColor")==0 && !changed) {
1744 proplist_t pl;
1746 pl = PLGetArrayElement(value, 0);
1747 if (!pl || !PLIsString(pl) || !PLGetString(pl)
1748 || strcasecmp(PLGetString(pl), "solid")!=0) {
1749 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1750 entry->key, "Solid Texture");
1752 value = entry->plvalue;
1753 changed = 1;
1754 wwarning(_("using default \"%s\" instead"), entry->default_value);
1755 goto again;
1759 texture = parse_texture(scr, value);
1761 if (!texture) {
1762 wwarning(_("Error in texture specification for key \"%s\""),
1763 entry->key);
1764 if (changed==0) {
1765 value = entry->plvalue;
1766 changed = 1;
1767 wwarning(_("using default \"%s\" instead"), entry->default_value);
1768 goto again;
1770 return False;
1773 if (ret)
1774 *ret = &texture;
1776 if (addr)
1777 *(WTexture**)addr = texture;
1779 return True;
1784 #ifdef EXPERIMENTAL
1785 static int
1786 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1787 void *addr, void **ret)
1789 proplist_t elem;
1790 char *val;
1791 int nelem;
1792 static WTexture *texture=NULL;
1793 int changed=0;
1794 char *file = NULL;
1796 again:
1797 entry->extra_data = NULL;
1799 if (!PLIsArray(value)) {
1800 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1801 "WorkspaceBack", "Texture");
1802 if (changed==0) {
1803 value = entry->plvalue;
1804 changed = 1;
1805 wwarning(_("using default \"%s\" instead"), entry->default_value);
1806 goto again;
1808 return False;
1811 nelem = PLGetNumberOfElements(value);
1812 if (nelem < 1) {
1813 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1814 if (changed==0) {
1815 value = entry->plvalue;
1816 changed = 1;
1817 wwarning(_("using default \"%s\" instead"), entry->default_value);
1818 goto again;
1820 return False;
1823 elem = PLGetArrayElement(value, 0);
1824 if (!elem || !PLIsString(elem)) {
1825 wwarning(_("Wrong type for workspace background. Should be Texture."));
1826 if (changed==0) {
1827 value = entry->plvalue;
1828 changed = 1;
1829 wwarning(_("using default \"%s\" instead"), entry->default_value);
1830 goto again;
1832 return False;
1834 val = PLGetString(elem);
1836 if (strcasecmp(val, "None")==0)
1837 return False;
1839 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
1840 && strcasecmp(val, "cpixmap")!=0) {
1841 texture = parse_texture(scr, value);
1842 } else {
1843 /* spixmap || tpixmap || cpixmap */
1844 XColor color;
1845 int style;
1847 if (nelem != 3) {
1848 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1849 if (changed==0) {
1850 value = entry->plvalue;
1851 changed = 1;
1852 wwarning(_("using default \"%s\" instead"), entry->default_value);
1853 goto again;
1855 return False;
1858 switch (val[0]) {
1859 case 's':
1860 case 'S':
1861 style = WTP_SCALE;
1862 break;
1863 case 'C':
1864 case 'c':
1865 style = WTP_CENTER;
1866 break;
1867 default:
1868 style = WTP_TILE;
1869 break;
1872 /* get color */
1873 elem = PLGetArrayElement(value, 2);
1874 if (!elem || !PLIsString(elem)) {
1875 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
1876 if (changed==0) {
1877 value = entry->plvalue;
1878 changed = 1;
1879 wwarning(_("using default \"%s\" instead"), entry->default_value);
1880 goto again;
1882 return False;
1884 val = PLGetString(elem);
1886 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1887 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
1888 val);
1889 if (changed==0) {
1890 value = entry->plvalue;
1891 changed = 1;
1892 wwarning(_("using default \"%s\" instead"), entry->default_value);
1893 goto again;
1895 return False;
1898 /* file name */
1899 elem = PLGetArrayElement(value, 1);
1900 if (!elem || !PLIsString(elem)) {
1901 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
1902 if (changed==0) {
1903 value = entry->plvalue;
1904 changed = 1;
1905 wwarning(_("using default \"%s\" instead"), entry->default_value);
1906 goto again;
1908 return False;
1911 val = PLGetString(elem);
1912 file = FindImage(wPreferences.pixmap_path, val);
1913 if (!file) {
1914 wwarning(_("could not find background image \"%s\""), val);
1915 /*return False;*/
1918 /* create a dummy texture.
1919 * use free() to free this texture.
1921 texture = wmalloc(sizeof(WTexture));
1922 memset(texture, 0, sizeof(WTexture));
1923 texture->type = WTEX_PIXMAP;
1924 texture->subtype = style;
1925 texture->normal = color;
1928 if (!texture) {
1929 if (file)
1930 free(file);
1931 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
1932 if (changed==0) {
1933 value = entry->plvalue;
1934 changed = 1;
1935 wwarning(_("using default \"%s\" instead"), entry->default_value);
1936 goto again;
1938 return False;
1941 if (ret)
1942 *ret = &texture;
1944 if (addr)
1945 *(WTexture**)addr = texture;
1947 /* we use the extra_data field to pass the filename string
1948 * to the background setting function. We can't pass it with
1949 * WTexture because it holds a RImage, not a file name.
1950 * It also would be dirtier to cast the RImage to char* to make it
1951 * hold the file name. The extra_data must be freed by the
1952 * setting function.
1954 entry->extra_data = file;
1956 return True;
1958 #else /* !EXPERIMENTAL */
1959 static int
1960 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1961 void *addr, void **ret)
1963 proplist_t elem;
1964 char *val;
1965 int nelem;
1966 static WTexture *texture=NULL;
1967 int changed=0;
1969 again:
1970 if (!PLIsArray(value)) {
1971 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1972 "WorkspaceBack", "Texture");
1973 if (changed==0) {
1974 value = entry->plvalue;
1975 changed = 1;
1976 wwarning(_("using default \"%s\" instead"), entry->default_value);
1977 goto again;
1979 return False;
1982 nelem = PLGetNumberOfElements(value);
1983 if (nelem < 1) {
1984 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1985 if (changed==0) {
1986 value = entry->plvalue;
1987 changed = 1;
1988 wwarning(_("using default \"%s\" instead"), entry->default_value);
1989 goto again;
1991 return False;
1994 elem = PLGetArrayElement(value, 0);
1995 if (!elem || !PLIsString(elem)) {
1996 wwarning(_("Wrong type for workspace background. Should be Texture."));
1997 if (changed==0) {
1998 value = entry->plvalue;
1999 changed = 1;
2000 wwarning(_("using default \"%s\" instead"), entry->default_value);
2001 goto again;
2003 return False;
2005 val = PLGetString(elem);
2007 if (strcasecmp(val, "None")==0)
2008 return False;
2010 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
2011 && strcasecmp(val, "cpixmap")!=0) {
2012 texture = parse_texture(scr, value);
2014 else {
2015 /* spixmap || tpixmap || cpixmap */
2016 XColor color;
2017 char *file, cpc[30], *style = "-s";
2018 char *program = "wmsetbg";
2019 char *back;
2021 if (nelem != 3) {
2022 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
2023 if (changed==0) {
2024 value = entry->plvalue;
2025 changed = 1;
2026 wwarning(_("using default \"%s\" instead"), entry->default_value);
2027 goto again;
2029 return False;
2032 if (val[0] == 't' || val[0] == 'T')
2033 style = "-t";
2034 else if (val[0] == 'c' || val[0] == 'C')
2035 style = "-e";
2037 sprintf(cpc, "%i", wPreferences.cmap_size);
2039 /* get color */
2040 elem = PLGetArrayElement(value, 2);
2041 if (!elem || !PLIsString(elem)) {
2042 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
2043 if (changed==0) {
2044 value = entry->plvalue;
2045 changed = 1;
2046 wwarning(_("using default \"%s\" instead"), entry->default_value);
2047 goto again;
2049 return False;
2051 val = PLGetString(elem);
2053 if (!XParseColor(dpy, scr->colormap, val, &color)) {
2054 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
2055 val);
2056 if (changed==0) {
2057 value = entry->plvalue;
2058 changed = 1;
2059 wwarning(_("using default \"%s\" instead"), entry->default_value);
2060 goto again;
2062 return False;
2065 back = wstrdup(val);
2067 /* file name */
2068 elem = PLGetArrayElement(value, 1);
2069 if (!elem || !PLIsString(elem)) {
2070 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
2071 if (changed==0) {
2072 value = entry->plvalue;
2073 changed = 1;
2074 wwarning(_("using default \"%s\" instead"), entry->default_value);
2075 goto again;
2077 return False;
2080 val = PLGetString(elem);
2082 file = FindImage(wPreferences.pixmap_path, val);
2083 if (file) {
2084 if (fork()==0) {
2085 SetupEnvironment(scr);
2087 CloseDescriptors();
2089 execlp(program, program, style, "-c", cpc, "-b", back, file, NULL);
2090 wwarning(_("could not run \"%s\""), program);
2091 exit(-1);
2093 free(file);
2094 } else {
2095 wwarning(_("could not find background image \"%s\""), val);
2098 free(back);
2100 /* This is to let WindowMaker put a color in the background
2101 * until the pixmap is loaded, if the image is big and loads slow.
2102 * It assumes that the color will be set before the image is set
2103 * by the child. Is this true for very small images?
2105 texture = (WTexture*)wTextureMakeSolid(scr, &color);
2108 if (!texture) {
2109 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
2110 if (changed==0) {
2111 value = entry->plvalue;
2112 changed = 1;
2113 wwarning(_("using default \"%s\" instead"), entry->default_value);
2114 goto again;
2116 return False;
2119 if (ret)
2120 *ret = &texture;
2122 if (addr)
2123 *(WTexture**)addr = texture;
2125 return True;
2127 #endif /* !EXPERIMENTAL */
2130 static int
2131 getFont(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2132 void **ret)
2134 static WFont *font;
2135 char *val;
2137 STRINGP("Font");
2139 val = PLGetString(value);
2141 font = wLoadFont(val);
2142 if (!font) {
2143 wwarning(_("could not load any usable font"));
2144 return False;
2147 if (ret)
2148 *ret = font;
2150 if (addr) {
2151 wwarning("BUG:can't assign font value outside update function");
2154 return True;
2158 static int
2159 getColor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2160 void **ret)
2162 static unsigned long pixel;
2163 XColor color;
2164 char *val;
2165 int second_pass=0;
2167 STRINGP("Color");
2169 val = PLGetString(value);
2171 again:
2172 if (!wGetColor(scr, val, &color)) {
2173 wwarning(_("could not get color for key \"%s\""),
2174 entry->key);
2175 if (second_pass==0) {
2176 val = PLGetString(entry->plvalue);
2177 second_pass = 1;
2178 wwarning(_("using default \"%s\" instead"), val);
2179 goto again;
2181 return False;
2184 pixel = color.pixel;
2186 if (ret)
2187 *ret = &pixel;
2189 if (addr)
2190 *(unsigned long*)addr = pixel;
2192 return True;
2197 static int
2198 getKeybind(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2199 void **ret)
2201 static WShortKey shortcut;
2202 KeySym ksym;
2203 char *val;
2204 char *k;
2205 char buf[128], *b;
2208 STRINGP("Key spec");
2210 val = PLGetString(value);
2212 if (!val || strcasecmp(val, "NONE")==0) {
2213 shortcut.keycode = 0;
2214 shortcut.modifier = 0;
2215 if (ret)
2216 *ret = &shortcut;
2217 return True;
2220 strcpy(buf, val);
2222 b = (char*)buf;
2224 /* get modifiers */
2225 shortcut.modifier = 0;
2226 while ((k = strchr(b, '+'))!=NULL) {
2227 int mod;
2229 *k = 0;
2230 mod = wXModifierFromKey(b);
2231 if (mod<0) {
2232 wwarning(_("%s:invalid key modifier \"%s\""), entry->key, val);
2233 return False;
2235 shortcut.modifier |= mod;
2237 b = k+1;
2240 /* get key */
2241 ksym = XStringToKeysym(b);
2243 if (ksym==NoSymbol) {
2244 wwarning(_("%s:invalid kbd shortcut specification \"%s\""), entry->key,
2245 val);
2246 return False;
2249 shortcut.keycode = XKeysymToKeycode(dpy, ksym);
2250 if (shortcut.keycode==0) {
2251 wwarning(_("%s:invalid key in shortcut \"%s\""), entry->key, val);
2252 return False;
2255 if (ret)
2256 *ret = &shortcut;
2258 return True;
2262 static int
2263 getModMask(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2264 void **ret)
2266 unsigned int mask;
2267 char *str;
2269 STRINGP("Modifier Key");
2271 str = PLGetString(value);
2272 if (!str)
2273 return False;
2275 mask = wXModifierFromKey(str);
2276 if (mask < 0) {
2277 wwarning(_("%s: modifier key %s is not valid"), entry->key, str);
2278 mask = 0;
2279 return False;
2282 if (addr)
2283 *(unsigned int*)addr = mask;
2285 if (ret)
2286 *ret = &mask;
2288 return True;
2293 /* ---------------- value setting functions --------------- */
2294 static int
2295 setJustify(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2297 return REFRESH_FORE_COLOR;
2301 static int
2302 setIfDockPresent(WScreen *scr, WDefaultEntry *entry, int *flag, long which)
2304 switch (which) {
2305 case WM_DOCK:
2306 wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
2307 break;
2308 case WM_CLIP:
2309 wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
2310 break;
2311 default:
2312 break;
2314 return 0;
2318 static int
2319 setStickyIcons(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
2321 if (scr->workspaces) {
2322 wWorkspaceForceChange(scr, scr->current_workspace);
2323 wArrangeIcons(scr, False);
2325 return 0;
2328 #if not_used
2329 static int
2330 setPositive(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
2332 if (*value <= 0)
2333 *(int*)foo = 1;
2335 return 0;
2337 #endif
2341 static int
2342 setIconTile(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2344 Pixmap pixmap;
2345 RImage *img;
2346 int reset = 0;
2348 img = wTextureRenderImage(*texture, wPreferences.icon_size,
2349 wPreferences.icon_size,
2350 ((*texture)->any.type & WREL_BORDER_MASK)
2351 ? WREL_ICON : WREL_FLAT);
2352 if (!img) {
2353 wwarning(_("could not render texture for icon background"));
2354 if (!entry->addr)
2355 wTextureDestroy(scr, *texture);
2356 return 0;
2358 RConvertImage(scr->rcontext, img, &pixmap);
2360 if (scr->icon_tile) {
2361 reset = 1;
2362 RDestroyImage(scr->icon_tile);
2363 XFreePixmap(dpy, scr->icon_tile_pixmap);
2366 scr->icon_tile = img;
2368 if (!wPreferences.flags.noclip) {
2369 if (scr->clip_tile) {
2370 RDestroyImage(scr->clip_tile);
2372 scr->clip_tile = wClipMakeTile(scr, img);
2375 scr->icon_tile_pixmap = pixmap;
2377 if (scr->def_icon_pixmap) {
2378 XFreePixmap(dpy, scr->def_icon_pixmap);
2379 scr->def_icon_pixmap = None;
2381 if (scr->def_ticon_pixmap) {
2382 XFreePixmap(dpy, scr->def_ticon_pixmap);
2383 scr->def_ticon_pixmap = None;
2386 if (scr->icon_back_texture) {
2387 wTextureDestroy(scr, (WTexture*)scr->icon_back_texture);
2389 scr->icon_back_texture = wTextureMakeSolid(scr, &((*texture)->any.color));
2391 if (scr->clip_balloon)
2392 XSetWindowBackground(dpy, scr->clip_balloon,
2393 (*texture)->any.color.pixel);
2396 * Free the texture as nobody else will use it, nor refer to it.
2398 if (!entry->addr)
2399 wTextureDestroy(scr, *texture);
2401 return (reset ? REFRESH_ICON_TILE : 0);
2406 static int
2407 setWinTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2409 if (scr->title_font) {
2410 wFreeFont(scr->title_font);
2413 scr->title_font = font;
2415 #ifndef I18N_MB
2416 XSetFont(dpy, scr->window_title_gc, font->font->fid);
2417 #endif
2419 return REFRESH_WINDOW_FONT;
2423 static int
2424 setMenuTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2426 if (scr->menu_title_font) {
2427 wFreeFont(scr->menu_title_font);
2430 scr->menu_title_font = font;
2432 #ifndef I18N_MB
2433 XSetFont(dpy, scr->menu_title_gc, font->font->fid);
2434 #endif
2436 return REFRESH_MENU_TITLE_FONT;
2440 static int
2441 setMenuTextFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2443 if (scr->menu_entry_font) {
2444 wFreeFont(scr->menu_entry_font);
2447 scr->menu_entry_font = font;
2449 #ifndef I18N_MB
2450 XSetFont(dpy, scr->menu_entry_gc, font->font->fid);
2451 XSetFont(dpy, scr->disabled_menu_entry_gc, font->font->fid);
2452 XSetFont(dpy, scr->select_menu_gc, font->font->fid);
2453 #endif
2455 return REFRESH_MENU_FONT;
2460 static int
2461 setIconTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2463 if (scr->icon_title_font) {
2464 wFreeFont(scr->icon_title_font);
2467 scr->icon_title_font = font;
2469 #ifndef I18N_MB
2470 XSetFont(dpy, scr->icon_title_gc, font->font->fid);
2471 #endif
2473 return REFRESH_ICON_FONT;
2477 static int
2478 setClipTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2480 if (scr->clip_title_font) {
2481 wFreeFont(scr->clip_title_font);
2484 scr->clip_title_font = font;
2486 #ifndef I18N_MB
2487 XSetFont(dpy, scr->clip_title_gc, font->font->fid);
2488 #endif
2490 return REFRESH_ICON_FONT;
2494 static int
2495 setDisplayFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2497 if (scr->info_text_font) {
2498 wFreeFont(scr->info_text_font);
2501 scr->info_text_font = font;
2503 #ifndef I18N_MB
2504 XSetFont(dpy, scr->info_text_gc, font->font->fid);
2505 XSetFont(dpy, scr->line_gc, font->font->fid);
2506 #endif
2508 /* This test works because the scr structure is initially zeroed out
2509 and None = 0. Any other time, the window should be valid. */
2510 if (scr->geometry_display != None) {
2511 wGetGeometryWindowSize(scr, &scr->geometry_display_width,
2512 &scr->geometry_display_height);
2513 XResizeWindow(dpy, scr->geometry_display,
2514 scr->geometry_display_width, scr->geometry_display_height);
2517 return 0;
2521 static int
2522 setHightlight(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2524 if (scr->select_pixel!=scr->white_pixel &&
2525 scr->select_pixel!=scr->black_pixel) {
2526 wFreeColor(scr, scr->select_pixel);
2529 scr->select_pixel = color->pixel;
2531 return REFRESH_FORE_COLOR;
2535 static int
2536 setHightlightText(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2538 if (scr->select_text_pixel!=scr->white_pixel &&
2539 scr->select_text_pixel!=scr->black_pixel) {
2540 wFreeColor(scr, scr->select_text_pixel);
2543 scr->select_text_pixel = color->pixel;
2545 return REFRESH_FORE_COLOR;
2549 static int
2550 setClipTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2552 if (scr->clip_title_pixel[index]!=scr->white_pixel &&
2553 scr->clip_title_pixel[index]!=scr->black_pixel) {
2554 wFreeColor(scr, scr->clip_title_pixel[index]);
2557 scr->clip_title_pixel[index] = color->pixel;
2559 return REFRESH_FORE_COLOR;
2563 static int
2564 setWTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2566 if (scr->window_title_pixel[index]!=scr->white_pixel &&
2567 scr->window_title_pixel[index]!=scr->black_pixel) {
2568 wFreeColor(scr, scr->window_title_pixel[index]);
2571 scr->window_title_pixel[index] = color->pixel;
2573 if (index == WS_FOCUSED)
2574 XSetForeground(dpy, scr->icon_title_gc, color->pixel);
2575 else if (index == WS_UNFOCUSED)
2576 XSetForeground(dpy, scr->info_text_gc, color->pixel);
2578 return REFRESH_FORE_COLOR;
2582 static int
2583 setMenuTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2585 if (scr->menu_title_pixel[0]!=scr->white_pixel &&
2586 scr->menu_title_pixel[0]!=scr->black_pixel) {
2587 wFreeColor(scr, scr->menu_title_pixel[0]);
2590 scr->menu_title_pixel[0] = color->pixel;
2592 XSetForeground(dpy, scr->menu_title_gc, color->pixel);
2594 return REFRESH_FORE_COLOR;
2598 static int
2599 setMenuTextColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2601 XGCValues gcv;
2602 #define gcm (GCForeground|GCBackground|GCFillStyle)
2604 if (scr->mtext_pixel!=scr->white_pixel &&
2605 scr->mtext_pixel!=scr->black_pixel) {
2606 wFreeColor(scr, scr->mtext_pixel);
2609 scr->mtext_pixel = color->pixel;
2611 XSetForeground(dpy, scr->menu_entry_gc, color->pixel);
2614 if (scr->dtext_pixel == scr->mtext_pixel) {
2615 gcv.foreground = scr->white_pixel;
2616 gcv.background = scr->black_pixel;
2617 gcv.fill_style = FillStippled;
2618 } else {
2619 gcv.foreground = scr->dtext_pixel;
2620 gcv.fill_style = FillSolid;
2622 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2624 return REFRESH_FORE_COLOR;
2625 #undef gcm
2629 static int
2630 setMenuDisabledColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2632 XGCValues gcv;
2633 #define gcm (GCForeground|GCBackground|GCFillStyle)
2635 if (scr->dtext_pixel!=scr->white_pixel &&
2636 scr->dtext_pixel!=scr->black_pixel) {
2637 wFreeColor(scr, scr->dtext_pixel);
2640 scr->dtext_pixel = color->pixel;
2642 if (scr->dtext_pixel == scr->mtext_pixel) {
2643 gcv.foreground = scr->white_pixel;
2644 gcv.background = scr->black_pixel;
2645 gcv.fill_style = FillStippled;
2646 } else {
2647 gcv.foreground = scr->dtext_pixel;
2648 gcv.fill_style = FillSolid;
2650 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2652 return REFRESH_FORE_COLOR;
2653 #undef gcm
2659 * Implementation of workspace specific backgrounds.
2661 * WorkspaceBack is used as the default background.
2662 * WorkspaceSpecificBack supplies an array with the textures for
2663 * other workspaces.
2664 * WorkspaceSpecificBack = (ws1texture, ws2texture, "", ws4texture);
2665 * "" means that workspace3 should use the default texture.
2667 * struct WWorkspaceTexture {
2668 * Pixmap pixmap; // the pixmap for non-solid textures.
2669 * //None means the texture is solid
2670 * WPixel color; // color for solid texture
2671 * proplist_t texture; // for checking updates
2672 * };
2675 * All textures are rendered by wmsetbg. When it exits with status 0
2676 * it outputs the pixmap ID.
2677 * wmaker will monitor the fd and when it becomes available it reads the
2678 * pixmap ID and uses it in the texture. The data read from the fd
2679 * is the pixmap ID and the pid of the wmsetbg process, separated by
2680 * a space (the pid is to allow paralel wmsetbg processes).
2682 * The workspace background cant be set if the pid field of the
2683 * texture is 0. Otherwise, the texture is still being rendered
2684 * and cant be set.
2686 * If the workspace background is changed before wmsetbg finishes
2687 * the rendering, wmsetbg must be killed.
2689 * Optimizations:
2690 * Workspace specific textures are generated only when switching to
2691 * that workspace, unless #define SLOW_CONFIGURATION_UPDATE.
2693 * -readme
2695 #ifdef EXPERIMENTAL
2696 static void
2697 trackDeadProcess(pid_t pid, unsigned char status, WScreen *scr)
2699 WWorkspaceTexture *wsback;
2700 int setBackground = 0;
2702 /* find out to which wsback, this process belongs to */
2704 wsback->pid = 0;
2705 if (status != 123) {
2706 /* something went wrong during rendering */
2707 XFreePixmap(dpy, wsback->pixmap);
2708 wsback->pixmap = None;
2709 wwarning(_("background texture rendering was unsuccessfull"));
2712 if (setBackground) {
2716 WWorkspaceTexture*
2717 makeWorkspaceTexture(WScreen *scr, WTexture *texture, char *file, char *option)
2719 WWorkspaceTexture *wsback;
2721 wsback = wmalloc(sizeof(WWorkspaceTexture));
2722 wsback->pid = 0;
2724 wsback->solid = (*texture)->any.color.pixel;
2726 if (texture->any.type==WTEX_SOLID) {
2727 wsback->pixmap = None;
2728 } else if (texture->any.type == WTEX_PIXMAP) {
2729 Pixmap pixmap;
2730 if (texture->pixmap.subtype == WTP_TILE) {
2731 RImage *image;
2733 /* render ourseves */
2734 image = RLoadImage(scr->rcontext, file, 0);
2735 if (!image) {
2736 wwarning(_("could not load image %s for option %s:%s\n"),
2737 file, option, RErrorString);
2738 wsback->pixmap = None;
2739 } else {
2741 } else {
2742 /* create a empty pixmap... */
2743 pid_t pid;
2744 int style = texture->pixmap.subtype;
2746 pixmap = XCreatePixmap(dpy, scr->root_win, scr->scr_width,
2747 scr->scr_height, scr->depth);
2749 /* ...and let wmsetbg render it */
2750 pid = fork();
2751 if (pid < 0) {
2752 wsyserror(_("could not spawn texture rendering subprocess for option"));
2753 } else if (pid == 0) {
2754 char *colorn, *pix;
2756 SetupEnvironment(scr);
2758 CloseDescriptors();
2760 colorn = wmalloc(32);
2761 sprintf(colorn, "\"#%2x%2x%2x\"",
2762 texture->any.color.red,
2763 texture->any.color.green,
2764 texture->any.color.blue);
2765 pix = wmalloc(32);
2766 sprintf(pix, "%x", pixmap);
2767 execlp("wmsetbg", "wmsetbg", (style==WTP_SCALE ? "-s":"-e"),
2768 "-b", colorn, "-x", pix, file);
2769 exit(1);
2771 wsback->pixmap = pixmap;
2772 /* must add a death handler to detect when wmsetbg has
2773 * exited (with exit status 123) and refresh the background.
2775 wsback->pid = pid;
2777 } else {
2778 int w, h;
2779 Pixmap pixmap;
2781 switch (texture->any.type) {
2782 case WTEX_HGRADIENT:
2783 case WTEX_MHGRADIENT:
2784 w = scr->scr_width;
2785 h = 8;
2786 break;
2788 case WTEX_VGRADIENT:
2789 case WTEX_MVGRADIENT:
2790 w = 8;
2791 h = scr->scr_height;
2792 break;
2794 case WTEX_DGRADIENT:
2795 case WTEX_MDGRADIENT:
2796 w = scr->scr_width;
2797 h = scr->scr_height;
2798 break;
2800 default:
2801 return NULL;
2804 img = wTextureRenderImage(texture, w, h, WREL_FLAT);
2805 if (!img) {
2806 wwarning(_("could not render texture for workspace background"));
2807 free(wsback);
2808 return NULL;
2810 RConvertImage(scr->rcontext, img, &pixmap);
2811 RDestroyImage(img);
2812 wsback->pixmap = pixmap;
2815 return wsback;
2819 static int
2820 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
2821 char *file)
2823 Pixmap pixmap;
2824 RImage *img;
2826 if (scr->defaultTexture) {
2827 if (scr->defaultTexture->pixmap)
2828 XFreePixmap(dpy, scr->defaultTexture->pixmap);
2829 free(scr->defaultTexture);
2832 if (!*texture) {
2833 scr->defaultTexture = NULL;
2834 if (file)
2835 free(file);
2836 return 0;
2839 scr->defaultTexture = makeWorkspaceTexture(scr, *texture, file);
2841 if (!entry->addr)
2842 wTextureDestroy(scr, *texture);
2844 /* free the file name that was passed from the getWSBackground()
2845 * function and placed in entry->extra_data */
2846 if (file)
2847 free(file);
2848 entry->extra_data = NULL;
2850 return REFRESH_WORKSPACE_BACK;
2852 #else /* !EXPERIMENTAL */
2853 static int
2854 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
2855 void *foo)
2857 Pixmap pixmap;
2858 RImage *img;
2861 if ((*texture)->any.type==WTEX_SOLID) {
2862 XSetWindowBackground(dpy, scr->root_win, (*texture)->solid.normal.pixel);
2863 XClearWindow(dpy, scr->root_win);
2864 } else {
2865 int w, h;
2867 switch ((*texture)->any.type) {
2868 case WTEX_HGRADIENT:
2869 case WTEX_MHGRADIENT:
2870 w = scr->scr_width;
2871 h = 8;
2872 break;
2874 case WTEX_VGRADIENT:
2875 case WTEX_MVGRADIENT:
2876 w = 8;
2877 h = scr->scr_height;
2878 break;
2880 case WTEX_DGRADIENT:
2881 case WTEX_MDGRADIENT:
2882 w = scr->scr_width;
2883 h = scr->scr_height;
2884 break;
2886 default:
2887 if (!entry->addr)
2888 wTextureDestroy(scr, *texture);
2889 return 0;
2892 img = wTextureRenderImage(*texture, w, h, WREL_FLAT);
2893 if (!img) {
2894 wwarning(_("could not render texture for workspace background"));
2895 if (!entry->addr)
2896 wTextureDestroy(scr, *texture);
2897 return 0;
2899 RConvertImage(scr->rcontext, img, &pixmap);
2900 RDestroyImage(img);
2901 XSetWindowBackgroundPixmap(dpy, scr->root_win, pixmap);
2902 XClearWindow(dpy, scr->root_win);
2906 * Free the texture as nobody else will use it, nor refer to it.
2908 if (!entry->addr)
2909 wTextureDestroy(scr, *texture);
2911 return 0;
2913 #endif /* !EXPERIMENTAL */
2915 static int
2916 setWidgetColor(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2918 if (scr->widget_texture) {
2919 wTextureDestroy(scr, (WTexture*)scr->widget_texture);
2921 scr->widget_texture = *(WTexSolid**)texture;
2923 return 0;
2927 static int
2928 setFTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2930 if (scr->window_title_texture[WS_FOCUSED]) {
2931 wTextureDestroy(scr, scr->window_title_texture[WS_FOCUSED]);
2933 scr->window_title_texture[WS_FOCUSED] = *texture;
2935 if (scr->icon_title_texture) {
2936 wTextureDestroy(scr, (WTexture*)scr->icon_title_texture);
2938 scr->icon_title_texture
2939 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_FOCUSED]->any.color);
2941 return REFRESH_WINDOW_TEXTURES;
2945 static int
2946 setPTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2948 if (scr->window_title_texture[WS_PFOCUSED]) {
2949 wTextureDestroy(scr, scr->window_title_texture[WS_PFOCUSED]);
2951 scr->window_title_texture[WS_PFOCUSED] = *texture;
2953 return REFRESH_WINDOW_TEXTURES;
2957 static int
2958 setUTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2960 if (scr->window_title_texture[WS_UNFOCUSED]) {
2961 wTextureDestroy(scr, scr->window_title_texture[WS_UNFOCUSED]);
2963 scr->window_title_texture[WS_UNFOCUSED] = *texture;
2965 if (scr->resizebar_texture[0]) {
2966 wTextureDestroy(scr, (WTexture*)scr->resizebar_texture[0]);
2968 scr->resizebar_texture[0]
2969 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_UNFOCUSED]->any.color);
2971 if (scr->geometry_display != None)
2972 XSetWindowBackground(dpy, scr->geometry_display,
2973 scr->resizebar_texture[0]->normal.pixel);
2975 return REFRESH_WINDOW_TEXTURES;
2979 static int
2980 setMenuTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2982 if (scr->menu_title_texture[0]) {
2983 wTextureDestroy(scr, scr->menu_title_texture[0]);
2985 scr->menu_title_texture[0] = *texture;
2987 return REFRESH_MENU_TEXTURES;
2991 static int
2992 setMenuTextBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2994 if (scr->menu_item_texture) {
2995 wTextureDestroy(scr, scr->menu_item_texture);
2996 wTextureDestroy(scr, (WTexture*)scr->menu_item_auxtexture);
2998 scr->menu_item_texture = *texture;
3000 scr->menu_item_auxtexture
3001 = wTextureMakeSolid(scr, &scr->menu_item_texture->any.color);
3003 return REFRESH_MENU_TEXTURES;
3007 static int
3008 setKeyGrab(WScreen *scr, WDefaultEntry *entry, WShortKey *shortcut, long index)
3010 WWindow *wwin;
3011 wKeyBindings[index] = *shortcut;
3013 wwin = scr->focused_window;
3015 while (wwin!=NULL) {
3016 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
3018 if (!wwin->window_flags.no_bind_keys) {
3019 wWindowSetKeyGrabs(wwin);
3021 wwin = wwin->prev;
3024 return 0;
3028 static int
3029 setIconPosition(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
3031 wArrangeIcons(scr, True);
3033 return 0;
3039 * Very ugly kluge.
3040 * Need access to the double click variables, so that all widgets in
3041 * wmaker panels will have the same dbl-click values.
3042 * TODO: figure a better way of dealing with it.
3044 #include "WINGsP.h"
3046 static int
3047 setDoubleClick(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
3049 extern _WINGsConfiguration WINGsConfiguration;
3051 if (*value <= 0)
3052 *(int*)foo = 1;
3054 WINGsConfiguration.doubleClickDelay = *value;
3056 return 0;