Browse Source

Added XRender support for semi-transparent windows in linux. Fixed a couple of vst build errors.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
a0adefc86e
9 changed files with 683 additions and 171 deletions
  1. +1
    -1
      extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp
  2. +5
    -4
      extras/audio plugins/wrapper/juce_PluginHostType.h
  3. +6
    -0
      juce_Config.h
  4. +333
    -82
      juce_amalgamated.cpp
  5. +5
    -1
      juce_amalgamated.h
  6. +1
    -1
      src/core/juce_StandardHeader.h
  7. +2
    -2
      src/native/linux/juce_linux_Messaging.cpp
  8. +6
    -0
      src/native/linux/juce_linux_NativeIncludes.h
  9. +324
    -80
      src/native/linux/juce_linux_Windowing.cpp

+ 1
- 1
extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp View File

@@ -1078,7 +1078,7 @@ public:
else else
filter->getStateInformation (chunkMemory); 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 // 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. // hope so) we'll give it a while and then free it in the timer callback.


+ 5
- 4
extras/audio plugins/wrapper/juce_PluginHostType.h View File

@@ -133,13 +133,14 @@ private:
buffer.calloc (size + 8); buffer.calloc (size + 8);
#if JUCE_WINDOWS #if JUCE_WINDOWS
GetModuleFileNameW (0, (WCHAR*) buffer, size / sizeof (WCHAR));
return String (reinterpret_cast <const WCHAR*> ((char*) buffer), size);
WCHAR* w = reinterpret_cast <const WCHAR*> (buffer.getData());
GetModuleFileNameW (0, w, size / sizeof (WCHAR));
return String (w, size);
#elif JUCE_MAC #elif JUCE_MAC
_NSGetExecutablePath ((char*) buffer, &size);
_NSGetExecutablePath (buffer.getData(), &size);
return String::fromUTF8 (buffer, size); return String::fromUTF8 (buffer, size);
#elif JUCE_LINUX #elif JUCE_LINUX
readlink ("/proc/self/exe", (char*) buffer, size);
readlink ("/proc/self/exe", buffer.getData(), size);
return String::fromUTF8 (buffer, size); return String::fromUTF8 (buffer, size);
#else #else
#error #error


+ 6
- 0
juce_Config.h View File

@@ -179,6 +179,12 @@
#define JUCE_USE_XSHM 1 #define JUCE_USE_XSHM 1
#endif #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 /** 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 Steinberg VST SDK to be installed on your machine, and should be left turned off unless


+ 333
- 82
juce_amalgamated.cpp View File

@@ -235,6 +235,10 @@
#define JUCE_USE_XSHM 1 #define JUCE_USE_XSHM 1
#endif #endif


#ifndef JUCE_USE_XRENDER
//#define JUCE_USE_XRENDER 1
#endif

#ifndef JUCE_PLUGINHOST_VST #ifndef JUCE_PLUGINHOST_VST
// #define JUCE_PLUGINHOST_VST 1 // #define JUCE_PLUGINHOST_VST 1
#endif #endif
@@ -520,6 +524,12 @@ public:
#include <sys/ipc.h> #include <sys/ipc.h>
#endif #endif


#if JUCE_USE_XRENDER
// If you're missing these headers, try installing the libxrender-dev and libxcomposite-dev
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h>
#endif

#if JUCE_OPENGL #if JUCE_OPENGL
#include <GL/glx.h> #include <GL/glx.h>
#endif #endif
@@ -230224,8 +230234,8 @@ public:
int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd); int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd);
(void) ret; jassert (ret == 0); (void) ret; jassert (ret == 0);


setNonBlocking (fd[0]);
setNonBlocking (fd[1]);
//setNonBlocking (fd[0]);
//setNonBlocking (fd[1]);
} }


~InternalMessageQueue() ~InternalMessageQueue()
@@ -231360,8 +231370,6 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw()
#if JUCE_USE_XSHM #if JUCE_USE_XSHM
static bool isShmAvailable() throw() static bool isShmAvailable() throw()
{ {
ScopedXLock xlock;

static bool isChecked = false; static bool isChecked = false;
static bool isAvailable = false; static bool isAvailable = false;


@@ -231372,6 +231380,8 @@ static bool isShmAvailable() throw()
int major, minor; int major, minor;
Bool pixmaps; Bool pixmaps;


ScopedXLock xlock;

if (XShmQueryVersion (display, &major, &minor, &pixmaps)) if (XShmQueryVersion (display, &major, &minor, &pixmaps))
{ {
trapErrors(); trapErrors();
@@ -231418,14 +231428,237 @@ static bool isShmAvailable() throw()
} }
#endif #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 class XBitmapImage : public Image
{ {
public: public:


XBitmapImage (const PixelFormat format_, const int w, const int h, 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), : Image (format_, w, h),
is16Bit (is16Bit_)
imageDepth (imageDepth_),
gc (None)
{ {
jassert (format_ == RGB || format_ == ARGB); jassert (format_ == RGB || format_ == ARGB);


@@ -231433,16 +231666,19 @@ public:
lineStride = ((w * pixelStride + 3) & ~3); lineStride = ((w * pixelStride + 3) & ~3);


ScopedXLock xlock; ScopedXLock xlock;
Visual* const visual = DefaultVisual (display, DefaultScreen (display));


#if JUCE_USE_XSHM #if JUCE_USE_XSHM
usingXShm = false; usingXShm = false;


if ((! is16Bit) && isShmAvailable())
if ((imageDepth > 16) && isShmAvailable())
{ {
zerostruct (segmentInfo); 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) if (xImage != 0)
{ {
@@ -231450,31 +231686,31 @@ public:
xImage->bytes_per_line * xImage->height, xImage->bytes_per_line * xImage->height,
IPC_CREAT | 0777)) >= 0) 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 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->green_mask = 0x0000FF00;
xImage->blue_mask = 0x000000FF; xImage->blue_mask = 0x000000FF;


if (is16Bit)
if (imageDepth == 16)
{ {
const int pixelStride = 2; const int pixelStride = 2;
const int lineStride = ((w * pixelStride + 3) & ~3); const int lineStride = ((w * pixelStride + 3) & ~3);
@@ -231556,12 +231792,22 @@ public:
{ {
ScopedXLock xlock; ScopedXLock xlock;


static GC gc = 0;

if (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 rMask = xImage->red_mask;
const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); const uint32 rShiftL = jmax (0, getShiftNeeded (rMask));
@@ -231605,9 +231851,11 @@ public:


private: private:
XImage* xImage; XImage* xImage;
const bool is16Bit;
const int imageDepth;
HeapBlock <char> imageData16Bit; HeapBlock <char> imageData16Bit;


GC gc;

#if JUCE_USE_XSHM #if JUCE_USE_XSHM
XShmSegmentInfo segmentInfo; XShmSegmentInfo segmentInfo;
bool usingXShm; bool usingXShm;
@@ -231640,7 +231888,9 @@ public:
wh (0), wh (0),
taskbarImage (0), taskbarImage (0),
fullScreen (false), 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.. // it's dangerous to create a window on a thread other than the message thread..
checkMessageManagerIsLocked checkMessageManagerIsLocked
@@ -232822,7 +233072,8 @@ private:
(totalArea.getWidth() + 31) & ~31, (totalArea.getWidth() + 31) & ~31,
(totalArea.getHeight() + 31) & ~31, (totalArea.getHeight() + 31) & ~31,
false, false,
peer->depthIs16Bit);
peer->depth,
peer->visual);
} }


startTimer (repaintTimerPeriod); startTimer (repaintTimerPeriod);
@@ -232832,7 +233083,20 @@ private:
context.setOrigin (-totalArea.getX(), -totalArea.getY()); context.setOrigin (-totalArea.getX(), -totalArea.getY());


if (context.clipToRectangleList (originalRepaintRegion)) if (context.clipToRectangleList (originalRepaintRegion))
{
if (peer->depth == 32)
{
RectangleList::Iterator i (originalRepaintRegion);

while (i.next())
{
const Rectangle<int>& r = *i.getRectangle();
image->clear (r.getX() - totalArea.getX(), r.getY() - totalArea.getY(), r.getWidth(), r.getHeight());
}
}

peer->handlePaint (context); peer->handlePaint (context);
}


if (! peer->maskedRegion.isEmpty()) if (! peer->maskedRegion.isEmpty())
originalRepaintRegion.subtract (peer->maskedRegion); originalRepaintRegion.subtract (peer->maskedRegion);
@@ -232877,7 +233141,9 @@ private:
Window windowH, parentWindow; Window windowH, parentWindow;
int wx, wy, ww, wh; int wx, wy, ww, wh;
Image* taskbarImage; Image* taskbarImage;
bool fullScreen, mapped, depthIs16Bit;
bool fullScreen, mapped;
int depth;
Visual* visual;
BorderSize windowBorder; BorderSize windowBorder;


struct MotifWmHints struct MotifWmHints
@@ -233161,47 +233427,30 @@ private:
const int screen = DefaultScreen (display); const int screen = DefaultScreen (display);
Window root = RootWindow (display, screen); 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 // Set up the window attributes
XSetWindowAttributes swa; XSetWindowAttributes swa;
swa.border_pixel = 0; swa.border_pixel = 0;
swa.background_pixmap = None; swa.background_pixmap = None;
swa.colormap = DefaultColormap (display, screen);
swa.colormap = colormap;
swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False; swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False;
swa.event_mask = eventMask; swa.event_mask = eventMask;


Window wndH = XCreateWindow (display, root, Window wndH = XCreateWindow (display, root,
0, 0, 1, 1, 0, 0, 1, 1,
0, 0, InputOutput, (Visual*) CopyFromParent,
0, depth, InputOutput, visual,
CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect,
&swa); &swa);


@@ -233227,23 +233476,6 @@ private:
XSetWMHints (display, wndH, wmHints); XSetWMHints (display, wndH, wmHints);
XFree (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 // Set window manager protocols
XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace, XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace,
(unsigned char*) wm_ProtocolList, 2); (unsigned char*) wm_ProtocolList, 2);
@@ -233262,6 +233494,24 @@ private:
XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace, XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace,
(const unsigned char*) &dndVersion, 1); (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 // Set window name
setWindowTitle (wndH, getComponent()->getName()); setWindowTitle (wndH, getComponent()->getName());


@@ -233840,7 +234090,11 @@ void Desktop::createMouseInputSources()


bool Desktop::canUseSemiTransparentWindows() throw() bool Desktop::canUseSemiTransparentWindows() throw()
{ {
return false;
int matchedDepth = 0;
const int desiredDepth = 32;

return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0
&& (matchedDepth == desiredDepth);
} }


const Point<int> Desktop::getMousePosition() const Point<int> Desktop::getMousePosition()
@@ -234358,9 +234612,6 @@ bool AlertWindow::showNativeDialogBox (const String& title,
const String& bodyText, const String& bodyText,
bool isOkCancel) bool isOkCancel)
{ {
// xxx this is supposed to pop up an alert!
Logger::outputDebugString (title + ": " + bodyText);

// use a non-native one for the time being.. // use a non-native one for the time being..
if (isOkCancel) if (isOkCancel)
return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText); return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText);


+ 5
- 1
juce_amalgamated.h View File

@@ -43,7 +43,7 @@


#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 51 #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) #define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8) + JUCE_BUILDNUMBER)


@@ -256,6 +256,10 @@
#define JUCE_USE_XSHM 1 #define JUCE_USE_XSHM 1
#endif #endif


#ifndef JUCE_USE_XRENDER
//#define JUCE_USE_XRENDER 1
#endif

#ifndef JUCE_PLUGINHOST_VST #ifndef JUCE_PLUGINHOST_VST
// #define JUCE_PLUGINHOST_VST 1 // #define JUCE_PLUGINHOST_VST 1
#endif #endif


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/ */
#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 51 #define JUCE_MINOR_VERSION 51
#define JUCE_BUILDNUMBER 8
#define JUCE_BUILDNUMBER 9
/** Current Juce version number. /** Current Juce version number.


+ 2
- 2
src/native/linux/juce_linux_Messaging.cpp View File

@@ -66,8 +66,8 @@ public:
int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd); int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd);
(void) ret; jassert (ret == 0); (void) ret; jassert (ret == 0);
setNonBlocking (fd[0]);
setNonBlocking (fd[1]);
//setNonBlocking (fd[0]);
//setNonBlocking (fd[1]);
} }
~InternalMessageQueue() ~InternalMessageQueue()


+ 6
- 0
src/native/linux/juce_linux_NativeIncludes.h View File

@@ -85,6 +85,12 @@
#include <sys/ipc.h> #include <sys/ipc.h>
#endif #endif
#if JUCE_USE_XRENDER
// If you're missing these headers, try installing the libxrender-dev and libxcomposite-dev
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h>
#endif
#if JUCE_OPENGL #if JUCE_OPENGL
/* Got an include error here? /* Got an include error here?


+ 324
- 80
src/native/linux/juce_linux_Windowing.cpp View File

@@ -177,8 +177,6 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw()
#if JUCE_USE_XSHM #if JUCE_USE_XSHM
static bool isShmAvailable() throw() static bool isShmAvailable() throw()
{ {
ScopedXLock xlock;
static bool isChecked = false; static bool isChecked = false;
static bool isAvailable = false; static bool isAvailable = false;
@@ -189,6 +187,8 @@ static bool isShmAvailable() throw()
int major, minor; int major, minor;
Bool pixmaps; Bool pixmaps;
ScopedXLock xlock;
if (XShmQueryVersion (display, &major, &minor, &pixmaps)) if (XShmQueryVersion (display, &major, &minor, &pixmaps))
{ {
trapErrors(); trapErrors();
@@ -235,15 +235,241 @@ static bool isShmAvailable() throw()
} }
#endif #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 class XBitmapImage : public Image
{ {
public: public:
//============================================================================== //==============================================================================
XBitmapImage (const PixelFormat format_, const int w, const int h, 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), : Image (format_, w, h),
is16Bit (is16Bit_)
imageDepth (imageDepth_),
gc (None)
{ {
jassert (format_ == RGB || format_ == ARGB); jassert (format_ == RGB || format_ == ARGB);
@@ -251,16 +477,19 @@ public:
lineStride = ((w * pixelStride + 3) & ~3); lineStride = ((w * pixelStride + 3) & ~3);
ScopedXLock xlock; ScopedXLock xlock;
Visual* const visual = DefaultVisual (display, DefaultScreen (display));
#if JUCE_USE_XSHM #if JUCE_USE_XSHM
usingXShm = false; usingXShm = false;
if ((! is16Bit) && isShmAvailable())
if ((imageDepth > 16) && isShmAvailable())
{ {
zerostruct (segmentInfo); 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) if (xImage != 0)
{ {
@@ -268,31 +497,31 @@ public:
xImage->bytes_per_line * xImage->height, xImage->bytes_per_line * xImage->height,
IPC_CREAT | 0777)) >= 0) 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 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->green_mask = 0x0000FF00;
xImage->blue_mask = 0x000000FF; xImage->blue_mask = 0x000000FF;
if (is16Bit)
if (imageDepth == 16)
{ {
const int pixelStride = 2; const int pixelStride = 2;
const int lineStride = ((w * pixelStride + 3) & ~3); const int lineStride = ((w * pixelStride + 3) & ~3);
@@ -374,12 +603,22 @@ public:
{ {
ScopedXLock xlock; ScopedXLock xlock;
static GC gc = 0;
if (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 rMask = xImage->red_mask;
const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); const uint32 rShiftL = jmax (0, getShiftNeeded (rMask));
@@ -424,9 +663,11 @@ public:
private: private:
XImage* xImage; XImage* xImage;
const bool is16Bit;
const int imageDepth;
HeapBlock <char> imageData16Bit; HeapBlock <char> imageData16Bit;
GC gc;
#if JUCE_USE_XSHM #if JUCE_USE_XSHM
XShmSegmentInfo segmentInfo; XShmSegmentInfo segmentInfo;
bool usingXShm; bool usingXShm;
@@ -460,7 +701,9 @@ public:
wh (0), wh (0),
taskbarImage (0), taskbarImage (0),
fullScreen (false), 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.. // it's dangerous to create a window on a thread other than the message thread..
checkMessageManagerIsLocked checkMessageManagerIsLocked
@@ -1646,7 +1889,8 @@ private:
(totalArea.getWidth() + 31) & ~31, (totalArea.getWidth() + 31) & ~31,
(totalArea.getHeight() + 31) & ~31, (totalArea.getHeight() + 31) & ~31,
false, false,
peer->depthIs16Bit);
peer->depth,
peer->visual);
} }
startTimer (repaintTimerPeriod); startTimer (repaintTimerPeriod);
@@ -1656,7 +1900,20 @@ private:
context.setOrigin (-totalArea.getX(), -totalArea.getY()); context.setOrigin (-totalArea.getX(), -totalArea.getY());
if (context.clipToRectangleList (originalRepaintRegion)) if (context.clipToRectangleList (originalRepaintRegion))
{
if (peer->depth == 32)
{
RectangleList::Iterator i (originalRepaintRegion);
while (i.next())
{
const Rectangle<int>& r = *i.getRectangle();
image->clear (r.getX() - totalArea.getX(), r.getY() - totalArea.getY(), r.getWidth(), r.getHeight());
}
}
peer->handlePaint (context); peer->handlePaint (context);
}
if (! peer->maskedRegion.isEmpty()) if (! peer->maskedRegion.isEmpty())
originalRepaintRegion.subtract (peer->maskedRegion); originalRepaintRegion.subtract (peer->maskedRegion);
@@ -1701,7 +1958,9 @@ private:
Window windowH, parentWindow; Window windowH, parentWindow;
int wx, wy, ww, wh; int wx, wy, ww, wh;
Image* taskbarImage; Image* taskbarImage;
bool fullScreen, mapped, depthIs16Bit;
bool fullScreen, mapped;
int depth;
Visual* visual;
BorderSize windowBorder; BorderSize windowBorder;
struct MotifWmHints struct MotifWmHints
@@ -1986,47 +2245,30 @@ private:
const int screen = DefaultScreen (display); const int screen = DefaultScreen (display);
Window root = RootWindow (display, screen); 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 // Set up the window attributes
XSetWindowAttributes swa; XSetWindowAttributes swa;
swa.border_pixel = 0; swa.border_pixel = 0;
swa.background_pixmap = None; swa.background_pixmap = None;
swa.colormap = DefaultColormap (display, screen);
swa.colormap = colormap;
swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False; swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False;
swa.event_mask = eventMask; swa.event_mask = eventMask;
Window wndH = XCreateWindow (display, root, Window wndH = XCreateWindow (display, root,
0, 0, 1, 1, 0, 0, 1, 1,
0, 0, InputOutput, (Visual*) CopyFromParent,
0, depth, InputOutput, visual,
CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect,
&swa); &swa);
@@ -2052,23 +2294,6 @@ private:
XSetWMHints (display, wndH, wmHints); XSetWMHints (display, wndH, wmHints);
XFree (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 // Set window manager protocols
XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace, XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace,
(unsigned char*) wm_ProtocolList, 2); (unsigned char*) wm_ProtocolList, 2);
@@ -2087,6 +2312,24 @@ private:
XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace, XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace,
(const unsigned char*) &dndVersion, 1); (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 // Set window name
setWindowTitle (wndH, getComponent()->getName()); setWindowTitle (wndH, getComponent()->getName());
@@ -2674,7 +2917,11 @@ void Desktop::createMouseInputSources()
bool Desktop::canUseSemiTransparentWindows() throw() bool Desktop::canUseSemiTransparentWindows() throw()
{ {
return false;
int matchedDepth = 0;
const int desiredDepth = 32;
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0
&& (matchedDepth == desiredDepth);
} }
const Point<int> Desktop::getMousePosition() const Point<int> Desktop::getMousePosition()
@@ -3210,9 +3457,6 @@ bool AlertWindow::showNativeDialogBox (const String& title,
const String& bodyText, const String& bodyText,
bool isOkCancel) bool isOkCancel)
{ {
// xxx this is supposed to pop up an alert!
Logger::outputDebugString (title + ": " + bodyText);
// use a non-native one for the time being.. // use a non-native one for the time being..
if (isOkCancel) if (isOkCancel)
return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText); return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText);


Loading…
Cancel
Save