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
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.


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

@@ -133,13 +133,14 @@ private:
buffer.calloc (size + 8);
#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
_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


+ 6
- 0
juce_Config.h View File

@@ -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


+ 333
- 82
juce_amalgamated.cpp View File

@@ -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 <sys/ipc.h>
#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
#include <GL/glx.h>
#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 <char> 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<int>& 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<int> 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);


+ 5
- 1
juce_amalgamated.h View File

@@ -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


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

@@ -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.


+ 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);
(void) ret; jassert (ret == 0);
setNonBlocking (fd[0]);
setNonBlocking (fd[1]);
//setNonBlocking (fd[0]);
//setNonBlocking (fd[1]);
}
~InternalMessageQueue()


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

@@ -85,6 +85,12 @@
#include <sys/ipc.h>
#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
/* 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
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 <char> 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<int>& 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<int> 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);


Loading…
Cancel
Save