On Tue 27 Sep 2005 at 21:05:58 +0300, Nadav Har'El wrote:
> I tried another scenario to find leaks. This time, I created many iconic
> windows, in hope of (not) finding leaks in icon handling. The loop I ran
> was:

Here is another patch. It replaces the previous one. I think it should
fix most if not all leaks you reported so far, but notoriously it is
bedtime again :-) I moved some cleanup stuff around but I'm not sure it
is at the best place yet, maybe I'll change it again.

I make these against the current development version, but so far it does
seem to work with the RELEASE version too.  If there some fuzz-messages
from patch, you know why.

# 
# patch "add_window.c"
#  from [79ec0cb30571b095df320d19d752aea845ecafa5]
#    to [000f73f70e516dae16feb1c65b9bbf6a32ae81fa]
# 
# patch "add_window.h"
#  from [6c9c58d6b599571e858da54907abc8fc075acd09]
#    to [b3743e7bde54f2ff45467f81288a5a9734d3ca5b]
# 
# patch "events.c"
#  from [f5776d0db26af573cc1704b9d66115765dd0d72b]
#    to [5e5586a270b285c36a7c70163f1044b39108d63c]
# 
# patch "icons.c"
#  from [8d86ee978eabd18d37f3ed4a6bb1aea3b8958e2d]
#    to [a3e4578bb9e0c8cfd01fb9434e10ea18eb63f45d]
# 
# patch "icons.h"
#  from [34477ed4efc3881059aea57745ad12dfe7864c31]
#    to [d6a146e9f7aafb77b5aadd27bcec9705852cea2b]
# 
# patch "util.c"
#  from [937af1aae5e51088d075a5661574482883d93482]
#    to [ffc14c9ce235cc633333e0c011d62918934a0f0e]
# 
# patch "util.h"
#  from [d30fa13a107095ac626aa8d43f1628beefc283de]
#    to [086a3b87e05de5bca8bb5221a7fce8478059865e]
# 
--- add_window.c
+++ add_window.c
@@ -207,11 +207,6 @@
     unsigned long valuemask;           /* mask for create windows */
     XSetWindowAttributes attributes;   /* attributes for create windows */
     int width, height;                 /* tmp variable */
-#ifdef NO_LOCALE
-    Atom actual_type;
-    int actual_format;
-    unsigned long nitems, bytesafter;
-#endif /* NO_LOCALE */
     int ask_user;              /* don't know where to put the window */
     int gravx, gravy;                  /* gravity signs for positioning */
     int namelen;
@@ -275,11 +270,7 @@
 
     XSelectInput(dpy, tmp_win->w, PropertyChangeMask);
     XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr);
-#ifndef NO_LOCALE
     tmp_win->name = (char*) GetWMPropertyString(tmp_win->w, XA_WM_NAME);
-#else /* NO_LOCALE */
-    XFetchName(dpy, tmp_win->w, &tmp_win->name);
-#endif /* NO_LOCALE */
     tmp_win->class = NoClass;
     XGetClassHint(dpy, tmp_win->w, &tmp_win->class);
     FetchWmProtocols (tmp_win);
@@ -373,6 +364,11 @@
     if (tmp_win->class.res_class == NULL)
        tmp_win->class.res_class = NoName;
 
+    /*
+     * full_name seems to exist only because in the conditional code below,
+     * name is sometimes changed. In all other cases, name and full_name
+     * seem to be identical. Is that worth it?
+     */
     tmp_win->full_name = tmp_win->name;
 #ifdef CLAUDE
     if (strstr (tmp_win->name, " - Mozilla")) {
@@ -1094,16 +1090,10 @@
 
     tmp_win->title_width = tmp_win->attr.width;
 
-#ifndef NO_LOCALE
     tmp_win->icon_name = (char*) GetWMPropertyString(tmp_win->w, 
XA_WM_ICON_NAME);
-#else /* NO_LOCALE */
-    if (XGetWindowProperty (dpy, tmp_win->w, XA_WM_ICON_NAME, 0L, 200L, False,
-                           XA_STRING, &actual_type, &actual_format, &nitems,
-                           &bytesafter,(unsigned char **)&tmp_win->icon_name))
+    if (!tmp_win->icon_name)
        tmp_win->icon_name = tmp_win->name;
-#endif /* NO_LOCALE */
 
-    if (tmp_win->icon_name == NULL) tmp_win->icon_name = tmp_win->name;
 #ifdef CLAUDE
     if (strstr (tmp_win->icon_name, " - Mozilla")) {
       char *moz = strstr (tmp_win->icon_name, " - Mozilla");
@@ -1757,6 +1747,26 @@
                       Scr->d_visual, valuemask, &attributes);
 }
 
+static void DeleteHighlightWindows(TwmWindow *tmp_win)
+{
+    if (tmp_win->HiliteImage) {
+       if (Scr->HighlightPixmapName) {
+           /*
+            * Image obtained from GetImage(): it is in a cache
+            * so we don't need to free it. There will not be multiple
+            * copies if the same xpm:foo image is requested again.
+            */
+       } else {
+           XFreePixmap (dpy, tmp_win->HiliteImage->pixmap);
+       }
+       free(tmp_win->HiliteImage);
+    }
+    /*
+     * The hilite_wl etc windows don't need to be XDestroyWindow()ed
+     * since that will happen when the parent is destroyed (??)
+     */
+}
+
 static void CreateLowlightWindows (TwmWindow *tmp_win)
 {
     XSetWindowAttributes attributes;    /* attributes for create windows */
@@ -2011,7 +2021,45 @@
     return;
 }
 
+void DeleteWindowTitlebarButtons(TwmWindow *Tmp_win)
+{
+    if (Tmp_win->title_height) {
+       int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
 
+       XDeleteContext(dpy, Tmp_win->title_w, TwmContext);
+       XDeleteContext(dpy, Tmp_win->title_w, ScreenContext);
+       if (Tmp_win->hilite_wl) {
+           XDeleteContext(dpy, Tmp_win->hilite_wl, TwmContext);
+           XDeleteContext(dpy, Tmp_win->hilite_wl, ScreenContext);
+       }
+       if (Tmp_win->hilite_wr) {
+           XDeleteContext(dpy, Tmp_win->hilite_wr, TwmContext);
+           XDeleteContext(dpy, Tmp_win->hilite_wr, ScreenContext);
+       }
+       if (Tmp_win->lolite_wr) {
+           XDeleteContext(dpy, Tmp_win->lolite_wr, TwmContext);
+           XDeleteContext(dpy, Tmp_win->lolite_wr, ScreenContext);
+       }
+       if (Tmp_win->lolite_wl) {
+           XDeleteContext(dpy, Tmp_win->lolite_wl, TwmContext);
+           XDeleteContext(dpy, Tmp_win->lolite_wl, ScreenContext);
+       }
+       if (Tmp_win->titlebuttons) {
+           int i;
+
+           for (i = 0; i < nb; i++) {
+               XDeleteContext (dpy, Tmp_win->titlebuttons[i].window,
+                               TwmContext);
+               XDeleteContext (dpy, Tmp_win->titlebuttons[i].window,
+                               ScreenContext);
+           }
+           free(Tmp_win->titlebuttons);
+        }
+    }
+    DeleteHighlightWindows(Tmp_win);
+}
+
+
 void SetHighlightPixmap (char *filename)
 {
 #ifdef VMS
--- add_window.h
+++ add_window.h
@@ -72,6 +72,7 @@
 
 extern void GetGravityOffsets (TwmWindow *tmp, int *xp, int *yp);
 extern TwmWindow *AddWindow(Window w, int iconm, IconMgr *iconp);
+extern void DeleteWindowTitlebarButtons(TwmWindow *tmp_win);
 extern int MappedNotOverride(Window w);
 extern void AddDefaultBindings (void);
 extern void GrabButtons(TwmWindow *tmp_win);
--- events.c
+++ events.c
@@ -1343,27 +1343,35 @@
  * XXX - are we sure that nobody ever sets these to another constant (check
  * twm windows)?
  */
-#define isokay(v) ((v) && (v) != NoName)
     if ((tmp->name == tmp->full_name) && (tmp->name == tmp->icon_name)) {
-       if (nukefull && nukename && nukeicon && isokay(tmp->name)) XFree 
(tmp->name);
+       if (nukefull && nukename && nukeicon)
+           FreeWMPropertyString(tmp->name);
     } else
     if (tmp->name == tmp->full_name) {
-       if (nukename && nukefull && isokay(tmp->name)) XFree (tmp->name);
-       if (nukeicon && isokay(tmp->icon_name)) XFree (tmp->icon_name);
+       if (nukename && nukefull)
+           FreeWMPropertyString(tmp->name);
+       if (nukeicon)
+           FreeWMPropertyString(tmp->icon_name);
     } else
     if (tmp->name == tmp->icon_name) {
-       if (nukename && nukeicon && isokay(tmp->name)) XFree (tmp->name);
-       if (nukefull && isokay(tmp->full_name)) XFree (tmp->full_name);
+       if (nukename && nukeicon)
+           FreeWMPropertyString(tmp->name);
+       if (nukefull)
+           FreeWMPropertyString(tmp->full_name);
     } else
     if (tmp->icon_name == tmp->full_name) {
-       if (nukeicon && nukefull && isokay(tmp->icon_name)) XFree 
(tmp->icon_name);
-       if (nukename && isokay(tmp->name)) XFree (tmp->name);
+       if (nukeicon && nukefull)
+           FreeWMPropertyString(tmp->icon_name);
+       if (nukename)
+           FreeWMPropertyString(tmp->name);
     } else {
-       if (nukefull && isokay(tmp->full_name)) XFree (tmp->full_name);
-       if (nukename && isokay(tmp->name)) XFree (tmp->name);
-       if (nukeicon && isokay(tmp->icon_name)) XFree (tmp->icon_name);
+       if (nukefull)
+           FreeWMPropertyString(tmp->full_name);
+       if (nukename)
+           FreeWMPropertyString(tmp->name);
+       if (nukeicon)
+           FreeWMPropertyString(tmp->icon_name);
     }
-#undef isokay
     return;
 }
 
@@ -1465,18 +1473,8 @@
 
     switch (Event.xproperty.atom) {
       case XA_WM_NAME:
-#ifndef NO_LOCALE
        prop = GetWMPropertyString(Tmp_win->w, XA_WM_NAME);
        if (prop == NULL) return;
-#else /* NO_LOCALE */
-       if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0L, 
-                               MAX_NAME_LEN, False, XA_STRING, &actual,
-                               &actual_format, &nitems, &bytesafter,
-                               &prop) != Success ||
-           actual == None)
-         return;
-       if (!prop) prop = NoName;
-#endif /* NO_LOCALE */
 #ifdef CLAUDE
        if (strstr (prop, " - Mozilla")) {
          char *moz = strstr (prop, " - Mozilla");
@@ -1550,18 +1548,8 @@
        break;
 
       case XA_WM_ICON_NAME:
-#ifndef NO_LOCALE
        prop = GetWMPropertyString(Tmp_win->w, XA_WM_ICON_NAME);
        if (prop == NULL) return;
-#else /* NO_LOCALE */
-       if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0, 
-                               MAX_ICON_NAME_LEN, False, XA_STRING, &actual,
-                               &actual_format, &nitems, &bytesafter,
-                               &prop) != Success ||
-           actual == None)
-         return;
-       if (!prop) prop = NoName;
-#endif /* NO_LOCALE */
 #ifdef CLAUDE
        if (strstr (prop, " - Mozilla")) {
          char *moz = strstr (prop, " - Mozilla");
@@ -2246,41 +2234,6 @@
        XDeleteContext(dpy, Tmp_win->icon->w, TwmContext);
        XDeleteContext(dpy, Tmp_win->icon->w, ScreenContext);
     }
-    if (Tmp_win->title_height)
-    {
-       int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
-       XDeleteContext(dpy, Tmp_win->title_w, TwmContext);
-       XDeleteContext(dpy, Tmp_win->title_w, ScreenContext);
-       if (Tmp_win->hilite_wl)
-       {
-           XDeleteContext(dpy, Tmp_win->hilite_wl, TwmContext);
-           XDeleteContext(dpy, Tmp_win->hilite_wl, ScreenContext);
-       }
-       if (Tmp_win->hilite_wr)
-       {
-           XDeleteContext(dpy, Tmp_win->hilite_wr, TwmContext);
-           XDeleteContext(dpy, Tmp_win->hilite_wr, ScreenContext);
-       }
-       if (Tmp_win->lolite_wr)
-       {
-           XDeleteContext(dpy, Tmp_win->lolite_wr, TwmContext);
-           XDeleteContext(dpy, Tmp_win->lolite_wr, ScreenContext);
-       }
-       if (Tmp_win->lolite_wl)
-       {
-           XDeleteContext(dpy, Tmp_win->lolite_wl, TwmContext);
-           XDeleteContext(dpy, Tmp_win->lolite_wl, ScreenContext);
-       }
-       if (Tmp_win->titlebuttons) {
-           for (i = 0; i < nb; i++) {
-               XDeleteContext (dpy, Tmp_win->titlebuttons[i].window,
-                               TwmContext);
-               XDeleteContext (dpy, Tmp_win->titlebuttons[i].window,
-                               ScreenContext);
-           }
-        }
-    }
-
     if (Scr->cmapInfo.cmaps == &Tmp_win->cmaps)
        InstallWindowColormaps(DestroyNotify, &Scr->TwmRoot);
 
@@ -2298,14 +2251,28 @@
      *     9.  cwins
      *     10. titlebuttons
      *     11. window ring
+     *     12. (reserved for squeeze_info)
+     *     13. HiliteImage
+     *     14. iconslist
      */
+
+    DeleteWindowTitlebarButtons(Tmp_win);                      /* 10,13 */
     WMapDestroyWindow (Tmp_win);
     if (Tmp_win->gray) XFreePixmap (dpy, Tmp_win->gray);
 
+    /*
+     * The following should destroy all child windows of the frame too,
+     * which is most of the windows we're concerned with, so anything
+     * related to them must be done before here.
+     * Icons are not child windows.
+     */
     XDestroyWindow(dpy, Tmp_win->frame);
-    if (Tmp_win->icon && Tmp_win->icon->w && !Tmp_win->icon_not_ours) {
-       XDestroyWindow(dpy, Tmp_win->icon->w);
-       IconDown (Tmp_win);
+    if (Tmp_win->icon) {
+       if (Tmp_win->icon->w && !Tmp_win->icon_not_ours) {
+           XDestroyWindow(dpy, Tmp_win->icon->w);
+           IconDown (Tmp_win);
+       }
+       free (Tmp_win->icon);
     }
     Tmp_win->occupation = 0;
     RemoveIconManager(Tmp_win);                                        /* 7 */
@@ -2323,10 +2290,9 @@
       XFree ((char *)Tmp_win->class.res_name);
     if (Tmp_win->class.res_class && Tmp_win->class.res_class != NoName) /* 6 */
       XFree ((char *)Tmp_win->class.res_class);
-    free_cwins (Tmp_win);                              /* 9 */
-    if (Tmp_win->titlebuttons)                                 /* 10 */
-      free ((char *) Tmp_win->titlebuttons);
+    free_cwins (Tmp_win);                                      /* 9 */
     remove_window_from_ring (Tmp_win);                         /* 11 */
+    DeleteIconsList (Tmp_win);
 
     free((char *)Tmp_win);
 
--- icons.c
+++ icons.c
@@ -752,7 +752,8 @@
        }
     }
 
-    if (icon->match != match_none) AddToList (&tmp_win->iconslist, 
icon->pattern, (char*) icon);
+    if (icon->match != match_none)
+       AddToList (&tmp_win->iconslist, icon->pattern, (char*) icon);
 
     tmp_win->icon = icon;
     /* I need to figure out where to put the icon window now, because 
@@ -796,6 +797,15 @@
     return (0);
 }
 
+void DeleteIconsList(TwmWindow *tmp_win)
+{
+    /*
+     * Only the list itself needs to be freed, since the pointers it
+     * contains point into various lists that belong to Scr.
+     */
+    FreeList(&tmp_win->iconslist);
+}
+
 void ShrinkIconTitle (TwmWindow *tmp_win)
 {
     Icon       *icon;
--- icons.h
+++ icons.h
@@ -108,6 +108,7 @@
                                 int stepx, int stepy,
                                 char *ijust, char *just, char *align);
 extern int CreateIconWindow(TwmWindow *tmp_win, int def_x, int def_y);
+extern void DeleteIconsList(TwmWindow *tmp_win);
 extern void ShrinkIconTitle (TwmWindow *tmp_win);
 extern void ExpandIconTitle (TwmWindow *tmp_win);
 extern void ReshapeIcon (Icon *icon);
--- util.c
+++ util.c
@@ -3145,7 +3145,6 @@
 {
     name_list **list;
     char fullname [256];
-    int   startn;
     Image *image;
 
     if (name == NULL) return (None);
@@ -3154,9 +3153,10 @@
     list = &Scr->ImageCache;
 #ifdef XPM
     if ((name [0] == '@') || (strncmp (name, "xpm:", 4) == 0)) {
-       startn = (name [0] == '@') ? 1 : 4;
-       if ((image = (Image*) LookInNameList (*list, name)) == None) {
-           sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
+       sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
+
+       if ((image = (Image*) LookInNameList (*list, fullname)) == None) {
+           int startn = (name [0] == '@') ? 1 : 4;
            if ((image = GetXpmImage (name + startn, cp)) != None) {
                AddToList (list, fullname, (char*) image);
            }
@@ -3186,7 +3186,7 @@
 #endif
 #if !defined(VMS) || defined(HAVE_XWDFILE_H)
     if ((strncmp (name, "xwd:", 4) == 0) || (name [0] == '|')) {
-       startn = (name [0] == '|') ? 0 : 4;
+       int startn = (name [0] == '|') ? 0 : 4;
        if ((image = (Image*) LookInNameList (*list, name)) == None) {
            if ((image = GetXwdImage (&name [startn], cp)) != None) {
                AddToList (list, name, (char*) image);
@@ -3885,7 +3885,6 @@
     }
 }
 
-#ifndef NO_LOCALE
 /***********************************************************************
  *
  *  Procedure:
@@ -3904,6 +3903,19 @@
 
 unsigned char *GetWMPropertyString(Window w, Atom prop)
 {
+#ifdef NO_LOCALE
+    Atom actual_type;
+    int actual_format;
+    unsigned long nitems, bytesafter;
+    unsigned char *string;
+
+    if (XGetWindowProperty (dpy, w, prop, 0L, 200L, False,
+                           XA_STRING, &actual_type, &actual_format, &nitems,
+                           &bytesafter, &string) != Success)
+       string = NULL;
+
+    return string;
+#else
     XTextProperty      text_prop;
     char               **text_list;
     int                text_list_count;
@@ -3970,10 +3982,20 @@
     }
 
     return stringptr;
+#endif /* NO_LOCALE */
 }
+
+void FreeWMPropertyString(unsigned char *prop)
+{
+    if (prop && (char *)prop != NoName) {
+#ifdef NO_LOCALE
+       XFree(prop);
+#else
+       free(prop);
 #endif /* NO_LOCALE */
+    }
+}
 
-
 static void ConstrainLeftTop (int *value, int border)
 {
   if (*value < border) {
--- util.h
+++ util.h
@@ -140,9 +140,8 @@
 
 extern Image *GetImage (char *name, ColorPair cp);
 
-#ifndef NO_LOCALE
 extern unsigned char *GetWMPropertyString(Window w, Atom prop);
-#endif /* NO_LOCALE */
+extern void FreeWMPropertyString(unsigned char *prop);
 extern void ConstrainByBorders1 (int *left, int width, int *top, int height);
 extern void ConstrainByBorders (TwmWindow *twmwin,
                                int *left, int width,
-Olaf.
-- 
___ Olaf 'Rhialto' Seibert      -- You author it, and I'll reader it.
\X/ rhialto/at/xs4all.nl        -- Cetero censeo "authored" delendum esse.

Reply via email to