#
# 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 @@
-/*
-  ==============================================================================
-
-   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"
-
-#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
+/*
+  ==============================================================================
+
+   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