Better patch is attached.
This one also works for applications that only export "large" icons
(larger then 48x48) - for example, djview4.
Packages for lenny/i386:
http://vnaum.com/misc/200905/icewm/
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<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);
g.fillRect(0, 0, w, h);
-
+
#ifdef CONFIG_ANTIALIASING
ref<YIconImage> 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<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
+ {
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> YPixbuf::scale(int width, int height) {
+ ref<YPixbuf> pix;
+ pix.init(this);
+ return YPixbuf::scale(pix, width, height);
+}
+
/******************************************************************************/
/******************************************************************************/
@@ -751,6 +757,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; }
@@ -1001,6 +1023,16 @@
#ifdef CONFIG_IMLIB
+
+bool YPixbuf::dumpToFile(char const *filename) const
+{
+ if (!this)
+ {
+ return false;
+ }
+ Imlib_save_image(hImlib, fImage, filename, NULL);
+}
+
YPixbuf::YPixbuf(char const *filename, bool fullAlpha):
fImage(NULL), fAlpha(NULL)
{
@@ -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<YPixbuf> &source,
int const width, int const height):
fImage(NULL), fAlpha(NULL)
@@ -1108,6 +1116,8 @@
Pixel * pixels(copyImageToPixbuf<3>(*image, 3 * w));
fImage = Imlib_create_image_from_data(hImlib, pixels, NULL, w, h);
+ // fImage = Imlib_create_image_from_drawable(hImlib, drawable, mask, x, y, w, h);
+
delete[] pixels;
XDestroyImage(image);
} else {
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<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);
+ ref<YPixbuf> scale(int width, int height);
private:
YPixbuf(const ref<YPixbuf> &source,
int const width, int const height);
@@ -89,6 +94,8 @@
bool valid() const { return fImage && fImage->rgb_data; }
operator bool() const { return valid(); }
bool inlineAlpha() const { return false; };
+
+ bool dumpToFile(char const * filename) const;
private:
void allocAlphaChannel();
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" },