diff --git a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp index 63085208b3..51c1b13caa 100644 --- a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp +++ b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp @@ -1078,7 +1078,7 @@ public: else filter->getStateInformation (chunkMemory); - *data = (void*) chunkMemory; + *data = (void*) chunkMemory.getData(); // because the chunk is only needed temporarily by the host (or at least you'd // hope so) we'll give it a while and then free it in the timer callback. diff --git a/extras/audio plugins/wrapper/juce_PluginHostType.h b/extras/audio plugins/wrapper/juce_PluginHostType.h index ae70136039..9148aa044d 100644 --- a/extras/audio plugins/wrapper/juce_PluginHostType.h +++ b/extras/audio plugins/wrapper/juce_PluginHostType.h @@ -133,13 +133,14 @@ private: buffer.calloc (size + 8); #if JUCE_WINDOWS - GetModuleFileNameW (0, (WCHAR*) buffer, size / sizeof (WCHAR)); - return String (reinterpret_cast ((char*) buffer), size); + WCHAR* w = reinterpret_cast (buffer.getData()); + GetModuleFileNameW (0, w, size / sizeof (WCHAR)); + return String (w, size); #elif JUCE_MAC - _NSGetExecutablePath ((char*) buffer, &size); + _NSGetExecutablePath (buffer.getData(), &size); return String::fromUTF8 (buffer, size); #elif JUCE_LINUX - readlink ("/proc/self/exe", (char*) buffer, size); + readlink ("/proc/self/exe", buffer.getData(), size); return String::fromUTF8 (buffer, size); #else #error diff --git a/juce_Config.h b/juce_Config.h index 0614cb57d0..91f22dc768 100644 --- a/juce_Config.h +++ b/juce_Config.h @@ -179,6 +179,12 @@ #define JUCE_USE_XSHM 1 #endif +/** JUCE_USE_XRENDER: Uses XRender to allow semi-transparent windowing on Linux. +*/ +#ifndef JUCE_USE_XRENDER + //#define JUCE_USE_XRENDER 1 +#endif + //============================================================================= /** JUCE_PLUGINHOST_VST: Enables the VST audio plugin hosting classes. This requires the Steinberg VST SDK to be installed on your machine, and should be left turned off unless diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index da64b24a65..2260f9f955 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -235,6 +235,10 @@ #define JUCE_USE_XSHM 1 #endif +#ifndef JUCE_USE_XRENDER + //#define JUCE_USE_XRENDER 1 +#endif + #ifndef JUCE_PLUGINHOST_VST // #define JUCE_PLUGINHOST_VST 1 #endif @@ -520,6 +524,12 @@ public: #include #endif +#if JUCE_USE_XRENDER + // If you're missing these headers, try installing the libxrender-dev and libxcomposite-dev + #include + #include +#endif + #if JUCE_OPENGL #include #endif @@ -230224,8 +230234,8 @@ public: int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd); (void) ret; jassert (ret == 0); - setNonBlocking (fd[0]); - setNonBlocking (fd[1]); + //setNonBlocking (fd[0]); + //setNonBlocking (fd[1]); } ~InternalMessageQueue() @@ -231360,8 +231370,6 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() #if JUCE_USE_XSHM static bool isShmAvailable() throw() { - ScopedXLock xlock; - static bool isChecked = false; static bool isAvailable = false; @@ -231372,6 +231380,8 @@ static bool isShmAvailable() throw() int major, minor; Bool pixmaps; + ScopedXLock xlock; + if (XShmQueryVersion (display, &major, &minor, &pixmaps)) { trapErrors(); @@ -231418,14 +231428,237 @@ static bool isShmAvailable() throw() } #endif +#if JUCE_USE_XRENDER + +namespace XRender +{ + typedef Status (*tXRenderQueryVersion) (Display*, int*, int*); + typedef XRenderPictFormat* (*tXrenderFindStandardFormat) (Display*, int); + typedef XRenderPictFormat* (*tXRenderFindFormat) (Display*, unsigned long, XRenderPictFormat*, int); + typedef XRenderPictFormat* (*tXRenderFindVisualFormat) (Display*, Visual*); + + static tXRenderQueryVersion xRenderQueryVersion = 0; + static tXrenderFindStandardFormat xRenderFindStandardFormat = 0; + static tXRenderFindFormat xRenderFindFormat = 0; + static tXRenderFindVisualFormat xRenderFindVisualFormat = 0; + + static bool isAvailable() + { + static bool isChecked = false; + static bool isAvailable = false; + + if (! isChecked) + { + ScopedXLock xlock; + + isChecked = true; + + if (xRenderQueryVersion == 0) + { + void* h = dlopen ("libXrender.so", RTLD_GLOBAL | RTLD_NOW); + + if (h != 0) + { + xRenderQueryVersion = (tXRenderQueryVersion) dlsym (h, "XRenderQueryVersion"); + xRenderFindStandardFormat = (tXrenderFindStandardFormat) dlsym (h, "XrenderFindStandardFormat"); + xRenderFindFormat = (tXRenderFindFormat) dlsym (h, "XRenderFindFormat"); + xRenderFindVisualFormat = (tXRenderFindVisualFormat) dlsym (h, "XRenderFindVisualFormat"); + } + } + + if (xRenderQueryVersion != 0 + && xRenderFindStandardFormat != 0 + && xRenderFindFormat != 0 + && xRenderFindVisualFormat != 0) + { + int major, minor; + if (xRenderQueryVersion (display, &major, &minor)) + isAvailable = true; + } + } + + return isAvailable; + } + + static XRenderPictFormat* findPictureFormat() + { + ScopedXLock xlock; + + XRenderPictFormat* pictFormat = 0; + + if (isAvailable()) + { + pictFormat = xRenderFindStandardFormat (display, PictStandardARGB32); + + if (pictFormat == 0) + { + XRenderPictFormat desiredFormat; + desiredFormat.type = PictTypeDirect; + desiredFormat.depth = 32; + + desiredFormat.direct.alphaMask = 0xff; + desiredFormat.direct.redMask = 0xff; + desiredFormat.direct.greenMask = 0xff; + desiredFormat.direct.blueMask = 0xff; + + desiredFormat.direct.alpha = 24; + desiredFormat.direct.red = 16; + desiredFormat.direct.green = 8; + desiredFormat.direct.blue = 0; + + pictFormat = xRenderFindFormat (display, + PictFormatType | PictFormatDepth + | PictFormatRedMask | PictFormatRed + | PictFormatGreenMask | PictFormatGreen + | PictFormatBlueMask | PictFormatBlue + | PictFormatAlphaMask | PictFormatAlpha, + &desiredFormat, + 0); + } + } + + return pictFormat; + } +} + +#endif + +namespace Visuals +{ + static Visual* findVisualWithDepth (const int desiredDepth) throw() + { + ScopedXLock xlock; + + Visual* visual = 0; + int numVisuals = 0; + long desiredMask = VisualNoMask; + XVisualInfo desiredVisual; + + desiredVisual.screen = DefaultScreen (display); + desiredVisual.depth = desiredDepth; + + desiredMask = VisualScreenMask | VisualDepthMask; + + if (desiredDepth == 32) + { + desiredVisual.c_class = TrueColor; + desiredVisual.red_mask = 0x00FF0000; + desiredVisual.green_mask = 0x0000FF00; + desiredVisual.blue_mask = 0x000000FF; + desiredVisual.bits_per_rgb = 8; + + desiredMask |= VisualClassMask; + desiredMask |= VisualRedMaskMask; + desiredMask |= VisualGreenMaskMask; + desiredMask |= VisualBlueMaskMask; + desiredMask |= VisualBitsPerRGBMask; + } + + XVisualInfo* xvinfos = XGetVisualInfo (display, + desiredMask, + &desiredVisual, + &numVisuals); + + if (xvinfos != 0) + { + for (int i = 0; i < numVisuals; i++) + { + if (xvinfos[i].depth == desiredDepth) + { + visual = xvinfos[i].visual; + break; + } + } + + XFree (xvinfos); + } + + return visual; + } + + static Visual* findVisualFormat (const int desiredDepth, int& matchedDepth) throw() + { + Visual* visual = 0; + + if (desiredDepth == 32) + { +#if JUCE_USE_XSHM + if (isShmAvailable()) + { +#if JUCE_USE_XRENDER + if (XRender::isAvailable()) + { + XRenderPictFormat* pictFormat = XRender::findPictureFormat(); + + if (pictFormat != 0) + { + int numVisuals = 0; + XVisualInfo desiredVisual; + desiredVisual.screen = DefaultScreen (display); + desiredVisual.depth = 32; + desiredVisual.bits_per_rgb = 8; + + XVisualInfo* xvinfos = XGetVisualInfo (display, + VisualScreenMask | VisualDepthMask | VisualBitsPerRGBMask, + &desiredVisual, &numVisuals); + if (xvinfos != 0) + { + for (int i = 0; i < numVisuals; ++i) + { + XRenderPictFormat* pictVisualFormat = XRender::xRenderFindVisualFormat (display, xvinfos[i].visual); + + if (pictVisualFormat != 0 + && pictVisualFormat->type == PictTypeDirect + && pictVisualFormat->direct.alphaMask) + { + visual = xvinfos[i].visual; + matchedDepth = 32; + break; + } + } + + XFree (xvinfos); + } + } + } +#endif + if (visual == 0) + { + visual = findVisualWithDepth (32); + if (visual != 0) + matchedDepth = 32; + } + } +#endif + } + + if (visual == 0 && desiredDepth >= 24) + { + visual = findVisualWithDepth (24); + if (visual != 0) + matchedDepth = 24; + } + + if (visual == 0 && desiredDepth >= 16) + { + visual = findVisualWithDepth (16); + if (visual != 0) + matchedDepth = 16; + } + + return visual; + } +} + class XBitmapImage : public Image { public: XBitmapImage (const PixelFormat format_, const int w, const int h, - const bool clearImage, const bool is16Bit_) + const bool clearImage, const int imageDepth_, Visual* visual) : Image (format_, w, h), - is16Bit (is16Bit_) + imageDepth (imageDepth_), + gc (None) { jassert (format_ == RGB || format_ == ARGB); @@ -231433,16 +231666,19 @@ public: lineStride = ((w * pixelStride + 3) & ~3); ScopedXLock xlock; - Visual* const visual = DefaultVisual (display, DefaultScreen (display)); #if JUCE_USE_XSHM usingXShm = false; - if ((! is16Bit) && isShmAvailable()) + if ((imageDepth > 16) && isShmAvailable()) { zerostruct (segmentInfo); - xImage = XShmCreateImage (display, visual, 24, ZPixmap, 0, &segmentInfo, w, h); + segmentInfo.shmid = -1; + segmentInfo.shmaddr = (char *) -1; + segmentInfo.readOnly = False; + + xImage = XShmCreateImage (display, visual, imageDepth, ZPixmap, 0, &segmentInfo, w, h); if (xImage != 0) { @@ -231450,31 +231686,31 @@ public: xImage->bytes_per_line * xImage->height, IPC_CREAT | 0777)) >= 0) { - segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - - if (segmentInfo.shmaddr != (void*) -1) + if (segmentInfo.shmid != -1) { - segmentInfo.readOnly = False; + segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - xImage->data = segmentInfo.shmaddr; - imageData = (uint8*) segmentInfo.shmaddr; + if (segmentInfo.shmaddr != (void*) -1) + { + segmentInfo.readOnly = False; - XSync (display, False); + xImage->data = segmentInfo.shmaddr; + imageData = (uint8*) segmentInfo.shmaddr; - if (XShmAttach (display, &segmentInfo) != 0) - { - XSync (display, False); - usingXShm = true; + if (XShmAttach (display, &segmentInfo) != 0) + { + usingXShm = true; + } + else + { + jassertfalse + } } else { - jassertfalse + shmctl (segmentInfo.shmid, IPC_RMID, 0); } } - else - { - shmctl (segmentInfo.shmid, IPC_RMID, 0); - } } } } @@ -231506,7 +231742,7 @@ public: xImage->green_mask = 0x0000FF00; xImage->blue_mask = 0x000000FF; - if (is16Bit) + if (imageDepth == 16) { const int pixelStride = 2; const int lineStride = ((w * pixelStride + 3) & ~3); @@ -231556,12 +231792,22 @@ public: { ScopedXLock xlock; - static GC gc = 0; - if (gc == 0) - gc = DefaultGC (display, DefaultScreen (display)); + { + XGCValues gcvalues; + gcvalues.foreground = None; + gcvalues.background = None; + gcvalues.function = GXcopy; + gcvalues.plane_mask = AllPlanes; + gcvalues.clip_mask = None; + gcvalues.graphics_exposures = False; - if (is16Bit) + gc = XCreateGC (display, window, + GCBackground | GCForeground | GCFunction | GCPlaneMask | GCClipMask | GCGraphicsExposures, + &gcvalues); + } + + if (imageDepth == 16) { const uint32 rMask = xImage->red_mask; const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); @@ -231605,9 +231851,11 @@ public: private: XImage* xImage; - const bool is16Bit; + const int imageDepth; HeapBlock imageData16Bit; + GC gc; + #if JUCE_USE_XSHM XShmSegmentInfo segmentInfo; bool usingXShm; @@ -231640,7 +231888,9 @@ public: wh (0), taskbarImage (0), fullScreen (false), - mapped (false) + mapped (false), + visual (0), + depth (0) { // it's dangerous to create a window on a thread other than the message thread.. checkMessageManagerIsLocked @@ -232822,7 +233072,8 @@ private: (totalArea.getWidth() + 31) & ~31, (totalArea.getHeight() + 31) & ~31, false, - peer->depthIs16Bit); + peer->depth, + peer->visual); } startTimer (repaintTimerPeriod); @@ -232832,7 +233083,20 @@ private: context.setOrigin (-totalArea.getX(), -totalArea.getY()); if (context.clipToRectangleList (originalRepaintRegion)) + { + if (peer->depth == 32) + { + RectangleList::Iterator i (originalRepaintRegion); + + while (i.next()) + { + const Rectangle& r = *i.getRectangle(); + image->clear (r.getX() - totalArea.getX(), r.getY() - totalArea.getY(), r.getWidth(), r.getHeight()); + } + } + peer->handlePaint (context); + } if (! peer->maskedRegion.isEmpty()) originalRepaintRegion.subtract (peer->maskedRegion); @@ -232877,7 +233141,9 @@ private: Window windowH, parentWindow; int wx, wy, ww, wh; Image* taskbarImage; - bool fullScreen, mapped, depthIs16Bit; + bool fullScreen, mapped; + int depth; + Visual* visual; BorderSize windowBorder; struct MotifWmHints @@ -233161,47 +233427,30 @@ private: const int screen = DefaultScreen (display); Window root = RootWindow (display, screen); - // Attempt to create a 24-bit window on the default screen. If this is not - // possible then exit - XVisualInfo desiredVisual; - desiredVisual.screen = screen; - desiredVisual.depth = 24; - depthIs16Bit = false; - - int numVisuals; - XVisualInfo* visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, - &desiredVisual, &numVisuals); + // Try to obtain a 32-bit visual or fallback to 24 or 16 + visual = Visuals::findVisualFormat ((styleFlags & windowIsSemiTransparent) ? 32 : 24, depth); - if (numVisuals < 1 || visuals == 0) + if (visual == 0) { - XFree (visuals); - desiredVisual.depth = 16; - - visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, - &desiredVisual, &numVisuals); - - if (numVisuals < 1 || visuals == 0) - { - Logger::outputDebugString ("ERROR: System doesn't support 24 or 16 bit RGB display.\n"); - Process::terminate(); - } - - depthIs16Bit = true; + Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); + Process::terminate(); } - XFree (visuals); + // Create and install a colormap suitable fr our visual + Colormap colormap = XCreateColormap (display, root, visual, AllocNone); + XInstallColormap (display, colormap); // Set up the window attributes XSetWindowAttributes swa; swa.border_pixel = 0; swa.background_pixmap = None; - swa.colormap = DefaultColormap (display, screen); + swa.colormap = colormap; swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False; swa.event_mask = eventMask; Window wndH = XCreateWindow (display, root, 0, 0, 1, 1, - 0, 0, InputOutput, (Visual*) CopyFromParent, + 0, depth, InputOutput, visual, CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, &swa); @@ -233227,23 +233476,6 @@ private: XSetWMHints (display, wndH, wmHints); XFree (wmHints); - if ((styleFlags & windowIsSemiTransparent) != 0) - { - //xxx - } - - if ((styleFlags & windowAppearsOnTaskbar) != 0) - { - //xxx - } - - //XSetTransientForHint (display, wndH, RootWindow (display, DefaultScreen (display))); - - if ((styleFlags & windowHasTitleBar) == 0) - removeWindowDecorations (wndH); - else - addWindowButtons (wndH); - // Set window manager protocols XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace, (unsigned char*) wm_ProtocolList, 2); @@ -233262,6 +233494,24 @@ private: XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace, (const unsigned char*) &dndVersion, 1); + if ((windowStyleFlags & windowHasDropShadow) != 0 + && Desktop::canUseSemiTransparentWindows()) + { + } + + if ((styleFlags & windowIsTemporary) != 0) + { + } + + if ((styleFlags & windowAppearsOnTaskbar) == 0) + { + } + + if ((styleFlags & windowHasTitleBar) == 0) + removeWindowDecorations (wndH); + else + addWindowButtons (wndH); + // Set window name setWindowTitle (wndH, getComponent()->getName()); @@ -233840,7 +234090,11 @@ void Desktop::createMouseInputSources() bool Desktop::canUseSemiTransparentWindows() throw() { - return false; + int matchedDepth = 0; + const int desiredDepth = 32; + + return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0 + && (matchedDepth == desiredDepth); } const Point Desktop::getMousePosition() @@ -234358,9 +234612,6 @@ bool AlertWindow::showNativeDialogBox (const String& title, const String& bodyText, bool isOkCancel) { - // xxx this is supposed to pop up an alert! - Logger::outputDebugString (title + ": " + bodyText); - // use a non-native one for the time being.. if (isOkCancel) return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index a74dd76637..4edc763f2f 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -43,7 +43,7 @@ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 51 -#define JUCE_BUILDNUMBER 8 +#define JUCE_BUILDNUMBER 9 #define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8) + JUCE_BUILDNUMBER) @@ -256,6 +256,10 @@ #define JUCE_USE_XSHM 1 #endif +#ifndef JUCE_USE_XRENDER + //#define JUCE_USE_XRENDER 1 +#endif + #ifndef JUCE_PLUGINHOST_VST // #define JUCE_PLUGINHOST_VST 1 #endif diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 9fa5ece878..42f2ec7b0b 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 51 -#define JUCE_BUILDNUMBER 8 +#define JUCE_BUILDNUMBER 9 /** Current Juce version number. diff --git a/src/native/linux/juce_linux_Messaging.cpp b/src/native/linux/juce_linux_Messaging.cpp index 22beb09dda..c17288b98e 100644 --- a/src/native/linux/juce_linux_Messaging.cpp +++ b/src/native/linux/juce_linux_Messaging.cpp @@ -66,8 +66,8 @@ public: int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd); (void) ret; jassert (ret == 0); - setNonBlocking (fd[0]); - setNonBlocking (fd[1]); + //setNonBlocking (fd[0]); + //setNonBlocking (fd[1]); } ~InternalMessageQueue() diff --git a/src/native/linux/juce_linux_NativeIncludes.h b/src/native/linux/juce_linux_NativeIncludes.h index 1b4ae66a18..3dee05039f 100644 --- a/src/native/linux/juce_linux_NativeIncludes.h +++ b/src/native/linux/juce_linux_NativeIncludes.h @@ -85,6 +85,12 @@ #include #endif +#if JUCE_USE_XRENDER + // If you're missing these headers, try installing the libxrender-dev and libxcomposite-dev + #include + #include +#endif + #if JUCE_OPENGL /* Got an include error here? diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index ed98d81ad7..f7a4e0d643 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -177,8 +177,6 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() #if JUCE_USE_XSHM static bool isShmAvailable() throw() { - ScopedXLock xlock; - static bool isChecked = false; static bool isAvailable = false; @@ -189,6 +187,8 @@ static bool isShmAvailable() throw() int major, minor; Bool pixmaps; + ScopedXLock xlock; + if (XShmQueryVersion (display, &major, &minor, &pixmaps)) { trapErrors(); @@ -235,15 +235,241 @@ static bool isShmAvailable() throw() } #endif +//============================================================================== +#if JUCE_USE_XRENDER + +namespace XRender +{ + typedef Status (*tXRenderQueryVersion) (Display*, int*, int*); + typedef XRenderPictFormat* (*tXrenderFindStandardFormat) (Display*, int); + typedef XRenderPictFormat* (*tXRenderFindFormat) (Display*, unsigned long, XRenderPictFormat*, int); + typedef XRenderPictFormat* (*tXRenderFindVisualFormat) (Display*, Visual*); + + static tXRenderQueryVersion xRenderQueryVersion = 0; + static tXrenderFindStandardFormat xRenderFindStandardFormat = 0; + static tXRenderFindFormat xRenderFindFormat = 0; + static tXRenderFindVisualFormat xRenderFindVisualFormat = 0; + + static bool isAvailable() + { + static bool isChecked = false; + static bool isAvailable = false; + + if (! isChecked) + { + ScopedXLock xlock; + + isChecked = true; + + if (xRenderQueryVersion == 0) + { + void* h = dlopen ("libXrender.so", RTLD_GLOBAL | RTLD_NOW); + + if (h != 0) + { + xRenderQueryVersion = (tXRenderQueryVersion) dlsym (h, "XRenderQueryVersion"); + xRenderFindStandardFormat = (tXrenderFindStandardFormat) dlsym (h, "XrenderFindStandardFormat"); + xRenderFindFormat = (tXRenderFindFormat) dlsym (h, "XRenderFindFormat"); + xRenderFindVisualFormat = (tXRenderFindVisualFormat) dlsym (h, "XRenderFindVisualFormat"); + } + } + + if (xRenderQueryVersion != 0 + && xRenderFindStandardFormat != 0 + && xRenderFindFormat != 0 + && xRenderFindVisualFormat != 0) + { + int major, minor; + if (xRenderQueryVersion (display, &major, &minor)) + isAvailable = true; + } + } + + return isAvailable; + } + + static XRenderPictFormat* findPictureFormat() + { + ScopedXLock xlock; + + XRenderPictFormat* pictFormat = 0; + + if (isAvailable()) + { + pictFormat = xRenderFindStandardFormat (display, PictStandardARGB32); + + if (pictFormat == 0) + { + XRenderPictFormat desiredFormat; + desiredFormat.type = PictTypeDirect; + desiredFormat.depth = 32; + + desiredFormat.direct.alphaMask = 0xff; + desiredFormat.direct.redMask = 0xff; + desiredFormat.direct.greenMask = 0xff; + desiredFormat.direct.blueMask = 0xff; + + desiredFormat.direct.alpha = 24; + desiredFormat.direct.red = 16; + desiredFormat.direct.green = 8; + desiredFormat.direct.blue = 0; + + pictFormat = xRenderFindFormat (display, + PictFormatType | PictFormatDepth + | PictFormatRedMask | PictFormatRed + | PictFormatGreenMask | PictFormatGreen + | PictFormatBlueMask | PictFormatBlue + | PictFormatAlphaMask | PictFormatAlpha, + &desiredFormat, + 0); + } + } + + return pictFormat; + } +} + +#endif + + +//============================================================================== +namespace Visuals +{ + static Visual* findVisualWithDepth (const int desiredDepth) throw() + { + ScopedXLock xlock; + + Visual* visual = 0; + int numVisuals = 0; + long desiredMask = VisualNoMask; + XVisualInfo desiredVisual; + + desiredVisual.screen = DefaultScreen (display); + desiredVisual.depth = desiredDepth; + + desiredMask = VisualScreenMask | VisualDepthMask; + + if (desiredDepth == 32) + { + desiredVisual.c_class = TrueColor; + desiredVisual.red_mask = 0x00FF0000; + desiredVisual.green_mask = 0x0000FF00; + desiredVisual.blue_mask = 0x000000FF; + desiredVisual.bits_per_rgb = 8; + + desiredMask |= VisualClassMask; + desiredMask |= VisualRedMaskMask; + desiredMask |= VisualGreenMaskMask; + desiredMask |= VisualBlueMaskMask; + desiredMask |= VisualBitsPerRGBMask; + } + + XVisualInfo* xvinfos = XGetVisualInfo (display, + desiredMask, + &desiredVisual, + &numVisuals); + + if (xvinfos != 0) + { + for (int i = 0; i < numVisuals; i++) + { + if (xvinfos[i].depth == desiredDepth) + { + visual = xvinfos[i].visual; + break; + } + } + + XFree (xvinfos); + } + + return visual; + } + + static Visual* findVisualFormat (const int desiredDepth, int& matchedDepth) throw() + { + Visual* visual = 0; + + if (desiredDepth == 32) + { +#if JUCE_USE_XSHM + if (isShmAvailable()) + { +#if JUCE_USE_XRENDER + if (XRender::isAvailable()) + { + XRenderPictFormat* pictFormat = XRender::findPictureFormat(); + + if (pictFormat != 0) + { + int numVisuals = 0; + XVisualInfo desiredVisual; + desiredVisual.screen = DefaultScreen (display); + desiredVisual.depth = 32; + desiredVisual.bits_per_rgb = 8; + + XVisualInfo* xvinfos = XGetVisualInfo (display, + VisualScreenMask | VisualDepthMask | VisualBitsPerRGBMask, + &desiredVisual, &numVisuals); + if (xvinfos != 0) + { + for (int i = 0; i < numVisuals; ++i) + { + XRenderPictFormat* pictVisualFormat = XRender::xRenderFindVisualFormat (display, xvinfos[i].visual); + + if (pictVisualFormat != 0 + && pictVisualFormat->type == PictTypeDirect + && pictVisualFormat->direct.alphaMask) + { + visual = xvinfos[i].visual; + matchedDepth = 32; + break; + } + } + + XFree (xvinfos); + } + } + } +#endif + if (visual == 0) + { + visual = findVisualWithDepth (32); + if (visual != 0) + matchedDepth = 32; + } + } +#endif + } + + if (visual == 0 && desiredDepth >= 24) + { + visual = findVisualWithDepth (24); + if (visual != 0) + matchedDepth = 24; + } + + if (visual == 0 && desiredDepth >= 16) + { + visual = findVisualWithDepth (16); + if (visual != 0) + matchedDepth = 16; + } + + return visual; + } +} + //============================================================================== class XBitmapImage : public Image { public: //============================================================================== XBitmapImage (const PixelFormat format_, const int w, const int h, - const bool clearImage, const bool is16Bit_) + const bool clearImage, const int imageDepth_, Visual* visual) : Image (format_, w, h), - is16Bit (is16Bit_) + imageDepth (imageDepth_), + gc (None) { jassert (format_ == RGB || format_ == ARGB); @@ -251,16 +477,19 @@ public: lineStride = ((w * pixelStride + 3) & ~3); ScopedXLock xlock; - Visual* const visual = DefaultVisual (display, DefaultScreen (display)); #if JUCE_USE_XSHM usingXShm = false; - if ((! is16Bit) && isShmAvailable()) + if ((imageDepth > 16) && isShmAvailable()) { zerostruct (segmentInfo); - xImage = XShmCreateImage (display, visual, 24, ZPixmap, 0, &segmentInfo, w, h); + segmentInfo.shmid = -1; + segmentInfo.shmaddr = (char *) -1; + segmentInfo.readOnly = False; + + xImage = XShmCreateImage (display, visual, imageDepth, ZPixmap, 0, &segmentInfo, w, h); if (xImage != 0) { @@ -268,31 +497,31 @@ public: xImage->bytes_per_line * xImage->height, IPC_CREAT | 0777)) >= 0) { - segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - - if (segmentInfo.shmaddr != (void*) -1) + if (segmentInfo.shmid != -1) { - segmentInfo.readOnly = False; + segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - xImage->data = segmentInfo.shmaddr; - imageData = (uint8*) segmentInfo.shmaddr; + if (segmentInfo.shmaddr != (void*) -1) + { + segmentInfo.readOnly = False; - XSync (display, False); + xImage->data = segmentInfo.shmaddr; + imageData = (uint8*) segmentInfo.shmaddr; - if (XShmAttach (display, &segmentInfo) != 0) - { - XSync (display, False); - usingXShm = true; + if (XShmAttach (display, &segmentInfo) != 0) + { + usingXShm = true; + } + else + { + jassertfalse + } } else { - jassertfalse + shmctl (segmentInfo.shmid, IPC_RMID, 0); } } - else - { - shmctl (segmentInfo.shmid, IPC_RMID, 0); - } } } } @@ -324,7 +553,7 @@ public: xImage->green_mask = 0x0000FF00; xImage->blue_mask = 0x000000FF; - if (is16Bit) + if (imageDepth == 16) { const int pixelStride = 2; const int lineStride = ((w * pixelStride + 3) & ~3); @@ -374,12 +603,22 @@ public: { ScopedXLock xlock; - static GC gc = 0; - if (gc == 0) - gc = DefaultGC (display, DefaultScreen (display)); + { + XGCValues gcvalues; + gcvalues.foreground = None; + gcvalues.background = None; + gcvalues.function = GXcopy; + gcvalues.plane_mask = AllPlanes; + gcvalues.clip_mask = None; + gcvalues.graphics_exposures = False; + + gc = XCreateGC (display, window, + GCBackground | GCForeground | GCFunction | GCPlaneMask | GCClipMask | GCGraphicsExposures, + &gcvalues); + } - if (is16Bit) + if (imageDepth == 16) { const uint32 rMask = xImage->red_mask; const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); @@ -424,9 +663,11 @@ public: private: XImage* xImage; - const bool is16Bit; + const int imageDepth; HeapBlock imageData16Bit; + GC gc; + #if JUCE_USE_XSHM XShmSegmentInfo segmentInfo; bool usingXShm; @@ -460,7 +701,9 @@ public: wh (0), taskbarImage (0), fullScreen (false), - mapped (false) + mapped (false), + visual (0), + depth (0) { // it's dangerous to create a window on a thread other than the message thread.. checkMessageManagerIsLocked @@ -1646,7 +1889,8 @@ private: (totalArea.getWidth() + 31) & ~31, (totalArea.getHeight() + 31) & ~31, false, - peer->depthIs16Bit); + peer->depth, + peer->visual); } startTimer (repaintTimerPeriod); @@ -1656,7 +1900,20 @@ private: context.setOrigin (-totalArea.getX(), -totalArea.getY()); if (context.clipToRectangleList (originalRepaintRegion)) + { + if (peer->depth == 32) + { + RectangleList::Iterator i (originalRepaintRegion); + + while (i.next()) + { + const Rectangle& r = *i.getRectangle(); + image->clear (r.getX() - totalArea.getX(), r.getY() - totalArea.getY(), r.getWidth(), r.getHeight()); + } + } + peer->handlePaint (context); + } if (! peer->maskedRegion.isEmpty()) originalRepaintRegion.subtract (peer->maskedRegion); @@ -1701,7 +1958,9 @@ private: Window windowH, parentWindow; int wx, wy, ww, wh; Image* taskbarImage; - bool fullScreen, mapped, depthIs16Bit; + bool fullScreen, mapped; + int depth; + Visual* visual; BorderSize windowBorder; struct MotifWmHints @@ -1986,47 +2245,30 @@ private: const int screen = DefaultScreen (display); Window root = RootWindow (display, screen); - // Attempt to create a 24-bit window on the default screen. If this is not - // possible then exit - XVisualInfo desiredVisual; - desiredVisual.screen = screen; - desiredVisual.depth = 24; - depthIs16Bit = false; - - int numVisuals; - XVisualInfo* visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, - &desiredVisual, &numVisuals); + // Try to obtain a 32-bit visual or fallback to 24 or 16 + visual = Visuals::findVisualFormat ((styleFlags & windowIsSemiTransparent) ? 32 : 24, depth); - if (numVisuals < 1 || visuals == 0) + if (visual == 0) { - XFree (visuals); - desiredVisual.depth = 16; - - visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, - &desiredVisual, &numVisuals); - - if (numVisuals < 1 || visuals == 0) - { - Logger::outputDebugString ("ERROR: System doesn't support 24 or 16 bit RGB display.\n"); - Process::terminate(); - } - - depthIs16Bit = true; + Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); + Process::terminate(); } - XFree (visuals); + // Create and install a colormap suitable fr our visual + Colormap colormap = XCreateColormap (display, root, visual, AllocNone); + XInstallColormap (display, colormap); // Set up the window attributes XSetWindowAttributes swa; swa.border_pixel = 0; swa.background_pixmap = None; - swa.colormap = DefaultColormap (display, screen); + swa.colormap = colormap; swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False; swa.event_mask = eventMask; Window wndH = XCreateWindow (display, root, 0, 0, 1, 1, - 0, 0, InputOutput, (Visual*) CopyFromParent, + 0, depth, InputOutput, visual, CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, &swa); @@ -2052,23 +2294,6 @@ private: XSetWMHints (display, wndH, wmHints); XFree (wmHints); - if ((styleFlags & windowIsSemiTransparent) != 0) - { - //xxx - } - - if ((styleFlags & windowAppearsOnTaskbar) != 0) - { - //xxx - } - - //XSetTransientForHint (display, wndH, RootWindow (display, DefaultScreen (display))); - - if ((styleFlags & windowHasTitleBar) == 0) - removeWindowDecorations (wndH); - else - addWindowButtons (wndH); - // Set window manager protocols XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace, (unsigned char*) wm_ProtocolList, 2); @@ -2087,6 +2312,24 @@ private: XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace, (const unsigned char*) &dndVersion, 1); + if ((windowStyleFlags & windowHasDropShadow) != 0 + && Desktop::canUseSemiTransparentWindows()) + { + } + + if ((styleFlags & windowIsTemporary) != 0) + { + } + + if ((styleFlags & windowAppearsOnTaskbar) == 0) + { + } + + if ((styleFlags & windowHasTitleBar) == 0) + removeWindowDecorations (wndH); + else + addWindowButtons (wndH); + // Set window name setWindowTitle (wndH, getComponent()->getName()); @@ -2674,7 +2917,11 @@ void Desktop::createMouseInputSources() bool Desktop::canUseSemiTransparentWindows() throw() { - return false; + int matchedDepth = 0; + const int desiredDepth = 32; + + return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0 + && (matchedDepth == desiredDepth); } const Point Desktop::getMousePosition() @@ -3210,9 +3457,6 @@ bool AlertWindow::showNativeDialogBox (const String& title, const String& bodyText, bool isOkCancel) { - // xxx this is supposed to pop up an alert! - Logger::outputDebugString (title + ": " + bodyText); - // use a non-native one for the time being.. if (isOkCancel) return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText);