diff --git a/build/linux/platform_specific_code/juce_linux_Windowing.cpp b/build/linux/platform_specific_code/juce_linux_Windowing.cpp index c869e654cd..cac2a2cc36 100644 --- a/build/linux/platform_specific_code/juce_linux_Windowing.cpp +++ b/build/linux/platform_specific_code/juce_linux_Windowing.cpp @@ -452,6 +452,7 @@ static bool isShmAvailable() throw() } #endif + //============================================================================== class XBitmapImage : public Image { @@ -697,6 +698,7 @@ public: checkMessageManagerIsLocked deleteTaskBarIcon(); + deleteIconPixmaps(); destroyWindow(); @@ -1099,7 +1101,7 @@ public: void setIcon (const Image& newIcon) { const int dataSize = newIcon.getWidth() * newIcon.getHeight() + 2; - uint32* const data = (uint32*) juce_malloc (dataSize); + uint32* const data = (uint32*) juce_malloc (dataSize * sizeof (uint32)); int index = 0; data[index++] = newIcon.getWidth(); @@ -1114,9 +1116,46 @@ public: XA_CARDINAL, 32, PropModeReplace, (unsigned char*) data, dataSize); - XSync (display, False); - juce_free (data); + + deleteIconPixmaps(); + + XWMHints* wmHints = XGetWMHints (display, windowH); + + if (wmHints == 0) + wmHints = XAllocWMHints(); + + wmHints->flags |= IconPixmapHint | IconMaskHint; + wmHints->icon_pixmap = juce_createColourPixmapFromImage (display, newIcon); + wmHints->icon_mask = juce_createMaskPixmapFromImage (display, newIcon); + + XSetWMHints (display, windowH, wmHints); + XFree (wmHints); + + XSync (display, False); + } + + void deleteIconPixmaps() + { + XWMHints* wmHints = XGetWMHints (display, windowH); + + if (wmHints != 0) + { + if ((wmHints->flags & IconPixmapHint) != 0) + { + wmHints->flags &= ~IconPixmapHint; + XFreePixmap (display, wmHints->icon_pixmap); + } + + if ((wmHints->flags & IconMaskHint) != 0) + { + wmHints->flags &= ~IconMaskHint; + XFreePixmap (display, wmHints->icon_mask); + } + + XSetWMHints (display, windowH, wmHints); + XFree (wmHints); + } } //============================================================================== @@ -2638,6 +2677,59 @@ bool Desktop::isScreenSaverEnabled() throw() } //============================================================================== +static Pixmap juce_createColourPixmapFromImage (Display* display, const Image& image) +{ + const int width = image.getWidth(); + const int height = image.getHeight(); + uint32* const colour = (uint32*) juce_malloc (width * height * sizeof (uint32)); + int index = 0; + + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) + colour[index++] = image.getPixelAt (x, y).getARGB(); + + XImage* ximage = XCreateImage (display, CopyFromParent, 24, ZPixmap, + 0, (char*) colour, width, height, 32, 0); + + Pixmap pixmap = XCreatePixmap (display, DefaultRootWindow (display), + width, height, 24); + + GC gc = XCreateGC (display, pixmap, 0, 0); + XPutImage (display, pixmap, gc, ximage, 0, 0, 0, 0, width, height); + XFreeGC (display, gc); + juce_free (colour); + + return pixmap; +} + +static Pixmap juce_createMaskPixmapFromImage (Display* display, const Image& image) +{ + const int width = image.getWidth(); + const int height = image.getHeight(); + const int stride = (width + 7) >> 3; + uint8* const mask = (uint8*) juce_calloc (stride * height); + const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); + + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + const uint8 bit = (uint8) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); + const int offset = y * stride + (x >> 3); + + if (image.getPixelAt (x, y).getAlpha() >= 128) + mask[offset] |= bit; + } + } + + Pixmap pixmap = XCreatePixmapFromBitmapData (display, DefaultRootWindow (display), + (char*) mask, width, height, 1, 0, 1); + + juce_free (mask); + + return pixmap; +} + void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { Window root = RootWindow (display, DefaultScreen (display)); @@ -2669,7 +2761,7 @@ void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hot uint8* const maskPlane = (uint8*) juce_calloc (stride * cursorH); uint8* const sourcePlane = (uint8*) juce_calloc (stride * cursorH); - bool msbfirst = (BitmapBitOrder (display) == MSBFirst); + const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); for (int y = cursorH; --y >= 0;) {