From 41996df786937970d2347ba1b3b7f7c4c77d19c2 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 20 Dec 2001 22:16:01 +0000 Subject: [PATCH] - 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. - Fixed bug with not extracting the icon from the client when using shared appicons. - Added WMSubtractPLDictionaries() to WINGs (opposite for merging, it will remove all entries from dest if they are present in source and are exactly the same. Unique entries in dest and entries with different values from those present in source will be preserved). --- ChangeLog | 6 ++++++ TODO | 6 +++--- WINGs/ChangeLog | 1 + WINGs/WINGs/WUtil.h | 8 ++++++- WINGs/proplist.c | 42 ++++++++++++++++++++++++++++++++++-- src/application.c | 5 +++-- src/defaults.c | 61 ++++++++++++++++++++++++++++++++++++----------------- src/dialog.h | 3 +++ src/dock.h | 1 + src/funcs.h | 3 +++ src/misc.c | 35 ++++++++++++++++++++++++++++++ src/wdefaults.c | 5 +++-- src/window.c | 9 ++++++-- src/winspector.c | 2 +- 14 files changed, 155 insertions(+), 32 deletions(-) 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); -- 2.11.4.GIT