diff --git a/ChangeLog b/ChangeLog index 7ce3c763..3db0fc3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,6 +39,12 @@ Changes since version 0.70.0: adapt to newer/faster machines. Also used wusleep(10) when the delay was 0 to get rid of the jerky animation when there was no delay. - Fixed bug with Unhide mapping windows from other workspaces. +- Saving a domain file will first strip all entries that are also present in + the global domain as well and are exactly the same. This fixes a bug where + settings from the global domain file were merged in the user domain file + and further changes in the global domain file for those merged values was + ignored making a system admin unable to set global defaults for all users + using the global domains. Changes since version 0.65.1: diff --git a/TODO b/TODO index 462ab8d1..35d8539d 100644 --- a/TODO +++ b/TODO @@ -27,9 +27,9 @@ Need to do: docked apps, balloons for the dock etc - check whether apps with name.class set to empty strings should be treated like if name.class is NULL.NULL -- review the defaults handling code (not to save globals in user, not to - reread after we update a domain if possible, check WINGs apps updating - WMWindowAttributes after start making screen to flash on update) +- review the defaults handling code (not to reread after we update a + domain if possible, check WINGs apps updating WMWindowAttributes after + start making screen to flash on update) Maybe some day: diff --git a/WINGs/ChangeLog b/WINGs/ChangeLog index 6288c533..be1da80e 100644 --- a/WINGs/ChangeLog +++ b/WINGs/ChangeLog @@ -7,6 +7,7 @@ Changes since wmaker 0.70.0: - removed a wsyserror() message when reading a property list from file (the programmer should decide if to give that message or just ignore). - added a 'Bool recursive' flag to WMMergePLDictionaries() +- added WMSubtractPLDictionaries() Changes since wmaker 0.65.0: diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index 4869de96..da7ea6ce 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -769,12 +769,18 @@ void WMPutInPLDictionary(WMPropList *plist, WMPropList *key, WMPropList *value); void WMRemoveFromPLDictionary(WMPropList *plist, WMPropList *key); -/* It inserts all key/value pairs from source into dest, overwriting +/* It will insert all key/value pairs from source into dest, overwriting * the values with the same keys from dest, keeping all values with keys * only present in dest unchanged */ WMPropList* WMMergePLDictionaries(WMPropList *dest, WMPropList *source, Bool recursive); +/* It will remove all key/value pairs from dest for which there is an + * identical key/value present in source. Entires only present in dest, or + * which have different values in dest than in source will be preserved. */ +WMPropList* WMSubtractPLDictionaries(WMPropList *dest, WMPropList *source, + Bool recursive); + int WMGetPropListItemCount(WMPropList *plist); Bool WMIsPLString(WMPropList *plist); diff --git a/WINGs/proplist.c b/WINGs/proplist.c index 2e9ccad4..ddb1ec1d 100644 --- a/WINGs/proplist.c +++ b/WINGs/proplist.c @@ -1218,12 +1218,15 @@ WMMergePLDictionaries(WMPropList *dest, WMPropList *source, Bool recursive) wassertr(source->type==WPLDictionary && dest->type==WPLDictionary); + if (source == dest) + return dest; + e = WMEnumerateHashTable(source->d.dict); while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) { if (recursive && value->type==WPLDictionary) { - dvalue = WMGetFromPLDictionary(dest, key); + dvalue = WMHashGet(dest->d.dict, key); if (dvalue && dvalue->type==WPLDictionary) { - WMMergePLDictionaries(dvalue, value, recursive); + WMMergePLDictionaries(dvalue, value, True); } else { WMPutInPLDictionary(dest, key, value); } @@ -1236,6 +1239,41 @@ WMMergePLDictionaries(WMPropList *dest, WMPropList *source, Bool recursive) } +WMPropList* +WMSubtractPLDictionaries(WMPropList *dest, WMPropList *source, Bool recursive) +{ + WMPropList *key, *value, *dvalue; + WMHashEnumerator e; + + wassertr(source->type==WPLDictionary && dest->type==WPLDictionary); + + if (source == dest) { + WMPropList *keys = WMGetPLDictionaryKeys(dest); + int i; + + for (i=0; id.array); i++) { + WMRemoveFromPLDictionary(dest, WMGetFromArray(keys->d.array, i)); + } + return dest; + } + + e = WMEnumerateHashTable(source->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) { + dvalue = WMHashGet(dest->d.dict, key); + if (!dvalue) + continue; + if (WMIsPropListEqualTo(value, dvalue)) { + WMRemoveFromPLDictionary(dest, key); + } else if (recursive && value->type==WPLDictionary && + dvalue->type==WPLDictionary) { + WMSubtractPLDictionaries(dvalue, value, True); + } + } + + return dest; +} + + int WMGetPropListItemCount(WMPropList *plist) { diff --git a/src/application.c b/src/application.c index 735b44ff..daa7eaad 100644 --- a/src/application.c +++ b/src/application.c @@ -185,8 +185,9 @@ saveIconNameFor(char *iconPath, char *wm_instance, char *wm_class) WMReleasePropList(key); WMReleasePropList(iconk); - if (val && !wPreferences.flags.noupdates) - WMWritePropListToFile(dict, WDWindowAttributes->path, True); + if (val && !wPreferences.flags.noupdates) { + UpdateDomainFile(WDWindowAttributes); + } } diff --git a/src/defaults.c b/src/defaults.c index c074f98b..31e43136 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -905,6 +905,29 @@ initDefaults() } +static WMPropList* +readGlobalDomain(char *domainName, Bool requireDictionary) +{ + WMPropList *globalDict = NULL; + char path[PATH_MAX]; + struct stat stbuf; + + snprintf(path, sizeof(path), "%s/WindowMaker/%s", SYSCONFDIR, domainName); + if (stat(path, &stbuf)>=0) { + globalDict = WMReadPropListFromFile(path); + if (globalDict && requireDictionary && !WMIsPLDictionary(globalDict)) { + wwarning(_("Domain %s (%s) of global defaults database is corrupted!"), + domainName, path); + WMReleasePropList(globalDict); + globalDict = NULL; + } else if (!globalDict) { + wwarning(_("could not load domain %s from global defaults database"), + domainName); + } + } + + return globalDict; +} #if 0 @@ -989,7 +1012,7 @@ wDefaultsInitDomain(char *domain, Bool requireDictionary) } else { if (db->dictionary && WMIsPLDictionary(shared_dict) && WMIsPLDictionary(db->dictionary)) { - WMMergePLDictionaries(shared_dict, db->dictionary, True); + WMMergePLDictionaries(shared_dict, db->dictionary, True); WMReleasePropList(db->dictionary); db->dictionary = shared_dict; if (stbuf.st_mtime > db->timestamp) @@ -1048,35 +1071,22 @@ wDefaultsCheckDomains(void *foo) { WScreen *scr; struct stat stbuf; + WMPropList *shared_dict = NULL; WMPropList *dict; int i; - char path[PATH_MAX]; #ifdef HEARTBEAT puts("Checking domains..."); #endif if (stat(WDWindowMaker->path, &stbuf)>=0 && WDWindowMaker->timestamp < stbuf.st_mtime) { - WMPropList *shared_dict = NULL; #ifdef HEARTBEAT puts("Checking WindowMaker domain"); #endif WDWindowMaker->timestamp = stbuf.st_mtime; /* global dictionary */ - snprintf(path, sizeof(path), "%s/WindowMaker/WindowMaker", SYSCONFDIR); - if (stat(path, &stbuf)>=0) { - shared_dict = WMReadPropListFromFile(path); - if (shared_dict && !WMIsPLDictionary(shared_dict)) { - wwarning(_("Domain %s (%s) of global defaults database is corrupted!"), - "WindowMaker", path); - WMReleasePropList(shared_dict); - shared_dict = NULL; - } else if (!shared_dict) { - wwarning(_("could not load domain %s from global defaults database"), - "WindowMaker"); - } - } + shared_dict = readGlobalDomain("WindowMaker", True); /* user dictionary */ dict = WMReadPropListFromFile(WDWindowMaker->path); if (dict) { @@ -1087,7 +1097,7 @@ wDefaultsCheckDomains(void *foo) "WindowMaker", WDWindowMaker->path); } else { if (shared_dict) { - WMMergePLDictionaries(shared_dict, dict, True); + WMMergePLDictionaries(shared_dict, dict, True); WMReleasePropList(dict); dict = shared_dict; shared_dict = NULL; @@ -1116,6 +1126,9 @@ wDefaultsCheckDomains(void *foo) #ifdef HEARTBEAT puts("Checking WMWindowAttributes domain"); #endif + /* global dictionary */ + shared_dict = readGlobalDomain("WMWindowAttributes", True); + /* user dictionary */ dict = WMReadPropListFromFile(WDWindowAttributes->path); if (dict) { if (!WMIsPLDictionary(dict)) { @@ -1124,8 +1137,15 @@ wDefaultsCheckDomains(void *foo) wwarning(_("Domain %s (%s) of defaults database is corrupted!"), "WMWindowAttributes", WDWindowAttributes->path); } else { - if (WDWindowAttributes->dictionary) - WMReleasePropList(WDWindowAttributes->dictionary); + if (shared_dict) { + WMMergePLDictionaries(shared_dict, dict, True); + WMReleasePropList(dict); + dict = shared_dict; + shared_dict = NULL; + } + if (WDWindowAttributes->dictionary) { + WMReleasePropList(WDWindowAttributes->dictionary); + } WDWindowAttributes->dictionary = dict; for (i=0; itimestamp = stbuf.st_mtime; + if (shared_dict) { + WMReleasePropList(shared_dict); + } } #ifndef LITE diff --git a/src/dialog.h b/src/dialog.h index c3ac103d..02c2f3e0 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -35,6 +35,9 @@ int wMessageDialog(WScreen *scr, char *title, char *message, char *defBtn, char *altBtn, char *othBtn); int wInputDialog(WScreen *scr, char *title, char *message, char **text); +int wExitDialog(WScreen *scr, char *title, char *message, char *defBtn, + char *altBtn, char *othBtn); + Bool wIconChooserDialog(WScreen *scr, char **file, char *instance, char *class); void wShowInfoPanel(WScreen *scr); diff --git a/src/dock.h b/src/dock.h index d4badd50..b11db064 100644 --- a/src/dock.h +++ b/src/dock.h @@ -86,6 +86,7 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, Bool wDockFindFreeSlot(WDock *dock, int *req_x, int *req_y); void wDockDetach(WDock *dock, WAppIcon *icon); +void wDockFinishLaunch(WDock *dock, WAppIcon *icon); void wDockTrackWindowLaunch(WDock *dock, Window window); WAppIcon *wDockFindIconForWindow(WDock *dock, Window window); void wDockDoAutoLaunch(WDock *dock, int workspace); diff --git a/src/funcs.h b/src/funcs.h index 19228d8a..9e602d77 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -26,6 +26,7 @@ #include #include "window.h" +#include "defaults.h" typedef void (WCallBack)(void *cdata); @@ -124,6 +125,8 @@ char *EscapeWM_CLASS(char *name, char *class); void UnescapeWM_CLASS(char *str, char **name, char **class); +Bool UpdateDomainFile(WDDomain *domain); + #ifdef NUMLOCK_HACK void wHackedGrabKey(int keycode, unsigned int modifiers, Window grab_window, Bool owner_events, int pointer_mode, diff --git a/src/misc.c b/src/misc.c index f4aa1378..f8d3d97a 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1236,3 +1236,38 @@ SendHelperMessage(WScreen *scr, char type, int workspace, char *msg) } wfree(buffer); } + + +Bool +UpdateDomainFile(WDDomain *domain) +{ + struct stat stbuf; + char path[PATH_MAX]; + WMPropList *shared_dict=NULL, *dict; + Bool result, freeDict = False; + + dict = domain->dictionary; + if (WMIsPLDictionary(domain->dictionary)) { + /* retrieve global system dictionary */ + snprintf(path, sizeof(path), "%s/WindowMaker/%s", + SYSCONFDIR, domain->domain_name); + if (stat(path, &stbuf) >= 0) { + shared_dict = WMReadPropListFromFile(path); + if (shared_dict && WMIsPLDictionary(shared_dict)) { + freeDict = True; + dict = WMDeepCopyPropList(domain->dictionary); + WMSubtractPLDictionaries(dict, shared_dict, True); + } + } + } + + result = WMWritePropListToFile(dict, domain->path, True); + + if (freeDict) { + WMReleasePropList(dict); + } + + return result; +} + + diff --git a/src/wdefaults.c b/src/wdefaults.c index 477326aa..f74a1f97 100644 --- a/src/wdefaults.c +++ b/src/wdefaults.c @@ -547,8 +547,9 @@ wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file) } else if (icon_value!=NULL && !same) { WMPutInPLDictionary(dict, key, icon_value); } - if (!wPreferences.flags.noupdates) - WMWritePropListToFile(dict, db->path, True); + if (!wPreferences.flags.noupdates) { + UpdateDomainFile(db); + } WMReleasePropList(key); if(icon_value) diff --git a/src/window.c b/src/window.c index aaaeb393..91f03310 100644 --- a/src/window.c +++ b/src/window.c @@ -551,10 +551,15 @@ createFakeWindowGroupLeader(WScreen *scr, Window win, char *instance, char *clas XSetClassHint(dpy, leader, classHint); XFree(classHint); + /* inherit these from the original leader if available */ + hints = XGetWMHints(dpy, win); + if (!hints) { + hints = XAllocWMHints(); + hints->flags = 0; + } /* set window group leader to self */ - hints = XAllocWMHints(); hints->window_group = leader; - hints->flags = WindowGroupHint; + hints->flags |= WindowGroupHint; XSetWMHints(dpy, leader, hints); XFree(hints); diff --git a/src/winspector.c b/src/winspector.c index 9cab3f07..a36acc03 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -713,7 +713,7 @@ saveSettings(WMButton *button, InspectorPanel *panel) WMReleasePropList(key); WMReleasePropList(winDic); - WMWritePropListToFile(dict, db->path, True); + UpdateDomainFile(db); /* clean up */ WMPLSetCaseSensitive(False);