Updating to version 0.20.2
[wmaker-crm.git] / src / defaults.c
blob12c41047482b9fb5dd4978ed6279e47d66a3dcc2
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
395 {"NoWindowUnderDock", "NO", NULL,
396 &wPreferences.no_window_under_dock, getBool, NULL
399 {"NoWindowOverIcons", "NO", NULL,
400 &wPreferences.no_window_over_icons, getBool, NULL
402 {"WindowPlaceOrigin", "(0, 0)", NULL,
403 &wPreferences.window_place_origin, getCoord, NULL
405 {"ResizeDisplay", "corner", seGeomDisplays,
406 &wPreferences.size_display, getEnum, NULL
408 {"MoveDisplay", "corner", seGeomDisplays,
409 &wPreferences.move_display, getEnum, NULL
411 {"DontConfirmKill", "NO", NULL,
412 &wPreferences.dont_confirm_kill, getBool,NULL
414 {"WindowTitleBalloons", "NO", NULL,
415 &wPreferences.window_balloon, getBool, NULL
417 {"MiniwindowTitleBalloons", "NO", NULL,
418 &wPreferences.miniwin_balloon,getBool, NULL
420 {"AppIconBalloons", "NO", NULL,
421 &wPreferences.appicon_balloon,getBool, NULL
423 {"DisableBlinking", "NO", NULL,
424 &wPreferences.dont_blink, getBool, NULL
426 /* style options */
427 {"WidgetColor", "(solid, gray)", NULL,
428 NULL, getTexture, setWidgetColor,
430 {"WorkspaceBack", "(solid, black)", NULL,
431 NULL, getWSBackground,setWorkspaceBack
433 {"IconBack", "(solid, gray)", NULL,
434 NULL, getTexture, setIconTile
436 {"TitleJustify", "center", seJustifications,
437 &wPreferences.title_justification, getEnum, setJustify
439 {"WindowTitleFont", DEF_TITLE_FONT, NULL,
440 NULL, getFont, setWinTitleFont
442 {"MenuTitleFont", DEF_MENU_TITLE_FONT, NULL,
443 NULL, getFont, setMenuTitleFont
445 {"MenuTextFont", DEF_MENU_ENTRY_FONT, NULL,
446 NULL, getFont, setMenuTextFont
448 {"IconTitleFont", DEF_ICON_TITLE_FONT, NULL,
449 NULL, getFont, setIconTitleFont
451 {"ClipTitleFont", DEF_CLIP_TITLE_FONT, NULL,
452 NULL, getFont, setClipTitleFont
454 {"DisplayFont", DEF_INFO_TEXT_FONT, NULL,
455 NULL, getFont, setDisplayFont
457 {"HighlightColor", "white", NULL,
458 NULL, getColor, setHightlight
460 {"HighlightTextColor", "black", NULL,
461 NULL, getColor, setHightlightText
463 {"ClipTitleColor", "black", (void*)CLIP_NORMAL,
464 NULL, getColor, setClipTitleColor
466 {"CClipTitleColor", "\"#454045\"", (void*)CLIP_COLLAPSED,
467 NULL, getColor, setClipTitleColor
469 {"FTitleColor", "white", (void*)WS_FOCUSED,
470 NULL, getColor, setWTitleColor
472 {"PTitleColor", "white", (void*)WS_PFOCUSED,
473 NULL, getColor, setWTitleColor
475 {"UTitleColor", "black", (void*)WS_UNFOCUSED,
476 NULL, getColor, setWTitleColor
478 {"FTitleBack", "(solid, black)", NULL,
479 NULL, getTexture, setFTitleBack
481 {"PTitleBack", "(solid, \"#616161\")", NULL,
482 NULL, getTexture, setPTitleBack
484 {"UTitleBack", "(solid, gray)", NULL,
485 NULL, getTexture, setUTitleBack
487 {"MenuTitleColor", "white", NULL,
488 NULL, getColor, setMenuTitleColor
490 {"MenuTextColor", "black", NULL,
491 NULL, getColor, setMenuTextColor
493 {"MenuDisabledColor", "\"#616161\"", NULL,
494 NULL, getColor, setMenuDisabledColor
496 {"MenuTitleBack", "(solid, black)", NULL,
497 NULL, getTexture, setMenuTitleBack
499 {"MenuTextBack", "(solid, gray)", NULL,
500 NULL, getTexture, setMenuTextBack
503 /* keybindings */
504 {"RootMenuKey", "None", (void*)WKBD_ROOTMENU,
505 NULL, getKeybind, setKeyGrab
507 {"WindowListKey", "None", (void*)WKBD_WINDOWLIST,
508 NULL, getKeybind, setKeyGrab
510 {"WindowMenuKey", "None", (void*)WKBD_WINDOWMENU,
511 NULL, getKeybind, setKeyGrab
513 {"ClipLowerKey", "None", (void*)WKBD_CLIPLOWER,
514 NULL, getKeybind, setKeyGrab
516 {"ClipRaiseKey", "None", (void*)WKBD_CLIPRAISE,
517 NULL, getKeybind, setKeyGrab
519 {"ClipRaiseLowerKey", "None", (void*)WKBD_CLIPRAISELOWER,
520 NULL, getKeybind, setKeyGrab
522 {"MiniaturizeKey", "None", (void*)WKBD_MINIATURIZE,
523 NULL, getKeybind, setKeyGrab
525 {"HideKey", "None", (void*)WKBD_HIDE,
526 NULL, getKeybind, setKeyGrab
528 {"CloseKey", "None", (void*)WKBD_CLOSE,
529 NULL, getKeybind, setKeyGrab
531 {"MaximizeKey", "None", (void*)WKBD_MAXIMIZE,
532 NULL, getKeybind, setKeyGrab
534 {"VMaximizeKey", "None", (void*)WKBD_VMAXIMIZE,
535 NULL, getKeybind, setKeyGrab
537 {"RaiseKey", "Meta+Up", (void*)WKBD_RAISE,
538 NULL, getKeybind, setKeyGrab
540 {"LowerKey", "Meta+Down", (void*)WKBD_LOWER,
541 NULL, getKeybind, setKeyGrab
543 {"RaiseLowerKey", "None", (void*)WKBD_RAISELOWER,
544 NULL, getKeybind, setKeyGrab
546 {"ShadeKey", "None", (void*)WKBD_SHADE,
547 NULL, getKeybind, setKeyGrab
549 {"SelectKey", "None", (void*)WKBD_SELECT,
550 NULL, getKeybind, setKeyGrab
552 {"FocusNextKey", "None", (void*)WKBD_FOCUSNEXT,
553 NULL, getKeybind, setKeyGrab
555 {"FocusPrevKey", "None", (void*)WKBD_FOCUSPREV,
556 NULL, getKeybind, setKeyGrab
558 {"NextWorkspaceKey", "None", (void*)WKBD_NEXTWORKSPACE,
559 NULL, getKeybind, setKeyGrab
561 {"PrevWorkspaceKey", "None", (void*)WKBD_PREVWORKSPACE,
562 NULL, getKeybind, setKeyGrab
564 {"NextWorkspaceLayerKey", "None", (void*)WKBD_NEXTWSLAYER,
565 NULL, getKeybind, setKeyGrab
567 {"PrevWorkspaceLayerKey", "None", (void*)WKBD_PREVWSLAYER,
568 NULL, getKeybind, setKeyGrab
570 {"Workspace1Key", "None", (void*)WKBD_WORKSPACE1,
571 NULL, getKeybind, setKeyGrab
573 {"Workspace2Key", "None", (void*)WKBD_WORKSPACE2,
574 NULL, getKeybind, setKeyGrab
576 {"Workspace3Key", "None", (void*)WKBD_WORKSPACE3,
577 NULL, getKeybind, setKeyGrab
579 {"Workspace4Key", "None", (void*)WKBD_WORKSPACE4,
580 NULL, getKeybind, setKeyGrab
582 {"Workspace5Key", "None", (void*)WKBD_WORKSPACE5,
583 NULL, getKeybind, setKeyGrab
585 {"Workspace6Key", "None", (void*)WKBD_WORKSPACE6,
586 NULL, getKeybind, setKeyGrab
588 {"Workspace7Key", "None", (void*)WKBD_WORKSPACE7,
589 NULL, getKeybind, setKeyGrab
591 {"Workspace8Key", "None", (void*)WKBD_WORKSPACE8,
592 NULL, getKeybind, setKeyGrab
594 {"Workspace9Key", "None", (void*)WKBD_WORKSPACE9,
595 NULL, getKeybind, setKeyGrab
597 {"Workspace10Key", "None", (void*)WKBD_WORKSPACE10,
598 NULL, getKeybind, setKeyGrab
603 #if 0
604 static void rereadDefaults(void);
605 #endif
607 #if 0
608 static void
609 rereadDefaults(void)
611 /* must defer the update because accessing X data from a
612 * signal handler can mess up Xlib */
615 #endif
617 static void
618 initDefaults()
620 int i;
621 WDefaultEntry *entry;
623 PLSetStringCmpHook(StringCompareHook);
625 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
626 entry = &optionList[i];
628 entry->plkey = PLMakeString(entry->key);
629 if (entry->default_value)
630 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
631 else
632 entry->plvalue = NULL;
635 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
636 entry = &staticOptionList[i];
638 entry->plkey = PLMakeString(entry->key);
639 if (entry->default_value)
640 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
641 else
642 entry->plvalue = NULL;
646 wDomainName = PLMakeString(WMDOMAIN_NAME);
647 wAttributeDomainName = PLMakeString(WMATTRIBUTE_DOMAIN_NAME);
649 PLRegister(wDomainName, rereadDefaults);
650 PLRegister(wAttributeDomainName, rereadDefaults);
657 #if 0
658 proplist_t
659 wDefaultsInit(int screen_number)
661 static int defaults_inited = 0;
662 proplist_t dict;
664 if (!defaults_inited) {
665 initDefaults();
668 dict = PLGetDomain(wDomainName);
669 if (!dict) {
670 wwarning(_("could not read domain \"%s\" from defaults database"),
671 PLGetString(wDomainName));
674 return dict;
676 #endif
679 void
680 wDefaultsDestroyDomain(WDDomain *domain)
682 if (domain->dictionary)
683 PLRelease(domain->dictionary);
684 free(domain->path);
685 free(domain);
689 WDDomain*
690 wDefaultsInitDomain(char *domain, Bool requireDictionary)
692 WDDomain *db;
693 struct stat stbuf;
694 static int inited = 0;
695 char path[PATH_MAX];
696 char *the_path;
697 proplist_t shared_dict=NULL;
699 if (!inited) {
700 inited = 1;
701 initDefaults();
704 db = wmalloc(sizeof(WDDomain));
705 memset(db, 0, sizeof(WDDomain));
706 db->domain_name = domain;
707 db->path = wdefaultspathfordomain(domain);
708 the_path = db->path;
710 if (the_path && stat(the_path, &stbuf)>=0) {
711 db->dictionary = ReadProplistFromFile(the_path);
712 if (db->dictionary) {
713 if (requireDictionary && !PLIsDictionary(db->dictionary)) {
714 PLRelease(db->dictionary);
715 db->dictionary = NULL;
716 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
717 domain, the_path);
719 db->timestamp = stbuf.st_mtime;
720 } else {
721 wwarning(_("could not load domain %s from user defaults database"),
722 domain);
726 /* global system dictionary */
727 sprintf(path, "%s/%s/%s", PKGDATADIR, DEFAULTS_DIR, domain);
728 if (stat(path, &stbuf)>=0) {
729 shared_dict = ReadProplistFromFile(path);
730 if (shared_dict) {
731 if (requireDictionary && !PLIsDictionary(shared_dict)) {
732 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
733 domain, path);
734 PLRelease(shared_dict);
735 shared_dict = NULL;
736 } else {
737 if (db->dictionary && PLIsDictionary(shared_dict) &&
738 PLIsDictionary(db->dictionary)) {
739 PLMergeDictionaries(shared_dict, db->dictionary);
740 PLRelease(db->dictionary);
741 db->dictionary = shared_dict;
742 if (stbuf.st_mtime > db->timestamp)
743 db->timestamp = stbuf.st_mtime;
744 } else if (!db->dictionary) {
745 db->dictionary = shared_dict;
746 if (stbuf.st_mtime > db->timestamp)
747 db->timestamp = stbuf.st_mtime;
750 } else {
751 wwarning(_("could not load domain %s from global defaults database"),
752 domain);
756 /* set to save it in user's directory, no matter from where it was read */
757 if (db->dictionary) {
758 proplist_t tmp = PLMakeString(db->path);
760 PLSetFilename(db->dictionary, tmp);
761 PLRelease(tmp);
764 return db;
768 void
769 wReadStaticDefaults(proplist_t dict)
771 proplist_t plvalue;
772 WDefaultEntry *entry;
773 int i;
774 void *tdata;
777 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
778 entry = &staticOptionList[i];
780 if (dict)
781 plvalue = PLGetDictionaryEntry(dict, entry->plkey);
782 else
783 plvalue = NULL;
785 if (!plvalue) {
786 /* no default in the DB. Use builtin default */
787 plvalue = entry->plvalue;
790 if (plvalue) {
791 /* convert data */
792 (*entry->convert)(NULL, entry, plvalue, entry->addr, &tdata);
793 if (entry->update) {
794 (*entry->update)(NULL, entry, tdata, entry->extra_data);
800 void
801 wDefaultsCheckDomains(void *foo)
803 WScreen *scr;
804 struct stat stbuf;
805 proplist_t dict;
806 int i;
807 char path[PATH_MAX];
809 #ifdef HEARTBEAT
810 puts("Checking domains...");
811 #endif
812 if (stat(WDWindowMaker->path, &stbuf)>=0
813 && WDWindowMaker->timestamp < stbuf.st_mtime) {
814 proplist_t shared_dict = NULL;
815 #ifdef HEARTBEAT
816 puts("Checking WindowMaker domain");
817 #endif
818 WDWindowMaker->timestamp = stbuf.st_mtime;
820 /* global dictionary */
821 sprintf(path, "%s/%s/WindowMaker", PKGDATADIR, DEFAULTS_DIR);
822 if (stat(path, &stbuf)>=0) {
823 shared_dict = ReadProplistFromFile(path);
824 if (shared_dict && !PLIsDictionary(shared_dict)) {
825 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
826 "WindowMaker", path);
827 PLRelease(shared_dict);
828 shared_dict = NULL;
829 } else if (!shared_dict) {
830 wwarning(_("could not load domain %s from global defaults database"),
831 "WindowMaker");
834 /* user dictionary */
835 dict = ReadProplistFromFile(WDWindowMaker->path);
836 if (dict) {
837 if (!PLIsDictionary(dict)) {
838 PLRelease(dict);
839 dict = NULL;
840 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
841 "WindowMaker", WDWindowMaker->path);
842 } else {
843 if (shared_dict) {
844 PLSetFilename(shared_dict, PLGetFilename(dict));
845 PLMergeDictionaries(shared_dict, dict);
846 PLRelease(dict);
847 dict = shared_dict;
848 shared_dict = NULL;
850 for (i=0; i<wScreenCount; i++) {
851 scr = wScreenWithNumber(i);
852 if (scr)
853 wReadDefaults(scr, dict);
855 if (WDWindowMaker->dictionary) {
856 PLRelease(WDWindowMaker->dictionary);
858 WDWindowMaker->dictionary = dict;
860 } else {
861 wwarning(_("could not load domain %s from user defaults database"),
862 "WindowMaker");
864 if (shared_dict) {
865 PLRelease(shared_dict);
869 if (stat(WDWindowAttributes->path, &stbuf)>=0
870 && WDWindowAttributes->timestamp < stbuf.st_mtime) {
871 #ifdef HEARTBEAT
872 puts("Checking WMWindowAttributes domain");
873 #endif
874 dict = ReadProplistFromFile(WDWindowAttributes->path);
875 if (dict) {
876 if (!PLIsDictionary(dict)) {
877 PLRelease(dict);
878 dict = NULL;
879 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
880 "WMWindowAttributes", WDWindowAttributes->path);
881 } else {
882 if (WDWindowAttributes->dictionary)
883 PLRelease(WDWindowAttributes->dictionary);
884 WDWindowAttributes->dictionary = dict;
885 for (i=0; i<wScreenCount; i++) {
886 scr = wScreenWithNumber(i);
887 if (scr)
888 wDefaultUpdateIcons(scr);
891 } else {
892 wwarning(_("could not load domain %s from user defaults database"),
893 "WMWindowAttributes");
895 WDWindowAttributes->timestamp = stbuf.st_mtime;
899 if (stat(WDRootMenu->path, &stbuf)>=0
900 && WDRootMenu->timestamp < stbuf.st_mtime) {
901 dict = ReadProplistFromFile(WDRootMenu->path);
902 #ifdef HEARTBEAT
903 puts("Checking WMRootMenu domain");
904 #endif
905 if (dict) {
906 if (!PLIsArray(dict) && !PLIsString(dict)) {
907 PLRelease(dict);
908 dict = NULL;
909 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
910 "WMRootMenu", WDRootMenu->path);
911 } else {
912 if (WDRootMenu->dictionary) {
913 PLRelease(WDRootMenu->dictionary);
915 WDRootMenu->dictionary = dict;
917 } else {
918 wwarning(_("could not load domain %s from user defaults database"),
919 "WMRootMenu");
921 WDRootMenu->timestamp = stbuf.st_mtime;
924 WMAddTimerHandler(DEFAULTS_CHECK_INTERVAL, wDefaultsCheckDomains, foo);
929 #define REFRESH_WINDOW_TEXTURES (1<<0)
930 #define REFRESH_MENU_TEXTURES (1<<1)
931 #define REFRESH_WINDOW_FONT (1<<2)
932 #define REFRESH_MENU_TITLE_FONT (1<<3)
933 #define REFRESH_MENU_FONT (1<<4)
934 #define REFRESH_FORE_COLOR (1<<5)
935 #define REFRESH_ICON_TILE (1<<6)
936 #define REFRESH_ICON_FONT (1<<7)
937 #define REFRESH_WORKSPACE_BACK (1<<8)
939 static void
940 refreshMenus(WScreen *scr, int flags)
942 WMenu *menu;
944 menu = scr->root_menu;
945 if (menu)
946 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
948 menu = scr->workspace_menu;
949 if (menu)
950 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
952 menu = scr->switch_menu;
953 if (menu)
954 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
956 menu = scr->window_menu;
957 if (menu)
958 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
960 menu = scr->icon_menu;
961 if (menu)
962 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
964 if (scr->dock) {
965 menu = scr->dock->menu;
966 if (menu)
967 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
969 menu = scr->clip_menu;
970 if (menu)
971 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
973 menu = scr->clip_submenu;
974 if (menu)
975 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
977 menu = scr->clip_options;
978 if (menu)
979 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
983 static void
984 refreshAppIcons(WScreen *scr, int flags)
986 WAppIcon *aicon = scr->app_icon_list;
988 while (aicon) {
989 if (aicon->icon) {
990 aicon->icon->force_paint = 1;
992 aicon = aicon->next;
997 static void
998 refreshWindows(WScreen *scr, int flags)
1000 WWindow *wwin;
1002 wwin = scr->focused_window;
1003 while (wwin) {
1004 if (flags & REFRESH_WINDOW_FONT) {
1005 wWindowConfigureBorders(wwin);
1007 if ((flags & (REFRESH_ICON_TILE|REFRESH_WINDOW_TEXTURES)) &&
1008 wwin->flags.miniaturized && wwin->icon) {
1009 wwin->icon->force_paint = 1;
1011 if (flags & REFRESH_WINDOW_TEXTURES) {
1012 wwin->frame->flags.need_texture_remake = 1;
1014 wwin = wwin->prev;
1019 void
1020 wReadDefaults(WScreen *scr, proplist_t new_dict)
1022 proplist_t plvalue, old_value;
1023 WDefaultEntry *entry;
1024 int i, changed, must_update;
1025 int needs_refresh;
1026 void *tdata;
1027 proplist_t old_dict = (WDWindowMaker->dictionary!=new_dict
1028 ? WDWindowMaker->dictionary : NULL);
1030 changed = 0;
1031 must_update = 0;
1033 needs_refresh = 0;
1035 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
1036 entry = &optionList[i];
1038 if (new_dict)
1039 plvalue = PLGetDictionaryEntry(new_dict, entry->plkey);
1040 else
1041 plvalue = NULL;
1043 if (!old_dict)
1044 old_value = NULL;
1045 else
1046 old_value = PLGetDictionaryEntry(old_dict, entry->plkey);
1049 if (!plvalue && !old_value) {
1050 /* no default in the DB. Use builtin default */
1051 plvalue = entry->plvalue;
1052 if (plvalue && new_dict) {
1053 PLInsertDictionaryEntry(new_dict, entry->plkey, plvalue);
1054 changed = 1;
1055 must_update = 1;
1057 } else if (!plvalue) {
1058 /* value was deleted from DB. Keep current value */
1059 continue;
1060 } else if (!old_value) {
1061 /* set value for the 1st time */
1062 changed = 1;
1063 } else if (!PLIsEqual(plvalue, old_value)) {
1064 /* value has changed */
1065 changed = 1;
1066 } else {
1067 /* value was not changed since last time */
1068 continue;
1071 if (plvalue) {
1072 #ifdef DEBUG
1073 printf("Updating %s to %s\n", entry->key, PLGetDescription(plvalue));
1074 #endif
1075 /* convert data */
1076 if ((*entry->convert)(scr, entry, plvalue, entry->addr, &tdata)) {
1077 if (entry->update) {
1078 needs_refresh |=
1079 (*entry->update)(scr, entry, tdata, entry->extra_data);
1085 if (needs_refresh!=0) {
1086 int foo;
1088 foo = 0;
1089 if (needs_refresh & REFRESH_MENU_TEXTURES)
1090 foo |= MR_TEXT_BACK;
1091 if (needs_refresh & REFRESH_MENU_FONT)
1092 foo |= MR_RESIZED;
1093 if (needs_refresh & REFRESH_MENU_TITLE_FONT)
1094 foo |= MR_TITLE_TEXT;
1096 if (foo)
1097 refreshMenus(scr, foo);
1099 if (needs_refresh & (REFRESH_WINDOW_TEXTURES|REFRESH_WINDOW_FONT|
1100 REFRESH_ICON_TILE))
1101 refreshWindows(scr, needs_refresh);
1103 if (needs_refresh & REFRESH_ICON_TILE)
1104 refreshAppIcons(scr, needs_refresh);
1106 #ifdef EXPERIMENTAL
1107 if (needs_refresh & REFRESH_WORKSPACE_BACK) {
1108 WWorkspaceTexture *wsback;
1110 /* update the background for the workspace */
1111 if (scr->current_workspace < scr->wspaceTextureCount
1112 && scr->wspaceTextures[scr->current_workspace]) {
1113 wsback = scr->wspaceTextures[scr->current_workspace];
1114 } else {
1115 wsback = scr->defaultTexure;
1117 if (wsback) {
1118 if (wsback->pixmap!=None) {
1119 XSetWindowBackgroundPixmap(dpy, scr->root_win,
1120 wsback->pixmap);
1121 } else {
1122 XSetWindowBackground(dpy, scr->root_win, wsback->solid);
1124 XClearWindow(dpy, scr->root_win);
1125 XFlush(dpy);
1128 #endif /* !EXPERIMENTAL */
1129 wRefreshDesktop(scr);
1134 void
1135 wDefaultUpdateIcons(WScreen *scr)
1137 WAppIcon *aicon = scr->app_icon_list;
1138 WWindow *wwin = scr->focused_window;
1139 char *file;
1141 while(aicon) {
1142 file = wDefaultGetIconFile(scr, aicon->wm_instance, aicon->wm_class,
1143 False);
1144 if ((file && aicon->icon->file && strcmp(file, aicon->icon->file)!=0)
1145 || (file && !aicon->icon->file)) {
1146 RImage *new_image;
1148 if (aicon->icon->file)
1149 free(aicon->icon->file);
1150 aicon->icon->file = wstrdup(file);
1152 new_image = wDefaultGetImage(scr, aicon->wm_instance,
1153 aicon->wm_class);
1154 if (new_image) {
1155 wIconChangeImage(aicon->icon, new_image);
1156 wAppIconPaint(aicon);
1159 aicon = aicon->next;
1162 if (!wPreferences.flags.noclip)
1163 wClipIconPaint(scr->clip_icon);
1165 while (wwin) {
1166 if (wwin->icon && wwin->flags.miniaturized) {
1167 file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
1168 False);
1169 if ((file && wwin->icon->file && strcmp(file, wwin->icon->file)!=0)
1170 || (file && !wwin->icon->file)) {
1171 RImage *new_image;
1173 if (wwin->icon->file)
1174 free(wwin->icon->file);
1175 wwin->icon->file = wstrdup(file);
1177 new_image = wDefaultGetImage(scr, wwin->wm_instance,
1178 wwin->wm_class);
1179 if (new_image)
1180 wIconChangeImage(wwin->icon, new_image);
1183 wwin = wwin->prev;
1188 /* --------------------------- Local ----------------------- */
1190 #define STRINGP(x) if (!PLIsString(value)) { \
1191 wwarning(_("Wrong option format for key \"%s\". Should be %s."), \
1192 PLGetString(entry->plkey), x); \
1193 return False; }
1197 static int
1198 string2index(proplist_t key, proplist_t val, proplist_t def,
1199 WOptionEnumeration *values)
1201 char *str;
1202 WOptionEnumeration *v;
1203 char buffer[TOTAL_VALUES_LENGTH];
1205 if (PLIsString(val) && (str = PLGetString(val))) {
1206 for (v=values; v->string!=NULL; v++) {
1207 if (strcasecmp(v->string, str)==0)
1208 return v->value;
1212 buffer[0] = 0;
1213 for (v=values; v->string!=NULL; v++) {
1214 if (!v->is_alias) {
1215 if (buffer[0]!=0)
1216 strcat(buffer, ", ");
1217 strcat(buffer, v->string);
1220 wwarning(_("wrong option value for key \"%s\". Should be one of %s"),
1221 PLGetString(key), buffer);
1223 if (def) {
1224 return string2index(key, val, NULL, values);
1227 return -1;
1234 * value - is the value in the defaults DB
1235 * addr - is the address to store the data
1236 * ret - is the address to store a pointer to a temporary buffer. ret
1237 * must not be freed and is used by the set functions
1239 static int
1240 getBool(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1241 void **ret)
1243 static char data;
1244 char *val;
1245 int second_pass=0;
1247 STRINGP("Boolean");
1249 val = PLGetString(value);
1251 again:
1252 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
1253 || strcasecmp(val, "YES")==0) {
1255 data = 1;
1256 } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
1257 || strcasecmp(val, "NO")==0) {
1258 data = 0;
1259 } else {
1260 int i;
1261 if (sscanf(val, "%i", &i)==1) {
1262 if (i!=0)
1263 data = 1;
1264 else
1265 data = 0;
1266 } else {
1267 wwarning(_("can't convert \"%s\" to boolean for key \"%s\""),
1268 val, PLGetString(entry->plkey));
1269 if (second_pass==0) {
1270 val = PLGetString(entry->plvalue);
1271 second_pass = 1;
1272 wwarning(_("using default \"%s\" instead"), val);
1273 goto again;
1275 return False;
1279 if (ret)
1280 *ret = &data;
1282 if (addr) {
1283 *(char*)addr = data;
1286 return True;
1290 static int
1291 getInt(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1292 void **ret)
1294 static int data;
1295 char *val;
1298 STRINGP("Integer");
1300 val = PLGetString(value);
1302 if (sscanf(val, "%i", &data)!=1) {
1303 wwarning(_("can't convert \"%s\" to integer for key \"%s\""),
1304 val, PLGetString(entry->plkey));
1305 val = PLGetString(entry->plvalue);
1306 wwarning(_("using default \"%s\" instead"), val);
1307 if (sscanf(val, "%i", &data)!=1) {
1308 return False;
1312 if (ret)
1313 *ret = &data;
1315 if (addr) {
1316 *(int*)addr = data;
1318 return True;
1322 static int
1323 getCoord(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1324 void **ret)
1326 static WCoord data;
1327 char *val_x, *val_y;
1328 int nelem, changed=0;
1329 proplist_t elem_x, elem_y;
1331 again:
1332 if (!PLIsArray(value)) {
1333 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1334 PLGetString(entry->plkey), "Coordinate");
1335 if (changed==0) {
1336 value = entry->plvalue;
1337 changed = 1;
1338 wwarning(_("using default \"%s\" instead"), entry->default_value);
1339 goto again;
1341 return False;
1344 nelem = PLGetNumberOfElements(value);
1345 if (nelem != 2) {
1346 wwarning(_("Incorrect number of elements in array for key \"%s\"."),
1347 PLGetString(entry->plkey));
1348 if (changed==0) {
1349 value = entry->plvalue;
1350 changed = 1;
1351 wwarning(_("using default \"%s\" instead"), entry->default_value);
1352 goto again;
1354 return False;
1357 elem_x = PLGetArrayElement(value, 0);
1358 elem_y = PLGetArrayElement(value, 1);
1360 if (!elem_x || !elem_y || !PLIsString(elem_x) || !PLIsString(elem_y)) {
1361 wwarning(_("Wrong value for key \"%s\". Should be Coordinate."),
1362 PLGetString(entry->plkey));
1363 if (changed==0) {
1364 value = entry->plvalue;
1365 changed = 1;
1366 wwarning(_("using default \"%s\" instead"), entry->default_value);
1367 goto again;
1369 return False;
1372 val_x = PLGetString(elem_x);
1373 val_y = PLGetString(elem_y);
1375 if (sscanf(val_x, "%i", &data.x)!=1 || sscanf(val_y, "%i", &data.y)!=1) {
1376 wwarning(_("can't convert array to integers for \"%s\"."),
1377 PLGetString(entry->plkey));
1378 if (changed==0) {
1379 value = entry->plvalue;
1380 changed = 1;
1381 wwarning(_("using default \"%s\" instead"), entry->default_value);
1382 goto again;
1384 return False;
1387 if (data.x < 0)
1388 data.x = 0;
1389 else if (data.x > scr->scr_width/3)
1390 data.x = scr->scr_width/3;
1391 if (data.y < 0)
1392 data.y = 0;
1393 else if (data.y > scr->scr_height/3)
1394 data.y = scr->scr_height/3;
1396 if (ret)
1397 *ret = &data;
1399 if (addr) {
1400 *(WCoord*)addr = data;
1403 return True;
1407 #if 0
1408 /* This function is not used at the moment. */
1409 static int
1410 getString(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1411 void **ret)
1413 static char *data;
1415 STRINGP("String");
1417 data = PLGetString(value);
1419 if (!data) {
1420 data = PLGetString(entry->plvalue);
1421 if (!data)
1422 return False;
1425 if (ret)
1426 *ret = &data;
1428 if (addr)
1429 *(char**)addr = wstrdup(data);
1431 return True;
1433 #endif
1436 static int
1437 getPathList(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1438 void **ret)
1440 static char **data;
1441 int i, count;
1442 proplist_t d;
1443 int changed=0;
1445 again:
1446 if (!PLIsArray(value)) {
1447 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1448 PLGetString(entry->plkey), "an array of paths");
1449 if (changed==0) {
1450 value = entry->plvalue;
1451 changed = 1;
1452 wwarning(_("using default \"%s\" instead"), entry->default_value);
1453 goto again;
1455 return False;
1458 i = 0;
1459 count = PLGetNumberOfElements(value);
1460 if (count < 1) {
1461 if (changed==0) {
1462 value = entry->plvalue;
1463 changed = 1;
1464 wwarning(_("using default \"%s\" instead"), entry->default_value);
1465 goto again;
1467 return False;
1470 data = wmalloc(sizeof(char*)*(count+1));
1471 for (i=0; i<count; i++) {
1472 d = PLGetArrayElement(value, i);
1473 if (!d || !PLIsString(d)) {
1474 break;
1476 data[i] = wstrdup(PLGetString(d));
1478 data[i]=NULL;
1480 if (*(char***)addr!=NULL) {
1481 char **tmp = *(char***)addr;
1482 for (i=0; tmp[i]!=NULL; i++) {
1483 free(tmp[i]);
1485 free(tmp);
1487 *(char***)addr = data;
1489 return True;
1493 static int
1494 getEnum(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1495 void **ret)
1497 static char data;
1499 data = string2index(entry->key, value, entry->default_value,
1500 (WOptionEnumeration*)entry->extra_data);
1501 if (data < 0)
1502 return False;
1504 if (ret)
1505 *ret = &data;
1507 if (addr)
1508 *(char*)addr = data;
1510 return True;
1516 * (solid <color>)
1517 * (hgradient <color> <color>)
1518 * (vgradient <color> <color>)
1519 * (dgradient <color> <color>)
1520 * (mhgradient <color> <color> ...)
1521 * (mvgradient <color> <color> ...)
1522 * (tpixmap <file> <color>)
1523 * (spixmap <file> <color>)
1524 * (cpixmap <file> <color>)
1527 static WTexture*
1528 parse_texture(WScreen *scr, proplist_t pl)
1530 proplist_t elem;
1531 char *val;
1532 int nelem;
1533 WTexture *texture=NULL;
1535 nelem = PLGetNumberOfElements(pl);
1536 if (nelem < 1)
1537 return NULL;
1540 elem = PLGetArrayElement(pl, 0);
1541 if (!elem || !PLIsString(elem))
1542 return NULL;
1543 val = PLGetString(elem);
1546 if (strcasecmp(val, "solid")==0) {
1547 XColor color;
1549 if (nelem != 2)
1550 return NULL;
1552 /* get color */
1554 elem = PLGetArrayElement(pl, 1);
1555 if (!elem || !PLIsString(elem))
1556 return NULL;
1557 val = PLGetString(elem);
1559 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1560 wwarning(_("\"%s\" is not a valid color name"), val);
1561 return NULL;
1564 texture = (WTexture*)wTextureMakeSolid(scr, &color);
1565 } else if (strcasecmp(val, "dgradient")==0
1566 || strcasecmp(val, "vgradient")==0
1567 || strcasecmp(val, "hgradient")==0) {
1568 XColor color1, color2;
1569 int type;
1571 if (nelem != 3) {
1572 wwarning(_("bad number of arguments in gradient specification"));
1573 return NULL;
1576 if (val[0]=='d' || val[0]=='D')
1577 type = WTEX_DGRADIENT;
1578 else if (val[0]=='h' || val[0]=='H')
1579 type = WTEX_HGRADIENT;
1580 else
1581 type = WTEX_VGRADIENT;
1584 /* get from color */
1585 elem = PLGetArrayElement(pl, 1);
1586 if (!elem || !PLIsString(elem))
1587 return NULL;
1588 val = PLGetString(elem);
1590 if (!XParseColor(dpy, scr->colormap, val, &color1)) {
1591 wwarning(_("\"%s\" is not a valid color name"), val);
1592 return NULL;
1595 /* get to color */
1596 elem = PLGetArrayElement(pl, 2);
1597 if (!elem || !PLIsString(elem)) {
1598 return NULL;
1600 val = PLGetString(elem);
1602 if (!XParseColor(dpy, scr->colormap, val, &color2)) {
1603 wwarning(_("\"%s\" is not a valid color name"), val);
1604 return NULL;
1607 texture = (WTexture*)wTextureMakeGradient(scr, type, &color1, &color2);
1609 } else if (strcasecmp(val, "mhgradient")==0
1610 || strcasecmp(val, "mvgradient")==0
1611 || strcasecmp(val, "mdgradient")==0) {
1612 XColor color;
1613 RColor **colors;
1614 int i, count;
1615 int type;
1617 if (nelem < 3) {
1618 wwarning(_("too few arguments in multicolor gradient specification"));
1619 return NULL;
1622 if (val[1]=='h' || val[1]=='H')
1623 type = WTEX_MHGRADIENT;
1624 else if (val[1]=='v' || val[1]=='V')
1625 type = WTEX_MVGRADIENT;
1626 else
1627 type = WTEX_MDGRADIENT;
1629 count = nelem-1;
1631 colors = wmalloc(sizeof(RColor*)*(count+1));
1633 for (i=0; i<count; i++) {
1634 elem = PLGetArrayElement(pl, i+1);
1635 if (!elem || !PLIsString(elem)) {
1636 for (--i; i>=0; --i) {
1637 free(colors[i]);
1639 free(colors);
1640 return NULL;
1642 val = PLGetString(elem);
1644 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1645 wwarning(_("\"%s\" is not a valid color name"), val);
1646 for (--i; i>=0; --i) {
1647 free(colors[i]);
1649 free(colors);
1650 return NULL;
1651 } else {
1652 colors[i] = wmalloc(sizeof(RColor));
1653 colors[i]->red = color.red >> 8;
1654 colors[i]->green = color.green >> 8;
1655 colors[i]->blue = color.blue >> 8;
1658 colors[i] = NULL;
1660 texture = (WTexture*)wTextureMakeMGradient(scr, type, colors);
1661 } else if (strcasecmp(val, "spixmap")==0 ||
1662 strcasecmp(val, "cpixmap")==0 ||
1663 strcasecmp(val, "tpixmap")==0) {
1664 XColor color;
1665 int type;
1667 if (nelem != 3)
1668 return NULL;
1670 if (val[0] == 's' || val[0] == 'S')
1671 type = WTP_SCALE;
1672 else if (val[0] == 'c' || val[0] == 'C')
1673 type = WTP_CENTER;
1674 else
1675 type = WTP_TILE;
1677 /* get color */
1678 elem = PLGetArrayElement(pl, 2);
1679 if (!elem || !PLIsString(elem)) {
1680 return NULL;
1682 val = PLGetString(elem);
1684 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1685 wwarning(_("\"%s\" is not a valid color name"), val);
1686 return NULL;
1689 /* file name */
1690 elem = PLGetArrayElement(pl, 1);
1691 if (!elem || !PLIsString(elem))
1692 return NULL;
1693 val = PLGetString(elem);
1695 texture = (WTexture*)wTextureMakePixmap(scr, type, val, &color);
1697 } else {
1698 return NULL;
1700 return texture;
1705 static int
1706 getTexture(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1707 void **ret)
1709 static WTexture *texture;
1710 int changed=0;
1712 again:
1713 if (!PLIsArray(value)) {
1714 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1715 PLGetString(entry->plkey), "Texture");
1716 if (changed==0) {
1717 value = entry->plvalue;
1718 changed = 1;
1719 wwarning(_("using default \"%s\" instead"), entry->default_value);
1720 goto again;
1722 return False;
1725 texture = parse_texture(scr, value);
1727 if (!texture) {
1728 wwarning(_("Error in texture specification for key \"%s\""),
1729 PLGetString(entry->plkey));
1730 if (changed==0) {
1731 value = entry->plvalue;
1732 changed = 1;
1733 wwarning(_("using default \"%s\" instead"), entry->default_value);
1734 goto again;
1736 return False;
1739 if (ret)
1740 *ret = &texture;
1742 if (addr)
1743 *(WTexture**)addr = texture;
1745 return True;
1750 #ifdef EXPERIMENTAL
1751 static int
1752 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1753 void *addr, void **ret)
1755 proplist_t elem;
1756 char *val;
1757 int nelem;
1758 static WTexture *texture=NULL;
1759 int changed=0;
1760 char *file = NULL;
1762 again:
1763 entry->extra_data = NULL;
1765 if (!PLIsArray(value)) {
1766 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1767 "WorkspaceBack", "Texture");
1768 if (changed==0) {
1769 value = entry->plvalue;
1770 changed = 1;
1771 wwarning(_("using default \"%s\" instead"), entry->default_value);
1772 goto again;
1774 return False;
1777 nelem = PLGetNumberOfElements(value);
1778 if (nelem < 1) {
1779 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1780 if (changed==0) {
1781 value = entry->plvalue;
1782 changed = 1;
1783 wwarning(_("using default \"%s\" instead"), entry->default_value);
1784 goto again;
1786 return False;
1789 elem = PLGetArrayElement(value, 0);
1790 if (!elem || !PLIsString(elem)) {
1791 wwarning(_("Wrong type for workspace background. Should be Texture."));
1792 if (changed==0) {
1793 value = entry->plvalue;
1794 changed = 1;
1795 wwarning(_("using default \"%s\" instead"), entry->default_value);
1796 goto again;
1798 return False;
1800 val = PLGetString(elem);
1802 if (strcasecmp(val, "None")==0)
1803 return False;
1805 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
1806 && strcasecmp(val, "cpixmap")!=0) {
1807 texture = parse_texture(scr, value);
1808 } else {
1809 /* spixmap || tpixmap || cpixmap */
1810 XColor color;
1811 int style;
1813 if (nelem != 3) {
1814 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1815 if (changed==0) {
1816 value = entry->plvalue;
1817 changed = 1;
1818 wwarning(_("using default \"%s\" instead"), entry->default_value);
1819 goto again;
1821 return False;
1824 switch (val[0]) {
1825 case 's':
1826 case 'S':
1827 style = WTP_SCALE;
1828 break;
1829 case 'C':
1830 case 'c':
1831 style = WTP_CENTER;
1832 break;
1833 default:
1834 style = WTP_TILE;
1835 break;
1838 /* get color */
1839 elem = PLGetArrayElement(value, 2);
1840 if (!elem || !PLIsString(elem)) {
1841 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
1842 if (changed==0) {
1843 value = entry->plvalue;
1844 changed = 1;
1845 wwarning(_("using default \"%s\" instead"), entry->default_value);
1846 goto again;
1848 return False;
1850 val = PLGetString(elem);
1852 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1853 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
1854 val);
1855 if (changed==0) {
1856 value = entry->plvalue;
1857 changed = 1;
1858 wwarning(_("using default \"%s\" instead"), entry->default_value);
1859 goto again;
1861 return False;
1864 /* file name */
1865 elem = PLGetArrayElement(value, 1);
1866 if (!elem || !PLIsString(elem)) {
1867 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
1868 if (changed==0) {
1869 value = entry->plvalue;
1870 changed = 1;
1871 wwarning(_("using default \"%s\" instead"), entry->default_value);
1872 goto again;
1874 return False;
1877 val = PLGetString(elem);
1878 file = FindImage(wPreferences.pixmap_path, val);
1879 if (!file) {
1880 wwarning(_("could not find background image \"%s\""), val);
1881 /*return False;*/
1884 /* create a dummy texture.
1885 * use free() to free this texture.
1887 texture = wmalloc(sizeof(WTexture));
1888 memset(texture, 0, sizeof(WTexture));
1889 texture->type = WTEX_PIXMAP;
1890 texture->subtype = style;
1891 texture->normal = color;
1894 if (!texture) {
1895 if (file)
1896 free(file);
1897 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
1898 if (changed==0) {
1899 value = entry->plvalue;
1900 changed = 1;
1901 wwarning(_("using default \"%s\" instead"), entry->default_value);
1902 goto again;
1904 return False;
1907 if (ret)
1908 *ret = &texture;
1910 if (addr)
1911 *(WTexture**)addr = texture;
1913 /* we use the extra_data field to pass the filename string
1914 * to the background setting function. We can't pass it with
1915 * WTexture because it holds a RImage, not a file name.
1916 * It also would be dirtier to cast the RImage to char* to make it
1917 * hold the file name. The extra_data must be freed by the
1918 * setting function.
1920 entry->extra_data = file;
1922 return True;
1924 #else /* !EXPERIMENTAL */
1925 static int
1926 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1927 void *addr, void **ret)
1929 proplist_t elem;
1930 char *val;
1931 int nelem;
1932 static WTexture *texture=NULL;
1933 int changed=0;
1935 again:
1936 if (!PLIsArray(value)) {
1937 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1938 "WorkspaceBack", "Texture");
1939 if (changed==0) {
1940 value = entry->plvalue;
1941 changed = 1;
1942 wwarning(_("using default \"%s\" instead"), entry->default_value);
1943 goto again;
1945 return False;
1948 nelem = PLGetNumberOfElements(value);
1949 if (nelem < 1) {
1950 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1951 if (changed==0) {
1952 value = entry->plvalue;
1953 changed = 1;
1954 wwarning(_("using default \"%s\" instead"), entry->default_value);
1955 goto again;
1957 return False;
1960 elem = PLGetArrayElement(value, 0);
1961 if (!elem || !PLIsString(elem)) {
1962 wwarning(_("Wrong type for workspace background. Should be Texture."));
1963 if (changed==0) {
1964 value = entry->plvalue;
1965 changed = 1;
1966 wwarning(_("using default \"%s\" instead"), entry->default_value);
1967 goto again;
1969 return False;
1971 val = PLGetString(elem);
1973 if (strcasecmp(val, "None")==0)
1974 return False;
1976 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
1977 && strcasecmp(val, "cpixmap")!=0) {
1978 texture = parse_texture(scr, value);
1980 else {
1981 /* spixmap || tpixmap || cpixmap */
1982 XColor color;
1983 char *file, cpc[30], *style = "-s";
1984 char *program = "wmsetbg";
1985 char *back;
1987 if (nelem != 3) {
1988 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1989 if (changed==0) {
1990 value = entry->plvalue;
1991 changed = 1;
1992 wwarning(_("using default \"%s\" instead"), entry->default_value);
1993 goto again;
1995 return False;
1998 if (val[0] == 't' || val[0] == 'T')
1999 style = "-t";
2000 else if (val[0] == 'c' || val[0] == 'C')
2001 style = "-e";
2003 sprintf(cpc, "%i", wPreferences.cmap_size);
2005 /* get color */
2006 elem = PLGetArrayElement(value, 2);
2007 if (!elem || !PLIsString(elem)) {
2008 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
2009 if (changed==0) {
2010 value = entry->plvalue;
2011 changed = 1;
2012 wwarning(_("using default \"%s\" instead"), entry->default_value);
2013 goto again;
2015 return False;
2017 val = PLGetString(elem);
2019 if (!XParseColor(dpy, scr->colormap, val, &color)) {
2020 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
2021 val);
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 back = wstrdup(val);
2033 /* file name */
2034 elem = PLGetArrayElement(value, 1);
2035 if (!elem || !PLIsString(elem)) {
2036 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
2037 if (changed==0) {
2038 value = entry->plvalue;
2039 changed = 1;
2040 wwarning(_("using default \"%s\" instead"), entry->default_value);
2041 goto again;
2043 return False;
2046 val = PLGetString(elem);
2048 file = FindImage(wPreferences.pixmap_path, val);
2049 if (file) {
2050 if (fork()==0) {
2051 SetupEnvironment(scr);
2053 close(ConnectionNumber(dpy));
2055 execlp(program, program, style, "-c", cpc, "-b", back, file, NULL);
2056 wwarning(_("could not run \"%s\""), program);
2057 exit(-1);
2059 free(file);
2060 } else {
2061 wwarning(_("could not find background image \"%s\""), val);
2064 free(back);
2066 /* This is to let WindowMaker put a color in the background
2067 * until the pixmap is loaded, if the image is big and loads slow.
2068 * It assumes that the color will be set before the image is set
2069 * by the child. Is this true for very small images?
2071 texture = (WTexture*)wTextureMakeSolid(scr, &color);
2074 if (!texture) {
2075 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
2076 if (changed==0) {
2077 value = entry->plvalue;
2078 changed = 1;
2079 wwarning(_("using default \"%s\" instead"), entry->default_value);
2080 goto again;
2082 return False;
2085 if (ret)
2086 *ret = &texture;
2088 if (addr)
2089 *(WTexture**)addr = texture;
2091 return True;
2093 #endif /* !EXPERIMENTAL */
2096 static int
2097 getFont(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2098 void **ret)
2100 static WFont *font;
2101 char *val;
2103 STRINGP("Font");
2105 val = PLGetString(value);
2107 font = wLoadFont(val);
2108 if (!font) {
2109 wwarning(_("could not load any usable font"));
2110 return False;
2113 if (ret)
2114 *ret = font;
2116 if (addr) {
2117 wwarning("BUG:can't assign font value outside update function");
2120 return True;
2124 static int
2125 getColor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2126 void **ret)
2128 static unsigned long pixel;
2129 XColor color;
2130 char *val;
2131 int second_pass=0;
2133 STRINGP("Color");
2135 val = PLGetString(value);
2137 again:
2138 if (!wGetColor(scr, val, &color)) {
2139 wwarning(_("could not get color for key \"%s\""),
2140 PLGetString(entry->plkey));
2141 if (second_pass==0) {
2142 val = PLGetString(entry->plvalue);
2143 second_pass = 1;
2144 wwarning(_("using default \"%s\" instead"), val);
2145 goto again;
2147 return False;
2150 pixel = color.pixel;
2152 if (ret)
2153 *ret = &pixel;
2155 if (addr)
2156 *(unsigned long*)addr = pixel;
2158 return True;
2163 static int
2164 getKeybind(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2165 void **ret)
2167 static WShortKey shortcut;
2168 KeySym ksym;
2169 char *val;
2170 char *k;
2171 char buf[128], *b;
2174 STRINGP("Key spec");
2176 val = PLGetString(value);
2178 if (!val || strcasecmp(val, "NONE")==0) {
2179 shortcut.keycode = 0;
2180 shortcut.modifier = 0;
2181 if (ret)
2182 *ret = &shortcut;
2183 return True;
2186 strcpy(buf, val);
2188 b = (char*)buf;
2190 /* get modifiers */
2191 shortcut.modifier = 0;
2192 while ((k = strchr(b, '+'))!=NULL) {
2193 int mod;
2195 *k = 0;
2196 mod = wXModifierFromKey(b);
2197 if (mod<0) {
2198 wwarning(_("%s:invalid key modifier \"%s\""), entry->key, val);
2199 return False;
2201 shortcut.modifier |= mod;
2203 b = k+1;
2206 /* get key */
2207 ksym = XStringToKeysym(b);
2209 if (ksym==NoSymbol) {
2210 wwarning(_("%s:invalid kbd shortcut specification \"%s\""), entry->key,
2211 val);
2212 return False;
2215 shortcut.keycode = XKeysymToKeycode(dpy, ksym);
2216 if (shortcut.keycode==0) {
2217 wwarning(_("%s:invalid key in shortcut \"%s\""), entry->key, val);
2218 return False;
2221 if (ret)
2222 *ret = &shortcut;
2224 return True;
2228 static int
2229 getModMask(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2230 void **ret)
2232 unsigned int mask;
2233 char *str;
2235 STRINGP("Modifier Key");
2237 str = PLGetString(value);
2238 if (!str)
2239 return False;
2241 mask = wXModifierFromKey(str);
2242 if (mask < 0) {
2243 wwarning(_("%s: modifier key %s is not valid"), entry->key, str);
2244 mask = 0;
2245 return False;
2248 if (addr)
2249 *(unsigned int*)addr = mask;
2251 if (ret)
2252 *ret = &mask;
2254 return True;
2259 /* ---------------- value setting functions --------------- */
2260 static int
2261 setJustify(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2263 return REFRESH_FORE_COLOR;
2267 static int
2268 setIfDockPresent(WScreen *scr, WDefaultEntry *entry, int *flag, long which)
2270 switch (which) {
2271 case WM_DOCK:
2272 wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
2273 break;
2274 case WM_CLIP:
2275 wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
2276 break;
2277 default:
2278 break;
2280 return 0;
2284 static int
2285 setStickyIcons(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
2287 if (scr->workspaces) {
2288 wWorkspaceForceChange(scr, scr->current_workspace);
2289 wArrangeIcons(scr, False);
2291 return 0;
2294 #if not_used
2295 static int
2296 setPositive(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
2298 if (*value <= 0)
2299 *(int*)foo = 1;
2301 return 0;
2303 #endif
2307 static int
2308 setIconTile(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2310 Pixmap pixmap;
2311 RImage *img;
2312 int reset = 0;
2314 img = wTextureRenderImage(*texture, wPreferences.icon_size,
2315 wPreferences.icon_size,
2316 ((*texture)->any.type & WREL_BORDER_MASK)
2317 ? WREL_ICON : WREL_FLAT);
2318 if (!img) {
2319 wwarning(_("could not render texture for icon background"));
2320 if (!entry->addr)
2321 wTextureDestroy(scr, *texture);
2322 return 0;
2324 RConvertImage(scr->rcontext, img, &pixmap);
2326 if (scr->icon_tile) {
2327 reset = 1;
2328 RDestroyImage(scr->icon_tile);
2329 XFreePixmap(dpy, scr->icon_tile_pixmap);
2332 scr->icon_tile = img;
2334 if (!wPreferences.flags.noclip) {
2335 if (scr->clip_tile) {
2336 RDestroyImage(scr->clip_tile);
2338 scr->clip_tile = wClipMakeTile(scr, img);
2341 scr->icon_tile_pixmap = pixmap;
2343 if (scr->def_icon_pixmap) {
2344 XFreePixmap(dpy, scr->def_icon_pixmap);
2345 scr->def_icon_pixmap = None;
2347 if (scr->def_ticon_pixmap) {
2348 XFreePixmap(dpy, scr->def_ticon_pixmap);
2349 scr->def_ticon_pixmap = None;
2352 if (scr->icon_back_texture) {
2353 wTextureDestroy(scr, (WTexture*)scr->icon_back_texture);
2355 scr->icon_back_texture = wTextureMakeSolid(scr, &((*texture)->any.color));
2357 if (scr->clip_balloon)
2358 XSetWindowBackground(dpy, scr->clip_balloon,
2359 (*texture)->any.color.pixel);
2362 * Free the texture as nobody else will use it, nor refer to it.
2364 if (!entry->addr)
2365 wTextureDestroy(scr, *texture);
2367 return (reset ? REFRESH_ICON_TILE : 0);
2372 static int
2373 setWinTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2375 if (scr->title_font) {
2376 wFreeFont(scr->title_font);
2379 scr->title_font = font;
2381 #ifndef I18N_MB
2382 XSetFont(dpy, scr->window_title_gc, font->font->fid);
2383 #endif
2385 return REFRESH_WINDOW_FONT;
2389 static int
2390 setMenuTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2392 if (scr->menu_title_font) {
2393 wFreeFont(scr->menu_title_font);
2396 scr->menu_title_font = font;
2398 #ifndef I18N_MB
2399 XSetFont(dpy, scr->menu_title_gc, font->font->fid);
2400 #endif
2402 return REFRESH_MENU_TITLE_FONT;
2406 static int
2407 setMenuTextFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2409 if (scr->menu_entry_font) {
2410 wFreeFont(scr->menu_entry_font);
2413 scr->menu_entry_font = font;
2415 #ifndef I18N_MB
2416 XSetFont(dpy, scr->menu_entry_gc, font->font->fid);
2417 XSetFont(dpy, scr->disabled_menu_entry_gc, font->font->fid);
2418 XSetFont(dpy, scr->select_menu_gc, font->font->fid);
2419 #endif
2421 return REFRESH_MENU_FONT;
2426 static int
2427 setIconTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2429 if (scr->icon_title_font) {
2430 wFreeFont(scr->icon_title_font);
2433 scr->icon_title_font = font;
2435 #ifndef I18N_MB
2436 XSetFont(dpy, scr->icon_title_gc, font->font->fid);
2437 #endif
2439 return REFRESH_ICON_FONT;
2443 static int
2444 setClipTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2446 if (scr->clip_title_font) {
2447 wFreeFont(scr->clip_title_font);
2450 scr->clip_title_font = font;
2452 #ifndef I18N_MB
2453 XSetFont(dpy, scr->clip_title_gc, font->font->fid);
2454 #endif
2456 return REFRESH_ICON_FONT;
2460 static int
2461 setDisplayFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2463 if (scr->info_text_font) {
2464 wFreeFont(scr->info_text_font);
2467 scr->info_text_font = font;
2469 #ifndef I18N_MB
2470 XSetFont(dpy, scr->info_text_gc, font->font->fid);
2471 XSetFont(dpy, scr->line_gc, font->font->fid);
2472 #endif
2474 /* This test works because the scr structure is initially zeroed out
2475 and None = 0. Any other time, the window should be valid. */
2476 if (scr->geometry_display != None) {
2477 wGetGeometryWindowSize(scr, &scr->geometry_display_width,
2478 &scr->geometry_display_height);
2479 XResizeWindow(dpy, scr->geometry_display,
2480 scr->geometry_display_width, scr->geometry_display_height);
2483 return 0;
2487 static int
2488 setHightlight(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2490 if (scr->select_pixel!=scr->white_pixel &&
2491 scr->select_pixel!=scr->black_pixel) {
2492 wFreeColor(scr, scr->select_pixel);
2495 scr->select_pixel = color->pixel;
2497 return REFRESH_FORE_COLOR;
2501 static int
2502 setHightlightText(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2504 if (scr->select_text_pixel!=scr->white_pixel &&
2505 scr->select_text_pixel!=scr->black_pixel) {
2506 wFreeColor(scr, scr->select_text_pixel);
2509 scr->select_text_pixel = color->pixel;
2511 return REFRESH_FORE_COLOR;
2515 static int
2516 setClipTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2518 if (scr->clip_title_pixel[index]!=scr->white_pixel &&
2519 scr->clip_title_pixel[index]!=scr->black_pixel) {
2520 wFreeColor(scr, scr->clip_title_pixel[index]);
2523 scr->clip_title_pixel[index] = color->pixel;
2525 return REFRESH_FORE_COLOR;
2529 static int
2530 setWTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2532 if (scr->window_title_pixel[index]!=scr->white_pixel &&
2533 scr->window_title_pixel[index]!=scr->black_pixel) {
2534 wFreeColor(scr, scr->window_title_pixel[index]);
2537 scr->window_title_pixel[index] = color->pixel;
2539 if (index == WS_FOCUSED)
2540 XSetForeground(dpy, scr->icon_title_gc, color->pixel);
2541 else if (index == WS_UNFOCUSED)
2542 XSetForeground(dpy, scr->info_text_gc, color->pixel);
2544 return REFRESH_FORE_COLOR;
2548 static int
2549 setMenuTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2551 if (scr->menu_title_pixel[0]!=scr->white_pixel &&
2552 scr->menu_title_pixel[0]!=scr->black_pixel) {
2553 wFreeColor(scr, scr->menu_title_pixel[0]);
2556 scr->menu_title_pixel[0] = color->pixel;
2558 XSetForeground(dpy, scr->menu_title_gc, color->pixel);
2560 return REFRESH_FORE_COLOR;
2564 static int
2565 setMenuTextColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2567 XGCValues gcv;
2568 #define gcm (GCForeground|GCBackground|GCFillStyle)
2570 if (scr->mtext_pixel!=scr->white_pixel &&
2571 scr->mtext_pixel!=scr->black_pixel) {
2572 wFreeColor(scr, scr->mtext_pixel);
2575 scr->mtext_pixel = color->pixel;
2577 XSetForeground(dpy, scr->menu_entry_gc, color->pixel);
2580 if (scr->dtext_pixel == scr->mtext_pixel) {
2581 gcv.foreground = scr->white_pixel;
2582 gcv.background = scr->black_pixel;
2583 gcv.fill_style = FillStippled;
2584 } else {
2585 gcv.foreground = scr->dtext_pixel;
2586 gcv.fill_style = FillSolid;
2588 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2590 return REFRESH_FORE_COLOR;
2591 #undef gcm
2595 static int
2596 setMenuDisabledColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2598 XGCValues gcv;
2599 #define gcm (GCForeground|GCBackground|GCFillStyle)
2601 if (scr->dtext_pixel!=scr->white_pixel &&
2602 scr->dtext_pixel!=scr->black_pixel) {
2603 wFreeColor(scr, scr->dtext_pixel);
2606 scr->dtext_pixel = color->pixel;
2608 if (scr->dtext_pixel == scr->mtext_pixel) {
2609 gcv.foreground = scr->white_pixel;
2610 gcv.background = scr->black_pixel;
2611 gcv.fill_style = FillStippled;
2612 } else {
2613 gcv.foreground = scr->dtext_pixel;
2614 gcv.fill_style = FillSolid;
2616 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2618 return REFRESH_FORE_COLOR;
2619 #undef gcm
2625 * Implementation of workspace specific backgrounds.
2627 * WorkspaceBack is used as the default background.
2628 * WorkspaceSpecificBack supplies an array with the textures for
2629 * other workspaces.
2630 * WorkspaceSpecificBack = (ws1texture, ws2texture, "", ws4texture);
2631 * "" means that workspace3 should use the default texture.
2633 * struct WWorkspaceTexture {
2634 * Pixmap pixmap; // the pixmap for non-solid textures.
2635 * //None means the texture is solid
2636 * WPixel color; // color for solid texture
2637 * proplist_t texture; // for checking updates
2638 * };
2641 * All textures are rendered by wmsetbg. When it exits with status 0
2642 * it outputs the pixmap ID.
2643 * wmaker will monitor the fd and when it becomes available it reads the
2644 * pixmap ID and uses it in the texture. The data read from the fd
2645 * is the pixmap ID and the pid of the wmsetbg process, separated by
2646 * a space (the pid is to allow paralel wmsetbg processes).
2648 * The workspace background cant be set if the pid field of the
2649 * texture is 0. Otherwise, the texture is still being rendered
2650 * and cant be set.
2652 * If the workspace background is changed before wmsetbg finishes
2653 * the rendering, wmsetbg must be killed.
2655 * Optimizations:
2656 * Workspace specific textures are generated only when switching to
2657 * that workspace, unless #define SLOW_CONFIGURATION_UPDATE.
2659 * -readme
2661 #ifdef EXPERIMENTAL
2662 static void
2663 trackDeadProcess(pid_t pid, unsigned char status, WScreen *scr)
2665 WWorkspaceTexture *wsback;
2666 int setBackground = 0;
2668 /* find out to which wsback, this process belongs to */
2670 wsback->pid = 0;
2671 if (status != 123) {
2672 /* something went wrong during rendering */
2673 XFreePixmap(dpy, wsback->pixmap);
2674 wsback->pixmap = None;
2675 wwarning(_("background texture rendering was unsuccessfull"));
2678 if (setBackground) {
2682 WWorkspaceTexture*
2683 makeWorkspaceTexture(WScreen *scr, WTexture *texture, char *file, char *option)
2685 WWorkspaceTexture *wsback;
2687 wsback = wmalloc(sizeof(WWorkspaceTexture));
2688 wsback->pid = 0;
2690 wsback->solid = (*texture)->any.color.pixel;
2692 if (texture->any.type==WTEX_SOLID) {
2693 wsback->pixmap = None;
2694 } else if (texture->any.type == WTEX_PIXMAP) {
2695 Pixmap pixmap;
2696 if (texture->pixmap.subtype == WTP_TILE) {
2697 RImage *image;
2699 /* render ourseves */
2700 image = RLoadImage(scr->rcontext, file, 0);
2701 if (!image) {
2702 wwarning(_("could not load image %s for option %s:%s\n"),
2703 file, option, RErrorString);
2704 wsback->pixmap = None;
2705 } else {
2707 } else {
2708 /* create a empty pixmap... */
2709 pid_t pid;
2710 int style = texture->pixmap.subtype;
2712 pixmap = XCreatePixmap(dpy, scr->root_win, scr->scr_width,
2713 scr->scr_height, scr->depth);
2715 /* ...and let wmsetbg render it */
2716 pid = fork();
2717 if (pid < 0) {
2718 wsyserror(_("could not spawn texture rendering subprocess for option"));
2719 } else if (pid == 0) {
2720 char *colorn, *pix;
2722 SetupEnvironment(scr);
2724 close(ConnectionNumber(dpy));
2726 colorn = wmalloc(32);
2727 sprintf(colorn, "\"#%2x%2x%2x\"",
2728 texture->any.color.red,
2729 texture->any.color.green,
2730 texture->any.color.blue);
2731 pix = wmalloc(32);
2732 sprintf(pix, "%x", pixmap);
2733 execlp("wmsetbg", "wmsetbg", (style==WTP_SCALE ? "-s":"-e"),
2734 "-b", colorn, "-x", pix, file);
2735 exit(1);
2737 wsback->pixmap = pixmap;
2738 /* must add a death handler to detect when wmsetbg has
2739 * exited (with exit status 123) and refresh the background.
2741 wsback->pid = pid;
2743 } else {
2744 int w, h;
2745 Pixmap pixmap;
2747 switch (texture->any.type) {
2748 case WTEX_HGRADIENT:
2749 case WTEX_MHGRADIENT:
2750 w = scr->scr_width;
2751 h = 8;
2752 break;
2754 case WTEX_VGRADIENT:
2755 case WTEX_MVGRADIENT:
2756 w = 8;
2757 h = scr->scr_height;
2758 break;
2760 case WTEX_DGRADIENT:
2761 case WTEX_MDGRADIENT:
2762 w = scr->scr_width;
2763 h = scr->scr_height;
2764 break;
2766 default:
2767 return NULL;
2770 img = wTextureRenderImage(texture, w, h, WREL_FLAT);
2771 if (!img) {
2772 wwarning(_("could not render texture for workspace background"));
2773 free(wsback);
2774 return NULL;
2776 RConvertImage(scr->rcontext, img, &pixmap);
2777 RDestroyImage(img);
2778 wsback->pixmap = pixmap;
2781 return wsback;
2785 static int
2786 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
2787 char *file)
2789 Pixmap pixmap;
2790 RImage *img;
2792 if (scr->defaultTexture) {
2793 if (scr->defaultTexture->pixmap)
2794 XFreePixmap(dpy, scr->defaultTexture->pixmap);
2795 free(scr->defaultTexture);
2798 if (!*texture) {
2799 scr->defaultTexture = NULL;
2800 if (file)
2801 free(file);
2802 return 0;
2805 scr->defaultTexture = makeWorkspaceTexture(scr, *texture, file);
2807 if (!entry->addr)
2808 wTextureDestroy(scr, *texture);
2810 /* free the file name that was passed from the getWSBackground()
2811 * function and placed in entry->extra_data */
2812 if (file)
2813 free(file);
2814 entry->extra_data = NULL;
2816 return REFRESH_WORKSPACE_BACK;
2818 #else /* !EXPERIMENTAL */
2819 static int
2820 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
2821 void *foo)
2823 Pixmap pixmap;
2824 RImage *img;
2827 if ((*texture)->any.type==WTEX_SOLID) {
2828 XSetWindowBackground(dpy, scr->root_win, (*texture)->solid.normal.pixel);
2829 XClearWindow(dpy, scr->root_win);
2830 } else {
2831 int w, h;
2833 switch ((*texture)->any.type) {
2834 case WTEX_HGRADIENT:
2835 case WTEX_MHGRADIENT:
2836 w = scr->scr_width;
2837 h = 8;
2838 break;
2840 case WTEX_VGRADIENT:
2841 case WTEX_MVGRADIENT:
2842 w = 8;
2843 h = scr->scr_height;
2844 break;
2846 case WTEX_DGRADIENT:
2847 case WTEX_MDGRADIENT:
2848 w = scr->scr_width;
2849 h = scr->scr_height;
2850 break;
2852 default:
2853 if (!entry->addr)
2854 wTextureDestroy(scr, *texture);
2855 return 0;
2858 img = wTextureRenderImage(*texture, w, h, WREL_FLAT);
2859 if (!img) {
2860 wwarning(_("could not render texture for workspace background"));
2861 if (!entry->addr)
2862 wTextureDestroy(scr, *texture);
2863 return 0;
2865 RConvertImage(scr->rcontext, img, &pixmap);
2866 RDestroyImage(img);
2867 XSetWindowBackgroundPixmap(dpy, scr->root_win, pixmap);
2868 XClearWindow(dpy, scr->root_win);
2872 * Free the texture as nobody else will use it, nor refer to it.
2874 if (!entry->addr)
2875 wTextureDestroy(scr, *texture);
2877 return 0;
2879 #endif /* !EXPERIMENTAL */
2881 static int
2882 setWidgetColor(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2884 if (scr->widget_texture) {
2885 wTextureDestroy(scr, (WTexture*)scr->widget_texture);
2887 scr->widget_texture = *(WTexSolid**)texture;
2889 return 0;
2893 static int
2894 setFTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2896 if (scr->window_title_texture[WS_FOCUSED]) {
2897 wTextureDestroy(scr, scr->window_title_texture[WS_FOCUSED]);
2899 scr->window_title_texture[WS_FOCUSED] = *texture;
2901 if (scr->icon_title_texture) {
2902 wTextureDestroy(scr, (WTexture*)scr->icon_title_texture);
2904 scr->icon_title_texture
2905 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_FOCUSED]->any.color);
2907 return REFRESH_WINDOW_TEXTURES;
2911 static int
2912 setPTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2914 if (scr->window_title_texture[WS_PFOCUSED]) {
2915 wTextureDestroy(scr, scr->window_title_texture[WS_PFOCUSED]);
2917 scr->window_title_texture[WS_PFOCUSED] = *texture;
2919 return REFRESH_WINDOW_TEXTURES;
2923 static int
2924 setUTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2926 if (scr->window_title_texture[WS_UNFOCUSED]) {
2927 wTextureDestroy(scr, scr->window_title_texture[WS_UNFOCUSED]);
2929 scr->window_title_texture[WS_UNFOCUSED] = *texture;
2931 if (scr->resizebar_texture[0]) {
2932 wTextureDestroy(scr, (WTexture*)scr->resizebar_texture[0]);
2934 scr->resizebar_texture[0]
2935 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_UNFOCUSED]->any.color);
2937 if (scr->geometry_display != None)
2938 XSetWindowBackground(dpy, scr->geometry_display,
2939 scr->resizebar_texture[0]->normal.pixel);
2941 return REFRESH_WINDOW_TEXTURES;
2945 static int
2946 setMenuTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2948 if (scr->menu_title_texture[0]) {
2949 wTextureDestroy(scr, scr->menu_title_texture[0]);
2951 scr->menu_title_texture[0] = *texture;
2953 return REFRESH_MENU_TEXTURES;
2957 static int
2958 setMenuTextBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2960 if (scr->menu_item_texture) {
2961 wTextureDestroy(scr, scr->menu_item_texture);
2962 wTextureDestroy(scr, (WTexture*)scr->menu_item_auxtexture);
2964 scr->menu_item_texture = *texture;
2966 scr->menu_item_auxtexture
2967 = wTextureMakeSolid(scr, &scr->menu_item_texture->any.color);
2969 return REFRESH_MENU_TEXTURES;
2973 static int
2974 setKeyGrab(WScreen *scr, WDefaultEntry *entry, WShortKey *shortcut, long index)
2976 WWindow *wwin;
2977 wKeyBindings[index] = *shortcut;
2979 wwin = scr->focused_window;
2981 while (wwin!=NULL) {
2982 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
2984 if (!wwin->window_flags.no_bind_keys) {
2985 wWindowSetKeyGrabs(wwin);
2987 wwin = wwin->prev;
2990 return 0;
2994 static int
2995 setIconPosition(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
2997 wArrangeIcons(scr, True);
2999 return 0;
3005 * Very ugly kluge.
3006 * Need access to the double click variables, so that all widgets in
3007 * wmaker panels will have the same dbl-click values.
3008 * TODO: figure a better way of dealing with it.
3010 #include "WINGsP.h"
3012 static int
3013 setDoubleClick(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
3015 extern _WINGsConfiguration WINGsConfiguration;
3017 if (*value <= 0)
3018 *(int*)foo = 1;
3020 WINGsConfiguration.doubleClickDelay = *value;
3022 return 0;