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