From d6c212ff5889b904e3207cfd7bfffef4d87c0233 Mon Sep 17 00:00:00 2001 From: Michael Lauer Date: Wed, 19 Apr 2006 17:15:59 +0000 Subject: add juce, a very nice C++ application framework. the .bb is WIP --- packages/juce/.mtn2git_empty | 0 packages/juce/files/.mtn2git_empty | 0 packages/juce/files/no-opengl.patch | 4477 ++++++++++++++++++++++++++++++ packages/juce/files/remove-x86isms.patch | 2353 ++++++++++++++++ packages/juce/juce_1.29.bb | 34 + 5 files changed, 6864 insertions(+) create mode 100644 packages/juce/.mtn2git_empty create mode 100644 packages/juce/files/.mtn2git_empty create mode 100644 packages/juce/files/no-opengl.patch create mode 100644 packages/juce/files/remove-x86isms.patch create mode 100644 packages/juce/juce_1.29.bb (limited to 'packages/juce') diff --git a/packages/juce/.mtn2git_empty b/packages/juce/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/juce/files/.mtn2git_empty b/packages/juce/files/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/juce/files/no-opengl.patch b/packages/juce/files/no-opengl.patch new file mode 100644 index 0000000000..dd379349f4 --- /dev/null +++ b/packages/juce/files/no-opengl.patch @@ -0,0 +1,4477 @@ + +# +# 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_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 (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 (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 ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../../juce_Config.h" ++#undef JUCE_USE_XINERAMA ++#undef JUCE_OPENGL ++#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_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 (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 (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 diff --git a/packages/juce/files/remove-x86isms.patch b/packages/juce/files/remove-x86isms.patch new file mode 100644 index 0000000000..83016f733a --- /dev/null +++ b/packages/juce/files/remove-x86isms.patch @@ -0,0 +1,2353 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- juce/src/juce_core/basics/juce_Atomic.h~remove-x86isms.patch ++++ juce/src/juce_core/basics/juce_Atomic.h +@@ -1,188 +1,200 @@ +-/* +- ============================================================================== +- +- This file is part of the JUCE library - "Jules' Utility Class Extensions" +- Copyright 2004-6 by Raw Material Software ltd. +- +- ------------------------------------------------------------------------------ +- +- JUCE can be redistributed and/or modified under the terms of the +- GNU General Public License, as published by the Free Software Foundation; +- either version 2 of the License, or (at your option) any later version. +- +- JUCE is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with JUCE; if not, visit www.gnu.org/licenses or write to the +- Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- Boston, MA 02111-1307 USA +- +- ------------------------------------------------------------------------------ +- +- If you'd like to release a closed-source product which uses JUCE, commercial +- licenses are also available: visit www.rawmaterialsoftware.com/juce for +- more information. +- +- ============================================================================== +-*/ +- +-#ifndef __JUCE_ATOMIC_JUCEHEADER__ +-#define __JUCE_ATOMIC_JUCEHEADER__ +- +-// Atomic increment/decrement operations.. +- +-//============================================================================== +-#if JUCE_MAC && ! DOXYGEN +- #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) +- #include +- +- forcedinline void atomicIncrement (int& variable) throw() +- { +- OSAtomicIncrement32 ((int32_t*) &variable); +- } +- +- forcedinline int atomicIncrementAndReturn (int& variable) throw() +- { +- return OSAtomicIncrement32 ((int32_t*) &variable); +- } +- +- forcedinline void atomicDecrement (int& variable) throw() +- { +- OSAtomicDecrement32 ((int32_t*) &variable); +- } +- +- forcedinline int atomicDecrementAndReturn (int& variable) throw() +- { +- return OSAtomicDecrement32 ((int32_t*) &variable); +- } +- +- #else +- forcedinline void atomicIncrement (int& variable) throw() +- { +- OTAtomicAdd32 (1, (SInt32*) &variable); +- } +- +- forcedinline int atomicIncrementAndReturn (int& variable) throw() +- { +- return OTAtomicAdd32 (1, (SInt32*) &variable); +- } +- +- forcedinline void atomicDecrement (int& variable) throw() +- { +- OTAtomicAdd32 (-1, (SInt32*) &variable); +- } +- +- forcedinline int atomicDecrementAndReturn (int& variable) throw() +- { +- return OTAtomicAdd32 (-1, (SInt32*) &variable); +- } +- #endif +-#else +-#ifdef __GNUC__ +- +- /** Increments an integer in a thread-safe way. */ +- forcedinline void atomicIncrement (int& variable) throw() +- { +- __asm__ __volatile ( +- "lock incl (%%ecx)" +- : +- : "c" (&variable)); +- } +- +- /** Increments an integer in a thread-safe way and returns the incremented value. */ +- forcedinline int atomicIncrementAndReturn (int& variable) throw() +- { +- int result; +- +- __asm__ __volatile ( +- "lock xaddl %%eax, (%%ebx) \n\ +- incl %%eax" +- : "=a" (result) +- : "b" (&variable), "a" (1) +- : "cc", "memory"); +- +- return result; +- } +- +- /** Decrememts an integer in a thread-safe way. */ +- forcedinline void atomicDecrement (int& variable) throw() +- { +- __asm__ __volatile ( +- "lock decl (%%ecx)" +- : +- : "c" (&variable)); +- } +- +- /** Decrememts an integer in a thread-safe way and returns the incremented value. */ +- forcedinline int atomicDecrementAndReturn (int& variable) throw() +- { +- int result; +- +- __asm__ __volatile ( +- "lock xaddl %%eax, (%%ebx) \n\ +- decl %%eax" +- : "=a" (result) +- : "b" (&variable), "a" (-1) +- : "cc", "memory"); +- +- return result; +- } +- +-#else +- +- /** Increments an integer in a thread-safe way. */ +- inline_assembly void __fastcall atomicIncrement (int& variable) throw() +- { +- __asm { +- mov ecx, dword ptr [variable] +- lock inc dword ptr [ecx] +- } +- } +- +- /** Increments an integer in a thread-safe way and returns the incremented value. */ +- inline_assembly int __fastcall atomicIncrementAndReturn (int& variable) throw() +- { +- int result; +- +- __asm { +- mov ecx, dword ptr [variable] +- mov eax, 1 +- lock xadd dword ptr [ecx], eax +- inc eax +- mov result, eax +- } +- +- return result; +- } +- +- /** Decrememts an integer in a thread-safe way. */ +- inline_assembly void __fastcall atomicDecrement (int& variable) throw() +- { +- __asm { +- mov ecx, dword ptr [variable] +- lock dec dword ptr [ecx] +- } +- } +- +- /** Decrememts an integer in a thread-safe way and returns the incremented value. */ +- inline_assembly int __fastcall atomicDecrementAndReturn (int& variable) throw() +- { +- int result; +- +- __asm { +- mov ecx, dword ptr [variable] +- mov eax, -1 +- lock xadd dword ptr [ecx], eax +- dec eax +- mov result, eax +- } +- +- return result; +- } +-#endif +-#endif +- +-#endif // __JUCE_ATOMIC_JUCEHEADER__ ++/* ++ ============================================================================== ++ ++ This file is part of the JUCE library - "Jules' Utility Class Extensions" ++ Copyright 2004-6 by Raw Material Software ltd. ++ ++ ------------------------------------------------------------------------------ ++ ++ JUCE can be redistributed and/or modified under the terms of the ++ GNU General Public License, as published by the Free Software Foundation; ++ either version 2 of the License, or (at your option) any later version. ++ ++ JUCE is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with JUCE; if not, visit www.gnu.org/licenses or write to the ++ Free Software Foundation, Inc., 59 Temple Place, Suite 330, ++ Boston, MA 02111-1307 USA ++ ++ ------------------------------------------------------------------------------ ++ ++ If you'd like to release a closed-source product which uses JUCE, commercial ++ licenses are also available: visit www.rawmaterialsoftware.com/juce for ++ more information. ++ ++ ============================================================================== ++*/ ++ ++#ifndef __JUCE_ATOMIC_JUCEHEADER__ ++#define __JUCE_ATOMIC_JUCEHEADER__ ++ ++// Atomic increment/decrement operations.. ++ ++//============================================================================== ++#if JUCE_MAC && ! DOXYGEN ++ #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) ++ #include ++ ++ forcedinline void atomicIncrement (int& variable) throw() ++ { ++ OSAtomicIncrement32 ((int32_t*) &variable); ++ } ++ ++ forcedinline int atomicIncrementAndReturn (int& variable) throw() ++ { ++ return OSAtomicIncrement32 ((int32_t*) &variable); ++ } ++ ++ forcedinline void atomicDecrement (int& variable) throw() ++ { ++ OSAtomicDecrement32 ((int32_t*) &variable); ++ } ++ ++ forcedinline int atomicDecrementAndReturn (int& variable) throw() ++ { ++ return OSAtomicDecrement32 ((int32_t*) &variable); ++ } ++ ++ #else ++ forcedinline void atomicIncrement (int& variable) throw() ++ { ++ OTAtomicAdd32 (1, (SInt32*) &variable); ++ } ++ ++ forcedinline int atomicIncrementAndReturn (int& variable) throw() ++ { ++ return OTAtomicAdd32 (1, (SInt32*) &variable); ++ } ++ ++ forcedinline void atomicDecrement (int& variable) throw() ++ { ++ OTAtomicAdd32 (-1, (SInt32*) &variable); ++ } ++ ++ forcedinline int atomicDecrementAndReturn (int& variable) throw() ++ { ++ return OTAtomicAdd32 (-1, (SInt32*) &variable); ++ } ++ #endif ++#else ++#ifdef __GNUC__ ++ ++ /** Increments an integer in a thread-safe way. */ ++ forcedinline void atomicIncrement (int& variable) throw() ++ { ++#ifndef __x86__ ++ variable++; ++#else ++ __asm__ __volatile ( ++ "lock incl (%%ecx)" ++ : ++ : "c" (&variable)); ++#endif ++ } ++ ++ /** Increments an integer in a thread-safe way and returns the incremented value. */ ++ forcedinline int atomicIncrementAndReturn (int& variable) throw() ++ { ++ int result; ++#ifndef __x86__ ++ result = ++variable; ++#else ++ __asm__ __volatile ( ++ "lock xaddl %%eax, (%%ebx) \n\ ++ incl %%eax" ++ : "=a" (result) ++ : "b" (&variable), "a" (1) ++ : "cc", "memory"); ++#endif ++ return result; ++ } ++ ++ /** Decrememts an integer in a thread-safe way. */ ++ forcedinline void atomicDecrement (int& variable) throw() ++ { ++#ifndef __x86__ ++ variable--; ++#else ++ __asm__ __volatile ( ++ "lock decl (%%ecx)" ++ : ++ : "c" (&variable)); ++#endif ++ } ++ ++ /** Decrememts an integer in a thread-safe way and returns the incremented value. */ ++ forcedinline int atomicDecrementAndReturn (int& variable) throw() ++ { ++ int result; ++#ifndef __x86__ ++ result = --variable; ++#else ++ __asm__ __volatile ( ++ "lock xaddl %%eax, (%%ebx) \n\ ++ decl %%eax" ++ : "=a" (result) ++ : "b" (&variable), "a" (-1) ++ : "cc", "memory"); ++#endif ++ return result; ++ } ++ ++#else ++ ++ /** Increments an integer in a thread-safe way. */ ++ inline_assembly void __fastcall atomicIncrement (int& variable) throw() ++ { ++ __asm { ++ mov ecx, dword ptr [variable] ++ lock inc dword ptr [ecx] ++ } ++ } ++ ++ /** Increments an integer in a thread-safe way and returns the incremented value. */ ++ inline_assembly int __fastcall atomicIncrementAndReturn (int& variable) throw() ++ { ++ int result; ++ ++ __asm { ++ mov ecx, dword ptr [variable] ++ mov eax, 1 ++ lock xadd dword ptr [ecx], eax ++ inc eax ++ mov result, eax ++ } ++ ++ return result; ++ } ++ ++ /** Decrememts an integer in a thread-safe way. */ ++ inline_assembly void __fastcall atomicDecrement (int& variable) throw() ++ { ++ __asm { ++ mov ecx, dword ptr [variable] ++ lock dec dword ptr [ecx] ++ } ++ } ++ ++ /** Decrememts an integer in a thread-safe way and returns the incremented value. */ ++ inline_assembly int __fastcall atomicDecrementAndReturn (int& variable) throw() ++ { ++ int result; ++ ++ __asm { ++ mov ecx, dword ptr [variable] ++ mov eax, -1 ++ lock xadd dword ptr [ecx], eax ++ dec eax ++ mov result, eax ++ } ++ ++ return result; ++ } ++#endif ++#endif ++ ++#endif // __JUCE_ATOMIC_JUCEHEADER__ +--- juce/src/juce_core/basics/juce_PlatformDefs.h~remove-x86isms.patch ++++ juce/src/juce_core/basics/juce_PlatformDefs.h +@@ -1,326 +1,330 @@ +-/* +- ============================================================================== +- +- This file is part of the JUCE library - "Jules' Utility Class Extensions" +- Copyright 2004-6 by Raw Material Software ltd. +- +- ------------------------------------------------------------------------------ +- +- JUCE can be redistributed and/or modified under the terms of the +- GNU General Public License, as published by the Free Software Foundation; +- either version 2 of the License, or (at your option) any later version. +- +- JUCE is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with JUCE; if not, visit www.gnu.org/licenses or write to the +- Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- Boston, MA 02111-1307 USA +- +- ------------------------------------------------------------------------------ +- +- If you'd like to release a closed-source product which uses JUCE, commercial +- licenses are also available: visit www.rawmaterialsoftware.com/juce for +- more information. +- +- ============================================================================== +-*/ +- +-#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ +-#define __JUCE_PLATFORMDEFS_JUCEHEADER__ +- +- +-//============================================================================== +-// set up platform definitions.. +-#ifdef _WIN32 +- #define JUCE_WIN32 1 +- #define JUCE_WINDOWS 1 +-#else +- #ifdef LINUX +- #define JUCE_LINUX 1 +- #else +- #define JUCE_MAC 1 +- #endif +-#endif +- +-//============================================================================== +-#ifdef JUCE_WINDOWS +- #ifdef _MSC_VER +- #ifdef _WIN64 +- #define JUCE_64BIT 1 +- #else +- #define JUCE_32BIT 1 +- #endif +- #endif +- +- #ifdef _DEBUG +- #define JUCE_DEBUG 1 +- #endif +- +- /** If defined, this indicates that the processor is little-endian. */ +- #define JUCE_LITTLE_ENDIAN 1 +- +- #define JUCE_INTEL 1 +-#endif +- +-//============================================================================== +-#ifdef JUCE_MAC +- +- #include +- #include +- +- #ifndef NDEBUG +- #define JUCE_DEBUG 1 +- #endif +- +- #ifdef __LITTLE_ENDIAN__ +- #define JUCE_LITTLE_ENDIAN 1 +- #else +- #define JUCE_BIG_ENDIAN 1 +- #endif +- +- #if defined (__ppc__) || defined (__ppc64__) +- #define JUCE_PPC 1 +- #else +- #define JUCE_INTEL 1 +- #endif +- +- #ifdef __LP64__ +- #define JUCE_64BIT 1 +- #else +- #define JUCE_32BIT 1 +- #endif +-#endif +- +-//============================================================================== +-#ifdef JUCE_LINUX +- +- #ifdef _DEBUG +- #define JUCE_DEBUG 1 +- #endif +- +- #include +- +- // Allow override for big-endian Linux platforms +- #ifndef JUCE_BIG_ENDIAN +- #define JUCE_LITTLE_ENDIAN 1 +- #endif +- +- #if defined (__LP64__) || defined (_LP64) +- #define JUCE_64BIT 1 +- #else +- #define JUCE_32BIT 1 +- #endif +- +- #define JUCE_INTEL 1 +-#endif +- +-//============================================================================== +-#if defined (__GNUC__) || defined (__MWERKS__) +- /** A platform-independent 64-bit integer type. */ +- typedef long long int64; +- /** A platform-independent 64-bit unsigned integer type. */ +- typedef unsigned long long uint64; +- /** A platform-independent unicode character type. */ +- typedef wchar_t juce_wchar; +- +- /** A platform-independent way of forcing an inline function. +- +- Use the syntax: @code +- forcedinline void myfunction (int x) +- @endcode +- */ +- #ifndef JUCE_DEBUG +- #define forcedinline inline __attribute__((always_inline)) +- #else +- #define forcedinline inline +- #endif +- +- /** A platform-independent way of stopping the compiler inlining a function. +- +- Use the syntax: @code +- juce_noinline void myfunction (int x) +- @endcode +- */ +- #define juce_noinline __attribute__((noinline)) +- +-#else +- //============================================================================== +- /** A platform-independent 64-bit integer type. */ +- typedef __int64 int64; +- /** A platform-independent 64-bit unsigned integer type. */ +- typedef unsigned __int64 uint64; +- +- /** A platform-independent unicode character type. */ +- typedef wchar_t juce_wchar; +- +- /** A platform-independent way of forcing an inline function. +- +- Use the syntax: @code +- forcedinline void myfunction (int x) +- @endcode +- */ +- #ifdef _MSC_VER +- #define forcedinline __forceinline +- #else +- #define forcedinline inline +- #endif +- +- /** A platform-independent way of stopping the compiler inlining a function. +- +- Use the syntax: @code +- juce_noinline void myfunction (int x) +- @endcode +- */ +- #define juce_noinline +- +-#endif +- +-#if JUCE_64BIT +- typedef int64 pointer_sized_int; +- typedef uint64 pointer_sized_uint; +-#else +- #if _MSC_VER >= 1300 +- typedef _W64 int pointer_sized_int; +- typedef _W64 unsigned int pointer_sized_uint; +- #else +- typedef int pointer_sized_int; +- typedef unsigned int pointer_sized_uint; +- #endif +-#endif +- +- +-// borland can't handle inline functions containing asm code, so define a +-// special type of inline modifier for this kind of function. Sigh.. +-#ifdef __BORLANDC__ +- #define inline_assembly +-#else +- #define inline_assembly forcedinline +-#endif +- +-//============================================================================== +-typedef signed char int8; +-typedef unsigned char uint8; +-typedef signed short int16; +-typedef unsigned short uint16; +-typedef signed int int32; +-typedef unsigned int uint32; +- +- +-//============================================================================== +-// Debugging macros +-// +- +-#ifdef JUCE_DEBUG +- //============================================================================== +- // If debugging is enabled.. +- +- /** Writes a string to the standard error stream. +- +- This is only compiled in a debug build. +- +- @see Logger::outputDebugString +- */ +- #define DBG(dbgtext) Logger::outputDebugString (dbgtext); +- +- /** Printf's a string to the standard error stream. +- +- This is only compiled in a debug build. +- +- @see Logger::outputDebugString +- */ +- #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; +- +- // Assertions.. +- #if defined (_MSC_VER) || DOXYGEN +- /** This will always cause an assertion failure. +- +- This is only compiled in a debug build. +- +- @see jassert() +- */ +- #ifdef __BORLANDC__ +- extern void juce_StopInDebugger(); +- #define jassertfalse { juce_StopInDebugger(); } +- #else +- #define jassertfalse { __asm int 3 } +- #endif +- #elif defined (JUCE_MAC) +- #define jassertfalse { Debugger(); } +- #elif defined (__GNUC__) || defined (JUCE_LINUX) +- #define jassertfalse { asm("int $3"); } +- #endif +- +- //============================================================================== +- /** Platform-independent assertion macro. +- +- This gets optimised out when not being built with debugging turned on. +- +- Be careful not to call any functions within its arguments that are vital to +- the behaviour of the program, because these won't get called in the release +- build. +- +- @see jassertfalse +- */ +- #define jassert(a) { if (! (a)) jassertfalse } +- +-#else +- //============================================================================== +- // If debugging is disabled, disable all the assertions and debugging stuff.. +- +- #define DBG(dbgtext) +- #define DBG_PRINTF(dbgprintf) +- +- #define jassert(a) {} +- #define jassertfalse {} +- +-#endif +- +-//============================================================================== +-#ifndef DOXYGEN +- template struct JuceStaticAssert; +- template <> struct JuceStaticAssert { static void dummy() {} }; +-#endif +- +-/** A compile-time assertion macro. +- +- If the expression parameter is false, the macro will cause a compile error. +-*/ +-#define static_jassert(expression) JuceStaticAssert::dummy(); +- +- +-//============================================================================== +-#if JUCE_CATCH_UNHANDLED_EXCEPTIONS +- +- #define JUCE_TRY try +- +- /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication +- object so they can be logged by the application if it wants to. +- */ +- #define JUCE_CATCH_EXCEPTION \ +- catch (const std::exception& e) \ +- { \ +- JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ +- } \ +- catch (...) \ +- { \ +- JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ +- } +- +- #define JUCE_CATCH_ALL catch (...) {} +- #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } +- +-#else +- +- #define JUCE_TRY +- #define JUCE_CATCH_EXCEPTION +- #define JUCE_CATCH_ALL +- #define JUCE_CATCH_ALL_ASSERT +- +-#endif +- +- +-#endif // __JUCE_PLATFORMDEFS_JUCEHEADER__ ++/* ++ ============================================================================== ++ ++ This file is part of the JUCE library - "Jules' Utility Class Extensions" ++ Copyright 2004-6 by Raw Material Software ltd. ++ ++ ------------------------------------------------------------------------------ ++ ++ JUCE can be redistributed and/or modified under the terms of the ++ GNU General Public License, as published by the Free Software Foundation; ++ either version 2 of the License, or (at your option) any later version. ++ ++ JUCE is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with JUCE; if not, visit www.gnu.org/licenses or write to the ++ Free Software Foundation, Inc., 59 Temple Place, Suite 330, ++ Boston, MA 02111-1307 USA ++ ++ ------------------------------------------------------------------------------ ++ ++ If you'd like to release a closed-source product which uses JUCE, commercial ++ licenses are also available: visit www.rawmaterialsoftware.com/juce for ++ more information. ++ ++ ============================================================================== ++*/ ++ ++#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ ++#define __JUCE_PLATFORMDEFS_JUCEHEADER__ ++ ++ ++//============================================================================== ++// set up platform definitions.. ++#ifdef _WIN32 ++ #define JUCE_WIN32 1 ++ #define JUCE_WINDOWS 1 ++#else ++ #ifdef LINUX ++ #define JUCE_LINUX 1 ++ #else ++ #define JUCE_MAC 1 ++ #endif ++#endif ++ ++//============================================================================== ++#ifdef JUCE_WINDOWS ++ #ifdef _MSC_VER ++ #ifdef _WIN64 ++ #define JUCE_64BIT 1 ++ #else ++ #define JUCE_32BIT 1 ++ #endif ++ #endif ++ ++ #ifdef _DEBUG ++ #define JUCE_DEBUG 1 ++ #endif ++ ++ /** If defined, this indicates that the processor is little-endian. */ ++ #define JUCE_LITTLE_ENDIAN 1 ++ ++ #define JUCE_INTEL 1 ++#endif ++ ++//============================================================================== ++#ifdef JUCE_MAC ++ ++ #include ++ #include ++ ++ #ifndef NDEBUG ++ #define JUCE_DEBUG 1 ++ #endif ++ ++ #ifdef __LITTLE_ENDIAN__ ++ #define JUCE_LITTLE_ENDIAN 1 ++ #else ++ #define JUCE_BIG_ENDIAN 1 ++ #endif ++ ++ #if defined (__ppc__) || defined (__ppc64__) ++ #define JUCE_PPC 1 ++ #else ++ #define JUCE_INTEL 1 ++ #endif ++ ++ #ifdef __LP64__ ++ #define JUCE_64BIT 1 ++ #else ++ #define JUCE_32BIT 1 ++ #endif ++#endif ++ ++//============================================================================== ++#ifdef JUCE_LINUX ++ ++ #ifdef _DEBUG ++ #define JUCE_DEBUG 1 ++ #endif ++ ++ #include ++ ++ // Allow override for big-endian Linux platforms ++ #ifndef JUCE_BIG_ENDIAN ++ #define JUCE_LITTLE_ENDIAN 1 ++ #endif ++ ++ #if defined (__LP64__) || defined (_LP64) ++ #define JUCE_64BIT 1 ++ #else ++ #define JUCE_32BIT 1 ++ #endif ++ ++ #define JUCE_INTEL 1 ++#endif ++ ++//============================================================================== ++#if defined (__GNUC__) || defined (__MWERKS__) ++ /** A platform-independent 64-bit integer type. */ ++ typedef long long int64; ++ /** A platform-independent 64-bit unsigned integer type. */ ++ typedef unsigned long long uint64; ++ /** A platform-independent unicode character type. */ ++ typedef wchar_t juce_wchar; ++ ++ /** A platform-independent way of forcing an inline function. ++ ++ Use the syntax: @code ++ forcedinline void myfunction (int x) ++ @endcode ++ */ ++ #ifndef JUCE_DEBUG ++ #define forcedinline inline __attribute__((always_inline)) ++ #else ++ #define forcedinline inline ++ #endif ++ ++ /** A platform-independent way of stopping the compiler inlining a function. ++ ++ Use the syntax: @code ++ juce_noinline void myfunction (int x) ++ @endcode ++ */ ++ #define juce_noinline __attribute__((noinline)) ++ ++#else ++ //============================================================================== ++ /** A platform-independent 64-bit integer type. */ ++ typedef __int64 int64; ++ /** A platform-independent 64-bit unsigned integer type. */ ++ typedef unsigned __int64 uint64; ++ ++ /** A platform-independent unicode character type. */ ++ typedef wchar_t juce_wchar; ++ ++ /** A platform-independent way of forcing an inline function. ++ ++ Use the syntax: @code ++ forcedinline void myfunction (int x) ++ @endcode ++ */ ++ #ifdef _MSC_VER ++ #define forcedinline __forceinline ++ #else ++ #define forcedinline inline ++ #endif ++ ++ /** A platform-independent way of stopping the compiler inlining a function. ++ ++ Use the syntax: @code ++ juce_noinline void myfunction (int x) ++ @endcode ++ */ ++ #define juce_noinline ++ ++#endif ++ ++#if JUCE_64BIT ++ typedef int64 pointer_sized_int; ++ typedef uint64 pointer_sized_uint; ++#else ++ #if _MSC_VER >= 1300 ++ typedef _W64 int pointer_sized_int; ++ typedef _W64 unsigned int pointer_sized_uint; ++ #else ++ typedef int pointer_sized_int; ++ typedef unsigned int pointer_sized_uint; ++ #endif ++#endif ++ ++ ++// borland can't handle inline functions containing asm code, so define a ++// special type of inline modifier for this kind of function. Sigh.. ++#ifdef __BORLANDC__ ++ #define inline_assembly ++#else ++ #define inline_assembly forcedinline ++#endif ++ ++//============================================================================== ++typedef signed char int8; ++typedef unsigned char uint8; ++typedef signed short int16; ++typedef unsigned short uint16; ++typedef signed int int32; ++typedef unsigned int uint32; ++ ++ ++//============================================================================== ++// Debugging macros ++// ++ ++#ifdef JUCE_DEBUG ++ //============================================================================== ++ // If debugging is enabled.. ++ ++ /** Writes a string to the standard error stream. ++ ++ This is only compiled in a debug build. ++ ++ @see Logger::outputDebugString ++ */ ++ #define DBG(dbgtext) Logger::outputDebugString (dbgtext); ++ ++ /** Printf's a string to the standard error stream. ++ ++ This is only compiled in a debug build. ++ ++ @see Logger::outputDebugString ++ */ ++ #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; ++ ++ // Assertions.. ++ #if defined (_MSC_VER) || DOXYGEN ++ /** This will always cause an assertion failure. ++ ++ This is only compiled in a debug build. ++ ++ @see jassert() ++ */ ++ #ifdef __BORLANDC__ ++ extern void juce_StopInDebugger(); ++ #define jassertfalse { juce_StopInDebugger(); } ++ #else ++ #define jassertfalse { __asm int 3 } ++ #endif ++ #elif defined (JUCE_MAC) ++ #define jassertfalse { Debugger(); } ++ #elif defined (__GNUC__) || defined (JUCE_LINUX) ++ #ifndef __x86__ ++ #define jassertfalse { 1/0; } ++ #else ++ #define jassertfalse { asm("int $3"); } ++ #endif ++ #endif ++ ++ //============================================================================== ++ /** Platform-independent assertion macro. ++ ++ This gets optimised out when not being built with debugging turned on. ++ ++ Be careful not to call any functions within its arguments that are vital to ++ the behaviour of the program, because these won't get called in the release ++ build. ++ ++ @see jassertfalse ++ */ ++ #define jassert(a) { if (! (a)) jassertfalse } ++ ++#else ++ //============================================================================== ++ // If debugging is disabled, disable all the assertions and debugging stuff.. ++ ++ #define DBG(dbgtext) ++ #define DBG_PRINTF(dbgprintf) ++ ++ #define jassert(a) {} ++ #define jassertfalse {} ++ ++#endif ++ ++//============================================================================== ++#ifndef DOXYGEN ++ template struct JuceStaticAssert; ++ template <> struct JuceStaticAssert { static void dummy() {} }; ++#endif ++ ++/** A compile-time assertion macro. ++ ++ If the expression parameter is false, the macro will cause a compile error. ++*/ ++#define static_jassert(expression) JuceStaticAssert::dummy(); ++ ++ ++//============================================================================== ++#if JUCE_CATCH_UNHANDLED_EXCEPTIONS ++ ++ #define JUCE_TRY try ++ ++ /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication ++ object so they can be logged by the application if it wants to. ++ */ ++ #define JUCE_CATCH_EXCEPTION \ ++ catch (const std::exception& e) \ ++ { \ ++ JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ ++ } \ ++ catch (...) \ ++ { \ ++ JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ ++ } ++ ++ #define JUCE_CATCH_ALL catch (...) {} ++ #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } ++ ++#else ++ ++ #define JUCE_TRY ++ #define JUCE_CATCH_EXCEPTION ++ #define JUCE_CATCH_ALL ++ #define JUCE_CATCH_ALL_ASSERT ++ ++#endif ++ ++ ++#endif // __JUCE_PLATFORMDEFS_JUCEHEADER__ +--- juce/src/juce_core/basics/juce_DataConversions.h~remove-x86isms.patch ++++ juce/src/juce_core/basics/juce_DataConversions.h +@@ -1,172 +1,176 @@ +-/* +- ============================================================================== +- +- This file is part of the JUCE library - "Jules' Utility Class Extensions" +- Copyright 2004-6 by Raw Material Software ltd. +- +- ------------------------------------------------------------------------------ +- +- JUCE can be redistributed and/or modified under the terms of the +- GNU General Public License, as published by the Free Software Foundation; +- either version 2 of the License, or (at your option) any later version. +- +- JUCE is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with JUCE; if not, visit www.gnu.org/licenses or write to the +- Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- Boston, MA 02111-1307 USA +- +- ------------------------------------------------------------------------------ +- +- If you'd like to release a closed-source product which uses JUCE, commercial +- licenses are also available: visit www.rawmaterialsoftware.com/juce for +- more information. +- +- ============================================================================== +-*/ +- +-#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__ +-#define __JUCE_DATACONVERSIONS_JUCEHEADER__ +- +-#include "juce_PlatformDefs.h" +- +-//============================================================================== +-// Endianness conversions.. +- +-/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */ +-inline_assembly uint32 swapByteOrder (uint32 n) throw() +-{ +-#ifdef JUCE_MAC +- return CFSwapInt32 (n); +-#else +- #ifdef __GNUC__ +- // Inpenetrable GCC version.. +- asm("bswap %%eax" : "=a"(n) : "a"(n)); +- return n; +- #else +- // Win32 version.. +- __asm { +- mov eax, n +- bswap eax +- mov n, eax +- } +- return n; +- #endif +-#endif +-} +- +-/** Swaps the byte-order of a 16-bit short. */ +-inline uint16 swapByteOrder (const uint16 n) throw() +-{ +- return (uint16) ((n << 8) | (n >> 8)); +-} +- +-inline uint64 swapByteOrder (const uint64 value) throw() +-{ +-#ifdef JUCE_MAC +- return CFSwapInt64 (value); +-#else +- return (((int64) swapByteOrder ((uint32) value)) << 32) +- | swapByteOrder ((uint32) (value >> 32)); +-#endif +-} +- +-#ifdef JUCE_LITTLE_ENDIAN +- /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ +- inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; } +- /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ +- inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; } +- /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ +- inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); } +- /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ +- inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); } +- +- /** Turns 4 bytes into a little-endian integer. */ +- inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } +- +- /** Turns 2 bytes into a little-endian integer. */ +- inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } +- +- /** Turns 4 bytes into a big-endian integer. */ +- inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } +- +- /** Turns 2 bytes into a big-endian integer. */ +- inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } +- +-#else +- /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ +- inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); } +- /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ +- inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); } +- /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ +- inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; } +- /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ +- inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; } +- +- /** Turns 4 bytes into a little-endian integer. */ +- inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } +- +- /** Turns 2 bytes into a little-endian integer. */ +- inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } +- +- /** Turns 4 bytes into a big-endian integer. */ +- inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } +- +- /** Turns 2 bytes into a big-endian integer. */ +- inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } +-#endif +- +-/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ +-inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } +-/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ +-inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } +- +-/** Copies a 24-bit number to 3 little-endian bytes. */ +-inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } +-/** Copies a 24-bit number to 3 big-endian bytes. */ +-inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } +- +- +-//============================================================================== +-/** Fast floating-point-to-integer conversion. +- +- This is faster than using the normal c++ cast to convert a double to an int, and +- it will round the value to the nearest integer, rather than rounding it down +- like the normal cast does. +-*/ +-inline int roundDoubleToInt (const double value) throw() +-{ +- union { int asInt[2]; double asDouble; } n; +- n.asDouble = value + 6755399441055744.0; +- +-#if JUCE_BIG_ENDIAN +- return n.asInt [1]; +-#else +- return n.asInt [0]; +-#endif +-} +- +-/** Fast floating-point-to-integer conversion. +- +- This is faster than using the normal c++ cast to convert a float to an int, and +- it will round the value to the nearest integer, rather than rounding it down +- like the normal cast does. +-*/ +-inline int roundFloatToInt (const float value) throw() +-{ +- union { int asInt[2]; double asDouble; } n; +- n.asDouble = value + 6755399441055744.0; +- +-#if JUCE_BIG_ENDIAN +- return n.asInt [1]; +-#else +- return n.asInt [0]; +-#endif +-} +- +- +-#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__ ++/* ++ ============================================================================== ++ ++ This file is part of the JUCE library - "Jules' Utility Class Extensions" ++ Copyright 2004-6 by Raw Material Software ltd. ++ ++ ------------------------------------------------------------------------------ ++ ++ JUCE can be redistributed and/or modified under the terms of the ++ GNU General Public License, as published by the Free Software Foundation; ++ either version 2 of the License, or (at your option) any later version. ++ ++ JUCE is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with JUCE; if not, visit www.gnu.org/licenses or write to the ++ Free Software Foundation, Inc., 59 Temple Place, Suite 330, ++ Boston, MA 02111-1307 USA ++ ++ ------------------------------------------------------------------------------ ++ ++ If you'd like to release a closed-source product which uses JUCE, commercial ++ licenses are also available: visit www.rawmaterialsoftware.com/juce for ++ more information. ++ ++ ============================================================================== ++*/ ++ ++#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__ ++#define __JUCE_DATACONVERSIONS_JUCEHEADER__ ++ ++#include "juce_PlatformDefs.h" ++ ++//============================================================================== ++// Endianness conversions.. ++ ++/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */ ++inline_assembly uint32 swapByteOrder (uint32 n) throw() ++{ ++#ifdef JUCE_MAC ++ return CFSwapInt32 (n); ++#else ++ #ifdef __GNUC__ ++ #ifndef __x86__ ++ return ( ((n)&0xff)<<24) | (((n)&0xff00)<<8) | (((n)>>8)&0xff00) | (((n)>>24)&0xff); ++ #else ++ // Inpenetrable GCC version.. ++ asm("bswap %%eax" : "=a"(n) : "a"(n)); ++ return n; ++ #endif ++ #else ++ // Win32 version.. ++ __asm { ++ mov eax, n ++ bswap eax ++ mov n, eax ++ } ++ return n; ++ #endif ++#endif ++} ++ ++/** Swaps the byte-order of a 16-bit short. */ ++inline uint16 swapByteOrder (const uint16 n) throw() ++{ ++ return (uint16) ((n << 8) | (n >> 8)); ++} ++ ++inline uint64 swapByteOrder (const uint64 value) throw() ++{ ++#ifdef JUCE_MAC ++ return CFSwapInt64 (value); ++#else ++ return (((int64) swapByteOrder ((uint32) value)) << 32) ++ | swapByteOrder ((uint32) (value >> 32)); ++#endif ++} ++ ++#ifdef JUCE_LITTLE_ENDIAN ++ /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ ++ inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; } ++ /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ ++ inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; } ++ /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ ++ inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); } ++ /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ ++ inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); } ++ ++ /** Turns 4 bytes into a little-endian integer. */ ++ inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } ++ ++ /** Turns 2 bytes into a little-endian integer. */ ++ inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } ++ ++ /** Turns 4 bytes into a big-endian integer. */ ++ inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } ++ ++ /** Turns 2 bytes into a big-endian integer. */ ++ inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } ++ ++#else ++ /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ ++ inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); } ++ /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ ++ inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); } ++ /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ ++ inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; } ++ /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ ++ inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; } ++ ++ /** Turns 4 bytes into a little-endian integer. */ ++ inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } ++ ++ /** Turns 2 bytes into a little-endian integer. */ ++ inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } ++ ++ /** Turns 4 bytes into a big-endian integer. */ ++ inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } ++ ++ /** Turns 2 bytes into a big-endian integer. */ ++ inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } ++#endif ++ ++/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ ++inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } ++/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ ++inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } ++ ++/** Copies a 24-bit number to 3 little-endian bytes. */ ++inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } ++/** Copies a 24-bit number to 3 big-endian bytes. */ ++inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } ++ ++ ++//============================================================================== ++/** Fast floating-point-to-integer conversion. ++ ++ This is faster than using the normal c++ cast to convert a double to an int, and ++ it will round the value to the nearest integer, rather than rounding it down ++ like the normal cast does. ++*/ ++inline int roundDoubleToInt (const double value) throw() ++{ ++ union { int asInt[2]; double asDouble; } n; ++ n.asDouble = value + 6755399441055744.0; ++ ++#if JUCE_BIG_ENDIAN ++ return n.asInt [1]; ++#else ++ return n.asInt [0]; ++#endif ++} ++ ++/** Fast floating-point-to-integer conversion. ++ ++ This is faster than using the normal c++ cast to convert a float to an int, and ++ it will round the value to the nearest integer, rather than rounding it down ++ like the normal cast does. ++*/ ++inline int roundFloatToInt (const float value) throw() ++{ ++ union { int asInt[2]; double asDouble; } n; ++ n.asDouble = value + 6755399441055744.0; ++ ++#if JUCE_BIG_ENDIAN ++ return n.asInt [1]; ++#else ++ return n.asInt [0]; ++#endif ++} ++ ++ ++#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__ +--- juce/build/linux/platform_specific_code/juce_linux_SystemStats.cpp~remove-x86isms.patch ++++ juce/build/linux/platform_specific_code/juce_linux_SystemStats.cpp +@@ -1,472 +1,472 @@ +-/* +- ============================================================================== +- +- This file is part of the JUCE library - "Jules' Utility Class Extensions" +- Copyright 2004-6 by Raw Material Software ltd. +- +- ------------------------------------------------------------------------------ +- +- JUCE can be redistributed and/or modified under the terms of the +- GNU General Public License, as published by the Free Software Foundation; +- either version 2 of the License, or (at your option) any later version. +- +- JUCE is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with JUCE; if not, visit www.gnu.org/licenses or write to the +- Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- Boston, MA 02111-1307 USA +- +- ------------------------------------------------------------------------------ +- +- If you'd like to release a closed-source product which uses JUCE, commercial +- licenses are also available: visit www.rawmaterialsoftware.com/juce for +- more information. +- +- ============================================================================== +-*/ +- +-#include "linuxincludes.h" +-#include "../../../src/juce_core/basics/juce_StandardHeader.h" +- +-#ifdef __CYGWIN__ +- #include +- #include +-#else +- #include +- #include +-#endif +- +-#ifdef JUCE_UUID +- #include +-#endif +- +-#ifndef CPU_ISSET +- #undef SUPPORT_AFFINITIES +-#endif +- +-BEGIN_JUCE_NAMESPACE +- +-#include "../../../src/juce_core/io/files/juce_File.h" +-#include "../../../src/juce_core/basics/juce_SystemStats.h" +-#include "../../../src/juce_core/basics/juce_Logger.h" +-#include "../../../src/juce_core/misc/juce_Uuid.h" +-#include "../../../src/juce_core/threads/juce_Process.h" +-#include "../../../src/juce_appframework/events/juce_Timer.h" +-#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" +- +-static struct _LogicalCpuInfo +-{ +- bool htSupported; +- bool htAvailable; +- int numPackages; +- int numLogicalPerPackage; +- uint32 physicalAffinityMask; +-} logicalCpuInfo; +- +-//============================================================================== +-static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) __attribute__ ((noinline)); +- +-static unsigned int getCPUIDWord (int* familyModel, int* extFeatures) +-{ +- unsigned int cpu = 0; +- unsigned int ext = 0; +- unsigned int family = 0; +- +- __asm__ __volatile__ ( +-" pushf \n" +-#if JUCE_64BIT +-" pop %%rax \n" +-#else +-" pop %%eax \n" +-#endif +-" movl %%eax, %%ecx \n" +-" xorl $0x200000, %%eax \n" +-#if JUCE_64BIT +-" push %%rax \n" +-#else +-" push %%eax \n" +-#endif +-" popf \n" +-" pushf \n" +-#if JUCE_64BIT +-" pop %%rax \n" +-#else +-" pop %%eax \n" +-#endif +-" andl $0x200000, %%eax \n" +-" andl $0x200000, %%ecx \n" +-" cmpl %%eax, %%ecx \n" +-" movl $0, %%edx \n" +-" je noCpuId \n" +-" movl $1, %%eax \n" +-" cpuid \n" +-"noCpuId: \n" +- : "=a"(family), /* Output in eax */ +- "=d"(cpu), /* Output in ebx */ +- "=b"(ext) /* Output in edx */ +- : /* No inputs */ +- : "cc", "ecx" /* Clobber list */ +- ); +- +- if (familyModel) +- *familyModel = family; +- if (extFeatures) +- *extFeatures = ext; +- +- return cpu; +-} +- +-void juce_initLogicalCpuInfo() +-{ +- int familyModelWord, extFeaturesWord; +- int featuresWord = getCPUIDWord (&familyModelWord, &extFeaturesWord); +- +- logicalCpuInfo.htSupported = false; +- logicalCpuInfo.htAvailable = false; +- logicalCpuInfo.numLogicalPerPackage = 1; +- logicalCpuInfo.numPackages = 0; +- logicalCpuInfo.physicalAffinityMask = 0; +- +-#if SUPPORT_AFFINITIES +- cpu_set_t processAffinity; +- +- /* +- N.B. If this line causes a compile error, then you've probably not got the latest +- version of glibc installed. +- +- If you don't want to update your copy of glibc and don't care about cpu affinities, +- then you can just disable all this stuff by removing the SUPPORT_AFFINITIES macro +- from the linuxincludes.h file. +- */ +- if (sched_getaffinity (getpid(), +- sizeof (cpu_set_t), +- &processAffinity) != sizeof (cpu_set_t)) +- { +- return; +- } +- +- // Checks: CPUID supported, model >= Pentium 4, Hyperthreading bit set, logical CPUs per package > 1 +- if (featuresWord == 0 +- || ((familyModelWord >> 8) & 0xf) < 15 +- || (featuresWord & (1 << 28)) == 0 +- || ((extFeaturesWord >> 16) & 0xff) < 2) +- { +- for (int i = 0; i < 64; ++i) +- if (CPU_ISSET (i, &processAffinity)) +- logicalCpuInfo.physicalAffinityMask |= (1 << i); +- +- return; +- } +- +- logicalCpuInfo.htSupported = true; +- logicalCpuInfo.numLogicalPerPackage = (extFeaturesWord >> 16) & 0xff; +- +- cpu_set_t affinityMask; +- cpu_set_t physAff; +- CPU_ZERO (&physAff); +- +- unsigned char i = 1; +- unsigned char physIdMask = 0xFF; +- unsigned char physIdShift = 0; +- +- //unsigned char apicId, logId, physId; +- +- while (i < logicalCpuInfo.numLogicalPerPackage) +- { +- i *= 2; +- physIdMask <<= 1; +- physIdShift++; +- } +- +- CPU_SET (0, &affinityMask); +- logicalCpuInfo.numPackages = 0; +- +-//xxx revisit this at some point.. +-/* while ((affinityMask != 0) && (affinityMask <= processAffinity)) +- { +- int ret; +- if (! sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinityMask)) +- { +- sched_yield(); // schedule onto correct CPU +- +- featuresWord = getCPUIDWord(&familyModelWord, &extFeaturesWord); +- apicId = (unsigned char)(extFeaturesWord >> 24); +- logId = (unsigned char)(apicId & ~physIdMask); +- physId = (unsigned char)(apicId >> physIdShift); +- +- if (logId != 0) +- logicalCpuInfo.htAvailable = true; +- +- if ((((int)logId) % logicalCpuInfo.numLogicalPerPackage) == 0) +- { +- // This is a physical CPU +- physAff |= affinityMask; +- logicalCpuInfo.numPackages++; +- } +- } +- +- affinityMask = affinityMask << 1; +- } +- +- sched_setaffinity (getpid(), sizeof(unsigned long), &processAffinity); +-*/ +- +- logicalCpuInfo.physicalAffinityMask = 0; +- +- for (int i = 0; i < 64; ++i) +- if (CPU_ISSET (i, &physAff)) +- logicalCpuInfo.physicalAffinityMask |= (1 << i); +- +-#endif +-} +- +-//============================================================================== +-void Logger::outputDebugString (const String& text) +-{ +- fprintf (stdout, (const char*) (text + T("\n"))); +-} +- +-void Logger::outputDebugPrintf (const tchar* format, ...) +-{ +- String text; +- va_list args; +- va_start (args, format); +- text.vprintf(format, args); +- outputDebugString(text); +-} +- +-const String SystemStats::getOSType() +-{ +- return SystemStats::Linux; +-} +- +-static const String getCpuInfo (const char* key, bool lastOne = false) +-{ +- String info; +- char buf [256]; +- +- FILE* f = fopen ("/proc/cpuinfo", "r"); +- +- while (f != 0 && fgets (buf, sizeof(buf), f)) +- { +- if (strncmp (buf, key, strlen (key)) == 0) +- { +- char* p = buf; +- +- while (*p && *p != '\n') +- ++p; +- +- if (*p != 0) +- *p = 0; +- +- p = buf; +- +- while (*p != 0 && *p != ':') +- ++p; +- +- if (*p != 0 && *(p + 1) != 0) +- info = p + 2; +- +- if (! lastOne) +- break; +- } +- } +- +- fclose (f); +- return info; +-} +- +-bool SystemStats::hasMMX() +-{ +- return getCpuInfo ("flags").contains (T("mmx")); +-} +- +-bool SystemStats::hasSSE() +-{ +- return getCpuInfo ("flags").contains (T("sse")); +-} +- +-bool SystemStats::hasSSE2() +-{ +- return getCpuInfo ("flags").contains (T("sse2")); +-} +- +-bool SystemStats::has3DNow() +-{ +- return getCpuInfo ("flags").contains (T("3dnow")); +-} +- +-const String SystemStats::getCpuVendor() +-{ +- return getCpuInfo ("vendor_id"); +-} +- +-int SystemStats::getCpuSpeedInMegaherz() +-{ +- const String speed (getCpuInfo ("cpu MHz")); +- +- return (int) (speed.getFloatValue() + 0.5f); +-} +- +-bool SystemStats::hasHyperThreading() +-{ +- return logicalCpuInfo.htAvailable; +-} +- +-int SystemStats::getMemorySizeInMegabytes() +-{ +-#ifndef __CYGWIN__ +- struct sysinfo sysi; +- +- if (sysinfo (&sysi) == 0) +- return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); +- +- return 0; +- +-#else +- jassertfalse +- return 256; +-#endif +-} +- +-unsigned int juce_millisecondsSinceStartup() +-{ +- static unsigned int calibrate = 0; +- static bool calibrated = false; +- timeval t; +- unsigned int ret = 0; +- +- if (! gettimeofday (&t, 0)) +- { +- if (! calibrated) +- { +-#ifndef __CYGWIN__ +- struct sysinfo sysi; +- +- if (sysinfo (&sysi) == 0) +- // Safe to assume system was not brought up earlier than 1970! +- calibrate = t.tv_sec - sysi.uptime; +-#else +- // bit of a hack, but things should all still work, as we're not often +- // really interested in how long the machine's been turned on, and just +- // use this call for relative times.. +- calibrate = t.tv_sec; +-#endif +- +- calibrated = true; +- } +- +- ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000); +- } +- +- return ret; +-} +- +-double juce_millisecondsSinceStartupHiRes() +-{ +- return Time::getHighResolutionTicks() * (1.0 / 1000000.0); +-} +- +-int64 Time::getHighResolutionTicks() +-{ +- timeval t; +- if (gettimeofday(&t,NULL)) +- return 0; +- +- return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; +-} +- +-int64 Time::getHighResolutionTicksPerSecond() +-{ +- // Microseconds +- return 1000000; +-} +- +-bool Time::setSystemTimeToThisTime() const +-{ +- timeval t; +- t.tv_sec = millisSinceEpoch % 1000000; +- t.tv_usec = millisSinceEpoch - t.tv_sec; +- +- return settimeofday (&t, NULL) ? false : true; +-} +- +-const String Uuid::generateUuid() +-{ +-#ifdef JUCE_UUID +- uuid_t uuid; +- char *s = new char[37]; +- String uuidStr; +- +- uuid_generate (uuid); +- uuid_unparse (uuid, s); +- +- uuidStr = s; +- delete[] s; +- +- return uuidStr; +-#else +- jassertfalse +- return String::empty; +-#endif +-} +- +-int SystemStats::getPageSize() +-{ +- static int systemPageSize = 0; +- +- if (systemPageSize == 0) +- systemPageSize = sysconf (_SC_PAGESIZE); +- +- return systemPageSize; +-} +- +-int SystemStats::getNumPhysicalCpus() +-{ +- if (logicalCpuInfo.numPackages) +- return logicalCpuInfo.numPackages; +- +- return getNumLogicalCpus(); +-} +- +-int SystemStats::getNumLogicalCpus() +-{ +- const int lastCpu = getCpuInfo ("processor", true).getIntValue(); +- +- return lastCpu + 1; +-} +- +-uint32 SystemStats::getPhysicalAffinityMask() +-{ +-#if SUPPORT_AFFINITIES +- return logicalCpuInfo.physicalAffinityMask; +-#else +- /* affinities aren't supported because either the appropriate header files weren't found, +- or the SUPPORT_AFFINITIES macro was turned off in linuxheaders.h +- */ +- jassertfalse +- return 0; +-#endif +- +-} +- +-//============================================================================== +-void SystemStats::initialiseStats() +-{ +- // Process starts off as root when running suid +- Process::lowerPrivilege(); +- +- String s (SystemStats::getJUCEVersion()); +- +- juce_initLogicalCpuInfo(); +-} +- +-void PlatformUtilities::fpuReset() +-{ +-} +- +-END_JUCE_NAMESPACE ++/* ++ ============================================================================== ++ ++ This file is part of the JUCE library - "Jules' Utility Class Extensions" ++ Copyright 2004-6 by Raw Material Software ltd. ++ ++ ------------------------------------------------------------------------------ ++ ++ JUCE can be redistributed and/or modified under the terms of the ++ GNU General Public License, as published by the Free Software Foundation; ++ either version 2 of the License, or (at your option) any later version. ++ ++ JUCE is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with JUCE; if not, visit www.gnu.org/licenses or write to the ++ Free Software Foundation, Inc., 59 Temple Place, Suite 330, ++ Boston, MA 02111-1307 USA ++ ++ ------------------------------------------------------------------------------ ++ ++ If you'd like to release a closed-source product which uses JUCE, commercial ++ licenses are also available: visit www.rawmaterialsoftware.com/juce for ++ more information. ++ ++ ============================================================================== ++*/ ++ ++#include "linuxincludes.h" ++#include "../../../src/juce_core/basics/juce_StandardHeader.h" ++ ++#ifdef __CYGWIN__ ++ #include ++ #include ++#else ++ #include ++ #include ++#endif ++ ++#ifdef JUCE_UUID ++ #include ++#endif ++ ++#ifndef CPU_ISSET ++ #undef SUPPORT_AFFINITIES ++#endif ++ ++BEGIN_JUCE_NAMESPACE ++ ++#include "../../../src/juce_core/io/files/juce_File.h" ++#include "../../../src/juce_core/basics/juce_SystemStats.h" ++#include "../../../src/juce_core/basics/juce_Logger.h" ++#include "../../../src/juce_core/misc/juce_Uuid.h" ++#include "../../../src/juce_core/threads/juce_Process.h" ++#include "../../../src/juce_appframework/events/juce_Timer.h" ++#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" ++ ++static struct _LogicalCpuInfo ++{ ++ bool htSupported; ++ bool htAvailable; ++ int numPackages; ++ int numLogicalPerPackage; ++ uint32 physicalAffinityMask; ++} logicalCpuInfo; ++ ++//============================================================================== ++static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) __attribute__ ((noinline)); ++ ++static unsigned int getCPUIDWord (int* familyModel, int* extFeatures) ++{ ++ unsigned int cpu = 0; ++ unsigned int ext = 0; ++ unsigned int family = 0; ++#ifdef __x86__ ++ __asm__ __volatile__ ( ++" pushf \n" ++#if JUCE_64BIT ++" pop %%rax \n" ++#else ++" pop %%eax \n" ++#endif ++" movl %%eax, %%ecx \n" ++" xorl $0x200000, %%eax \n" ++#if JUCE_64BIT ++" push %%rax \n" ++#else ++" push %%eax \n" ++#endif ++" popf \n" ++" pushf \n" ++#if JUCE_64BIT ++" pop %%rax \n" ++#else ++" pop %%eax \n" ++#endif ++" andl $0x200000, %%eax \n" ++" andl $0x200000, %%ecx \n" ++" cmpl %%eax, %%ecx \n" ++" movl $0, %%edx \n" ++" je noCpuId \n" ++" movl $1, %%eax \n" ++" cpuid \n" ++"noCpuId: \n" ++ : "=a"(family), /* Output in eax */ ++ "=d"(cpu), /* Output in ebx */ ++ "=b"(ext) /* Output in edx */ ++ : /* No inputs */ ++ : "cc", "ecx" /* Clobber list */ ++ ); ++#endif ++ if (familyModel) ++ *familyModel = family; ++ if (extFeatures) ++ *extFeatures = ext; ++ ++ return cpu; ++} ++ ++void juce_initLogicalCpuInfo() ++{ ++ int familyModelWord, extFeaturesWord; ++ int featuresWord = getCPUIDWord (&familyModelWord, &extFeaturesWord); ++ ++ logicalCpuInfo.htSupported = false; ++ logicalCpuInfo.htAvailable = false; ++ logicalCpuInfo.numLogicalPerPackage = 1; ++ logicalCpuInfo.numPackages = 0; ++ logicalCpuInfo.physicalAffinityMask = 0; ++ ++#if SUPPORT_AFFINITIES ++ cpu_set_t processAffinity; ++ ++ /* ++ N.B. If this line causes a compile error, then you've probably not got the latest ++ version of glibc installed. ++ ++ If you don't want to update your copy of glibc and don't care about cpu affinities, ++ then you can just disable all this stuff by removing the SUPPORT_AFFINITIES macro ++ from the linuxincludes.h file. ++ */ ++ if (sched_getaffinity (getpid(), ++ sizeof (cpu_set_t), ++ &processAffinity) != sizeof (cpu_set_t)) ++ { ++ return; ++ } ++ ++ // Checks: CPUID supported, model >= Pentium 4, Hyperthreading bit set, logical CPUs per package > 1 ++ if (featuresWord == 0 ++ || ((familyModelWord >> 8) & 0xf) < 15 ++ || (featuresWord & (1 << 28)) == 0 ++ || ((extFeaturesWord >> 16) & 0xff) < 2) ++ { ++ for (int i = 0; i < 64; ++i) ++ if (CPU_ISSET (i, &processAffinity)) ++ logicalCpuInfo.physicalAffinityMask |= (1 << i); ++ ++ return; ++ } ++ ++ logicalCpuInfo.htSupported = true; ++ logicalCpuInfo.numLogicalPerPackage = (extFeaturesWord >> 16) & 0xff; ++ ++ cpu_set_t affinityMask; ++ cpu_set_t physAff; ++ CPU_ZERO (&physAff); ++ ++ unsigned char i = 1; ++ unsigned char physIdMask = 0xFF; ++ unsigned char physIdShift = 0; ++ ++ //unsigned char apicId, logId, physId; ++ ++ while (i < logicalCpuInfo.numLogicalPerPackage) ++ { ++ i *= 2; ++ physIdMask <<= 1; ++ physIdShift++; ++ } ++ ++ CPU_SET (0, &affinityMask); ++ logicalCpuInfo.numPackages = 0; ++ ++//xxx revisit this at some point.. ++/* while ((affinityMask != 0) && (affinityMask <= processAffinity)) ++ { ++ int ret; ++ if (! sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinityMask)) ++ { ++ sched_yield(); // schedule onto correct CPU ++ ++ featuresWord = getCPUIDWord(&familyModelWord, &extFeaturesWord); ++ apicId = (unsigned char)(extFeaturesWord >> 24); ++ logId = (unsigned char)(apicId & ~physIdMask); ++ physId = (unsigned char)(apicId >> physIdShift); ++ ++ if (logId != 0) ++ logicalCpuInfo.htAvailable = true; ++ ++ if ((((int)logId) % logicalCpuInfo.numLogicalPerPackage) == 0) ++ { ++ // This is a physical CPU ++ physAff |= affinityMask; ++ logicalCpuInfo.numPackages++; ++ } ++ } ++ ++ affinityMask = affinityMask << 1; ++ } ++ ++ sched_setaffinity (getpid(), sizeof(unsigned long), &processAffinity); ++*/ ++ ++ logicalCpuInfo.physicalAffinityMask = 0; ++ ++ for (int i = 0; i < 64; ++i) ++ if (CPU_ISSET (i, &physAff)) ++ logicalCpuInfo.physicalAffinityMask |= (1 << i); ++ ++#endif ++} ++ ++//============================================================================== ++void Logger::outputDebugString (const String& text) ++{ ++ fprintf (stdout, (const char*) (text + T("\n"))); ++} ++ ++void Logger::outputDebugPrintf (const tchar* format, ...) ++{ ++ String text; ++ va_list args; ++ va_start (args, format); ++ text.vprintf(format, args); ++ outputDebugString(text); ++} ++ ++const String SystemStats::getOSType() ++{ ++ return SystemStats::Linux; ++} ++ ++static const String getCpuInfo (const char* key, bool lastOne = false) ++{ ++ String info; ++ char buf [256]; ++ ++ FILE* f = fopen ("/proc/cpuinfo", "r"); ++ ++ while (f != 0 && fgets (buf, sizeof(buf), f)) ++ { ++ if (strncmp (buf, key, strlen (key)) == 0) ++ { ++ char* p = buf; ++ ++ while (*p && *p != '\n') ++ ++p; ++ ++ if (*p != 0) ++ *p = 0; ++ ++ p = buf; ++ ++ while (*p != 0 && *p != ':') ++ ++p; ++ ++ if (*p != 0 && *(p + 1) != 0) ++ info = p + 2; ++ ++ if (! lastOne) ++ break; ++ } ++ } ++ ++ fclose (f); ++ return info; ++} ++ ++bool SystemStats::hasMMX() ++{ ++ return getCpuInfo ("flags").contains (T("mmx")); ++} ++ ++bool SystemStats::hasSSE() ++{ ++ return getCpuInfo ("flags").contains (T("sse")); ++} ++ ++bool SystemStats::hasSSE2() ++{ ++ return getCpuInfo ("flags").contains (T("sse2")); ++} ++ ++bool SystemStats::has3DNow() ++{ ++ return getCpuInfo ("flags").contains (T("3dnow")); ++} ++ ++const String SystemStats::getCpuVendor() ++{ ++ return getCpuInfo ("vendor_id"); ++} ++ ++int SystemStats::getCpuSpeedInMegaherz() ++{ ++ const String speed (getCpuInfo ("cpu MHz")); ++ ++ return (int) (speed.getFloatValue() + 0.5f); ++} ++ ++bool SystemStats::hasHyperThreading() ++{ ++ return logicalCpuInfo.htAvailable; ++} ++ ++int SystemStats::getMemorySizeInMegabytes() ++{ ++#ifndef __CYGWIN__ ++ struct sysinfo sysi; ++ ++ if (sysinfo (&sysi) == 0) ++ return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); ++ ++ return 0; ++ ++#else ++ jassertfalse ++ return 256; ++#endif ++} ++ ++unsigned int juce_millisecondsSinceStartup() ++{ ++ static unsigned int calibrate = 0; ++ static bool calibrated = false; ++ timeval t; ++ unsigned int ret = 0; ++ ++ if (! gettimeofday (&t, 0)) ++ { ++ if (! calibrated) ++ { ++#ifndef __CYGWIN__ ++ struct sysinfo sysi; ++ ++ if (sysinfo (&sysi) == 0) ++ // Safe to assume system was not brought up earlier than 1970! ++ calibrate = t.tv_sec - sysi.uptime; ++#else ++ // bit of a hack, but things should all still work, as we're not often ++ // really interested in how long the machine's been turned on, and just ++ // use this call for relative times.. ++ calibrate = t.tv_sec; ++#endif ++ ++ calibrated = true; ++ } ++ ++ ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000); ++ } ++ ++ return ret; ++} ++ ++double juce_millisecondsSinceStartupHiRes() ++{ ++ return Time::getHighResolutionTicks() * (1.0 / 1000000.0); ++} ++ ++int64 Time::getHighResolutionTicks() ++{ ++ timeval t; ++ if (gettimeofday(&t,NULL)) ++ return 0; ++ ++ return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; ++} ++ ++int64 Time::getHighResolutionTicksPerSecond() ++{ ++ // Microseconds ++ return 1000000; ++} ++ ++bool Time::setSystemTimeToThisTime() const ++{ ++ timeval t; ++ t.tv_sec = millisSinceEpoch % 1000000; ++ t.tv_usec = millisSinceEpoch - t.tv_sec; ++ ++ return settimeofday (&t, NULL) ? false : true; ++} ++ ++const String Uuid::generateUuid() ++{ ++#ifdef JUCE_UUID ++ uuid_t uuid; ++ char *s = new char[37]; ++ String uuidStr; ++ ++ uuid_generate (uuid); ++ uuid_unparse (uuid, s); ++ ++ uuidStr = s; ++ delete[] s; ++ ++ return uuidStr; ++#else ++ jassertfalse ++ return String::empty; ++#endif ++} ++ ++int SystemStats::getPageSize() ++{ ++ static int systemPageSize = 0; ++ ++ if (systemPageSize == 0) ++ systemPageSize = sysconf (_SC_PAGESIZE); ++ ++ return systemPageSize; ++} ++ ++int SystemStats::getNumPhysicalCpus() ++{ ++ if (logicalCpuInfo.numPackages) ++ return logicalCpuInfo.numPackages; ++ ++ return getNumLogicalCpus(); ++} ++ ++int SystemStats::getNumLogicalCpus() ++{ ++ const int lastCpu = getCpuInfo ("processor", true).getIntValue(); ++ ++ return lastCpu + 1; ++} ++ ++uint32 SystemStats::getPhysicalAffinityMask() ++{ ++#if SUPPORT_AFFINITIES ++ return logicalCpuInfo.physicalAffinityMask; ++#else ++ /* affinities aren't supported because either the appropriate header files weren't found, ++ or the SUPPORT_AFFINITIES macro was turned off in linuxheaders.h ++ */ ++ jassertfalse ++ return 0; ++#endif ++ ++} ++ ++//============================================================================== ++void SystemStats::initialiseStats() ++{ ++ // Process starts off as root when running suid ++ Process::lowerPrivilege(); ++ ++ String s (SystemStats::getJUCEVersion()); ++ ++ juce_initLogicalCpuInfo(); ++} ++ ++void PlatformUtilities::fpuReset() ++{ ++} ++ ++END_JUCE_NAMESPACE diff --git a/packages/juce/juce_1.29.bb b/packages/juce/juce_1.29.bb new file mode 100644 index 0000000000..0127a355a0 --- /dev/null +++ b/packages/juce/juce_1.29.bb @@ -0,0 +1,34 @@ +DESCRIPTION = "JUCE is a cross-platform application framework" +HOMEPAGE = "http://www.rawmaterialsoftware.com/juce" +AUTHOR = "Julian Stoerer" +MAINTAINER = "Michael 'Mickey' Lauer " +LICENSE = "GPL" +DEPENDS = "alsa-lib freetype x11" +PR = "r0" + +#FIXME the patches are a) HACKS and b) something's wrong with lineend conversion +SRC_URI = "http://www.rawmaterialsoftware.com/juce/downloads/juce_1_29.zip \ + file://remove-x86isms.patch;patch=1 \ + file://no-opengl.patch;patch=1" +S = "${WORKDIR}/juce" + +LIB = "libjuce_debug" + +do_compile() { + cd ${S}/build/linux && oe_runmake + cd ${S}/demo/build/linux && oe_runmake +} + +do_stage() { + oe_libinstall -a -C bin ${LIB} ${STAGING_LIBDIR} + #FIXME add includes +} + +do_install() { + install -d ${D}${bindir} + install -m 0655 demo/build/linux/build/jucedemo ${D}${bindir} +} + +PACKAGES = "jucedemo" +FILES_jucedemo = "${bindir}" + -- cgit 1.2.3-korg