See attachment.
Applies to icewm_1.2.37 from squeeze.
Includes previous patch (xclock / xcalc icons).

A couple of functions were backported from 1.3 branch.
Psi / Skype / keepassx icons look fine now.
Sometimes psi icons are created b/w (open/close dialog box several times
to see this), but I guess it's not an icewm bug - at least, it can be
seen in LXDE, too. Probably something with psi/qt.
diff -ur icewm-1.2.37/src/wmclient.cc icewm-1.2.37.my/src/wmclient.cc
--- icewm-1.2.37/src/wmclient.cc	2009-03-10 22:38:55.000000000 +0600
+++ icewm-1.2.37.my/src/wmclient.cc	2009-03-10 22:38:57.000000000 +0600
@@ -1005,6 +1005,57 @@
     }
     return false;
 }
+
+static void *GetFullWindowProperty(Display *display, Window handle, Atom propAtom, int &itemCount, int itemSize)
+{
+    void *data = NULL;
+    itemCount = 0;
+
+    {
+        Atom r_type;
+        int r_format;
+        unsigned long nitems;
+        unsigned long bytes_remain;
+        unsigned char *prop;
+
+        while (XGetWindowProperty(display, handle,
+                               propAtom, 0, 1024*32, False, AnyPropertyType,
+                               &r_type, &r_format, &nitems, &bytes_remain,
+                               &prop) == Success && prop)
+        {
+            if (r_format == itemSize && nitems > 0) {
+                data = realloc(data, (itemCount + nitems) * itemSize / 8);
+                memcpy((char *)data + itemCount * itemSize / 8, prop, nitems * itemSize / 8);
+                itemCount += nitems;
+                XFree(prop);
+                if (bytes_remain == 0)
+                    break;
+                continue;
+            }
+            XFree(prop);
+            free(data);
+            itemCount = 0;
+            return NULL;
+        }
+    }
+    return data;
+}
+
+bool YFrameClient::getNetWMIcon(int *count, long **elem) {
+    *count = 0;
+    *elem = 0;
+
+    MSG(("get_net_wm_icon 1"));
+
+    *elem = (long *)GetFullWindowProperty(xapp->display(), handle(),
+                                          _XA_NET_WM_ICON, *count, 32);
+
+    if (elem != NULL)
+        return true;
+
+    return false;
+}
+
 #endif
 
 #if defined(GNOME1_HINTS) || defined(WMSPEC_HINTS)
diff -ur icewm-1.2.37/src/wmclient.h icewm-1.2.37.my/src/wmclient.h
--- icewm-1.2.37/src/wmclient.h	2009-03-10 22:38:55.000000000 +0600
+++ icewm-1.2.37.my/src/wmclient.h	2009-03-10 22:38:57.000000000 +0600
@@ -136,6 +136,7 @@
     long winHints() const { return fWinHints; }
 
 #ifdef WMSPEC_HINTS
+    bool getNetWMIcon(int *count, long **elem);
     bool getNetWMStateHint(long *mask, long *state);
     bool getNetWMDesktopHint(long *workspace);
     bool getNetWMStrut(int *left, int *right, int *top, int *bottom);
diff -ur icewm-1.2.37/src/ypixbuf.cc icewm-1.2.37.my/src/ypixbuf.cc
--- icewm-1.2.37/src/ypixbuf.cc	2009-03-10 22:38:55.000000000 +0600
+++ icewm-1.2.37.my/src/ypixbuf.cc	2009-03-10 22:38:57.000000000 +0600
@@ -751,6 +751,47 @@
     }
 }
 
+/* Creates Imlib image from _NET_WM_ICON property */
+ref<YPixbuf> YPixbuf::createFromIconProperty(long *prop_pixels,
+                                           int width, int height)
+{
+    ref<YPixbuf> pbuf;
+    unsigned char *data = NULL;
+
+    /*init data*/
+    data = new unsigned char[width * height * 3];
+    Pixel * t_alpha = new Pixel[width * height];
+
+    unsigned char * dscan = data;
+    unsigned char * ascan = (unsigned char * ) t_alpha;
+    for (int r = 0; r < height; r++) {
+        for (int c = 0; c < width; c++) {
+            unsigned long pix =
+                prop_pixels[c + r * width];
+
+            ascan[0] = (pix >> 24) & 0xFF;  // A;
+            ascan += 1;
+            
+            dscan[0] = (pix >> 16) & 0xFF;  // R
+            dscan[1] = (pix >>  8) & 0xFF;  // G
+            dscan[2] =         pix & 0xFF;  // B
+            dscan += 3;
+        }
+    }
+    
+    ImlibImage *img = Imlib_create_image_from_data(
+            hImlib,
+            data,
+            NULL,  // The pointer to the alpha data is currently unused and is there for future use
+            width, height);
+
+    /* free data */
+    delete[] data;
+
+    pbuf.init(new YPixbuf(width, height, img, t_alpha));
+    return pbuf;
+}
+
 void YPixbuf::copyAlphaToMask(Pixmap pixmap, GC gc, int sx, int sy,
                               int w, int h, int dx, int dy) {
     if (sx < 0) { dx-= sx; w+= sx; sx = 0; }
@@ -1051,6 +1047,12 @@
     delete[] empty;
 }
 
+YPixbuf::YPixbuf(int const width, int const height, ImlibImage * image, Pixel * alpha):
+    fAlpha(NULL) {
+    fImage = Imlib_clone_image(hImlib, image);
+    fAlpha = alpha;
+}
+
 YPixbuf::YPixbuf(const ref<YPixbuf> &source,
                  int const width, int const height):
     fImage(NULL), fAlpha(NULL)
diff -ur icewm-1.2.37/src/ypixbuf.h icewm-1.2.37.my/src/ypixbuf.h
--- icewm-1.2.37/src/ypixbuf.h	2009-03-10 22:38:55.000000000 +0600
+++ icewm-1.2.37.my/src/ypixbuf.h	2009-03-10 22:38:56.000000000 +0600
@@ -36,6 +36,7 @@
     YPixbuf(Drawable drawable, Pixmap mask,
             int dWidth, int dHeight, int width, int height, int x = 0, int y = 0,
             bool fullAlpha = true);
+    YPixbuf(int const width, int const height, ImlibImage * fImage, Pixel * alpha);
 
     ~YPixbuf();
 
@@ -47,6 +48,9 @@
     void copyAlphaToMask(Pixmap pixmap, GC gc, int sx, int sy,
                          int w, int h,
                          int dx, int dy);
+    static ref<YPixbuf> createFromIconProperty(long *pixels,
+                                              int width, int height);
+
 #endif
 #if defined(CONFIG_ANTIALIASING) || defined(CONFIG_IMLIB)
     static ref<YPixbuf> scale(ref<YPixbuf> source, int const width, int const height);
diff -ur icewm-1.2.37/src/yxapp.cc icewm-1.2.37.my/src/yxapp.cc
--- icewm-1.2.37/src/yxapp.cc	2009-03-10 22:38:56.000000000 +0600
+++ icewm-1.2.37.my/src/yxapp.cc	2009-03-10 22:38:57.000000000 +0600
@@ -91,6 +91,7 @@
 Atom _XA_NET_WM_WINDOW_TYPE_SPLASH;
 
 Atom _XA_NET_WM_NAME;
+Atom _XA_NET_WM_ICON;
 Atom _XA_NET_WM_PID;
 
 Atom _XA_NET_WM_USER_TIME;
@@ -310,6 +311,7 @@
         { &_XA_NET_WM_WINDOW_TYPE_SPLASH, "_NET_WM_WINDOW_TYPE_SPLASH" },
 
         { &_XA_NET_WM_NAME, "_NET_WM_NAME" },
+        { &_XA_NET_WM_ICON, "_NET_WM_ICON" },
         { &_XA_NET_WM_PID, "_NET_WM_PID" },
         { &_XA_NET_WM_USER_TIME, "_NET_WM_USER_TIME" },
         { &_XA_NET_WM_STATE_DEMANDS_ATTENTION, "_NET_WM_STATE_DEMANDS_ATTENTION" },
diff -ur icewm-1.2.37/src/wmframe.cc icewm-1.2.37.my/src/wmframe.cc
--- icewm-1.2.37/src/wmframe.cc	2009-01-25 20:39:51.000000000 +0600
+++ icewm-1.2.37.my/src/wmframe.cc	2009-03-10 23:13:25.000000000 +0600
@@ -2340,7 +2340,7 @@
             ref<YPixmap> img(new YPixmap(w, h));
             Graphics g(img, 0, 0);
 
-            g.setColorPixel(1);
+            g.setColorPixel(0xffffff);
             g.fillRect(0, 0, w, h);
             g.setColorPixel(0);
             g.setClipMask(pixmap);
@@ -2403,7 +2403,35 @@
 
     YIcon *oldFrameIcon(fFrameIcon);
 
-    if (client()->getWinIcons(&type, &count, &elem)) {
+    if (client()->getNetWMIcon(&count, &elem) and count > 0) {
+        ref<YIconImage> icons[4];
+        int sizes[] = { YIcon::smallSize(), YIcon::largeSize(), YIcon::hugeSize() };
+
+        // find icons that match Small-/Large-/HugeIconSize, icons[3] is
+        // fallback if none matches
+        for (long *e = elem; e - count < elem; e += 2 + e[0] * e[1]) {
+            int i = 0;
+            for (; i < 3; i++)
+                if (e[0] == sizes[i] && e[0] == e[1])
+                    break;
+            if (icons[i] == null)
+                icons[i] = YIconImage::createFromIconProperty(e + 2, e[0], e[1]);
+        }
+
+        /* 
+        // use the next larger existing icon to scale those that were missing
+        for (int i = 0; i < 3; i++)
+            if (icons[i] == null)
+                for (int j = i + 1; j < 4; j++)
+                    if (icons[j] != null) {
+                        icons[i] = icons[j]->scale(sizes[i], sizes[i]);
+                        break;
+                    }
+        */
+
+        fFrameIcon = new YIcon(icons[0], icons[1], icons[2]);
+        XFree(elem);
+    } else if (client()->getWinIcons(&type, &count, &elem)) {
         if (type == _XA_WIN_ICONS)
             fFrameIcon = newClientIcon(elem[0], elem[1], elem + 2);
         else // compatibility

Reply via email to