| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    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
 -    22nd April 2020).
 - 
 -    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
 - {
 - 
 - typedef void (*WindowMessageReceiveCallback) (XEvent&);
 - WindowMessageReceiveCallback dispatchWindowMessage = nullptr;
 - 
 - typedef void (*SelectionRequestCallback) (XSelectionRequestEvent&);
 - SelectionRequestCallback handleSelectionRequest = nullptr;
 - 
 - ::Window juce_messageWindowHandle;
 - XContext windowHandleXContext;
 - 
 - //==============================================================================
 - namespace X11ErrorHandling
 - {
 -     static XErrorHandler   oldErrorHandler = {};
 -     static XIOErrorHandler oldIOErrorHandler = {};
 - 
 -     //==============================================================================
 -     // Usually happens when client-server connection is broken
 -     int ioErrorHandler (::Display*)
 -     {
 -         DBG ("ERROR: connection to X server broken.. terminating.");
 - 
 -         if (JUCEApplicationBase::isStandaloneApp())
 -             MessageManager::getInstance()->stopDispatchLoop();
 - 
 -         return 0;
 -     }
 - 
 - 
 -     int errorHandler (::Display* display, XErrorEvent* event)
 -     {
 -         ignoreUnused (display, event);
 - 
 -        #if JUCE_DEBUG_XERRORS
 -         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);
 -         DBG ("ERROR: X returned " << errorStr << " for operation " << requestStr);
 -        #endif
 - 
 -         return 0;
 -     }
 - 
 -     void installXErrorHandlers()
 -     {
 -         oldIOErrorHandler = XSetIOErrorHandler (ioErrorHandler);
 -         oldErrorHandler = XSetErrorHandler (errorHandler);
 -     }
 - 
 -     void removeXErrorHandlers()
 -     {
 -         XSetIOErrorHandler (oldIOErrorHandler);
 -         oldIOErrorHandler = {};
 - 
 -         XSetErrorHandler (oldErrorHandler);
 -         oldErrorHandler = {};
 -     }
 - }
 - 
 - //==============================================================================
 - XWindowSystem::XWindowSystem() noexcept
 - {
 -     if (JUCEApplicationBase::isStandaloneApp())
 -     {
 -         // Initialise xlib for multiple thread support
 -         static bool initThreadCalled = false;
 - 
 -         if (! initThreadCalled)
 -         {
 -             if (! XInitThreads())
 -             {
 -                 // This is fatal!  Print error and closedown
 -                 Logger::outputDebugString ("Failed to initialise xlib thread support.");
 -                 Process::terminate();
 -                 return;
 -             }
 - 
 -             initThreadCalled = true;
 -         }
 - 
 -         X11ErrorHandling::installXErrorHandlers();
 -     }
 - }
 - 
 - XWindowSystem::~XWindowSystem() noexcept
 - {
 -     if (JUCEApplicationBase::isStandaloneApp())
 -         X11ErrorHandling::removeXErrorHandlers();
 - 
 -     clearSingletonInstance();
 - }
 - 
 - ::Display* XWindowSystem::displayRef() noexcept
 - {
 -     if (++displayCount == 1)
 -     {
 -         jassert (display == nullptr);
 - 
 -         String displayName (getenv ("DISPLAY"));
 - 
 -         if (displayName.isEmpty())
 -             displayName = ":0.0";
 - 
 -         // it seems that on some systems XOpenDisplay will occasionally
 -         // fail the first time, but succeed on a second attempt..
 -         for (int retries = 2; --retries >= 0;)
 -         {
 -             display = XOpenDisplay (displayName.toUTF8());
 - 
 -             if (display != nullptr)
 -                 break;
 -         }
 - 
 -         initialiseXDisplay();
 -     }
 - 
 -     return display;
 - }
 - 
 - ::Display* XWindowSystem::displayUnref() noexcept
 - {
 -     jassert (display != nullptr);
 -     jassert (displayCount.get() > 0);
 - 
 -     if (--displayCount == 0)
 -     {
 -         destroyXDisplay();
 -         XCloseDisplay (display);
 -         display = nullptr;
 -     }
 - 
 -     return display;
 - }
 - 
 - void XWindowSystem::initialiseXDisplay() noexcept
 - {
 -     // 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 = 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));
 - }
 - 
 - JUCE_IMPLEMENT_SINGLETON (XWindowSystem)
 - 
 - //==============================================================================
 - ScopedXDisplay::ScopedXDisplay() : display (XWindowSystem::getInstance()->displayRef())
 - {
 - }
 - 
 - ScopedXDisplay::~ScopedXDisplay()
 - {
 -     XWindowSystem::getInstance()->displayUnref();
 - }
 - 
 - //==============================================================================
 - ScopedXLock::ScopedXLock (::Display* d) : display (d)
 - {
 -     if (display != nullptr)
 -         XLockDisplay (display);
 - }
 - 
 - ScopedXLock::~ScopedXLock()
 - {
 -     if (display != nullptr)
 -         XUnlockDisplay (display);
 - }
 - 
 - //==============================================================================
 - Atoms::Atoms (::Display* display)
 - {
 -     protocols                    = getIfExists (display, "WM_PROTOCOLS");
 -     protocolList [TAKE_FOCUS]    = getIfExists (display, "WM_TAKE_FOCUS");
 -     protocolList [DELETE_WINDOW] = getIfExists (display, "WM_DELETE_WINDOW");
 -     protocolList [PING]          = getIfExists (display, "_NET_WM_PING");
 -     changeState                  = getIfExists (display, "WM_CHANGE_STATE");
 -     state                        = getIfExists (display, "WM_STATE");
 -     userTime                     = getCreating (display, "_NET_WM_USER_TIME");
 -     activeWin                    = getCreating (display, "_NET_ACTIVE_WINDOW");
 -     pid                          = getCreating (display, "_NET_WM_PID");
 -     windowType                   = getIfExists (display, "_NET_WM_WINDOW_TYPE");
 -     windowState                  = getIfExists (display, "_NET_WM_STATE");
 - 
 -     XdndAware                    = getCreating (display, "XdndAware");
 -     XdndEnter                    = getCreating (display, "XdndEnter");
 -     XdndLeave                    = getCreating (display, "XdndLeave");
 -     XdndPosition                 = getCreating (display, "XdndPosition");
 -     XdndStatus                   = getCreating (display, "XdndStatus");
 -     XdndDrop                     = getCreating (display, "XdndDrop");
 -     XdndFinished                 = getCreating (display, "XdndFinished");
 -     XdndSelection                = getCreating (display, "XdndSelection");
 - 
 -     XdndTypeList                 = getCreating (display, "XdndTypeList");
 -     XdndActionList               = getCreating (display, "XdndActionList");
 -     XdndActionCopy               = getCreating (display, "XdndActionCopy");
 -     XdndActionPrivate            = getCreating (display, "XdndActionPrivate");
 -     XdndActionDescription        = getCreating (display, "XdndActionDescription");
 - 
 -     XembedMsgType                = getCreating (display, "_XEMBED");
 -     XembedInfo                   = getCreating (display, "_XEMBED_INFO");
 - 
 -     allowedMimeTypes[0]          = getCreating (display, "UTF8_STRING");
 -     allowedMimeTypes[1]          = getCreating (display, "text/plain;charset=utf-8");
 -     allowedMimeTypes[2]          = getCreating (display, "text/plain");
 -     allowedMimeTypes[3]          = getCreating (display, "text/uri-list");
 - 
 -     allowedActions[0]            = getCreating (display, "XdndActionMove");
 -     allowedActions[1]            = XdndActionCopy;
 -     allowedActions[2]            = getCreating (display, "XdndActionLink");
 -     allowedActions[3]            = getCreating (display, "XdndActionAsk");
 -     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); }
 - 
 - String Atoms::getName (::Display* display, const Atom atom)
 - {
 -     if (atom == None)
 -         return "None";
 - 
 -     return String (XGetAtomName (display, atom));
 - }
 - 
 - bool Atoms::isMimeTypeFile (::Display* display, const Atom atom)
 - {
 -     return getName (display, atom).equalsIgnoreCase ("text/uri-list");
 - }
 - 
 - 
 - const unsigned long Atoms::DndVersion = 3;
 - 
 - //==============================================================================
 - GetXProperty::GetXProperty (::Display* display, Window window, Atom atom,
 -               long offset, long length, bool shouldDelete,
 -               Atom requestedType)
 - {
 -     success = (XGetWindowProperty (display, window, atom, offset, length,
 -                                    (Bool) shouldDelete, requestedType, &actualType,
 -                                    &actualFormat, &numItems, &bytesLeft, &data) == Success)
 -                 && data != nullptr;
 - }
 - 
 - GetXProperty::~GetXProperty()
 - {
 -     if (data != nullptr)
 -         XFree (data);
 - }
 - 
 - } // namespace juce
 
 
  |