diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp index d3f2dca555..7724a63418 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp @@ -81,8 +81,6 @@ namespace Vst2 #include "pluginterfaces/vst2.x/aeffectx.h" } -using namespace juce; - JUCE_END_IGNORE_WARNINGS_MSVC JUCE_END_IGNORE_WARNINGS_GCC_LIKE @@ -92,8 +90,12 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE #endif #define JUCE_VSTINTERFACE_H_INCLUDED 1 +#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 #include "../utility/juce_IncludeModuleHeaders.h" + +using namespace juce; + #include "../utility/juce_FakeMouseMoveGenerator.h" #include "../utility/juce_WindowsHooks.h" @@ -1086,7 +1088,7 @@ public: #elif JUCE_LINUX addToDesktop (0, args.ptr); hostWindow = (Window) args.ptr; - XReparentWindow (display.display, (Window) getWindowHandle(), hostWindow, 0, 0); + X11Symbols::getInstance()->xReparentWindow (display.display, (Window) getWindowHandle(), hostWindow, 0, 0); #else hostWindow = attachComponentToWindowRefVST (this, args.ptr, wrapper.useNSView); #endif @@ -1195,9 +1197,9 @@ public: if (auto* peer = ed->getPeer()) scale *= (float) peer->getPlatformScaleFactor(); - XResizeWindow (display.display, (Window) getWindowHandle(), - static_cast (roundToInt (pos.getWidth() * scale)), - static_cast (roundToInt (pos.getHeight() * scale))); + X11Symbols::getInstance()->xResizeWindow (display.display, (Window) getWindowHandle(), + static_cast (roundToInt (pos.getWidth() * scale)), + static_cast (roundToInt (pos.getHeight() * scale))); #endif #if JUCE_MAC diff --git a/modules/juce_audio_plugin_client/utility/juce_IncludeSystemHeaders.h b/modules/juce_audio_plugin_client/utility/juce_IncludeSystemHeaders.h index ae57c538f1..54e57b9e8d 100644 --- a/modules/juce_audio_plugin_client/utility/juce_IncludeSystemHeaders.h +++ b/modules/juce_audio_plugin_client/utility/juce_IncludeSystemHeaders.h @@ -29,19 +29,10 @@ #ifdef __INTEL_COMPILER #pragma warning (disable : 1899) #endif - #elif JUCE_LINUX #include #include - #include - #include - #include - #undef Font - #undef KeyPress - #undef Drawable - #undef Time -#elif JUCE_ANDROID -#else +#elif JUCE_MAC || JUCE_IOS #if ! (defined (JUCE_SUPPORT_CARBON) || defined (__LP64__)) #define JUCE_SUPPORT_CARBON 1 #endif diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 82ab4dfa15..d0ba7cb888 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -239,7 +239,7 @@ namespace { ScopedXDisplay xDisplay; - XQueryTree (xDisplay.display, windowToCheck, &rootWindow, &parentWindow, &childWindows, &numChildren); + X11Symbols::getInstance()->xQueryTree (xDisplay.display, windowToCheck, &rootWindow, &parentWindow, &childWindows, &numChildren); } if (numChildren > 0) @@ -2836,8 +2836,9 @@ public: { auto clip = g.getClipBounds(); - XClearArea (display, pluginWindow, clip.getX(), clip.getY(), - static_cast (clip.getWidth()), static_cast (clip.getHeight()), True); + X11Symbols::getInstance()->xClearArea (display, pluginWindow, clip.getX(), clip.getY(), + static_cast (clip.getWidth()), + static_cast (clip.getHeight()), True); } #endif } @@ -2875,13 +2876,13 @@ public: #elif JUCE_LINUX if (pluginWindow != 0) { - XMoveResizeWindow (display, pluginWindow, - pos.getX(), pos.getY(), - static_cast (roundToInt (getWidth() * nativeScaleFactor)), - static_cast (roundToInt (getHeight() * nativeScaleFactor))); + X11Symbols::getInstance()->xMoveResizeWindow (display, pluginWindow, + pos.getX(), pos.getY(), + static_cast (roundToInt (getWidth() * nativeScaleFactor)), + static_cast (roundToInt (getHeight() * nativeScaleFactor))); - XMapRaised (display, pluginWindow); - XFlush (display); + X11Symbols::getInstance()->xMapRaised (display, pluginWindow); + X11Symbols::getInstance()->xFlush (display); } #endif @@ -3160,7 +3161,7 @@ private: } if (pluginWindow != 0) - XMapRaised (display, pluginWindow); + X11Symbols::getInstance()->xMapRaised (display, pluginWindow); #endif w = roundToInt (w / nativeScaleFactor); diff --git a/modules/juce_audio_processors/juce_audio_processors.cpp b/modules/juce_audio_processors/juce_audio_processors.cpp index b1c1697aab..aa1e360f9d 100644 --- a/modules/juce_audio_processors/juce_audio_processors.cpp +++ b/modules/juce_audio_processors/juce_audio_processors.cpp @@ -27,6 +27,7 @@ #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 #define JUCE_CORE_INCLUDE_OBJC_HELPERS 1 +#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 #include "juce_audio_processors.h" #include diff --git a/modules/juce_graphics/juce_graphics.h b/modules/juce_graphics/juce_graphics.h index 0f582725ce..10ea2cbf08 100644 --- a/modules/juce_graphics/juce_graphics.h +++ b/modules/juce_graphics/juce_graphics.h @@ -37,7 +37,7 @@ dependencies: juce_events OSXFrameworks: Cocoa QuartzCore iOSFrameworks: CoreGraphics CoreImage CoreText QuartzCore - linuxPackages: x11 xinerama xext freetype2 + linuxPackages: freetype2 END_JUCE_MODULE_DECLARATION diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp index 63eaff86a9..057c8505d6 100644 --- a/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/modules/juce_gui_basics/juce_gui_basics.cpp @@ -33,6 +33,7 @@ #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 #define JUCE_EVENTS_INCLUDE_WIN32_MESSAGE_WINDOW 1 #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 +#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 #include "juce_gui_basics.h" @@ -79,48 +80,6 @@ #pragma comment (lib, "D2d1.lib") #endif #endif - -//============================================================================== -#elif JUCE_LINUX - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #if JUCE_USE_XRANDR - /* If you're trying to use Xrandr, you'll need to install the "libxrandr-dev" package.. */ - #include - #endif - - #if JUCE_USE_XINERAMA - /* If you're trying to use Xinerama, you'll need to install the "libxinerama-dev" package.. */ - #include - #endif - - #if JUCE_USE_XSHM - #include - #include - #include - #endif - - #if JUCE_USE_XRENDER - // If you're missing these headers, try installing the libxrender-dev and libxcomposite-dev - #include - #include - #endif - - #if JUCE_USE_XCURSOR - // If you're missing this header, try installing the libxcursor-dev package - #include - #endif - - #undef SIZEOF - #undef KeyPress #endif #include @@ -291,6 +250,7 @@ namespace juce #include "native/juce_win32_FileChooser.cpp" #elif JUCE_LINUX + #include "native/juce_linux_X11Symbols.cpp" #include "native/juce_linux_X11.cpp" #include "native/juce_linux_X11_Clipboard.cpp" diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index fdbca8d631..cf2e3dbf78 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -37,7 +37,6 @@ dependencies: juce_graphics juce_data_structures OSXFrameworks: Cocoa Carbon QuartzCore iOSFrameworks: UIKit MobileCoreServices - linuxPackages: x11 xinerama xext END_JUCE_MODULE_DECLARATION @@ -290,6 +289,51 @@ namespace juce #if JUCE_LINUX #include "native/juce_linux_X11.h" + + #if JUCE_GUI_BASICS_INCLUDE_XHEADERS + // If you're missing these headers, you need to install the libx11-dev package + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #if JUCE_USE_XRANDR + // If you're missing this header, you need to install the libxrandr-dev package + #include + #endif + + #if JUCE_USE_XINERAMA + // If you're missing this header, you need to install the libxinerama-dev package + #include + #endif + + #if JUCE_USE_XSHM + #include + #include + #include + #endif + + #if JUCE_USE_XRENDER + // If you're missing these headers, you need to install the libxrender-dev and libxcomposite-dev packages + #include + #include + #endif + + #if JUCE_USE_XCURSOR + // If you're missing this header, you need to install the libxcursor-dev package + #include + #endif + + #undef SIZEOF + #undef KeyPress + + #include "native/juce_linux_X11Symbols.h" + #endif #endif #include "layout/juce_FlexItem.h" diff --git a/modules/juce_gui_basics/native/juce_linux_X11.cpp b/modules/juce_gui_basics/native/juce_linux_X11.cpp index 9f4928c4d6..c24b660450 100644 --- a/modules/juce_gui_basics/native/juce_linux_X11.cpp +++ b/modules/juce_gui_basics/native/juce_linux_X11.cpp @@ -19,10 +19,11 @@ namespace juce { -typedef void (*WindowMessageReceiveCallback) (XEvent&); +//============================================================================== +using WindowMessageReceiveCallback = void (*) (XEvent&); WindowMessageReceiveCallback dispatchWindowMessage = nullptr; -typedef void (*SelectionRequestCallback) (XSelectionRequestEvent&); +using SelectionRequestCallback = void (*) (XSelectionRequestEvent&); SelectionRequestCallback handleSelectionRequest = nullptr; ::Window juce_messageWindowHandle; @@ -31,7 +32,7 @@ XContext windowHandleXContext; //============================================================================== namespace X11ErrorHandling { - static XErrorHandler oldErrorHandler = {}; + static XErrorHandler oldErrorHandler = {}; static XIOErrorHandler oldIOErrorHandler = {}; //============================================================================== @@ -52,11 +53,12 @@ namespace X11ErrorHandling ignoreUnused (display, event); #if JUCE_DEBUG_XERRORS - char errorStr[64] = { 0 }; + char errorStr[64] = { 0 }; char requestStr[64] = { 0 }; - XGetErrorText (display, event->error_code, errorStr, 64); - XGetErrorDatabaseText (display, "XRequest", String (event->request_code).toUTF8(), "Unknown", requestStr, 64); + X11Symbols::getInstance()->xGetErrorText (display, event->error_code, errorStr, 64); + X11Symbols::getInstance()->xGetErrorDatabaseText (display, "XRequest", String (event->request_code).toUTF8(), "Unknown", requestStr, 64); + DBG ("ERROR: X returned " << errorStr << " for operation " << requestStr); #endif @@ -65,35 +67,37 @@ namespace X11ErrorHandling void installXErrorHandlers() { - oldIOErrorHandler = XSetIOErrorHandler (ioErrorHandler); - oldErrorHandler = XSetErrorHandler (errorHandler); + oldIOErrorHandler = X11Symbols::getInstance()->xSetIOErrorHandler (ioErrorHandler); + oldErrorHandler = X11Symbols::getInstance()->xSetErrorHandler (errorHandler); } void removeXErrorHandlers() { - XSetIOErrorHandler (oldIOErrorHandler); + X11Symbols::getInstance()->xSetIOErrorHandler (oldIOErrorHandler); oldIOErrorHandler = {}; - XSetErrorHandler (oldErrorHandler); + X11Symbols::getInstance()->xSetErrorHandler (oldErrorHandler); oldErrorHandler = {}; } } -//============================================================================== XWindowSystem::XWindowSystem() noexcept { - if (JUCEApplicationBase::isStandaloneApp()) + xIsAvailable = X11Symbols::getInstance()->areXFunctionsAvailable(); + + if (JUCEApplicationBase::isStandaloneApp() && xIsAvailable) { // Initialise xlib for multiple thread support static bool initThreadCalled = false; if (! initThreadCalled) { - if (! XInitThreads()) + if (! X11Symbols::getInstance()->xInitThreads()) { // This is fatal! Print error and closedown Logger::outputDebugString ("Failed to initialise xlib thread support."); Process::terminate(); + return; } @@ -106,15 +110,18 @@ XWindowSystem::XWindowSystem() noexcept XWindowSystem::~XWindowSystem() noexcept { - if (JUCEApplicationBase::isStandaloneApp()) + if (JUCEApplicationBase::isStandaloneApp() && xIsAvailable) + { X11ErrorHandling::removeXErrorHandlers(); + X11Symbols::deleteInstance(); + } clearSingletonInstance(); } ::Display* XWindowSystem::displayRef() noexcept { - if (++displayCount == 1) + if (xIsAvailable && ++displayCount == 1) { jassert (display == nullptr); @@ -127,7 +134,7 @@ XWindowSystem::~XWindowSystem() noexcept // fail the first time, but succeed on a second attempt.. for (int retries = 2; --retries >= 0;) { - display = XOpenDisplay (displayName.toUTF8()); + display = X11Symbols::getInstance()->xOpenDisplay (displayName.toUTF8()); if (display != nullptr) break; @@ -141,14 +148,17 @@ XWindowSystem::~XWindowSystem() noexcept ::Display* XWindowSystem::displayUnref() noexcept { - jassert (display != nullptr); - jassert (displayCount.get() > 0); - - if (--displayCount == 0) + if (xIsAvailable) { - destroyXDisplay(); - XCloseDisplay (display); - display = nullptr; + jassert (display != nullptr); + jassert (displayCount.get() > 0); + + if (--displayCount == 0) + { + destroyXDisplay(); + X11Symbols::getInstance()->xCloseDisplay (display); + display = nullptr; + } } return display; @@ -156,76 +166,83 @@ XWindowSystem::~XWindowSystem() noexcept void XWindowSystem::initialiseXDisplay() noexcept { - // This is fatal! Print error and closedown - if (display == nullptr) + if (xIsAvailable) { - Logger::outputDebugString ("Failed to connect to the X Server."); - Process::terminate(); + // This is fatal! Print error and closedown + if (display == nullptr) + { + Logger::outputDebugString ("Failed to connect to the X Server."); + Process::terminate(); + } + + // Create a context to store user data associated with Windows we create + windowHandleXContext = (XContext) X11Symbols::getInstance()->xrmUniqueQuark(); + + // We're only interested in client messages for this window, which are always sent + XSetWindowAttributes swa; + swa.event_mask = NoEventMask; + + // Create our message window (this will never be mapped) + auto screen = X11Symbols::getInstance()->xDefaultScreen (display); + juce_messageWindowHandle = X11Symbols::getInstance()->xCreateWindow (display, X11Symbols::getInstance()->xRootWindow (display, screen), + 0, 0, 1, 1, 0, 0, InputOnly, + X11Symbols::getInstance()->xDefaultVisual (display, screen), + CWEventMask, &swa); + + X11Symbols::getInstance()->xSync (display, False); + + // Setup input event handler + LinuxEventLoop::registerFdCallback (X11Symbols::getInstance()->xConnectionNumber (display), + [this](int) + { + do + { + XEvent evt; + + { + ScopedXLock xlock (display); + + if (! X11Symbols::getInstance()->xPending (display)) + return; + + X11Symbols::getInstance()->xNextEvent (display, &evt); + } + + if (evt.type == SelectionRequest && evt.xany.window == juce_messageWindowHandle + && handleSelectionRequest != nullptr) + { + handleSelectionRequest (evt.xselectionrequest); + } + else if (evt.xany.window != juce_messageWindowHandle + && dispatchWindowMessage != nullptr) + { + dispatchWindowMessage (evt); + } + + } while (display != nullptr); + }); } - - // Create a context to store user data associated with Windows we create - windowHandleXContext = XUniqueContext(); - - // We're only interested in client messages for this window, which are always sent - XSetWindowAttributes swa; - swa.event_mask = NoEventMask; - - // Create our message window (this will never be mapped) - const int screen = DefaultScreen (display); - juce_messageWindowHandle = XCreateWindow (display, RootWindow (display, screen), - 0, 0, 1, 1, 0, 0, InputOnly, - DefaultVisual (display, screen), - CWEventMask, &swa); - - XSync (display, False); - - // Setup input event handler - int fd = XConnectionNumber (display); - - LinuxEventLoop::registerFdCallback (fd, - [this](int) - { - do - { - XEvent evt; - - { - ScopedXLock xlock (display); - - if (! XPending (display)) - return; - - XNextEvent (display, &evt); - } - - if (evt.type == SelectionRequest && evt.xany.window == juce_messageWindowHandle - && handleSelectionRequest != nullptr) - { - handleSelectionRequest (evt.xselectionrequest); - } - else if (evt.xany.window != juce_messageWindowHandle - && dispatchWindowMessage != nullptr) - { - dispatchWindowMessage (evt); - } - - } while (display != nullptr); - }); } void XWindowSystem::destroyXDisplay() noexcept { - ScopedXLock xlock (display); - XDestroyWindow (display, juce_messageWindowHandle); - juce_messageWindowHandle = 0; - XSync (display, True); - LinuxEventLoop::unregisterFdCallback (XConnectionNumber (display)); + if (xIsAvailable) + { + ScopedXLock xlock (display); + + X11Symbols::getInstance()->xDestroyWindow (display, juce_messageWindowHandle); + juce_messageWindowHandle = 0; + X11Symbols::getInstance()->xSync (display, True); + + LinuxEventLoop::unregisterFdCallback (X11Symbols::getInstance()->xConnectionNumber (display)); + } } JUCE_IMPLEMENT_SINGLETON (XWindowSystem) //============================================================================== -ScopedXDisplay::ScopedXDisplay() : display (XWindowSystem::getInstance()->displayRef()) +ScopedXDisplay::ScopedXDisplay() + : display (XWindowSystem::getInstance()->displayRef()) { } @@ -235,16 +252,17 @@ ScopedXDisplay::~ScopedXDisplay() } //============================================================================== -ScopedXLock::ScopedXLock (::Display* d) : display (d) +ScopedXLock::ScopedXLock (::Display* d) + : display (d) { if (display != nullptr) - XLockDisplay (display); + X11Symbols::getInstance()->xLockDisplay (display); } ScopedXLock::~ScopedXLock() { if (display != nullptr) - XUnlockDisplay (display); + X11Symbols::getInstance()->xUnlockDisplay (display); } //============================================================================== @@ -292,15 +310,15 @@ Atoms::Atoms (::Display* display) allowedActions[4] = XdndActionPrivate; } -Atom Atoms::getIfExists (::Display* display, const char* name) { return XInternAtom (display, name, True); } -Atom Atoms::getCreating (::Display* display, const char* name) { return XInternAtom (display, name, False); } +Atom Atoms::getIfExists (::Display* display, const char* name) { return X11Symbols::getInstance()->xInternAtom (display, name, True); } +Atom Atoms::getCreating (::Display* display, const char* name) { return X11Symbols::getInstance()->xInternAtom (display, name, False); } String Atoms::getName (::Display* display, const Atom atom) { if (atom == None) return "None"; - return String (XGetAtomName (display, atom)); + return X11Symbols::getInstance()->xGetAtomName (display, atom); } bool Atoms::isMimeTypeFile (::Display* display, const Atom atom) @@ -313,19 +331,19 @@ const unsigned long Atoms::DndVersion = 3; //============================================================================== GetXProperty::GetXProperty (::Display* display, Window window, Atom atom, - long offset, long length, bool shouldDelete, - Atom requestedType) + long offset, long length, bool shouldDelete, + Atom requestedType) { - success = (XGetWindowProperty (display, window, atom, offset, length, - (Bool) shouldDelete, requestedType, &actualType, - &actualFormat, &numItems, &bytesLeft, &data) == Success) + success = (X11Symbols::getInstance()->xGetWindowProperty (display, window, atom, offset, length, + (Bool) shouldDelete, requestedType, &actualType, + &actualFormat, &numItems, &bytesLeft, &data) == Success) && data != nullptr; } GetXProperty::~GetXProperty() { if (data != nullptr) - XFree (data); + X11Symbols::getInstance()->xFree (data); } } // namespace juce diff --git a/modules/juce_gui_basics/native/juce_linux_X11.h b/modules/juce_gui_basics/native/juce_linux_X11.h index 671cda1fcb..45a72298fc 100644 --- a/modules/juce_gui_basics/native/juce_linux_X11.h +++ b/modules/juce_gui_basics/native/juce_linux_X11.h @@ -37,6 +37,8 @@ public: JUCE_DECLARE_SINGLETON (XWindowSystem, false) private: + bool xIsAvailable = false; + XDisplay display = {}; Atomic displayCount; @@ -80,7 +82,6 @@ public: ~ScopedXLock(); private: - // defined in juce_linux_X11.h XDisplay display; }; @@ -131,39 +132,4 @@ struct GetXProperty int actualFormat; }; -//============================================================================== -enum -{ - maxXEmbedVersionToSupport = 0 -}; - -enum -{ - XEMBED_MAPPED = (1<<0) -}; - -enum -{ - XEMBED_EMBEDDED_NOTIFY = 0, - XEMBED_WINDOW_ACTIVATE = 1, - XEMBED_WINDOW_DEACTIVATE = 2, - XEMBED_REQUEST_FOCUS = 3, - XEMBED_FOCUS_IN = 4, - XEMBED_FOCUS_OUT = 5, - XEMBED_FOCUS_NEXT = 6, - XEMBED_FOCUS_PREV = 7, - XEMBED_MODALITY_ON = 10, - XEMBED_MODALITY_OFF = 11, - XEMBED_REGISTER_ACCELERATOR = 12, - XEMBED_UNREGISTER_ACCELERATOR = 13, - XEMBED_ACTIVATE_ACCELERATOR = 14 -}; - -enum -{ - XEMBED_FOCUS_CURRENT = 0, - XEMBED_FOCUS_FIRST = 1, - XEMBED_FOCUS_LAST = 2 -}; - } // namespace juce diff --git a/modules/juce_gui_basics/native/juce_linux_X11Symbols.cpp b/modules/juce_gui_basics/native/juce_linux_X11Symbols.cpp new file mode 100644 index 0000000000..0da9d61ab7 --- /dev/null +++ b/modules/juce_gui_basics/native/juce_linux_X11Symbols.cpp @@ -0,0 +1,236 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 5 End-User License + Agreement and JUCE 5 Privacy Policy (both updated and effective as of the + 27th April 2017). + + End User License Agreement: www.juce.com/juce-5-licence + Privacy Policy: www.juce.com/juce-5-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +namespace X11SymbolHelpers +{ + +template +struct SymbolBinding +{ + FuncPtr& func; + const char* name; +}; + +template +SymbolBinding makeSymbolBinding (FuncPtr& func, const char* name) +{ + return { func, name }; +} + +template +bool loadSymbols (DynamicLibrary& lib, SymbolBinding binding) +{ + if (auto* func = lib.getFunction (binding.name)) + { + binding.func = reinterpret_cast (func); + return true; + } + + return false; +} + +template +bool loadSymbols (DynamicLibrary& lib1, DynamicLibrary& lib2, SymbolBinding binding) +{ + return loadSymbols (lib1, binding) || loadSymbols (lib2, binding); +} + +template +bool loadSymbols (DynamicLibrary& lib, SymbolBinding binding, Args... args) +{ + return loadSymbols (lib, binding) && loadSymbols (lib, args...); +} + +template +bool loadSymbols (DynamicLibrary& lib1, DynamicLibrary& lib2, SymbolBinding binding, Args... args) +{ + return loadSymbols (lib1, lib2, binding) && loadSymbols (lib1, lib2, args...); +} + +} + +//============================================================================== +bool X11Symbols::loadAllSymbols() +{ + using namespace X11SymbolHelpers; + + if (! loadSymbols (xLib, xextLib, + makeSymbolBinding (xAllocSizeHints, "XAllocSizeHints"), + makeSymbolBinding (xAllocWMHints, "XAllocWMHints"), + makeSymbolBinding (xBitmapBitOrder, "XBitmapBitOrder"), + makeSymbolBinding (xBitmapUnit, "XBitmapUnit"), + makeSymbolBinding (xChangeActivePointerGrab, "XChangeActivePointerGrab"), + makeSymbolBinding (xChangeProperty, "XChangeProperty"), + makeSymbolBinding (xCheckTypedWindowEvent, "XCheckTypedWindowEvent"), + makeSymbolBinding (xCheckWindowEvent, "XCheckWindowEvent"), + makeSymbolBinding (xClearArea, "XClearArea"), + makeSymbolBinding (xCloseDisplay, "XCloseDisplay"), + makeSymbolBinding (xConnectionNumber, "XConnectionNumber"), + makeSymbolBinding (xConvertSelection, "XConvertSelection"), + makeSymbolBinding (xCreateColormap, "XCreateColormap"), + makeSymbolBinding (xCreateFontCursor, "XCreateFontCursor"), + makeSymbolBinding (xCreateGC, "XCreateGC"), + makeSymbolBinding (xCreateImage, "XCreateImage"), + makeSymbolBinding (xCreatePixmap, "XCreatePixmap"), + makeSymbolBinding (xCreatePixmapCursor, "XCreatePixmapCursor"), + makeSymbolBinding (xCreatePixmapFromBitmapData, "XCreatePixmapFromBitmapData"), + makeSymbolBinding (xCreateWindow, "XCreateWindow"), + makeSymbolBinding (xDefaultRootWindow, "XDefaultRootWindow"), + makeSymbolBinding (xDefaultScreen, "XDefaultScreen"), + makeSymbolBinding (xDefaultScreenOfDisplay, "XDefaultScreenOfDisplay"), + makeSymbolBinding (xDefaultVisual, "XDefaultVisual"), + makeSymbolBinding (xDefineCursor, "XDefineCursor"), + makeSymbolBinding (xDeleteContext, "XDeleteContext"), + makeSymbolBinding (xDeleteProperty, "XDeleteProperty"), + makeSymbolBinding (xDestroyImage, "XDestroyImage"), + makeSymbolBinding (xDestroyWindow, "XDestroyWindow"), + makeSymbolBinding (xDisplayHeight, "XDisplayHeight"), + makeSymbolBinding (xDisplayHeightMM, "XDisplayHeightMM"), + makeSymbolBinding (xDisplayWidth, "XDisplayWidth"), + makeSymbolBinding (xDisplayWidthMM, "XDisplayWidthMM"), + makeSymbolBinding (xEventsQueued, "XEventsQueued"), + makeSymbolBinding (xFindContext, "XFindContext"), + makeSymbolBinding (xFlush, "XFlush"), + makeSymbolBinding (xFree, "XFree"), + makeSymbolBinding (xFreeCursor, "XFreeCursor"), + makeSymbolBinding (xFreeColormap, "XFreeColormap"), + makeSymbolBinding (xFreeGC, "XFreeGC"), + makeSymbolBinding (xFreeModifiermap, "XFreeModifiermap"), + makeSymbolBinding (xFreePixmap, "XFreePixmap"), + makeSymbolBinding (xGetAtomName, "XGetAtomName"), + makeSymbolBinding (xGetErrorDatabaseText, "XGetErrorDatabaseText"), + makeSymbolBinding (xGetErrorText, "XGetErrorText"), + makeSymbolBinding (xGetGeometry, "XGetGeometry"), + makeSymbolBinding (xGetInputFocus, "XGetInputFocus"), + makeSymbolBinding (xGetModifierMapping, "XGetModifierMapping"), + makeSymbolBinding (xGetPointerMapping, "XGetPointerMapping"), + makeSymbolBinding (xGetSelectionOwner, "XGetSelectionOwner"), + makeSymbolBinding (xGetVisualInfo, "XGetVisualInfo"), + makeSymbolBinding (xGetWMHints, "XGetWMHints"), + makeSymbolBinding (xGetWindowAttributes, "XGetWindowAttributes"), + makeSymbolBinding (xGetWindowProperty, "XGetWindowProperty"), + makeSymbolBinding (xGrabPointer, "XGrabPointer"), + makeSymbolBinding (xGrabServer, "XGrabServer"), + makeSymbolBinding (xImageByteOrder, "XImageByteOrder"), + makeSymbolBinding (xInitImage, "XInitImage"), + makeSymbolBinding (xInitThreads, "XInitThreads"), + makeSymbolBinding (xInstallColormap, "XInstallColormap"), + makeSymbolBinding (xInternAtom, "XInternAtom"), + makeSymbolBinding (xkbKeycodeToKeysym, "XkbKeycodeToKeysym"), + makeSymbolBinding (xKeysymToKeycode, "XKeysymToKeycode"), + makeSymbolBinding (xListProperties, "XListProperties"), + makeSymbolBinding (xLockDisplay, "XLockDisplay"), + makeSymbolBinding (xLookupString, "XLookupString"), + makeSymbolBinding (xMapRaised, "XMapRaised"), + makeSymbolBinding (xMapWindow, "XMapWindow"), + makeSymbolBinding (xMoveResizeWindow, "XMoveResizeWindow"), + makeSymbolBinding (xNextEvent, "XNextEvent"), + makeSymbolBinding (xOpenDisplay, "XOpenDisplay"), + makeSymbolBinding (xPeekEvent, "XPeekEvent"), + makeSymbolBinding (xPending, "XPending"), + makeSymbolBinding (xPutImage, "XPutImage"), + makeSymbolBinding (xPutPixel, "XPutPixel"), + makeSymbolBinding (xQueryBestCursor, "XQueryBestCursor"), + makeSymbolBinding (xQueryExtension, "XQueryExtension"), + makeSymbolBinding (xQueryPointer, "XQueryPointer"), + makeSymbolBinding (xQueryTree, "XQueryTree"), + makeSymbolBinding (xRefreshKeyboardMapping, "XRefreshKeyboardMapping"), + makeSymbolBinding (xReparentWindow, "XReparentWindow"), + makeSymbolBinding (xResizeWindow, "XResizeWindow"), + makeSymbolBinding (xRestackWindows, "XRestackWindows"), + makeSymbolBinding (xRootWindow, "XRootWindow"), + makeSymbolBinding (xSaveContext, "XSaveContext"), + makeSymbolBinding (xScreenCount, "XScreenCount"), + makeSymbolBinding (xScreenNumberOfScreen, "XScreenNumberOfScreen"), + makeSymbolBinding (xSelectInput, "XSelectInput"), + makeSymbolBinding (xSendEvent, "XSendEvent"), + makeSymbolBinding (xSetErrorHandler, "XSetErrorHandler"), + makeSymbolBinding (xSetIOErrorHandler, "XSetIOErrorHandler"), + makeSymbolBinding (xSetInputFocus, "XSetInputFocus"), + makeSymbolBinding (xSetSelectionOwner, "XSetSelectionOwner"), + makeSymbolBinding (xSetWMHints, "XSetWMHints"), + makeSymbolBinding (xSetWMIconName, "XSetWMIconName"), + makeSymbolBinding (xSetWMName, "XSetWMName"), + makeSymbolBinding (xSetWMNormalHints, "XSetWMNormalHints"), + makeSymbolBinding (xStringListToTextProperty, "XStringListToTextProperty"), + makeSymbolBinding (xSync, "XSync"), + makeSymbolBinding (xTranslateCoordinates, "XTranslateCoordinates"), + makeSymbolBinding (xrmUniqueQuark, "XrmUniqueQuark"), + makeSymbolBinding (xUngrabPointer, "XUngrabPointer"), + makeSymbolBinding (xUngrabServer, "XUngrabServer"), + makeSymbolBinding (xUnlockDisplay, "XUnlockDisplay"), + makeSymbolBinding (xUnmapWindow, "XUnmapWindow"), + makeSymbolBinding (xWarpPointer, "XWarpPointer"))) + return false; + + #if JUCE_USE_XCURSOR + loadSymbols (xcursorLib, + makeSymbolBinding (xcursorImageCreate, "XcursorImageCreate"), + makeSymbolBinding (xcursorImageLoadCursor, "XcursorImageLoadCursor"), + makeSymbolBinding (xcursorImageDestroy, "XcursorImageDestroy")); + #endif + #if JUCE_USE_XINERAMA + loadSymbols (xineramaLib, + makeSymbolBinding (xineramaIsActive, "XineramaIsActive"), + makeSymbolBinding (xineramaQueryScreens, "XineramaQueryScreens")); + #endif + #if JUCE_USE_XRENDER + loadSymbols (xrenderLib, + makeSymbolBinding (xRenderQueryVersion, "XRenderQueryVersion"), + makeSymbolBinding (xRenderFindStandardFormat, "XRenderFindStandardFormat"), + makeSymbolBinding (xRenderFindFormat, "XRenderFindFormat"), + makeSymbolBinding (xRenderFindVisualFormat, "XRenderFindVisualFormat")); + #endif + #if JUCE_USE_XRANDR + loadSymbols (xrandrLib, + makeSymbolBinding (xRRGetScreenResources, "XRRGetScreenResources"), + makeSymbolBinding (xRRFreeScreenResources, "XRRFreeScreenResources"), + makeSymbolBinding (xRRGetOutputInfo, "XRRGetOutputInfo"), + makeSymbolBinding (xRRFreeOutputInfo, "XRRFreeOutputInfo"), + makeSymbolBinding (xRRGetCrtcInfo, "XRRGetCrtcInfo"), + makeSymbolBinding (xRRFreeCrtcInfo, "XRRFreeCrtcInfo"), + makeSymbolBinding (xRRGetOutputPrimary, "XRRGetOutputPrimary")); + #endif + #if JUCE_USE_XSHM + loadSymbols (xLib, xextLib, + makeSymbolBinding (xShmAttach, "XShmAttach"), + makeSymbolBinding (xShmCreateImage, "XShmCreateImage"), + makeSymbolBinding (xShmDetach, "XShmDetach"), + makeSymbolBinding (xShmGetEventBase, "XShmGetEventBase"), + makeSymbolBinding (xShmPutImage, "XShmPutImage"), + makeSymbolBinding (xShmQueryVersion, "XShmQueryVersion")); + #endif + + return true; +} + +//============================================================================== +JUCE_IMPLEMENT_SINGLETON (X11Symbols) + +} diff --git a/modules/juce_gui_basics/native/juce_linux_X11Symbols.h b/modules/juce_gui_basics/native/juce_linux_X11Symbols.h new file mode 100644 index 0000000000..98776a0e98 --- /dev/null +++ b/modules/juce_gui_basics/native/juce_linux_X11Symbols.h @@ -0,0 +1,606 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 5 End-User License + Agreement and JUCE 5 Privacy Policy (both updated and effective as of the + 27th April 2017). + + End User License Agreement: www.juce.com/juce-5-licence + Privacy Policy: www.juce.com/juce-5-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +//============================================================================== +namespace ReturnHelpers +{ + template + Type returnDefaultConstructedAnyType() { return {}; } + + template<> + inline void returnDefaultConstructedAnyType() {} +} + +#define JUCE_GENERATE_FUNCTION_WITH_DEFAULT(functionName, objectName, args, returnType) \ + using functionName = returnType (*) args; \ + functionName objectName = [] args -> returnType { return ReturnHelpers::returnDefaultConstructedAnyType(); }; + + +//============================================================================== +class JUCE_API X11Symbols : public DeletedAtShutdown +{ +public: + //============================================================================== + bool areXFunctionsAvailable() { return functionsAreAvailable; } + + //============================================================================== + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XAllocSizeHints, xAllocSizeHints, + (), + XSizeHints*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XAllocWMHints, xAllocWMHints, + (), + XWMHints*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XBitmapBitOrder, xBitmapBitOrder, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XBitmapUnit, xBitmapUnit, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XChangeActivePointerGrab, xChangeActivePointerGrab, + (::Display*, unsigned int, Cursor, ::Time), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XChangeProperty, xChangeProperty, + (::Display*, ::Window, Atom, Atom, int, int, const unsigned char*, int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCheckTypedWindowEvent, xCheckTypedWindowEvent, + (::Display*, ::Window, int, XEvent*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCheckWindowEvent, xCheckWindowEvent, + (::Display*, ::Window, long, XEvent*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XClearArea, xClearArea, + (::Display*, ::Window, int, int, unsigned int, unsigned int, Bool), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCloseDisplay, xCloseDisplay, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XConnectionNumber, xConnectionNumber, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XConvertSelection, xConvertSelection, + (::Display*, Atom, Atom, Atom, ::Window, ::Time), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreateColormap, xCreateColormap, + (::Display*, ::Window, Visual*, int), + Colormap) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreateFontCursor, xCreateFontCursor, + (::Display*, unsigned int), + Cursor) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreateGC, xCreateGC, + (::Display*, ::Drawable, unsigned long, XGCValues*), + GC) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreateImage, xCreateImage, + (::Display*, Visual*, unsigned int, int, int, const char*, unsigned int, unsigned int, int, int), + XImage*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreatePixmap, xCreatePixmap, + (::Display*, ::Drawable, unsigned int, unsigned int, unsigned int), + Pixmap) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreatePixmapCursor, xCreatePixmapCursor, + (::Display*, Pixmap, Pixmap, XColor*, XColor*, unsigned int, unsigned int), + Cursor) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreatePixmapFromBitmapData, xCreatePixmapFromBitmapData, + (::Display*, ::Drawable, const char*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int), + Pixmap) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XCreateWindow, xCreateWindow, + (::Display*, ::Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*), + ::Window) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDefaultRootWindow, xDefaultRootWindow, + (::Display*), + ::Window) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDefaultScreen, xDefaultScreen, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDefaultScreenOfDisplay, xDefaultScreenOfDisplay, + (::Display*), + Screen*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDefaultVisual, xDefaultVisual, + (::Display*, int), + Visual*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDefineCursor, xDefineCursor, + (::Display*, ::Window, Cursor), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDeleteContext, xDeleteContext, + (::Display*, XID, XContext), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDeleteProperty, xDeleteProperty, + (::Display*, Window, Atom), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDestroyImage, xDestroyImage, + (XImage*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDestroyWindow, xDestroyWindow, + (::Display*, ::Window), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDisplayHeight, xDisplayHeight, + (::Display*, int), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDisplayHeightMM, xDisplayHeightMM, + (::Display*, int), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDisplayWidth, xDisplayWidth, + (::Display*, int), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XDisplayWidthMM, xDisplayWidthMM, + (::Display*, int), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XEventsQueued, xEventsQueued, + (::Display*, int), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFindContext, xFindContext, + (::Display*, XID, XContext, XPointer*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFlush, xFlush, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFree, xFree, + (void*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFreeCursor, xFreeCursor, + (::Display*, Cursor), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFreeColormap ,xFreeColormap, + (::Display*, Colormap), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFreeGC, xFreeGC, + (::Display*, GC), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFreeModifiermap, xFreeModifiermap, + (XModifierKeymap*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XFreePixmap, xFreePixmap, + (::Display*, Pixmap), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetAtomName, xGetAtomName, + (::Display*, Atom), + char*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetErrorDatabaseText, xGetErrorDatabaseText, + (::Display*, char*, const char*, const char*, int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetErrorText, xGetErrorText, + (::Display*, int, const char*, int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetGeometry, xGetGeometry, + (::Display*, ::Drawable, ::Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetInputFocus, xGetInputFocus, + (::Display*, ::Window*, int*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetModifierMapping, xGetModifierMapping, + (::Display*), + XModifierKeymap*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetPointerMapping, xGetPointerMapping, + (::Display*, unsigned char[], int), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetSelectionOwner, xGetSelectionOwner, + (::Display*, Atom), + ::Window) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetVisualInfo, xGetVisualInfo, + (::Display*, long, XVisualInfo*, int*), + XVisualInfo*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetWMHints, xGetWMHints, + (::Display*, ::Window), + XWMHints*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetWindowAttributes, xGetWindowAttributes, + (::Display*, ::Window, XWindowAttributes*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetWindowProperty, xGetWindowProperty, + (::Display*, ::Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long*, unsigned long*, unsigned char**), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGrabPointer, xGrabPointer, + (::Display*, ::Window, Bool, unsigned int, int, int, ::Window, Cursor, ::Time), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGrabServer, xGrabServer, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XImageByteOrder, xImageByteOrder, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XInitImage, xInitImage, + (XImage*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XInitThreads, xInitThreads, + (), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XInstallColormap, xInstallColormap, + (::Display*, Colormap), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XInternAtom, xInternAtom, + (::Display*, const char*, Bool), + Atom) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XkbKeycodeToKeysym, xkbKeycodeToKeysym, + (::Display*, KeyCode, unsigned int, unsigned int), + KeySym) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XKeysymToKeycode, xKeysymToKeycode, + (::Display*, KeySym), + KeyCode) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XListProperties, xListProperties, + (::Display*, Window, int*), + Atom*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XLockDisplay, xLockDisplay, + (::Display*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XLookupString, xLookupString, + (XKeyEvent*, const char*, int, KeySym*, XComposeStatus*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XMapRaised, xMapRaised, + (::Display*, ::Window), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XMapWindow, xMapWindow, + (::Display*, ::Window), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XMoveResizeWindow, xMoveResizeWindow, + (::Display*, ::Window, int, int, unsigned int, unsigned int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XNextEvent, xNextEvent, + (::Display*, XEvent*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XOpenDisplay, xOpenDisplay, + (const char*), + ::Display*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XPeekEvent, xPeekEvent, + (::Display*, XEvent*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XPending, xPending, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XPutImage, xPutImage, + (::Display*, ::Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XPutPixel, xPutPixel, + (XImage*, int, int, unsigned long), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XQueryBestCursor, xQueryBestCursor, + (::Display*, ::Drawable, unsigned int, unsigned int, unsigned int*, unsigned int*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XQueryExtension, xQueryExtension, + (::Display*, const char*, int*, int*, int*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XQueryPointer, xQueryPointer, + (::Display*, ::Window, ::Window*, ::Window*, int*, int*, int*, int*, unsigned int*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XQueryTree, xQueryTree, + (::Display*, ::Window, ::Window*, ::Window*, ::Window**, unsigned int*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRefreshKeyboardMapping, xRefreshKeyboardMapping, + (XMappingEvent*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XReparentWindow, xReparentWindow, + (::Display*, ::Window, ::Window, int, int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XResizeWindow, xResizeWindow, + (::Display*, Window, unsigned int, unsigned int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRestackWindows, xRestackWindows, + (::Display*, ::Window[], int), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRootWindow, xRootWindow, + (::Display*, int), + ::Window) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSaveContext, xSaveContext, + (::Display*, XID, XContext, XPointer), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XScreenCount, xScreenCount, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XScreenNumberOfScreen, xScreenNumberOfScreen, + (Screen*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSelectInput, xSelectInput, + (::Display*, ::Window, long), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSendEvent, xSendEvent, + (::Display*, ::Window, Bool, long, XEvent*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetErrorHandler, xSetErrorHandler, + (XErrorHandler), + XErrorHandler) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetIOErrorHandler, xSetIOErrorHandler, + (XIOErrorHandler), + XIOErrorHandler) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetInputFocus, xSetInputFocus, + (::Display*, ::Window, int, ::Time), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetSelectionOwner, xSetSelectionOwner, + (::Display*, Atom, ::Window, ::Time), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetWMHints, xSetWMHints, + (::Display*, ::Window, XWMHints*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetWMIconName, xSetWMIconName, + (::Display*, ::Window, XTextProperty*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetWMName, xSetWMName, + (::Display*, ::Window, XTextProperty*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSetWMNormalHints, xSetWMNormalHints, + (::Display*, ::Window, XSizeHints*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XStringListToTextProperty, xStringListToTextProperty, + (char**, int, XTextProperty*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XSync, xSync, + (::Display*, Bool), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XTranslateCoordinates, xTranslateCoordinates, + (::Display*, ::Window, ::Window, int, int, int*, int*, ::Window*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XrmUniqueQuark, xrmUniqueQuark, + (), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XUngrabPointer, xUngrabPointer, + (::Display*, ::Time), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XUngrabServer, xUngrabServer, + (::Display*), + int) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XUnlockDisplay, xUnlockDisplay, + (::Display*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XUnmapWindow, xUnmapWindow, + (::Display*, ::Window), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XWarpPointer, xWarpPointer, + (::Display*, ::Window, ::Window, int, int, unsigned int, unsigned int, int, int), + void) + #if JUCE_USE_XCURSOR + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XcursorImageCreate, xcursorImageCreate, + (int, int), + XcursorImage*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XcursorImageLoadCursor, xcursorImageLoadCursor, + (::Display*, XcursorImage*), + Cursor) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XcursorImageDestroy, xcursorImageDestroy, + (XcursorImage*), + void) + #endif + #if JUCE_USE_XINERAMA + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XineramaIsActive, xineramaIsActive, + (::Display*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XineramaQueryScreens, xineramaQueryScreens, + (::Display*, int*), + XineramaScreenInfo*) + #endif + #if JUCE_USE_XRENDER + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRenderQueryVersion, xRenderQueryVersion, + (::Display*, int*, int*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRenderFindStandardFormat, xRenderFindStandardFormat, + (Display*, int), + XRenderPictFormat*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRenderFindFormat, xRenderFindFormat, + (Display*, unsigned long, XRenderPictFormat*, int), + XRenderPictFormat*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRenderFindVisualFormat, xRenderFindVisualFormat, + (Display*, Visual*), + XRenderPictFormat*) + #endif + #if JUCE_USE_XRANDR + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRGetScreenResources, xRRGetScreenResources, + (::Display*, Window), + XRRScreenResources*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRFreeScreenResources, xRRFreeScreenResources, + (XRRScreenResources*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRGetOutputInfo, xRRGetOutputInfo, + (::Display*, XRRScreenResources*, RROutput), + XRROutputInfo*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRFreeOutputInfo, xRRFreeOutputInfo, + (XRROutputInfo*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRGetCrtcInfo, xRRGetCrtcInfo, + (::Display*, XRRScreenResources*, RRCrtc), + XRRCrtcInfo*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRFreeCrtcInfo, xRRFreeCrtcInfo, + (XRRCrtcInfo*), + void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XRRGetOutputPrimary, xRRGetOutputPrimary, + (::Display*, ::Window), + RROutput) + #endif + #if JUCE_USE_XSHM + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XShmAttach, xShmAttach, + (::Display*, XShmSegmentInfo*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XShmCreateImage, xShmCreateImage, + (::Display*, Visual*, unsigned int, int, const char*, XShmSegmentInfo*, unsigned int, unsigned int), + XImage*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XShmDetach, xShmDetach, + (::Display*, XShmSegmentInfo*), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XShmGetEventBase, xShmGetEventBase, + (::Display*), + Status) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XShmPutImage, xShmPutImage, + (::Display*, ::Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int, bool), + Bool) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XShmQueryVersion, xShmQueryVersion, + (::Display*, int*, int*, Bool*), + Bool) + #endif + + //============================================================================== + JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (X11Symbols) + +private: + X11Symbols() = default; + + ~X11Symbols() + { + clearSingletonInstance(); + } + + //============================================================================== + bool loadAllSymbols(); + + //============================================================================== + DynamicLibrary xLib { "libX11.so" }, xextLib { "libXext.so" }; + + #if JUCE_USE_XCURSOR + DynamicLibrary xcursorLib { "libXcursor.so" }; + #endif + #if JUCE_USE_XINERAMA + DynamicLibrary xineramaLib { "libXinerama.so" }; + #endif + #if JUCE_USE_XRENDER + DynamicLibrary xrenderLib { "libXrender.so" }; + #endif + #if JUCE_USE_XRANDR + DynamicLibrary xrandrLib { "libXrandr.so" }; + #endif + + const bool functionsAreAvailable = loadAllSymbols(); + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (X11Symbols) +}; + +} diff --git a/modules/juce_gui_basics/native/juce_linux_X11_Clipboard.cpp b/modules/juce_gui_basics/native/juce_linux_X11_Clipboard.cpp index ea0dec80d3..3f056bffaa 100644 --- a/modules/juce_gui_basics/native/juce_linux_X11_Clipboard.cpp +++ b/modules/juce_gui_basics/native/juce_linux_X11_Clipboard.cpp @@ -57,11 +57,11 @@ namespace ClipboardHelpers int actualFormat; unsigned long numItems, bytesLeft; - if (XGetWindowProperty (display, window, prop, - 0L /* offset */, 1000000 /* length (max) */, False, - AnyPropertyType /* format */, - &actualType, &actualFormat, &numItems, &bytesLeft, - (unsigned char**) &clipData) == Success) + if (X11Symbols::getInstance()->xGetWindowProperty (display, window, prop, + 0L /* offset */, 1000000 /* length (max) */, False, + AnyPropertyType /* format */, + &actualType, &actualFormat, &numItems, &bytesLeft, + (unsigned char**) &clipData) == Success) { if (actualType == atom_UTF8_STRING && actualFormat == 8) returnData = String::fromUTF8 (clipData, (int) numItems); @@ -69,12 +69,12 @@ namespace ClipboardHelpers returnData = String (clipData, numItems); if (clipData != nullptr) - XFree (clipData); + X11Symbols::getInstance()->xFree (clipData); jassert (bytesLeft == 0 || numItems == 1000000); } - XDeleteProperty (display, window, prop); + X11Symbols::getInstance()->xDeleteProperty (display, window, prop); } return returnData; @@ -85,12 +85,12 @@ namespace ClipboardHelpers static bool requestSelectionContent (::Display* display, String& selectionContent, Atom selection, Atom requestedFormat) { - Atom property_name = XInternAtom (display, "JUCE_SEL", false); + auto property_name = X11Symbols::getInstance()->xInternAtom (display, "JUCE_SEL", false); // The selection owner will be asked to set the JUCE_SEL property on the // juce_messageWindowHandle with the selection content - XConvertSelection (display, selection, requestedFormat, property_name, - juce_messageWindowHandle, CurrentTime); + X11Symbols::getInstance()->xConvertSelection (display, selection, requestedFormat, property_name, + juce_messageWindowHandle, CurrentTime); int count = 50; // will wait at most for 200 ms @@ -98,7 +98,7 @@ namespace ClipboardHelpers { XEvent event; - if (XCheckTypedWindowEvent (display, juce_messageWindowHandle, SelectionNotify, &event)) + if (X11Symbols::getInstance()->xCheckTypedWindowEvent (display, juce_messageWindowHandle, SelectionNotify, &event)) { if (event.xselection.property == property_name) { @@ -176,15 +176,15 @@ namespace ClipboardHelpers // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss if (evt.property != None && numDataItems < maxReasonableSelectionSize) { - XChangeProperty (evt.display, evt.requestor, - evt.property, evt.target, - propertyFormat /* 8 or 32 */, PropModeReplace, - reinterpret_cast (data.getData()), (int) numDataItems); + X11Symbols::getInstance()->xChangeProperty (evt.display, evt.requestor, + evt.property, evt.target, + propertyFormat /* 8 or 32 */, PropModeReplace, + reinterpret_cast (data.getData()), (int) numDataItems); reply.property = evt.property; // " == success" } } - XSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply); + X11Symbols::getInstance()->xSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply); } } @@ -212,8 +212,8 @@ void SystemClipboard::copyTextToClipboard (const String& clipText) ClipboardHelpers::initSelectionAtoms (display); ClipboardHelpers::localClipboardContent = clipText; - XSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); - XSetSelectionOwner (display, ClipboardHelpers::atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime); + X11Symbols::getInstance()->xSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); + X11Symbols::getInstance()->xSetSelectionOwner (display, ClipboardHelpers::atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime); } } @@ -238,10 +238,10 @@ String SystemClipboard::getTextFromClipboard() Atom selection = XA_PRIMARY; Window selectionOwner = None; - if ((selectionOwner = XGetSelectionOwner (display, selection)) == None) + if ((selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selection)) == None) { selection = ClipboardHelpers::atom_CLIPBOARD; - selectionOwner = XGetSelectionOwner (display, selection); + selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selection); } if (selectionOwner != None) diff --git a/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp index 5b404f5fa5..40e2108e46 100644 --- a/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp @@ -30,8 +30,8 @@ namespace juce #endif #if JUCE_X11_SUPPORTS_XEMBED -bool juce_handleXEmbedEvent (ComponentPeer*, void*); -unsigned long juce_getCurrentFocusWindow (ComponentPeer*); + bool juce_handleXEmbedEvent (ComponentPeer*, void*); + unsigned long juce_getCurrentFocusWindow (ComponentPeer*); #endif extern WindowMessageReceiveCallback dispatchWindowMessage; @@ -87,9 +87,9 @@ bool KeyPress::isKeyCurrentlyDown (int keyCode) ScopedXLock xlock (display); - const int keycode = XKeysymToKeycode (display, (KeySym) keysym); - const int keybyte = keycode >> 3; - const int keybit = (1 << (keycode & 7)); + auto keycode = X11Symbols::getInstance()->xKeysymToKeycode (display, (KeySym) keysym); + auto keybyte = keycode >> 3; + auto keybit = (1 << (keycode & 7)); return (Keys::keyStates [keybyte] & keybit) != 0; } @@ -202,16 +202,17 @@ namespace XSHMHelpers ScopedXLock xlock (display); - if (XShmQueryVersion (display, &major, &minor, &pixmaps)) + if (X11Symbols::getInstance()->xShmQueryVersion (display, &major, &minor, &pixmaps)) { trappedErrorCode = 0; - XErrorHandler oldHandler = XSetErrorHandler (errorTrapHandler); + auto oldHandler = X11Symbols::getInstance()->xSetErrorHandler (errorTrapHandler); XShmSegmentInfo segmentInfo; zerostruct (segmentInfo); - if (auto* xImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), - 24, ZPixmap, nullptr, &segmentInfo, 50, 50)) + if (auto* xImage = X11Symbols::getInstance()->xShmCreateImage (display, + X11Symbols::getInstance()->xDefaultVisual (display, X11Symbols::getInstance()->xDefaultScreen (display)), + 24, ZPixmap, nullptr, &segmentInfo, 50, 50)) { if ((segmentInfo.shmid = shmget (IPC_PRIVATE, (size_t) (xImage->bytes_per_line * xImage->height), @@ -223,26 +224,27 @@ namespace XSHMHelpers { segmentInfo.readOnly = False; xImage->data = segmentInfo.shmaddr; - XSync (display, False); + X11Symbols::getInstance()->xSync (display, False); - if (XShmAttach (display, &segmentInfo) != 0) + if (X11Symbols::getInstance()->xShmAttach (display, &segmentInfo) != 0) { - XSync (display, False); - XShmDetach (display, &segmentInfo); + X11Symbols::getInstance()->xSync (display, False); + X11Symbols::getInstance()->xShmDetach (display, &segmentInfo); isAvailable = true; } } - XFlush (display); - XDestroyImage (xImage); + X11Symbols::getInstance()->xFlush (display); + X11Symbols::getInstance()->xDestroyImage (xImage); shmdt (segmentInfo.shmaddr); } shmctl (segmentInfo.shmid, IPC_RMID, nullptr); - XSetErrorHandler (oldHandler); + X11Symbols::getInstance()->xSetErrorHandler (oldHandler); + if (trappedErrorCode != 0) isAvailable = false; } @@ -260,69 +262,25 @@ namespace XSHMHelpers #if JUCE_USE_XRENDER namespace XRender { - typedef Status (*tXRenderQueryVersion) (Display*, int*, int*); - typedef XRenderPictFormat* (*tXRenderFindStandardFormat) (Display*, int); - typedef XRenderPictFormat* (*tXRenderFindFormat) (Display*, unsigned long, XRenderPictFormat*, int); - typedef XRenderPictFormat* (*tXRenderFindVisualFormat) (Display*, Visual*); - - static tXRenderQueryVersion xRenderQueryVersion = nullptr; - static tXRenderFindStandardFormat xRenderFindStandardFormat = nullptr; - static tXRenderFindFormat xRenderFindFormat = nullptr; - static tXRenderFindVisualFormat xRenderFindVisualFormat = nullptr; - static bool isAvailable (::Display* display) { - static bool hasLoaded = false; - - if (! hasLoaded) - { - if (display != nullptr) - { - hasLoaded = true; - - ScopedXLock xlock (display); - - if (void* h = dlopen ("libXrender.so.1", RTLD_GLOBAL | RTLD_NOW)) - { - xRenderQueryVersion = (tXRenderQueryVersion) dlsym (h, "XRenderQueryVersion"); - xRenderFindStandardFormat = (tXRenderFindStandardFormat) dlsym (h, "XRenderFindStandardFormat"); - xRenderFindFormat = (tXRenderFindFormat) dlsym (h, "XRenderFindFormat"); - xRenderFindVisualFormat = (tXRenderFindVisualFormat) dlsym (h, "XRenderFindVisualFormat"); - } - - if (xRenderQueryVersion != nullptr - && xRenderFindStandardFormat != nullptr - && xRenderFindFormat != nullptr - && xRenderFindVisualFormat != nullptr) - { - int major, minor; - if (xRenderQueryVersion (display, &major, &minor)) - return true; - } - } - - xRenderQueryVersion = nullptr; - } - - return xRenderQueryVersion != nullptr; + int major, minor; + return X11Symbols::getInstance()->xRenderQueryVersion (display, &major, &minor); } static bool hasCompositingWindowManager (::Display* display) noexcept { return display != nullptr - && XGetSelectionOwner (display, Atoms::getCreating (display, "_NET_WM_CM_S0")) != 0; + && X11Symbols::getInstance()->xGetSelectionOwner (display, Atoms::getCreating (display, "_NET_WM_CM_S0")) != 0; } static XRenderPictFormat* findPictureFormat (::Display* display) { ScopedXLock xlock (display); - XRenderPictFormat* pictFormat = nullptr; if (isAvailable (display)) { - pictFormat = xRenderFindStandardFormat (display, PictStandardARGB32); - - if (pictFormat == nullptr) + if (auto* pictFormat = X11Symbols::getInstance()->xRenderFindStandardFormat (display, PictStandardARGB32)) { XRenderPictFormat desiredFormat; desiredFormat.type = PictTypeDirect; @@ -338,18 +296,20 @@ namespace XRender desiredFormat.direct.green = 8; desiredFormat.direct.blue = 0; - pictFormat = xRenderFindFormat (display, - PictFormatType | PictFormatDepth - | PictFormatRedMask | PictFormatRed - | PictFormatGreenMask | PictFormatGreen - | PictFormatBlueMask | PictFormatBlue - | PictFormatAlphaMask | PictFormatAlpha, - &desiredFormat, - 0); + pictFormat = X11Symbols::getInstance()->xRenderFindFormat (display, + PictFormatType | PictFormatDepth + | PictFormatRedMask | PictFormatRed + | PictFormatGreenMask | PictFormatGreen + | PictFormatBlueMask | PictFormatBlue + | PictFormatAlphaMask | PictFormatAlpha, + &desiredFormat, + 0); + + return pictFormat; } } - return pictFormat; + return nullptr; } } #endif @@ -364,10 +324,10 @@ namespace Visuals Visual* visual = nullptr; int numVisuals = 0; - long desiredMask = VisualNoMask; + auto desiredMask = VisualNoMask; XVisualInfo desiredVisual; - desiredVisual.screen = DefaultScreen (display); + desiredVisual.screen = X11Symbols::getInstance()->xDefaultScreen (display); desiredVisual.depth = desiredDepth; desiredMask = VisualScreenMask | VisualDepthMask; @@ -387,7 +347,7 @@ namespace Visuals desiredMask |= VisualBitsPerRGBMask; } - if (auto* xvinfos = XGetVisualInfo (display, desiredMask, &desiredVisual, &numVisuals)) + if (auto* xvinfos = X11Symbols::getInstance()->xGetVisualInfo (display, desiredMask, &desiredVisual, &numVisuals)) { for (int i = 0; i < numVisuals; i++) { @@ -398,7 +358,7 @@ namespace Visuals } } - XFree (xvinfos); + X11Symbols::getInstance()->xFree (xvinfos); } return visual; @@ -416,21 +376,21 @@ namespace Visuals #if JUCE_USE_XRENDER if (XRender::isAvailable (display)) { - if (auto pictFormat = XRender::findPictureFormat (display)) + if (auto* pictFormat = XRender::findPictureFormat (display)) { int numVisuals = 0; XVisualInfo desiredVisual; - desiredVisual.screen = DefaultScreen (display); + desiredVisual.screen = X11Symbols::getInstance()->xDefaultScreen (display); desiredVisual.depth = 32; desiredVisual.bits_per_rgb = 8; - if (auto xvinfos = XGetVisualInfo (display, - VisualScreenMask | VisualDepthMask | VisualBitsPerRGBMask, - &desiredVisual, &numVisuals)) + if (auto xvinfos = X11Symbols::getInstance()->xGetVisualInfo (display, + VisualScreenMask | VisualDepthMask | VisualBitsPerRGBMask, + &desiredVisual, &numVisuals)) { for (int i = 0; i < numVisuals; ++i) { - auto pictVisualFormat = XRender::xRenderFindVisualFormat (display, xvinfos[i].visual); + auto pictVisualFormat = X11Symbols::getInstance()->xRenderFindVisualFormat (display, xvinfos[i].visual); if (pictVisualFormat != nullptr && pictVisualFormat->type == PictTypeDirect @@ -442,7 +402,7 @@ namespace Visuals } } - XFree (xvinfos); + X11Symbols::getInstance()->xFree (xvinfos); } } } @@ -507,8 +467,8 @@ public: segmentInfo.shmaddr = (char *) -1; segmentInfo.readOnly = False; - xImage = XShmCreateImage (display, visual, imageDepth, ZPixmap, nullptr, - &segmentInfo, (unsigned int) w, (unsigned int) h); + xImage = X11Symbols::getInstance()->xShmCreateImage (display, visual, imageDepth, ZPixmap, nullptr, + &segmentInfo, (unsigned int) w, (unsigned int) h); if (xImage != nullptr) { @@ -527,7 +487,7 @@ public: xImage->data = segmentInfo.shmaddr; imageData = (uint8*) segmentInfo.shmaddr; - if (XShmAttach (display, &segmentInfo) != 0) + if (X11Symbols::getInstance()->xShmAttach (display, &segmentInfo) != 0) usingXShm = true; else jassertfalse; @@ -554,9 +514,9 @@ public: 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->byte_order = X11Symbols::getInstance()->xImageByteOrder (display); + xImage->bitmap_unit = X11Symbols::getInstance()->xBitmapUnit (display); + xImage->bitmap_bit_order = X11Symbols::getInstance()->xBitmapBitOrder (display); xImage->bitmap_pad = 32; xImage->depth = pixelStride * 8; xImage->bytes_per_line = lineStride; @@ -567,8 +527,8 @@ public: if (imageDepth == 16) { - const int pixStride = 2; - const int stride = ((w * pixStride + 3) & ~3); + int pixStride = 2; + auto stride = ((w * pixStride + 3) & ~3); imageData16Bit.malloc (stride * h); xImage->data = imageData16Bit; @@ -581,7 +541,7 @@ public: xImage->blue_mask = visual->blue_mask; } - if (! XInitImage (xImage)) + if (! X11Symbols::getInstance()->xInitImage (xImage)) jassertfalse; } } @@ -591,15 +551,15 @@ public: ScopedXLock xlock (display); if (gc != None) - XFreeGC (display, gc); + X11Symbols::getInstance()->xFreeGC (display, gc); #if JUCE_USE_XSHM if (isUsingXShm()) { - XShmDetach (display, &segmentInfo); + X11Symbols::getInstance()->xShmDetach (display, &segmentInfo); - XFlush (display); - XDestroyImage (xImage); + X11Symbols::getInstance()->xFlush (display); + X11Symbols::getInstance()->xDestroyImage (xImage); shmdt (segmentInfo.shmaddr); shmctl (segmentInfo.shmid, IPC_RMID, nullptr); @@ -608,7 +568,7 @@ public: #endif { xImage->data = nullptr; - XDestroyImage (xImage); + X11Symbols::getInstance()->xDestroyImage (xImage); } } @@ -653,9 +613,9 @@ public: gcvalues.clip_mask = None; gcvalues.graphics_exposures = False; - gc = XCreateGC (display, window, - GCBackground | GCForeground | GCFunction | GCPlaneMask | GCClipMask | GCGraphicsExposures, - &gcvalues); + gc = X11Symbols::getInstance()->xCreateGC (display, window, + GCBackground | GCForeground | GCFunction | GCPlaneMask | GCClipMask | GCGraphicsExposures, + &gcvalues); } if (imageDepth == 16) @@ -670,21 +630,21 @@ public: auto bShiftL = (uint32) jmax (0, getShiftNeeded (bMask)); auto bShiftR = (uint32) jmax (0, -getShiftNeeded (bMask)); - const Image::BitmapData srcData (Image (this), Image::BitmapData::readOnly); + Image::BitmapData srcData (Image (this), Image::BitmapData::readOnly); - for (int y = sy; y < sy + (int)dh; ++y) + for (int y = sy; y < sy + (int) dh; ++y) { - const uint8* p = srcData.getPixelPointer (sx, y); + auto* p = srcData.getPixelPointer (sx, y); - for (int x = sx; x < sx + (int)dw; ++x) + for (int x = sx; x < sx + (int) dw; ++x) { - auto* pixel = (const PixelRGB*) p; + auto* pixel = (PixelRGB*) p; p += srcData.pixelStride; - XPutPixel (xImage, x, y, - (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) - | (((((uint32) pixel->getGreen()) << gShiftL) >> gShiftR) & gMask) - | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); + X11Symbols::getInstance()->xPutPixel (xImage, x, y, + (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) + | (((((uint32) pixel->getGreen()) << gShiftL) >> gShiftR) & gMask) + | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); } } } @@ -692,10 +652,10 @@ public: // blit results to screen. #if JUCE_USE_XSHM if (isUsingXShm()) - XShmPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh, True); + X11Symbols::getInstance()->xShmPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh, True); else #endif - XPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); + X11Symbols::getInstance()->xPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); } #if JUCE_USE_XSHM @@ -735,42 +695,19 @@ private: #if JUCE_USE_XINERAMA static Array XineramaQueryDisplays (::Display* display) { - typedef Bool (*tXineramaIsActive) (::Display*); - typedef XineramaScreenInfo* (*tXineramaQueryScreens) (::Display*, int*); - int major_opcode, first_event, first_error; - if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)) + if (X11Symbols::getInstance()->xQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error) + && (X11Symbols::getInstance()->xineramaIsActive (display) != 0)) { - static void* libXinerama = nullptr; - static tXineramaIsActive isActiveFuncPtr = nullptr; - static tXineramaQueryScreens xineramaQueryScreens = nullptr; + int numScreens; - if (libXinerama == nullptr) + if (auto* xinfo = X11Symbols::getInstance()->xineramaQueryScreens (display, &numScreens)) { - libXinerama = dlopen ("libXinerama.so", RTLD_GLOBAL | RTLD_NOW); + Array infos (xinfo, numScreens); + X11Symbols::getInstance()->xFree (xinfo); - if (libXinerama == nullptr) - libXinerama = dlopen ("libXinerama.so.1", RTLD_GLOBAL | RTLD_NOW); - - if (libXinerama != nullptr) - { - isActiveFuncPtr = (tXineramaIsActive) dlsym (libXinerama, "XineramaIsActive"); - xineramaQueryScreens = (tXineramaQueryScreens) dlsym (libXinerama, "XineramaQueryScreens"); - } - } - - if (isActiveFuncPtr != nullptr && xineramaQueryScreens != nullptr && isActiveFuncPtr (display) != 0) - { - int numScreens; - - if (auto* xinfo = xineramaQueryScreens (display, &numScreens)) - { - Array infos (xinfo, numScreens); - XFree (xinfo); - - return infos; - } + return infos; } } @@ -779,120 +716,14 @@ static Array XineramaQueryDisplays (::Display* display) #endif //============================================================================== -#if JUCE_USE_XRANDR -class XRandrWrapper -{ -private: - XRandrWrapper() - { - if (libXrandr == nullptr) - { - libXrandr = dlopen ("libXrandr.so", RTLD_GLOBAL | RTLD_NOW); - - if (libXrandr == nullptr) - libXrandr = dlopen ("libXrandr.so.2", RTLD_GLOBAL | RTLD_NOW); - - if (libXrandr != nullptr) - { - getScreenResourcesPtr = (tXRRGetScreenResources) dlsym (libXrandr, "XRRGetScreenResources"); - freeScreenResourcesPtr = (tXRRFreeScreenResources) dlsym (libXrandr, "XRRFreeScreenResources"); - getOutputInfoPtr = (tXRRGetOutputInfo) dlsym (libXrandr, "XRRGetOutputInfo"); - freeOutputInfoPtr = (tXRRFreeOutputInfo) dlsym (libXrandr, "XRRFreeOutputInfo"); - getCrtcInfoPtr = (tXRRGetCrtcInfo) dlsym (libXrandr, "XRRGetCrtcInfo"); - freeCrtcInfoPtr = (tXRRFreeCrtcInfo) dlsym (libXrandr, "XRRFreeCrtcInfo"); - getOutputPrimaryPtr = (tXRRGetOutputPrimary) dlsym (libXrandr, "XRRGetOutputPrimary"); - } - } - } - -public: - //============================================================================== - static XRandrWrapper& getInstance() - { - static XRandrWrapper xrandr; - return xrandr; - } - - //============================================================================== - XRRScreenResources* getScreenResources (::Display* display, ::Window window) - { - if (getScreenResourcesPtr != nullptr) - return getScreenResourcesPtr (display, window); - - return nullptr; - } - - XRROutputInfo* getOutputInfo (::Display* display, XRRScreenResources* resources, RROutput output) - { - if (getOutputInfoPtr != nullptr) - return getOutputInfoPtr (display, resources, output); - - return nullptr; - } - - XRRCrtcInfo* getCrtcInfo (::Display* display, XRRScreenResources* resources, RRCrtc crtc) - { - if (getCrtcInfoPtr != nullptr) - return getCrtcInfoPtr (display, resources, crtc); - - return nullptr; - } - - RROutput getOutputPrimary (::Display* display, ::Window window) - { - if (getOutputPrimaryPtr != nullptr) - return getOutputPrimaryPtr (display, window); - - return 0; - } - - //============================================================================== - void freeScreenResources (XRRScreenResources* ptr) - { - if (freeScreenResourcesPtr != nullptr) - freeScreenResourcesPtr (ptr); - } - - void freeOutputInfo (XRROutputInfo* ptr) - { - if (freeOutputInfoPtr != nullptr) - freeOutputInfoPtr (ptr); - } - - void freeCrtcInfo (XRRCrtcInfo* ptr) - { - if (freeCrtcInfoPtr != nullptr) - freeCrtcInfoPtr (ptr); - } - -private: - using tXRRGetScreenResources = XRRScreenResources* (*) (::Display*, ::Window); - using tXRRFreeScreenResources = void (*) (XRRScreenResources*); - using tXRRGetOutputInfo = XRROutputInfo* (*) (::Display*, XRRScreenResources*, RROutput); - using tXRRFreeOutputInfo = void (*) (XRROutputInfo*); - using tXRRGetCrtcInfo = XRRCrtcInfo* (*) (::Display*, XRRScreenResources*, RRCrtc); - using tXRRFreeCrtcInfo = void (*) (XRRCrtcInfo*); - using tXRRGetOutputPrimary = RROutput (*) (::Display*, ::Window); - - void* libXrandr = nullptr; - tXRRGetScreenResources getScreenResourcesPtr = nullptr; - tXRRFreeScreenResources freeScreenResourcesPtr = nullptr; - tXRRGetOutputInfo getOutputInfoPtr = nullptr; - tXRRFreeOutputInfo freeOutputInfoPtr = nullptr; - tXRRGetCrtcInfo getCrtcInfoPtr = nullptr; - tXRRFreeCrtcInfo freeCrtcInfoPtr = nullptr; - tXRRGetOutputPrimary getOutputPrimaryPtr = nullptr; -}; -#endif - - static double getDisplayDPI (::Display* display, int index) { - auto widthMM = DisplayWidthMM (display, index); - auto heightMM = DisplayHeightMM (display, index); + auto widthMM = X11Symbols::getInstance()->xDisplayWidthMM (display, index); + auto heightMM = X11Symbols::getInstance()->xDisplayHeightMM (display, index); if (widthMM > 0 && heightMM > 0) - return (((DisplayWidth (display, index) * 25.4) / widthMM) + ((DisplayHeight (display, index) * 25.4) / heightMM)) / 2.0; + return (((X11Symbols::getInstance()->xDisplayWidth (display, index) * 25.4) / widthMM) + + ((X11Symbols::getInstance()->xDisplayHeight (display, index) * 25.4) / heightMM)) / 2.0; return 96.0; } @@ -971,26 +802,28 @@ namespace PixmapHelpers { ScopedXLock xlock (display); - auto width = (unsigned int) image.getWidth(); + auto width = (unsigned int) image.getWidth(); auto height = (unsigned int) image.getHeight(); HeapBlock colour (width * height); int index = 0; - for (int y = 0; y < (int) height; ++y) + for (int y = 0; y < (int) height; ++y) for (int x = 0; x < (int) width; ++x) colour[index++] = image.getPixelAt (x, y).getARGB(); - XImage* ximage = XCreateImage (display, CopyFromParent, 24, ZPixmap, - 0, reinterpret_cast (colour.getData()), - width, height, 32, 0); + auto* ximage = X11Symbols::getInstance()->xCreateImage (display, CopyFromParent, 24, ZPixmap, + 0, reinterpret_cast (colour.getData()), + width, height, 32, 0); - Pixmap pixmap = XCreatePixmap (display, DefaultRootWindow (display), - width, height, 24); + auto pixmap = X11Symbols::getInstance()->xCreatePixmap (display, + X11Symbols::getInstance()->xDefaultRootWindow (display), + width, height, 24); - GC gc = XCreateGC (display, pixmap, 0, nullptr); - XPutImage (display, pixmap, gc, ximage, 0, 0, 0, 0, width, height); - XFreeGC (display, gc); - XFree (ximage); + auto gc = X11Symbols::getInstance()->xCreateGC (display, pixmap, 0, nullptr); + + X11Symbols::getInstance()->xPutImage (display, pixmap, gc, ximage, 0, 0, 0, 0, width, height); + X11Symbols::getInstance()->xFreeGC (display, gc); + X11Symbols::getInstance()->xFree (ximage); return pixmap; } @@ -999,35 +832,38 @@ namespace PixmapHelpers { ScopedXLock xlock (display); - auto width = (unsigned int) image.getWidth(); + auto width = (unsigned int) image.getWidth(); auto height = (unsigned int) image.getHeight(); auto stride = (width + 7) >> 3; HeapBlock mask; mask.calloc (stride * height); - const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); + + auto msbfirst = (X11Symbols::getInstance()->xBitmapBitOrder (display) == MSBFirst); for (unsigned int y = 0; y < height; ++y) { for (unsigned int x = 0; x < width; ++x) { auto bit = (char) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); - const unsigned int offset = y * stride + (x >> 3); + auto offset = y * stride + (x >> 3); if (image.getPixelAt ((int) x, (int) y).getAlpha() >= 128) mask[offset] |= bit; } } - return XCreatePixmapFromBitmapData (display, DefaultRootWindow (display), - mask.getData(), width, height, 1, 0, 1); + return X11Symbols::getInstance()->xCreatePixmapFromBitmapData (display, X11Symbols::getInstance()->xDefaultRootWindow (display), + mask.getData(), width, height, 1, 0, 1); } } static void* createDraggingHandCursor() { - 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 }; + 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 + }; size_t dragHandDataSize = 99; return CustomMouseCursorInfo (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), { 8, 7 }).create(); @@ -1052,11 +888,14 @@ public: // it's dangerous to create a window on a thread other than the message thread.. JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED + // can't open a window on a system that doesn't have X11 installed! + jassert (X11Symbols::getInstance()->areXFunctionsAvailable()); + display = XWindowSystem::getInstance()->displayRef(); - atoms.reset (new Atoms (display)); - dragState.reset (new DragState (display)); - repainter.reset (new LinuxRepaintManager (*this, display)); + atoms = std::make_unique (display); + dragState = std::make_unique (display); + repainter = std::make_unique (*this, display); if (isAlwaysOnTop) ++numAlwaysOnTopPeers; @@ -1078,8 +917,8 @@ public: ScopedXLock xlock (d); - if (XQueryPointer (d, RootWindow (d, DefaultScreen (d)), - &root, &child, &x, &y, &winx, &winy, &mask) != False) + if (X11Symbols::getInstance()->xQueryPointer (d, X11Symbols::getInstance()->xRootWindow (d, X11Symbols::getInstance()->xDefaultScreen (d)), + &root, &child, &x, &y, &winx, &winy, &mask) != False) { if ((mask & Button1Mask) != 0) mouseMods |= ModifierKeys::leftButtonModifier; if ((mask & Button2Mask) != 0) mouseMods |= ModifierKeys::middleButtonModifier; @@ -1129,7 +968,7 @@ public: { ScopedXLock xlock (display); - if (! XFindContext (display, (XID) windowHandle, windowHandleXContext, &peer)) + if (! X11Symbols::getInstance()->xFindContext (display, (XID) windowHandle, windowHandleXContext, &peer)) if (peer != nullptr && ! ComponentPeer::isValidPeer (reinterpret_cast (peer))) peer = nullptr; } @@ -1142,9 +981,9 @@ public: ScopedXLock xlock (display); if (shouldBeVisible) - XMapWindow (display, windowH); + X11Symbols::getInstance()->xMapWindow (display, windowH); else - XUnmapWindow (display, windowH); + X11Symbols::getInstance()->xUnmapWindow (display, windowH); } void setTitle (const String& title) override @@ -1153,12 +992,12 @@ public: char* strings[] = { const_cast (title.toRawUTF8()) }; ScopedXLock xlock (display); - if (XStringListToTextProperty (strings, 1, &nameProperty)) + if (X11Symbols::getInstance()->xStringListToTextProperty (strings, 1, &nameProperty)) { - XSetWMName (display, windowH, &nameProperty); - XSetWMIconName (display, windowH, &nameProperty); + X11Symbols::getInstance()->xSetWMName (display, windowH, &nameProperty); + X11Symbols::getInstance()->xSetWMIconName (display, windowH, &nameProperty); - XFree (nameProperty.value); + X11Symbols::getInstance()->xFree (nameProperty.value); } } @@ -1186,7 +1025,7 @@ public: if (fs != None) { - Window root = RootWindow (display, DefaultScreen (display)); + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); XClientMessageEvent clientMsg; clientMsg.display = display; @@ -1200,9 +1039,9 @@ public: clientMsg.data.l[3] = 1; // Normal Source ScopedXLock xlock (display); - XSendEvent (display, root, false, - SubstructureRedirectMask | SubstructureNotifyMask, - (XEvent*) &clientMsg); + X11Symbols::getInstance()->xSendEvent (display, root, false, + SubstructureRedirectMask | SubstructureNotifyMask, + (XEvent*) &clientMsg); } } @@ -1221,7 +1060,7 @@ public: WeakReference deletionChecker (&component); ScopedXLock xlock (display); - auto* hints = XAllocSizeHints(); + auto* hints = X11Symbols::getInstance()->xAllocSizeHints(); hints->flags = USSize | USPosition; hints->x = physicalBounds.getX(); hints->y = physicalBounds.getY(); @@ -1235,14 +1074,14 @@ public: hints->flags |= PMinSize | PMaxSize; } - XSetWMNormalHints (display, windowH, hints); - XFree (hints); + X11Symbols::getInstance()->xSetWMNormalHints (display, windowH, hints); + X11Symbols::getInstance()->xFree (hints); - XMoveResizeWindow (display, windowH, - physicalBounds.getX() - windowBorder.getLeft(), - physicalBounds.getY() - windowBorder.getTop(), - (unsigned int) physicalBounds.getWidth(), - (unsigned int) physicalBounds.getHeight()); + X11Symbols::getInstance()->xMoveResizeWindow (display, windowH, + physicalBounds.getX() - windowBorder.getLeft(), + physicalBounds.getY() - windowBorder.getTop(), + (unsigned int) physicalBounds.getWidth(), + (unsigned int) physicalBounds.getHeight()); if (deletionChecker != nullptr) { @@ -1278,14 +1117,14 @@ public: StringArray getAvailableRenderingEngines() override { - return StringArray ("Software Renderer"); + return { "Software Renderer" }; } void setMinimised (bool shouldBeMinimised) override { if (shouldBeMinimised) { - Window root = RootWindow (display, DefaultScreen (display)); + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); XClientMessageEvent clientMsg; clientMsg.display = display; @@ -1296,7 +1135,7 @@ public: clientMsg.data.l[0] = IconicState; ScopedXLock xlock (display); - XSendEvent (display, root, false, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*) &clientMsg); + X11Symbols::getInstance()->xSendEvent (display, root, false, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*) &clientMsg); } else { @@ -1351,10 +1190,10 @@ public: Window parent, root; ScopedXLock xlock (display); - if (XQueryTree (display, windowH, &root, &parent, &windowList, &windowListSize) != 0) + if (X11Symbols::getInstance()->xQueryTree (display, windowH, &root, &parent, &windowList, &windowListSize) != 0) { if (windowList != nullptr) - XFree (windowList); + X11Symbols::getInstance()->xFree (windowList); return parent == possibleParent; } @@ -1374,10 +1213,10 @@ public: Window parent, root; ScopedXLock xlock (display); - if (XQueryTree (display, possibleChild, &root, &parent, &windowList, &windowListSize) != 0) + if (X11Symbols::getInstance()->xQueryTree (display, possibleChild, &root, &parent, &windowList, &windowListSize) != 0) { if (windowList != nullptr) - XFree (windowList); + X11Symbols::getInstance()->xFree (windowList); if (parent == root) return false; @@ -1396,9 +1235,10 @@ public: bool result = false; ScopedXLock xlock (display); - Window parent, root = RootWindow (display, DefaultScreen (display)); + Window parent; + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); - if (XQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0) + if (X11Symbols::getInstance()->xQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0) { for (int i = (int) windowListSize; --i >= 0;) { @@ -1411,7 +1251,7 @@ public: } if (windowList != nullptr) - XFree (windowList); + X11Symbols::getInstance()->xFree (windowList); return result; } @@ -1447,8 +1287,8 @@ public: localPos *= currentScaleFactor; - return XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth) - && XTranslateCoordinates (display, windowH, windowH, localPos.getX(), localPos.getY(), &wx, &wy, &child) + return X11Symbols::getInstance()->xGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth) + && X11Symbols::getInstance()->xTranslateCoordinates (display, windowH, windowH, localPos.getX(), localPos.getY(), &wx, &wy, &child) && child == None; } @@ -1485,10 +1325,10 @@ public: ev.xclient.data.l[3] = 0; ev.xclient.data.l[4] = 0; - XSendEvent (display, RootWindow (display, DefaultScreen (display)), - False, SubstructureRedirectMask | SubstructureNotifyMask, &ev); + X11Symbols::getInstance()->xSendEvent (display, X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)), + False, SubstructureRedirectMask | SubstructureNotifyMask, &ev); - XSync (display, False); + X11Symbols::getInstance()->xSync (display, False); } handleBroughtToFront(); @@ -1506,10 +1346,12 @@ public: Window newStack[] = { otherPeer->windowH, windowH }; ScopedXLock xlock (display); - XRestackWindows (display, newStack, 2); + X11Symbols::getInstance()->xRestackWindows (display, newStack, 2); } else + { jassertfalse; // wrong type of window? + } } bool isFocused() const override @@ -1517,7 +1359,7 @@ public: int revert = 0; Window focusedWindow = 0; ScopedXLock xlock (display); - XGetInputFocus (display, &focusedWindow, &revert); + X11Symbols::getInstance()->xGetInputFocus (display, &focusedWindow, &revert); if (focusedWindow == PointerRoot) return false; @@ -1541,11 +1383,11 @@ public: ScopedXLock xlock (display); if (windowH != 0 - && XGetWindowAttributes (display, windowH, &atts) + && X11Symbols::getInstance()->xGetWindowAttributes (display, windowH, &atts) && atts.map_state == IsViewable && ! isFocused()) { - XSetInputFocus (display, getFocusWindow(), RevertToParent, (::Time) getUserTime()); + X11Symbols::getInstance()->xSetInputFocus (display, getFocusWindow(), RevertToParent, (::Time) getUserTime()); isActiveApplication = true; } } @@ -1564,7 +1406,7 @@ public: void setIcon (const Image& newIcon) override { - const int dataSize = newIcon.getWidth() * newIcon.getHeight() + 2; + auto dataSize = newIcon.getWidth() * newIcon.getHeight() + 2; HeapBlock data (dataSize); int index = 0; @@ -1580,41 +1422,41 @@ public: deleteIconPixmaps(); - XWMHints* wmHints = XGetWMHints (display, windowH); + auto* wmHints = X11Symbols::getInstance()->xGetWMHints (display, windowH); if (wmHints == nullptr) - wmHints = XAllocWMHints(); + wmHints = X11Symbols::getInstance()->xAllocWMHints(); wmHints->flags |= IconPixmapHint | IconMaskHint; wmHints->icon_pixmap = PixmapHelpers::createColourPixmapFromImage (display, newIcon); wmHints->icon_mask = PixmapHelpers::createMaskPixmapFromImage (display, newIcon); - XSetWMHints (display, windowH, wmHints); - XFree (wmHints); + X11Symbols::getInstance()->xSetWMHints (display, windowH, wmHints); + X11Symbols::getInstance()->xFree (wmHints); - XSync (display, False); + X11Symbols::getInstance()->xSync (display, False); } void deleteIconPixmaps() { ScopedXLock xlock (display); - if (auto* wmHints = XGetWMHints (display, windowH)) + if (auto* wmHints = X11Symbols::getInstance()->xGetWMHints (display, windowH)) { if ((wmHints->flags & IconPixmapHint) != 0) { wmHints->flags &= ~IconPixmapHint; - XFreePixmap (display, wmHints->icon_pixmap); + X11Symbols::getInstance()->xFreePixmap (display, wmHints->icon_pixmap); } if ((wmHints->flags & IconMaskHint) != 0) { wmHints->flags &= ~IconMaskHint; - XFreePixmap (display, wmHints->icon_mask); + X11Symbols::getInstance()->xFreePixmap (display, wmHints->icon_mask); } - XSetWMHints (display, windowH, wmHints); - XFree (wmHints); + X11Symbols::getInstance()->xSetWMHints (display, windowH, wmHints); + X11Symbols::getInstance()->xFree (wmHints); } } @@ -1686,7 +1528,7 @@ public: String oldLocale (::setlocale (LC_ALL, nullptr)); ::setlocale (LC_ALL, ""); - XLookupString (&keyEvent, utf8, sizeof (utf8), &sym, nullptr); + X11Symbols::getInstance()->xLookupString (&keyEvent, utf8, sizeof (utf8), &sym, nullptr); if (oldLocale.isNotEmpty()) ::setlocale (LC_ALL, oldLocale.toRawUTF8()); @@ -1695,7 +1537,8 @@ public: keyCode = (int) unicodeChar; if (keyCode < 0x20) - keyCode = (int) XkbKeycodeToKeysym (display, (::KeyCode) keyEvent.keycode, 0, ModifierKeys::currentModifiers.isShiftDown() ? 1 : 0); + keyCode = (int) X11Symbols::getInstance()->xkbKeycodeToKeysym (display, (::KeyCode) keyEvent.keycode, 0, + ModifierKeys::currentModifiers.isShiftDown() ? 1 : 0); keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true); } @@ -1791,10 +1634,10 @@ public: static bool isKeyReleasePartOfAutoRepeat (const XKeyEvent& keyReleaseEvent) { - if (XPending (display)) + if (X11Symbols::getInstance()->xPending (display)) { XEvent e; - XPeekEvent (display, &e); + X11Symbols::getInstance()->xPeekEvent (display, &e); // Look for a subsequent key-down event with the same timestamp and keycode return e.type == KeyPressEventType @@ -1814,11 +1657,11 @@ public: { ScopedXLock xlock (display); - sym = XkbKeycodeToKeysym (display, (::KeyCode) keyEvent.keycode, 0, 0); + sym = X11Symbols::getInstance()->xkbKeycodeToKeysym (display, (::KeyCode) keyEvent.keycode, 0, 0); } auto oldMods = ModifierKeys::currentModifiers; - const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false); + auto keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false); if (oldMods != ModifierKeys::currentModifiers) handleModifierKeysChange(); @@ -1983,9 +1826,9 @@ public: if (exposeEvent.window != windowH) { Window child; - XTranslateCoordinates (display, exposeEvent.window, windowH, - exposeEvent.x, exposeEvent.y, &exposeEvent.x, &exposeEvent.y, - &child); + X11Symbols::getInstance()->xTranslateCoordinates (display, exposeEvent.window, windowH, + exposeEvent.x, exposeEvent.y, &exposeEvent.x, &exposeEvent.y, + &child); } // exposeEvent is in local window local coordinates so do not convert with @@ -1993,14 +1836,14 @@ public: repaint (Rectangle (exposeEvent.x, exposeEvent.y, exposeEvent.width, exposeEvent.height) / currentScaleFactor); - while (XEventsQueued (display, QueuedAfterFlush) > 0) + while (X11Symbols::getInstance()->xEventsQueued (display, QueuedAfterFlush) > 0) { - XPeekEvent (display, &nextEvent); + X11Symbols::getInstance()->xPeekEvent (display, &nextEvent); if (nextEvent.type != Expose || nextEvent.xany.window != exposeEvent.window) break; - XNextEvent (display, &nextEvent); + X11Symbols::getInstance()->xNextEvent (display, &nextEvent); auto& nextExposeEvent = (const XExposeEvent&) nextEvent.xexpose; repaint (Rectangle (nextExposeEvent.x, nextExposeEvent.y, nextExposeEvent.width, nextExposeEvent.height) / currentScaleFactor); @@ -2038,7 +1881,7 @@ public: { // Deal with modifier/keyboard mapping ScopedXLock xlock (display); - XRefreshKeyboardMapping (&mappingEvent); + X11Symbols::getInstance()->xRefreshKeyboardMapping (&mappingEvent); updateModifierMappings(); } } @@ -2051,12 +1894,12 @@ public: if (atom == atoms->protocolList [Atoms::PING]) { - Window root = RootWindow (display, DefaultScreen (display)); + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); clientMsg.window = root; - XSendEvent (display, root, False, NoEventMask, &event); - XFlush (display); + X11Symbols::getInstance()->xSendEvent (display, root, False, NoEventMask, &event); + X11Symbols::getInstance()->xFlush (display); } else if (atom == atoms->protocolList [Atoms::TAKE_FOCUS]) { @@ -2066,14 +1909,14 @@ public: ScopedXLock xlock (display); if (clientMsg.window != 0 - && XGetWindowAttributes (display, clientMsg.window, &atts)) + && X11Symbols::getInstance()->xGetWindowAttributes (display, clientMsg.window, &atts)) { if (atts.map_state == IsViewable) - XSetInputFocus (display, - (clientMsg.window == windowH ? getFocusWindow() - : clientMsg.window), - RevertToParent, - (::Time) clientMsg.data.l[1]); + X11Symbols::getInstance()->xSetInputFocus (display, + (clientMsg.window == windowH ? getFocusWindow() + : clientMsg.window), + RevertToParent, + (::Time) clientMsg.data.l[1]); } } } @@ -2143,15 +1986,15 @@ public: { switch (clientMsg.data.l[1]) { - case XEMBED_EMBEDDED_NOTIFY: + case 0: // XEMBED_EMBEDDED_NOTIFY parentWindow = (::Window) clientMsg.data.l[3]; updateWindowBounds(); component.setBounds (bounds); break; - case XEMBED_FOCUS_IN: + case 4: // XEMBED_FOCUS_IN handleFocusInEvent(); break; - case XEMBED_FOCUS_OUT: + case 5: // XEMBED_FOCUS_OUT handleFocusOutEvent(); break; @@ -2164,7 +2007,7 @@ public: void showMouseCursor (Cursor cursor) noexcept { ScopedXLock xlock (display); - XDefineCursor (display, windowH, cursor); + X11Symbols::getInstance()->xDefineCursor (display, windowH, cursor); } //============================================================================== @@ -2188,9 +2031,8 @@ public: void repaintOpenGLContexts() { - for (int i = 0; i < glRepaintListeners.size(); ++i) - if (auto* c = glRepaintListeners [i]) - c->handleCommandMessage (0); + for (auto* c : glRepaintListeners) + c->handleCommandMessage (0); } //============================================================================== @@ -2203,14 +2045,14 @@ public: XSetWindowAttributes swa; swa.event_mask = KeyPressMask | KeyReleaseMask | FocusChangeMask; - keyProxy = XCreateWindow (display, windowH, - -1, -1, 1, 1, 0, 0, - InputOnly, CopyFromParent, - CWEventMask, - &swa); + keyProxy = X11Symbols::getInstance()->xCreateWindow (display, windowH, + -1, -1, 1, 1, 0, 0, + InputOnly, CopyFromParent, + CWEventMask, + &swa); - XMapWindow (display, keyProxy); - XSaveContext (display, (XID) keyProxy, windowHandleXContext, (XPointer) this); + X11Symbols::getInstance()->xMapWindow (display, keyProxy); + X11Symbols::getInstance()->xSaveContext (display, (XID) keyProxy, windowHandleXContext, (XPointer) this); } return keyProxy; @@ -2224,14 +2066,14 @@ public: { XPointer handlePointer; - if (! XFindContext (display, (XID) keyProxy, windowHandleXContext, &handlePointer)) - XDeleteContext (display, (XID) keyProxy, windowHandleXContext); + if (! X11Symbols::getInstance()->xFindContext (display, (XID) keyProxy, windowHandleXContext, &handlePointer)) + X11Symbols::getInstance()->xDeleteContext (display, (XID) keyProxy, windowHandleXContext); - XDestroyWindow (display, keyProxy); - XSync (display, false); + X11Symbols::getInstance()->xDestroyWindow (display, keyProxy); + X11Symbols::getInstance()->xSync (display, false); XEvent event; - while (XCheckWindowEvent (display, keyProxy, getAllEventsMask(), &event) == True) + while (X11Symbols::getInstance()->xCheckWindowEvent (display, keyProxy, getAllEventsMask(), &event) == True) {} keyProxy = 0; @@ -2258,11 +2100,12 @@ private: ScopedXLock xlock (display); XShmSegmentInfo segmentinfo; - auto testImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), - 24, ZPixmap, nullptr, &segmentinfo, 64, 64); + auto testImage = X11Symbols::getInstance()->xShmCreateImage (display, + X11Symbols::getInstance()->xDefaultVisual (display, X11Symbols::getInstance()->xDefaultScreen (display)), + 24, ZPixmap, nullptr, &segmentinfo, 64, 64); useARGBImagesForRendering = (testImage->bits_per_pixel == 32); - XDestroyImage (testImage); + X11Symbols::getInstance()->xDestroyImage (testImage); } #endif } @@ -2275,7 +2118,7 @@ private: ScopedXLock xlock (display); XEvent evt; - while (XCheckTypedWindowEvent (display, peer.windowH, peer.shmCompletionEvent, &evt)) + while (X11Symbols::getInstance()->xCheckTypedWindowEvent (display, peer.windowH, peer.shmCompletionEvent, &evt)) --shmPaintsPending; } @@ -2389,6 +2232,7 @@ private: bool useARGBImagesForRendering; int shmPaintsPending = 0; #endif + JUCE_DECLARE_NON_COPYABLE (LinuxRepaintManager) }; @@ -2425,8 +2269,8 @@ private: static void updateKeyStates (int keycode, bool press) noexcept { - const int keybyte = keycode >> 3; - const int keybit = (1 << (keycode & 7)); + auto keybyte = keycode >> 3; + auto keybit = (1 << (keycode & 7)); if (press) Keys::keyStates[keybyte] = static_cast (Keys::keyStates[keybyte] | keybit); @@ -2495,13 +2339,13 @@ private: static void updateModifierMappings() noexcept { ScopedXLock xlock (display); - int altLeftCode = XKeysymToKeycode (display, XK_Alt_L); - int numLockCode = XKeysymToKeycode (display, XK_Num_Lock); + auto altLeftCode = X11Symbols::getInstance()->xKeysymToKeycode (display, XK_Alt_L); + auto numLockCode = X11Symbols::getInstance()->xKeysymToKeycode (display, XK_Num_Lock); Keys::AltMask = 0; Keys::NumLockMask = 0; - if (auto* mapping = XGetModifierMapping (display)) + if (auto* mapping = X11Symbols::getInstance()->xGetModifierMapping (display)) { for (int modifierIdx = 0; modifierIdx < 8; ++modifierIdx) { @@ -2516,14 +2360,14 @@ private: } } - XFreeModifiermap (mapping); + X11Symbols::getInstance()->xFreeModifiermap (mapping); } } //============================================================================== static void xchangeProperty (Window wndH, Atom property, Atom type, int format, const void* data, int numElements) { - XChangeProperty (display, wndH, property, type, format, PropModeReplace, (const unsigned char*) data, numElements); + X11Symbols::getInstance()->xChangeProperty (display, wndH, property, type, format, PropModeReplace, (const unsigned char*) data, numElements); } void removeWindowDecorations (Window wndH) @@ -2663,8 +2507,8 @@ private: resetDragAndDrop(); // Get defaults for various properties - const int screen = DefaultScreen (display); - Window root = RootWindow (display, screen); + auto screen = X11Symbols::getInstance()->xDefaultScreen (display); + auto root = X11Symbols::getInstance()->xRootWindow (display, screen); parentWindow = parentToAddTo; @@ -2678,8 +2522,8 @@ private: } // Create and install a colormap suitable fr our visual - Colormap colormap = XCreateColormap (display, root, visual, AllocNone); - XInstallColormap (display, colormap); + auto colormap = X11Symbols::getInstance()->xCreateColormap (display, root, visual, AllocNone); + X11Symbols::getInstance()->xInstallColormap (display, colormap); // Set up the window attributes XSetWindowAttributes swa; @@ -2689,30 +2533,32 @@ private: swa.override_redirect = ((styleFlags & windowIsTemporary) != 0) ? True : False; swa.event_mask = getAllEventsMask(); - windowH = XCreateWindow (display, parentToAddTo != 0 ? parentToAddTo : root, - 0, 0, 1, 1, - 0, depth, InputOutput, visual, - CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, - &swa); + windowH = X11Symbols::getInstance()->xCreateWindow (display, parentToAddTo != 0 ? parentToAddTo : root, + 0, 0, 1, 1, + 0, depth, InputOutput, visual, + CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, + &swa); // Set the window context to identify the window handle object - if (XSaveContext (display, (XID) windowH, windowHandleXContext, (XPointer) this)) + if (X11Symbols::getInstance()->xSaveContext (display, (XID) windowH, windowHandleXContext, (XPointer) this)) { // Failed jassertfalse; + Logger::outputDebugString ("Failed to create context information for window.\n"); - XDestroyWindow (display, windowH); + X11Symbols::getInstance()->xDestroyWindow (display, windowH); windowH = 0; + return; } // Set window manager hints - XWMHints* wmHints = XAllocWMHints(); + XWMHints* wmHints = X11Symbols::getInstance()->xAllocWMHints(); wmHints->flags = InputHint | StateHint; wmHints->input = True; // Locally active input model wmHints->initial_state = NormalState; - XSetWMHints (display, windowH, wmHints); - XFree (wmHints); + X11Symbols::getInstance()->xSetWMHints (display, windowH, wmHints); + X11Symbols::getInstance()->xFree (wmHints); // Set the window type setWindowType(); @@ -2726,7 +2572,7 @@ private: setTitle (component.getName()); // Associate the PID, allowing to be shut down when something goes wrong - unsigned long pid = (unsigned long) getpid(); + auto pid = (unsigned long) getpid(); xchangeProperty (windowH, atoms->pid, XA_CARDINAL, 32, &pid, 1); // Set window manager protocols @@ -2746,7 +2592,7 @@ private: #if JUCE_USE_XSHM if (XSHMHelpers::isShmAvailable (display)) - shmCompletionEvent = XShmGetEventBase (display) + ShmCompletion; + shmCompletionEvent = X11Symbols::getInstance()->xShmGetEventBase (display) + ShmCompletion; #endif } @@ -2759,17 +2605,17 @@ private: if (keyProxy != 0) deleteKeyProxy(); - if (! XFindContext (display, (XID) windowH, windowHandleXContext, &handlePointer)) - XDeleteContext (display, (XID) windowH, windowHandleXContext); + if (! X11Symbols::getInstance()->xFindContext (display, (XID) windowH, windowHandleXContext, &handlePointer)) + X11Symbols::getInstance()->xDeleteContext (display, (XID) windowH, windowHandleXContext); - XDestroyWindow (display, windowH); + X11Symbols::getInstance()->xDestroyWindow (display, windowH); // Wait for it to complete and then remove any events for this // window from the event queue. - XSync (display, false); + X11Symbols::getInstance()->xSync (display, false); XEvent event; - while (XCheckWindowEvent (display, windowH, getAllEventsMask(), &event) == True) + while (X11Symbols::getInstance()->xCheckWindowEvent (display, windowH, getAllEventsMask(), &event) == True) {} } @@ -2805,7 +2651,7 @@ private: if (! prop.success) return 0; - long result; + long result = 0; memcpy (&result, prop.data, sizeof (long)); return result; @@ -2820,7 +2666,7 @@ private: else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0) { ScopedXLock xlock (display); - Atom hints = Atoms::getIfExists (display, "_NET_FRAME_EXTENTS"); + auto hints = Atoms::getIfExists (display, "_NET_FRAME_EXTENTS"); if (hints != None) { @@ -2855,11 +2701,11 @@ private: ScopedXLock xlock (display); - if (XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth)) + if (X11Symbols::getInstance()->xGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth)) { int rootX = 0, rootY = 0; - if (! XTranslateCoordinates (display, windowH, root, 0, 0, &rootX, &rootY, &child)) + if (! X11Symbols::getInstance()->xTranslateCoordinates (display, windowH, root, 0, 0, &rootX, &rootY, &child)) rootX = rootY = 0; if (parentWindow == 0) @@ -2930,7 +2776,7 @@ private: msg.data.l[0] = (long) windowH; ScopedXLock xlock (display); - XSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg); + X11Symbols::getInstance()->xSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg); } bool sendExternalDragAndDropMessage (XClientMessageEvent& msg, Window targetWindow) @@ -2942,7 +2788,7 @@ private: msg.data.l[0] = (long) windowH; ScopedXLock xlock (display); - return XSendEvent (display, targetWindow, False, 0, (XEvent*) &msg) != 0; + return X11Symbols::getInstance()->xSendEvent (display, targetWindow, False, 0, (XEvent*) &msg) != 0; } void sendExternalDragAndDropDrop (Window targetWindow) @@ -2977,7 +2823,7 @@ private: msg.message_type = atoms->XdndPosition; - Point mousePos (Desktop::getInstance().getMousePosition()); + auto mousePos = Desktop::getInstance().getMousePosition(); if (dragState->silentRect.contains (mousePos)) // we've been asked to keep silent return; @@ -3052,7 +2898,7 @@ private: (int) dragState->textOrFiles.getNumBytesAsUTF8()); } - XSendEvent (display, evt.xselectionrequest.requestor, True, 0, &s); + X11Symbols::getInstance()->xSendEvent (display, evt.xselectionrequest.requestor, True, 0, &s); } void handleExternalDragAndDropStatus (const XClientMessageEvent& clientMsg) @@ -3069,9 +2915,9 @@ private: { if ((clientMsg.data.l[1] & 2) == 0) // target requests silent rectangle dragState->silentRect.setBounds ((int) clientMsg.data.l[2] >> 16, - (int) clientMsg.data.l[2] & 0xffff, - (int) clientMsg.data.l[3] >> 16, - (int) clientMsg.data.l[3] & 0xffff); + (int) clientMsg.data.l[2] & 0xffff, + (int) clientMsg.data.l[3] >> 16, + (int) clientMsg.data.l[3] & 0xffff); dragState->canDrop = true; } @@ -3081,7 +2927,7 @@ private: void handleExternalDragButtonReleaseEvent() { if (dragState->dragging) - XUngrabPointer (display, CurrentTime); + X11Symbols::getInstance()->xUngrabPointer (display, CurrentTime); if (dragState->canDrop) { @@ -3096,7 +2942,8 @@ private: void handleExternalDragMotionNotify() { - Window targetWindow = externalFindDragTargetWindow (RootWindow (display, DefaultScreen (display))); + auto targetWindow = externalFindDragTargetWindow (X11Symbols::getInstance()->xRootWindow (display, + X11Symbols::getInstance()->xDefaultScreen (display))); if (dragState->targetWindow != targetWindow) { @@ -3104,7 +2951,7 @@ private: sendExternalDragAndDropLeave (dragState->targetWindow); dragState->canDrop = false; - dragState->silentRect = Rectangle(); + dragState->silentRect = {}; if (targetWindow == None) return; @@ -3135,7 +2982,7 @@ private: dropPos = Desktop::getInstance().getDisplays().physicalToLogical (dropPos); dropPos -= bounds.getPosition(); - Atom targetAction = atoms->XdndActionCopy; + auto targetAction = atoms->XdndActionCopy; for (int i = numElementsInArray (atoms->allowedActions); --i >= 0;) { @@ -3301,19 +3148,19 @@ private: && dragAndDropCurrentMimeType != None) { ScopedXLock xlock (display); - XConvertSelection (display, - atoms->XdndSelection, - dragAndDropCurrentMimeType, - Atoms::getCreating (display, "JXSelectionWindowProperty"), - windowH, - (::Time) clientMsg.data.l[2]); + X11Symbols::getInstance()->xConvertSelection (display, + atoms->XdndSelection, + dragAndDropCurrentMimeType, + Atoms::getCreating (display, "JXSelectionWindowProperty"), + windowH, + (::Time) clientMsg.data.l[2]); } } bool isWindowDnDAware (Window w) const { int numProperties = 0; - auto* properties = XListProperties (display, w, &numProperties); + auto* properties = X11Symbols::getInstance()->xListProperties (display, w, &numProperties); bool dndAwarePropFound = false; for (int i = 0; i < numProperties; ++i) @@ -3321,7 +3168,7 @@ private: dndAwarePropFound = true; if (properties != nullptr) - XFree (properties); + X11Symbols::getInstance()->xFree (properties); return dndAwarePropFound; } @@ -3349,8 +3196,8 @@ private: int phony; unsigned int uphony; - XQueryPointer (display, targetWindow, &phonyWin, &child, - &phony, &phony, &phony, &phony, &uphony); + X11Symbols::getInstance()->xQueryPointer (display, targetWindow, &phonyWin, &child, + &phony, &phony, &phony, &phony, &uphony); return externalFindDragTargetWindow (child); } @@ -3365,15 +3212,15 @@ private: dragState->targetWindow = windowH; dragState->completionCallback = cb; - const int pointerGrabMask = Button1MotionMask | ButtonReleaseMask; + auto pointerGrabMask = (unsigned int) (Button1MotionMask | ButtonReleaseMask); - if (XGrabPointer (display, windowH, True, pointerGrabMask, - GrabModeAsync, GrabModeAsync, None, None, CurrentTime) == GrabSuccess) + if (X11Symbols::getInstance()->xGrabPointer (display, windowH, True, pointerGrabMask, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime) == GrabSuccess) { // No other method of changing the pointer seems to work, this call is needed from this very context - XChangeActivePointerGrab (display, pointerGrabMask, (Cursor) createDraggingHandCursor(), CurrentTime); + X11Symbols::getInstance()->xChangeActivePointerGrab (display, pointerGrabMask, (Cursor) createDraggingHandCursor(), CurrentTime); - XSetSelectionOwner (display, atoms->XdndSelection, windowH, CurrentTime); + X11Symbols::getInstance()->xSetSelectionOwner (display, atoms->XdndSelection, windowH, CurrentTime); // save the available types to XdndTypeList xchangeProperty (windowH, atoms->XdndTypeList, XA_ATOM, 32, @@ -3397,7 +3244,7 @@ private: if (dragState->dragging) { ScopedXLock xlock (display); - XUngrabPointer (display, CurrentTime); + X11Symbols::getInstance()->xUngrabPointer (display, CurrentTime); } if (dragState->completionCallback != nullptr) @@ -3418,7 +3265,7 @@ private: void initialisePointerMap() { - const int numButtons = XGetPointerMapping (display, nullptr, 0); + auto numButtons = X11Symbols::getInstance()->xGetPointerMapping (display, nullptr, 0); pointerMap[2] = pointerMap[3] = pointerMap[4] = Keys::NoButton; if (numButtons == 2) @@ -3525,7 +3372,7 @@ void Displays::findDisplays (float masterScale) { if (hints != None) { - GetXProperty prop (display, RootWindow (display, screenNum), hints, 0, 4, false, XA_CARDINAL); + GetXProperty prop (display, X11Symbols::getInstance()->xRootWindow (display, screenNum), hints, 0, 4, false, XA_CARDINAL); if (prop.success && prop.actualType == XA_CARDINAL && prop.actualFormat == 32 && prop.numItems == 4) return prop.data; @@ -3538,19 +3385,18 @@ void Displays::findDisplays (float masterScale) { int major_opcode, first_event, first_error; - if (XQueryExtension (display, "RANDR", &major_opcode, &first_event, &first_error)) + if (X11Symbols::getInstance()->xQueryExtension (display, "RANDR", &major_opcode, &first_event, &first_error)) { - auto& xrandr = XRandrWrapper::getInstance(); - - auto numMonitors = ScreenCount (display); - auto mainDisplay = xrandr.getOutputPrimary (display, RootWindow (display, 0)); + auto numMonitors = X11Symbols::getInstance()->xScreenCount (display); + auto mainDisplay = X11Symbols::getInstance()->xRRGetOutputPrimary (display, X11Symbols::getInstance()->xRootWindow (display, 0)); for (int i = 0; i < numMonitors; ++i) { if (getWorkAreaPropertyData (i) == nullptr) continue; - if (auto* screens = xrandr.getScreenResources (display, RootWindow (display, i))) + if (auto* screens = X11Symbols::getInstance()->xRRGetScreenResources (display, + X11Symbols::getInstance()->xRootWindow (display, i))) { for (int j = 0; j < screens->noutput; ++j) { @@ -3561,15 +3407,14 @@ void Displays::findDisplays (float masterScale) if (! mainDisplay) mainDisplay = screens->outputs[j]; - if (auto* output = xrandr.getOutputInfo (display, screens, screens->outputs[j])) + if (auto* output = X11Symbols::getInstance()->xRRGetOutputInfo (display, screens, screens->outputs[j])) { if (output->crtc) { - if (auto* crtc = xrandr.getCrtcInfo (display, screens, output->crtc)) + if (auto* crtc = X11Symbols::getInstance()->xRRGetCrtcInfo (display, screens, output->crtc)) { Display d; - d.totalArea = Rectangle (crtc->x, crtc->y, - (int) crtc->width, (int) crtc->height); + d.totalArea = { crtc->x, crtc->y, (int) crtc->width, (int) crtc->height }; d.isMain = (mainDisplay == screens->outputs[j]) && (i == 0); d.dpi = getDisplayDPI (display, 0); @@ -3578,7 +3423,7 @@ void Displays::findDisplays (float masterScale) d.dpi = ((static_cast (crtc->width) * 25.4 * 0.5) / static_cast (output->mm_width)) + ((static_cast (crtc->height) * 25.4 * 0.5) / static_cast (output->mm_height)); - double scale = getScaleForDisplay (output->name, d.dpi); + auto scale = getScaleForDisplay (output->name, d.dpi); scale = (scale <= 0.1 ? 1.0 : scale); d.scale = masterScale * scale; @@ -3588,16 +3433,16 @@ void Displays::findDisplays (float masterScale) else displays.add (d); - xrandr.freeCrtcInfo (crtc); + X11Symbols::getInstance()->xRRFreeCrtcInfo (crtc); } } - xrandr.freeOutputInfo (output); + X11Symbols::getInstance()->xRRFreeOutputInfo (output); } } } - xrandr.freeScreenResources (screens); + X11Symbols::getInstance()->xRRFreeScreenResources (screens); } } @@ -3611,19 +3456,17 @@ void Displays::findDisplays (float masterScale) #if JUCE_USE_XINERAMA { auto screens = XineramaQueryDisplays (display); - int numMonitors = screens.size(); + auto numMonitors = screens.size(); for (int index = 0; index < numMonitors; ++index) { - for (int j = numMonitors; --j >= 0;) + for (auto j = numMonitors; --j >= 0;) { if (screens[j].screen_number == index) { Display d; - d.totalArea = Rectangle (screens[j].x_org, - screens[j].y_org, - screens[j].width, - screens[j].height); + d.totalArea = { screens[j].x_org, screens[j].y_org, + screens[j].width, screens[j].height }; d.isMain = (index == 0); d.scale = masterScale; d.dpi = getDisplayDPI (display, 0); // (all screens share the same DPI) @@ -3639,7 +3482,7 @@ void Displays::findDisplays (float masterScale) { if (hints != None) { - auto numMonitors = ScreenCount (display); + auto numMonitors = X11Symbols::getInstance()->xScreenCount (display); for (int i = 0; i < numMonitors; ++i) { @@ -3654,8 +3497,8 @@ void Displays::findDisplays (float masterScale) } Display d; - d.totalArea = Rectangle ((int) position[0], (int) position[1], - (int) position[2], (int) position[3]); + d.totalArea = { (int) position[0], (int) position[1], + (int) position[2], (int) position[3] }; d.isMain = displays.isEmpty(); d.scale = masterScale; d.dpi = getDisplayDPI (display, i); @@ -3668,8 +3511,8 @@ void Displays::findDisplays (float masterScale) if (displays.isEmpty()) { Display d; - d.totalArea = Rectangle (DisplayWidth (display, DefaultScreen (display)), - DisplayHeight (display, DefaultScreen (display))); + d.totalArea = { X11Symbols::getInstance()->xDisplayWidth (display, X11Symbols::getInstance()->xDefaultScreen (display)), + X11Symbols::getInstance()->xDisplayHeight (display, X11Symbols::getInstance()->xDefaultScreen (display)) }; d.isMain = true; d.scale = masterScale; d.dpi = getDisplayDPI (display, 0); @@ -3733,10 +3576,10 @@ Point MouseInputSource::getCurrentRawMousePosition() ScopedXLock xlock (display); - if (XQueryPointer (display, - RootWindow (display, DefaultScreen (display)), - &root, &child, - &x, &y, &winx, &winy, &mask) == False) + if (X11Symbols::getInstance()->xQueryPointer (display, + X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)), + &root, &child, + &x, &y, &winx, &winy, &mask) == False) { // Pointer not on the default screen x = y = -1; @@ -3752,9 +3595,10 @@ void MouseInputSource::setRawMousePosition (Point newPosition) if (auto display = xDisplay.display) { ScopedXLock xlock (display); - Window root = RootWindow (display, DefaultScreen (display)); + + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); newPosition = Desktop::getInstance().getDisplays().logicalToPhysical (newPosition); - XWarpPointer (display, None, root, 0, 0, 0, 0, roundToInt (newPosition.getX()), roundToInt (newPosition.getY())); + X11Symbols::getInstance()->xWarpPointer (display, None, root, 0, 0, 0, 0, roundToInt (newPosition.getX()), roundToInt (newPosition.getY())); } } @@ -3781,7 +3625,7 @@ void Desktop::setScreenSaverEnabled (bool isEnabled) if (auto display = xDisplay.display) { - typedef void (*tXScreenSaverSuspend) (Display*, Bool); + using tXScreenSaverSuspend = void (*) (Display*, Bool); static tXScreenSaverSuspend xScreenSaverSuspend = nullptr; if (xScreenSaverSuspend == nullptr) @@ -3789,6 +3633,7 @@ void Desktop::setScreenSaverEnabled (bool isEnabled) xScreenSaverSuspend = (tXScreenSaverSuspend) dlsym (h, "XScreenSaverSuspend"); ScopedXLock xlock (display); + if (xScreenSaverSuspend != nullptr) xScreenSaverSuspend (display, ! isEnabled); } @@ -3907,68 +3752,34 @@ void* CustomMouseCursorInfo::create() const ScopedXLock xlock (display); auto imageW = (unsigned int) image.getWidth(); auto imageH = (unsigned int) image.getHeight(); - int hotspotX = hotspot.x; - int hotspotY = hotspot.y; + auto hotspotX = hotspot.x; + auto hotspotY = hotspot.y; #if JUCE_USE_XCURSOR + if (auto* xcImage = X11Symbols::getInstance()->xcursorImageCreate ((int) imageW, (int) imageH)) { - using tXcursorSupportsARGB = XcursorBool (*) (Display*); - using tXcursorImageCreate = XcursorImage* (*) (int, int); - using tXcursorImageDestroy = void (*) (XcursorImage*); - using tXcursorImageLoadCursor = Cursor (*) (Display*, const XcursorImage*); + xcImage->xhot = (XcursorDim) hotspotX; + xcImage->yhot = (XcursorDim) hotspotY; + auto* dest = xcImage->pixels; - static tXcursorSupportsARGB xcursorSupportsARGB = nullptr; - static tXcursorImageCreate xcursorImageCreate = nullptr; - static tXcursorImageDestroy xcursorImageDestroy = nullptr; - static tXcursorImageLoadCursor xcursorImageLoadCursor = nullptr; - static bool hasBeenLoaded = false; + for (int y = 0; y < (int) imageH; ++y) + for (int x = 0; x < (int) imageW; ++x) + *dest++ = image.getPixelAt (x, y).getARGB(); - if (! hasBeenLoaded) + auto* result = (void*) X11Symbols::getInstance()->xcursorImageLoadCursor (display, xcImage); + X11Symbols::getInstance()->xcursorImageDestroy (xcImage); + + if (result != nullptr) { - hasBeenLoaded = true; - - if (void* h = dlopen ("libXcursor.so.1", RTLD_GLOBAL | RTLD_NOW)) - { - xcursorSupportsARGB = (tXcursorSupportsARGB) dlsym (h, "XcursorSupportsARGB"); - xcursorImageCreate = (tXcursorImageCreate) dlsym (h, "XcursorImageCreate"); - xcursorImageLoadCursor = (tXcursorImageLoadCursor) dlsym (h, "XcursorImageLoadCursor"); - xcursorImageDestroy = (tXcursorImageDestroy) dlsym (h, "XcursorImageDestroy"); - - if (xcursorSupportsARGB == nullptr || xcursorImageCreate == nullptr - || xcursorImageLoadCursor == nullptr || xcursorImageDestroy == nullptr - || ! xcursorSupportsARGB (display)) - xcursorSupportsARGB = nullptr; - } - } - - if (xcursorSupportsARGB != nullptr) - { - if (XcursorImage* xcImage = xcursorImageCreate ((int) imageW, (int) imageH)) - { - xcImage->xhot = (XcursorDim) hotspotX; - xcImage->yhot = (XcursorDim) hotspotY; - XcursorPixel* dest = xcImage->pixels; - - for (int y = 0; y < (int) imageH; ++y) - for (int x = 0; x < (int) imageW; ++x) - *dest++ = image.getPixelAt (x, y).getARGB(); - - void* result = (void*) xcursorImageLoadCursor (display, xcImage); - xcursorImageDestroy (xcImage); - - if (result != nullptr) - { - cursorMap[(Cursor) result] = display; - return result; - } - } + cursorMap[(Cursor) result] = display; + return result; } } #endif - Window root = RootWindow (display, DefaultScreen (display)); + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); unsigned int cursorW, cursorH; - if (! XQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH)) + if (! X11Symbols::getInstance()->xQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH)) return nullptr; Image im (Image::ARGB, (int) cursorW, (int) cursorH, true); @@ -3990,16 +3801,16 @@ void* CustomMouseCursorInfo::create() const } } - const unsigned int stride = (cursorW + 7) >> 3; + auto stride = (cursorW + 7) >> 3; HeapBlock maskPlane, sourcePlane; maskPlane.calloc (stride * cursorH); sourcePlane.calloc (stride * cursorH); - const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); + auto msbfirst = (X11Symbols::getInstance()->xBitmapBitOrder (display) == MSBFirst); - for (int y = (int) cursorH; --y >= 0;) + for (auto y = (int) cursorH; --y >= 0;) { - for (int x = (int) cursorW; --x >= 0;) + for (auto x = (int) cursorW; --x >= 0;) { auto mask = (char) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); auto offset = (unsigned int) y * stride + ((unsigned int) x >> 3); @@ -4011,18 +3822,18 @@ void* CustomMouseCursorInfo::create() const } } - Pixmap sourcePixmap = XCreatePixmapFromBitmapData (display, root, sourcePlane.getData(), cursorW, cursorH, 0xffff, 0, 1); - Pixmap maskPixmap = XCreatePixmapFromBitmapData (display, root, maskPlane.getData(), cursorW, cursorH, 0xffff, 0, 1); + auto sourcePixmap = X11Symbols::getInstance()->xCreatePixmapFromBitmapData (display, root, sourcePlane.getData(), cursorW, cursorH, 0xffff, 0, 1); + auto maskPixmap = X11Symbols::getInstance()->xCreatePixmapFromBitmapData (display, root, maskPlane.getData(), cursorW, cursorH, 0xffff, 0, 1); 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, - (unsigned int) hotspotX, (unsigned int) hotspotY); + auto* result = (void*) X11Symbols::getInstance()->xCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, + (unsigned int) hotspotX, (unsigned int) hotspotY); - XFreePixmap (display, sourcePixmap); - XFreePixmap (display, maskPixmap); + X11Symbols::getInstance()->xFreePixmap (display, sourcePixmap); + X11Symbols::getInstance()->xFreePixmap (display, maskPixmap); cursorMap[(Cursor) result] = display; return result; @@ -4039,7 +3850,7 @@ void MouseCursor::deleteMouseCursor (void* cursorHandle, bool) ScopedXLock xlock (display); cursorMap.erase ((Cursor) cursorHandle); - XFreeCursor (display, (Cursor) cursorHandle); + X11Symbols::getInstance()->xFreeCursor (display, (Cursor) cursorHandle); } } } @@ -4079,10 +3890,12 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty case CopyingCursor: { - 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 }; + 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; return CustomMouseCursorInfo (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), { 1, 3 }).create(); @@ -4090,13 +3903,15 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty case NumStandardCursorTypes: default: + { jassertfalse; return None; + } } ScopedXLock xlock (display); - auto* result = (void*) XCreateFontCursor (display, shape); + auto* result = (void*) X11Symbols::getInstance()->xCreateFontCursor (display, shape); cursorMap[(Cursor) result] = display; return result; diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index a871524b0d..98c4ebc312 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -4704,10 +4704,12 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT if (copyCursor == nullptr) { - 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 }; + 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; copyCursor = CustomMouseCursorInfo (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), { 1, 3 }).create(); diff --git a/modules/juce_gui_extra/juce_gui_extra.cpp b/modules/juce_gui_extra/juce_gui_extra.cpp index fbd8152cf1..6491e0ef95 100644 --- a/modules/juce_gui_extra/juce_gui_extra.cpp +++ b/modules/juce_gui_extra/juce_gui_extra.cpp @@ -31,6 +31,7 @@ #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 #define JUCE_EVENTS_INCLUDE_WIN32_MESSAGE_WINDOW 1 #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 +#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 #if JUCE_USE_WINRT_WEBVIEW #define JUCE_EVENTS_INCLUDE_WINRT_WRAPPER 1 @@ -99,28 +100,18 @@ #endif //============================================================================== -#elif JUCE_LINUX - #include - #include - #include - #undef SIZEOF - #undef KeyPress +#elif JUCE_LINUX && JUCE_WEB_BROWSER + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant", "-Wparentheses") - #if JUCE_WEB_BROWSER - #include - #include - #include + // If you're missing this header, you need to install the webkit2gtk-4.0 package + #include - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant", "-Wparentheses") + JUCE_END_IGNORE_WARNINGS_GCC_LIKE - #include - - JUCE_END_IGNORE_WARNINGS_GCC_LIKE - - #include - #include - #include - #endif + // If you're missing these headers, you need to install the webkit2gtk-4.0 package + #include + #include + #include #endif //============================================================================== diff --git a/modules/juce_gui_extra/juce_gui_extra.h b/modules/juce_gui_extra/juce_gui_extra.h index 10cc461129..3d712e51b6 100644 --- a/modules/juce_gui_extra/juce_gui_extra.h +++ b/modules/juce_gui_extra/juce_gui_extra.h @@ -50,7 +50,7 @@ //============================================================================== /** Config: JUCE_WEB_BROWSER - This lets you disable the WebBrowserComponent class (Mac and Windows). + This lets you disable the WebBrowserComponent class (Mac, Windows, and Linux). If you're not using any embedded web-pages, turning this off may reduce your code size. */ #ifndef JUCE_WEB_BROWSER diff --git a/modules/juce_gui_extra/native/juce_linux_X11_SystemTrayIcon.cpp b/modules/juce_gui_extra/native/juce_linux_X11_SystemTrayIcon.cpp index bde343bd6c..df166569fa 100644 --- a/modules/juce_gui_extra/native/juce_linux_X11_SystemTrayIcon.cpp +++ b/modules/juce_gui_extra/native/juce_linux_X11_SystemTrayIcon.cpp @@ -29,21 +29,21 @@ public: ScopedXLock xlock (display); - Screen* const screen = XDefaultScreenOfDisplay (display); - const int screenNumber = XScreenNumberOfScreen (screen); + auto* screen = X11Symbols::getInstance()->xDefaultScreenOfDisplay (display); + auto screenNumber = X11Symbols::getInstance()->xScreenNumberOfScreen (screen); String screenAtom ("_NET_SYSTEM_TRAY_S"); screenAtom << screenNumber; Atom selectionAtom = Atoms::getCreating (display, screenAtom.toUTF8()); - XGrabServer (display); - Window managerWin = XGetSelectionOwner (display, selectionAtom); + X11Symbols::getInstance()->xGrabServer (display); + auto managerWin = X11Symbols::getInstance()->xGetSelectionOwner (display, selectionAtom); if (managerWin != None) - XSelectInput (display, managerWin, StructureNotifyMask); + X11Symbols::getInstance()->xSelectInput (display, managerWin, StructureNotifyMask); - XUngrabServer (display); - XFlush (display); + X11Symbols::getInstance()->xUngrabServer (display); + X11Symbols::getInstance()->xFlush (display); if (managerWin != None) { @@ -58,26 +58,28 @@ public: ev.xclient.data.l[3] = 0; ev.xclient.data.l[4] = 0; - XSendEvent (display, managerWin, False, NoEventMask, &ev); - XSync (display, False); + X11Symbols::getInstance()->xSendEvent (display, managerWin, False, NoEventMask, &ev); + X11Symbols::getInstance()->xSync (display, False); } // For older KDE's ... long atomData = 1; Atom trayAtom = Atoms::getCreating (display, "KWM_DOCKWINDOW"); - XChangeProperty (display, windowH, trayAtom, trayAtom, 32, PropModeReplace, (unsigned char*) &atomData, 1); + X11Symbols::getInstance()->xChangeProperty (display, windowH, trayAtom, trayAtom, + 32, PropModeReplace, (unsigned char*) &atomData, 1); // For more recent KDE's... trayAtom = Atoms::getCreating (display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR"); - XChangeProperty (display, windowH, trayAtom, XA_WINDOW, 32, PropModeReplace, (unsigned char*) &windowH, 1); + X11Symbols::getInstance()->xChangeProperty (display, windowH, trayAtom, XA_WINDOW, + 32, PropModeReplace, (unsigned char*) &windowH, 1); // A minimum size must be specified for GNOME and Xfce, otherwise the icon is displayed with a width of 1 - XSizeHints* hints = XAllocSizeHints(); + auto* hints = X11Symbols::getInstance()->xAllocSizeHints(); hints->flags = PMinSize; hints->min_width = 22; hints->min_height = 22; - XSetWMNormalHints (display, windowH, hints); - XFree (hints); + X11Symbols::getInstance()->xSetWMNormalHints (display, windowH, hints); + X11Symbols::getInstance()->xFree (hints); } Image image; diff --git a/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp b/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp index bbb1efd642..b6844716dc 100644 --- a/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp +++ b/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp @@ -19,6 +19,186 @@ namespace juce { +//============================================================================== +class WebKitSymbols : public DeletedAtShutdown +{ +public: + //============================================================================== + bool isWebKitAvailable() { return webKitIsAvailable; } + + //============================================================================== + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_new, juce_webkit_settings_new, + (), WebKitSettings*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_set_hardware_acceleration_policy, juce_webkit_settings_set_hardware_acceleration_policy, + (WebKitSettings*, int), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_new_with_settings, juce_webkit_web_view_new_with_settings, + (WebKitSettings*), GtkWidget*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_load_uri, juce_webkit_web_view_load_uri, + (WebKitWebView*, const gchar*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_policy_decision_use, juce_webkit_policy_decision_use, + (WebKitPolicyDecision*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_policy_decision_ignore, juce_webkit_policy_decision_ignore, + (WebKitPolicyDecision*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_go_back, juce_webkit_web_view_go_back, + (WebKitWebView*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_go_forward, juce_webkit_web_view_go_forward, + (WebKitWebView*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_reload, juce_webkit_web_view_reload, + (WebKitWebView*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_stop_loading, juce_webkit_web_view_stop_loading, + (WebKitWebView*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_uri_request_get_uri, juce_webkit_uri_request_get_uri, + (WebKitURIRequest*), const gchar*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_navigation_action_get_request, juce_webkit_navigation_action_get_request, + (WebKitNavigationAction*), WebKitURIRequest*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_navigation_policy_decision_get_frame_name, juce_webkit_navigation_policy_decision_get_frame_name, + (WebKitNavigationPolicyDecision*), const gchar*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_navigation_policy_decision_get_navigation_action, juce_webkit_navigation_policy_decision_get_navigation_action, + (WebKitNavigationPolicyDecision*), WebKitNavigationAction*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_get_uri, juce_webkit_web_view_get_uri, + (WebKitWebView*), const gchar*) + + //============================================================================== + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_init, juce_gtk_init, + (int*, char***), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_plug_new, juce_gtk_plug_new, + (::Window), GtkWidget*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_scrolled_window_new, juce_gtk_scrolled_window_new, + (GtkAdjustment*, GtkAdjustment*), GtkWidget*) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_container_add, juce_gtk_container_add, + (GtkContainer*, GtkWidget*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_widget_show_all, juce_gtk_widget_show_all, + (GtkWidget*), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_plug_get_id, juce_gtk_plug_get_id, + (GtkPlug*), ::Window) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_main, juce_gtk_main, + (), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gtk_main_quit, juce_gtk_main_quit, + (), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (g_unix_fd_add, juce_g_unix_fd_add, + (gint, GIOCondition, GUnixFDSourceFunc, gpointer), guint) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (g_object_ref, juce_g_object_ref, + (gpointer), gpointer) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (g_object_unref, juce_g_object_unref, + (gpointer), void) + + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (g_signal_connect_data, juce_g_signal_connect_data, + (gpointer, const gchar*, GCallback, gpointer, GClosureNotify, GConnectFlags), gulong) + + //============================================================================== + JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (WebKitSymbols) + +private: + WebKitSymbols() = default; + + ~WebKitSymbols() + { + clearSingletonInstance(); + } + + template + struct SymbolBinding + { + FuncPtr& func; + const char* name; + }; + + template + SymbolBinding makeSymbolBinding (FuncPtr& func, const char* name) + { + return { func, name }; + } + + template + bool loadSymbols (DynamicLibrary& lib, SymbolBinding binding) + { + if (auto* func = lib.getFunction (binding.name)) + { + binding.func = reinterpret_cast (func); + return true; + } + + return false; + } + + template + bool loadSymbols (DynamicLibrary& lib, SymbolBinding binding, Args... args) + { + return loadSymbols (lib, binding) && loadSymbols (lib, args...); + } + + //============================================================================== + bool loadWebkitSymbols() + { + return loadSymbols (webkitLib, + makeSymbolBinding (juce_webkit_settings_new, "webkit_settings_new"), + makeSymbolBinding (juce_webkit_settings_set_hardware_acceleration_policy, "webkit_settings_set_hardware_acceleration_policy"), + makeSymbolBinding (juce_webkit_web_view_new_with_settings, "webkit_web_view_new_with_settings"), + makeSymbolBinding (juce_webkit_policy_decision_use, "webkit_policy_decision_use"), + makeSymbolBinding (juce_webkit_policy_decision_ignore, "webkit_policy_decision_ignore"), + makeSymbolBinding (juce_webkit_web_view_go_back, "webkit_web_view_go_back"), + makeSymbolBinding (juce_webkit_web_view_go_forward, "webkit_web_view_go_forward"), + makeSymbolBinding (juce_webkit_web_view_reload, "webkit_web_view_reload"), + makeSymbolBinding (juce_webkit_web_view_stop_loading, "webkit_web_view_stop_loading"), + makeSymbolBinding (juce_webkit_uri_request_get_uri, "webkit_uri_request_get_uri"), + makeSymbolBinding (juce_webkit_web_view_load_uri, "webkit_web_view_load_uri"), + makeSymbolBinding (juce_webkit_navigation_action_get_request, "webkit_navigation_action_get_request"), + makeSymbolBinding (juce_webkit_navigation_policy_decision_get_frame_name, "webkit_navigation_policy_decision_get_frame_name"), + makeSymbolBinding (juce_webkit_navigation_policy_decision_get_navigation_action, "webkit_navigation_policy_decision_get_navigation_action"), + makeSymbolBinding (juce_webkit_web_view_get_uri, "webkit_web_view_get_uri")); + } + + bool loadGtkSymbols() + { + return loadSymbols (gtkLib, + makeSymbolBinding (juce_gtk_init, "gtk_init"), + makeSymbolBinding (juce_gtk_plug_new, "gtk_plug_new"), + makeSymbolBinding (juce_gtk_scrolled_window_new, "gtk_scrolled_window_new"), + makeSymbolBinding (juce_gtk_container_add, "gtk_container_add"), + makeSymbolBinding (juce_gtk_widget_show_all, "gtk_widget_show_all"), + makeSymbolBinding (juce_gtk_plug_get_id, "gtk_plug_get_id"), + makeSymbolBinding (juce_gtk_main, "gtk_main"), + makeSymbolBinding (juce_gtk_main_quit, "gtk_main_quit"), + makeSymbolBinding (juce_g_unix_fd_add, "g_unix_fd_add"), + makeSymbolBinding (juce_g_object_ref, "g_object_ref"), + makeSymbolBinding (juce_g_object_unref, "g_object_unref"), + makeSymbolBinding (juce_g_signal_connect_data, "g_signal_connect_data")); + } + + //============================================================================== + DynamicLibrary gtkLib { "libgtk-3.so" }, webkitLib { "libwebkit2gtk-4.0.so" }; + const bool webKitIsAvailable = loadWebkitSymbols() && loadGtkSymbols(); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebKitSymbols) +}; + +JUCE_IMPLEMENT_SINGLETON (WebKitSymbols) + +//============================================================================== extern int juce_gtkWebkitMain (int argc, const char* argv[]); class CommandReceiver @@ -40,9 +220,9 @@ public: static void setBlocking (int fd, bool shouldBlock) { - int flags = fcntl (fd, F_GETFL); + auto flags = fcntl (fd, F_GETFL); fcntl (fd, F_SETFL, (shouldBlock ? (flags & ~O_NONBLOCK) - : (flags | O_NONBLOCK))); + : (flags | O_NONBLOCK))); } int getFd() const { return inChannel; } @@ -51,14 +231,14 @@ public: { for (;;) { - size_t len = (receivingLength ? sizeof (size_t) : bufferLength.len); + auto len = (receivingLength ? sizeof (size_t) : bufferLength.len); if (! receivingLength) buffer.realloc (len); - char* dst = (receivingLength ? bufferLength.data : buffer.getData()); + auto* dst = (receivingLength ? bufferLength.data : buffer.getData()); - ssize_t actual = read (inChannel, &dst[pos], static_cast (len - pos)); + auto actual = read (inChannel, &dst[pos], static_cast (len - pos)); if (actual < 0) { @@ -94,13 +274,13 @@ public: if (! params.isVoid()) obj->setProperty (getParamIdentifier(), params); - String json (JSON::toString (var (obj.get()))); + auto json = JSON::toString (var (obj.get())); - size_t jsonLength = static_cast (json.length()); - size_t len = sizeof (size_t) + jsonLength; + auto jsonLength = static_cast (json.length()); + auto len = sizeof (size_t) + jsonLength; HeapBlock buffer (len); - char* dst = buffer.getData(); + auto* dst = buffer.getData(); memcpy (dst, &jsonLength, sizeof (size_t)); dst += sizeof (size_t); @@ -109,21 +289,24 @@ public: ssize_t ret; - do + for (;;) { ret = write (outChannel, buffer.getData(), len); - } while (ret == -1 && errno == EINTR); + + if (ret != -1 || errno != EINTR) + break; + } } private: void parseJSON (const String& json) { - var object (JSON::fromString (json)); + auto object = JSON::fromString (json); if (! object.isVoid()) { - String cmd (object.getProperty (getCmdIdentifier(), var()).toString()); - var params (object.getProperty (getParamIdentifier(), var())); + auto cmd = object.getProperty (getCmdIdentifier(), {}).toString(); + auto params = object.getProperty (getParamIdentifier(), {}); if (responder != nullptr) responder->handleCommand (cmd, params); @@ -133,105 +316,101 @@ private: static Identifier getCmdIdentifier() { static Identifier Id ("cmd"); return Id; } static Identifier getParamIdentifier() { static Identifier Id ("params"); return Id; } - Responder* responder; - int inChannel; + Responder* responder = nullptr; + int inChannel = 0; size_t pos = 0; bool receivingLength = true; union { char data [sizeof (size_t)]; size_t len; } bufferLength; HeapBlock buffer; }; +#define juce_g_signal_connect(instance, detailed_signal, c_handler, data) \ + WebKitSymbols::getInstance()->juce_g_signal_connect_data (instance, detailed_signal, c_handler, data, nullptr, (GConnectFlags) 0) + //============================================================================== class GtkChildProcess : private CommandReceiver::Responder { public: //============================================================================== GtkChildProcess (int inChannel, int outChannelToUse) - : outChannel (outChannelToUse), receiver (this, inChannel) + : outChannel (outChannelToUse), + receiver (this, inChannel) {} - typedef void (*SetHardwareAcclPolicyFunctionPtr) (WebKitSettings*, int); - int entry() { - CommandReceiver::setBlocking (outChannel, true); + CommandReceiver::setBlocking (outChannel, true); - gtk_init (nullptr, nullptr); + WebKitSymbols::getInstance()->juce_gtk_init (nullptr, nullptr); - WebKitSettings* settings = webkit_settings_new(); + auto* settings = WebKitSymbols::getInstance()->juce_webkit_settings_new(); + WebKitSymbols::getInstance()->juce_webkit_settings_set_hardware_acceleration_policy (settings, + /* WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER */ 2); - // webkit_settings_set_hardware_acceleration_policy was only added recently to webkit2 - // but is needed when running a WebBrowserComponent in a Parallels VM with 3D acceleration enabled - auto setHardwarePolicy - = reinterpret_cast (dlsym (RTLD_DEFAULT, "webkit_settings_set_hardware_acceleration_policy")); + auto* plug = WebKitSymbols::getInstance()->juce_gtk_plug_new (0); + auto* container = WebKitSymbols::getInstance()->juce_gtk_scrolled_window_new (nullptr, nullptr); - if (setHardwarePolicy != nullptr) - setHardwarePolicy (settings, 2 /*WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER*/); + auto* webviewWidget = WebKitSymbols::getInstance()->juce_webkit_web_view_new_with_settings (settings); + webview = (WebKitWebView*) webviewWidget; - GtkWidget *plug; + WebKitSymbols::getInstance()->juce_gtk_container_add ((GtkContainer*) container, webviewWidget); + WebKitSymbols::getInstance()->juce_gtk_container_add ((GtkContainer*) plug, container); - plug = gtk_plug_new(0); - GtkWidget* container; - container = gtk_scrolled_window_new (nullptr, nullptr); + WebKitSymbols::getInstance()->juce_webkit_web_view_load_uri (webview, "about:blank"); - GtkWidget* webviewWidget = webkit_web_view_new_with_settings (settings); - webview = WEBKIT_WEB_VIEW (webviewWidget); + juce_g_signal_connect (webview, "decide-policy", + (GCallback) decidePolicyCallback, this); + juce_g_signal_connect (webview, "load-changed", + (GCallback) loadChangedCallback, this); - gtk_container_add (GTK_CONTAINER (container), webviewWidget); - gtk_container_add (GTK_CONTAINER (plug), container); - - webkit_web_view_load_uri (webview, "about:blank"); - - g_signal_connect (webview, "decide-policy", - G_CALLBACK (decidePolicyCallback), this); - - g_signal_connect (webview, "load-changed", - G_CALLBACK (loadChangedCallback), this); - - g_signal_connect (webview, "load-failed", - G_CALLBACK (loadFailedCallback), this); - - gtk_widget_show_all (plug); - unsigned long wID = (unsigned long) gtk_plug_get_id (GTK_PLUG (plug)); + juce_g_signal_connect (webview, "load-failed", + (GCallback) loadFailedCallback, this); + WebKitSymbols::getInstance()->juce_gtk_widget_show_all (plug); + auto wID = (unsigned long) WebKitSymbols::getInstance()->juce_gtk_plug_get_id ((GtkPlug*) plug); ssize_t ret; - do { + for (;;) + { ret = write (outChannel, &wID, sizeof (wID)); - } while (ret == -1 && errno == EINTR); - g_unix_fd_add (receiver.getFd(), G_IO_IN, pipeReadyStatic, this); + if (ret != -1 || errno != EINTR) + break; + } + + WebKitSymbols::getInstance()->juce_g_unix_fd_add (receiver.getFd(), G_IO_IN, pipeReadyStatic, this); receiver.tryNextRead(); - gtk_main(); + WebKitSymbols::getInstance()->juce_gtk_main(); + + WebKitSymbols::getInstance()->deleteInstance(); return 0; } void goToURL (const var& params) { static Identifier urlIdentifier ("url"); - String url (params.getProperty (urlIdentifier, var()).toString()); + auto url = params.getProperty (urlIdentifier, var()).toString(); - webkit_web_view_load_uri (webview, url.toRawUTF8()); + WebKitSymbols::getInstance()->juce_webkit_web_view_load_uri (webview, url.toRawUTF8()); } void handleDecisionResponse (const var& params) { - WebKitPolicyDecision* decision - = (WebKitPolicyDecision*) ((int64) params.getProperty ("decision_id", var (0))); + auto* decision = (WebKitPolicyDecision*) ((int64) params.getProperty ("decision_id", var (0))); bool allow = params.getProperty ("allow", var (false)); if (decision != nullptr && decisions.contains (decision)) { if (allow) - webkit_policy_decision_use (decision); + WebKitSymbols::getInstance()->juce_webkit_policy_decision_use (decision); else - webkit_policy_decision_ignore (decision); + WebKitSymbols::getInstance()->juce_webkit_policy_decision_ignore (decision); decisions.removeAllInstancesOf (decision); - g_object_unref (decision); + WebKitSymbols::getInstance()->juce_g_object_unref (decision); } } @@ -240,10 +419,10 @@ public: { if (cmd == "quit") quit(); else if (cmd == "goToURL") goToURL (params); - else if (cmd == "goBack") webkit_web_view_go_back (webview); - else if (cmd == "goForward") webkit_web_view_go_forward (webview); - else if (cmd == "refresh") webkit_web_view_reload (webview); - else if (cmd == "stop") webkit_web_view_stop_loading (webview); + else if (cmd == "goBack") WebKitSymbols::getInstance()->juce_webkit_web_view_go_back (webview); + else if (cmd == "goForward") WebKitSymbols::getInstance()->juce_webkit_web_view_go_forward (webview); + else if (cmd == "refresh") WebKitSymbols::getInstance()->juce_webkit_web_view_reload (webview); + else if (cmd == "stop") WebKitSymbols::getInstance()->juce_webkit_web_view_stop_loading (webview); else if (cmd == "decision") handleDecisionResponse (params); } @@ -266,7 +445,13 @@ public: void quit() { - gtk_main_quit(); + WebKitSymbols::getInstance()->juce_gtk_main_quit(); + } + + String getURIStringForAction (WebKitNavigationAction* action) + { + auto* request = WebKitSymbols::getInstance()->juce_webkit_navigation_action_get_request (action); + return WebKitSymbols::getInstance()->juce_webkit_uri_request_get_uri (request); } bool onNavigation (String frameName, @@ -275,12 +460,12 @@ public: { if (decision != nullptr && frameName.isEmpty()) { - g_object_ref (decision); + WebKitSymbols::getInstance()->juce_g_object_ref (decision); decisions.add (decision); DynamicObject::Ptr params = new DynamicObject; - params->setProperty ("url", String (webkit_uri_request_get_uri (webkit_navigation_action_get_request (action)))); + params->setProperty ("url", getURIStringForAction (action)); params->setProperty ("decision_id", (int64) decision); CommandReceiver::sendCommand (outChannel, "pageAboutToLoad", var (params.get())); @@ -298,11 +483,11 @@ public: { DynamicObject::Ptr params = new DynamicObject; - params->setProperty ("url", String (webkit_uri_request_get_uri (webkit_navigation_action_get_request (action)))); + params->setProperty ("url", getURIStringForAction (action)); CommandReceiver::sendCommand (outChannel, "newWindowAttemptingToLoad", var (params.get())); // never allow new windows - webkit_policy_decision_ignore (decision); + WebKitSymbols::getInstance()->juce_webkit_policy_decision_ignore (decision); return true; } @@ -316,7 +501,7 @@ public: { DynamicObject::Ptr params = new DynamicObject; - params->setProperty ("url", String (webkit_web_view_get_uri (webview))); + params->setProperty ("url", String (WebKitSymbols::getInstance()->juce_webkit_web_view_get_uri (webview))); CommandReceiver::sendCommand (outChannel, "pageFinishedLoading", var (params.get())); } } @@ -328,31 +513,31 @@ public: { case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: { - WebKitNavigationPolicyDecision* navigationDecision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); - const char* frameName = webkit_navigation_policy_decision_get_frame_name (navigationDecision); + auto* navigationDecision = (WebKitNavigationPolicyDecision*) decision; + auto* frameName = WebKitSymbols::getInstance()->juce_webkit_navigation_policy_decision_get_frame_name (navigationDecision); return onNavigation (String (frameName != nullptr ? frameName : ""), - webkit_navigation_policy_decision_get_navigation_action (navigationDecision), + WebKitSymbols::getInstance()->juce_webkit_navigation_policy_decision_get_navigation_action (navigationDecision), decision); } break; case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: { - WebKitNavigationPolicyDecision* navigationDecision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); - const char* frameName = webkit_navigation_policy_decision_get_frame_name (navigationDecision); + auto* navigationDecision = (WebKitNavigationPolicyDecision*) decision; + auto* frameName = WebKitSymbols::getInstance()->juce_webkit_navigation_policy_decision_get_frame_name (navigationDecision); return onNewWindow (String (frameName != nullptr ? frameName : ""), - webkit_navigation_policy_decision_get_navigation_action (navigationDecision), + WebKitSymbols::getInstance()->juce_webkit_navigation_policy_decision_get_navigation_action (navigationDecision), decision); } break; case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: { - WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision); + auto* response = (WebKitNavigationPolicyDecision*) decision; // for now just always allow response requests ignoreUnused (response); - webkit_policy_decision_use (decision); + WebKitSymbols::getInstance()->juce_webkit_policy_decision_use (decision); return true; } break; @@ -382,7 +567,7 @@ private: WebKitPolicyDecisionType decisionType, gpointer user) { - GtkChildProcess& owner = *reinterpret_cast (user); + auto& owner = *reinterpret_cast (user); return (owner.onDecidePolicy (decision, decisionType) ? TRUE : FALSE); } @@ -390,7 +575,7 @@ private: WebKitLoadEvent loadEvent, gpointer user) { - GtkChildProcess& owner = *reinterpret_cast (user); + auto& owner = *reinterpret_cast (user); owner.onLoadChanged (loadEvent); } @@ -400,11 +585,11 @@ private: GError* error, gpointer user) { - GtkChildProcess& owner = *reinterpret_cast (user); + auto& owner = *reinterpret_cast (user); owner.onLoadFailed (error); } - int outChannel; + int outChannel = 0; CommandReceiver receiver; WebKitWebView* webview = nullptr; Array decisions; @@ -417,7 +602,9 @@ class WebBrowserComponent::Pimpl : private Thread, public: Pimpl (WebBrowserComponent& parent) : Thread ("Webview"), owner (parent) - {} + { + webKitIsAvailable = WebKitSymbols::getInstance()->isWebKitAvailable(); + } ~Pimpl() override { @@ -427,9 +614,12 @@ public: //============================================================================== void init() { + if (! webKitIsAvailable) + return; + launchChild(); - int ret = pipe (threadControl); + auto ret = pipe (threadControl); ignoreUnused (ret); jassert (ret == 0); @@ -440,7 +630,7 @@ public: CommandReceiver::setBlocking (threadControl[1], true); unsigned long windowHandle; - ssize_t actual = read (inChannel, &windowHandle, sizeof (windowHandle)); + auto actual = read (inChannel, &windowHandle, sizeof (windowHandle)); if (actual != (ssize_t) sizeof (windowHandle)) { @@ -461,6 +651,9 @@ public: void quit() { + if (! webKitIsAvailable) + return; + if (isThreadRunning()) { signalThreadShouldExit(); @@ -468,10 +661,13 @@ public: char ignore = 0; ssize_t ret; - do + for (;;) { ret = write (threadControl[1], &ignore, 1); - } while (ret == -1 && errno == EINTR); + + if (ret != -1 || errno != EINTR) + break; + } waitForThreadToExit (-1); receiver = nullptr; @@ -479,7 +675,7 @@ public: if (childProcess != 0) { - CommandReceiver::sendCommand (outChannel, "quit", var()); + CommandReceiver::sendCommand (outChannel, "quit", {}); killChild(); } } @@ -487,6 +683,9 @@ public: //============================================================================== void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) { + if (! webKitIsAvailable) + return; + DynamicObject::Ptr params = new DynamicObject; params->setProperty ("url", url); @@ -500,16 +699,17 @@ public: CommandReceiver::sendCommand (outChannel, "goToURL", var (params.get())); } - void goBack() { CommandReceiver::sendCommand (outChannel, "goBack", var()); } - void goForward() { CommandReceiver::sendCommand (outChannel, "goForward", var()); } - void refresh() { CommandReceiver::sendCommand (outChannel, "refresh", var()); } - void stop() { CommandReceiver::sendCommand (outChannel, "stop", var()); } + void goBack() { if (webKitIsAvailable) CommandReceiver::sendCommand (outChannel, "goBack", {}); } + void goForward() { if (webKitIsAvailable) CommandReceiver::sendCommand (outChannel, "goForward", {}); } + void refresh() { if (webKitIsAvailable) CommandReceiver::sendCommand (outChannel, "refresh", {}); } + void stop() { if (webKitIsAvailable) CommandReceiver::sendCommand (outChannel, "stop", {}); } void resized() { if (xembed != nullptr) xembed->setBounds (owner.getLocalBounds()); } + private: //============================================================================== void killChild() @@ -518,7 +718,7 @@ private: { xembed = nullptr; - int status = 0, result; + int status = 0, result = 0; result = waitpid (childProcess, &status, WNOHANG); for (int i = 0; i < 15 && (! WIFEXITED(status) || result != childProcess); ++i) @@ -531,11 +731,14 @@ private: status = 0; if (! WIFEXITED(status) || result != childProcess) { - do + for (;;) { kill (childProcess, SIGTERM); waitpid (childProcess, &status, 0); - } while (! WIFEXITED(status)); + + if (WIFEXITED (status)) + break; + } } childProcess = 0; @@ -544,16 +747,15 @@ private: void launchChild() { - int ret; int inPipe[2], outPipe[2]; - ret = pipe (inPipe); + auto ret = pipe (inPipe); ignoreUnused (ret); jassert (ret == 0); ret = pipe (outPipe); ignoreUnused (ret); jassert (ret == 0); - int pid = fork(); + auto pid = fork(); if (pid == 0) { close (inPipe[0]); @@ -611,7 +813,7 @@ private: bool shouldExit() { char ignore; - ssize_t result = read (threadControl[0], &ignore, 1); + auto result = read (threadControl[0], &ignore, 1); return (result != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)); } @@ -619,7 +821,7 @@ private: //============================================================================== void handleCommandOnMessageThread (const String& cmd, const var& params) { - String url (params.getProperty ("url", var()).toString()); + auto url = params.getProperty ("url", var()).toString(); if (cmd == "pageAboutToLoad") handlePageAboutToLoad (url, params); else if (cmd == "pageFinishedLoading") owner.pageFinishedLoading (url); @@ -679,12 +881,13 @@ private: owner->handleCommandOnMessageThread (cmdToSend, paramsToSend); } - Pimpl* owner; + Pimpl* owner = nullptr; String cmdToSend; var paramsToSend; }; -private: + bool webKitIsAvailable = false; + WebBrowserComponent& owner; std::unique_ptr receiver; int childProcess = 0, inChannel = 0, outChannel = 0; @@ -802,11 +1005,12 @@ void WebBrowserComponent::clearCookies() int juce_gtkWebkitMain (int argc, const char* argv[]) { - if (argc != 4) return -1; - + if (argc != 4) + return -1; GtkChildProcess child (String (argv[2]).getIntValue(), String (argv[3]).getIntValue()); + return child.entry(); } diff --git a/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp b/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp index bcf9b3d3ce..d6ce4dccd7 100644 --- a/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp +++ b/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp @@ -26,6 +26,41 @@ Window juce_getCurrentFocusWindow (ComponentPeer*); unsigned long juce_createKeyProxyWindow (ComponentPeer*); void juce_deleteKeyProxyWindow (ComponentPeer*); +//============================================================================== +enum +{ + maxXEmbedVersionToSupport = 0 +}; + +enum +{ + XEMBED_MAPPED = (1<<0) +}; + +enum +{ + XEMBED_EMBEDDED_NOTIFY = 0, + XEMBED_WINDOW_ACTIVATE = 1, + XEMBED_WINDOW_DEACTIVATE = 2, + XEMBED_REQUEST_FOCUS = 3, + XEMBED_FOCUS_IN = 4, + XEMBED_FOCUS_OUT = 5, + XEMBED_FOCUS_NEXT = 6, + XEMBED_FOCUS_PREV = 7, + XEMBED_MODALITY_ON = 10, + XEMBED_MODALITY_OFF = 11, + XEMBED_REGISTER_ACCELERATOR = 12, + XEMBED_UNREGISTER_ACCELERATOR = 13, + XEMBED_ACTIVATE_ACCELERATOR = 14 +}; + +enum +{ + XEMBED_FOCUS_CURRENT = 0, + XEMBED_FOCUS_FIRST = 1, + XEMBED_FOCUS_LAST = 2 +}; + //============================================================================== class XEmbedComponent::Pimpl : private ComponentListener { @@ -117,16 +152,17 @@ public: if (host != 0) { auto dpy = getDisplay(); - XDestroyWindow (dpy, host); - XSync (dpy, false); - const long mask = NoEventMask | KeyPressMask | KeyReleaseMask - | EnterWindowMask | LeaveWindowMask | PointerMotionMask - | KeymapStateMask | ExposureMask | StructureNotifyMask - | FocusChangeMask; + X11Symbols::getInstance()->xDestroyWindow (dpy, host); + X11Symbols::getInstance()->xSync (dpy, false); + + auto mask = NoEventMask | KeyPressMask | KeyReleaseMask + | EnterWindowMask | LeaveWindowMask | PointerMotionMask + | KeymapStateMask | ExposureMask | StructureNotifyMask + | FocusChangeMask; XEvent event; - while (XCheckWindowEvent (dpy, host, mask, &event) == True) + while (X11Symbols::getInstance()->xCheckWindowEvent (dpy, host, mask, &event) == True) {} host = 0; @@ -155,22 +191,22 @@ public: else { auto newBounds = getX11BoundsFromJuce(); - XResizeWindow (dpy, client, static_cast (newBounds.getWidth()), - static_cast (newBounds.getHeight())); + X11Symbols::getInstance()->xResizeWindow (dpy, client, static_cast (newBounds.getWidth()), + static_cast (newBounds.getHeight())); } auto eventMask = StructureNotifyMask | PropertyChangeMask | FocusChangeMask; XWindowAttributes clientAttr; - XGetWindowAttributes (dpy, client, &clientAttr); + X11Symbols::getInstance()->xGetWindowAttributes (dpy, client, &clientAttr); if ((eventMask & clientAttr.your_event_mask) != eventMask) - XSelectInput (dpy, client, clientAttr.your_event_mask | eventMask); + X11Symbols::getInstance()->xSelectInput (dpy, client, clientAttr.your_event_mask | eventMask); getXEmbedMappedFlag(); if (shouldReparent) - XReparentWindow (dpy, client, host, 0, 0); + X11Symbols::getInstance()->xReparentWindow (dpy, client, host, 0, 0); if (supportsXembed) sendXEmbedEvent (CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, (long) host, xembedVersion); @@ -242,27 +278,27 @@ private: auto newBounds = getX11BoundsFromJuce(); XWindowAttributes attr; - if (XGetWindowAttributes (dpy, host, &attr)) + if (X11Symbols::getInstance()->xGetWindowAttributes (dpy, host, &attr)) { Rectangle currentBounds (attr.x, attr.y, attr.width, attr.height); if (currentBounds != newBounds) { - XMoveResizeWindow (dpy, host, newBounds.getX(), newBounds.getY(), - static_cast (newBounds.getWidth()), - static_cast (newBounds.getHeight())); + X11Symbols::getInstance()->xMoveResizeWindow (dpy, host, newBounds.getX(), newBounds.getY(), + static_cast (newBounds.getWidth()), + static_cast (newBounds.getHeight())); } } - if (client != 0 && XGetWindowAttributes (dpy, client, &attr)) + if (client != 0 && X11Symbols::getInstance()->xGetWindowAttributes (dpy, client, &attr)) { Rectangle currentBounds (attr.x, attr.y, attr.width, attr.height); if ((currentBounds.getWidth() != newBounds.getWidth() || currentBounds.getHeight() != newBounds.getHeight())) { - XMoveResizeWindow (dpy, client, 0, 0, - static_cast (newBounds.getWidth()), - static_cast (newBounds.getHeight())); + X11Symbols::getInstance()->xMoveResizeWindow (dpy, client, 0, 0, + static_cast (newBounds.getWidth()), + static_cast (newBounds.getHeight())); } } } @@ -272,8 +308,8 @@ private: void createHostWindow() { auto dpy = getDisplay(); - int defaultScreen = XDefaultScreen (dpy); - Window root = RootWindow (dpy, defaultScreen); + int defaultScreen = X11Symbols::getInstance()->xDefaultScreen (dpy); + Window root = X11Symbols::getInstance()->xRootWindow (dpy, defaultScreen); XSetWindowAttributes swa; swa.border_pixel = 0; @@ -281,10 +317,10 @@ private: swa.override_redirect = True; swa.event_mask = SubstructureNotifyMask | StructureNotifyMask | FocusChangeMask; - host = XCreateWindow (dpy, root, 0, 0, 1, 1, 0, CopyFromParent, - InputOutput, CopyFromParent, - CWEventMask | CWBorderPixel | CWBackPixmap | CWOverrideRedirect, - &swa); + host = X11Symbols::getInstance()->xCreateWindow (dpy, root, 0, 0, 1, 1, 0, CopyFromParent, + InputOutput, CopyFromParent, + CWEventMask | CWBorderPixel | CWBackPixmap | CWOverrideRedirect, + &swa); } void removeClient() @@ -292,20 +328,20 @@ private: if (client != 0) { auto dpy = getDisplay(); - XSelectInput (dpy, client, 0); + X11Symbols::getInstance()->xSelectInput (dpy, client, 0); keyWindow = nullptr; - int defaultScreen = XDefaultScreen (dpy); - Window root = RootWindow (dpy, defaultScreen); + int defaultScreen = X11Symbols::getInstance()->xDefaultScreen (dpy); + Window root = X11Symbols::getInstance()->xRootWindow (dpy, defaultScreen); if (hasBeenMapped) { - XUnmapWindow (dpy, client); + X11Symbols::getInstance()->xUnmapWindow (dpy, client); hasBeenMapped = false; } - XReparentWindow (dpy, client, root, 0, 0); + X11Symbols::getInstance()->xReparentWindow (dpy, client, root, 0, 0); client = 0; } } @@ -321,9 +357,9 @@ private: hasBeenMapped = shouldBeMapped; if (shouldBeMapped) - XMapWindow (getDisplay(), client); + X11Symbols::getInstance()->xMapWindow (getDisplay(), client); else - XUnmapWindow (getDisplay(), client); + X11Symbols::getInstance()->xUnmapWindow (getDisplay(), client); } } } @@ -378,13 +414,13 @@ private: XWindowAttributes attr; auto dpy = getDisplay(); - if (XGetWindowAttributes (dpy, client, &attr)) + if (X11Symbols::getInstance()->xGetWindowAttributes (dpy, client, &attr)) { XWindowAttributes hostAttr; - if (XGetWindowAttributes (dpy, host, &hostAttr)) + if (X11Symbols::getInstance()->xGetWindowAttributes (dpy, host, &hostAttr)) if (attr.width != hostAttr.width || attr.height != hostAttr.height) - XResizeWindow (dpy, host, (unsigned int) attr.width, (unsigned int) attr.height); + X11Symbols::getInstance()->xResizeWindow (dpy, host, (unsigned int) attr.width, (unsigned int) attr.height); // as the client window is not on any screen yet, we need to guess // on which screen it might appear to get a scaling factor :-( @@ -420,14 +456,14 @@ private: keyWindow = nullptr; auto dpy = getDisplay(); - Window rootWindow = RootWindow (dpy, DefaultScreen (dpy)); + Window rootWindow = X11Symbols::getInstance()->xRootWindow (dpy, DefaultScreen (dpy)); Rectangle newBounds = getX11BoundsFromJuce(); if (newPeer == nullptr) - XUnmapWindow (dpy, host); + X11Symbols::getInstance()->xUnmapWindow (dpy, host); Window newParent = (newPeer != nullptr ? getParentX11Window() : rootWindow); - XReparentWindow (dpy, host, newParent, newBounds.getX(), newBounds.getY()); + X11Symbols::getInstance()->xReparentWindow (dpy, host, newParent, newBounds.getX(), newBounds.getY()); lastPeer = newPeer; @@ -440,7 +476,7 @@ private: } componentMovedOrResized (owner, true, true); - XMapWindow (dpy, host); + X11Symbols::getInstance()->xMapWindow (dpy, host); broughtToFront(); } @@ -450,7 +486,7 @@ private: void updateKeyFocus() { if (lastPeer != nullptr && lastPeer->isFocused()) - XSetInputFocus (getDisplay(), getCurrentFocusWindow (lastPeer), RevertToParent, CurrentTime); + X11Symbols::getInstance()->xSetInputFocus (getDisplay(), getCurrentFocusWindow (lastPeer), RevertToParent, CurrentTime); } //============================================================================== @@ -560,8 +596,8 @@ private: msg.data.l[3] = data1; msg.data.l[4] = data2; - XSendEvent (dpy, client, False, NoEventMask, (XEvent*) &msg); - XSync (dpy, False); + X11Symbols::getInstance()->xSendEvent (dpy, client, False, NoEventMask, (XEvent*) &msg); + X11Symbols::getInstance()->xSync (dpy, False); } Rectangle getX11BoundsFromJuce() diff --git a/modules/juce_opengl/juce_opengl.cpp b/modules/juce_opengl/juce_opengl.cpp index 4356938141..4444c04370 100644 --- a/modules/juce_opengl/juce_opengl.cpp +++ b/modules/juce_opengl/juce_opengl.cpp @@ -29,6 +29,7 @@ #define JUCE_CORE_INCLUDE_JNI_HELPERS 1 #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 +#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 #include "juce_opengl.h" diff --git a/modules/juce_opengl/native/juce_OpenGL_linux_X11.h b/modules/juce_opengl/native/juce_OpenGL_linux_X11.h index 478d7bd2ae..055ab2e749 100644 --- a/modules/juce_opengl/native/juce_OpenGL_linux_X11.h +++ b/modules/juce_opengl/native/juce_OpenGL_linux_X11.h @@ -58,7 +58,7 @@ public: display = XWindowSystem::getInstance()->displayRef(); ScopedXLock xlock (display); - XSync (display, False); + X11Symbols::getInstance()->xSync (display, False); GLint attribs[] = { @@ -77,7 +77,7 @@ public: None }; - bestVisual = glXChooseVisual (display, DefaultScreen (display), attribs); + bestVisual = glXChooseVisual (display, X11Symbols::getInstance()->xDefaultScreen (display), attribs); if (bestVisual == nullptr) return; @@ -85,7 +85,7 @@ public: jassert (peer != nullptr); auto windowH = (Window) peer->getNativeHandle(); - auto colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone); + auto colourMap = X11Symbols::getInstance()->xCreateColormap (display, windowH, bestVisual->visual, AllocNone); XSetWindowAttributes swa; swa.colormap = colourMap; @@ -97,22 +97,22 @@ public: glBounds = juce_LinuxScaledToPhysicalBounds (peer, glBounds); - embeddedWindow = XCreateWindow (display, windowH, - glBounds.getX(), glBounds.getY(), - (unsigned int) jmax (1, glBounds.getWidth()), - (unsigned int) jmax (1, glBounds.getHeight()), - 0, bestVisual->depth, - InputOutput, - bestVisual->visual, - CWBorderPixel | CWColormap | CWEventMask, - &swa); + embeddedWindow = X11Symbols::getInstance()->xCreateWindow (display, windowH, + glBounds.getX(), glBounds.getY(), + (unsigned int) jmax (1, glBounds.getWidth()), + (unsigned int) jmax (1, glBounds.getHeight()), + 0, bestVisual->depth, + InputOutput, + bestVisual->visual, + CWBorderPixel | CWColormap | CWEventMask, + &swa); - XSaveContext (display, (XID) embeddedWindow, windowHandleXContext, (XPointer) peer); + X11Symbols::getInstance()->xSaveContext (display, (XID) embeddedWindow, windowHandleXContext, (XPointer) peer); - XMapWindow (display, embeddedWindow); - XFreeColormap (display, colourMap); + X11Symbols::getInstance()->xMapWindow (display, embeddedWindow); + X11Symbols::getInstance()->xFreeColormap (display, colourMap); - XSync (display, False); + X11Symbols::getInstance()->xSync (display, False); juce_LinuxAddRepaintListener (peer, &dummy); } @@ -124,12 +124,12 @@ public: if (embeddedWindow != 0) { ScopedXLock xlock (display); - XUnmapWindow (display, embeddedWindow); - XDestroyWindow (display, embeddedWindow); + X11Symbols::getInstance()->xUnmapWindow (display, embeddedWindow); + X11Symbols::getInstance()->xDestroyWindow (display, embeddedWindow); } if (bestVisual != nullptr) - XFree (bestVisual); + X11Symbols::getInstance()->xFree (bestVisual); XWindowSystem::getInstance()->displayUnref(); } @@ -185,10 +185,10 @@ public: auto physicalBounds = juce_LinuxScaledToPhysicalBounds (component.getPeer(), bounds); ScopedXLock xlock (display); - XMoveResizeWindow (display, embeddedWindow, - physicalBounds.getX(), physicalBounds.getY(), - (unsigned int) jmax (1, physicalBounds.getWidth()), - (unsigned int) jmax (1, physicalBounds.getHeight())); + X11Symbols::getInstance()->xMoveResizeWindow (display, embeddedWindow, + physicalBounds.getX(), physicalBounds.getY(), + (unsigned int) jmax (1, physicalBounds.getWidth()), + (unsigned int) jmax (1, physicalBounds.getHeight())); } bool setSwapInterval (int numFramesPerSwap)