--- /dev/null
+
+#
+# Patch managed by http://www.holgerschurig.de/patcher.html
+#
+
+--- juce/demo/build/linux/JuceDemo.make~no-opengl
++++ juce/demo/build/linux/JuceDemo.make
+@@ -13,7 +13,7 @@
+ CPPFLAGS := -MD -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include"
+ CFLAGS += $(CPPFLAGS) -g -D_DEBUG -ggdb
+ CXXFLAGS := $(CFLAGS)
+- LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -L "/usr/X11R6/lib/" -L "../../../bin" -lfreetype -lpthread -lX11 -lGL -lGLU -lXinerama -lasound -ljuce_debug
++ LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -L "/usr/X11R6/lib/" -L "../../../bin" -lfreetype -lpthread -lX11 -lasound -ljuce_debug
+ LDDEPS :=
+ TARGET := jucedemo
+ endif
+@@ -26,7 +26,7 @@
+ CPPFLAGS := -MD -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include"
+ CFLAGS += $(CPPFLAGS) -O2
+ CXXFLAGS := $(CFLAGS)
+- LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s -L "/usr/X11R6/lib/" -L "../../../bin" -lfreetype -lpthread -lX11 -lGL -lGLU -lXinerama -lasound -ljuce
++ LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s -L "/usr/X11R6/lib/" -L "../../../bin" -lfreetype -lpthread -lX11 -lasound -ljuce
+ LDDEPS :=
+ TARGET := jucedemo
+ endif
+@@ -39,7 +39,6 @@
+ $(OBJDIR)/DragAndDropDemo.o \
+ $(OBJDIR)/FontsAndTextDemo.o \
+ $(OBJDIR)/InterprocessCommsDemo.o \
+- $(OBJDIR)/OpenGLDemo.o \
+ $(OBJDIR)/PathsAndTransformsDemo.o \
+ $(OBJDIR)/QuickTimeDemo.o \
+ $(OBJDIR)/ThreadingDemo.o \
+--- juce/platform_specific_code/juce_linux_Windowing.cpp
++++ /dev/null
+--- juce/linux/platform_specific_code/juce_linux_Windowing.cpp
++++ /dev/null
+--- juce/build/linux/platform_specific_code/juce_linux_Windowing.cpp~no-opengl
++++ juce/build/linux/platform_specific_code/juce_linux_Windowing.cpp
+@@ -1,2218 +1,2219 @@
+-/*\r
+- ==============================================================================\r
+-\r
+- This file is part of the JUCE library - "Jules' Utility Class Extensions"\r
+- Copyright 2004-6 by Raw Material Software ltd.\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- JUCE can be redistributed and/or modified under the terms of the\r
+- GNU General Public License, as published by the Free Software Foundation;\r
+- either version 2 of the License, or (at your option) any later version.\r
+-\r
+- JUCE is distributed in the hope that it will be useful,\r
+- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+- GNU General Public License for more details.\r
+-\r
+- You should have received a copy of the GNU General Public License\r
+- along with JUCE; if not, visit www.gnu.org/licenses or write to the\r
+- Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+- Boston, MA 02111-1307 USA\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- If you'd like to release a closed-source product which uses JUCE, commercial\r
+- licenses are also available: visit www.rawmaterialsoftware.com/juce for\r
+- more information.\r
+-\r
+- ==============================================================================\r
+-*/\r
+-\r
+-#include "juce_Config.h"\r
+-#if JUCE_BUILD_GUI_CLASSES\r
+-\r
+-#include "linuxincludes.h"\r
+-#include <X11/Xlib.h>\r
+-#include <X11/Xutil.h>\r
+-#include <X11/Xatom.h>\r
+-#include <X11/Xmd.h>\r
+-#include <X11/keysym.h>\r
+-#include <X11/cursorfont.h>\r
+-\r
+-#include "../../../juce_Config.h"\r
+-\r
+-#if JUCE_USE_XINERAMA\r
+-#include <X11/extensions/Xinerama.h>\r
+-#endif\r
+-\r
+-#if JUCE_OPENGL\r
+-#include <X11/Xlib.h>\r
+-#include <GL/glx.h>\r
+-#endif\r
+-\r
+-#undef KeyPress\r
+-\r
+-#include "../../../src/juce_core/basics/juce_StandardHeader.h"\r
+-\r
+-BEGIN_JUCE_NAMESPACE\r
+-\r
+-#include "../../../src/juce_appframework/events/juce_Timer.h"\r
+-#include "../../../src/juce_appframework/application/juce_DeletedAtShutdown.h"\r
+-#include "../../../src/juce_appframework/gui/components/keyboard/juce_KeyPress.h"\r
+-#include "../../../src/juce_appframework/application/juce_SystemClipboard.h"\r
+-#include "../../../src/juce_appframework/gui/components/windows/juce_AlertWindow.h"\r
+-#include "../../../src/juce_appframework/gui/components/special/juce_OpenGLComponent.h"\r
+-#include "../../../src/juce_appframework/gui/components/juce_Desktop.h"\r
+-#include "../../../src/juce_appframework/events/juce_MessageManager.h"\r
+-#include "../../../src/juce_appframework/gui/components/juce_RepaintManager.h"\r
+-#include "../../../src/juce_appframework/gui/components/juce_ComponentDeletionWatcher.h"\r
+-#include "../../../src/juce_appframework/gui/graphics/geometry/juce_RectangleList.h"\r
+-#include "../../../src/juce_appframework/gui/graphics/imaging/juce_ImageFileFormat.h"\r
+-#include "../../../src/juce_appframework/gui/components/mouse/juce_DragAndDropContainer.h"\r
+-#include "../../../src/juce_core/basics/juce_Logger.h"\r
+-#include "../../../src/juce_core/threads/juce_Process.h"\r
+-#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"\r
+-\r
+-\r
+-//==============================================================================\r
+-static Atom wm_ChangeState = None;\r
+-static Atom wm_State = None;\r
+-static Atom wm_Protocols = None;\r
+-static Atom wm_ProtocolList [2] = { None, None };\r
+-static Atom wm_ActiveWin = None;\r
+-static Atom repaintId = None;\r
+-\r
+-#define TAKE_FOCUS 0\r
+-#define DELETE_WINDOW 1\r
+-\r
+-//==============================================================================\r
+-static bool isActiveApplication = false;\r
+-\r
+-bool Process::isForegroundProcess()\r
+-{\r
+- return isActiveApplication;\r
+-}\r
+-\r
+-//==============================================================================\r
+-// These are defined in juce_linux_Messages.cpp\r
+-extern Display* display;\r
+-extern XContext improbableNumber;\r
+-\r
+-const int juce_windowIsSemiTransparentFlag = (1 << 31); // also in component.cpp\r
+-\r
+-static const int eventMask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask\r
+- | EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeymapStateMask\r
+- | ExposureMask | StructureNotifyMask | FocusChangeMask;\r
+-\r
+-//==============================================================================\r
+-static int pointerMap[5];\r
+-static int lastMousePosX = 0, lastMousePosY = 0;\r
+-\r
+-enum MouseButtons\r
+-{\r
+- NoButton = 0,\r
+- LeftButton = 1,\r
+- MiddleButton = 2,\r
+- RightButton = 3,\r
+- WheelUp = 4,\r
+- WheelDown = 5\r
+-};\r
+-\r
+-static void getMousePos (int& x, int& y, int& mouseMods)\r
+-{\r
+- Window root, child;\r
+- int winx, winy;\r
+- unsigned int mask;\r
+-\r
+- mouseMods = 0;\r
+-\r
+- if (XQueryPointer (display,\r
+- RootWindow (display, DefaultScreen (display)),\r
+- &root, &child,\r
+- &x, &y, &winx, &winy, &mask) == False)\r
+- {\r
+- // Pointer not on the default screen\r
+- x = y = -1;\r
+- }\r
+- else\r
+- {\r
+- if ((mask & Button1Mask) != 0)\r
+- mouseMods |= ModifierKeys::leftButtonModifier;\r
+-\r
+- if ((mask & Button2Mask) != 0)\r
+- mouseMods |= ModifierKeys::middleButtonModifier;\r
+-\r
+- if ((mask & Button3Mask) != 0)\r
+- mouseMods |= ModifierKeys::rightButtonModifier;\r
+- }\r
+-}\r
+-\r
+-//==============================================================================\r
+-static int AltMask = 0;\r
+-static int NumLockMask = 0;\r
+-static bool numLock = 0;\r
+-static bool capsLock = 0;\r
+-static char keyStates [32];\r
+-\r
+-static void updateKeyStates (const int keycode, const bool press)\r
+-{\r
+- const int keybyte = keycode >> 3;\r
+- const int keybit = (1 << (keycode & 7));\r
+-\r
+- if (press)\r
+- keyStates [keybyte] |= keybit;\r
+- else\r
+- keyStates [keybyte] &= ~keybit;\r
+-}\r
+-\r
+-static bool keyDown (const int keycode)\r
+-{\r
+- const int keybyte = keycode >> 3;\r
+- const int keybit = (1 << (keycode & 7));\r
+-\r
+- return (keyStates [keybyte] & keybit) != 0;\r
+-}\r
+-\r
+-static const int nonAsciiModifier = 0x10000;\r
+-\r
+-bool KeyPress::isKeyCurrentlyDown (int keyCode)\r
+-{\r
+- int keysym;\r
+-\r
+- if (keyCode & nonAsciiModifier)\r
+- {\r
+- keysym = 0xff00 | (keyCode & 0xff);\r
+- }\r
+- else\r
+- {\r
+- keysym = keyCode;\r
+-\r
+- if (keysym == (XK_Tab & 0xff)\r
+- || keysym == (XK_Return & 0xff)\r
+- || keysym == (XK_Escape & 0xff)\r
+- || keysym == (XK_BackSpace & 0xff))\r
+- {\r
+- keysym |= 0xff00;\r
+- }\r
+- }\r
+-\r
+- return keyDown (XKeysymToKeycode (display, keysym));\r
+-}\r
+-\r
+-//==============================================================================\r
+-// Alt and Num lock are not defined by standard X\r
+-// modifier constants: check what they're mapped to\r
+-static void getModifierMapping()\r
+-{\r
+- const int altLeftCode = XKeysymToKeycode (display, XK_Alt_L);\r
+- const int numLockCode = XKeysymToKeycode (display, XK_Num_Lock);\r
+-\r
+- AltMask = 0;\r
+- NumLockMask = 0;\r
+-\r
+- XModifierKeymap* mapping = XGetModifierMapping (display);\r
+-\r
+- if (mapping)\r
+- {\r
+- for (int i = 0; i < 8; i++)\r
+- {\r
+- if (mapping->modifiermap [i << 1] == altLeftCode)\r
+- AltMask = 1 << i;\r
+- else if (mapping->modifiermap [i << 1] == numLockCode)\r
+- NumLockMask = 1 << i;\r
+- }\r
+-\r
+- XFreeModifiermap (mapping);\r
+- }\r
+-}\r
+-\r
+-static int currentModifiers = 0;\r
+-\r
+-void ModifierKeys::updateCurrentModifiers()\r
+-{\r
+- currentModifierFlags = currentModifiers;\r
+-}\r
+-\r
+-const ModifierKeys ModifierKeys::getCurrentModifiersRealtime()\r
+-{\r
+- int x, y, mouseMods;\r
+- getMousePos (x, y, mouseMods);\r
+-\r
+- currentModifiers &= ~ModifierKeys::allMouseButtonModifiers;\r
+- currentModifiers |= mouseMods;\r
+-\r
+- return ModifierKeys (currentModifiers);\r
+-}\r
+-\r
+-static void updateKeyModifiers (const int status)\r
+-{\r
+- currentModifiers &= ~(ModifierKeys::shiftModifier\r
+- | ModifierKeys::ctrlModifier\r
+- | ModifierKeys::altModifier);\r
+-\r
+- if (status & ShiftMask)\r
+- currentModifiers |= ModifierKeys::shiftModifier;\r
+-\r
+- if (status & ControlMask)\r
+- currentModifiers |= ModifierKeys::ctrlModifier;\r
+-\r
+- if (status & AltMask)\r
+- currentModifiers |= ModifierKeys::altModifier;\r
+-\r
+- numLock = ((status & NumLockMask) != 0);\r
+- capsLock = ((status & LockMask) != 0);\r
+-}\r
+-\r
+-static bool updateKeyModifiersFromSym (KeySym sym, const bool press)\r
+-{\r
+- int modifier = 0;\r
+- bool isModifier = true;\r
+-\r
+- switch (sym)\r
+- {\r
+- case XK_Shift_L:\r
+- case XK_Shift_R:\r
+- modifier = ModifierKeys::shiftModifier;\r
+- break;\r
+-\r
+- case XK_Control_L:\r
+- case XK_Control_R:\r
+- modifier = ModifierKeys::ctrlModifier;\r
+- break;\r
+-\r
+- case XK_Alt_L:\r
+- case XK_Alt_R:\r
+- modifier = ModifierKeys::altModifier;\r
+- break;\r
+-\r
+- case XK_Num_Lock:\r
+- if (press)\r
+- numLock = ! numLock;\r
+-\r
+- break;\r
+-\r
+- case XK_Caps_Lock:\r
+- if (press)\r
+- capsLock = ! capsLock;\r
+-\r
+- break;\r
+-\r
+- case XK_Scroll_Lock:\r
+- break;\r
+-\r
+- default:\r
+- isModifier = false;\r
+- break;\r
+- }\r
+-\r
+- if (modifier != 0)\r
+- {\r
+- if (press)\r
+- currentModifiers |= modifier;\r
+- else\r
+- currentModifiers &= ~modifier;\r
+- }\r
+-\r
+- return isModifier;\r
+-}\r
+-\r
+-\r
+-//==============================================================================\r
+-class XBitmapImage : public Image\r
+-{\r
+-public:\r
+- //==============================================================================\r
+- XBitmapImage (const PixelFormat format_, const int w, const int h, const bool clearImage)\r
+- : Image (format_, w, h)\r
+- {\r
+- jassert (format_ == RGB || format_ == ARGB);\r
+-\r
+- pixelStride = (format_ == RGB) ? 3 : 4;\r
+- lineStride = ((w * pixelStride + 3) & ~3);\r
+- imageData = (uint8*) juce_malloc (lineStride * h);\r
+-\r
+- if (format_ == ARGB && clearImage)\r
+- zeromem (xImage->data, h * lineStride);\r
+-\r
+- xImage = new XImage();\r
+- xImage->width = w;\r
+- xImage->height = h;\r
+- xImage->xoffset = 0;\r
+- xImage->format = ZPixmap;\r
+- xImage->data = (char*) imageData;\r
+- xImage->byte_order = ImageByteOrder (display);\r
+- xImage->bitmap_unit = BitmapUnit (display);\r
+- xImage->bitmap_bit_order = BitmapBitOrder (display);\r
+- xImage->bitmap_pad = 32;\r
+- xImage->depth = pixelStride * 8;\r
+- xImage->bytes_per_line = lineStride;\r
+- xImage->bits_per_pixel = pixelStride * 8;\r
+- xImage->red_mask = 0x00FF0000;\r
+- xImage->green_mask = 0x0000FF00;\r
+- xImage->blue_mask = 0x000000FF;\r
+-\r
+- if (! XInitImage (xImage))\r
+- {\r
+- jassertfalse\r
+- }\r
+- }\r
+-\r
+- ~XBitmapImage()\r
+- {\r
+- juce_free (xImage->data);\r
+- xImage->data = 0;\r
+- XDestroyImage (xImage);\r
+- imageData = 0; // to stop the base class freeing this\r
+- }\r
+-\r
+- void blitToWindow (Window window, int dx, int dy, int dw, int dh, int sx, int sy)\r
+- {\r
+- static GC gc = 0;\r
+-\r
+- if (gc == 0)\r
+- gc = DefaultGC (display, DefaultScreen (display));\r
+-\r
+- // blit results to screen.\r
+- XPutImage (display, (Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh);\r
+- }\r
+-\r
+- //==============================================================================\r
+- juce_UseDebuggingNewOperator\r
+-\r
+-private:\r
+- XImage* xImage;\r
+-};\r
+-\r
+-\r
+-//==============================================================================\r
+-class LinuxComponentPeer : public ComponentPeer\r
+-{\r
+-public:\r
+- //==============================================================================\r
+- LinuxComponentPeer (Component* const component, const int windowStyleFlags)\r
+- : ComponentPeer (component, windowStyleFlags),\r
+- windowH (0),\r
+- wx (0),\r
+- wy (0),\r
+- ww (0),\r
+- wh (0),\r
+- fullScreen (false),\r
+- entered (false),\r
+- mapped (false)\r
+- {\r
+- repainter = new LinuxRepaintManager (this, component, 3000);\r
+-\r
+- MessageManager::getInstance()\r
+- ->callFunctionOnMessageThread (&createWindowCallback, (void*) this);\r
+-\r
+- setTitle (component->getName());\r
+- }\r
+-\r
+- ~LinuxComponentPeer()\r
+- {\r
+- MessageManager::getInstance()\r
+- ->callFunctionOnMessageThread (&destroyWindowCallback, (void*) windowH);\r
+-\r
+- windowH = 0;\r
+- delete repainter;\r
+- }\r
+-\r
+- //==============================================================================\r
+- void* getNativeHandle() const\r
+- {\r
+- return (void*) windowH;\r
+- }\r
+-\r
+- void setVisible (bool shouldBeVisible)\r
+- {\r
+- if (shouldBeVisible)\r
+- XMapWindow (display, windowH);\r
+- else\r
+- XUnmapWindow (display, windowH);\r
+- }\r
+-\r
+- void setTitle (const String& title)\r
+- {\r
+- setWindowTitle (windowH, title);\r
+- }\r
+-\r
+- void setPosition (int x, int y)\r
+- {\r
+- setBounds (x, y, ww, wh, false);\r
+- }\r
+-\r
+- void setSize (int w, int h)\r
+- {\r
+- setBounds (wx, wy, w, h, false);\r
+- }\r
+-\r
+- void setBounds (int x, int y, int w, int h, const bool isNowFullScreen)\r
+- {\r
+- fullScreen = isNowFullScreen;\r
+-\r
+- if (windowH != 0)\r
+- {\r
+- const ComponentDeletionWatcher deletionChecker (component);\r
+-\r
+- wx = x;\r
+- wy = y;\r
+- ww = jmax (1, w);\r
+- wh = jmax (1, h);\r
+-\r
+- if (! mapped)\r
+- {\r
+- // Make sure the Window manager does what we want\r
+- XSizeHints* hints = XAllocSizeHints();\r
+- hints->flags = USSize | USPosition;\r
+- hints->width = ww + windowBorder.getLeftAndRight();\r
+- hints->height = wh + windowBorder.getTopAndBottom();\r
+- hints->x = wx - windowBorder.getLeft();\r
+- hints->y = wy - windowBorder.getTop();\r
+- XSetWMNormalHints (display, windowH, hints);\r
+- XFree (hints);\r
+- }\r
+-\r
+- XMoveResizeWindow (display, windowH,\r
+- wx - windowBorder.getLeft(),\r
+- wy - windowBorder.getTop(),\r
+- ww + windowBorder.getLeftAndRight(),\r
+- wh + windowBorder.getTopAndBottom());\r
+-\r
+- if (! deletionChecker.hasBeenDeleted())\r
+- {\r
+- updateBorderSize();\r
+- handleMovedOrResized();\r
+- }\r
+- }\r
+- }\r
+-\r
+- void getBounds (int& x, int& y, int& w, int& h) const\r
+- {\r
+- x = wx;\r
+- y = wy;\r
+- w = ww;\r
+- h = wh;\r
+- }\r
+-\r
+- int getScreenX() const\r
+- {\r
+- return wx;\r
+- }\r
+-\r
+- int getScreenY() const\r
+- {\r
+- return wy;\r
+- }\r
+-\r
+- void setMinimised (bool shouldBeMinimised)\r
+- {\r
+- if (shouldBeMinimised)\r
+- {\r
+- Window root = RootWindow (display, DefaultScreen (display));\r
+-\r
+- XClientMessageEvent clientMsg;\r
+- clientMsg.display = display;\r
+- clientMsg.window = windowH;\r
+- clientMsg.type = ClientMessage;\r
+- clientMsg.format = 32;\r
+- clientMsg.message_type = wm_ChangeState;\r
+- clientMsg.data.l[0] = IconicState;\r
+-\r
+- XSendEvent (display, root, false,\r
+- SubstructureRedirectMask | SubstructureNotifyMask,\r
+- (XEvent*) &clientMsg);\r
+- }\r
+- else\r
+- {\r
+- setVisible (true);\r
+- }\r
+- }\r
+-\r
+- bool isMinimised() const\r
+- {\r
+- bool minimised = false;\r
+-\r
+- CARD32* stateProp;\r
+- unsigned long nitems, bytesLeft;\r
+- Atom actualType;\r
+- int actualFormat;\r
+-\r
+- if (XGetWindowProperty (display, windowH, wm_State, 0, 64, False,\r
+- wm_State, &actualType, &actualFormat, &nitems, &bytesLeft,\r
+- (unsigned char**) &stateProp) == Success\r
+- && actualType == wm_State\r
+- && actualFormat == 32\r
+- && nitems > 0)\r
+- {\r
+- if (stateProp[0] == IconicState)\r
+- minimised = true;\r
+-\r
+- XFree (stateProp);\r
+- }\r
+-\r
+- return minimised;\r
+- }\r
+-\r
+- void setFullScreen (bool shouldBeFullScreen)\r
+- {\r
+- setMinimised (false);\r
+-\r
+- if (fullScreen != shouldBeFullScreen)\r
+- {\r
+- Rectangle r (lastNonFullscreenBounds);\r
+-\r
+- if (shouldBeFullScreen)\r
+- r = Desktop::getInstance().getMainMonitorArea();\r
+-\r
+- if (! r.isEmpty())\r
+- setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen);\r
+-\r
+- getComponent()->repaint();\r
+- }\r
+- }\r
+-\r
+- bool isFullScreen() const\r
+- {\r
+- return fullScreen;\r
+- }\r
+-\r
+- bool isChildWindowOf (Window possibleParent) const\r
+- {\r
+- Window* windowList = 0;\r
+- uint32 windowListSize = 0;\r
+- Window parent, root;\r
+-\r
+- if (XQueryTree (display, windowH, &root, &parent, &windowList, &windowListSize) != 0)\r
+- {\r
+- if (windowList != 0)\r
+- XFree (windowList);\r
+-\r
+- return parent == possibleParent;\r
+- }\r
+-\r
+- return false;\r
+- }\r
+-\r
+- bool contains (int x, int y, bool trueIfInAChildWindow) const\r
+- {\r
+- jassert (x >= 0 && y >= 0 && x < ww && y < wh); // should only be called for points that are actually inside the bounds\r
+-\r
+- x += wx;\r
+- y += wy;\r
+-\r
+- // the XQueryTree stuff later on is VERY slow, so if this call's just to check the mouse pos, it's\r
+- // much more efficient to cheat..\r
+- if (x == lastMousePosX && y == lastMousePosY)\r
+- {\r
+- Window root, child;\r
+- int winx, winy;\r
+- unsigned int mask;\r
+-\r
+- if (XQueryPointer (display,\r
+- RootWindow (display, DefaultScreen (display)),\r
+- &root, &child,\r
+- &x, &y, &winx, &winy, &mask) != False)\r
+- {\r
+- return child == windowH\r
+- || (((styleFlags & windowHasTitleBar) != 0) && isChildWindowOf (child));\r
+- }\r
+- }\r
+-\r
+- bool result = false;\r
+-\r
+- Window* windowList = 0;\r
+- uint32 windowListSize = 0;\r
+-\r
+- Window parent, root = RootWindow (display, DefaultScreen (display));\r
+-\r
+- if (XQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0)\r
+- {\r
+- for (int i = windowListSize; --i >= 0;)\r
+- {\r
+- XWindowAttributes atts;\r
+-\r
+- if (windowList[i] == windowH\r
+- || (((styleFlags & windowHasTitleBar) != 0) && isChildWindowOf (windowList[i])))\r
+- {\r
+- result = true;\r
+-\r
+- if (! trueIfInAChildWindow)\r
+- {\r
+- Window child;\r
+- int tempX, tempY;\r
+-\r
+- result = XTranslateCoordinates (display, windowH, windowH,\r
+- x - wx - windowBorder.getLeft(),\r
+- y - wy - windowBorder.getTop(),\r
+- &tempX, &tempY,\r
+- &child)\r
+- && (child == None);\r
+- }\r
+-\r
+- break;\r
+- }\r
+- else if (XGetWindowAttributes (display, windowList[i], &atts)\r
+- && atts.map_state == IsViewable\r
+- && x >= atts.x && y >= atts.y\r
+- && x < atts.x + atts.width\r
+- && y < atts.y + atts.height)\r
+- {\r
+- break;\r
+- }\r
+- }\r
+- }\r
+-\r
+- if (windowList != 0)\r
+- XFree (windowList);\r
+-\r
+- return result;\r
+- }\r
+-\r
+- const BorderSize getFrameSize() const\r
+- {\r
+- return BorderSize();\r
+- }\r
+-\r
+- bool setAlwaysOnTop (bool alwaysOnTop)\r
+- {\r
+- if (windowH != 0)\r
+- {\r
+- XSetWindowAttributes swa;\r
+- swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False;\r
+-\r
+- XChangeWindowAttributes (display, windowH, CWOverrideRedirect, &swa);\r
+- }\r
+-\r
+- return true;\r
+- }\r
+-\r
+- void toFront (bool makeActive)\r
+- {\r
+- if (makeActive)\r
+- {\r
+- setVisible (true);\r
+- grabFocus();\r
+- }\r
+-\r
+- XEvent ev;\r
+- ev.xclient.type = ClientMessage;\r
+- ev.xclient.serial = 0;\r
+- ev.xclient.send_event = True;\r
+- ev.xclient.message_type = wm_ActiveWin;\r
+- ev.xclient.window = windowH;\r
+- ev.xclient.format = 32;\r
+- ev.xclient.data.l[0] = 2;\r
+- ev.xclient.data.l[1] = CurrentTime;\r
+- ev.xclient.data.l[2] = 0;\r
+- ev.xclient.data.l[3] = 0;\r
+- ev.xclient.data.l[4] = 0;\r
+-\r
+- XSendEvent (display, RootWindow (display, DefaultScreen (display)),\r
+- False,\r
+- SubstructureRedirectMask | SubstructureNotifyMask,\r
+- &ev);\r
+-\r
+- XSync (display, False);\r
+- }\r
+-\r
+- void toBehind (ComponentPeer* other)\r
+- {\r
+- LinuxComponentPeer* const otherPeer = dynamic_cast <LinuxComponentPeer*> (other);\r
+- jassert (otherPeer != 0); // wrong type of window?\r
+-\r
+- if (otherPeer != 0)\r
+- {\r
+- setMinimised (false);\r
+-\r
+- Window newStack[] = { otherPeer->windowH, windowH };\r
+-\r
+- XRestackWindows (display, newStack, 2);\r
+- }\r
+- }\r
+-\r
+- bool isFocused() const\r
+- {\r
+- int revert;\r
+- Window focus = 0;\r
+- XGetInputFocus (display, &focus, &revert);\r
+-\r
+- if (focus == 0 || focus == None || focus == PointerRoot)\r
+- return 0;\r
+-\r
+- ComponentPeer* focusedPeer = 0;\r
+- if (XFindContext (display, (XID) focus, improbableNumber, (XPointer*) &focusedPeer) != 0)\r
+- focusedPeer = 0;\r
+-\r
+- return this == focusedPeer;\r
+- }\r
+-\r
+- void grabFocus()\r
+- {\r
+- XWindowAttributes atts;\r
+-\r
+- if (windowH != 0\r
+- && XGetWindowAttributes (display, windowH, &atts)\r
+- && atts.map_state == IsViewable)\r
+- {\r
+- XSetInputFocus (display, windowH, RevertToParent, CurrentTime);\r
+-\r
+- if (! isActiveApplication)\r
+- {\r
+- isActiveApplication = true;\r
+- handleFocusGain();\r
+- }\r
+- }\r
+- }\r
+-\r
+- void repaint (int x, int y, int w, int h)\r
+- {\r
+- repainter->invalidateCache (x, y, w, h);\r
+- repainter->repaint (x, y, w, h);\r
+- }\r
+-\r
+- void performPendingRepaints()\r
+- {\r
+- repainter->performPendingRepaints();\r
+- }\r
+-\r
+- //==============================================================================\r
+- void handleWindowMessage (XEvent* event)\r
+- {\r
+- switch (event->xany.type)\r
+- {\r
+- case 2: // 'KeyPress'\r
+- {\r
+- XKeyEvent* keyEvent = (XKeyEvent*) &event->xkey;\r
+- updateKeyStates (keyEvent->keycode, true);\r
+-\r
+- int index = currentModifiers & ModifierKeys::shiftModifier ? 1 : 0;\r
+- KeySym sym = XKeycodeToKeysym (display, keyEvent->keycode, index);\r
+-\r
+- const int oldMods = currentModifiers;\r
+- bool keyPressed = false;\r
+-\r
+- const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false);\r
+-\r
+- if ((sym & 0xff00) == 0xff00)\r
+- {\r
+- // Translate keypad\r
+- if (sym == XK_KP_Divide)\r
+- sym = XK_slash;\r
+- else if (sym == XK_KP_Multiply)\r
+- sym = XK_asterisk;\r
+- else if (sym == XK_KP_Subtract)\r
+- sym = XK_hyphen;\r
+- else if (sym == XK_KP_Add)\r
+- sym = XK_plus;\r
+- else if (sym == XK_KP_Enter)\r
+- sym = XK_Return;\r
+- else if (sym == XK_KP_Decimal)\r
+- sym = numLock ? XK_period : XK_Delete;\r
+- else if (sym == XK_KP_0)\r
+- sym = numLock ? XK_0 : XK_Insert;\r
+- else if (sym == XK_KP_1)\r
+- sym = numLock ? XK_1 : XK_End;\r
+- else if (sym == XK_KP_2)\r
+- sym = numLock ? XK_2 : XK_Down;\r
+- else if (sym == XK_KP_3)\r
+- sym = numLock ? XK_3 : XK_Page_Down;\r
+- else if (sym == XK_KP_4)\r
+- sym = numLock ? XK_4 : XK_Left;\r
+- else if (sym == XK_KP_5)\r
+- sym = XK_5;\r
+- else if (sym == XK_KP_6)\r
+- sym = numLock ? XK_6 : XK_Right;\r
+- else if (sym == XK_KP_7)\r
+- sym = numLock ? XK_7 : XK_Home;\r
+- else if (sym == XK_KP_8)\r
+- sym = numLock ? XK_8 : XK_Up;\r
+- else if (sym == XK_KP_9)\r
+- sym = numLock ? XK_9 : XK_Page_Up;\r
+-\r
+- switch (sym)\r
+- {\r
+- case XK_Left:\r
+- case XK_Right:\r
+- case XK_Up:\r
+- case XK_Down:\r
+- case XK_Page_Up:\r
+- case XK_Page_Down:\r
+- case XK_End:\r
+- case XK_Home:\r
+- case XK_Delete:\r
+- case XK_Insert:\r
+- keyPressed = true;\r
+- sym = (sym & 0xff) | nonAsciiModifier;\r
+- break;\r
+- case XK_Tab:\r
+- case XK_Return:\r
+- case XK_Escape:\r
+- case XK_BackSpace:\r
+- keyPressed = true;\r
+- sym &= 0xff;\r
+- break;\r
+- default:\r
+- {\r
+- if (sym >= XK_F1 && sym <= XK_F12)\r
+- {\r
+- keyPressed = true;\r
+- sym = (sym & 0xff) | nonAsciiModifier;\r
+- }\r
+- break;\r
+- }\r
+- }\r
+- }\r
+-\r
+- if ((sym & 0xff00) == 0 && sym >= 8)\r
+- keyPressed = true;\r
+-\r
+- if (capsLock && ((sym >= XK_A && sym <= XK_Z) || (sym >= XK_a && sym <= XK_z)))\r
+- {\r
+- index ^= 1;\r
+- sym = XKeycodeToKeysym (display, keyEvent->keycode, index);\r
+- }\r
+-\r
+- if (oldMods != currentModifiers)\r
+- handleModifierKeysChange();\r
+-\r
+- if (keyDownChange)\r
+- handleKeyUpOrDown();\r
+-\r
+- if (keyPressed)\r
+- handleKeyPress (sym);\r
+-\r
+- break;\r
+- }\r
+-\r
+- case KeyRelease:\r
+- {\r
+- XKeyEvent* keyEvent = (XKeyEvent*) &event->xkey;\r
+- updateKeyStates (keyEvent->keycode, false);\r
+-\r
+- KeySym sym = XKeycodeToKeysym (display, keyEvent->keycode, 0);\r
+-\r
+- const int oldMods = currentModifiers;\r
+- const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false);\r
+-\r
+- if (oldMods != currentModifiers)\r
+- handleModifierKeysChange();\r
+-\r
+- if (keyDownChange)\r
+- handleKeyUpOrDown();\r
+-\r
+- break;\r
+- }\r
+-\r
+- case ButtonPress:\r
+- {\r
+- XButtonPressedEvent* buttonPressEvent = (XButtonPressedEvent*) &event->xbutton;\r
+-\r
+- bool buttonMsg = false;\r
+- bool wheelUpMsg = false;\r
+- bool wheelDownMsg = false;\r
+-\r
+- const int map = pointerMap [buttonPressEvent->button - Button1];\r
+-\r
+- if (map == LeftButton)\r
+- {\r
+- currentModifiers |= ModifierKeys::leftButtonModifier;\r
+- buttonMsg = true;\r
+- }\r
+- else if (map == RightButton)\r
+- {\r
+- currentModifiers |= ModifierKeys::rightButtonModifier;\r
+- buttonMsg = true;\r
+- }\r
+- else if (map == MiddleButton)\r
+- {\r
+- currentModifiers |= ModifierKeys::middleButtonModifier;\r
+- buttonMsg = true;\r
+- }\r
+- else if (map == WheelUp)\r
+- {\r
+- wheelUpMsg = true;\r
+- }\r
+- else if (map == WheelDown)\r
+- {\r
+- wheelDownMsg = true;\r
+- }\r
+-\r
+- updateKeyModifiers (buttonPressEvent->state);\r
+-\r
+- if (buttonMsg)\r
+- {\r
+- toFront (true);\r
+- handleMouseDown (buttonPressEvent->x, buttonPressEvent->y,\r
+- getEventTime (buttonPressEvent->time));\r
+- }\r
+- else if (wheelUpMsg || wheelDownMsg)\r
+- {\r
+- handleMouseWheel (wheelDownMsg ? -84 : 84,\r
+- getEventTime (buttonPressEvent->time));\r
+- }\r
+-\r
+- lastMousePosX = lastMousePosY = 0x100000;\r
+- break;\r
+- }\r
+-\r
+- case ButtonRelease:\r
+- {\r
+- XButtonReleasedEvent* buttonRelEvent = (XButtonReleasedEvent*) &event->xbutton;\r
+-\r
+- const int oldModifiers = currentModifiers;\r
+- const int map = pointerMap [buttonRelEvent->button - Button1];\r
+-\r
+- if (map == LeftButton)\r
+- currentModifiers &= ~ModifierKeys::leftButtonModifier;\r
+- else if (map == RightButton)\r
+- currentModifiers &= ~ModifierKeys::rightButtonModifier;\r
+- else if (map == MiddleButton)\r
+- currentModifiers &= ~ModifierKeys::middleButtonModifier;\r
+-\r
+- updateKeyModifiers (buttonRelEvent->state);\r
+-\r
+- handleMouseUp (oldModifiers,\r
+- buttonRelEvent->x, buttonRelEvent->y,\r
+- getEventTime (buttonRelEvent->time));\r
+-\r
+- lastMousePosX = lastMousePosY = 0x100000;\r
+- break;\r
+- }\r
+-\r
+- case MotionNotify:\r
+- {\r
+- XPointerMovedEvent* movedEvent = (XPointerMovedEvent*) &event->xmotion;\r
+-\r
+- updateKeyModifiers (movedEvent->state);\r
+-\r
+- int x, y, mouseMods;\r
+- getMousePos (x, y, mouseMods);\r
+-\r
+- if (lastMousePosX != x || lastMousePosY != y)\r
+- {\r
+- lastMousePosX = x;\r
+- lastMousePosY = y;\r
+-\r
+- x -= getScreenX();\r
+- y -= getScreenY();\r
+-\r
+- if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0)\r
+- handleMouseMove (x, y, getEventTime (movedEvent->time));\r
+- else\r
+- handleMouseDrag (x, y, getEventTime (movedEvent->time));\r
+- }\r
+-\r
+- break;\r
+- }\r
+-\r
+- case EnterNotify:\r
+- {\r
+- lastMousePosX = lastMousePosY = 0x100000;\r
+- XEnterWindowEvent* enterEvent = (XEnterWindowEvent*) &event->xcrossing;\r
+-\r
+- if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0\r
+- && ! entered)\r
+- {\r
+- updateKeyModifiers (enterEvent->state);\r
+-\r
+- handleMouseEnter (enterEvent->x, enterEvent->y, getEventTime (enterEvent->time));\r
+-\r
+- entered = true;\r
+- }\r
+-\r
+- break;\r
+- }\r
+-\r
+- case LeaveNotify:\r
+- {\r
+- XLeaveWindowEvent* leaveEvent = (XLeaveWindowEvent*) &event->xcrossing;\r
+-\r
+- // Suppress the normal leave if we've got a pointer grab, or if\r
+- // it's a bogus one caused by clicking a mouse button when running\r
+- // in a Window manager\r
+- if (((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0\r
+- && leaveEvent->mode == NotifyNormal)\r
+- || leaveEvent->mode == NotifyUngrab)\r
+- {\r
+- updateKeyModifiers (leaveEvent->state);\r
+-\r
+- handleMouseExit (leaveEvent->x, leaveEvent->y, getEventTime (leaveEvent->time));\r
+-\r
+- entered = false;\r
+- }\r
+-\r
+- break;\r
+- }\r
+-\r
+- case FocusIn:\r
+- {\r
+- isActiveApplication = true;\r
+- handleFocusGain();\r
+- break;\r
+- }\r
+-\r
+- case FocusOut:\r
+- {\r
+- isActiveApplication = false;\r
+- handleFocusLoss();\r
+- break;\r
+- }\r
+-\r
+- case Expose:\r
+- {\r
+- // Batch together all pending expose events\r
+- XExposeEvent* exposeEvent = (XExposeEvent*) &event->xexpose;\r
+- XEvent nextEvent;\r
+-\r
+- repaint (exposeEvent->x, exposeEvent->y,\r
+- exposeEvent->width, exposeEvent->height);\r
+-\r
+- while (XEventsQueued (display, QueuedAfterFlush) > 0)\r
+- {\r
+- XPeekEvent (display, (XEvent*) &nextEvent);\r
+- if (nextEvent.type != Expose || nextEvent.xany.window != event->xany.window)\r
+- break;\r
+-\r
+- XNextEvent (display, (XEvent*)&nextEvent);\r
+- XExposeEvent* nextExposeEvent = (XExposeEvent*)(&nextEvent.xexpose);\r
+- repaint (nextExposeEvent->x, nextExposeEvent->y,\r
+- nextExposeEvent->width, nextExposeEvent->height);\r
+- }\r
+-\r
+- break;\r
+- }\r
+-\r
+- case CreateNotify:\r
+- case DestroyNotify:\r
+- // Think we can ignore these\r
+- break;\r
+-\r
+- case CirculateNotify:\r
+- break;\r
+-\r
+- case ConfigureNotify:\r
+- case ReparentNotify:\r
+- case GravityNotify:\r
+- updateBounds();\r
+- break;\r
+-\r
+- case MapNotify:\r
+- mapped = true;\r
+- handleBroughtToFront();\r
+- break;\r
+-\r
+- case UnmapNotify:\r
+- mapped = false;\r
+- break;\r
+-\r
+- case MappingNotify:\r
+- {\r
+- XMappingEvent* mappingEvent = (XMappingEvent*) &event->xmapping;\r
+-\r
+- if (mappingEvent->request != MappingPointer)\r
+- {\r
+- // Deal with modifier/keyboard mapping\r
+- XRefreshKeyboardMapping (mappingEvent);\r
+- getModifierMapping();\r
+- }\r
+-\r
+- break;\r
+- }\r
+-\r
+- case ClientMessage:\r
+- {\r
+- XClientMessageEvent* clientMsg = (XClientMessageEvent*) &event->xclient;\r
+-\r
+- if (clientMsg->message_type == wm_Protocols && clientMsg->format == 32)\r
+- {\r
+- const Atom atom = (Atom) clientMsg->data.l[0];\r
+-\r
+- if (atom == wm_ProtocolList [TAKE_FOCUS])\r
+- {\r
+- XWindowAttributes atts;\r
+-\r
+- if (clientMsg->window != 0\r
+- && XGetWindowAttributes (display, clientMsg->window, &atts))\r
+- {\r
+- if (atts.map_state == IsViewable)\r
+- XSetInputFocus (display, clientMsg->window, RevertToParent, clientMsg->data.l[1]);\r
+- }\r
+- }\r
+- else if (atom == wm_ProtocolList [DELETE_WINDOW])\r
+- {\r
+- handleUserClosingWindow();\r
+- }\r
+- }\r
+- else if (clientMsg->message_type == repaintId)\r
+- {\r
+- // Get rid of all pending repaint events\r
+- XEvent nextEvent;\r
+-\r
+- while (XEventsQueued (display, QueuedAfterFlush) > 0)\r
+- {\r
+- XPeekEvent (display, &nextEvent);\r
+- if (nextEvent.xany.type != ClientMessage ||\r
+- nextEvent.xany.window != event->xany.window)\r
+- break;\r
+-\r
+- XClientMessageEvent* nextClientMsg = (XClientMessageEvent*) (&nextEvent.xclient);\r
+- if (nextClientMsg->message_type != repaintId)\r
+- break;\r
+-\r
+- XNextEvent (display, &nextEvent);\r
+- }\r
+-\r
+- static bool reentrancyCheck = false;\r
+- if (! reentrancyCheck)\r
+- {\r
+- reentrancyCheck = true;\r
+-\r
+- int ox, oy, ow, oh;\r
+- getBounds (ox, oy, ow, oh);\r
+- repaint (0, 0, ow, oh);\r
+- performPendingRepaints();\r
+-\r
+- reentrancyCheck = false;\r
+- }\r
+- }\r
+-\r
+- break;\r
+- }\r
+-\r
+- case SelectionClear:\r
+- case SelectionNotify:\r
+- case SelectionRequest:\r
+- // We shouldn't get these on normal windows\r
+- break;\r
+-\r
+- default:\r
+- break;\r
+- }\r
+- }\r
+-\r
+- void showMouseCursor (Cursor cursor)\r
+- {\r
+- XDefineCursor (display, windowH, cursor);\r
+- }\r
+-\r
+- //==============================================================================\r
+- juce_UseDebuggingNewOperator\r
+-\r
+- bool dontRepaint;\r
+-\r
+-private:\r
+- //==============================================================================\r
+- class LinuxRepaintManager : public RepaintManager\r
+- {\r
+- public:\r
+- LinuxRepaintManager (LinuxComponentPeer* const peer_,\r
+- Component* const component,\r
+- const int timeBeforeReleasingImage)\r
+- : RepaintManager (component, timeBeforeReleasingImage),\r
+- peer (peer_)\r
+- {\r
+- }\r
+-\r
+- Image* createNewImage (int w, int h)\r
+- {\r
+- return new XBitmapImage (Image::RGB, w, h, false);\r
+- }\r
+-\r
+- void repaintNow (const RectangleList& areasToPaint)\r
+- {\r
+- peer->clearMaskedRegion();\r
+-\r
+- renderCacheAreasNeedingRepaint();\r
+-\r
+- int x, y;\r
+- XBitmapImage* const paintingBuffer = (XBitmapImage*) getImage (x, y);\r
+-\r
+- if (paintingBuffer != 0)\r
+- {\r
+- const RectangleList* repaintRegion = &areasToPaint;\r
+- RectangleList temp;\r
+-\r
+- if (! peer->maskedRegion.isEmpty())\r
+- {\r
+- temp = areasToPaint;\r
+- temp.subtract (peer->maskedRegion);\r
+- repaintRegion = &temp;\r
+- }\r
+-\r
+- for (RectangleList::Iterator i (*repaintRegion); i.next();)\r
+- {\r
+- const Rectangle& r = i.getRectangle();\r
+-\r
+- paintingBuffer->blitToWindow (peer->windowH,\r
+- r.getX(), r.getY(), r.getWidth(), r.getHeight(),\r
+- r.getX() - x, r.getY() - y);\r
+- }\r
+- }\r
+- }\r
+-\r
+- private:\r
+- LinuxComponentPeer* const peer;\r
+-\r
+- LinuxRepaintManager (const LinuxRepaintManager&);\r
+- const LinuxRepaintManager& operator= (const LinuxRepaintManager&);\r
+- };\r
+-\r
+- LinuxRepaintManager* repainter;\r
+-\r
+- friend class LinuxRepaintManager;\r
+- Window windowH;\r
+- int wx, wy, ww, wh;\r
+- bool fullScreen, entered, mapped;\r
+- BorderSize windowBorder;\r
+-\r
+- //==============================================================================\r
+- void removeWindowDecorations (Window wndH)\r
+- {\r
+- Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- typedef struct\r
+- {\r
+- CARD32 flags;\r
+- CARD32 functions;\r
+- CARD32 decorations;\r
+- INT32 input_mode;\r
+- CARD32 status;\r
+- } MotifWmHints;\r
+-\r
+- MotifWmHints motifHints;\r
+- motifHints.flags = 2; /* MWM_HINTS_DECORATIONS */\r
+- motifHints.decorations = 0;\r
+-\r
+- XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,\r
+- (unsigned char*) &motifHints, 4);\r
+- }\r
+-\r
+- hints = XInternAtom (display, "_WIN_HINTS", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- long gnomeHints = 0;\r
+-\r
+- XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,\r
+- (unsigned char*) &gnomeHints, 1);\r
+- }\r
+-\r
+- hints = XInternAtom (display, "KWM_WIN_DECORATION", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- long kwmHints = 2; /*KDE_tinyDecoration*/\r
+-\r
+- XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,\r
+- (unsigned char*) &kwmHints, 1);\r
+- }\r
+-\r
+- hints = XInternAtom (display, "_NET_WM_WINDOW_TYPE", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- Atom netHints [2];\r
+- netHints[0] = XInternAtom (display, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", True);\r
+-\r
+- if ((styleFlags & windowIsTemporary) != 0)\r
+- netHints[1] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_MENU", True);\r
+- else\r
+- netHints[1] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_NORMAL", True);\r
+-\r
+- XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace,\r
+- (unsigned char*) &netHints, 2);\r
+- }\r
+- }\r
+-\r
+- void addWindowButtons (Window wndH)\r
+- {\r
+- Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- typedef struct\r
+- {\r
+- CARD32 flags;\r
+- CARD32 functions;\r
+- CARD32 decorations;\r
+- INT32 input_mode;\r
+- CARD32 status;\r
+- } MotifWmHints;\r
+-\r
+- MotifWmHints motifHints;\r
+-\r
+- motifHints.flags = 1 | 2; /* MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS */\r
+- motifHints.decorations = 2 /* MWM_DECOR_BORDER */ | 8 /* MWM_DECOR_TITLE */ | 16; /* MWM_DECOR_MENU */\r
+-\r
+- motifHints.functions = 4 /* MWM_FUNC_MOVE */;\r
+-\r
+- if ((styleFlags & windowHasCloseButton) != 0)\r
+- motifHints.functions |= 32; /* MWM_FUNC_CLOSE */\r
+-\r
+- if ((styleFlags & windowHasMinimiseButton) != 0)\r
+- {\r
+- motifHints.functions |= 8; /* MWM_FUNC_MINIMIZE */\r
+- motifHints.decorations |= 0x20; /* MWM_DECOR_MINIMIZE */\r
+- }\r
+-\r
+- if ((styleFlags & windowHasMaximiseButton) != 0)\r
+- {\r
+- motifHints.functions |= 0x10; /* MWM_FUNC_MAXIMIZE */\r
+- motifHints.decorations |= 0x40; /* MWM_DECOR_MAXIMIZE */\r
+- }\r
+-\r
+- if ((styleFlags & windowIsResizable) != 0)\r
+- {\r
+- motifHints.functions |= 2; /* MWM_FUNC_RESIZE */\r
+- motifHints.decorations |= 0x4; /* MWM_DECOR_RESIZEH */\r
+- }\r
+-\r
+- XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,\r
+- (unsigned char*) &motifHints, 4);\r
+- }\r
+-\r
+- hints = XInternAtom (display, "_NET_WM_ALLOWED_ACTIONS", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- Atom netHints [6];\r
+- int num = 0;\r
+-\r
+- netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_RESIZE", (styleFlags & windowIsResizable) ? True : False);\r
+- netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_FULLSCREEN", (styleFlags & windowHasMaximiseButton) ? True : False);\r
+- netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_MINIMIZE", (styleFlags & windowHasMinimiseButton) ? True : False);\r
+- netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_CLOSE", (styleFlags & windowHasCloseButton) ? True : False);\r
+-\r
+- XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace,\r
+- (unsigned char*) &netHints, num);\r
+- }\r
+- }\r
+-\r
+- static void* createWindowCallback (void* userData)\r
+- {\r
+- ((LinuxComponentPeer*) userData)->createWindow();\r
+- return 0;\r
+- }\r
+-\r
+- void createWindow()\r
+- {\r
+- static bool atomsInitialised = false;\r
+-\r
+- if (! atomsInitialised)\r
+- {\r
+- atomsInitialised = true;\r
+-\r
+- wm_Protocols = XInternAtom (display, "WM_PROTOCOLS", 1);\r
+- wm_ProtocolList [TAKE_FOCUS] = XInternAtom (display, "WM_TAKE_FOCUS", 1);\r
+- wm_ProtocolList [DELETE_WINDOW] = XInternAtom (display, "WM_DELETE_WINDOW", 1);\r
+- wm_ChangeState = XInternAtom (display, "WM_CHANGE_STATE", 1);\r
+- wm_State = XInternAtom (display, "WM_STATE", 1);\r
+- wm_ActiveWin = XInternAtom (display, "_NET_ACTIVE_WINDOW", False);\r
+- repaintId = XInternAtom (display, "JUCERepaintAtom", 1);\r
+- }\r
+-\r
+- // Get defaults for various properties\r
+- const int screen = DefaultScreen (display);\r
+- Window root = RootWindow (display, screen);\r
+-\r
+- // Attempt to create a 24-bit window on the default screen. If this is not\r
+- // possible then exit\r
+- XVisualInfo desiredVisual;\r
+- desiredVisual.screen = screen;\r
+- desiredVisual.depth = 24;\r
+-\r
+- int numVisuals;\r
+- XVisualInfo* visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask,\r
+- &desiredVisual, &numVisuals);\r
+-\r
+- if (numVisuals < 1 || visuals == 0)\r
+- {\r
+- Logger::outputDebugString ("ERROR: System doesn't support 24-bit RGB display.\n");\r
+- Process::terminate();\r
+- }\r
+-\r
+- // Just choose the first one\r
+- Visual* visual = visuals[0].visual;\r
+- const int depth = visuals[0].depth;\r
+- XFree (visuals);\r
+-\r
+- // Set up the window attributes\r
+- XSetWindowAttributes swa;\r
+- swa.border_pixel = 0;\r
+- swa.colormap = DefaultColormap (display, screen);\r
+- swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False;\r
+- swa.event_mask = eventMask;\r
+-\r
+- Window wndH = XCreateWindow (display, root,\r
+- 0, 0, 1, 1, 0,\r
+- depth, InputOutput, visual,\r
+- CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,\r
+- &swa);\r
+-\r
+- XGrabButton (display, AnyButton, AnyModifier, wndH, False,\r
+- ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,\r
+- GrabModeAsync, GrabModeAsync, None, None);\r
+-\r
+- // Set the window context to identify the window handle object\r
+- if (XSaveContext (display, (XID) wndH, improbableNumber, (XPointer) this))\r
+- {\r
+- // Failed\r
+- jassertfalse\r
+- Logger::outputDebugString ("Failed to create context information for window.\n");\r
+- XDestroyWindow (display, wndH);\r
+- wndH = 0;\r
+- }\r
+-\r
+- // Set window manager hints\r
+- XWMHints* wmHints = XAllocWMHints();\r
+- wmHints->flags = InputHint | StateHint;\r
+- wmHints->input = True; // Locally active input model\r
+- wmHints->initial_state = NormalState;\r
+- XSetWMHints (display, wndH, wmHints);\r
+- XFree (wmHints);\r
+-\r
+- if ((styleFlags & juce_windowIsSemiTransparentFlag) != 0)\r
+- {\r
+- //xxx\r
+- jassertfalse\r
+- }\r
+-\r
+- if ((styleFlags & windowAppearsOnTaskbar) != 0)\r
+- {\r
+- //xxx\r
+- }\r
+-\r
+- if ((styleFlags & windowHasTitleBar) == 0)\r
+- removeWindowDecorations (wndH);\r
+- else\r
+- addWindowButtons (wndH);\r
+-\r
+- XSetTransientForHint (display, wndH, RootWindow (display, DefaultScreen (display)));\r
+-\r
+- // Set window manager protocols\r
+- XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace,\r
+- (unsigned char*) wm_ProtocolList, 2);\r
+-\r
+- // Set window name\r
+- setWindowTitle (wndH, getComponent()->getName());\r
+-\r
+- // Initialise the pointer and keyboard mapping\r
+- // This is not the same as the logical pointer mapping the X server uses:\r
+- // we don't mess with this.\r
+- static bool mappingInitialised = false;\r
+-\r
+- if (! mappingInitialised)\r
+- {\r
+- mappingInitialised = true;\r
+-\r
+- const int numButtons = XGetPointerMapping (display, 0, 0);\r
+-\r
+- if (numButtons == 2)\r
+- {\r
+- pointerMap[0] = LeftButton;\r
+- pointerMap[1] = RightButton;\r
+- pointerMap[2] = pointerMap[3] = pointerMap[4] = NoButton;\r
+- }\r
+- else if (numButtons >= 3)\r
+- {\r
+- pointerMap[0] = LeftButton;\r
+- pointerMap[1] = MiddleButton;\r
+- pointerMap[2] = RightButton;\r
+-\r
+- if (numButtons >= 5)\r
+- {\r
+- pointerMap[3] = WheelUp;\r
+- pointerMap[4] = WheelDown;\r
+- }\r
+- }\r
+-\r
+- getModifierMapping();\r
+- }\r
+-\r
+- windowH = wndH;\r
+- }\r
+-\r
+- static void* destroyWindowCallback (void* userData)\r
+- {\r
+- Window windowH = (Window) userData;\r
+-\r
+- XPointer handlePointer;\r
+- if (! XFindContext (display, (XID) windowH, improbableNumber, &handlePointer))\r
+- XDeleteContext (display, (XID) windowH, improbableNumber);\r
+-\r
+- XDestroyWindow (display, windowH);\r
+-\r
+- // Wait for it to complete and then remove any events for this\r
+- // window from the event queue.\r
+- XSync (display, false);\r
+-\r
+- XEvent event;\r
+- while (XCheckWindowEvent (display, windowH, eventMask, &event) == True)\r
+- {}\r
+-\r
+- return 0;\r
+- }\r
+-\r
+- static int64 getEventTime (::Time t)\r
+- {\r
+- static int64 eventTimeOffset = 0x12345678;\r
+- const int64 thisMessageTime = t;\r
+-\r
+- if (eventTimeOffset == 0x12345678)\r
+- eventTimeOffset = Time::currentTimeMillis() - thisMessageTime;\r
+-\r
+- return eventTimeOffset + thisMessageTime;\r
+- }\r
+-\r
+- static void setWindowTitle (Window xwin, const char* const title)\r
+- {\r
+- XTextProperty nameProperty;\r
+- char* strings[] = { (char*) title };\r
+-\r
+- if (XStringListToTextProperty (strings, 1, &nameProperty))\r
+- {\r
+- XSetWMName (display, xwin, &nameProperty);\r
+- XSetWMIconName (display, xwin, &nameProperty);\r
+- }\r
+- }\r
+-\r
+- void updateBorderSize()\r
+- {\r
+- if ((styleFlags & windowHasTitleBar) == 0)\r
+- {\r
+- windowBorder = BorderSize (0);\r
+- }\r
+- else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0)\r
+- {\r
+- Atom hints = XInternAtom (display, "_NET_FRAME_EXTENTS", True);\r
+-\r
+- if (hints != None)\r
+- {\r
+- CARD32* sizes = 0;\r
+- unsigned long nitems, bytesLeft;\r
+- Atom actualType;\r
+- int actualFormat;\r
+-\r
+- if (XGetWindowProperty (display, windowH, hints, 0, 4, False,\r
+- XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft,\r
+- (unsigned char**) &sizes) == Success)\r
+- {\r
+- if (actualFormat == 32)\r
+- windowBorder = BorderSize ((int) sizes[2], (int) sizes[0],\r
+- (int) sizes[3], (int) sizes[1]);\r
+-\r
+- XFree (sizes);\r
+- }\r
+- }\r
+- }\r
+- }\r
+-\r
+- void updateBounds()\r
+- {\r
+- jassert (windowH != 0);\r
+- if (windowH != 0)\r
+- {\r
+- Window root, child;\r
+- unsigned int bw, depth;\r
+-\r
+- if (! XGetGeometry (display, (Drawable) windowH, &root,\r
+- &wx, &wy, (unsigned int*) &ww, (unsigned int*) &wh,\r
+- &bw, &depth))\r
+- {\r
+- wx = wy = ww = wh = 0;\r
+- }\r
+- else if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child))\r
+- {\r
+- wx = wy = 0;\r
+- }\r
+-\r
+- updateBorderSize();\r
+- handleMovedOrResized();\r
+- }\r
+- }\r
+-};\r
+-\r
+-//==============================================================================\r
+-ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/)\r
+-{\r
+- return new LinuxComponentPeer (this, styleFlags);\r
+-}\r
+-\r
+-\r
+-//==============================================================================\r
+-// (this callback is hooked up in the messaging code)\r
+-void juce_windowMessageReceive (XEvent* event)\r
+-{\r
+- if (event->xany.window != None)\r
+- {\r
+- // Check if the event is for one of our windows\r
+- LinuxComponentPeer* peer = 0;\r
+-\r
+- if (! XFindContext (display, (XID) event->xany.window, improbableNumber, (XPointer*) &peer))\r
+- {\r
+- if (peer != 0 && peer->isValidMessageListener())\r
+- peer->handleWindowMessage (event);\r
+- }\r
+- }\r
+- else\r
+- {\r
+- switch (event->xany.type)\r
+- {\r
+- case KeymapNotify:\r
+- {\r
+- const XKeymapEvent* const keymapEvent = (const XKeymapEvent*) &event->xkeymap;\r
+- memcpy (keyStates, keymapEvent->key_vector, 32);\r
+- break;\r
+- }\r
+-\r
+- default:\r
+- break;\r
+- }\r
+- }\r
+-}\r
+-\r
+-//==============================================================================\r
+-void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool clipToWorkArea)\r
+-{\r
+-#if JUCE_USE_XINERAMA\r
+- int major_opcode, first_event, first_error;\r
+-\r
+- if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)\r
+- && XineramaIsActive (display))\r
+- {\r
+- int numMonitors = 0;\r
+- XineramaScreenInfo* const screens = XineramaQueryScreens (display, &numMonitors);\r
+-\r
+- if (screens != 0)\r
+- {\r
+- for (int i = numMonitors; --i >= 0;)\r
+- {\r
+- int index = screens[i].screen_number;\r
+-\r
+- if (index >= 0)\r
+- {\r
+- while (monitorCoords.size() < index)\r
+- monitorCoords.add (Rectangle (0, 0, 0, 0));\r
+-\r
+- monitorCoords.set (index, Rectangle (screens[i].x_org,\r
+- screens[i].y_org,\r
+- screens[i].width,\r
+- screens[i].height));\r
+- }\r
+- }\r
+-\r
+- XFree (screens);\r
+- }\r
+- }\r
+-\r
+- if (monitorCoords.size() == 0)\r
+-#endif\r
+- {\r
+- monitorCoords.add (Rectangle (0, 0,\r
+- DisplayWidth (display, DefaultScreen (display)),\r
+- DisplayHeight (display, DefaultScreen (display))));\r
+- }\r
+-}\r
+-\r
+-//==============================================================================\r
+-bool Desktop::canUseSemiTransparentWindows()\r
+-{\r
+- return false;\r
+-}\r
+-\r
+-void Desktop::getMousePosition (int& x, int& y)\r
+-{\r
+- int mouseMods;\r
+- getMousePos (x, y, mouseMods);\r
+-}\r
+-\r
+-void Desktop::setMousePosition (int x, int y)\r
+-{\r
+- Window root = RootWindow (display, DefaultScreen (display));\r
+- XWarpPointer (display, None, root, 0, 0, 0, 0, x, y);\r
+-}\r
+-\r
+-\r
+-//==============================================================================\r
+-void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY)\r
+-{\r
+- Window root = RootWindow (display, DefaultScreen (display));\r
+- const unsigned int imageW = image.getWidth();\r
+- const unsigned int imageH = image.getHeight();\r
+- unsigned int cursorW, cursorH;\r
+-\r
+- if (! XQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH))\r
+- return 0;\r
+-\r
+- Image im (Image::ARGB, cursorW, cursorH, true);\r
+- Graphics g (im);\r
+-\r
+- if (imageW > cursorW || imageH > cursorH)\r
+- {\r
+- hotspotX = (hotspotX * cursorW) / imageW;\r
+- hotspotY = (hotspotY * cursorH) / imageH;\r
+-\r
+- g.drawImageWithin (&image, 0, 0, imageW, imageH,\r
+- Justification::topLeft,\r
+- false, false);\r
+- }\r
+- else\r
+- {\r
+- g.drawImageAt (&image, 0, 0);\r
+- }\r
+-\r
+- const int stride = (cursorW + 7) >> 3;\r
+- unsigned char* const maskPlane = (unsigned char*)juce_calloc (stride*cursorH);\r
+- unsigned char* const sourcePlane = (unsigned char*)juce_calloc (stride*cursorH);\r
+-\r
+- bool msbfirst = (BitmapBitOrder (display) == MSBFirst);\r
+-\r
+- for (int y = cursorH; --y >= 0;)\r
+- {\r
+- for (int x = cursorW; --x >= 0;)\r
+- {\r
+- const unsigned char mask = (unsigned char)(1 << (msbfirst ? (7 - (x & 7)) : (x & 7)));\r
+- const int offset = y * stride + (x >> 3);\r
+-\r
+- const Colour c (im.getPixelAt (x, y));\r
+-\r
+- if (c.getAlpha() >= 128)\r
+- maskPlane[offset] |= mask;\r
+-\r
+- if (c.getBrightness() >= 0.5f)\r
+- sourcePlane[offset] |= mask;\r
+- }\r
+- }\r
+-\r
+- Pixmap sourcePixmap = XCreatePixmapFromBitmapData (display, root, (char*)sourcePlane, cursorW, cursorH, 0xffff, 0, 1);\r
+- Pixmap maskPixmap = XCreatePixmapFromBitmapData (display, root, (char*)maskPlane, cursorW, cursorH, 0xffff, 0, 1);\r
+-\r
+- juce_free (maskPlane);\r
+- juce_free (sourcePlane);\r
+-\r
+- XColor white, black;\r
+- black.red = black.green = black.blue = 0;\r
+- white.red = white.green = white.blue = 0xffff;\r
+-\r
+- void* result = (void*) XCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, hotspotX, hotspotY);\r
+-\r
+- XFreePixmap (display, sourcePixmap);\r
+- XFreePixmap (display, maskPixmap);\r
+-\r
+- return result;\r
+-}\r
+-\r
+-void juce_deleteMouseCursor (void* cursorHandle, bool)\r
+-{\r
+- if (cursorHandle != None)\r
+- XFreeCursor (display, (Cursor)cursorHandle);\r
+-}\r
+-\r
+-void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type)\r
+-{\r
+- unsigned int shape;\r
+-\r
+- switch (type)\r
+- {\r
+- case MouseCursor::NoCursor:\r
+- {\r
+- void* invisibleCursor;\r
+-\r
+- Image im (Image::ARGB, 16, 16, true);\r
+- invisibleCursor = juce_createMouseCursorFromImage (im, 0, 0);\r
+-\r
+- return invisibleCursor;\r
+- }\r
+-\r
+- case MouseCursor::NormalCursor:\r
+- return (void*) None; // Use parent cursor\r
+-\r
+- case MouseCursor::DraggingHandCursor:\r
+- {\r
+- void* dragHandCursor;\r
+- static unsigned char dragHandData[] = {71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,\r
+- 0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0,\r
+- 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,\r
+- 132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217,\r
+- 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 };\r
+- const int dragHandDataSize = 99;\r
+-\r
+- Image* im = ImageFileFormat::loadFrom ((const char*) dragHandData, dragHandDataSize);\r
+- dragHandCursor = juce_createMouseCursorFromImage (*im, 8, 7);\r
+- delete im;\r
+-\r
+- return dragHandCursor;\r
+- }\r
+-\r
+- case MouseCursor::CopyingCursor:\r
+- {\r
+- void* copyCursor;\r
+-\r
+- static unsigned char copyCursorData[] = {71,73,70,56,57,97,21,0,21,0,145,0,0,0,0,0,255,255,255,0,\r
+- 128,128,255,255,255,33,249,4,1,0,0,3,0,44,0,0,0,0,21,0,\r
+- 21,0,0,2,72,4,134,169,171,16,199,98,11,79,90,71,161,93,56,111,\r
+- 78,133,218,215,137,31,82,154,100,200,86,91,202,142,12,108,212,87,235,174,\r
+- 15,54,214,126,237,226,37,96,59,141,16,37,18,201,142,157,230,204,51,112,\r
+- 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 };\r
+- const int copyCursorSize = 119;\r
+-\r
+- Image* im = ImageFileFormat::loadFrom ((const char*)copyCursorData, copyCursorSize);\r
+- copyCursor = juce_createMouseCursorFromImage (*im, 1, 3);\r
+- delete im;\r
+-\r
+- return copyCursor;\r
+- }\r
+-\r
+- case MouseCursor::WaitCursor:\r
+- shape = XC_watch;\r
+- break;\r
+-\r
+- case MouseCursor::IBeamCursor:\r
+- shape = XC_xterm;\r
+- break;\r
+-\r
+- case MouseCursor::PointingHandCursor:\r
+- shape = XC_hand2;\r
+- break;\r
+-\r
+- case MouseCursor::LeftRightResizeCursor:\r
+- shape = XC_sb_h_double_arrow;\r
+- break;\r
+-\r
+- case MouseCursor::UpDownResizeCursor:\r
+- shape = XC_sb_v_double_arrow;\r
+- break;\r
+-\r
+- case MouseCursor::UpDownLeftRightResizeCursor:\r
+- shape = XC_fleur;\r
+- break;\r
+-\r
+- case MouseCursor::TopEdgeResizeCursor:\r
+- shape = XC_top_side;\r
+- break;\r
+-\r
+- case MouseCursor::BottomEdgeResizeCursor:\r
+- shape = XC_bottom_side;\r
+- break;\r
+-\r
+- case MouseCursor::LeftEdgeResizeCursor:\r
+- shape = XC_left_side;\r
+- break;\r
+-\r
+- case MouseCursor::RightEdgeResizeCursor:\r
+- shape = XC_right_side;\r
+- break;\r
+-\r
+- case MouseCursor::TopLeftCornerResizeCursor:\r
+- shape = XC_top_left_corner;\r
+- break;\r
+-\r
+- case MouseCursor::TopRightCornerResizeCursor:\r
+- shape = XC_top_right_corner;\r
+- break;\r
+-\r
+- case MouseCursor::BottomLeftCornerResizeCursor:\r
+- shape = XC_bottom_left_corner;\r
+- break;\r
+-\r
+- case MouseCursor::BottomRightCornerResizeCursor:\r
+- shape = XC_bottom_right_corner;\r
+- break;\r
+-\r
+- case MouseCursor::CrosshairCursor:\r
+- shape = XC_crosshair;\r
+- break;\r
+-\r
+- default:\r
+- return (void*) None; // Use parent cursor\r
+- }\r
+-\r
+- return (void*) XCreateFontCursor (display, shape);\r
+-}\r
+-\r
+-void MouseCursor::showInWindow (ComponentPeer* peer) const\r
+-{\r
+- LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (peer);\r
+-\r
+- if (lp != 0)\r
+- lp->showMouseCursor ((Cursor) getHandle());\r
+-}\r
+-\r
+-void MouseCursor::showInAllWindows() const\r
+-{\r
+- for (int i = ComponentPeer::getNumPeers(); --i >= 0;)\r
+- showInWindow (ComponentPeer::getPeer (i));\r
+-}\r
+-\r
+-//==============================================================================\r
+-Image* juce_createIconForFile (const File& file)\r
+-{\r
+- return 0;\r
+-}\r
+-\r
+-\r
+-//==============================================================================\r
+-#if JUCE_OPENGL\r
+-\r
+-struct OpenGLContextInfo\r
+-{\r
+- Window embeddedWindow;\r
+- GLXContext renderContext;\r
+-};\r
+-\r
+-void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)\r
+-{\r
+- XSync (display, False);\r
+- jassert (component != 0);\r
+-\r
+- if (component == 0)\r
+- return 0;\r
+-\r
+- LinuxComponentPeer* const peer\r
+- = dynamic_cast <LinuxComponentPeer*> (component->getTopLevelComponent()->getPeer());\r
+-\r
+- if (peer == 0)\r
+- return 0;\r
+-\r
+- GLint attribList[] =\r
+- {\r
+- GLX_RGBA,\r
+- GLX_DOUBLEBUFFER,\r
+- GLX_RED_SIZE, 8,\r
+- GLX_GREEN_SIZE, 8,\r
+- GLX_BLUE_SIZE, 8,\r
+- GLX_ALPHA_SIZE, 8,\r
+- GLX_DEPTH_SIZE, 8,\r
+- None\r
+- };\r
+-\r
+- XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribList);\r
+-\r
+- if (bestVisual == 0)\r
+- return 0;\r
+-\r
+- OpenGLContextInfo* const oc = new OpenGLContextInfo();\r
+-\r
+- oc->renderContext = glXCreateContext (display, bestVisual,\r
+- (sharedContext != 0) ? ((OpenGLContextInfo*) sharedContext)->renderContext\r
+- : 0,\r
+- GL_TRUE);\r
+-\r
+- Window windowH = (Window) peer->getNativeHandle();\r
+-\r
+- Colormap colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone);\r
+- XSetWindowAttributes swa;\r
+- swa.colormap = colourMap;\r
+- swa.border_pixel = 0;\r
+- swa.event_mask = StructureNotifyMask;\r
+-\r
+- oc->embeddedWindow = XCreateWindow (display, windowH,\r
+- 0, 0, 1, 1, 0,\r
+- bestVisual->depth,\r
+- InputOutput,\r
+- bestVisual->visual,\r
+- CWBorderPixel | CWColormap | CWEventMask,\r
+- &swa);\r
+-\r
+- XMapWindow (display, oc->embeddedWindow);\r
+- XFreeColormap (display, colourMap);\r
+-\r
+- XFree (bestVisual);\r
+- XSync (display, False);\r
+-\r
+- return oc;\r
+-}\r
+-\r
+-void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp)\r
+-{\r
+- jassert (context != 0);\r
+- OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;\r
+-\r
+- XMoveResizeWindow (display, oc->embeddedWindow,\r
+- owner->getScreenX() - topComp->getScreenX(),\r
+- owner->getScreenY() - topComp->getScreenY(),\r
+- jmax (1, owner->getWidth()),\r
+- jmax (1, owner->getHeight()));\r
+-}\r
+-\r
+-void juce_deleteOpenGLContext (void* context)\r
+-{\r
+- OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;\r
+-\r
+- if (oc != 0)\r
+- {\r
+- glXDestroyContext (display, oc->renderContext);\r
+-\r
+- XUnmapWindow (display, oc->embeddedWindow);\r
+- XDestroyWindow (display, oc->embeddedWindow);\r
+-\r
+- delete oc;\r
+- }\r
+-}\r
+-\r
+-bool juce_makeOpenGLContextCurrent (void* context)\r
+-{\r
+- OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;\r
+-\r
+- if (oc != 0)\r
+- return glXMakeCurrent (display, oc->embeddedWindow, oc->renderContext)\r
+- && XSync (display, False);\r
+- else\r
+- return glXMakeCurrent (display, None, 0);\r
+-}\r
+-\r
+-void juce_swapOpenGLBuffers (void* context)\r
+-{\r
+- OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;\r
+-\r
+- if (oc != 0)\r
+- glXSwapBuffers (display, oc->embeddedWindow);\r
+-}\r
+-\r
+-void juce_repaintOpenGLWindow (void* context)\r
+-{\r
+-}\r
+-\r
+-#endif\r
+-\r
+-\r
+-//==============================================================================\r
+-static void initClipboard (Window root, Atom* cutBuffers)\r
+-{\r
+- static bool init = false;\r
+-\r
+- if (! init)\r
+- {\r
+- init = true;\r
+-\r
+- // Make sure all cut buffers exist before use\r
+- for (int i = 0; i < 8; i++)\r
+- {\r
+- XChangeProperty (display, root, cutBuffers[i],\r
+- XA_STRING, 8, PropModeAppend, NULL, 0);\r
+- }\r
+- }\r
+-}\r
+-\r
+-// Clipboard implemented currently using cut buffers\r
+-// rather than the more powerful selection method\r
+-void SystemClipboard::copyTextToClipboard (const String& clipText)\r
+-{\r
+- Window root = RootWindow (display, DefaultScreen (display));\r
+- Atom cutBuffers[8] = { XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3,\r
+- XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7 };\r
+-\r
+- initClipboard (root, cutBuffers);\r
+-\r
+- XRotateWindowProperties (display, root, cutBuffers, 8, 1);\r
+- XChangeProperty (display, root, cutBuffers[0],\r
+- XA_STRING, 8, PropModeReplace, (const unsigned char*)((const char*)clipText),\r
+- clipText.length());\r
+-}\r
+-\r
+-const String SystemClipboard::getTextFromClipboard()\r
+-{\r
+- char* clipData;\r
+- const int bufSize = 64; // in words\r
+- int actualFormat;\r
+- int byteOffset = 0;\r
+- unsigned long bytesLeft, nitems;\r
+- Atom actualType;\r
+- String returnData;\r
+-\r
+- Window root = RootWindow (display, DefaultScreen (display));\r
+-\r
+- Atom cutBuffers[8] = { XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3,\r
+- XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7 };\r
+-\r
+- initClipboard (root, cutBuffers);\r
+-\r
+- do\r
+- {\r
+- if (XGetWindowProperty (display, root, cutBuffers[0], byteOffset >> 2, bufSize,\r
+- False, XA_STRING, &actualType, &actualFormat, &nitems, &bytesLeft,\r
+- (unsigned char**) &clipData) != Success\r
+- || actualType != XA_STRING\r
+- || actualFormat != 8)\r
+- return String();\r
+-\r
+- byteOffset += nitems;\r
+- returnData += String(clipData, nitems);\r
+- XFree (clipData);\r
+- }\r
+- while (bytesLeft);\r
+-\r
+- return returnData;\r
+-}\r
+-\r
+-//==============================================================================\r
+-bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles)\r
+-{\r
+- jassertfalse // not implemented!\r
+- return false;\r
+-}\r
+-\r
+-bool DragAndDropContainer::performExternalDragDropOfText (const String& text)\r
+-{\r
+- jassertfalse // not implemented!\r
+- return false;\r
+-}\r
+-\r
+-\r
+-//==============================================================================\r
+-void PlatformUtilities::beep()\r
+-{\r
+- //xxx\r
+-}\r
+-\r
+-\r
+-//==============================================================================\r
+-bool AlertWindow::showNativeDialogBox (const String& title,\r
+- const String& bodyText,\r
+- bool isOkCancel)\r
+-{\r
+- // xxx this is supposed to pop up an alert!\r
+- Logger::outputDebugString (title + ": " + bodyText);\r
+- return true;\r
+-}\r
+-\r
+-//==============================================================================\r
+-const int KeyPress::spaceKey = XK_space & 0xff;\r
+-const int KeyPress::returnKey = XK_Return & 0xff;\r
+-const int KeyPress::escapeKey = XK_Escape & 0xff;\r
+-const int KeyPress::backspaceKey = XK_BackSpace & 0xff;\r
+-const int KeyPress::leftKey = (XK_Left & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::rightKey = (XK_Right & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::upKey = (XK_Up & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::downKey = (XK_Down & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::pageUpKey = (XK_Page_Up & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::pageDownKey = (XK_Page_Down & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::endKey = (XK_End & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::homeKey = (XK_Home & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::insertKey = (XK_Insert & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::deleteKey = (XK_Delete & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::tabKey = XK_Tab & 0xff;\r
+-const int KeyPress::F1Key = (XK_F1 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F2Key = (XK_F2 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F3Key = (XK_F3 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F4Key = (XK_F4 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F5Key = (XK_F5 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F6Key = (XK_F6 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F7Key = (XK_F7 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F8Key = (XK_F8 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F9Key = (XK_F9 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F10Key = (XK_F10 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F11Key = (XK_F11 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::F12Key = (XK_F12 & 0xff) | nonAsciiModifier;\r
+-const int KeyPress::playKey = (0xffeeff00) | nonAsciiModifier;\r
+-const int KeyPress::stopKey = (0xffeeff01) | nonAsciiModifier;\r
+-const int KeyPress::fastForwardKey = (0xffeeff02) | nonAsciiModifier;\r
+-const int KeyPress::rewindKey = (0xffeeff03) | nonAsciiModifier;\r
+-\r
+-\r
+-END_JUCE_NAMESPACE\r
+-\r
+-#endif\r
++/*
++ ==============================================================================
++
++ This file is part of the JUCE library - "Jules' Utility Class Extensions"
++ Copyright 2004-6 by Raw Material Software ltd.
++
++ ------------------------------------------------------------------------------
++
++ JUCE can be redistributed and/or modified under the terms of the
++ GNU General Public License, as published by the Free Software Foundation;
++ either version 2 of the License, or (at your option) any later version.
++
++ JUCE is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with JUCE; if not, visit www.gnu.org/licenses or write to the
++ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
++ Boston, MA 02111-1307 USA
++
++ ------------------------------------------------------------------------------
++
++ If you'd like to release a closed-source product which uses JUCE, commercial
++ licenses are also available: visit www.rawmaterialsoftware.com/juce for
++ more information.
++
++ ==============================================================================
++*/
++
++#include "juce_Config.h"
++#if JUCE_BUILD_GUI_CLASSES
++
++#include "linuxincludes.h"
++#include <X11/Xlib.h>
++#include <X11/Xutil.h>
++#include <X11/Xatom.h>
++#include <X11/Xmd.h>
++#include <X11/keysym.h>
++#include <X11/cursorfont.h>
++
++#include "../../../juce_Config.h"
++#undef JUCE_USE_XINERAMA
++#undef JUCE_OPENGL
++#if JUCE_USE_XINERAMA
++#include <X11/extensions/Xinerama.h>
++#endif
++
++#if JUCE_OPENGL
++#include <X11/Xlib.h>
++#include <GL/glx.h>
++#endif
++
++#undef KeyPress
++
++#include "../../../src/juce_core/basics/juce_StandardHeader.h"
++
++BEGIN_JUCE_NAMESPACE
++
++#include "../../../src/juce_appframework/events/juce_Timer.h"
++#include "../../../src/juce_appframework/application/juce_DeletedAtShutdown.h"
++#include "../../../src/juce_appframework/gui/components/keyboard/juce_KeyPress.h"
++#include "../../../src/juce_appframework/application/juce_SystemClipboard.h"
++#include "../../../src/juce_appframework/gui/components/windows/juce_AlertWindow.h"
++#include "../../../src/juce_appframework/gui/components/special/juce_OpenGLComponent.h"
++#include "../../../src/juce_appframework/gui/components/juce_Desktop.h"
++#include "../../../src/juce_appframework/events/juce_MessageManager.h"
++#include "../../../src/juce_appframework/gui/components/juce_RepaintManager.h"
++#include "../../../src/juce_appframework/gui/components/juce_ComponentDeletionWatcher.h"
++#include "../../../src/juce_appframework/gui/graphics/geometry/juce_RectangleList.h"
++#include "../../../src/juce_appframework/gui/graphics/imaging/juce_ImageFileFormat.h"
++#include "../../../src/juce_appframework/gui/components/mouse/juce_DragAndDropContainer.h"
++#include "../../../src/juce_core/basics/juce_Logger.h"
++#include "../../../src/juce_core/threads/juce_Process.h"
++#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
++
++
++//==============================================================================
++static Atom wm_ChangeState = None;
++static Atom wm_State = None;
++static Atom wm_Protocols = None;
++static Atom wm_ProtocolList [2] = { None, None };
++static Atom wm_ActiveWin = None;
++static Atom repaintId = None;
++
++#define TAKE_FOCUS 0
++#define DELETE_WINDOW 1
++
++//==============================================================================
++static bool isActiveApplication = false;
++
++bool Process::isForegroundProcess()
++{
++ return isActiveApplication;
++}
++
++//==============================================================================
++// These are defined in juce_linux_Messages.cpp
++extern Display* display;
++extern XContext improbableNumber;
++
++const int juce_windowIsSemiTransparentFlag = (1 << 31); // also in component.cpp
++
++static const int eventMask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask
++ | EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeymapStateMask
++ | ExposureMask | StructureNotifyMask | FocusChangeMask;
++
++//==============================================================================
++static int pointerMap[5];
++static int lastMousePosX = 0, lastMousePosY = 0;
++
++enum MouseButtons
++{
++ NoButton = 0,
++ LeftButton = 1,
++ MiddleButton = 2,
++ RightButton = 3,
++ WheelUp = 4,
++ WheelDown = 5
++};
++
++static void getMousePos (int& x, int& y, int& mouseMods)
++{
++ Window root, child;
++ int winx, winy;
++ unsigned int mask;
++
++ mouseMods = 0;
++
++ if (XQueryPointer (display,
++ RootWindow (display, DefaultScreen (display)),
++ &root, &child,
++ &x, &y, &winx, &winy, &mask) == False)
++ {
++ // Pointer not on the default screen
++ x = y = -1;
++ }
++ else
++ {
++ if ((mask & Button1Mask) != 0)
++ mouseMods |= ModifierKeys::leftButtonModifier;
++
++ if ((mask & Button2Mask) != 0)
++ mouseMods |= ModifierKeys::middleButtonModifier;
++
++ if ((mask & Button3Mask) != 0)
++ mouseMods |= ModifierKeys::rightButtonModifier;
++ }
++}
++
++//==============================================================================
++static int AltMask = 0;
++static int NumLockMask = 0;
++static bool numLock = 0;
++static bool capsLock = 0;
++static char keyStates [32];
++
++static void updateKeyStates (const int keycode, const bool press)
++{
++ const int keybyte = keycode >> 3;
++ const int keybit = (1 << (keycode & 7));
++
++ if (press)
++ keyStates [keybyte] |= keybit;
++ else
++ keyStates [keybyte] &= ~keybit;
++}
++
++static bool keyDown (const int keycode)
++{
++ const int keybyte = keycode >> 3;
++ const int keybit = (1 << (keycode & 7));
++
++ return (keyStates [keybyte] & keybit) != 0;
++}
++
++static const int nonAsciiModifier = 0x10000;
++
++bool KeyPress::isKeyCurrentlyDown (int keyCode)
++{
++ int keysym;
++
++ if (keyCode & nonAsciiModifier)
++ {
++ keysym = 0xff00 | (keyCode & 0xff);
++ }
++ else
++ {
++ keysym = keyCode;
++
++ if (keysym == (XK_Tab & 0xff)
++ || keysym == (XK_Return & 0xff)
++ || keysym == (XK_Escape & 0xff)
++ || keysym == (XK_BackSpace & 0xff))
++ {
++ keysym |= 0xff00;
++ }
++ }
++
++ return keyDown (XKeysymToKeycode (display, keysym));
++}
++
++//==============================================================================
++// Alt and Num lock are not defined by standard X
++// modifier constants: check what they're mapped to
++static void getModifierMapping()
++{
++ const int altLeftCode = XKeysymToKeycode (display, XK_Alt_L);
++ const int numLockCode = XKeysymToKeycode (display, XK_Num_Lock);
++
++ AltMask = 0;
++ NumLockMask = 0;
++
++ XModifierKeymap* mapping = XGetModifierMapping (display);
++
++ if (mapping)
++ {
++ for (int i = 0; i < 8; i++)
++ {
++ if (mapping->modifiermap [i << 1] == altLeftCode)
++ AltMask = 1 << i;
++ else if (mapping->modifiermap [i << 1] == numLockCode)
++ NumLockMask = 1 << i;
++ }
++
++ XFreeModifiermap (mapping);
++ }
++}
++
++static int currentModifiers = 0;
++
++void ModifierKeys::updateCurrentModifiers()
++{
++ currentModifierFlags = currentModifiers;
++}
++
++const ModifierKeys ModifierKeys::getCurrentModifiersRealtime()
++{
++ int x, y, mouseMods;
++ getMousePos (x, y, mouseMods);
++
++ currentModifiers &= ~ModifierKeys::allMouseButtonModifiers;
++ currentModifiers |= mouseMods;
++
++ return ModifierKeys (currentModifiers);
++}
++
++static void updateKeyModifiers (const int status)
++{
++ currentModifiers &= ~(ModifierKeys::shiftModifier
++ | ModifierKeys::ctrlModifier
++ | ModifierKeys::altModifier);
++
++ if (status & ShiftMask)
++ currentModifiers |= ModifierKeys::shiftModifier;
++
++ if (status & ControlMask)
++ currentModifiers |= ModifierKeys::ctrlModifier;
++
++ if (status & AltMask)
++ currentModifiers |= ModifierKeys::altModifier;
++
++ numLock = ((status & NumLockMask) != 0);
++ capsLock = ((status & LockMask) != 0);
++}
++
++static bool updateKeyModifiersFromSym (KeySym sym, const bool press)
++{
++ int modifier = 0;
++ bool isModifier = true;
++
++ switch (sym)
++ {
++ case XK_Shift_L:
++ case XK_Shift_R:
++ modifier = ModifierKeys::shiftModifier;
++ break;
++
++ case XK_Control_L:
++ case XK_Control_R:
++ modifier = ModifierKeys::ctrlModifier;
++ break;
++
++ case XK_Alt_L:
++ case XK_Alt_R:
++ modifier = ModifierKeys::altModifier;
++ break;
++
++ case XK_Num_Lock:
++ if (press)
++ numLock = ! numLock;
++
++ break;
++
++ case XK_Caps_Lock:
++ if (press)
++ capsLock = ! capsLock;
++
++ break;
++
++ case XK_Scroll_Lock:
++ break;
++
++ default:
++ isModifier = false;
++ break;
++ }
++
++ if (modifier != 0)
++ {
++ if (press)
++ currentModifiers |= modifier;
++ else
++ currentModifiers &= ~modifier;
++ }
++
++ return isModifier;
++}
++
++
++//==============================================================================
++class XBitmapImage : public Image
++{
++public:
++ //==============================================================================
++ XBitmapImage (const PixelFormat format_, const int w, const int h, const bool clearImage)
++ : Image (format_, w, h)
++ {
++ jassert (format_ == RGB || format_ == ARGB);
++
++ pixelStride = (format_ == RGB) ? 3 : 4;
++ lineStride = ((w * pixelStride + 3) & ~3);
++ imageData = (uint8*) juce_malloc (lineStride * h);
++
++ if (format_ == ARGB && clearImage)
++ zeromem (xImage->data, h * lineStride);
++
++ xImage = new XImage();
++ xImage->width = w;
++ xImage->height = h;
++ xImage->xoffset = 0;
++ xImage->format = ZPixmap;
++ xImage->data = (char*) imageData;
++ xImage->byte_order = ImageByteOrder (display);
++ xImage->bitmap_unit = BitmapUnit (display);
++ xImage->bitmap_bit_order = BitmapBitOrder (display);
++ xImage->bitmap_pad = 32;
++ xImage->depth = pixelStride * 8;
++ xImage->bytes_per_line = lineStride;
++ xImage->bits_per_pixel = pixelStride * 8;
++ xImage->red_mask = 0x00FF0000;
++ xImage->green_mask = 0x0000FF00;
++ xImage->blue_mask = 0x000000FF;
++
++ if (! XInitImage (xImage))
++ {
++ jassertfalse
++ }
++ }
++
++ ~XBitmapImage()
++ {
++ juce_free (xImage->data);
++ xImage->data = 0;
++ XDestroyImage (xImage);
++ imageData = 0; // to stop the base class freeing this
++ }
++
++ void blitToWindow (Window window, int dx, int dy, int dw, int dh, int sx, int sy)
++ {
++ static GC gc = 0;
++
++ if (gc == 0)
++ gc = DefaultGC (display, DefaultScreen (display));
++
++ // blit results to screen.
++ XPutImage (display, (Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh);
++ }
++
++ //==============================================================================
++ juce_UseDebuggingNewOperator
++
++private:
++ XImage* xImage;
++};
++
++
++//==============================================================================
++class LinuxComponentPeer : public ComponentPeer
++{
++public:
++ //==============================================================================
++ LinuxComponentPeer (Component* const component, const int windowStyleFlags)
++ : ComponentPeer (component, windowStyleFlags),
++ windowH (0),
++ wx (0),
++ wy (0),
++ ww (0),
++ wh (0),
++ fullScreen (false),
++ entered (false),
++ mapped (false)
++ {
++ repainter = new LinuxRepaintManager (this, component, 3000);
++
++ MessageManager::getInstance()
++ ->callFunctionOnMessageThread (&createWindowCallback, (void*) this);
++
++ setTitle (component->getName());
++ }
++
++ ~LinuxComponentPeer()
++ {
++ MessageManager::getInstance()
++ ->callFunctionOnMessageThread (&destroyWindowCallback, (void*) windowH);
++
++ windowH = 0;
++ delete repainter;
++ }
++
++ //==============================================================================
++ void* getNativeHandle() const
++ {
++ return (void*) windowH;
++ }
++
++ void setVisible (bool shouldBeVisible)
++ {
++ if (shouldBeVisible)
++ XMapWindow (display, windowH);
++ else
++ XUnmapWindow (display, windowH);
++ }
++
++ void setTitle (const String& title)
++ {
++ setWindowTitle (windowH, title);
++ }
++
++ void setPosition (int x, int y)
++ {
++ setBounds (x, y, ww, wh, false);
++ }
++
++ void setSize (int w, int h)
++ {
++ setBounds (wx, wy, w, h, false);
++ }
++
++ void setBounds (int x, int y, int w, int h, const bool isNowFullScreen)
++ {
++ fullScreen = isNowFullScreen;
++
++ if (windowH != 0)
++ {
++ const ComponentDeletionWatcher deletionChecker (component);
++
++ wx = x;
++ wy = y;
++ ww = jmax (1, w);
++ wh = jmax (1, h);
++
++ if (! mapped)
++ {
++ // Make sure the Window manager does what we want
++ XSizeHints* hints = XAllocSizeHints();
++ hints->flags = USSize | USPosition;
++ hints->width = ww + windowBorder.getLeftAndRight();
++ hints->height = wh + windowBorder.getTopAndBottom();
++ hints->x = wx - windowBorder.getLeft();
++ hints->y = wy - windowBorder.getTop();
++ XSetWMNormalHints (display, windowH, hints);
++ XFree (hints);
++ }
++
++ XMoveResizeWindow (display, windowH,
++ wx - windowBorder.getLeft(),
++ wy - windowBorder.getTop(),
++ ww + windowBorder.getLeftAndRight(),
++ wh + windowBorder.getTopAndBottom());
++
++ if (! deletionChecker.hasBeenDeleted())
++ {
++ updateBorderSize();
++ handleMovedOrResized();
++ }
++ }
++ }
++
++ void getBounds (int& x, int& y, int& w, int& h) const
++ {
++ x = wx;
++ y = wy;
++ w = ww;
++ h = wh;
++ }
++
++ int getScreenX() const
++ {
++ return wx;
++ }
++
++ int getScreenY() const
++ {
++ return wy;
++ }
++
++ void setMinimised (bool shouldBeMinimised)
++ {
++ if (shouldBeMinimised)
++ {
++ Window root = RootWindow (display, DefaultScreen (display));
++
++ XClientMessageEvent clientMsg;
++ clientMsg.display = display;
++ clientMsg.window = windowH;
++ clientMsg.type = ClientMessage;
++ clientMsg.format = 32;
++ clientMsg.message_type = wm_ChangeState;
++ clientMsg.data.l[0] = IconicState;
++
++ XSendEvent (display, root, false,
++ SubstructureRedirectMask | SubstructureNotifyMask,
++ (XEvent*) &clientMsg);
++ }
++ else
++ {
++ setVisible (true);
++ }
++ }
++
++ bool isMinimised() const
++ {
++ bool minimised = false;
++
++ CARD32* stateProp;
++ unsigned long nitems, bytesLeft;
++ Atom actualType;
++ int actualFormat;
++
++ if (XGetWindowProperty (display, windowH, wm_State, 0, 64, False,
++ wm_State, &actualType, &actualFormat, &nitems, &bytesLeft,
++ (unsigned char**) &stateProp) == Success
++ && actualType == wm_State
++ && actualFormat == 32
++ && nitems > 0)
++ {
++ if (stateProp[0] == IconicState)
++ minimised = true;
++
++ XFree (stateProp);
++ }
++
++ return minimised;
++ }
++
++ void setFullScreen (bool shouldBeFullScreen)
++ {
++ setMinimised (false);
++
++ if (fullScreen != shouldBeFullScreen)
++ {
++ Rectangle r (lastNonFullscreenBounds);
++
++ if (shouldBeFullScreen)
++ r = Desktop::getInstance().getMainMonitorArea();
++
++ if (! r.isEmpty())
++ setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen);
++
++ getComponent()->repaint();
++ }
++ }
++
++ bool isFullScreen() const
++ {
++ return fullScreen;
++ }
++
++ bool isChildWindowOf (Window possibleParent) const
++ {
++ Window* windowList = 0;
++ uint32 windowListSize = 0;
++ Window parent, root;
++
++ if (XQueryTree (display, windowH, &root, &parent, &windowList, &windowListSize) != 0)
++ {
++ if (windowList != 0)
++ XFree (windowList);
++
++ return parent == possibleParent;
++ }
++
++ return false;
++ }
++
++ bool contains (int x, int y, bool trueIfInAChildWindow) const
++ {
++ jassert (x >= 0 && y >= 0 && x < ww && y < wh); // should only be called for points that are actually inside the bounds
++
++ x += wx;
++ y += wy;
++
++ // the XQueryTree stuff later on is VERY slow, so if this call's just to check the mouse pos, it's
++ // much more efficient to cheat..
++ if (x == lastMousePosX && y == lastMousePosY)
++ {
++ Window root, child;
++ int winx, winy;
++ unsigned int mask;
++
++ if (XQueryPointer (display,
++ RootWindow (display, DefaultScreen (display)),
++ &root, &child,
++ &x, &y, &winx, &winy, &mask) != False)
++ {
++ return child == windowH
++ || (((styleFlags & windowHasTitleBar) != 0) && isChildWindowOf (child));
++ }
++ }
++
++ bool result = false;
++
++ Window* windowList = 0;
++ uint32 windowListSize = 0;
++
++ Window parent, root = RootWindow (display, DefaultScreen (display));
++
++ if (XQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0)
++ {
++ for (int i = windowListSize; --i >= 0;)
++ {
++ XWindowAttributes atts;
++
++ if (windowList[i] == windowH
++ || (((styleFlags & windowHasTitleBar) != 0) && isChildWindowOf (windowList[i])))
++ {
++ result = true;
++
++ if (! trueIfInAChildWindow)
++ {
++ Window child;
++ int tempX, tempY;
++
++ result = XTranslateCoordinates (display, windowH, windowH,
++ x - wx - windowBorder.getLeft(),
++ y - wy - windowBorder.getTop(),
++ &tempX, &tempY,
++ &child)
++ && (child == None);
++ }
++
++ break;
++ }
++ else if (XGetWindowAttributes (display, windowList[i], &atts)
++ && atts.map_state == IsViewable
++ && x >= atts.x && y >= atts.y
++ && x < atts.x + atts.width
++ && y < atts.y + atts.height)
++ {
++ break;
++ }
++ }
++ }
++
++ if (windowList != 0)
++ XFree (windowList);
++
++ return result;
++ }
++
++ const BorderSize getFrameSize() const
++ {
++ return BorderSize();
++ }
++
++ bool setAlwaysOnTop (bool alwaysOnTop)
++ {
++ if (windowH != 0)
++ {
++ XSetWindowAttributes swa;
++ swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False;
++
++ XChangeWindowAttributes (display, windowH, CWOverrideRedirect, &swa);
++ }
++
++ return true;
++ }
++
++ void toFront (bool makeActive)
++ {
++ if (makeActive)
++ {
++ setVisible (true);
++ grabFocus();
++ }
++
++ XEvent ev;
++ ev.xclient.type = ClientMessage;
++ ev.xclient.serial = 0;
++ ev.xclient.send_event = True;
++ ev.xclient.message_type = wm_ActiveWin;
++ ev.xclient.window = windowH;
++ ev.xclient.format = 32;
++ ev.xclient.data.l[0] = 2;
++ ev.xclient.data.l[1] = CurrentTime;
++ ev.xclient.data.l[2] = 0;
++ ev.xclient.data.l[3] = 0;
++ ev.xclient.data.l[4] = 0;
++
++ XSendEvent (display, RootWindow (display, DefaultScreen (display)),
++ False,
++ SubstructureRedirectMask | SubstructureNotifyMask,
++ &ev);
++
++ XSync (display, False);
++ }
++
++ void toBehind (ComponentPeer* other)
++ {
++ LinuxComponentPeer* const otherPeer = dynamic_cast <LinuxComponentPeer*> (other);
++ jassert (otherPeer != 0); // wrong type of window?
++
++ if (otherPeer != 0)
++ {
++ setMinimised (false);
++
++ Window newStack[] = { otherPeer->windowH, windowH };
++
++ XRestackWindows (display, newStack, 2);
++ }
++ }
++
++ bool isFocused() const
++ {
++ int revert;
++ Window focus = 0;
++ XGetInputFocus (display, &focus, &revert);
++
++ if (focus == 0 || focus == None || focus == PointerRoot)
++ return 0;
++
++ ComponentPeer* focusedPeer = 0;
++ if (XFindContext (display, (XID) focus, improbableNumber, (XPointer*) &focusedPeer) != 0)
++ focusedPeer = 0;
++
++ return this == focusedPeer;
++ }
++
++ void grabFocus()
++ {
++ XWindowAttributes atts;
++
++ if (windowH != 0
++ && XGetWindowAttributes (display, windowH, &atts)
++ && atts.map_state == IsViewable)
++ {
++ XSetInputFocus (display, windowH, RevertToParent, CurrentTime);
++
++ if (! isActiveApplication)
++ {
++ isActiveApplication = true;
++ handleFocusGain();
++ }
++ }
++ }
++
++ void repaint (int x, int y, int w, int h)
++ {
++ repainter->invalidateCache (x, y, w, h);
++ repainter->repaint (x, y, w, h);
++ }
++
++ void performPendingRepaints()
++ {
++ repainter->performPendingRepaints();
++ }
++
++ //==============================================================================
++ void handleWindowMessage (XEvent* event)
++ {
++ switch (event->xany.type)
++ {
++ case 2: // 'KeyPress'
++ {
++ XKeyEvent* keyEvent = (XKeyEvent*) &event->xkey;
++ updateKeyStates (keyEvent->keycode, true);
++
++ int index = currentModifiers & ModifierKeys::shiftModifier ? 1 : 0;
++ KeySym sym = XKeycodeToKeysym (display, keyEvent->keycode, index);
++
++ const int oldMods = currentModifiers;
++ bool keyPressed = false;
++
++ const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false);
++
++ if ((sym & 0xff00) == 0xff00)
++ {
++ // Translate keypad
++ if (sym == XK_KP_Divide)
++ sym = XK_slash;
++ else if (sym == XK_KP_Multiply)
++ sym = XK_asterisk;
++ else if (sym == XK_KP_Subtract)
++ sym = XK_hyphen;
++ else if (sym == XK_KP_Add)
++ sym = XK_plus;
++ else if (sym == XK_KP_Enter)
++ sym = XK_Return;
++ else if (sym == XK_KP_Decimal)
++ sym = numLock ? XK_period : XK_Delete;
++ else if (sym == XK_KP_0)
++ sym = numLock ? XK_0 : XK_Insert;
++ else if (sym == XK_KP_1)
++ sym = numLock ? XK_1 : XK_End;
++ else if (sym == XK_KP_2)
++ sym = numLock ? XK_2 : XK_Down;
++ else if (sym == XK_KP_3)
++ sym = numLock ? XK_3 : XK_Page_Down;
++ else if (sym == XK_KP_4)
++ sym = numLock ? XK_4 : XK_Left;
++ else if (sym == XK_KP_5)
++ sym = XK_5;
++ else if (sym == XK_KP_6)
++ sym = numLock ? XK_6 : XK_Right;
++ else if (sym == XK_KP_7)
++ sym = numLock ? XK_7 : XK_Home;
++ else if (sym == XK_KP_8)
++ sym = numLock ? XK_8 : XK_Up;
++ else if (sym == XK_KP_9)
++ sym = numLock ? XK_9 : XK_Page_Up;
++
++ switch (sym)
++ {
++ case XK_Left:
++ case XK_Right:
++ case XK_Up:
++ case XK_Down:
++ case XK_Page_Up:
++ case XK_Page_Down:
++ case XK_End:
++ case XK_Home:
++ case XK_Delete:
++ case XK_Insert:
++ keyPressed = true;
++ sym = (sym & 0xff) | nonAsciiModifier;
++ break;
++ case XK_Tab:
++ case XK_Return:
++ case XK_Escape:
++ case XK_BackSpace:
++ keyPressed = true;
++ sym &= 0xff;
++ break;
++ default:
++ {
++ if (sym >= XK_F1 && sym <= XK_F12)
++ {
++ keyPressed = true;
++ sym = (sym & 0xff) | nonAsciiModifier;
++ }
++ break;
++ }
++ }
++ }
++
++ if ((sym & 0xff00) == 0 && sym >= 8)
++ keyPressed = true;
++
++ if (capsLock && ((sym >= XK_A && sym <= XK_Z) || (sym >= XK_a && sym <= XK_z)))
++ {
++ index ^= 1;
++ sym = XKeycodeToKeysym (display, keyEvent->keycode, index);
++ }
++
++ if (oldMods != currentModifiers)
++ handleModifierKeysChange();
++
++ if (keyDownChange)
++ handleKeyUpOrDown();
++
++ if (keyPressed)
++ handleKeyPress (sym);
++
++ break;
++ }
++
++ case KeyRelease:
++ {
++ XKeyEvent* keyEvent = (XKeyEvent*) &event->xkey;
++ updateKeyStates (keyEvent->keycode, false);
++
++ KeySym sym = XKeycodeToKeysym (display, keyEvent->keycode, 0);
++
++ const int oldMods = currentModifiers;
++ const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false);
++
++ if (oldMods != currentModifiers)
++ handleModifierKeysChange();
++
++ if (keyDownChange)
++ handleKeyUpOrDown();
++
++ break;
++ }
++
++ case ButtonPress:
++ {
++ XButtonPressedEvent* buttonPressEvent = (XButtonPressedEvent*) &event->xbutton;
++
++ bool buttonMsg = false;
++ bool wheelUpMsg = false;
++ bool wheelDownMsg = false;
++
++ const int map = pointerMap [buttonPressEvent->button - Button1];
++
++ if (map == LeftButton)
++ {
++ currentModifiers |= ModifierKeys::leftButtonModifier;
++ buttonMsg = true;
++ }
++ else if (map == RightButton)
++ {
++ currentModifiers |= ModifierKeys::rightButtonModifier;
++ buttonMsg = true;
++ }
++ else if (map == MiddleButton)
++ {
++ currentModifiers |= ModifierKeys::middleButtonModifier;
++ buttonMsg = true;
++ }
++ else if (map == WheelUp)
++ {
++ wheelUpMsg = true;
++ }
++ else if (map == WheelDown)
++ {
++ wheelDownMsg = true;
++ }
++
++ updateKeyModifiers (buttonPressEvent->state);
++
++ if (buttonMsg)
++ {
++ toFront (true);
++ handleMouseDown (buttonPressEvent->x, buttonPressEvent->y,
++ getEventTime (buttonPressEvent->time));
++ }
++ else if (wheelUpMsg || wheelDownMsg)
++ {
++ handleMouseWheel (wheelDownMsg ? -84 : 84,
++ getEventTime (buttonPressEvent->time));
++ }
++
++ lastMousePosX = lastMousePosY = 0x100000;
++ break;
++ }
++
++ case ButtonRelease:
++ {
++ XButtonReleasedEvent* buttonRelEvent = (XButtonReleasedEvent*) &event->xbutton;
++
++ const int oldModifiers = currentModifiers;
++ const int map = pointerMap [buttonRelEvent->button - Button1];
++
++ if (map == LeftButton)
++ currentModifiers &= ~ModifierKeys::leftButtonModifier;
++ else if (map == RightButton)
++ currentModifiers &= ~ModifierKeys::rightButtonModifier;
++ else if (map == MiddleButton)
++ currentModifiers &= ~ModifierKeys::middleButtonModifier;
++
++ updateKeyModifiers (buttonRelEvent->state);
++
++ handleMouseUp (oldModifiers,
++ buttonRelEvent->x, buttonRelEvent->y,
++ getEventTime (buttonRelEvent->time));
++
++ lastMousePosX = lastMousePosY = 0x100000;
++ break;
++ }
++
++ case MotionNotify:
++ {
++ XPointerMovedEvent* movedEvent = (XPointerMovedEvent*) &event->xmotion;
++
++ updateKeyModifiers (movedEvent->state);
++
++ int x, y, mouseMods;
++ getMousePos (x, y, mouseMods);
++
++ if (lastMousePosX != x || lastMousePosY != y)
++ {
++ lastMousePosX = x;
++ lastMousePosY = y;
++
++ x -= getScreenX();
++ y -= getScreenY();
++
++ if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0)
++ handleMouseMove (x, y, getEventTime (movedEvent->time));
++ else
++ handleMouseDrag (x, y, getEventTime (movedEvent->time));
++ }
++
++ break;
++ }
++
++ case EnterNotify:
++ {
++ lastMousePosX = lastMousePosY = 0x100000;
++ XEnterWindowEvent* enterEvent = (XEnterWindowEvent*) &event->xcrossing;
++
++ if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0
++ && ! entered)
++ {
++ updateKeyModifiers (enterEvent->state);
++
++ handleMouseEnter (enterEvent->x, enterEvent->y, getEventTime (enterEvent->time));
++
++ entered = true;
++ }
++
++ break;
++ }
++
++ case LeaveNotify:
++ {
++ XLeaveWindowEvent* leaveEvent = (XLeaveWindowEvent*) &event->xcrossing;
++
++ // Suppress the normal leave if we've got a pointer grab, or if
++ // it's a bogus one caused by clicking a mouse button when running
++ // in a Window manager
++ if (((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0
++ && leaveEvent->mode == NotifyNormal)
++ || leaveEvent->mode == NotifyUngrab)
++ {
++ updateKeyModifiers (leaveEvent->state);
++
++ handleMouseExit (leaveEvent->x, leaveEvent->y, getEventTime (leaveEvent->time));
++
++ entered = false;
++ }
++
++ break;
++ }
++
++ case FocusIn:
++ {
++ isActiveApplication = true;
++ handleFocusGain();
++ break;
++ }
++
++ case FocusOut:
++ {
++ isActiveApplication = false;
++ handleFocusLoss();
++ break;
++ }
++
++ case Expose:
++ {
++ // Batch together all pending expose events
++ XExposeEvent* exposeEvent = (XExposeEvent*) &event->xexpose;
++ XEvent nextEvent;
++
++ repaint (exposeEvent->x, exposeEvent->y,
++ exposeEvent->width, exposeEvent->height);
++
++ while (XEventsQueued (display, QueuedAfterFlush) > 0)
++ {
++ XPeekEvent (display, (XEvent*) &nextEvent);
++ if (nextEvent.type != Expose || nextEvent.xany.window != event->xany.window)
++ break;
++
++ XNextEvent (display, (XEvent*)&nextEvent);
++ XExposeEvent* nextExposeEvent = (XExposeEvent*)(&nextEvent.xexpose);
++ repaint (nextExposeEvent->x, nextExposeEvent->y,
++ nextExposeEvent->width, nextExposeEvent->height);
++ }
++
++ break;
++ }
++
++ case CreateNotify:
++ case DestroyNotify:
++ // Think we can ignore these
++ break;
++
++ case CirculateNotify:
++ break;
++
++ case ConfigureNotify:
++ case ReparentNotify:
++ case GravityNotify:
++ updateBounds();
++ break;
++
++ case MapNotify:
++ mapped = true;
++ handleBroughtToFront();
++ break;
++
++ case UnmapNotify:
++ mapped = false;
++ break;
++
++ case MappingNotify:
++ {
++ XMappingEvent* mappingEvent = (XMappingEvent*) &event->xmapping;
++
++ if (mappingEvent->request != MappingPointer)
++ {
++ // Deal with modifier/keyboard mapping
++ XRefreshKeyboardMapping (mappingEvent);
++ getModifierMapping();
++ }
++
++ break;
++ }
++
++ case ClientMessage:
++ {
++ XClientMessageEvent* clientMsg = (XClientMessageEvent*) &event->xclient;
++
++ if (clientMsg->message_type == wm_Protocols && clientMsg->format == 32)
++ {
++ const Atom atom = (Atom) clientMsg->data.l[0];
++
++ if (atom == wm_ProtocolList [TAKE_FOCUS])
++ {
++ XWindowAttributes atts;
++
++ if (clientMsg->window != 0
++ && XGetWindowAttributes (display, clientMsg->window, &atts))
++ {
++ if (atts.map_state == IsViewable)
++ XSetInputFocus (display, clientMsg->window, RevertToParent, clientMsg->data.l[1]);
++ }
++ }
++ else if (atom == wm_ProtocolList [DELETE_WINDOW])
++ {
++ handleUserClosingWindow();
++ }
++ }
++ else if (clientMsg->message_type == repaintId)
++ {
++ // Get rid of all pending repaint events
++ XEvent nextEvent;
++
++ while (XEventsQueued (display, QueuedAfterFlush) > 0)
++ {
++ XPeekEvent (display, &nextEvent);
++ if (nextEvent.xany.type != ClientMessage ||
++ nextEvent.xany.window != event->xany.window)
++ break;
++
++ XClientMessageEvent* nextClientMsg = (XClientMessageEvent*) (&nextEvent.xclient);
++ if (nextClientMsg->message_type != repaintId)
++ break;
++
++ XNextEvent (display, &nextEvent);
++ }
++
++ static bool reentrancyCheck = false;
++ if (! reentrancyCheck)
++ {
++ reentrancyCheck = true;
++
++ int ox, oy, ow, oh;
++ getBounds (ox, oy, ow, oh);
++ repaint (0, 0, ow, oh);
++ performPendingRepaints();
++
++ reentrancyCheck = false;
++ }
++ }
++
++ break;
++ }
++
++ case SelectionClear:
++ case SelectionNotify:
++ case SelectionRequest:
++ // We shouldn't get these on normal windows
++ break;
++
++ default:
++ break;
++ }
++ }
++
++ void showMouseCursor (Cursor cursor)
++ {
++ XDefineCursor (display, windowH, cursor);
++ }
++
++ //==============================================================================
++ juce_UseDebuggingNewOperator
++
++ bool dontRepaint;
++
++private:
++ //==============================================================================
++ class LinuxRepaintManager : public RepaintManager
++ {
++ public:
++ LinuxRepaintManager (LinuxComponentPeer* const peer_,
++ Component* const component,
++ const int timeBeforeReleasingImage)
++ : RepaintManager (component, timeBeforeReleasingImage),
++ peer (peer_)
++ {
++ }
++
++ Image* createNewImage (int w, int h)
++ {
++ return new XBitmapImage (Image::RGB, w, h, false);
++ }
++
++ void repaintNow (const RectangleList& areasToPaint)
++ {
++ peer->clearMaskedRegion();
++
++ renderCacheAreasNeedingRepaint();
++
++ int x, y;
++ XBitmapImage* const paintingBuffer = (XBitmapImage*) getImage (x, y);
++
++ if (paintingBuffer != 0)
++ {
++ const RectangleList* repaintRegion = &areasToPaint;
++ RectangleList temp;
++
++ if (! peer->maskedRegion.isEmpty())
++ {
++ temp = areasToPaint;
++ temp.subtract (peer->maskedRegion);
++ repaintRegion = &temp;
++ }
++
++ for (RectangleList::Iterator i (*repaintRegion); i.next();)
++ {
++ const Rectangle& r = i.getRectangle();
++
++ paintingBuffer->blitToWindow (peer->windowH,
++ r.getX(), r.getY(), r.getWidth(), r.getHeight(),
++ r.getX() - x, r.getY() - y);
++ }
++ }
++ }
++
++ private:
++ LinuxComponentPeer* const peer;
++
++ LinuxRepaintManager (const LinuxRepaintManager&);
++ const LinuxRepaintManager& operator= (const LinuxRepaintManager&);
++ };
++
++ LinuxRepaintManager* repainter;
++
++ friend class LinuxRepaintManager;
++ Window windowH;
++ int wx, wy, ww, wh;
++ bool fullScreen, entered, mapped;
++ BorderSize windowBorder;
++
++ //==============================================================================
++ void removeWindowDecorations (Window wndH)
++ {
++ Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True);
++
++ if (hints != None)
++ {
++ typedef struct
++ {
++ CARD32 flags;
++ CARD32 functions;
++ CARD32 decorations;
++ INT32 input_mode;
++ CARD32 status;
++ } MotifWmHints;
++
++ MotifWmHints motifHints;
++ motifHints.flags = 2; /* MWM_HINTS_DECORATIONS */
++ motifHints.decorations = 0;
++
++ XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,
++ (unsigned char*) &motifHints, 4);
++ }
++
++ hints = XInternAtom (display, "_WIN_HINTS", True);
++
++ if (hints != None)
++ {
++ long gnomeHints = 0;
++
++ XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,
++ (unsigned char*) &gnomeHints, 1);
++ }
++
++ hints = XInternAtom (display, "KWM_WIN_DECORATION", True);
++
++ if (hints != None)
++ {
++ long kwmHints = 2; /*KDE_tinyDecoration*/
++
++ XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,
++ (unsigned char*) &kwmHints, 1);
++ }
++
++ hints = XInternAtom (display, "_NET_WM_WINDOW_TYPE", True);
++
++ if (hints != None)
++ {
++ Atom netHints [2];
++ netHints[0] = XInternAtom (display, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", True);
++
++ if ((styleFlags & windowIsTemporary) != 0)
++ netHints[1] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_MENU", True);
++ else
++ netHints[1] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_NORMAL", True);
++
++ XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace,
++ (unsigned char*) &netHints, 2);
++ }
++ }
++
++ void addWindowButtons (Window wndH)
++ {
++ Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True);
++
++ if (hints != None)
++ {
++ typedef struct
++ {
++ CARD32 flags;
++ CARD32 functions;
++ CARD32 decorations;
++ INT32 input_mode;
++ CARD32 status;
++ } MotifWmHints;
++
++ MotifWmHints motifHints;
++
++ motifHints.flags = 1 | 2; /* MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS */
++ motifHints.decorations = 2 /* MWM_DECOR_BORDER */ | 8 /* MWM_DECOR_TITLE */ | 16; /* MWM_DECOR_MENU */
++
++ motifHints.functions = 4 /* MWM_FUNC_MOVE */;
++
++ if ((styleFlags & windowHasCloseButton) != 0)
++ motifHints.functions |= 32; /* MWM_FUNC_CLOSE */
++
++ if ((styleFlags & windowHasMinimiseButton) != 0)
++ {
++ motifHints.functions |= 8; /* MWM_FUNC_MINIMIZE */
++ motifHints.decorations |= 0x20; /* MWM_DECOR_MINIMIZE */
++ }
++
++ if ((styleFlags & windowHasMaximiseButton) != 0)
++ {
++ motifHints.functions |= 0x10; /* MWM_FUNC_MAXIMIZE */
++ motifHints.decorations |= 0x40; /* MWM_DECOR_MAXIMIZE */
++ }
++
++ if ((styleFlags & windowIsResizable) != 0)
++ {
++ motifHints.functions |= 2; /* MWM_FUNC_RESIZE */
++ motifHints.decorations |= 0x4; /* MWM_DECOR_RESIZEH */
++ }
++
++ XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace,
++ (unsigned char*) &motifHints, 4);
++ }
++
++ hints = XInternAtom (display, "_NET_WM_ALLOWED_ACTIONS", True);
++
++ if (hints != None)
++ {
++ Atom netHints [6];
++ int num = 0;
++
++ netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_RESIZE", (styleFlags & windowIsResizable) ? True : False);
++ netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_FULLSCREEN", (styleFlags & windowHasMaximiseButton) ? True : False);
++ netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_MINIMIZE", (styleFlags & windowHasMinimiseButton) ? True : False);
++ netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_CLOSE", (styleFlags & windowHasCloseButton) ? True : False);
++
++ XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace,
++ (unsigned char*) &netHints, num);
++ }
++ }
++
++ static void* createWindowCallback (void* userData)
++ {
++ ((LinuxComponentPeer*) userData)->createWindow();
++ return 0;
++ }
++
++ void createWindow()
++ {
++ static bool atomsInitialised = false;
++
++ if (! atomsInitialised)
++ {
++ atomsInitialised = true;
++
++ wm_Protocols = XInternAtom (display, "WM_PROTOCOLS", 1);
++ wm_ProtocolList [TAKE_FOCUS] = XInternAtom (display, "WM_TAKE_FOCUS", 1);
++ wm_ProtocolList [DELETE_WINDOW] = XInternAtom (display, "WM_DELETE_WINDOW", 1);
++ wm_ChangeState = XInternAtom (display, "WM_CHANGE_STATE", 1);
++ wm_State = XInternAtom (display, "WM_STATE", 1);
++ wm_ActiveWin = XInternAtom (display, "_NET_ACTIVE_WINDOW", False);
++ repaintId = XInternAtom (display, "JUCERepaintAtom", 1);
++ }
++
++ // Get defaults for various properties
++ 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;
++
++ int numVisuals;
++ XVisualInfo* visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask,
++ &desiredVisual, &numVisuals);
++
++ if (numVisuals < 1 || visuals == 0)
++ {
++ Logger::outputDebugString ("ERROR: System doesn't support 24-bit RGB display.\n");
++ Process::terminate();
++ }
++
++ // Just choose the first one
++ Visual* visual = visuals[0].visual;
++ const int depth = visuals[0].depth;
++ XFree (visuals);
++
++ // Set up the window attributes
++ XSetWindowAttributes swa;
++ swa.border_pixel = 0;
++ swa.colormap = DefaultColormap (display, screen);
++ swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False;
++ swa.event_mask = eventMask;
++
++ Window wndH = XCreateWindow (display, root,
++ 0, 0, 1, 1, 0,
++ depth, InputOutput, visual,
++ CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
++ &swa);
++
++ XGrabButton (display, AnyButton, AnyModifier, wndH, False,
++ ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
++ GrabModeAsync, GrabModeAsync, None, None);
++
++ // Set the window context to identify the window handle object
++ if (XSaveContext (display, (XID) wndH, improbableNumber, (XPointer) this))
++ {
++ // Failed
++ jassertfalse
++ Logger::outputDebugString ("Failed to create context information for window.\n");
++ XDestroyWindow (display, wndH);
++ wndH = 0;
++ }
++
++ // Set window manager hints
++ XWMHints* wmHints = XAllocWMHints();
++ wmHints->flags = InputHint | StateHint;
++ wmHints->input = True; // Locally active input model
++ wmHints->initial_state = NormalState;
++ XSetWMHints (display, wndH, wmHints);
++ XFree (wmHints);
++
++ if ((styleFlags & juce_windowIsSemiTransparentFlag) != 0)
++ {
++ //xxx
++ jassertfalse
++ }
++
++ if ((styleFlags & windowAppearsOnTaskbar) != 0)
++ {
++ //xxx
++ }
++
++ if ((styleFlags & windowHasTitleBar) == 0)
++ removeWindowDecorations (wndH);
++ else
++ addWindowButtons (wndH);
++
++ XSetTransientForHint (display, wndH, RootWindow (display, DefaultScreen (display)));
++
++ // Set window manager protocols
++ XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace,
++ (unsigned char*) wm_ProtocolList, 2);
++
++ // Set window name
++ setWindowTitle (wndH, getComponent()->getName());
++
++ // Initialise the pointer and keyboard mapping
++ // This is not the same as the logical pointer mapping the X server uses:
++ // we don't mess with this.
++ static bool mappingInitialised = false;
++
++ if (! mappingInitialised)
++ {
++ mappingInitialised = true;
++
++ const int numButtons = XGetPointerMapping (display, 0, 0);
++
++ if (numButtons == 2)
++ {
++ pointerMap[0] = LeftButton;
++ pointerMap[1] = RightButton;
++ pointerMap[2] = pointerMap[3] = pointerMap[4] = NoButton;
++ }
++ else if (numButtons >= 3)
++ {
++ pointerMap[0] = LeftButton;
++ pointerMap[1] = MiddleButton;
++ pointerMap[2] = RightButton;
++
++ if (numButtons >= 5)
++ {
++ pointerMap[3] = WheelUp;
++ pointerMap[4] = WheelDown;
++ }
++ }
++
++ getModifierMapping();
++ }
++
++ windowH = wndH;
++ }
++
++ static void* destroyWindowCallback (void* userData)
++ {
++ Window windowH = (Window) userData;
++
++ XPointer handlePointer;
++ if (! XFindContext (display, (XID) windowH, improbableNumber, &handlePointer))
++ XDeleteContext (display, (XID) windowH, improbableNumber);
++
++ XDestroyWindow (display, windowH);
++
++ // Wait for it to complete and then remove any events for this
++ // window from the event queue.
++ XSync (display, false);
++
++ XEvent event;
++ while (XCheckWindowEvent (display, windowH, eventMask, &event) == True)
++ {}
++
++ return 0;
++ }
++
++ static int64 getEventTime (::Time t)
++ {
++ static int64 eventTimeOffset = 0x12345678;
++ const int64 thisMessageTime = t;
++
++ if (eventTimeOffset == 0x12345678)
++ eventTimeOffset = Time::currentTimeMillis() - thisMessageTime;
++
++ return eventTimeOffset + thisMessageTime;
++ }
++
++ static void setWindowTitle (Window xwin, const char* const title)
++ {
++ XTextProperty nameProperty;
++ char* strings[] = { (char*) title };
++
++ if (XStringListToTextProperty (strings, 1, &nameProperty))
++ {
++ XSetWMName (display, xwin, &nameProperty);
++ XSetWMIconName (display, xwin, &nameProperty);
++ }
++ }
++
++ void updateBorderSize()
++ {
++ if ((styleFlags & windowHasTitleBar) == 0)
++ {
++ windowBorder = BorderSize (0);
++ }
++ else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0)
++ {
++ Atom hints = XInternAtom (display, "_NET_FRAME_EXTENTS", True);
++
++ if (hints != None)
++ {
++ CARD32* sizes = 0;
++ unsigned long nitems, bytesLeft;
++ Atom actualType;
++ int actualFormat;
++
++ if (XGetWindowProperty (display, windowH, hints, 0, 4, False,
++ XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft,
++ (unsigned char**) &sizes) == Success)
++ {
++ if (actualFormat == 32)
++ windowBorder = BorderSize ((int) sizes[2], (int) sizes[0],
++ (int) sizes[3], (int) sizes[1]);
++
++ XFree (sizes);
++ }
++ }
++ }
++ }
++
++ void updateBounds()
++ {
++ jassert (windowH != 0);
++ if (windowH != 0)
++ {
++ Window root, child;
++ unsigned int bw, depth;
++
++ if (! XGetGeometry (display, (Drawable) windowH, &root,
++ &wx, &wy, (unsigned int*) &ww, (unsigned int*) &wh,
++ &bw, &depth))
++ {
++ wx = wy = ww = wh = 0;
++ }
++ else if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child))
++ {
++ wx = wy = 0;
++ }
++
++ updateBorderSize();
++ handleMovedOrResized();
++ }
++ }
++};
++
++//==============================================================================
++ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/)
++{
++ return new LinuxComponentPeer (this, styleFlags);
++}
++
++
++//==============================================================================
++// (this callback is hooked up in the messaging code)
++void juce_windowMessageReceive (XEvent* event)
++{
++ if (event->xany.window != None)
++ {
++ // Check if the event is for one of our windows
++ LinuxComponentPeer* peer = 0;
++
++ if (! XFindContext (display, (XID) event->xany.window, improbableNumber, (XPointer*) &peer))
++ {
++ if (peer != 0 && peer->isValidMessageListener())
++ peer->handleWindowMessage (event);
++ }
++ }
++ else
++ {
++ switch (event->xany.type)
++ {
++ case KeymapNotify:
++ {
++ const XKeymapEvent* const keymapEvent = (const XKeymapEvent*) &event->xkeymap;
++ memcpy (keyStates, keymapEvent->key_vector, 32);
++ break;
++ }
++
++ default:
++ break;
++ }
++ }
++}
++
++//==============================================================================
++void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool clipToWorkArea)
++{
++#if JUCE_USE_XINERAMA
++ int major_opcode, first_event, first_error;
++
++ if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)
++ && XineramaIsActive (display))
++ {
++ int numMonitors = 0;
++ XineramaScreenInfo* const screens = XineramaQueryScreens (display, &numMonitors);
++
++ if (screens != 0)
++ {
++ for (int i = numMonitors; --i >= 0;)
++ {
++ int index = screens[i].screen_number;
++
++ if (index >= 0)
++ {
++ while (monitorCoords.size() < index)
++ monitorCoords.add (Rectangle (0, 0, 0, 0));
++
++ monitorCoords.set (index, Rectangle (screens[i].x_org,
++ screens[i].y_org,
++ screens[i].width,
++ screens[i].height));
++ }
++ }
++
++ XFree (screens);
++ }
++ }
++
++ if (monitorCoords.size() == 0)
++#endif
++ {
++ monitorCoords.add (Rectangle (0, 0,
++ DisplayWidth (display, DefaultScreen (display)),
++ DisplayHeight (display, DefaultScreen (display))));
++ }
++}
++
++//==============================================================================
++bool Desktop::canUseSemiTransparentWindows()
++{
++ return false;
++}
++
++void Desktop::getMousePosition (int& x, int& y)
++{
++ int mouseMods;
++ getMousePos (x, y, mouseMods);
++}
++
++void Desktop::setMousePosition (int x, int y)
++{
++ Window root = RootWindow (display, DefaultScreen (display));
++ XWarpPointer (display, None, root, 0, 0, 0, 0, x, y);
++}
++
++
++//==============================================================================
++void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY)
++{
++ Window root = RootWindow (display, DefaultScreen (display));
++ const unsigned int imageW = image.getWidth();
++ const unsigned int imageH = image.getHeight();
++ unsigned int cursorW, cursorH;
++
++ if (! XQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH))
++ return 0;
++
++ Image im (Image::ARGB, cursorW, cursorH, true);
++ Graphics g (im);
++
++ if (imageW > cursorW || imageH > cursorH)
++ {
++ hotspotX = (hotspotX * cursorW) / imageW;
++ hotspotY = (hotspotY * cursorH) / imageH;
++
++ g.drawImageWithin (&image, 0, 0, imageW, imageH,
++ Justification::topLeft,
++ false, false);
++ }
++ else
++ {
++ g.drawImageAt (&image, 0, 0);
++ }
++
++ const int stride = (cursorW + 7) >> 3;
++ unsigned char* const maskPlane = (unsigned char*)juce_calloc (stride*cursorH);
++ unsigned char* const sourcePlane = (unsigned char*)juce_calloc (stride*cursorH);
++
++ bool msbfirst = (BitmapBitOrder (display) == MSBFirst);
++
++ for (int y = cursorH; --y >= 0;)
++ {
++ for (int x = cursorW; --x >= 0;)
++ {
++ const unsigned char mask = (unsigned char)(1 << (msbfirst ? (7 - (x & 7)) : (x & 7)));
++ const int offset = y * stride + (x >> 3);
++
++ const Colour c (im.getPixelAt (x, y));
++
++ if (c.getAlpha() >= 128)
++ maskPlane[offset] |= mask;
++
++ if (c.getBrightness() >= 0.5f)
++ sourcePlane[offset] |= mask;
++ }
++ }
++
++ Pixmap sourcePixmap = XCreatePixmapFromBitmapData (display, root, (char*)sourcePlane, cursorW, cursorH, 0xffff, 0, 1);
++ Pixmap maskPixmap = XCreatePixmapFromBitmapData (display, root, (char*)maskPlane, cursorW, cursorH, 0xffff, 0, 1);
++
++ juce_free (maskPlane);
++ juce_free (sourcePlane);
++
++ XColor white, black;
++ black.red = black.green = black.blue = 0;
++ white.red = white.green = white.blue = 0xffff;
++
++ void* result = (void*) XCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, hotspotX, hotspotY);
++
++ XFreePixmap (display, sourcePixmap);
++ XFreePixmap (display, maskPixmap);
++
++ return result;
++}
++
++void juce_deleteMouseCursor (void* cursorHandle, bool)
++{
++ if (cursorHandle != None)
++ XFreeCursor (display, (Cursor)cursorHandle);
++}
++
++void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type)
++{
++ unsigned int shape;
++
++ switch (type)
++ {
++ case MouseCursor::NoCursor:
++ {
++ void* invisibleCursor;
++
++ Image im (Image::ARGB, 16, 16, true);
++ invisibleCursor = juce_createMouseCursorFromImage (im, 0, 0);
++
++ return invisibleCursor;
++ }
++
++ case MouseCursor::NormalCursor:
++ return (void*) None; // Use parent cursor
++
++ case MouseCursor::DraggingHandCursor:
++ {
++ void* dragHandCursor;
++ static unsigned char dragHandData[] = {71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,
++ 0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0,
++ 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,
++ 132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217,
++ 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 };
++ const int dragHandDataSize = 99;
++
++ Image* im = ImageFileFormat::loadFrom ((const char*) dragHandData, dragHandDataSize);
++ dragHandCursor = juce_createMouseCursorFromImage (*im, 8, 7);
++ delete im;
++
++ return dragHandCursor;
++ }
++
++ case MouseCursor::CopyingCursor:
++ {
++ void* copyCursor;
++
++ static unsigned char copyCursorData[] = {71,73,70,56,57,97,21,0,21,0,145,0,0,0,0,0,255,255,255,0,
++ 128,128,255,255,255,33,249,4,1,0,0,3,0,44,0,0,0,0,21,0,
++ 21,0,0,2,72,4,134,169,171,16,199,98,11,79,90,71,161,93,56,111,
++ 78,133,218,215,137,31,82,154,100,200,86,91,202,142,12,108,212,87,235,174,
++ 15,54,214,126,237,226,37,96,59,141,16,37,18,201,142,157,230,204,51,112,
++ 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 };
++ const int copyCursorSize = 119;
++
++ Image* im = ImageFileFormat::loadFrom ((const char*)copyCursorData, copyCursorSize);
++ copyCursor = juce_createMouseCursorFromImage (*im, 1, 3);
++ delete im;
++
++ return copyCursor;
++ }
++
++ case MouseCursor::WaitCursor:
++ shape = XC_watch;
++ break;
++
++ case MouseCursor::IBeamCursor:
++ shape = XC_xterm;
++ break;
++
++ case MouseCursor::PointingHandCursor:
++ shape = XC_hand2;
++ break;
++
++ case MouseCursor::LeftRightResizeCursor:
++ shape = XC_sb_h_double_arrow;
++ break;
++
++ case MouseCursor::UpDownResizeCursor:
++ shape = XC_sb_v_double_arrow;
++ break;
++
++ case MouseCursor::UpDownLeftRightResizeCursor:
++ shape = XC_fleur;
++ break;
++
++ case MouseCursor::TopEdgeResizeCursor:
++ shape = XC_top_side;
++ break;
++
++ case MouseCursor::BottomEdgeResizeCursor:
++ shape = XC_bottom_side;
++ break;
++
++ case MouseCursor::LeftEdgeResizeCursor:
++ shape = XC_left_side;
++ break;
++
++ case MouseCursor::RightEdgeResizeCursor:
++ shape = XC_right_side;
++ break;
++
++ case MouseCursor::TopLeftCornerResizeCursor:
++ shape = XC_top_left_corner;
++ break;
++
++ case MouseCursor::TopRightCornerResizeCursor:
++ shape = XC_top_right_corner;
++ break;
++
++ case MouseCursor::BottomLeftCornerResizeCursor:
++ shape = XC_bottom_left_corner;
++ break;
++
++ case MouseCursor::BottomRightCornerResizeCursor:
++ shape = XC_bottom_right_corner;
++ break;
++
++ case MouseCursor::CrosshairCursor:
++ shape = XC_crosshair;
++ break;
++
++ default:
++ return (void*) None; // Use parent cursor
++ }
++
++ return (void*) XCreateFontCursor (display, shape);
++}
++
++void MouseCursor::showInWindow (ComponentPeer* peer) const
++{
++ LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (peer);
++
++ if (lp != 0)
++ lp->showMouseCursor ((Cursor) getHandle());
++}
++
++void MouseCursor::showInAllWindows() const
++{
++ for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
++ showInWindow (ComponentPeer::getPeer (i));
++}
++
++//==============================================================================
++Image* juce_createIconForFile (const File& file)
++{
++ return 0;
++}
++
++
++//==============================================================================
++#if JUCE_OPENGL
++
++struct OpenGLContextInfo
++{
++ Window embeddedWindow;
++ GLXContext renderContext;
++};
++
++void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
++{
++ XSync (display, False);
++ jassert (component != 0);
++
++ if (component == 0)
++ return 0;
++
++ LinuxComponentPeer* const peer
++ = dynamic_cast <LinuxComponentPeer*> (component->getTopLevelComponent()->getPeer());
++
++ if (peer == 0)
++ return 0;
++
++ GLint attribList[] =
++ {
++ GLX_RGBA,
++ GLX_DOUBLEBUFFER,
++ GLX_RED_SIZE, 8,
++ GLX_GREEN_SIZE, 8,
++ GLX_BLUE_SIZE, 8,
++ GLX_ALPHA_SIZE, 8,
++ GLX_DEPTH_SIZE, 8,
++ None
++ };
++
++ XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribList);
++
++ if (bestVisual == 0)
++ return 0;
++
++ OpenGLContextInfo* const oc = new OpenGLContextInfo();
++
++ oc->renderContext = glXCreateContext (display, bestVisual,
++ (sharedContext != 0) ? ((OpenGLContextInfo*) sharedContext)->renderContext
++ : 0,
++ GL_TRUE);
++
++ Window windowH = (Window) peer->getNativeHandle();
++
++ Colormap colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone);
++ XSetWindowAttributes swa;
++ swa.colormap = colourMap;
++ swa.border_pixel = 0;
++ swa.event_mask = StructureNotifyMask;
++
++ oc->embeddedWindow = XCreateWindow (display, windowH,
++ 0, 0, 1, 1, 0,
++ bestVisual->depth,
++ InputOutput,
++ bestVisual->visual,
++ CWBorderPixel | CWColormap | CWEventMask,
++ &swa);
++
++ XMapWindow (display, oc->embeddedWindow);
++ XFreeColormap (display, colourMap);
++
++ XFree (bestVisual);
++ XSync (display, False);
++
++ return oc;
++}
++
++void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp)
++{
++ jassert (context != 0);
++ OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
++
++ XMoveResizeWindow (display, oc->embeddedWindow,
++ owner->getScreenX() - topComp->getScreenX(),
++ owner->getScreenY() - topComp->getScreenY(),
++ jmax (1, owner->getWidth()),
++ jmax (1, owner->getHeight()));
++}
++
++void juce_deleteOpenGLContext (void* context)
++{
++ OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
++
++ if (oc != 0)
++ {
++ glXDestroyContext (display, oc->renderContext);
++
++ XUnmapWindow (display, oc->embeddedWindow);
++ XDestroyWindow (display, oc->embeddedWindow);
++
++ delete oc;
++ }
++}
++
++bool juce_makeOpenGLContextCurrent (void* context)
++{
++ OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
++
++ if (oc != 0)
++ return glXMakeCurrent (display, oc->embeddedWindow, oc->renderContext)
++ && XSync (display, False);
++ else
++ return glXMakeCurrent (display, None, 0);
++}
++
++void juce_swapOpenGLBuffers (void* context)
++{
++ OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
++
++ if (oc != 0)
++ glXSwapBuffers (display, oc->embeddedWindow);
++}
++
++void juce_repaintOpenGLWindow (void* context)
++{
++}
++
++#endif
++
++
++//==============================================================================
++static void initClipboard (Window root, Atom* cutBuffers)
++{
++ static bool init = false;
++
++ if (! init)
++ {
++ init = true;
++
++ // Make sure all cut buffers exist before use
++ for (int i = 0; i < 8; i++)
++ {
++ XChangeProperty (display, root, cutBuffers[i],
++ XA_STRING, 8, PropModeAppend, NULL, 0);
++ }
++ }
++}
++
++// Clipboard implemented currently using cut buffers
++// rather than the more powerful selection method
++void SystemClipboard::copyTextToClipboard (const String& clipText)
++{
++ Window root = RootWindow (display, DefaultScreen (display));
++ Atom cutBuffers[8] = { XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3,
++ XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7 };
++
++ initClipboard (root, cutBuffers);
++
++ XRotateWindowProperties (display, root, cutBuffers, 8, 1);
++ XChangeProperty (display, root, cutBuffers[0],
++ XA_STRING, 8, PropModeReplace, (const unsigned char*)((const char*)clipText),
++ clipText.length());
++}
++
++const String SystemClipboard::getTextFromClipboard()
++{
++ char* clipData;
++ const int bufSize = 64; // in words
++ int actualFormat;
++ int byteOffset = 0;
++ unsigned long bytesLeft, nitems;
++ Atom actualType;
++ String returnData;
++
++ Window root = RootWindow (display, DefaultScreen (display));
++
++ Atom cutBuffers[8] = { XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3,
++ XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7 };
++
++ initClipboard (root, cutBuffers);
++
++ do
++ {
++ if (XGetWindowProperty (display, root, cutBuffers[0], byteOffset >> 2, bufSize,
++ False, XA_STRING, &actualType, &actualFormat, &nitems, &bytesLeft,
++ (unsigned char**) &clipData) != Success
++ || actualType != XA_STRING
++ || actualFormat != 8)
++ return String();
++
++ byteOffset += nitems;
++ returnData += String(clipData, nitems);
++ XFree (clipData);
++ }
++ while (bytesLeft);
++
++ return returnData;
++}
++
++//==============================================================================
++bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles)
++{
++ jassertfalse // not implemented!
++ return false;
++}
++
++bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
++{
++ jassertfalse // not implemented!
++ return false;
++}
++
++
++//==============================================================================
++void PlatformUtilities::beep()
++{
++ //xxx
++}
++
++
++//==============================================================================
++bool AlertWindow::showNativeDialogBox (const String& title,
++ const String& bodyText,
++ bool isOkCancel)
++{
++ // xxx this is supposed to pop up an alert!
++ Logger::outputDebugString (title + ": " + bodyText);
++ return true;
++}
++
++//==============================================================================
++const int KeyPress::spaceKey = XK_space & 0xff;
++const int KeyPress::returnKey = XK_Return & 0xff;
++const int KeyPress::escapeKey = XK_Escape & 0xff;
++const int KeyPress::backspaceKey = XK_BackSpace & 0xff;
++const int KeyPress::leftKey = (XK_Left & 0xff) | nonAsciiModifier;
++const int KeyPress::rightKey = (XK_Right & 0xff) | nonAsciiModifier;
++const int KeyPress::upKey = (XK_Up & 0xff) | nonAsciiModifier;
++const int KeyPress::downKey = (XK_Down & 0xff) | nonAsciiModifier;
++const int KeyPress::pageUpKey = (XK_Page_Up & 0xff) | nonAsciiModifier;
++const int KeyPress::pageDownKey = (XK_Page_Down & 0xff) | nonAsciiModifier;
++const int KeyPress::endKey = (XK_End & 0xff) | nonAsciiModifier;
++const int KeyPress::homeKey = (XK_Home & 0xff) | nonAsciiModifier;
++const int KeyPress::insertKey = (XK_Insert & 0xff) | nonAsciiModifier;
++const int KeyPress::deleteKey = (XK_Delete & 0xff) | nonAsciiModifier;
++const int KeyPress::tabKey = XK_Tab & 0xff;
++const int KeyPress::F1Key = (XK_F1 & 0xff) | nonAsciiModifier;
++const int KeyPress::F2Key = (XK_F2 & 0xff) | nonAsciiModifier;
++const int KeyPress::F3Key = (XK_F3 & 0xff) | nonAsciiModifier;
++const int KeyPress::F4Key = (XK_F4 & 0xff) | nonAsciiModifier;
++const int KeyPress::F5Key = (XK_F5 & 0xff) | nonAsciiModifier;
++const int KeyPress::F6Key = (XK_F6 & 0xff) | nonAsciiModifier;
++const int KeyPress::F7Key = (XK_F7 & 0xff) | nonAsciiModifier;
++const int KeyPress::F8Key = (XK_F8 & 0xff) | nonAsciiModifier;
++const int KeyPress::F9Key = (XK_F9 & 0xff) | nonAsciiModifier;
++const int KeyPress::F10Key = (XK_F10 & 0xff) | nonAsciiModifier;
++const int KeyPress::F11Key = (XK_F11 & 0xff) | nonAsciiModifier;
++const int KeyPress::F12Key = (XK_F12 & 0xff) | nonAsciiModifier;
++const int KeyPress::playKey = (0xffeeff00) | nonAsciiModifier;
++const int KeyPress::stopKey = (0xffeeff01) | nonAsciiModifier;
++const int KeyPress::fastForwardKey = (0xffeeff02) | nonAsciiModifier;
++const int KeyPress::rewindKey = (0xffeeff03) | nonAsciiModifier;
++
++
++END_JUCE_NAMESPACE
++
++#endif
--- /dev/null
+
+#
+# Patch managed by http://www.holgerschurig.de/patcher.html
+#
+
+--- juce/src/juce_core/basics/juce_Atomic.h~remove-x86isms.patch
++++ juce/src/juce_core/basics/juce_Atomic.h
+@@ -1,188 +1,200 @@
+-/*\r
+- ==============================================================================\r
+-\r
+- This file is part of the JUCE library - "Jules' Utility Class Extensions"\r
+- Copyright 2004-6 by Raw Material Software ltd.\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- JUCE can be redistributed and/or modified under the terms of the\r
+- GNU General Public License, as published by the Free Software Foundation;\r
+- either version 2 of the License, or (at your option) any later version.\r
+-\r
+- JUCE is distributed in the hope that it will be useful,\r
+- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+- GNU General Public License for more details.\r
+-\r
+- You should have received a copy of the GNU General Public License\r
+- along with JUCE; if not, visit www.gnu.org/licenses or write to the\r
+- Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+- Boston, MA 02111-1307 USA\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- If you'd like to release a closed-source product which uses JUCE, commercial\r
+- licenses are also available: visit www.rawmaterialsoftware.com/juce for\r
+- more information.\r
+-\r
+- ==============================================================================\r
+-*/\r
+-\r
+-#ifndef __JUCE_ATOMIC_JUCEHEADER__\r
+-#define __JUCE_ATOMIC_JUCEHEADER__\r
+-\r
+-// Atomic increment/decrement operations..\r
+-\r
+-//==============================================================================\r
+-#if JUCE_MAC && ! DOXYGEN\r
+- #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)\r
+- #include <libkern/OSAtomic.h>\r
+-\r
+- forcedinline void atomicIncrement (int& variable) throw()\r
+- {\r
+- OSAtomicIncrement32 ((int32_t*) &variable);\r
+- }\r
+-\r
+- forcedinline int atomicIncrementAndReturn (int& variable) throw()\r
+- {\r
+- return OSAtomicIncrement32 ((int32_t*) &variable);\r
+- }\r
+-\r
+- forcedinline void atomicDecrement (int& variable) throw()\r
+- {\r
+- OSAtomicDecrement32 ((int32_t*) &variable);\r
+- }\r
+-\r
+- forcedinline int atomicDecrementAndReturn (int& variable) throw()\r
+- {\r
+- return OSAtomicDecrement32 ((int32_t*) &variable);\r
+- }\r
+-\r
+- #else\r
+- forcedinline void atomicIncrement (int& variable) throw()\r
+- {\r
+- OTAtomicAdd32 (1, (SInt32*) &variable);\r
+- }\r
+-\r
+- forcedinline int atomicIncrementAndReturn (int& variable) throw()\r
+- {\r
+- return OTAtomicAdd32 (1, (SInt32*) &variable);\r
+- }\r
+-\r
+- forcedinline void atomicDecrement (int& variable) throw()\r
+- {\r
+- OTAtomicAdd32 (-1, (SInt32*) &variable);\r
+- }\r
+-\r
+- forcedinline int atomicDecrementAndReturn (int& variable) throw()\r
+- {\r
+- return OTAtomicAdd32 (-1, (SInt32*) &variable);\r
+- }\r
+- #endif\r
+-#else\r
+-#ifdef __GNUC__\r
+-\r
+- /** Increments an integer in a thread-safe way. */\r
+- forcedinline void atomicIncrement (int& variable) throw()\r
+- {\r
+- __asm__ __volatile (\r
+- "lock incl (%%ecx)"\r
+- :\r
+- : "c" (&variable));\r
+- }\r
+-\r
+- /** Increments an integer in a thread-safe way and returns the incremented value. */\r
+- forcedinline int atomicIncrementAndReturn (int& variable) throw()\r
+- {\r
+- int result;\r
+-\r
+- __asm__ __volatile (\r
+- "lock xaddl %%eax, (%%ebx) \n\\r
+- incl %%eax"\r
+- : "=a" (result)\r
+- : "b" (&variable), "a" (1)\r
+- : "cc", "memory");\r
+-\r
+- return result;\r
+- }\r
+-\r
+- /** Decrememts an integer in a thread-safe way. */\r
+- forcedinline void atomicDecrement (int& variable) throw()\r
+- {\r
+- __asm__ __volatile (\r
+- "lock decl (%%ecx)"\r
+- :\r
+- : "c" (&variable));\r
+- }\r
+-\r
+- /** Decrememts an integer in a thread-safe way and returns the incremented value. */\r
+- forcedinline int atomicDecrementAndReturn (int& variable) throw()\r
+- {\r
+- int result;\r
+-\r
+- __asm__ __volatile (\r
+- "lock xaddl %%eax, (%%ebx) \n\\r
+- decl %%eax"\r
+- : "=a" (result)\r
+- : "b" (&variable), "a" (-1)\r
+- : "cc", "memory");\r
+-\r
+- return result;\r
+- }\r
+-\r
+-#else\r
+-\r
+- /** Increments an integer in a thread-safe way. */\r
+- inline_assembly void __fastcall atomicIncrement (int& variable) throw()\r
+- {\r
+- __asm {\r
+- mov ecx, dword ptr [variable]\r
+- lock inc dword ptr [ecx]\r
+- }\r
+- }\r
+-\r
+- /** Increments an integer in a thread-safe way and returns the incremented value. */\r
+- inline_assembly int __fastcall atomicIncrementAndReturn (int& variable) throw()\r
+- {\r
+- int result;\r
+-\r
+- __asm {\r
+- mov ecx, dword ptr [variable]\r
+- mov eax, 1\r
+- lock xadd dword ptr [ecx], eax\r
+- inc eax\r
+- mov result, eax\r
+- }\r
+-\r
+- return result;\r
+- }\r
+-\r
+- /** Decrememts an integer in a thread-safe way. */\r
+- inline_assembly void __fastcall atomicDecrement (int& variable) throw()\r
+- {\r
+- __asm {\r
+- mov ecx, dword ptr [variable]\r
+- lock dec dword ptr [ecx]\r
+- }\r
+- }\r
+-\r
+- /** Decrememts an integer in a thread-safe way and returns the incremented value. */\r
+- inline_assembly int __fastcall atomicDecrementAndReturn (int& variable) throw()\r
+- {\r
+- int result;\r
+-\r
+- __asm {\r
+- mov ecx, dword ptr [variable]\r
+- mov eax, -1\r
+- lock xadd dword ptr [ecx], eax\r
+- dec eax\r
+- mov result, eax\r
+- }\r
+-\r
+- return result;\r
+- }\r
+-#endif\r
+-#endif\r
+-\r
+-#endif // __JUCE_ATOMIC_JUCEHEADER__\r
++/*
++ ==============================================================================
++
++ This file is part of the JUCE library - "Jules' Utility Class Extensions"
++ Copyright 2004-6 by Raw Material Software ltd.
++
++ ------------------------------------------------------------------------------
++
++ JUCE can be redistributed and/or modified under the terms of the
++ GNU General Public License, as published by the Free Software Foundation;
++ either version 2 of the License, or (at your option) any later version.
++
++ JUCE is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with JUCE; if not, visit www.gnu.org/licenses or write to the
++ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
++ Boston, MA 02111-1307 USA
++
++ ------------------------------------------------------------------------------
++
++ If you'd like to release a closed-source product which uses JUCE, commercial
++ licenses are also available: visit www.rawmaterialsoftware.com/juce for
++ more information.
++
++ ==============================================================================
++*/
++
++#ifndef __JUCE_ATOMIC_JUCEHEADER__
++#define __JUCE_ATOMIC_JUCEHEADER__
++
++// Atomic increment/decrement operations..
++
++//==============================================================================
++#if JUCE_MAC && ! DOXYGEN
++ #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
++ #include <libkern/OSAtomic.h>
++
++ forcedinline void atomicIncrement (int& variable) throw()
++ {
++ OSAtomicIncrement32 ((int32_t*) &variable);
++ }
++
++ forcedinline int atomicIncrementAndReturn (int& variable) throw()
++ {
++ return OSAtomicIncrement32 ((int32_t*) &variable);
++ }
++
++ forcedinline void atomicDecrement (int& variable) throw()
++ {
++ OSAtomicDecrement32 ((int32_t*) &variable);
++ }
++
++ forcedinline int atomicDecrementAndReturn (int& variable) throw()
++ {
++ return OSAtomicDecrement32 ((int32_t*) &variable);
++ }
++
++ #else
++ forcedinline void atomicIncrement (int& variable) throw()
++ {
++ OTAtomicAdd32 (1, (SInt32*) &variable);
++ }
++
++ forcedinline int atomicIncrementAndReturn (int& variable) throw()
++ {
++ return OTAtomicAdd32 (1, (SInt32*) &variable);
++ }
++
++ forcedinline void atomicDecrement (int& variable) throw()
++ {
++ OTAtomicAdd32 (-1, (SInt32*) &variable);
++ }
++
++ forcedinline int atomicDecrementAndReturn (int& variable) throw()
++ {
++ return OTAtomicAdd32 (-1, (SInt32*) &variable);
++ }
++ #endif
++#else
++#ifdef __GNUC__
++
++ /** Increments an integer in a thread-safe way. */
++ forcedinline void atomicIncrement (int& variable) throw()
++ {
++#ifndef __x86__
++ variable++;
++#else
++ __asm__ __volatile (
++ "lock incl (%%ecx)"
++ :
++ : "c" (&variable));
++#endif
++ }
++
++ /** Increments an integer in a thread-safe way and returns the incremented value. */
++ forcedinline int atomicIncrementAndReturn (int& variable) throw()
++ {
++ int result;
++#ifndef __x86__
++ result = ++variable;
++#else
++ __asm__ __volatile (
++ "lock xaddl %%eax, (%%ebx) \n\
++ incl %%eax"
++ : "=a" (result)
++ : "b" (&variable), "a" (1)
++ : "cc", "memory");
++#endif
++ return result;
++ }
++
++ /** Decrememts an integer in a thread-safe way. */
++ forcedinline void atomicDecrement (int& variable) throw()
++ {
++#ifndef __x86__
++ variable--;
++#else
++ __asm__ __volatile (
++ "lock decl (%%ecx)"
++ :
++ : "c" (&variable));
++#endif
++ }
++
++ /** Decrememts an integer in a thread-safe way and returns the incremented value. */
++ forcedinline int atomicDecrementAndReturn (int& variable) throw()
++ {
++ int result;
++#ifndef __x86__
++ result = --variable;
++#else
++ __asm__ __volatile (
++ "lock xaddl %%eax, (%%ebx) \n\
++ decl %%eax"
++ : "=a" (result)
++ : "b" (&variable), "a" (-1)
++ : "cc", "memory");
++#endif
++ return result;
++ }
++
++#else
++
++ /** Increments an integer in a thread-safe way. */
++ inline_assembly void __fastcall atomicIncrement (int& variable) throw()
++ {
++ __asm {
++ mov ecx, dword ptr [variable]
++ lock inc dword ptr [ecx]
++ }
++ }
++
++ /** Increments an integer in a thread-safe way and returns the incremented value. */
++ inline_assembly int __fastcall atomicIncrementAndReturn (int& variable) throw()
++ {
++ int result;
++
++ __asm {
++ mov ecx, dword ptr [variable]
++ mov eax, 1
++ lock xadd dword ptr [ecx], eax
++ inc eax
++ mov result, eax
++ }
++
++ return result;
++ }
++
++ /** Decrememts an integer in a thread-safe way. */
++ inline_assembly void __fastcall atomicDecrement (int& variable) throw()
++ {
++ __asm {
++ mov ecx, dword ptr [variable]
++ lock dec dword ptr [ecx]
++ }
++ }
++
++ /** Decrememts an integer in a thread-safe way and returns the incremented value. */
++ inline_assembly int __fastcall atomicDecrementAndReturn (int& variable) throw()
++ {
++ int result;
++
++ __asm {
++ mov ecx, dword ptr [variable]
++ mov eax, -1
++ lock xadd dword ptr [ecx], eax
++ dec eax
++ mov result, eax
++ }
++
++ return result;
++ }
++#endif
++#endif
++
++#endif // __JUCE_ATOMIC_JUCEHEADER__
+--- juce/src/juce_core/basics/juce_PlatformDefs.h~remove-x86isms.patch
++++ juce/src/juce_core/basics/juce_PlatformDefs.h
+@@ -1,326 +1,330 @@
+-/*\r
+- ==============================================================================\r
+-\r
+- This file is part of the JUCE library - "Jules' Utility Class Extensions"\r
+- Copyright 2004-6 by Raw Material Software ltd.\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- JUCE can be redistributed and/or modified under the terms of the\r
+- GNU General Public License, as published by the Free Software Foundation;\r
+- either version 2 of the License, or (at your option) any later version.\r
+-\r
+- JUCE is distributed in the hope that it will be useful,\r
+- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+- GNU General Public License for more details.\r
+-\r
+- You should have received a copy of the GNU General Public License\r
+- along with JUCE; if not, visit www.gnu.org/licenses or write to the\r
+- Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+- Boston, MA 02111-1307 USA\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- If you'd like to release a closed-source product which uses JUCE, commercial\r
+- licenses are also available: visit www.rawmaterialsoftware.com/juce for\r
+- more information.\r
+-\r
+- ==============================================================================\r
+-*/\r
+-\r
+-#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__\r
+-#define __JUCE_PLATFORMDEFS_JUCEHEADER__\r
+-\r
+-\r
+-//==============================================================================\r
+-// set up platform definitions..\r
+-#ifdef _WIN32\r
+- #define JUCE_WIN32 1\r
+- #define JUCE_WINDOWS 1\r
+-#else\r
+- #ifdef LINUX\r
+- #define JUCE_LINUX 1\r
+- #else\r
+- #define JUCE_MAC 1\r
+- #endif\r
+-#endif\r
+-\r
+-//==============================================================================\r
+-#ifdef JUCE_WINDOWS\r
+- #ifdef _MSC_VER\r
+- #ifdef _WIN64\r
+- #define JUCE_64BIT 1\r
+- #else\r
+- #define JUCE_32BIT 1\r
+- #endif\r
+- #endif\r
+-\r
+- #ifdef _DEBUG\r
+- #define JUCE_DEBUG 1\r
+- #endif\r
+-\r
+- /** If defined, this indicates that the processor is little-endian. */\r
+- #define JUCE_LITTLE_ENDIAN 1\r
+-\r
+- #define JUCE_INTEL 1\r
+-#endif\r
+-\r
+-//==============================================================================\r
+-#ifdef JUCE_MAC\r
+-\r
+- #include <CoreServices/CoreServices.h>\r
+- #include <wchar.h>\r
+-\r
+- #ifndef NDEBUG\r
+- #define JUCE_DEBUG 1\r
+- #endif\r
+-\r
+- #ifdef __LITTLE_ENDIAN__\r
+- #define JUCE_LITTLE_ENDIAN 1\r
+- #else\r
+- #define JUCE_BIG_ENDIAN 1\r
+- #endif\r
+-\r
+- #if defined (__ppc__) || defined (__ppc64__)\r
+- #define JUCE_PPC 1\r
+- #else\r
+- #define JUCE_INTEL 1\r
+- #endif\r
+-\r
+- #ifdef __LP64__\r
+- #define JUCE_64BIT 1\r
+- #else\r
+- #define JUCE_32BIT 1\r
+- #endif\r
+-#endif\r
+-\r
+-//==============================================================================\r
+-#ifdef JUCE_LINUX\r
+-\r
+- #ifdef _DEBUG\r
+- #define JUCE_DEBUG 1\r
+- #endif\r
+-\r
+- #include <wchar.h>\r
+-\r
+- // Allow override for big-endian Linux platforms\r
+- #ifndef JUCE_BIG_ENDIAN\r
+- #define JUCE_LITTLE_ENDIAN 1\r
+- #endif\r
+-\r
+- #if defined (__LP64__) || defined (_LP64)\r
+- #define JUCE_64BIT 1\r
+- #else\r
+- #define JUCE_32BIT 1\r
+- #endif\r
+-\r
+- #define JUCE_INTEL 1\r
+-#endif\r
+-\r
+-//==============================================================================\r
+-#if defined (__GNUC__) || defined (__MWERKS__)\r
+- /** A platform-independent 64-bit integer type. */\r
+- typedef long long int64;\r
+- /** A platform-independent 64-bit unsigned integer type. */\r
+- typedef unsigned long long uint64;\r
+- /** A platform-independent unicode character type. */\r
+- typedef wchar_t juce_wchar;\r
+-\r
+- /** A platform-independent way of forcing an inline function.\r
+-\r
+- Use the syntax: @code\r
+- forcedinline void myfunction (int x)\r
+- @endcode\r
+- */\r
+- #ifndef JUCE_DEBUG\r
+- #define forcedinline inline __attribute__((always_inline))\r
+- #else\r
+- #define forcedinline inline\r
+- #endif\r
+-\r
+- /** A platform-independent way of stopping the compiler inlining a function.\r
+-\r
+- Use the syntax: @code\r
+- juce_noinline void myfunction (int x)\r
+- @endcode\r
+- */\r
+- #define juce_noinline __attribute__((noinline))\r
+-\r
+-#else\r
+- //==============================================================================\r
+- /** A platform-independent 64-bit integer type. */\r
+- typedef __int64 int64;\r
+- /** A platform-independent 64-bit unsigned integer type. */\r
+- typedef unsigned __int64 uint64;\r
+-\r
+- /** A platform-independent unicode character type. */\r
+- typedef wchar_t juce_wchar;\r
+-\r
+- /** A platform-independent way of forcing an inline function.\r
+-\r
+- Use the syntax: @code\r
+- forcedinline void myfunction (int x)\r
+- @endcode\r
+- */\r
+- #ifdef _MSC_VER\r
+- #define forcedinline __forceinline\r
+- #else\r
+- #define forcedinline inline\r
+- #endif\r
+-\r
+- /** A platform-independent way of stopping the compiler inlining a function.\r
+-\r
+- Use the syntax: @code\r
+- juce_noinline void myfunction (int x)\r
+- @endcode\r
+- */\r
+- #define juce_noinline\r
+-\r
+-#endif\r
+-\r
+-#if JUCE_64BIT\r
+- typedef int64 pointer_sized_int;\r
+- typedef uint64 pointer_sized_uint;\r
+-#else\r
+- #if _MSC_VER >= 1300\r
+- typedef _W64 int pointer_sized_int;\r
+- typedef _W64 unsigned int pointer_sized_uint;\r
+- #else\r
+- typedef int pointer_sized_int;\r
+- typedef unsigned int pointer_sized_uint;\r
+- #endif\r
+-#endif\r
+-\r
+-\r
+-// borland can't handle inline functions containing asm code, so define a\r
+-// special type of inline modifier for this kind of function. Sigh..\r
+-#ifdef __BORLANDC__\r
+- #define inline_assembly\r
+-#else\r
+- #define inline_assembly forcedinline\r
+-#endif\r
+-\r
+-//==============================================================================\r
+-typedef signed char int8;\r
+-typedef unsigned char uint8;\r
+-typedef signed short int16;\r
+-typedef unsigned short uint16;\r
+-typedef signed int int32;\r
+-typedef unsigned int uint32;\r
+-\r
+-\r
+-//==============================================================================\r
+-// Debugging macros\r
+-//\r
+-\r
+-#ifdef JUCE_DEBUG\r
+- //==============================================================================\r
+- // If debugging is enabled..\r
+-\r
+- /** Writes a string to the standard error stream.\r
+-\r
+- This is only compiled in a debug build.\r
+-\r
+- @see Logger::outputDebugString\r
+- */\r
+- #define DBG(dbgtext) Logger::outputDebugString (dbgtext);\r
+-\r
+- /** Printf's a string to the standard error stream.\r
+-\r
+- This is only compiled in a debug build.\r
+-\r
+- @see Logger::outputDebugString\r
+- */\r
+- #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf;\r
+-\r
+- // Assertions..\r
+- #if defined (_MSC_VER) || DOXYGEN\r
+- /** This will always cause an assertion failure.\r
+-\r
+- This is only compiled in a debug build.\r
+-\r
+- @see jassert()\r
+- */\r
+- #ifdef __BORLANDC__\r
+- extern void juce_StopInDebugger();\r
+- #define jassertfalse { juce_StopInDebugger(); }\r
+- #else\r
+- #define jassertfalse { __asm int 3 }\r
+- #endif\r
+- #elif defined (JUCE_MAC)\r
+- #define jassertfalse { Debugger(); }\r
+- #elif defined (__GNUC__) || defined (JUCE_LINUX)\r
+- #define jassertfalse { asm("int $3"); }\r
+- #endif\r
+-\r
+- //==============================================================================\r
+- /** Platform-independent assertion macro.\r
+-\r
+- This gets optimised out when not being built with debugging turned on.\r
+-\r
+- Be careful not to call any functions within its arguments that are vital to\r
+- the behaviour of the program, because these won't get called in the release\r
+- build.\r
+-\r
+- @see jassertfalse\r
+- */\r
+- #define jassert(a) { if (! (a)) jassertfalse }\r
+-\r
+-#else\r
+- //==============================================================================\r
+- // If debugging is disabled, disable all the assertions and debugging stuff..\r
+-\r
+- #define DBG(dbgtext)\r
+- #define DBG_PRINTF(dbgprintf)\r
+-\r
+- #define jassert(a) {}\r
+- #define jassertfalse {}\r
+-\r
+-#endif\r
+-\r
+-//==============================================================================\r
+-#ifndef DOXYGEN\r
+- template <bool b> struct JuceStaticAssert;\r
+- template <> struct JuceStaticAssert <true> { static void dummy() {} };\r
+-#endif\r
+-\r
+-/** A compile-time assertion macro.\r
+-\r
+- If the expression parameter is false, the macro will cause a compile error.\r
+-*/\r
+-#define static_jassert(expression) JuceStaticAssert<expression>::dummy();\r
+-\r
+-\r
+-//==============================================================================\r
+-#if JUCE_CATCH_UNHANDLED_EXCEPTIONS\r
+-\r
+- #define JUCE_TRY try\r
+-\r
+- /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication\r
+- object so they can be logged by the application if it wants to.\r
+- */\r
+- #define JUCE_CATCH_EXCEPTION \\r
+- catch (const std::exception& e) \\r
+- { \\r
+- JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \\r
+- } \\r
+- catch (...) \\r
+- { \\r
+- JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \\r
+- }\r
+-\r
+- #define JUCE_CATCH_ALL catch (...) {}\r
+- #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse }\r
+-\r
+-#else\r
+-\r
+- #define JUCE_TRY\r
+- #define JUCE_CATCH_EXCEPTION\r
+- #define JUCE_CATCH_ALL\r
+- #define JUCE_CATCH_ALL_ASSERT\r
+-\r
+-#endif\r
+-\r
+-\r
+-#endif // __JUCE_PLATFORMDEFS_JUCEHEADER__\r
++/*
++ ==============================================================================
++
++ This file is part of the JUCE library - "Jules' Utility Class Extensions"
++ Copyright 2004-6 by Raw Material Software ltd.
++
++ ------------------------------------------------------------------------------
++
++ JUCE can be redistributed and/or modified under the terms of the
++ GNU General Public License, as published by the Free Software Foundation;
++ either version 2 of the License, or (at your option) any later version.
++
++ JUCE is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with JUCE; if not, visit www.gnu.org/licenses or write to the
++ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
++ Boston, MA 02111-1307 USA
++
++ ------------------------------------------------------------------------------
++
++ If you'd like to release a closed-source product which uses JUCE, commercial
++ licenses are also available: visit www.rawmaterialsoftware.com/juce for
++ more information.
++
++ ==============================================================================
++*/
++
++#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__
++#define __JUCE_PLATFORMDEFS_JUCEHEADER__
++
++
++//==============================================================================
++// set up platform definitions..
++#ifdef _WIN32
++ #define JUCE_WIN32 1
++ #define JUCE_WINDOWS 1
++#else
++ #ifdef LINUX
++ #define JUCE_LINUX 1
++ #else
++ #define JUCE_MAC 1
++ #endif
++#endif
++
++//==============================================================================
++#ifdef JUCE_WINDOWS
++ #ifdef _MSC_VER
++ #ifdef _WIN64
++ #define JUCE_64BIT 1
++ #else
++ #define JUCE_32BIT 1
++ #endif
++ #endif
++
++ #ifdef _DEBUG
++ #define JUCE_DEBUG 1
++ #endif
++
++ /** If defined, this indicates that the processor is little-endian. */
++ #define JUCE_LITTLE_ENDIAN 1
++
++ #define JUCE_INTEL 1
++#endif
++
++//==============================================================================
++#ifdef JUCE_MAC
++
++ #include <CoreServices/CoreServices.h>
++ #include <wchar.h>
++
++ #ifndef NDEBUG
++ #define JUCE_DEBUG 1
++ #endif
++
++ #ifdef __LITTLE_ENDIAN__
++ #define JUCE_LITTLE_ENDIAN 1
++ #else
++ #define JUCE_BIG_ENDIAN 1
++ #endif
++
++ #if defined (__ppc__) || defined (__ppc64__)
++ #define JUCE_PPC 1
++ #else
++ #define JUCE_INTEL 1
++ #endif
++
++ #ifdef __LP64__
++ #define JUCE_64BIT 1
++ #else
++ #define JUCE_32BIT 1
++ #endif
++#endif
++
++//==============================================================================
++#ifdef JUCE_LINUX
++
++ #ifdef _DEBUG
++ #define JUCE_DEBUG 1
++ #endif
++
++ #include <wchar.h>
++
++ // Allow override for big-endian Linux platforms
++ #ifndef JUCE_BIG_ENDIAN
++ #define JUCE_LITTLE_ENDIAN 1
++ #endif
++
++ #if defined (__LP64__) || defined (_LP64)
++ #define JUCE_64BIT 1
++ #else
++ #define JUCE_32BIT 1
++ #endif
++
++ #define JUCE_INTEL 1
++#endif
++
++//==============================================================================
++#if defined (__GNUC__) || defined (__MWERKS__)
++ /** A platform-independent 64-bit integer type. */
++ typedef long long int64;
++ /** A platform-independent 64-bit unsigned integer type. */
++ typedef unsigned long long uint64;
++ /** A platform-independent unicode character type. */
++ typedef wchar_t juce_wchar;
++
++ /** A platform-independent way of forcing an inline function.
++
++ Use the syntax: @code
++ forcedinline void myfunction (int x)
++ @endcode
++ */
++ #ifndef JUCE_DEBUG
++ #define forcedinline inline __attribute__((always_inline))
++ #else
++ #define forcedinline inline
++ #endif
++
++ /** A platform-independent way of stopping the compiler inlining a function.
++
++ Use the syntax: @code
++ juce_noinline void myfunction (int x)
++ @endcode
++ */
++ #define juce_noinline __attribute__((noinline))
++
++#else
++ //==============================================================================
++ /** A platform-independent 64-bit integer type. */
++ typedef __int64 int64;
++ /** A platform-independent 64-bit unsigned integer type. */
++ typedef unsigned __int64 uint64;
++
++ /** A platform-independent unicode character type. */
++ typedef wchar_t juce_wchar;
++
++ /** A platform-independent way of forcing an inline function.
++
++ Use the syntax: @code
++ forcedinline void myfunction (int x)
++ @endcode
++ */
++ #ifdef _MSC_VER
++ #define forcedinline __forceinline
++ #else
++ #define forcedinline inline
++ #endif
++
++ /** A platform-independent way of stopping the compiler inlining a function.
++
++ Use the syntax: @code
++ juce_noinline void myfunction (int x)
++ @endcode
++ */
++ #define juce_noinline
++
++#endif
++
++#if JUCE_64BIT
++ typedef int64 pointer_sized_int;
++ typedef uint64 pointer_sized_uint;
++#else
++ #if _MSC_VER >= 1300
++ typedef _W64 int pointer_sized_int;
++ typedef _W64 unsigned int pointer_sized_uint;
++ #else
++ typedef int pointer_sized_int;
++ typedef unsigned int pointer_sized_uint;
++ #endif
++#endif
++
++
++// borland can't handle inline functions containing asm code, so define a
++// special type of inline modifier for this kind of function. Sigh..
++#ifdef __BORLANDC__
++ #define inline_assembly
++#else
++ #define inline_assembly forcedinline
++#endif
++
++//==============================================================================
++typedef signed char int8;
++typedef unsigned char uint8;
++typedef signed short int16;
++typedef unsigned short uint16;
++typedef signed int int32;
++typedef unsigned int uint32;
++
++
++//==============================================================================
++// Debugging macros
++//
++
++#ifdef JUCE_DEBUG
++ //==============================================================================
++ // If debugging is enabled..
++
++ /** Writes a string to the standard error stream.
++
++ This is only compiled in a debug build.
++
++ @see Logger::outputDebugString
++ */
++ #define DBG(dbgtext) Logger::outputDebugString (dbgtext);
++
++ /** Printf's a string to the standard error stream.
++
++ This is only compiled in a debug build.
++
++ @see Logger::outputDebugString
++ */
++ #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf;
++
++ // Assertions..
++ #if defined (_MSC_VER) || DOXYGEN
++ /** This will always cause an assertion failure.
++
++ This is only compiled in a debug build.
++
++ @see jassert()
++ */
++ #ifdef __BORLANDC__
++ extern void juce_StopInDebugger();
++ #define jassertfalse { juce_StopInDebugger(); }
++ #else
++ #define jassertfalse { __asm int 3 }
++ #endif
++ #elif defined (JUCE_MAC)
++ #define jassertfalse { Debugger(); }
++ #elif defined (__GNUC__) || defined (JUCE_LINUX)
++ #ifndef __x86__
++ #define jassertfalse { 1/0; }
++ #else
++ #define jassertfalse { asm("int $3"); }
++ #endif
++ #endif
++
++ //==============================================================================
++ /** Platform-independent assertion macro.
++
++ This gets optimised out when not being built with debugging turned on.
++
++ Be careful not to call any functions within its arguments that are vital to
++ the behaviour of the program, because these won't get called in the release
++ build.
++
++ @see jassertfalse
++ */
++ #define jassert(a) { if (! (a)) jassertfalse }
++
++#else
++ //==============================================================================
++ // If debugging is disabled, disable all the assertions and debugging stuff..
++
++ #define DBG(dbgtext)
++ #define DBG_PRINTF(dbgprintf)
++
++ #define jassert(a) {}
++ #define jassertfalse {}
++
++#endif
++
++//==============================================================================
++#ifndef DOXYGEN
++ template <bool b> struct JuceStaticAssert;
++ template <> struct JuceStaticAssert <true> { static void dummy() {} };
++#endif
++
++/** A compile-time assertion macro.
++
++ If the expression parameter is false, the macro will cause a compile error.
++*/
++#define static_jassert(expression) JuceStaticAssert<expression>::dummy();
++
++
++//==============================================================================
++#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
++
++ #define JUCE_TRY try
++
++ /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication
++ object so they can be logged by the application if it wants to.
++ */
++ #define JUCE_CATCH_EXCEPTION \
++ catch (const std::exception& e) \
++ { \
++ JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \
++ } \
++ catch (...) \
++ { \
++ JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \
++ }
++
++ #define JUCE_CATCH_ALL catch (...) {}
++ #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse }
++
++#else
++
++ #define JUCE_TRY
++ #define JUCE_CATCH_EXCEPTION
++ #define JUCE_CATCH_ALL
++ #define JUCE_CATCH_ALL_ASSERT
++
++#endif
++
++
++#endif // __JUCE_PLATFORMDEFS_JUCEHEADER__
+--- juce/src/juce_core/basics/juce_DataConversions.h~remove-x86isms.patch
++++ juce/src/juce_core/basics/juce_DataConversions.h
+@@ -1,172 +1,176 @@
+-/*\r
+- ==============================================================================\r
+-\r
+- This file is part of the JUCE library - "Jules' Utility Class Extensions"\r
+- Copyright 2004-6 by Raw Material Software ltd.\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- JUCE can be redistributed and/or modified under the terms of the\r
+- GNU General Public License, as published by the Free Software Foundation;\r
+- either version 2 of the License, or (at your option) any later version.\r
+-\r
+- JUCE is distributed in the hope that it will be useful,\r
+- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+- GNU General Public License for more details.\r
+-\r
+- You should have received a copy of the GNU General Public License\r
+- along with JUCE; if not, visit www.gnu.org/licenses or write to the\r
+- Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+- Boston, MA 02111-1307 USA\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- If you'd like to release a closed-source product which uses JUCE, commercial\r
+- licenses are also available: visit www.rawmaterialsoftware.com/juce for\r
+- more information.\r
+-\r
+- ==============================================================================\r
+-*/\r
+-\r
+-#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__\r
+-#define __JUCE_DATACONVERSIONS_JUCEHEADER__\r
+-\r
+-#include "juce_PlatformDefs.h"\r
+-\r
+-//==============================================================================\r
+-// Endianness conversions..\r
+-\r
+-/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */\r
+-inline_assembly uint32 swapByteOrder (uint32 n) throw()\r
+-{\r
+-#ifdef JUCE_MAC\r
+- return CFSwapInt32 (n);\r
+-#else\r
+- #ifdef __GNUC__\r
+- // Inpenetrable GCC version..\r
+- asm("bswap %%eax" : "=a"(n) : "a"(n));\r
+- return n;\r
+- #else\r
+- // Win32 version..\r
+- __asm {\r
+- mov eax, n\r
+- bswap eax\r
+- mov n, eax\r
+- }\r
+- return n;\r
+- #endif\r
+-#endif\r
+-}\r
+-\r
+-/** Swaps the byte-order of a 16-bit short. */\r
+-inline uint16 swapByteOrder (const uint16 n) throw()\r
+-{\r
+- return (uint16) ((n << 8) | (n >> 8));\r
+-}\r
+-\r
+-inline uint64 swapByteOrder (const uint64 value) throw()\r
+-{\r
+-#ifdef JUCE_MAC\r
+- return CFSwapInt64 (value);\r
+-#else\r
+- return (((int64) swapByteOrder ((uint32) value)) << 32)\r
+- | swapByteOrder ((uint32) (value >> 32));\r
+-#endif\r
+-}\r
+-\r
+-#ifdef JUCE_LITTLE_ENDIAN\r
+- /** Swaps the byte order of a 16-bit int if the CPU is big-endian */\r
+- inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; }\r
+- /** Swaps the byte order of a 32-bit int if the CPU is big-endian */\r
+- inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; }\r
+- /** Swaps the byte order of a 16-bit int if the CPU is little-endian */\r
+- inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); }\r
+- /** Swaps the byte order of a 32-bit int if the CPU is little-endian */\r
+- inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); }\r
+-\r
+- /** Turns 4 bytes into a little-endian integer. */\r
+- inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; }\r
+-\r
+- /** Turns 2 bytes into a little-endian integer. */\r
+- inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; }\r
+-\r
+- /** Turns 4 bytes into a big-endian integer. */\r
+- inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); }\r
+-\r
+- /** Turns 2 bytes into a big-endian integer. */\r
+- inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); }\r
+-\r
+-#else\r
+- /** Swaps the byte order of a 16-bit int if the CPU is big-endian */\r
+- inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); }\r
+- /** Swaps the byte order of a 32-bit int if the CPU is big-endian */\r
+- inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); }\r
+- /** Swaps the byte order of a 16-bit int if the CPU is little-endian */\r
+- inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; }\r
+- /** Swaps the byte order of a 32-bit int if the CPU is little-endian */\r
+- inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; }\r
+-\r
+- /** Turns 4 bytes into a little-endian integer. */\r
+- inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); }\r
+-\r
+- /** Turns 2 bytes into a little-endian integer. */\r
+- inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); }\r
+-\r
+- /** Turns 4 bytes into a big-endian integer. */\r
+- inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; }\r
+-\r
+- /** Turns 2 bytes into a big-endian integer. */\r
+- inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; }\r
+-#endif\r
+-\r
+-/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */\r
+-inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); }\r
+-/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */\r
+-inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); }\r
+-\r
+-/** Copies a 24-bit number to 3 little-endian bytes. */\r
+-inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); }\r
+-/** Copies a 24-bit number to 3 big-endian bytes. */\r
+-inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); }\r
+-\r
+-\r
+-//==============================================================================\r
+-/** Fast floating-point-to-integer conversion.\r
+-\r
+- This is faster than using the normal c++ cast to convert a double to an int, and\r
+- it will round the value to the nearest integer, rather than rounding it down\r
+- like the normal cast does.\r
+-*/\r
+-inline int roundDoubleToInt (const double value) throw()\r
+-{\r
+- union { int asInt[2]; double asDouble; } n;\r
+- n.asDouble = value + 6755399441055744.0;\r
+-\r
+-#if JUCE_BIG_ENDIAN\r
+- return n.asInt [1];\r
+-#else\r
+- return n.asInt [0];\r
+-#endif\r
+-}\r
+-\r
+-/** Fast floating-point-to-integer conversion.\r
+-\r
+- This is faster than using the normal c++ cast to convert a float to an int, and\r
+- it will round the value to the nearest integer, rather than rounding it down\r
+- like the normal cast does.\r
+-*/\r
+-inline int roundFloatToInt (const float value) throw()\r
+-{\r
+- union { int asInt[2]; double asDouble; } n;\r
+- n.asDouble = value + 6755399441055744.0;\r
+-\r
+-#if JUCE_BIG_ENDIAN\r
+- return n.asInt [1];\r
+-#else\r
+- return n.asInt [0];\r
+-#endif\r
+-}\r
+-\r
+-\r
+-#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__\r
++/*
++ ==============================================================================
++
++ This file is part of the JUCE library - "Jules' Utility Class Extensions"
++ Copyright 2004-6 by Raw Material Software ltd.
++
++ ------------------------------------------------------------------------------
++
++ JUCE can be redistributed and/or modified under the terms of the
++ GNU General Public License, as published by the Free Software Foundation;
++ either version 2 of the License, or (at your option) any later version.
++
++ JUCE is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with JUCE; if not, visit www.gnu.org/licenses or write to the
++ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
++ Boston, MA 02111-1307 USA
++
++ ------------------------------------------------------------------------------
++
++ If you'd like to release a closed-source product which uses JUCE, commercial
++ licenses are also available: visit www.rawmaterialsoftware.com/juce for
++ more information.
++
++ ==============================================================================
++*/
++
++#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__
++#define __JUCE_DATACONVERSIONS_JUCEHEADER__
++
++#include "juce_PlatformDefs.h"
++
++//==============================================================================
++// Endianness conversions..
++
++/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */
++inline_assembly uint32 swapByteOrder (uint32 n) throw()
++{
++#ifdef JUCE_MAC
++ return CFSwapInt32 (n);
++#else
++ #ifdef __GNUC__
++ #ifndef __x86__
++ return ( ((n)&0xff)<<24) | (((n)&0xff00)<<8) | (((n)>>8)&0xff00) | (((n)>>24)&0xff);
++ #else
++ // Inpenetrable GCC version..
++ asm("bswap %%eax" : "=a"(n) : "a"(n));
++ return n;
++ #endif
++ #else
++ // Win32 version..
++ __asm {
++ mov eax, n
++ bswap eax
++ mov n, eax
++ }
++ return n;
++ #endif
++#endif
++}
++
++/** Swaps the byte-order of a 16-bit short. */
++inline uint16 swapByteOrder (const uint16 n) throw()
++{
++ return (uint16) ((n << 8) | (n >> 8));
++}
++
++inline uint64 swapByteOrder (const uint64 value) throw()
++{
++#ifdef JUCE_MAC
++ return CFSwapInt64 (value);
++#else
++ return (((int64) swapByteOrder ((uint32) value)) << 32)
++ | swapByteOrder ((uint32) (value >> 32));
++#endif
++}
++
++#ifdef JUCE_LITTLE_ENDIAN
++ /** Swaps the byte order of a 16-bit int if the CPU is big-endian */
++ inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; }
++ /** Swaps the byte order of a 32-bit int if the CPU is big-endian */
++ inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; }
++ /** Swaps the byte order of a 16-bit int if the CPU is little-endian */
++ inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); }
++ /** Swaps the byte order of a 32-bit int if the CPU is little-endian */
++ inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); }
++
++ /** Turns 4 bytes into a little-endian integer. */
++ inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; }
++
++ /** Turns 2 bytes into a little-endian integer. */
++ inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; }
++
++ /** Turns 4 bytes into a big-endian integer. */
++ inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); }
++
++ /** Turns 2 bytes into a big-endian integer. */
++ inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); }
++
++#else
++ /** Swaps the byte order of a 16-bit int if the CPU is big-endian */
++ inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); }
++ /** Swaps the byte order of a 32-bit int if the CPU is big-endian */
++ inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); }
++ /** Swaps the byte order of a 16-bit int if the CPU is little-endian */
++ inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; }
++ /** Swaps the byte order of a 32-bit int if the CPU is little-endian */
++ inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; }
++
++ /** Turns 4 bytes into a little-endian integer. */
++ inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); }
++
++ /** Turns 2 bytes into a little-endian integer. */
++ inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); }
++
++ /** Turns 4 bytes into a big-endian integer. */
++ inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; }
++
++ /** Turns 2 bytes into a big-endian integer. */
++ inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; }
++#endif
++
++/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
++inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); }
++/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
++inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); }
++
++/** Copies a 24-bit number to 3 little-endian bytes. */
++inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); }
++/** Copies a 24-bit number to 3 big-endian bytes. */
++inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); }
++
++
++//==============================================================================
++/** Fast floating-point-to-integer conversion.
++
++ This is faster than using the normal c++ cast to convert a double to an int, and
++ it will round the value to the nearest integer, rather than rounding it down
++ like the normal cast does.
++*/
++inline int roundDoubleToInt (const double value) throw()
++{
++ union { int asInt[2]; double asDouble; } n;
++ n.asDouble = value + 6755399441055744.0;
++
++#if JUCE_BIG_ENDIAN
++ return n.asInt [1];
++#else
++ return n.asInt [0];
++#endif
++}
++
++/** Fast floating-point-to-integer conversion.
++
++ This is faster than using the normal c++ cast to convert a float to an int, and
++ it will round the value to the nearest integer, rather than rounding it down
++ like the normal cast does.
++*/
++inline int roundFloatToInt (const float value) throw()
++{
++ union { int asInt[2]; double asDouble; } n;
++ n.asDouble = value + 6755399441055744.0;
++
++#if JUCE_BIG_ENDIAN
++ return n.asInt [1];
++#else
++ return n.asInt [0];
++#endif
++}
++
++
++#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__
+--- juce/build/linux/platform_specific_code/juce_linux_SystemStats.cpp~remove-x86isms.patch
++++ juce/build/linux/platform_specific_code/juce_linux_SystemStats.cpp
+@@ -1,472 +1,472 @@
+-/*\r
+- ==============================================================================\r
+-\r
+- This file is part of the JUCE library - "Jules' Utility Class Extensions"\r
+- Copyright 2004-6 by Raw Material Software ltd.\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- JUCE can be redistributed and/or modified under the terms of the\r
+- GNU General Public License, as published by the Free Software Foundation;\r
+- either version 2 of the License, or (at your option) any later version.\r
+-\r
+- JUCE is distributed in the hope that it will be useful,\r
+- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+- GNU General Public License for more details.\r
+-\r
+- You should have received a copy of the GNU General Public License\r
+- along with JUCE; if not, visit www.gnu.org/licenses or write to the\r
+- Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+- Boston, MA 02111-1307 USA\r
+-\r
+- ------------------------------------------------------------------------------\r
+-\r
+- If you'd like to release a closed-source product which uses JUCE, commercial\r
+- licenses are also available: visit www.rawmaterialsoftware.com/juce for\r
+- more information.\r
+-\r
+- ==============================================================================\r
+-*/\r
+-\r
+-#include "linuxincludes.h"\r
+-#include "../../../src/juce_core/basics/juce_StandardHeader.h"\r
+-\r
+-#ifdef __CYGWIN__\r
+- #include <apr_uuid.h>\r
+- #include <malloc.h>\r
+-#else\r
+- #include <sys/sysinfo.h>\r
+- #include <dlfcn.h>\r
+-#endif\r
+-\r
+-#ifdef JUCE_UUID\r
+- #include <uuid/uuid.h>\r
+-#endif\r
+-\r
+-#ifndef CPU_ISSET\r
+- #undef SUPPORT_AFFINITIES\r
+-#endif\r
+-\r
+-BEGIN_JUCE_NAMESPACE\r
+-\r
+-#include "../../../src/juce_core/io/files/juce_File.h"\r
+-#include "../../../src/juce_core/basics/juce_SystemStats.h"\r
+-#include "../../../src/juce_core/basics/juce_Logger.h"\r
+-#include "../../../src/juce_core/misc/juce_Uuid.h"\r
+-#include "../../../src/juce_core/threads/juce_Process.h"\r
+-#include "../../../src/juce_appframework/events/juce_Timer.h"\r
+-#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"\r
+-\r
+-static struct _LogicalCpuInfo\r
+-{\r
+- bool htSupported;\r
+- bool htAvailable;\r
+- int numPackages;\r
+- int numLogicalPerPackage;\r
+- uint32 physicalAffinityMask;\r
+-} logicalCpuInfo;\r
+-\r
+-//==============================================================================\r
+-static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) __attribute__ ((noinline));\r
+-\r
+-static unsigned int getCPUIDWord (int* familyModel, int* extFeatures)\r
+-{\r
+- unsigned int cpu = 0;\r
+- unsigned int ext = 0;\r
+- unsigned int family = 0;\r
+-\r
+- __asm__ __volatile__ (\r
+-" pushf \n"\r
+-#if JUCE_64BIT\r
+-" pop %%rax \n"\r
+-#else\r
+-" pop %%eax \n"\r
+-#endif\r
+-" movl %%eax, %%ecx \n"\r
+-" xorl $0x200000, %%eax \n"\r
+-#if JUCE_64BIT\r
+-" push %%rax \n"\r
+-#else\r
+-" push %%eax \n"\r
+-#endif\r
+-" popf \n"\r
+-" pushf \n"\r
+-#if JUCE_64BIT\r
+-" pop %%rax \n"\r
+-#else\r
+-" pop %%eax \n"\r
+-#endif\r
+-" andl $0x200000, %%eax \n"\r
+-" andl $0x200000, %%ecx \n"\r
+-" cmpl %%eax, %%ecx \n"\r
+-" movl $0, %%edx \n"\r
+-" je noCpuId \n"\r
+-" movl $1, %%eax \n"\r
+-" cpuid \n"\r
+-"noCpuId: \n"\r
+- : "=a"(family), /* Output in eax */\r
+- "=d"(cpu), /* Output in ebx */\r
+- "=b"(ext) /* Output in edx */\r
+- : /* No inputs */\r
+- : "cc", "ecx" /* Clobber list */\r
+- );\r
+-\r
+- if (familyModel)\r
+- *familyModel = family;\r
+- if (extFeatures)\r
+- *extFeatures = ext;\r
+-\r
+- return cpu;\r
+-}\r
+-\r
+-void juce_initLogicalCpuInfo()\r
+-{\r
+- int familyModelWord, extFeaturesWord;\r
+- int featuresWord = getCPUIDWord (&familyModelWord, &extFeaturesWord);\r
+-\r
+- logicalCpuInfo.htSupported = false;\r
+- logicalCpuInfo.htAvailable = false;\r
+- logicalCpuInfo.numLogicalPerPackage = 1;\r
+- logicalCpuInfo.numPackages = 0;\r
+- logicalCpuInfo.physicalAffinityMask = 0;\r
+-\r
+-#if SUPPORT_AFFINITIES\r
+- cpu_set_t processAffinity;\r
+-\r
+- /*\r
+- N.B. If this line causes a compile error, then you've probably not got the latest\r
+- version of glibc installed.\r
+-\r
+- If you don't want to update your copy of glibc and don't care about cpu affinities,\r
+- then you can just disable all this stuff by removing the SUPPORT_AFFINITIES macro\r
+- from the linuxincludes.h file.\r
+- */\r
+- if (sched_getaffinity (getpid(),\r
+- sizeof (cpu_set_t),\r
+- &processAffinity) != sizeof (cpu_set_t))\r
+- {\r
+- return;\r
+- }\r
+-\r
+- // Checks: CPUID supported, model >= Pentium 4, Hyperthreading bit set, logical CPUs per package > 1\r
+- if (featuresWord == 0\r
+- || ((familyModelWord >> 8) & 0xf) < 15\r
+- || (featuresWord & (1 << 28)) == 0\r
+- || ((extFeaturesWord >> 16) & 0xff) < 2)\r
+- {\r
+- for (int i = 0; i < 64; ++i)\r
+- if (CPU_ISSET (i, &processAffinity))\r
+- logicalCpuInfo.physicalAffinityMask |= (1 << i);\r
+-\r
+- return;\r
+- }\r
+-\r
+- logicalCpuInfo.htSupported = true;\r
+- logicalCpuInfo.numLogicalPerPackage = (extFeaturesWord >> 16) & 0xff;\r
+-\r
+- cpu_set_t affinityMask;\r
+- cpu_set_t physAff;\r
+- CPU_ZERO (&physAff);\r
+-\r
+- unsigned char i = 1;\r
+- unsigned char physIdMask = 0xFF;\r
+- unsigned char physIdShift = 0;\r
+-\r
+- //unsigned char apicId, logId, physId;\r
+-\r
+- while (i < logicalCpuInfo.numLogicalPerPackage)\r
+- {\r
+- i *= 2;\r
+- physIdMask <<= 1;\r
+- physIdShift++;\r
+- }\r
+-\r
+- CPU_SET (0, &affinityMask);\r
+- logicalCpuInfo.numPackages = 0;\r
+-\r
+-//xxx revisit this at some point..\r
+-/* while ((affinityMask != 0) && (affinityMask <= processAffinity))\r
+- {\r
+- int ret;\r
+- if (! sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinityMask))\r
+- {\r
+- sched_yield(); // schedule onto correct CPU\r
+-\r
+- featuresWord = getCPUIDWord(&familyModelWord, &extFeaturesWord);\r
+- apicId = (unsigned char)(extFeaturesWord >> 24);\r
+- logId = (unsigned char)(apicId & ~physIdMask);\r
+- physId = (unsigned char)(apicId >> physIdShift);\r
+-\r
+- if (logId != 0)\r
+- logicalCpuInfo.htAvailable = true;\r
+-\r
+- if ((((int)logId) % logicalCpuInfo.numLogicalPerPackage) == 0)\r
+- {\r
+- // This is a physical CPU\r
+- physAff |= affinityMask;\r
+- logicalCpuInfo.numPackages++;\r
+- }\r
+- }\r
+-\r
+- affinityMask = affinityMask << 1;\r
+- }\r
+-\r
+- sched_setaffinity (getpid(), sizeof(unsigned long), &processAffinity);\r
+-*/\r
+-\r
+- logicalCpuInfo.physicalAffinityMask = 0;\r
+-\r
+- for (int i = 0; i < 64; ++i)\r
+- if (CPU_ISSET (i, &physAff))\r
+- logicalCpuInfo.physicalAffinityMask |= (1 << i);\r
+-\r
+-#endif\r
+-}\r
+-\r
+-//==============================================================================\r
+-void Logger::outputDebugString (const String& text)\r
+-{\r
+- fprintf (stdout, (const char*) (text + T("\n")));\r
+-}\r
+-\r
+-void Logger::outputDebugPrintf (const tchar* format, ...)\r
+-{\r
+- String text;\r
+- va_list args;\r
+- va_start (args, format);\r
+- text.vprintf(format, args);\r
+- outputDebugString(text);\r
+-}\r
+-\r
+-const String SystemStats::getOSType()\r
+-{\r
+- return SystemStats::Linux;\r
+-}\r
+-\r
+-static const String getCpuInfo (const char* key, bool lastOne = false)\r
+-{\r
+- String info;\r
+- char buf [256];\r
+-\r
+- FILE* f = fopen ("/proc/cpuinfo", "r");\r
+-\r
+- while (f != 0 && fgets (buf, sizeof(buf), f))\r
+- {\r
+- if (strncmp (buf, key, strlen (key)) == 0)\r
+- {\r
+- char* p = buf;\r
+-\r
+- while (*p && *p != '\n')\r
+- ++p;\r
+-\r
+- if (*p != 0)\r
+- *p = 0;\r
+-\r
+- p = buf;\r
+-\r
+- while (*p != 0 && *p != ':')\r
+- ++p;\r
+-\r
+- if (*p != 0 && *(p + 1) != 0)\r
+- info = p + 2;\r
+-\r
+- if (! lastOne)\r
+- break;\r
+- }\r
+- }\r
+-\r
+- fclose (f);\r
+- return info;\r
+-}\r
+-\r
+-bool SystemStats::hasMMX()\r
+-{\r
+- return getCpuInfo ("flags").contains (T("mmx"));\r
+-}\r
+-\r
+-bool SystemStats::hasSSE()\r
+-{\r
+- return getCpuInfo ("flags").contains (T("sse"));\r
+-}\r
+-\r
+-bool SystemStats::hasSSE2()\r
+-{\r
+- return getCpuInfo ("flags").contains (T("sse2"));\r
+-}\r
+-\r
+-bool SystemStats::has3DNow()\r
+-{\r
+- return getCpuInfo ("flags").contains (T("3dnow"));\r
+-}\r
+-\r
+-const String SystemStats::getCpuVendor()\r
+-{\r
+- return getCpuInfo ("vendor_id");\r
+-}\r
+-\r
+-int SystemStats::getCpuSpeedInMegaherz()\r
+-{\r
+- const String speed (getCpuInfo ("cpu MHz"));\r
+-\r
+- return (int) (speed.getFloatValue() + 0.5f);\r
+-}\r
+-\r
+-bool SystemStats::hasHyperThreading()\r
+-{\r
+- return logicalCpuInfo.htAvailable;\r
+-}\r
+-\r
+-int SystemStats::getMemorySizeInMegabytes()\r
+-{\r
+-#ifndef __CYGWIN__\r
+- struct sysinfo sysi;\r
+-\r
+- if (sysinfo (&sysi) == 0)\r
+- return (sysi.totalram * sysi.mem_unit / (1024 * 1024));\r
+-\r
+- return 0;\r
+-\r
+-#else\r
+- jassertfalse\r
+- return 256;\r
+-#endif\r
+-}\r
+-\r
+-unsigned int juce_millisecondsSinceStartup()\r
+-{\r
+- static unsigned int calibrate = 0;\r
+- static bool calibrated = false;\r
+- timeval t;\r
+- unsigned int ret = 0;\r
+-\r
+- if (! gettimeofday (&t, 0))\r
+- {\r
+- if (! calibrated)\r
+- {\r
+-#ifndef __CYGWIN__\r
+- struct sysinfo sysi;\r
+-\r
+- if (sysinfo (&sysi) == 0)\r
+- // Safe to assume system was not brought up earlier than 1970!\r
+- calibrate = t.tv_sec - sysi.uptime;\r
+-#else\r
+- // bit of a hack, but things should all still work, as we're not often\r
+- // really interested in how long the machine's been turned on, and just\r
+- // use this call for relative times..\r
+- calibrate = t.tv_sec;\r
+-#endif\r
+-\r
+- calibrated = true;\r
+- }\r
+-\r
+- ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000);\r
+- }\r
+-\r
+- return ret;\r
+-}\r
+-\r
+-double juce_millisecondsSinceStartupHiRes()\r
+-{\r
+- return Time::getHighResolutionTicks() * (1.0 / 1000000.0);\r
+-}\r
+-\r
+-int64 Time::getHighResolutionTicks()\r
+-{\r
+- timeval t;\r
+- if (gettimeofday(&t,NULL))\r
+- return 0;\r
+-\r
+- return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec;\r
+-}\r
+-\r
+-int64 Time::getHighResolutionTicksPerSecond()\r
+-{\r
+- // Microseconds\r
+- return 1000000;\r
+-}\r
+-\r
+-bool Time::setSystemTimeToThisTime() const\r
+-{\r
+- timeval t;\r
+- t.tv_sec = millisSinceEpoch % 1000000;\r
+- t.tv_usec = millisSinceEpoch - t.tv_sec;\r
+-\r
+- return settimeofday (&t, NULL) ? false : true;\r
+-}\r
+-\r
+-const String Uuid::generateUuid()\r
+-{\r
+-#ifdef JUCE_UUID\r
+- uuid_t uuid;\r
+- char *s = new char[37];\r
+- String uuidStr;\r
+-\r
+- uuid_generate (uuid);\r
+- uuid_unparse (uuid, s);\r
+-\r
+- uuidStr = s;\r
+- delete[] s;\r
+-\r
+- return uuidStr;\r
+-#else\r
+- jassertfalse\r
+- return String::empty;\r
+-#endif\r
+-}\r
+-\r
+-int SystemStats::getPageSize()\r
+-{\r
+- static int systemPageSize = 0;\r
+-\r
+- if (systemPageSize == 0)\r
+- systemPageSize = sysconf (_SC_PAGESIZE);\r
+-\r
+- return systemPageSize;\r
+-}\r
+-\r
+-int SystemStats::getNumPhysicalCpus()\r
+-{\r
+- if (logicalCpuInfo.numPackages)\r
+- return logicalCpuInfo.numPackages;\r
+-\r
+- return getNumLogicalCpus();\r
+-}\r
+-\r
+-int SystemStats::getNumLogicalCpus()\r
+-{\r
+- const int lastCpu = getCpuInfo ("processor", true).getIntValue();\r
+-\r
+- return lastCpu + 1;\r
+-}\r
+-\r
+-uint32 SystemStats::getPhysicalAffinityMask()\r
+-{\r
+-#if SUPPORT_AFFINITIES\r
+- return logicalCpuInfo.physicalAffinityMask;\r
+-#else\r
+- /* affinities aren't supported because either the appropriate header files weren't found,\r
+- or the SUPPORT_AFFINITIES macro was turned off in linuxheaders.h\r
+- */\r
+- jassertfalse\r
+- return 0;\r
+-#endif\r
+-\r
+-}\r
+-\r
+-//==============================================================================\r
+-void SystemStats::initialiseStats()\r
+-{\r
+- // Process starts off as root when running suid\r
+- Process::lowerPrivilege();\r
+-\r
+- String s (SystemStats::getJUCEVersion());\r
+-\r
+- juce_initLogicalCpuInfo();\r
+-}\r
+-\r
+-void PlatformUtilities::fpuReset()\r
+-{\r
+-}\r
+-\r
+-END_JUCE_NAMESPACE\r
++/*
++ ==============================================================================
++
++ This file is part of the JUCE library - "Jules' Utility Class Extensions"
++ Copyright 2004-6 by Raw Material Software ltd.
++
++ ------------------------------------------------------------------------------
++
++ JUCE can be redistributed and/or modified under the terms of the
++ GNU General Public License, as published by the Free Software Foundation;
++ either version 2 of the License, or (at your option) any later version.
++
++ JUCE is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with JUCE; if not, visit www.gnu.org/licenses or write to the
++ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
++ Boston, MA 02111-1307 USA
++
++ ------------------------------------------------------------------------------
++
++ If you'd like to release a closed-source product which uses JUCE, commercial
++ licenses are also available: visit www.rawmaterialsoftware.com/juce for
++ more information.
++
++ ==============================================================================
++*/
++
++#include "linuxincludes.h"
++#include "../../../src/juce_core/basics/juce_StandardHeader.h"
++
++#ifdef __CYGWIN__
++ #include <apr_uuid.h>
++ #include <malloc.h>
++#else
++ #include <sys/sysinfo.h>
++ #include <dlfcn.h>
++#endif
++
++#ifdef JUCE_UUID
++ #include <uuid/uuid.h>
++#endif
++
++#ifndef CPU_ISSET
++ #undef SUPPORT_AFFINITIES
++#endif
++
++BEGIN_JUCE_NAMESPACE
++
++#include "../../../src/juce_core/io/files/juce_File.h"
++#include "../../../src/juce_core/basics/juce_SystemStats.h"
++#include "../../../src/juce_core/basics/juce_Logger.h"
++#include "../../../src/juce_core/misc/juce_Uuid.h"
++#include "../../../src/juce_core/threads/juce_Process.h"
++#include "../../../src/juce_appframework/events/juce_Timer.h"
++#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
++
++static struct _LogicalCpuInfo
++{
++ bool htSupported;
++ bool htAvailable;
++ int numPackages;
++ int numLogicalPerPackage;
++ uint32 physicalAffinityMask;
++} logicalCpuInfo;
++
++//==============================================================================
++static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) __attribute__ ((noinline));
++
++static unsigned int getCPUIDWord (int* familyModel, int* extFeatures)
++{
++ unsigned int cpu = 0;
++ unsigned int ext = 0;
++ unsigned int family = 0;
++#ifdef __x86__
++ __asm__ __volatile__ (
++" pushf \n"
++#if JUCE_64BIT
++" pop %%rax \n"
++#else
++" pop %%eax \n"
++#endif
++" movl %%eax, %%ecx \n"
++" xorl $0x200000, %%eax \n"
++#if JUCE_64BIT
++" push %%rax \n"
++#else
++" push %%eax \n"
++#endif
++" popf \n"
++" pushf \n"
++#if JUCE_64BIT
++" pop %%rax \n"
++#else
++" pop %%eax \n"
++#endif
++" andl $0x200000, %%eax \n"
++" andl $0x200000, %%ecx \n"
++" cmpl %%eax, %%ecx \n"
++" movl $0, %%edx \n"
++" je noCpuId \n"
++" movl $1, %%eax \n"
++" cpuid \n"
++"noCpuId: \n"
++ : "=a"(family), /* Output in eax */
++ "=d"(cpu), /* Output in ebx */
++ "=b"(ext) /* Output in edx */
++ : /* No inputs */
++ : "cc", "ecx" /* Clobber list */
++ );
++#endif
++ if (familyModel)
++ *familyModel = family;
++ if (extFeatures)
++ *extFeatures = ext;
++
++ return cpu;
++}
++
++void juce_initLogicalCpuInfo()
++{
++ int familyModelWord, extFeaturesWord;
++ int featuresWord = getCPUIDWord (&familyModelWord, &extFeaturesWord);
++
++ logicalCpuInfo.htSupported = false;
++ logicalCpuInfo.htAvailable = false;
++ logicalCpuInfo.numLogicalPerPackage = 1;
++ logicalCpuInfo.numPackages = 0;
++ logicalCpuInfo.physicalAffinityMask = 0;
++
++#if SUPPORT_AFFINITIES
++ cpu_set_t processAffinity;
++
++ /*
++ N.B. If this line causes a compile error, then you've probably not got the latest
++ version of glibc installed.
++
++ If you don't want to update your copy of glibc and don't care about cpu affinities,
++ then you can just disable all this stuff by removing the SUPPORT_AFFINITIES macro
++ from the linuxincludes.h file.
++ */
++ if (sched_getaffinity (getpid(),
++ sizeof (cpu_set_t),
++ &processAffinity) != sizeof (cpu_set_t))
++ {
++ return;
++ }
++
++ // Checks: CPUID supported, model >= Pentium 4, Hyperthreading bit set, logical CPUs per package > 1
++ if (featuresWord == 0
++ || ((familyModelWord >> 8) & 0xf) < 15
++ || (featuresWord & (1 << 28)) == 0
++ || ((extFeaturesWord >> 16) & 0xff) < 2)
++ {
++ for (int i = 0; i < 64; ++i)
++ if (CPU_ISSET (i, &processAffinity))
++ logicalCpuInfo.physicalAffinityMask |= (1 << i);
++
++ return;
++ }
++
++ logicalCpuInfo.htSupported = true;
++ logicalCpuInfo.numLogicalPerPackage = (extFeaturesWord >> 16) & 0xff;
++
++ cpu_set_t affinityMask;
++ cpu_set_t physAff;
++ CPU_ZERO (&physAff);
++
++ unsigned char i = 1;
++ unsigned char physIdMask = 0xFF;
++ unsigned char physIdShift = 0;
++
++ //unsigned char apicId, logId, physId;
++
++ while (i < logicalCpuInfo.numLogicalPerPackage)
++ {
++ i *= 2;
++ physIdMask <<= 1;
++ physIdShift++;
++ }
++
++ CPU_SET (0, &affinityMask);
++ logicalCpuInfo.numPackages = 0;
++
++//xxx revisit this at some point..
++/* while ((affinityMask != 0) && (affinityMask <= processAffinity))
++ {
++ int ret;
++ if (! sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinityMask))
++ {
++ sched_yield(); // schedule onto correct CPU
++
++ featuresWord = getCPUIDWord(&familyModelWord, &extFeaturesWord);
++ apicId = (unsigned char)(extFeaturesWord >> 24);
++ logId = (unsigned char)(apicId & ~physIdMask);
++ physId = (unsigned char)(apicId >> physIdShift);
++
++ if (logId != 0)
++ logicalCpuInfo.htAvailable = true;
++
++ if ((((int)logId) % logicalCpuInfo.numLogicalPerPackage) == 0)
++ {
++ // This is a physical CPU
++ physAff |= affinityMask;
++ logicalCpuInfo.numPackages++;
++ }
++ }
++
++ affinityMask = affinityMask << 1;
++ }
++
++ sched_setaffinity (getpid(), sizeof(unsigned long), &processAffinity);
++*/
++
++ logicalCpuInfo.physicalAffinityMask = 0;
++
++ for (int i = 0; i < 64; ++i)
++ if (CPU_ISSET (i, &physAff))
++ logicalCpuInfo.physicalAffinityMask |= (1 << i);
++
++#endif
++}
++
++//==============================================================================
++void Logger::outputDebugString (const String& text)
++{
++ fprintf (stdout, (const char*) (text + T("\n")));
++}
++
++void Logger::outputDebugPrintf (const tchar* format, ...)
++{
++ String text;
++ va_list args;
++ va_start (args, format);
++ text.vprintf(format, args);
++ outputDebugString(text);
++}
++
++const String SystemStats::getOSType()
++{
++ return SystemStats::Linux;
++}
++
++static const String getCpuInfo (const char* key, bool lastOne = false)
++{
++ String info;
++ char buf [256];
++
++ FILE* f = fopen ("/proc/cpuinfo", "r");
++
++ while (f != 0 && fgets (buf, sizeof(buf), f))
++ {
++ if (strncmp (buf, key, strlen (key)) == 0)
++ {
++ char* p = buf;
++
++ while (*p && *p != '\n')
++ ++p;
++
++ if (*p != 0)
++ *p = 0;
++
++ p = buf;
++
++ while (*p != 0 && *p != ':')
++ ++p;
++
++ if (*p != 0 && *(p + 1) != 0)
++ info = p + 2;
++
++ if (! lastOne)
++ break;
++ }
++ }
++
++ fclose (f);
++ return info;
++}
++
++bool SystemStats::hasMMX()
++{
++ return getCpuInfo ("flags").contains (T("mmx"));
++}
++
++bool SystemStats::hasSSE()
++{
++ return getCpuInfo ("flags").contains (T("sse"));
++}
++
++bool SystemStats::hasSSE2()
++{
++ return getCpuInfo ("flags").contains (T("sse2"));
++}
++
++bool SystemStats::has3DNow()
++{
++ return getCpuInfo ("flags").contains (T("3dnow"));
++}
++
++const String SystemStats::getCpuVendor()
++{
++ return getCpuInfo ("vendor_id");
++}
++
++int SystemStats::getCpuSpeedInMegaherz()
++{
++ const String speed (getCpuInfo ("cpu MHz"));
++
++ return (int) (speed.getFloatValue() + 0.5f);
++}
++
++bool SystemStats::hasHyperThreading()
++{
++ return logicalCpuInfo.htAvailable;
++}
++
++int SystemStats::getMemorySizeInMegabytes()
++{
++#ifndef __CYGWIN__
++ struct sysinfo sysi;
++
++ if (sysinfo (&sysi) == 0)
++ return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
++
++ return 0;
++
++#else
++ jassertfalse
++ return 256;
++#endif
++}
++
++unsigned int juce_millisecondsSinceStartup()
++{
++ static unsigned int calibrate = 0;
++ static bool calibrated = false;
++ timeval t;
++ unsigned int ret = 0;
++
++ if (! gettimeofday (&t, 0))
++ {
++ if (! calibrated)
++ {
++#ifndef __CYGWIN__
++ struct sysinfo sysi;
++
++ if (sysinfo (&sysi) == 0)
++ // Safe to assume system was not brought up earlier than 1970!
++ calibrate = t.tv_sec - sysi.uptime;
++#else
++ // bit of a hack, but things should all still work, as we're not often
++ // really interested in how long the machine's been turned on, and just
++ // use this call for relative times..
++ calibrate = t.tv_sec;
++#endif
++
++ calibrated = true;
++ }
++
++ ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000);
++ }
++
++ return ret;
++}
++
++double juce_millisecondsSinceStartupHiRes()
++{
++ return Time::getHighResolutionTicks() * (1.0 / 1000000.0);
++}
++
++int64 Time::getHighResolutionTicks()
++{
++ timeval t;
++ if (gettimeofday(&t,NULL))
++ return 0;
++
++ return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec;
++}
++
++int64 Time::getHighResolutionTicksPerSecond()
++{
++ // Microseconds
++ return 1000000;
++}
++
++bool Time::setSystemTimeToThisTime() const
++{
++ timeval t;
++ t.tv_sec = millisSinceEpoch % 1000000;
++ t.tv_usec = millisSinceEpoch - t.tv_sec;
++
++ return settimeofday (&t, NULL) ? false : true;
++}
++
++const String Uuid::generateUuid()
++{
++#ifdef JUCE_UUID
++ uuid_t uuid;
++ char *s = new char[37];
++ String uuidStr;
++
++ uuid_generate (uuid);
++ uuid_unparse (uuid, s);
++
++ uuidStr = s;
++ delete[] s;
++
++ return uuidStr;
++#else
++ jassertfalse
++ return String::empty;
++#endif
++}
++
++int SystemStats::getPageSize()
++{
++ static int systemPageSize = 0;
++
++ if (systemPageSize == 0)
++ systemPageSize = sysconf (_SC_PAGESIZE);
++
++ return systemPageSize;
++}
++
++int SystemStats::getNumPhysicalCpus()
++{
++ if (logicalCpuInfo.numPackages)
++ return logicalCpuInfo.numPackages;
++
++ return getNumLogicalCpus();
++}
++
++int SystemStats::getNumLogicalCpus()
++{
++ const int lastCpu = getCpuInfo ("processor", true).getIntValue();
++
++ return lastCpu + 1;
++}
++
++uint32 SystemStats::getPhysicalAffinityMask()
++{
++#if SUPPORT_AFFINITIES
++ return logicalCpuInfo.physicalAffinityMask;
++#else
++ /* affinities aren't supported because either the appropriate header files weren't found,
++ or the SUPPORT_AFFINITIES macro was turned off in linuxheaders.h
++ */
++ jassertfalse
++ return 0;
++#endif
++
++}
++
++//==============================================================================
++void SystemStats::initialiseStats()
++{
++ // Process starts off as root when running suid
++ Process::lowerPrivilege();
++
++ String s (SystemStats::getJUCEVersion());
++
++ juce_initLogicalCpuInfo();
++}
++
++void PlatformUtilities::fpuReset()
++{
++}
++
++END_JUCE_NAMESPACE