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-01-25 20:39:51.000000000 +0600 +++ icewm-1.2.37.my/src/wmclient.cc 2009-05-03 19:37:08.000000000 +0700 @@ -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-01-25 20:39:51.000000000 +0600 +++ icewm-1.2.37.my/src/wmclient.h 2009-03-09 21:52:44.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/wmframe.cc icewm-1.2.37.my/src/wmframe.cc --- icewm-1.2.37/src/wmframe.cc 2009-05-03 20:55:44.000000000 +0700 +++ icewm-1.2.37.my/src/wmframe.cc 2009-05-03 19:40:16.000000000 +0700 @@ -2301,6 +2301,8 @@ if (reclen < 2) return 0; + + /* iterate through pixmap+pask pairs, construct icons */ for (int i = 0; i < count; i++, elem += reclen) { Pixmap pixmap(elem[0]), mask(elem[1]); @@ -2340,12 +2344,12 @@ ref 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); g.fillRect(0, 0, w, h); - + #ifdef CONFIG_ANTIALIASING ref img2(new YIconImage(img->pixmap(), mask, img->width(), img->height(), w, h)); @@ -2403,11 +2406,42 @@ YIcon *oldFrameIcon(fFrameIcon); - if (client()->getWinIcons(&type, &count, &elem)) { + int res = client()->getNetWMIcon(&count, &elem); + if (res and count > 0) { + ref 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 + { fFrameIcon = newClientIcon(count/2, 2, elem); + } XFree(elem); } else if (client()->getKwmIcon(&count, &pixmap) && count == 2) { XWMHints *h = client()->hints(); 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-01-25 20:39:51.000000000 +0600 +++ icewm-1.2.37.my/src/ypixbuf.cc 2009-05-03 19:40:36.000000000 +0700 @@ -547,6 +547,12 @@ return pixels; } +ref YPixbuf::scale(int width, int height) { + ref pix; + pix.init(this); + return YPixbuf::scale(pix, width, height); +} + /******************************************************************************/ /******************************************************************************/ @@ -751,6 +757,47 @@ } } +/* Creates Imlib image from _NET_WM_ICON property */ +ref YPixbuf::createFromIconProperty(long *prop_pixels, + int width, int height) +{ + ref 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 +1053,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 &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-01-25 20:39:51.000000000 +0600 +++ icewm-1.2.37.my/src/ypixbuf.h 2009-05-03 19:22:39.000000000 +0700 @@ -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,9 +48,13 @@ void copyAlphaToMask(Pixmap pixmap, GC gc, int sx, int sy, int w, int h, int dx, int dy); + static ref createFromIconProperty(long *pixels, + int width, int height); + #endif #if defined(CONFIG_ANTIALIASING) || defined(CONFIG_IMLIB) static ref scale(ref source, int const width, int const height); + ref scale(int width, int height); private: YPixbuf(const ref &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-01-25 20:39:51.000000000 +0600 +++ icewm-1.2.37.my/src/yxapp.cc 2009-03-09 23:17:52.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" },