# # 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 -#include -#include -#include -#include -#include - -#include "../../../juce_Config.h" - -#if JUCE_USE_XINERAMA -#include -#endif - -#if JUCE_OPENGL -#include -#include -#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 (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 & 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_crea