Initial revision
[wmaker-crm.git] / src / defaults.c
blob079ba17afb65787430a26f1d61c018f446f0cdca
1 /* defaults.c - manage configuration through defaults db
2 *
3 * WindowMaker 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;
100 /* type converters */
101 static int getBool();
102 static int getInt();
103 static int getCoord();
104 #if 0
105 /* this is not used yet */
106 static int getString();
107 #endif
108 static int getPathList();
109 static int getFocusMode();
110 static int getPlacement();
111 static int getGeomDisp();
112 static int getTexture();
113 static int getWSBackground();
114 static int getJust();
115 static int getFont();
116 static int getColor();
117 static int getKeybind();
118 static int getModMask();
119 static int getSpeed();
120 static int getMButton();
121 static int getIconPosition();
122 static int getIconificationStyle();
124 /* value setting functions */
125 static int setJustify();
126 static int setIfDockPresent();
127 static int setStickyIcons();
129 static int setPositive();
131 static int setWidgetColor();
132 static int setIconTile();
133 static int setWinTitleFont();
134 static int setMenuTitleFont();
135 static int setMenuTextFont();
136 static int setIconTitleFont();
137 static int setDisplayFont();
138 static int setWTitleColor();
139 static int setFTitleBack();
140 static int setPTitleBack();
141 static int setUTitleBack();
142 static int setWorkspaceBack();
143 static int setMenuTitleColor();
144 static int setMenuTextColor();
145 static int setMenuDisabledColor();
146 static int setMenuTitleBack();
147 static int setMenuTextBack();
148 static int setHightlight();
149 static int setHightlightText();
150 static int setKeyGrab();
151 static int setDoubleClick();
152 static int setIconPosition();
154 static int setClipTitleFont();
155 static int setClipTitleColor();
160 * All entries in the tables bellow, NEED to have a default value
161 * defined, and this value needs to be correct.
164 /* these options will only affect the window manager on startup
166 * static defaults can't access the screen data, because it is
167 * created after these defaults are read
169 WDefaultEntry staticOptionList[] = {
171 {"DisableDithering", "NO", NULL,
172 &wPreferences.no_dithering, getBool, NULL
174 {"ColormapSize", "4", NULL,
175 &wPreferences.cmap_size, getInt, NULL
177 /* static by laziness */
178 {"IconSize", "64", NULL,
179 &wPreferences.icon_size, getInt, NULL
181 {"ModifierKey", "Mod1", NULL,
182 &wPreferences.modifier_mask, getModMask, NULL
184 {"DisableWSMouseActions", "NO", NULL,
185 &wPreferences.disable_root_mouse, getBool, NULL
187 {"FocusMode", "manual", (void*)False,
188 &wPreferences.focus_mode, getFocusMode, NULL
189 }, /* have a problem when switching from manual to sloppy without restart */
190 {"NewStyle", "NO", NULL,
191 &wPreferences.new_style, getBool, NULL
193 {"DisableDock", "NO", (void*) WM_DOCK,
194 NULL, getBool, setIfDockPresent
196 {"DisableClip", "NO", (void*) WM_CLIP,
197 NULL, getBool, setIfDockPresent
203 WDefaultEntry optionList[] = {
204 /* dynamic options */
205 {"IconPosition", "blh", NULL,
206 &wPreferences.icon_yard, getIconPosition, setIconPosition
208 {"IconificationStyle", "Zoom", NULL,
209 &wPreferences.iconification_style, getIconificationStyle, NULL
211 {"SelectWindowsMouseButton", "Left", NULL,
212 &wPreferences.select_button, getMButton, NULL
214 {"WindowListMouseButton", "Middle", NULL,
215 &wPreferences.windowl_button, getMButton, NULL
217 {"ApplicationMenuMouseButton", "Right", NULL,
218 &wPreferences.menu_button, getMButton, NULL
220 {"PixmapPath", DEF_PIXMAP_PATHS, NULL,
221 &wPreferences.pixmap_path, getPathList, NULL
223 {"IconPath", DEF_ICON_PATHS, NULL,
224 &wPreferences.icon_path, getPathList, NULL
226 {"ColormapMode", "auto", (void*)True,
227 &wPreferences.colormap_mode, getFocusMode, NULL
229 {"AutoFocus", "NO", NULL,
230 &wPreferences.auto_focus, getBool, NULL
232 {"RaiseDelay", "0", NULL,
233 &wPreferences.raise_delay, getInt, NULL
235 {"CirculateRaise", "NO", NULL,
236 &wPreferences.circ_raise, getBool, NULL
238 {"Superfluous", "NO", NULL,
239 &wPreferences.superfluous, getBool, NULL
241 {"AdvanceToNewWorkspace", "NO", NULL,
242 &wPreferences.ws_advance, getBool, NULL
244 {"CycleWorkspaces", "NO", NULL,
245 &wPreferences.ws_cycle, getBool, NULL
247 {"StickyIcons", "NO", NULL,
248 &wPreferences.sticky_icons, getBool, setStickyIcons
250 {"SaveSessionOnExit", "NO", NULL,
251 &wPreferences.save_session_on_exit, getBool, NULL
253 {"WrapMenus", "NO", NULL,
254 &wPreferences.wrap_menus, getBool, NULL
256 {"ScrollableMenus", "NO", NULL,
257 &wPreferences.scrollable_menus, getBool, NULL
259 {"MenuScrollSpeed", "medium", NULL,
260 &wPreferences.menu_scroll_speed, getSpeed, NULL
262 {"IconSlideSpeed", "medium", NULL,
263 &wPreferences.icon_slide_speed, getSpeed, NULL
265 {"ShadeSpeed", "medium", NULL,
266 &wPreferences.shade_speed, getSpeed, NULL
268 {"DoubleClickTime", "250", (void*) &wPreferences.dblclick_time,
269 &wPreferences.dblclick_time, getInt, setDoubleClick,
271 {"AlignSubmenus", "NO", NULL,
272 &wPreferences.align_menus, getBool, NULL
274 {"OnTopTransients", "NO", NULL,
275 &wPreferences.on_top_transients, getBool, NULL
277 {"WindowPlacement", "auto", NULL,
278 &wPreferences.window_placement, getPlacement, NULL
280 {"IgnoreFocusClick","NO", NULL,
281 &wPreferences.ignore_focus_click, getBool, NULL
283 {"UseSaveUnders", "NO", NULL,
284 &wPreferences.use_saveunders, getBool, NULL
286 {"OpaqueMove", "NO", NULL,
287 &wPreferences.opaque_move, getBool, NULL
289 {"DisableSound", "NO", NULL,
290 &wPreferences.no_sound, getBool, NULL
292 {"DisableAnimations", "NO", NULL,
293 &wPreferences.no_animations, getBool, NULL
295 {"DontLinkWorkspaces","NO", NULL,
296 &wPreferences.no_autowrap, getBool, NULL
298 {"EdgeResistance", "0", NULL,
299 &wPreferences.edge_resistance,getInt, NULL
301 {"AutoArrangeIcons", "NO", NULL,
302 &wPreferences.auto_arrange_icons, getBool, NULL
304 {"NoWindowUnderDock", "NO", NULL,
305 &wPreferences.no_window_under_dock, getBool, NULL
307 {"NoWindowOverIcons", "NO", NULL,
308 &wPreferences.no_window_over_icons, getBool, NULL
310 {"WindowPlaceOrigin", "(0, 0)", NULL,
311 &wPreferences.window_place_origin, getCoord, NULL
313 {"ResizeDisplay", "corner", NULL,
314 &wPreferences.size_display, getGeomDisp, NULL
316 {"MoveDisplay", "corner", NULL,
317 &wPreferences.move_display, getGeomDisp, NULL
319 {"DontConfirmKill", "NO", NULL,
320 &wPreferences.dont_confirm_kill, getBool,NULL
322 {"WindowTitleBalloons", "NO", NULL,
323 &wPreferences.window_balloon, getBool, NULL
325 {"MiniwindowTitleBalloons", "NO", NULL,
326 &wPreferences.miniwin_balloon,getBool, NULL
328 {"AppIconBalloons", "NO", NULL,
329 &wPreferences.appicon_balloon,getBool, NULL
331 {"DisableBlinking", "NO", NULL,
332 &wPreferences.dont_blink, getBool, NULL
334 /* style options */
335 {"WidgetColor", "(solid, gray)", NULL,
336 NULL, getTexture, setWidgetColor,
338 {"WorkspaceBack", "(solid, black)", NULL,
339 NULL, getWSBackground,setWorkspaceBack
341 {"IconBack", "(solid, gray)", NULL,
342 NULL, getTexture, setIconTile
344 {"TitleJustify", "center", NULL,
345 &wPreferences.title_justification, getJust, setJustify
347 {"WindowTitleFont", DEF_TITLE_FONT, NULL,
348 NULL, getFont, setWinTitleFont
350 {"MenuTitleFont", DEF_MENU_TITLE_FONT, NULL,
351 NULL, getFont, setMenuTitleFont
353 {"MenuTextFont", DEF_MENU_ENTRY_FONT, NULL,
354 NULL, getFont, setMenuTextFont
356 {"IconTitleFont", DEF_ICON_TITLE_FONT, NULL,
357 NULL, getFont, setIconTitleFont
359 {"ClipTitleFont", DEF_CLIP_TITLE_FONT, NULL,
360 NULL, getFont, setClipTitleFont
362 {"DisplayFont", DEF_INFO_TEXT_FONT, NULL,
363 NULL, getFont, setDisplayFont
365 {"HighlightColor", "white", NULL,
366 NULL, getColor, setHightlight
368 {"HighlightTextColor", "black", NULL,
369 NULL, getColor, setHightlightText
371 {"ClipTitleColor", "black", (void*)CLIP_NORMAL,
372 NULL, getColor, setClipTitleColor
374 {"CClipTitleColor", "\"#454045\"", (void*)CLIP_COLLAPSED,
375 NULL, getColor, setClipTitleColor
377 {"FTitleColor", "white", (void*)WS_FOCUSED,
378 NULL, getColor, setWTitleColor
380 {"PTitleColor", "white", (void*)WS_PFOCUSED,
381 NULL, getColor, setWTitleColor
383 {"UTitleColor", "black", (void*)WS_UNFOCUSED,
384 NULL, getColor, setWTitleColor
386 {"FTitleBack", "(solid, black)", NULL,
387 NULL, getTexture, setFTitleBack
389 {"PTitleBack", "(solid, \"#616161\")", NULL,
390 NULL, getTexture, setPTitleBack
392 {"UTitleBack", "(solid, gray)", NULL,
393 NULL, getTexture, setUTitleBack
395 {"MenuTitleColor", "white", NULL,
396 NULL, getColor, setMenuTitleColor
398 {"MenuTextColor", "black", NULL,
399 NULL, getColor, setMenuTextColor
401 {"MenuDisabledColor", "\"#616161\"", NULL,
402 NULL, getColor, setMenuDisabledColor
404 {"MenuTitleBack", "(solid, black)", NULL,
405 NULL, getTexture, setMenuTitleBack
407 {"MenuTextBack", "(solid, gray)", NULL,
408 NULL, getTexture, setMenuTextBack
411 /* keybindings */
412 {"RootMenuKey", "None", (void*)WKBD_ROOTMENU,
413 NULL, getKeybind, setKeyGrab
415 {"WindowListKey", "None", (void*)WKBD_WINDOWLIST,
416 NULL, getKeybind, setKeyGrab
418 {"WindowMenuKey", "None", (void*)WKBD_WINDOWMENU,
419 NULL, getKeybind, setKeyGrab
421 {"ClipLowerKey", "None", (void*)WKBD_CLIPLOWER,
422 NULL, getKeybind, setKeyGrab
424 {"ClipRaiseKey", "None", (void*)WKBD_CLIPRAISE,
425 NULL, getKeybind, setKeyGrab
427 {"ClipRaiseLowerKey", "None", (void*)WKBD_CLIPRAISELOWER,
428 NULL, getKeybind, setKeyGrab
430 {"MiniaturizeKey", "None", (void*)WKBD_MINIATURIZE,
431 NULL, getKeybind, setKeyGrab
433 {"HideKey", "None", (void*)WKBD_HIDE,
434 NULL, getKeybind, setKeyGrab
436 {"CloseKey", "None", (void*)WKBD_CLOSE,
437 NULL, getKeybind, setKeyGrab
439 {"MaximizeKey", "None", (void*)WKBD_MAXIMIZE,
440 NULL, getKeybind, setKeyGrab
442 {"VMaximizeKey", "None", (void*)WKBD_VMAXIMIZE,
443 NULL, getKeybind, setKeyGrab
445 {"RaiseKey", "Meta+Up", (void*)WKBD_RAISE,
446 NULL, getKeybind, setKeyGrab
448 {"LowerKey", "Meta+Down", (void*)WKBD_LOWER,
449 NULL, getKeybind, setKeyGrab
451 {"RaiseLowerKey", "None", (void*)WKBD_RAISELOWER,
452 NULL, getKeybind, setKeyGrab
454 {"ShadeKey", "None", (void*)WKBD_SHADE,
455 NULL, getKeybind, setKeyGrab
457 {"SelectKey", "None", (void*)WKBD_SELECT,
458 NULL, getKeybind, setKeyGrab
460 {"FocusNextKey", "None", (void*)WKBD_FOCUSNEXT,
461 NULL, getKeybind, setKeyGrab
463 {"FocusPrevKey", "None", (void*)WKBD_FOCUSPREV,
464 NULL, getKeybind, setKeyGrab
466 {"NextWorkspaceKey", "None", (void*)WKBD_NEXTWORKSPACE,
467 NULL, getKeybind, setKeyGrab
469 {"PrevWorkspaceKey", "None", (void*)WKBD_PREVWORKSPACE,
470 NULL, getKeybind, setKeyGrab
472 {"NextWorkspaceLayerKey", "None", (void*)WKBD_NEXTWSLAYER,
473 NULL, getKeybind, setKeyGrab
475 {"PrevWorkspaceLayerKey", "None", (void*)WKBD_PREVWSLAYER,
476 NULL, getKeybind, setKeyGrab
478 {"Workspace1Key", "None", (void*)WKBD_WORKSPACE1,
479 NULL, getKeybind, setKeyGrab
481 {"Workspace2Key", "None", (void*)WKBD_WORKSPACE2,
482 NULL, getKeybind, setKeyGrab
484 {"Workspace3Key", "None", (void*)WKBD_WORKSPACE3,
485 NULL, getKeybind, setKeyGrab
487 {"Workspace4Key", "None", (void*)WKBD_WORKSPACE4,
488 NULL, getKeybind, setKeyGrab
490 {"Workspace5Key", "None", (void*)WKBD_WORKSPACE5,
491 NULL, getKeybind, setKeyGrab
493 {"Workspace6Key", "None", (void*)WKBD_WORKSPACE6,
494 NULL, getKeybind, setKeyGrab
496 {"Workspace7Key", "None", (void*)WKBD_WORKSPACE7,
497 NULL, getKeybind, setKeyGrab
499 {"Workspace8Key", "None", (void*)WKBD_WORKSPACE8,
500 NULL, getKeybind, setKeyGrab
502 {"Workspace9Key", "None", (void*)WKBD_WORKSPACE9,
503 NULL, getKeybind, setKeyGrab
505 {"Workspace10Key", "None", (void*)WKBD_WORKSPACE10,
506 NULL, getKeybind, setKeyGrab
512 /* Option names */
513 static proplist_t DCenter, DCorner, DFloating, DLine;
514 static proplist_t JLeft, JCenter, JRight;
516 #if 0
517 static void rereadDefaults(void);
518 #endif
520 #if 0
521 static void
522 rereadDefaults(void)
524 /* must defer the update because accessing X data from a
525 * signal handler can mess up Xlib */
528 #endif
530 static void
531 initDefaults()
533 int i;
534 WDefaultEntry *entry;
536 PLSetStringCmpHook(StringCompareHook);
538 DCenter = PLMakeString("Center");
539 DCorner = PLMakeString("Corner");
540 DFloating = PLMakeString("Floating");
541 DLine = PLMakeString("Line");
543 JLeft = PLMakeString("Left");
544 JCenter = PLMakeString("Center");
545 JRight = PLMakeString("Right");
547 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
548 entry = &optionList[i];
550 entry->plkey = PLMakeString(entry->key);
551 if (entry->default_value)
552 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
553 else
554 entry->plvalue = NULL;
557 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
558 entry = &staticOptionList[i];
560 entry->plkey = PLMakeString(entry->key);
561 if (entry->default_value)
562 entry->plvalue = PLGetProplistWithDescription(entry->default_value);
563 else
564 entry->plvalue = NULL;
568 wDomainName = PLMakeString(WMDOMAIN_NAME);
569 wAttributeDomainName = PLMakeString(WMATTRIBUTE_DOMAIN_NAME);
571 PLRegister(wDomainName, rereadDefaults);
572 PLRegister(wAttributeDomainName, rereadDefaults);
579 #if 0
580 proplist_t
581 wDefaultsInit(int screen_number)
583 static int defaults_inited = 0;
584 proplist_t dict;
586 if (!defaults_inited) {
587 initDefaults();
590 dict = PLGetDomain(wDomainName);
591 if (!dict) {
592 wwarning(_("could not read domain \"%s\" from defaults database"),
593 PLGetString(wDomainName));
596 return dict;
598 #endif
601 void
602 wDefaultsDestroyDomain(WDDomain *domain)
604 if (domain->dictionary)
605 PLRelease(domain->dictionary);
606 free(domain->path);
607 free(domain);
611 WDDomain*
612 wDefaultsInitDomain(char *domain, Bool requireDictionary)
614 WDDomain *db;
615 struct stat stbuf;
616 static int inited = 0;
617 char path[PATH_MAX];
618 char *the_path;
619 proplist_t shared_dict=NULL;
621 if (!inited) {
622 inited = 1;
623 initDefaults();
626 db = wmalloc(sizeof(WDDomain));
627 memset(db, 0, sizeof(WDDomain));
628 db->domain_name = domain;
629 db->path = wdefaultspathfordomain(domain);
630 the_path = db->path;
632 if (the_path && stat(the_path, &stbuf)>=0) {
633 db->dictionary = ReadProplistFromFile(the_path);
634 if (db->dictionary) {
635 if (requireDictionary && !PLIsDictionary(db->dictionary)) {
636 PLRelease(db->dictionary);
637 db->dictionary = NULL;
638 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
639 domain, the_path);
641 db->timestamp = stbuf.st_mtime;
642 } else {
643 wwarning(_("could not load domain %s from user defaults database"),
644 domain);
648 /* global system dictionary */
649 sprintf(path, "%s/%s/%s", PKGDATADIR, DEFAULTS_DIR, domain);
650 if (stat(path, &stbuf)>=0) {
651 shared_dict = ReadProplistFromFile(path);
652 if (shared_dict) {
653 if (requireDictionary && !PLIsDictionary(shared_dict)) {
654 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
655 domain, path);
656 PLRelease(shared_dict);
657 shared_dict = NULL;
658 } else {
659 if (db->dictionary && PLIsDictionary(shared_dict) &&
660 PLIsDictionary(db->dictionary)) {
661 PLMergeDictionaries(shared_dict, db->dictionary);
662 PLRelease(db->dictionary);
663 db->dictionary = shared_dict;
664 if (stbuf.st_mtime > db->timestamp)
665 db->timestamp = stbuf.st_mtime;
666 } else if (!db->dictionary) {
667 db->dictionary = shared_dict;
668 if (stbuf.st_mtime > db->timestamp)
669 db->timestamp = stbuf.st_mtime;
672 } else {
673 wwarning(_("could not load domain %s from global defaults database"),
674 domain);
678 /* set to save it in user's directory, no matter from where it was read */
679 if (db->dictionary) {
680 proplist_t tmp = PLMakeString(db->path);
682 PLSetFilename(db->dictionary, tmp);
683 PLRelease(tmp);
686 return db;
690 void
691 wReadStaticDefaults(proplist_t dict)
693 proplist_t plvalue;
694 WDefaultEntry *entry;
695 int i;
696 void *tdata;
699 for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
700 entry = &staticOptionList[i];
702 if (dict)
703 plvalue = PLGetDictionaryEntry(dict, entry->plkey);
704 else
705 plvalue = NULL;
707 if (!plvalue) {
708 /* no default in the DB. Use builtin default */
709 plvalue = entry->plvalue;
712 if (plvalue) {
713 /* convert data */
714 (*entry->convert)(NULL, entry, plvalue, entry->addr, &tdata);
715 if (entry->update) {
716 (*entry->update)(NULL, entry, tdata, entry->extra_data);
722 void
723 wDefaultsCheckDomains(void *foo)
725 WScreen *scr;
726 struct stat stbuf;
727 proplist_t dict;
728 int i;
729 char path[PATH_MAX];
731 #ifdef HEARTBEAT
732 puts("Checking domains...");
733 #endif
734 if (stat(WDWindowMaker->path, &stbuf)>=0
735 && WDWindowMaker->timestamp < stbuf.st_mtime) {
736 proplist_t shared_dict = NULL;
737 #ifdef HEARTBEAT
738 puts("Checking WindowMaker domain");
739 #endif
740 WDWindowMaker->timestamp = stbuf.st_mtime;
742 /* global dictionary */
743 sprintf(path, "%s/%s/WindowMaker", PKGDATADIR, DEFAULTS_DIR);
744 if (stat(path, &stbuf)>=0) {
745 shared_dict = ReadProplistFromFile(path);
746 if (shared_dict && !PLIsDictionary(shared_dict)) {
747 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
748 "WindowMaker", path);
749 PLRelease(shared_dict);
750 shared_dict = NULL;
751 } else if (!shared_dict) {
752 wwarning(_("could not load domain %s from global defaults database"),
753 "WindowMaker");
756 /* user dictionary */
757 dict = ReadProplistFromFile(WDWindowMaker->path);
758 if (dict) {
759 if (!PLIsDictionary(dict)) {
760 PLRelease(dict);
761 dict = NULL;
762 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
763 "WindowMaker", WDWindowMaker->path);
764 } else {
765 if (shared_dict) {
766 PLSetFilename(shared_dict, PLGetFilename(dict));
767 PLMergeDictionaries(shared_dict, dict);
768 PLRelease(dict);
769 dict = shared_dict;
770 shared_dict = NULL;
772 for (i=0; i<wScreenCount; i++) {
773 scr = wScreenWithNumber(i);
774 if (scr)
775 wReadDefaults(scr, dict);
777 if (WDWindowMaker->dictionary) {
778 PLRelease(WDWindowMaker->dictionary);
780 WDWindowMaker->dictionary = dict;
782 } else {
783 wwarning(_("could not load domain %s from user defaults database"),
784 "WindowMaker");
786 if (shared_dict) {
787 PLRelease(shared_dict);
791 if (stat(WDWindowAttributes->path, &stbuf)>=0
792 && WDWindowAttributes->timestamp < stbuf.st_mtime) {
793 #ifdef HEARTBEAT
794 puts("Checking WMWindowAttributes domain");
795 #endif
796 dict = ReadProplistFromFile(WDWindowAttributes->path);
797 if (dict) {
798 if (!PLIsDictionary(dict)) {
799 PLRelease(dict);
800 dict = NULL;
801 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
802 "WMWindowAttributes", WDWindowAttributes->path);
803 } else {
804 if (WDWindowAttributes->dictionary)
805 PLRelease(WDWindowAttributes->dictionary);
806 WDWindowAttributes->dictionary = dict;
807 for (i=0; i<wScreenCount; i++) {
808 scr = wScreenWithNumber(i);
809 if (scr)
810 wDefaultUpdateIcons(scr);
813 } else {
814 wwarning(_("could not load domain %s from user defaults database"),
815 "WMWindowAttributes");
817 WDWindowAttributes->timestamp = stbuf.st_mtime;
821 if (stat(WDRootMenu->path, &stbuf)>=0
822 && WDRootMenu->timestamp < stbuf.st_mtime) {
823 dict = ReadProplistFromFile(WDRootMenu->path);
824 #ifdef HEARTBEAT
825 puts("Checking WMRootMenu domain");
826 #endif
827 if (dict) {
828 if (!PLIsArray(dict) && !PLIsString(dict)) {
829 PLRelease(dict);
830 dict = NULL;
831 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
832 "WMRootMenu", WDRootMenu->path);
833 } else {
834 if (WDRootMenu->dictionary) {
835 PLRelease(WDRootMenu->dictionary);
837 WDRootMenu->dictionary = dict;
839 } else {
840 wwarning(_("could not load domain %s from user defaults database"),
841 "WMRootMenu");
843 WDRootMenu->timestamp = stbuf.st_mtime;
846 WMAddTimerHandler(DEFAULTS_CHECK_INTERVAL, wDefaultsCheckDomains, foo);
851 #define REFRESH_WINDOW_TEXTURES (1<<0)
852 #define REFRESH_MENU_TEXTURES (1<<1)
853 #define REFRESH_WINDOW_FONT (1<<2)
854 #define REFRESH_MENU_TITLE_FONT (1<<3)
855 #define REFRESH_MENU_FONT (1<<4)
856 #define REFRESH_FORE_COLOR (1<<5)
857 #define REFRESH_ICON_TILE (1<<6)
858 #define REFRESH_ICON_FONT (1<<7)
859 #define REFRESH_WORKSPACE_BACK (1<<8)
861 static void
862 refreshMenus(WScreen *scr, int flags)
864 WMenu *menu;
866 menu = scr->root_menu;
867 if (menu)
868 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
870 menu = scr->workspace_menu;
871 if (menu)
872 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
874 menu = scr->switch_menu;
875 if (menu)
876 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
878 menu = scr->window_menu;
879 if (menu)
880 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
882 menu = scr->icon_menu;
883 if (menu)
884 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
886 if (scr->dock) {
887 menu = scr->dock->menu;
888 if (menu)
889 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
891 menu = scr->clip_menu;
892 if (menu)
893 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
895 menu = scr->clip_submenu;
896 if (menu)
897 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
899 menu = scr->clip_options;
900 if (menu)
901 wMenuRefresh(!menu->flags.brother ? menu : menu->brother, flags);
905 static void
906 refreshAppIcons(WScreen *scr, int flags)
908 WAppIcon *aicon = scr->app_icon_list;
910 while (aicon) {
911 if (aicon->icon) {
912 aicon->icon->force_paint = 1;
914 aicon = aicon->next;
919 static void
920 refreshWindows(WScreen *scr, int flags)
922 WWindow *wwin;
924 wwin = scr->focused_window;
925 while (wwin) {
926 if (flags & REFRESH_WINDOW_FONT) {
927 wWindowConfigureBorders(wwin);
929 if ((flags & (REFRESH_ICON_TILE|REFRESH_WINDOW_TEXTURES)) &&
930 wwin->flags.miniaturized && wwin->icon) {
931 wwin->icon->force_paint = 1;
933 if (flags & REFRESH_WINDOW_TEXTURES) {
934 wwin->frame->flags.need_texture_remake = 1;
936 wwin = wwin->prev;
941 void
942 wReadDefaults(WScreen *scr, proplist_t new_dict)
944 proplist_t plvalue, old_value;
945 WDefaultEntry *entry;
946 int i, changed, must_update;
947 int needs_refresh;
948 void *tdata;
949 proplist_t old_dict = (WDWindowMaker->dictionary!=new_dict
950 ? WDWindowMaker->dictionary : NULL);
952 changed = 0;
953 must_update = 0;
955 needs_refresh = 0;
957 for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
958 entry = &optionList[i];
960 if (new_dict)
961 plvalue = PLGetDictionaryEntry(new_dict, entry->plkey);
962 else
963 plvalue = NULL;
965 if (!old_dict)
966 old_value = NULL;
967 else
968 old_value = PLGetDictionaryEntry(old_dict, entry->plkey);
971 if (!plvalue && !old_value) {
972 /* no default in the DB. Use builtin default */
973 plvalue = entry->plvalue;
974 if (plvalue && new_dict) {
975 PLInsertDictionaryEntry(new_dict, entry->plkey, plvalue);
976 changed = 1;
977 must_update = 1;
979 } else if (!plvalue) {
980 /* value was deleted from DB. Keep current value */
981 continue;
982 } else if (!old_value) {
983 /* set value for the 1st time */
984 changed = 1;
985 } else if (!PLIsEqual(plvalue, old_value)) {
986 /* value has changed */
987 changed = 1;
988 } else {
989 /* value was not changed since last time */
990 continue;
993 if (plvalue) {
994 #ifdef DEBUG
995 printf("Updating %s to %s\n", entry->key, PLGetDescription(plvalue));
996 #endif
997 /* convert data */
998 if ((*entry->convert)(scr, entry, plvalue, entry->addr, &tdata)) {
999 if (entry->update) {
1000 needs_refresh |=
1001 (*entry->update)(scr, entry, tdata, entry->extra_data);
1007 if (needs_refresh!=0) {
1008 int foo;
1010 foo = 0;
1011 if (needs_refresh & REFRESH_MENU_TEXTURES)
1012 foo |= MR_TEXT_BACK;
1013 if (needs_refresh & REFRESH_MENU_FONT)
1014 foo |= MR_RESIZED;
1015 if (needs_refresh & REFRESH_MENU_TITLE_FONT)
1016 foo |= MR_TITLE_TEXT;
1018 if (foo)
1019 refreshMenus(scr, foo);
1021 if (needs_refresh & (REFRESH_WINDOW_TEXTURES|REFRESH_WINDOW_FONT|
1022 REFRESH_ICON_TILE))
1023 refreshWindows(scr, needs_refresh);
1025 if (needs_refresh & REFRESH_ICON_TILE)
1026 refreshAppIcons(scr, needs_refresh);
1028 #ifdef EXPERIMENTAL
1029 if (needs_refresh & REFRESH_WORKSPACE_BACK) {
1030 WWorkspaceTexture *wsback;
1032 /* update the background for the workspace */
1033 if (scr->current_workspace < scr->wspaceTextureCount
1034 && scr->wspaceTextures[scr->current_workspace]) {
1035 wsback = scr->wspaceTextures[scr->current_workspace];
1036 } else {
1037 wsback = scr->defaultTexure;
1039 if (wsback) {
1040 if (wsback->pixmap!=None) {
1041 XSetWindowBackgroundPixmap(dpy, scr->root_win,
1042 wsback->pixmap);
1043 } else {
1044 XSetWindowBackground(dpy, scr->root_win, wsback->solid);
1046 XClearWindow(dpy, scr->root_win);
1047 XFlush(dpy);
1050 #endif /* !EXPERIMENTAL */
1051 wRefreshDesktop(scr);
1056 void
1057 wDefaultUpdateIcons(WScreen *scr)
1059 WAppIcon *aicon = scr->app_icon_list;
1060 WWindow *wwin = scr->focused_window;
1061 char *file;
1063 while(aicon) {
1064 file = wDefaultGetIconFile(scr, aicon->wm_instance, aicon->wm_class,
1065 False);
1066 if ((file && aicon->icon->file && strcmp(file, aicon->icon->file)!=0)
1067 || (file && !aicon->icon->file)) {
1068 RImage *new_image;
1070 if (aicon->icon->file)
1071 free(aicon->icon->file);
1072 aicon->icon->file = wstrdup(file);
1074 new_image = wDefaultGetImage(scr, aicon->wm_instance,
1075 aicon->wm_class);
1076 if (new_image) {
1077 wIconChangeImage(aicon->icon, new_image);
1078 wAppIconPaint(aicon);
1081 aicon = aicon->next;
1084 if (!wPreferences.flags.noclip)
1085 wClipIconPaint(scr->clip_icon);
1087 while (wwin) {
1088 if (wwin->icon && wwin->flags.miniaturized) {
1089 file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
1090 False);
1091 if ((file && wwin->icon->file && strcmp(file, wwin->icon->file)!=0)
1092 || (file && !wwin->icon->file)) {
1093 RImage *new_image;
1095 if (wwin->icon->file)
1096 free(wwin->icon->file);
1097 wwin->icon->file = wstrdup(file);
1099 new_image = wDefaultGetImage(scr, wwin->wm_instance,
1100 wwin->wm_class);
1101 if (new_image)
1102 wIconChangeImage(wwin->icon, new_image);
1105 wwin = wwin->prev;
1110 /* --------------------------- Local ----------------------- */
1112 #define STRINGP(x) if (!PLIsString(value)) { \
1113 wwarning(_("Wrong option format for key \"%s\". Should be %s."), \
1114 PLGetString(entry->plkey), x); \
1115 return False; }
1118 * value - is the value in the defaults DB
1119 * addr - is the address to store the data
1120 * ret - is the address to store a pointer to a temporary buffer. ret
1121 * must not be freed and is used by the set functions
1123 static int
1124 getBool(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1125 void **ret)
1127 static char data;
1128 char *val;
1129 int second_pass=0;
1131 STRINGP("Boolean");
1133 val = PLGetString(value);
1135 again:
1136 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
1137 || strcasecmp(val, "YES")==0) {
1139 data = 1;
1140 } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
1141 || strcasecmp(val, "NO")==0) {
1142 data = 0;
1143 } else {
1144 int i;
1145 if (sscanf(val, "%i", &i)==1) {
1146 if (i!=0)
1147 data = 1;
1148 else
1149 data = 0;
1150 } else {
1151 wwarning(_("can't convert \"%s\" to boolean for key \"%s\""),
1152 val, PLGetString(entry->plkey));
1153 if (second_pass==0) {
1154 val = PLGetString(entry->plvalue);
1155 second_pass = 1;
1156 wwarning(_("using default \"%s\" instead"), val);
1157 goto again;
1159 return False;
1163 if (ret)
1164 *ret = &data;
1166 if (addr) {
1167 *(char*)addr = data;
1170 return True;
1174 static int
1175 getInt(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1176 void **ret)
1178 static int data;
1179 char *val;
1182 STRINGP("Integer");
1184 val = PLGetString(value);
1186 if (sscanf(val, "%i", &data)!=1) {
1187 wwarning(_("can't convert \"%s\" to integer for key \"%s\""),
1188 val, PLGetString(entry->plkey));
1189 val = PLGetString(entry->plvalue);
1190 wwarning(_("using default \"%s\" instead"), val);
1191 if (sscanf(val, "%i", &data)!=1) {
1192 return False;
1196 if (ret)
1197 *ret = &data;
1199 if (addr) {
1200 *(int*)addr = data;
1202 return True;
1206 static int
1207 getCoord(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1208 void **ret)
1210 static WCoord data;
1211 char *val_x, *val_y;
1212 int nelem, changed=0;
1213 proplist_t elem_x, elem_y;
1215 again:
1216 if (!PLIsArray(value)) {
1217 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1218 PLGetString(entry->plkey), "Coordinate");
1219 if (changed==0) {
1220 value = entry->plvalue;
1221 changed = 1;
1222 wwarning(_("using default \"%s\" instead"), entry->default_value);
1223 goto again;
1225 return False;
1228 nelem = PLGetNumberOfElements(value);
1229 if (nelem != 2) {
1230 wwarning(_("Incorrect number of elements in array for key \"%s\"."),
1231 PLGetString(entry->plkey));
1232 if (changed==0) {
1233 value = entry->plvalue;
1234 changed = 1;
1235 wwarning(_("using default \"%s\" instead"), entry->default_value);
1236 goto again;
1238 return False;
1241 elem_x = PLGetArrayElement(value, 0);
1242 elem_y = PLGetArrayElement(value, 1);
1244 if (!elem_x || !elem_y || !PLIsString(elem_x) || !PLIsString(elem_y)) {
1245 wwarning(_("Wrong value for key \"%s\". Should be Coordinate."),
1246 PLGetString(entry->plkey));
1247 if (changed==0) {
1248 value = entry->plvalue;
1249 changed = 1;
1250 wwarning(_("using default \"%s\" instead"), entry->default_value);
1251 goto again;
1253 return False;
1256 val_x = PLGetString(elem_x);
1257 val_y = PLGetString(elem_y);
1259 if (sscanf(val_x, "%i", &data.x)!=1 || sscanf(val_y, "%i", &data.y)!=1) {
1260 wwarning(_("can't convert array to integers for \"%s\"."),
1261 PLGetString(entry->plkey));
1262 if (changed==0) {
1263 value = entry->plvalue;
1264 changed = 1;
1265 wwarning(_("using default \"%s\" instead"), entry->default_value);
1266 goto again;
1268 return False;
1271 if (data.x < 0)
1272 data.x = 0;
1273 else if (data.x > scr->scr_width/3)
1274 data.x = scr->scr_width/3;
1275 if (data.y < 0)
1276 data.y = 0;
1277 else if (data.y > scr->scr_height/3)
1278 data.y = scr->scr_height/3;
1280 if (ret)
1281 *ret = &data;
1283 if (addr) {
1284 *(WCoord*)addr = data;
1287 return True;
1291 #if 0
1292 /* This function is not used at the moment. */
1293 static int
1294 getString(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1295 void **ret)
1297 static char *data;
1299 STRINGP("String");
1301 data = PLGetString(value);
1303 if (!data) {
1304 data = PLGetString(entry->plvalue);
1305 if (!data)
1306 return False;
1309 if (ret)
1310 *ret = &data;
1312 if (addr)
1313 *(char**)addr = wstrdup(data);
1315 return True;
1317 #endif
1320 static int
1321 getPathList(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1322 void **ret)
1324 static char **data;
1325 int i, count;
1326 proplist_t d;
1327 int changed=0;
1329 again:
1330 if (!PLIsArray(value)) {
1331 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1332 PLGetString(entry->plkey), "an array of paths");
1333 if (changed==0) {
1334 value = entry->plvalue;
1335 changed = 1;
1336 wwarning(_("using default \"%s\" instead"), entry->default_value);
1337 goto again;
1339 return False;
1342 i = 0;
1343 count = PLGetNumberOfElements(value);
1344 if (count < 1) {
1345 if (changed==0) {
1346 value = entry->plvalue;
1347 changed = 1;
1348 wwarning(_("using default \"%s\" instead"), entry->default_value);
1349 goto again;
1351 return False;
1354 data = wmalloc(sizeof(char*)*(count+1));
1355 for (i=0; i<count; i++) {
1356 d = PLGetArrayElement(value, i);
1357 if (!d || !PLIsString(d)) {
1358 break;
1360 data[i] = wstrdup(PLGetString(d));
1362 data[i]=NULL;
1364 if (*(char***)addr!=NULL) {
1365 char **tmp = *(char***)addr;
1366 for (i=0; tmp[i]!=NULL; i++) {
1367 free(tmp[i]);
1369 free(tmp);
1371 *(char***)addr = data;
1373 return True;
1377 static int
1378 getFocusMode(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1379 void **ret)
1381 static char data;
1382 char *val;
1383 int second_pass=0;
1385 STRINGP("one of Manual, Auto or Sloppy");
1387 val = PLGetString(value);
1389 again:
1390 if (strcasecmp(val, "manual")==0 || strcasecmp(val, "clicktofocus")==0)
1391 data = WKF_CLICK;
1392 else if (strcasecmp(val, "auto")==0 || strcasecmp(val, "focusfollowsmouse")==0)
1393 data = WKF_POINTER;
1394 else if ((strcasecmp(val, "semiauto")==0 || strcasecmp(val, "sloppy")==0)
1395 && !(int)entry->extra_data)
1396 data = WKF_SLOPPY;
1397 else {
1398 if (!(int)entry->extra_data)
1399 wwarning(_("Invalid focus mode \"%s\". Should be Manual, "
1400 "Auto or Sloppy."), PLGetString(value));
1401 else
1402 wwarning(_("Invalid colormap focus mode \"%s\". Should be Manual or "
1403 "Auto."), PLGetString(value));
1404 if (second_pass==0) {
1405 val = PLGetString(entry->plvalue);
1406 second_pass = 1;
1407 wwarning(_("using default \"%s\" instead"), val);
1408 goto again;
1410 return False;
1413 if (ret)
1414 *ret = &data;
1416 if (addr)
1417 *(char*)addr = data;
1419 return True;
1423 static int
1424 getPlacement(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1425 void **ret)
1427 static char data;
1428 char *val;
1429 int second_pass=0;
1431 STRINGP("one of Auto, Cascade, Random or Manual");
1433 val = PLGetString(value);
1435 again:
1436 if (strcasecmp(val, "auto")==0 || strcasecmp(val, "smart")==0)
1437 data = WPM_SMART;
1438 else if (strcasecmp(val, "cascade")==0)
1439 data = WPM_CASCADE;
1440 else if (strcasecmp(val, "manual")==0)
1441 data = WPM_MANUAL;
1442 else if (strcasecmp(val, "random")==0)
1443 data = WPM_RANDOM;
1444 else {
1445 wwarning(_("Invalid window placement mode \"%s\". "
1446 "Should be Auto, Cascade, Random or Manual."),
1447 PLGetString(value));
1448 if (second_pass==0) {
1449 val = PLGetString(entry->plvalue);
1450 second_pass = 1;
1451 wwarning(_("using default \"%s\" instead"), val);
1452 goto again;
1454 return False;
1457 if (ret)
1458 *ret = &data;
1460 if (addr)
1461 *(char*)addr = data;
1463 return True;
1468 static int
1469 getGeomDisp(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1470 void **ret)
1472 static char data;
1473 int changed=0;
1475 STRINGP("one of Center, Corner, Floating or Line");
1477 again:
1478 if(PLIsEqual(value, DCenter))
1479 data = WDIS_CENTER;
1480 else if(PLIsEqual(value, DCorner))
1481 data = WDIS_TOPLEFT;
1482 else if(PLIsEqual(value, DFloating))
1483 data = WDIS_FRAME_CENTER;
1484 else if(PLIsEqual(value, DLine))
1485 data = WDIS_NEW;
1486 else {
1487 wwarning(_("Invalid geometry display type \"%s\". Should "
1488 "be Center, Corner, Floating or Line."),
1489 PLGetString(value));
1490 if (changed==0) {
1491 value = entry->plvalue;
1492 changed = 1;
1493 wwarning(_("using default \"%s\" instead"), entry->default_value);
1494 goto again;
1496 return False;
1499 if (ret)
1500 *ret = &data;
1502 if (addr)
1503 *(char*)addr = data;
1505 return True;
1509 static int
1510 getSpeed(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1511 void **ret)
1513 static int data;
1514 char *val;
1515 int second_pass=0;
1517 STRINGP("one of UltraFast, Fast, Medium, Slow or UltraSlow");
1519 val = PLGetString(value);
1521 again:
1523 if (strcasecmp(val, "ultrafast")==0)
1524 data = SPEED_ULTRAFAST;
1525 else if (strcasecmp(val, "fast")==0)
1526 data = SPEED_FAST;
1527 else if (strcasecmp(val, "medium")==0)
1528 data = SPEED_MEDIUM;
1529 else if (strcasecmp(val, "slow")==0)
1530 data = SPEED_SLOW;
1531 else if (strcasecmp(val, "ultraslow")==0)
1532 data = SPEED_ULTRASLOW;
1533 else {
1534 wwarning(_("Invalid speed \"%s\". Should be UltraFast, Fast, "
1535 "Medium, Slow or UltraSlow."), PLGetString(value));
1536 if (second_pass==0) {
1537 val = PLGetString(entry->plvalue);
1538 second_pass = 1;
1539 wwarning(_("using default \"%s\" instead"), val);
1540 goto again;
1542 return False;
1545 if (ret)
1546 *ret = &data;
1548 if (addr)
1549 *(int*)addr = data;
1551 return True;
1555 static int
1556 getMButton(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1557 void **ret)
1559 static char data;
1560 char *val;
1561 int second_pass=0;
1563 STRINGP("one of Left, Middle, Right or Button1 through Button5");
1565 val = PLGetString(value);
1567 again:
1568 if (strcasecmp(val, "left")==0 || strcasecmp(val, "button1")==0)
1569 data = Button1;
1570 else if (strcasecmp(val, "middle")==0 || strcasecmp(val, "button2")==0)
1571 data = Button2;
1572 else if (strcasecmp(val, "right")==0 || strcasecmp(val, "button3")==0)
1573 data = Button3;
1574 else if (strcasecmp(val, "button4")==0)
1575 data = Button4;
1576 else if (strcasecmp(val, "button5")==0)
1577 data = Button4;
1578 else {
1579 wwarning(_("Invalid mouse button \"%s\". "
1580 "Should be Left, Middle, Right or Button1 through Button5"),
1581 PLGetString(value));
1582 if (second_pass==0) {
1583 val = PLGetString(entry->plvalue);
1584 second_pass = 1;
1585 wwarning(_("using default \"%s\" instead"), val);
1586 goto again;
1588 return False;
1591 if (ret)
1592 *ret = &data;
1594 if (addr)
1595 *(char*)addr = data;
1597 return True;
1601 static int
1602 getIconificationStyle(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1603 void *addr, void **ret)
1605 static char data;
1606 char *val;
1607 int second_pass=0;
1609 STRINGP("one of Zoom, Twist, Flip or None");
1611 val = PLGetString(value);
1613 again:
1614 if (strcasecmp(val, "zoom")==0)
1615 data = WIS_ZOOM;
1616 else if (strcasecmp(val, "twist")==0)
1617 data = WIS_TWIST;
1618 else if (strcasecmp(val, "flip")==0)
1619 data = WIS_FLIP;
1620 else if (strcasecmp(val, "none")==0)
1621 data = WIS_NONE;
1622 else {
1623 wwarning(_("Invalid iconification style \"%s\". "
1624 "Should be Zoom, Twist, Flip or None"),
1625 PLGetString(value));
1626 if (second_pass==0) {
1627 val = PLGetString(entry->plvalue);
1628 second_pass = 1;
1629 wwarning(_("using default \"%s\" instead"), val);
1630 goto again;
1632 return False;
1635 if (ret)
1636 *ret = &data;
1638 if (addr)
1639 *(char*)addr = data;
1641 return True;
1648 * (solid <color>)
1649 * (hgradient <color> <color>)
1650 * (vgradient <color> <color>)
1651 * (dgradient <color> <color>)
1652 * (mhgradient <color> <color> ...)
1653 * (mvgradient <color> <color> ...)
1654 * (tpixmap <file> <color>)
1655 * (spixmap <file> <color>)
1656 * (cpixmap <file> <color>)
1659 static WTexture*
1660 parse_texture(WScreen *scr, proplist_t pl)
1662 proplist_t elem;
1663 char *val;
1664 int nelem;
1665 WTexture *texture=NULL;
1667 nelem = PLGetNumberOfElements(pl);
1668 if (nelem < 1)
1669 return NULL;
1672 elem = PLGetArrayElement(pl, 0);
1673 if (!elem || !PLIsString(elem))
1674 return NULL;
1675 val = PLGetString(elem);
1678 if (strcasecmp(val, "solid")==0) {
1679 XColor color;
1681 if (nelem != 2)
1682 return NULL;
1684 /* get color */
1686 elem = PLGetArrayElement(pl, 1);
1687 if (!elem || !PLIsString(elem))
1688 return NULL;
1689 val = PLGetString(elem);
1691 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1692 wwarning(_("\"%s\" is not a valid color name"), val);
1693 return NULL;
1696 texture = (WTexture*)wTextureMakeSolid(scr, &color);
1697 } else if (strcasecmp(val, "dgradient")==0
1698 || strcasecmp(val, "vgradient")==0
1699 || strcasecmp(val, "hgradient")==0) {
1700 XColor color1, color2;
1701 int type;
1703 if (nelem != 3) {
1704 wwarning(_("bad number of arguments in gradient specification"));
1705 return NULL;
1708 if (val[0]=='d' || val[0]=='D')
1709 type = WTEX_DGRADIENT;
1710 else if (val[0]=='h' || val[0]=='H')
1711 type = WTEX_HGRADIENT;
1712 else
1713 type = WTEX_VGRADIENT;
1716 /* get from color */
1717 elem = PLGetArrayElement(pl, 1);
1718 if (!elem || !PLIsString(elem))
1719 return NULL;
1720 val = PLGetString(elem);
1722 if (!XParseColor(dpy, scr->colormap, val, &color1)) {
1723 wwarning(_("\"%s\" is not a valid color name"), val);
1724 return NULL;
1727 /* get to color */
1728 elem = PLGetArrayElement(pl, 2);
1729 if (!elem || !PLIsString(elem)) {
1730 return NULL;
1732 val = PLGetString(elem);
1734 if (!XParseColor(dpy, scr->colormap, val, &color2)) {
1735 wwarning(_("\"%s\" is not a valid color name"), val);
1736 return NULL;
1739 texture = (WTexture*)wTextureMakeGradient(scr, type, &color1, &color2);
1741 } else if (strcasecmp(val, "mhgradient")==0
1742 || strcasecmp(val, "mvgradient")==0
1743 || strcasecmp(val, "mdgradient")==0) {
1744 XColor color;
1745 RColor **colors;
1746 int i, count;
1747 int type;
1749 if (nelem < 3) {
1750 wwarning(_("too few arguments in multicolor gradient specification"));
1751 return NULL;
1754 if (val[1]=='h' || val[1]=='H')
1755 type = WTEX_MHGRADIENT;
1756 else if (val[1]=='v' || val[1]=='V')
1757 type = WTEX_MVGRADIENT;
1758 else
1759 type = WTEX_MDGRADIENT;
1761 count = nelem-1;
1763 colors = wmalloc(sizeof(RColor*)*(count+1));
1765 for (i=0; i<count; i++) {
1766 elem = PLGetArrayElement(pl, i+1);
1767 if (!elem || !PLIsString(elem)) {
1768 for ( ; i>=0; --i) {
1769 free(colors[i]);
1771 free(colors);
1772 break;
1774 val = PLGetString(elem);
1776 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1777 wwarning(_("\"%s\" is not a valid color name"), val);
1778 for ( ; i>=0; --i) {
1779 free(colors[i]);
1781 free(colors);
1782 break;
1783 } else {
1784 colors[i] = wmalloc(sizeof(RColor));
1785 colors[i]->red = color.red >> 8;
1786 colors[i]->green = color.green >> 8;
1787 colors[i]->blue = color.blue >> 8;
1790 colors[i] = NULL;
1792 texture = (WTexture*)wTextureMakeMGradient(scr, type, colors);
1793 } else if (strcasecmp(val, "spixmap")==0 ||
1794 strcasecmp(val, "cpixmap")==0 ||
1795 strcasecmp(val, "tpixmap")==0) {
1796 XColor color;
1797 int type;
1799 if (nelem != 3)
1800 return NULL;
1802 if (val[0] == 's' || val[0] == 'S')
1803 type = WTP_SCALE;
1804 else if (val[0] == 'c' || val[0] == 'C')
1805 type = WTP_CENTER;
1806 else
1807 type = WTP_TILE;
1809 /* get color */
1810 elem = PLGetArrayElement(pl, 2);
1811 if (!elem || !PLIsString(elem)) {
1812 return NULL;
1814 val = PLGetString(elem);
1816 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1817 wwarning(_("\"%s\" is not a valid color name"), val);
1818 return NULL;
1821 /* file name */
1822 elem = PLGetArrayElement(pl, 1);
1823 if (!elem || !PLIsString(elem))
1824 return NULL;
1825 val = PLGetString(elem);
1827 texture = (WTexture*)wTextureMakePixmap(scr, type, val, &color);
1829 } else {
1830 return NULL;
1832 return texture;
1837 static int
1838 getTexture(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
1839 void **ret)
1841 static WTexture *texture;
1842 int changed=0;
1844 again:
1845 if (!PLIsArray(value)) {
1846 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1847 PLGetString(entry->plkey), "Texture");
1848 if (changed==0) {
1849 value = entry->plvalue;
1850 changed = 1;
1851 wwarning(_("using default \"%s\" instead"), entry->default_value);
1852 goto again;
1854 return False;
1857 texture = parse_texture(scr, value);
1859 if (!texture) {
1860 wwarning(_("Error in texture specification for key \"%s\""),
1861 PLGetString(entry->plkey));
1862 if (changed==0) {
1863 value = entry->plvalue;
1864 changed = 1;
1865 wwarning(_("using default \"%s\" instead"), entry->default_value);
1866 goto again;
1868 return False;
1871 if (ret)
1872 *ret = &texture;
1874 if (addr)
1875 *(WTexture**)addr = texture;
1877 return True;
1882 #ifdef EXPERIMENTAL
1883 static int
1884 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
1885 void *addr, void **ret)
1887 proplist_t elem;
1888 char *val;
1889 int nelem;
1890 static WTexture *texture=NULL;
1891 int changed=0;
1892 char *file = NULL;
1894 again:
1895 entry->extra_data = NULL;
1897 if (!PLIsArray(value)) {
1898 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
1899 "WorkspaceBack", "Texture");
1900 if (changed==0) {
1901 value = entry->plvalue;
1902 changed = 1;
1903 wwarning(_("using default \"%s\" instead"), entry->default_value);
1904 goto again;
1906 return False;
1909 nelem = PLGetNumberOfElements(value);
1910 if (nelem < 1) {
1911 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1912 if (changed==0) {
1913 value = entry->plvalue;
1914 changed = 1;
1915 wwarning(_("using default \"%s\" instead"), entry->default_value);
1916 goto again;
1918 return False;
1921 elem = PLGetArrayElement(value, 0);
1922 if (!elem || !PLIsString(elem)) {
1923 wwarning(_("Wrong type for workspace background. Should be Texture."));
1924 if (changed==0) {
1925 value = entry->plvalue;
1926 changed = 1;
1927 wwarning(_("using default \"%s\" instead"), entry->default_value);
1928 goto again;
1930 return False;
1932 val = PLGetString(elem);
1934 if (strcasecmp(val, "None")==0)
1935 return False;
1937 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
1938 && strcasecmp(val, "cpixmap")!=0) {
1939 texture = parse_texture(scr, value);
1940 } else {
1941 /* spixmap || tpixmap || cpixmap */
1942 XColor color;
1943 int style;
1945 if (nelem != 3) {
1946 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
1947 if (changed==0) {
1948 value = entry->plvalue;
1949 changed = 1;
1950 wwarning(_("using default \"%s\" instead"), entry->default_value);
1951 goto again;
1953 return False;
1956 switch (val[0]) {
1957 case 's':
1958 case 'S':
1959 style = WTP_SCALE;
1960 break;
1961 case 'C':
1962 case 'c':
1963 style = WTP_CENTER;
1964 break;
1965 default:
1966 style = WTP_TILE;
1967 break;
1970 /* get color */
1971 elem = PLGetArrayElement(value, 2);
1972 if (!elem || !PLIsString(elem)) {
1973 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
1974 if (changed==0) {
1975 value = entry->plvalue;
1976 changed = 1;
1977 wwarning(_("using default \"%s\" instead"), entry->default_value);
1978 goto again;
1980 return False;
1982 val = PLGetString(elem);
1984 if (!XParseColor(dpy, scr->colormap, val, &color)) {
1985 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
1986 val);
1987 if (changed==0) {
1988 value = entry->plvalue;
1989 changed = 1;
1990 wwarning(_("using default \"%s\" instead"), entry->default_value);
1991 goto again;
1993 return False;
1996 /* file name */
1997 elem = PLGetArrayElement(value, 1);
1998 if (!elem || !PLIsString(elem)) {
1999 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
2000 if (changed==0) {
2001 value = entry->plvalue;
2002 changed = 1;
2003 wwarning(_("using default \"%s\" instead"), entry->default_value);
2004 goto again;
2006 return False;
2009 val = PLGetString(elem);
2010 file = FindImage(wPreferences.pixmap_path, val);
2011 if (!file) {
2012 wwarning(_("could not find background image \"%s\""), val);
2013 /*return False;*/
2016 /* create a dummy texture.
2017 * use free() to free this texture.
2019 texture = wmalloc(sizeof(WTexture));
2020 memset(texture, 0, sizeof(WTexture));
2021 texture->type = WTEX_PIXMAP;
2022 texture->subtype = style;
2023 texture->normal = color;
2026 if (!texture) {
2027 if (file)
2028 free(file);
2029 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
2030 if (changed==0) {
2031 value = entry->plvalue;
2032 changed = 1;
2033 wwarning(_("using default \"%s\" instead"), entry->default_value);
2034 goto again;
2036 return False;
2039 if (ret)
2040 *ret = &texture;
2042 if (addr)
2043 *(WTexture**)addr = texture;
2045 /* we use the extra_data field to pass the filename string
2046 * to the background setting function. We can't pass it with
2047 * WTexture because it holds a RImage, not a file name.
2048 * It also would be dirtier to cast the RImage to char* to make it
2049 * hold the file name. The extra_data must be freed by the
2050 * setting function.
2052 entry->extra_data = file;
2054 return True;
2056 #else /* !EXPERIMENTAL */
2057 static int
2058 getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
2059 void *addr, void **ret)
2061 proplist_t elem;
2062 char *val;
2063 int nelem;
2064 static WTexture *texture=NULL;
2065 int changed=0;
2067 again:
2068 if (!PLIsArray(value)) {
2069 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
2070 "WorkspaceBack", "Texture");
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 nelem = PLGetNumberOfElements(value);
2081 if (nelem < 1) {
2082 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
2083 if (changed==0) {
2084 value = entry->plvalue;
2085 changed = 1;
2086 wwarning(_("using default \"%s\" instead"), entry->default_value);
2087 goto again;
2089 return False;
2092 elem = PLGetArrayElement(value, 0);
2093 if (!elem || !PLIsString(elem)) {
2094 wwarning(_("Wrong type for workspace background. Should be Texture."));
2095 if (changed==0) {
2096 value = entry->plvalue;
2097 changed = 1;
2098 wwarning(_("using default \"%s\" instead"), entry->default_value);
2099 goto again;
2101 return False;
2103 val = PLGetString(elem);
2105 if (strcasecmp(val, "None")==0)
2106 return False;
2108 if (strcasecmp(val, "spixmap")!=0 && strcasecmp(val, "tpixmap")!=0
2109 && strcasecmp(val, "cpixmap")!=0) {
2110 texture = parse_texture(scr, value);
2112 else {
2113 /* spixmap || tpixmap || cpixmap */
2114 XColor color;
2115 char *file, cpc[30], *style = "-s";
2116 char *program = "wmsetbg";
2117 char *back;
2119 if (nelem != 3) {
2120 wwarning(_("Too few elements in array for key \"WorkspaceBack\"."));
2121 if (changed==0) {
2122 value = entry->plvalue;
2123 changed = 1;
2124 wwarning(_("using default \"%s\" instead"), entry->default_value);
2125 goto again;
2127 return False;
2130 if (val[0] == 't' || val[0] == 'T')
2131 style = "-t";
2132 else if (val[0] == 'c' || val[0] == 'C')
2133 style = "-e";
2135 sprintf(cpc, "%i", wPreferences.cmap_size);
2137 /* get color */
2138 elem = PLGetArrayElement(value, 2);
2139 if (!elem || !PLIsString(elem)) {
2140 wwarning(_("Cannot get color entry for key \"WorkspaceBack\"."));
2141 if (changed==0) {
2142 value = entry->plvalue;
2143 changed = 1;
2144 wwarning(_("using default \"%s\" instead"), entry->default_value);
2145 goto again;
2147 return False;
2149 val = PLGetString(elem);
2151 if (!XParseColor(dpy, scr->colormap, val, &color)) {
2152 wwarning(_("key \"WorkspaceBack\" has invalid color \"%s\""),
2153 val);
2154 if (changed==0) {
2155 value = entry->plvalue;
2156 changed = 1;
2157 wwarning(_("using default \"%s\" instead"), entry->default_value);
2158 goto again;
2160 return False;
2163 back = wstrdup(val);
2165 /* file name */
2166 elem = PLGetArrayElement(value, 1);
2167 if (!elem || !PLIsString(elem)) {
2168 wwarning(_("Cannot get file entry for key \"WorkspaceBack\"."));
2169 if (changed==0) {
2170 value = entry->plvalue;
2171 changed = 1;
2172 wwarning(_("using default \"%s\" instead"), entry->default_value);
2173 goto again;
2175 return False;
2178 val = PLGetString(elem);
2180 file = FindImage(wPreferences.pixmap_path, val);
2181 if (file) {
2182 if (fork()==0) {
2183 SetupEnvironment(scr);
2185 close(ConnectionNumber(dpy));
2187 execlp(program, program, style, "-c", cpc, "-b", back, file, NULL);
2188 wwarning(_("could not run \"%s\""), program);
2189 exit(-1);
2191 free(file);
2192 } else {
2193 wwarning(_("could not find background image \"%s\""), val);
2196 free(back);
2198 /* This is to let WindowMaker put a color in the background
2199 * until the pixmap is loaded, if the image is big and loads slow.
2200 * It assumes that the color will be set before the image is set
2201 * by the child. Is this true for very small images?
2203 texture = (WTexture*)wTextureMakeSolid(scr, &color);
2206 if (!texture) {
2207 wwarning(_("Error in texture specification for key \"WorkspaceBack\""));
2208 if (changed==0) {
2209 value = entry->plvalue;
2210 changed = 1;
2211 wwarning(_("using default \"%s\" instead"), entry->default_value);
2212 goto again;
2214 return False;
2217 if (ret)
2218 *ret = &texture;
2220 if (addr)
2221 *(WTexture**)addr = texture;
2223 return True;
2225 #endif /* !EXPERIMENTAL */
2227 static int
2228 getJust(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2229 void **ret)
2231 static char data;
2232 int changed=0;
2234 STRINGP("one of Left, Center or Right");
2236 again:
2237 if(PLIsEqual(value, JLeft))
2238 data = WTJ_LEFT;
2239 else if(PLIsEqual(value, JRight))
2240 data = WTJ_RIGHT;
2241 else if(PLIsEqual(value, JCenter))
2242 data = WTJ_CENTER;
2243 else {
2244 wwarning(_("Invalid justification type \"%s\". Should be "
2245 "Left, Center or Right"), PLGetString(value));
2246 if (changed==0) {
2247 value = entry->plvalue;
2248 changed = 1;
2249 wwarning(_("using default \"%s\" instead"), entry->default_value);
2250 goto again;
2252 return False;
2255 if (ret)
2256 *ret = &data;
2258 if (addr)
2259 *(char*)addr = data;
2261 return True;
2265 static int
2266 getFont(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2267 void **ret)
2269 static WFont *font;
2270 char *val;
2272 STRINGP("Font");
2274 val = PLGetString(value);
2276 font = wLoadFont(val);
2277 if (!font) {
2278 wwarning(_("could not load any usable font"));
2279 return False;
2282 if (ret)
2283 *ret = font;
2285 if (addr) {
2286 wwarning("BUG:can't assign font value outside update function");
2289 return True;
2293 static int
2294 getColor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2295 void **ret)
2297 static unsigned long pixel;
2298 XColor color;
2299 char *val;
2300 int second_pass=0;
2302 STRINGP("Color");
2304 val = PLGetString(value);
2306 again:
2307 if (!wGetColor(scr, val, &color)) {
2308 wwarning(_("could not get color for key \"%s\""),
2309 PLGetString(entry->plkey));
2310 if (second_pass==0) {
2311 val = PLGetString(entry->plvalue);
2312 second_pass = 1;
2313 wwarning(_("using default \"%s\" instead"), val);
2314 goto again;
2316 return False;
2319 pixel = color.pixel;
2321 if (ret)
2322 *ret = &pixel;
2324 if (addr)
2325 *(unsigned long*)addr = pixel;
2327 return True;
2332 static int
2333 getKeybind(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2334 void **ret)
2336 static WShortKey shortcut;
2337 KeySym ksym;
2338 char *val;
2339 char *k;
2340 char buf[128], *b;
2343 STRINGP("Key spec");
2345 val = PLGetString(value);
2347 if (!val || strcasecmp(val, "NONE")==0) {
2348 shortcut.keycode = 0;
2349 shortcut.modifier = 0;
2350 if (ret)
2351 *ret = &shortcut;
2352 return True;
2355 strcpy(buf, val);
2357 b = (char*)buf;
2359 /* get modifiers */
2360 shortcut.modifier = 0;
2361 while ((k = strchr(b, '+'))!=NULL) {
2362 int mod;
2364 *k = 0;
2365 mod = wXModifierFromKey(b);
2366 if (mod<0) {
2367 wwarning(_("%s:invalid key modifier \"%s\""), entry->key, val);
2368 return False;
2370 shortcut.modifier |= mod;
2372 b = k+1;
2375 /* get key */
2376 ksym = XStringToKeysym(b);
2378 if (ksym==NoSymbol) {
2379 wwarning(_("%s:invalid kbd shortcut specification \"%s\""), entry->key,
2380 val);
2381 return False;
2384 shortcut.keycode = XKeysymToKeycode(dpy, ksym);
2385 if (shortcut.keycode==0) {
2386 wwarning(_("%s:invalid key in shortcut \"%s\""), entry->key, val);
2387 return False;
2390 if (ret)
2391 *ret = &shortcut;
2393 return True;
2397 static int
2398 getModMask(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2399 void **ret)
2401 unsigned int mask;
2402 char *str;
2404 STRINGP("Modifier Key");
2406 str = PLGetString(value);
2407 if (!str)
2408 return False;
2410 mask = wXModifierFromKey(str);
2411 if (mask < 0) {
2412 wwarning(_("%s: modifier key %s is not valid"), entry->key, str);
2413 mask = 0;
2414 return False;
2417 if (addr)
2418 *(unsigned int*)addr = mask;
2420 if (ret)
2421 *ret = &mask;
2423 return True;
2428 static int
2429 getIconPosition(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
2430 void **ret)
2432 static int data;
2433 char *val;
2434 int second_pass=0;
2436 STRINGP("one of blv, blh, brv, brh, tlv, tlh, trv, trh");
2438 val = PLGetString(value);
2440 again:
2441 if (strlen(val)==3) {
2442 if (val[0]=='T' || val[0]=='t') {
2443 data = IY_TOP;
2444 } else {
2445 data = IY_BOTTOM;
2447 if (val[1]=='R' || val[1]=='r') {
2448 data |= IY_RIGHT;
2449 } else {
2450 data |= IY_LEFT;
2452 if (val[2]=='V' || val[2]=='v') {
2453 data |= IY_VERT;
2454 } else {
2455 data |= IY_HORIZ;
2457 } else {
2458 wwarning(_("Invalid icon Position \"%s\". "
2459 "Should be one of blv, blh, brv, brh, tlv, tlh, trv, trh"),
2460 PLGetString(value));
2461 if (second_pass==0) {
2462 val = PLGetString(entry->plvalue);
2463 second_pass = 1;
2464 wwarning(_("using default \"%s\" instead"), val);
2465 goto again;
2467 return False;
2470 if (ret)
2471 *ret = &data;
2473 if (addr)
2474 *(int*)addr = data;
2476 return True;
2480 /* ---------------- value setting functions --------------- */
2481 static int
2482 setJustify(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2484 return REFRESH_FORE_COLOR;
2488 static int
2489 setIfDockPresent(WScreen *scr, WDefaultEntry *entry, int *flag, long which)
2491 switch (which) {
2492 case WM_DOCK:
2493 wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
2494 break;
2495 case WM_CLIP:
2496 wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
2497 break;
2498 default:
2499 break;
2501 return 0;
2505 static int
2506 setStickyIcons(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
2508 if (scr->workspaces) {
2509 wWorkspaceForceChange(scr, scr->current_workspace);
2510 wArrangeIcons(scr, False);
2512 return 0;
2515 #if not_used
2516 static int
2517 setPositive(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
2519 if (*value <= 0)
2520 *(int*)foo = 1;
2522 return 0;
2524 #endif
2528 static int
2529 setIconTile(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
2531 Pixmap pixmap;
2532 RImage *img;
2533 int reset = 0;
2535 img = wTextureRenderImage(*texture, wPreferences.icon_size,
2536 wPreferences.icon_size,
2537 ((*texture)->any.type & WREL_BORDER_MASK)
2538 ? WREL_ICON : WREL_FLAT);
2539 if (!img) {
2540 wwarning(_("could not render texture for icon background"));
2541 if (!entry->addr)
2542 wTextureDestroy(scr, *texture);
2543 return 0;
2545 RConvertImage(scr->rcontext, img, &pixmap);
2547 if (scr->icon_tile) {
2548 reset = 1;
2549 RDestroyImage(scr->icon_tile);
2550 XFreePixmap(dpy, scr->icon_tile_pixmap);
2553 scr->icon_tile = img;
2555 if (!wPreferences.flags.noclip) {
2556 if (scr->clip_tile) {
2557 RDestroyImage(scr->clip_tile);
2559 scr->clip_tile = wClipMakeTile(scr, img);
2562 scr->icon_tile_pixmap = pixmap;
2564 if (scr->def_icon_pixmap) {
2565 XFreePixmap(dpy, scr->def_icon_pixmap);
2566 scr->def_icon_pixmap = None;
2568 if (scr->def_ticon_pixmap) {
2569 XFreePixmap(dpy, scr->def_ticon_pixmap);
2570 scr->def_ticon_pixmap = None;
2573 if (scr->icon_back_texture) {
2574 wTextureDestroy(scr, (WTexture*)scr->icon_back_texture);
2576 scr->icon_back_texture = wTextureMakeSolid(scr, &((*texture)->any.color));
2578 if (scr->clip_balloon)
2579 XSetWindowBackground(dpy, scr->clip_balloon,
2580 (*texture)->any.color.pixel);
2583 * Free the texture as nobody else will use it, nor refer to it.
2585 if (!entry->addr)
2586 wTextureDestroy(scr, *texture);
2588 return (reset ? REFRESH_ICON_TILE : 0);
2593 static int
2594 setWinTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2596 if (scr->title_font) {
2597 wFreeFont(scr->title_font);
2600 scr->title_font = font;
2602 #ifndef I18N_MB
2603 XSetFont(dpy, scr->window_title_gc, font->font->fid);
2604 #endif
2606 return REFRESH_WINDOW_FONT;
2610 static int
2611 setMenuTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2613 if (scr->menu_title_font) {
2614 wFreeFont(scr->menu_title_font);
2617 scr->menu_title_font = font;
2619 #ifndef I18N_MB
2620 XSetFont(dpy, scr->menu_title_gc, font->font->fid);
2621 #endif
2623 return REFRESH_MENU_TITLE_FONT;
2627 static int
2628 setMenuTextFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2630 if (scr->menu_entry_font) {
2631 wFreeFont(scr->menu_entry_font);
2634 scr->menu_entry_font = font;
2636 #ifndef I18N_MB
2637 XSetFont(dpy, scr->menu_entry_gc, font->font->fid);
2638 XSetFont(dpy, scr->disabled_menu_entry_gc, font->font->fid);
2639 XSetFont(dpy, scr->select_menu_gc, font->font->fid);
2640 #endif
2642 return REFRESH_MENU_FONT;
2647 static int
2648 setIconTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2650 if (scr->icon_title_font) {
2651 wFreeFont(scr->icon_title_font);
2654 scr->icon_title_font = font;
2656 #ifndef I18N_MB
2657 XSetFont(dpy, scr->icon_title_gc, font->font->fid);
2658 #endif
2660 return REFRESH_ICON_FONT;
2664 static int
2665 setClipTitleFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2667 if (scr->clip_title_font) {
2668 wFreeFont(scr->clip_title_font);
2671 scr->clip_title_font = font;
2673 #ifndef I18N_MB
2674 XSetFont(dpy, scr->clip_title_gc, font->font->fid);
2675 #endif
2677 return REFRESH_ICON_FONT;
2681 static int
2682 setDisplayFont(WScreen *scr, WDefaultEntry *entry, WFont *font, void *foo)
2684 if (scr->info_text_font) {
2685 wFreeFont(scr->info_text_font);
2688 scr->info_text_font = font;
2690 #ifndef I18N_MB
2691 XSetFont(dpy, scr->info_text_gc, font->font->fid);
2692 XSetFont(dpy, scr->line_gc, font->font->fid);
2693 #endif
2695 /* This test works because the scr structure is initially zeroed out
2696 and None = 0. Any other time, the window should be valid. */
2697 if (scr->geometry_display != None) {
2698 wGetGeometryWindowSize(scr, &scr->geometry_display_width,
2699 &scr->geometry_display_height);
2700 XResizeWindow(dpy, scr->geometry_display,
2701 scr->geometry_display_width, scr->geometry_display_height);
2704 return 0;
2708 static int
2709 setHightlight(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2711 if (scr->select_pixel!=scr->white_pixel &&
2712 scr->select_pixel!=scr->black_pixel) {
2713 wFreeColor(scr, scr->select_pixel);
2716 scr->select_pixel = color->pixel;
2718 return REFRESH_FORE_COLOR;
2722 static int
2723 setHightlightText(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2725 if (scr->select_text_pixel!=scr->white_pixel &&
2726 scr->select_text_pixel!=scr->black_pixel) {
2727 wFreeColor(scr, scr->select_text_pixel);
2730 scr->select_text_pixel = color->pixel;
2732 return REFRESH_FORE_COLOR;
2736 static int
2737 setClipTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2739 if (scr->clip_title_pixel[index]!=scr->white_pixel &&
2740 scr->clip_title_pixel[index]!=scr->black_pixel) {
2741 wFreeColor(scr, scr->clip_title_pixel[index]);
2744 scr->clip_title_pixel[index] = color->pixel;
2746 return REFRESH_FORE_COLOR;
2750 static int
2751 setWTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
2753 if (scr->window_title_pixel[index]!=scr->white_pixel &&
2754 scr->window_title_pixel[index]!=scr->black_pixel) {
2755 wFreeColor(scr, scr->window_title_pixel[index]);
2758 scr->window_title_pixel[index] = color->pixel;
2760 if (index == WS_FOCUSED)
2761 XSetForeground(dpy, scr->icon_title_gc, color->pixel);
2762 else if (index == WS_UNFOCUSED)
2763 XSetForeground(dpy, scr->info_text_gc, color->pixel);
2765 return REFRESH_FORE_COLOR;
2769 static int
2770 setMenuTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2772 if (scr->menu_title_pixel[0]!=scr->white_pixel &&
2773 scr->menu_title_pixel[0]!=scr->black_pixel) {
2774 wFreeColor(scr, scr->menu_title_pixel[0]);
2777 scr->menu_title_pixel[0] = color->pixel;
2779 XSetForeground(dpy, scr->menu_title_gc, color->pixel);
2781 return REFRESH_FORE_COLOR;
2785 static int
2786 setMenuTextColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2788 XGCValues gcv;
2789 #define gcm (GCForeground|GCBackground|GCFillStyle)
2791 if (scr->mtext_pixel!=scr->white_pixel &&
2792 scr->mtext_pixel!=scr->black_pixel) {
2793 wFreeColor(scr, scr->mtext_pixel);
2796 scr->mtext_pixel = color->pixel;
2798 XSetForeground(dpy, scr->menu_entry_gc, color->pixel);
2801 if (scr->dtext_pixel == scr->mtext_pixel) {
2802 gcv.foreground = scr->white_pixel;
2803 gcv.background = scr->black_pixel;
2804 gcv.fill_style = FillStippled;
2805 } else {
2806 gcv.foreground = scr->dtext_pixel;
2807 gcv.fill_style = FillSolid;
2809 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2811 return REFRESH_FORE_COLOR;
2812 #undef gcm
2816 static int
2817 setMenuDisabledColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
2819 XGCValues gcv;
2820 #define gcm (GCForeground|GCBackground|GCFillStyle)
2822 if (scr->dtext_pixel!=scr->white_pixel &&
2823 scr->dtext_pixel!=scr->black_pixel) {
2824 wFreeColor(scr, scr->dtext_pixel);
2827 scr->dtext_pixel = color->pixel;
2829 if (scr->dtext_pixel == scr->mtext_pixel) {
2830 gcv.foreground = scr->white_pixel;
2831 gcv.background = scr->black_pixel;
2832 gcv.fill_style = FillStippled;
2833 } else {
2834 gcv.foreground = scr->dtext_pixel;
2835 gcv.fill_style = FillSolid;
2837 XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
2839 return REFRESH_FORE_COLOR;
2840 #undef gcm
2846 * Implementation of workspace specific backgrounds.
2848 * WorkspaceBack is used as the default background.
2849 * WorkspaceSpecificBack supplies an array with the textures for
2850 * other workspaces.
2851 * WorkspaceSpecificBack = (ws1texture, ws2texture, "", ws4texture);
2852 * "" means that workspace3 should use the default texture.
2854 * struct WWorkspaceTexture {
2855 * Pixmap pixmap; // the pixmap for non-solid textures.
2856 * //None means the texture is solid
2857 * WPixel color; // color for solid texture
2858 * proplist_t texture; // for checking updates
2859 * };
2861 * spixmap and cpixmap textures are rendered by wmsetbg in a buffer
2862 * supplied by wmaker (-x drawable-XID).
2863 * All other textures are rendered by wmaker itself. This is to
2864 * prevent wmaker from blocking when rendering large pixmaps.
2865 * tpixmap must be rendered by wmaker because we dont know the size
2866 * of the image before loading the image. We supply the pixmap
2867 * to wmsetbg, instead of letting wmsetbg create it for 2 reasons:
2868 * 1 - Xlib will free the pixmap when wmsetbg exits
2869 * 2 - it would require wmaker to figure when wmsetbg finished
2870 * rendering (complicated synchronization...).
2872 * The workspace background cant be set if the pid field of the
2873 * texture is 0. Otherwise, the texture is still being rendered
2874 * and cant be set.
2876 * If the workspace background is changed before wmsetbg finishes
2877 * the rendering, wmsetbg must be killed.
2879 * Optimizations:
2880 * Workspace specific textures are generated only when switching to
2881 * that workspace, unless #define SLOW_CONFIGURATION_UPDATE.
2883 * -readme
2885 #ifdef EXPERIMENTAL
2886 static void
2887 trackDeadProcess(pid_t pid, unsigned char status, WScreen *scr)
2889 WWorkspaceTexture *wsback;
2890 int setBackground = 0;
2892 /* find out to which wsback, this process belongs to */
2894 wsback->pid = 0;
2895 if (status != 123) {
2896 /* something went wrong during rendering */
2897 XFreePixmap(dpy, wsback->pixmap);
2898 wsback->pixmap = None;
2899 wwarning(_("background texture rendering was unsuccessfull"));
2902 if (setBackground) {
2906 WWorkspaceTexture*
2907 makeWorkspaceTexture(WScreen *scr, WTexture *texture, char *file, char *option)
2909 WWorkspaceTexture *wsback;
2911 wsback = wmalloc(sizeof(WWorkspaceTexture));
2912 wsback->pid = 0;
2914 wsback->solid = (*texture)->any.color.pixel;
2916 if (texture->any.type==WTEX_SOLID) {
2917 wsback->pixmap = None;
2918 } else if (texture->any.type == WTEX_PIXMAP) {
2919 Pixmap pixmap;
2920 if (texture->pixmap.subtype == WTP_TILE) {
2921 RImage *image;
2923 /* render ourseves */
2924 image = RLoadImage(scr->rcontext, file, 0);
2925 if (!image) {
2926 wwarning(_("could not load image %s for option %s:%s\n"),
2927 file, option, RErrorString);
2928 wsback->pixmap = None;
2929 } else {
2931 } else {
2932 /* create a empty pixmap... */
2933 pid_t pid;
2934 int style = texture->pixmap.subtype;
2936 pixmap = XCreatePixmap(dpy, scr->root_win, scr->scr_width,
2937 scr->scr_height, scr->depth);
2939 /* ...and let wmsetbg render it */
2940 pid = fork();
2941 if (pid < 0) {
2942 wsyserror(_("could not spawn texture rendering subprocess for option"));
2943 } else if (pid == 0) {
2944 char *colorn, *pix;
2946 SetupEnvironment(scr);
2948 close(ConnectionNumber(dpy));
2950 colorn = wmalloc(32);
2951 sprintf(colorn, "\"#%2x%2x%2x\"",
2952 texture->any.color.red,
2953 texture->any.color.green,
2954 texture->any.color.blue);
2955 pix = wmalloc(32);
2956 sprintf(pix, "%x", pixmap);
2957 execlp("wmsetbg", "wmsetbg", (style==WTP_SCALE ? "-s":"-e"),
2958 "-b", colorn, "-x", pix, file);
2959 exit(1);
2961 wsback->pixmap = pixmap;
2962 /* must add a death handler to detect when wmsetbg has
2963 * exited (with exit status 123) and refresh the background.
2965 wsback->pid = pid;
2967 } else {
2968 int w, h;
2969 Pixmap pixmap;
2971 switch (texture->any.type) {
2972 case WTEX_HGRADIENT:
2973 case WTEX_MHGRADIENT:
2974 w = scr->scr_width;
2975 h = 8;
2976 break;
2978 case WTEX_VGRADIENT:
2979 case WTEX_MVGRADIENT:
2980 w = 8;
2981 h = scr->scr_height;
2982 break;
2984 case WTEX_DGRADIENT:
2985 case WTEX_MDGRADIENT:
2986 w = scr->scr_width;
2987 h = scr->scr_height;
2988 break;
2990 default:
2991 return NULL;
2994 img = wTextureRenderImage(texture, w, h, WREL_FLAT);
2995 if (!img) {
2996 wwarning(_("could not render texture for workspace background"));
2997 free(wsback);
2998 return NULL;
3000 RConvertImage(scr->rcontext, img, &pixmap);
3001 RDestroyImage(img);
3002 wsback->pixmap = pixmap;
3005 return wsback;
3009 static int
3010 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
3011 char *file)
3013 Pixmap pixmap;
3014 RImage *img;
3016 if (scr->defaultTexture) {
3017 if (scr->defaultTexture->pixmap)
3018 XFreePixmap(dpy, scr->defaultTexture->pixmap);
3019 free(scr->defaultTexture);
3022 if (!*texture) {
3023 scr->defaultTexture = NULL;
3024 if (file)
3025 free(file);
3026 return 0;
3029 scr->defaultTexture = makeWorkspaceTexture(scr, *texture, file);
3031 if (!entry->addr)
3032 wTextureDestroy(scr, *texture);
3034 /* free the file name that was passed from the getWSBackground()
3035 * function and placed in entry->extra_data */
3036 if (file)
3037 free(file);
3038 entry->extra_data = NULL;
3040 return REFRESH_WORKSPACE_BACK;
3042 #else /* !EXPERIMENTAL */
3043 static int
3044 setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture,
3045 void *foo)
3047 Pixmap pixmap;
3048 RImage *img;
3051 if ((*texture)->any.type==WTEX_SOLID) {
3052 XSetWindowBackground(dpy, scr->root_win, (*texture)->solid.normal.pixel);
3053 XClearWindow(dpy, scr->root_win);
3054 } else {
3055 int w, h;
3057 switch ((*texture)->any.type) {
3058 case WTEX_HGRADIENT:
3059 case WTEX_MHGRADIENT:
3060 w = scr->scr_width;
3061 h = 8;
3062 break;
3064 case WTEX_VGRADIENT:
3065 case WTEX_MVGRADIENT:
3066 w = 8;
3067 h = scr->scr_height;
3068 break;
3070 case WTEX_DGRADIENT:
3071 case WTEX_MDGRADIENT:
3072 w = scr->scr_width;
3073 h = scr->scr_height;
3074 break;
3076 default:
3077 if (!entry->addr)
3078 wTextureDestroy(scr, *texture);
3079 return 0;
3082 img = wTextureRenderImage(*texture, w, h, WREL_FLAT);
3083 if (!img) {
3084 wwarning(_("could not render texture for workspace background"));
3085 if (!entry->addr)
3086 wTextureDestroy(scr, *texture);
3087 return 0;
3089 RConvertImage(scr->rcontext, img, &pixmap);
3090 RDestroyImage(img);
3091 XSetWindowBackgroundPixmap(dpy, scr->root_win, pixmap);
3092 XClearWindow(dpy, scr->root_win);
3096 * Free the texture as nobody else will use it, nor refer to it.
3098 if (!entry->addr)
3099 wTextureDestroy(scr, *texture);
3101 return 0;
3103 #endif /* !EXPERIMENTAL */
3105 static int
3106 setWidgetColor(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
3108 if (scr->widget_texture) {
3109 wTextureDestroy(scr, (WTexture*)scr->widget_texture);
3111 scr->widget_texture = *(WTexSolid**)texture;
3113 return 0;
3117 static int
3118 setFTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
3120 if (scr->window_title_texture[WS_FOCUSED]) {
3121 wTextureDestroy(scr, scr->window_title_texture[WS_FOCUSED]);
3123 scr->window_title_texture[WS_FOCUSED] = *texture;
3125 if (scr->icon_title_texture) {
3126 wTextureDestroy(scr, (WTexture*)scr->icon_title_texture);
3128 scr->icon_title_texture
3129 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_FOCUSED]->any.color);
3131 return REFRESH_WINDOW_TEXTURES;
3135 static int
3136 setPTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
3138 if (scr->window_title_texture[WS_PFOCUSED]) {
3139 wTextureDestroy(scr, scr->window_title_texture[WS_PFOCUSED]);
3141 scr->window_title_texture[WS_PFOCUSED] = *texture;
3143 return REFRESH_WINDOW_TEXTURES;
3147 static int
3148 setUTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
3150 if (scr->window_title_texture[WS_UNFOCUSED]) {
3151 wTextureDestroy(scr, scr->window_title_texture[WS_UNFOCUSED]);
3153 scr->window_title_texture[WS_UNFOCUSED] = *texture;
3155 if (scr->resizebar_texture[0]) {
3156 wTextureDestroy(scr, (WTexture*)scr->resizebar_texture[0]);
3158 scr->resizebar_texture[0]
3159 = wTextureMakeSolid(scr, &scr->window_title_texture[WS_UNFOCUSED]->any.color);
3161 if (scr->geometry_display != None)
3162 XSetWindowBackground(dpy, scr->geometry_display,
3163 scr->resizebar_texture[0]->normal.pixel);
3165 return REFRESH_WINDOW_TEXTURES;
3169 static int
3170 setMenuTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
3172 if (scr->menu_title_texture[0]) {
3173 wTextureDestroy(scr, scr->menu_title_texture[0]);
3175 scr->menu_title_texture[0] = *texture;
3177 return REFRESH_MENU_TEXTURES;
3181 static int
3182 setMenuTextBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
3184 if (scr->menu_item_texture) {
3185 wTextureDestroy(scr, scr->menu_item_texture);
3186 wTextureDestroy(scr, (WTexture*)scr->menu_item_auxtexture);
3188 scr->menu_item_texture = *texture;
3190 scr->menu_item_auxtexture
3191 = wTextureMakeSolid(scr, &scr->menu_item_texture->any.color);
3193 return REFRESH_MENU_TEXTURES;
3197 static int
3198 setKeyGrab(WScreen *scr, WDefaultEntry *entry, WShortKey *shortcut, long index)
3200 WWindow *wwin;
3201 wKeyBindings[index] = *shortcut;
3203 wwin = scr->focused_window;
3205 while (wwin!=NULL) {
3206 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
3208 if (!wwin->window_flags.no_bind_keys) {
3209 wWindowSetKeyGrabs(wwin);
3211 wwin = wwin->prev;
3214 return 0;
3218 static int
3219 setIconPosition(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
3221 wArrangeIcons(scr, True);
3223 return 0;
3229 * Very ugly kluge.
3230 * Need access to the double click variables, so that all widgets in
3231 * wmaker panels will have the same dbl-click values.
3232 * TODO: figure a better way of dealing with it.
3234 #include "WINGsP.h"
3236 static int
3237 setDoubleClick(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
3239 extern _WINGsConfiguration WINGsConfiguration;
3241 if (*value <= 0)
3242 *(int*)foo = 1;
3244 WINGsConfiguration.doubleClickDelay = *value;
3246 return 0;