diff --git a/modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp b/modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp index d6508e09f6..5aa3a15052 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp +++ b/modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp @@ -60,17 +60,19 @@ public: s.xselection.property = None; s.xselection.time = evt.xselectionrequest.time; + auto* display = getDisplay(); + if (allowedTypes.contains (targetType)) { s.xselection.property = evt.xselectionrequest.property; - X11Symbols::getInstance()->xChangeProperty (getDisplay(), evt.xselectionrequest.requestor, evt.xselectionrequest.property, + X11Symbols::getInstance()->xChangeProperty (display, evt.xselectionrequest.requestor, evt.xselectionrequest.property, targetType, 8, PropModeReplace, reinterpret_cast (textOrFiles.toRawUTF8()), (int) textOrFiles.getNumBytesAsUTF8()); } - X11Symbols::getInstance()->xSendEvent (getDisplay(), evt.xselectionrequest.requestor, True, 0, &s); + X11Symbols::getInstance()->xSendEvent (display, evt.xselectionrequest.requestor, True, 0, &s); } void handleExternalDragAndDropStatus (const XClientMessageEvent& clientMsg) @@ -81,9 +83,11 @@ public: canDrop = false; silentRect = {}; + const auto& atoms = getAtoms(); + if ((clientMsg.data.l[1] & 1) != 0 - && ((Atom) clientMsg.data.l[4] == getAtoms().XdndActionCopy - || (Atom) clientMsg.data.l[4] == getAtoms().XdndActionPrivate)) + && ((Atom) clientMsg.data.l[4] == atoms.XdndActionCopy + || (Atom) clientMsg.data.l[4] == atoms.XdndActionPrivate)) { if ((clientMsg.data.l[1] & 2) == 0) // target requests silent rectangle silentRect.setBounds ((int) clientMsg.data.l[2] >> 16, (int) clientMsg.data.l[2] & 0xffff, @@ -112,8 +116,11 @@ public: void handleExternalDragMotionNotify() { - auto newTargetWindow = externalFindDragTargetWindow (X11Symbols::getInstance()->xRootWindow (getDisplay(), - X11Symbols::getInstance()->xDefaultScreen (getDisplay()))); + auto* display = getDisplay(); + + auto newTargetWindow = externalFindDragTargetWindow (X11Symbols::getInstance() + ->xRootWindow (display, + X11Symbols::getInstance()->xDefaultScreen (display))); if (targetWindow != newTargetWindow) { @@ -153,13 +160,15 @@ public: (int) clientMsg.data.l[2] & 0xffff)); dropPos -= peer->getBounds().getPosition(); - auto targetAction = getAtoms().XdndActionCopy; + const auto& atoms = getAtoms(); - for (int i = numElementsInArray (getAtoms().allowedActions); --i >= 0;) + auto targetAction = atoms.XdndActionCopy; + + for (int i = numElementsInArray (atoms.allowedActions); --i >= 0;) { - if ((Atom) clientMsg.data.l[4] == getAtoms().allowedActions[i]) + if ((Atom) clientMsg.data.l[4] == atoms.allowedActions[i]) { - targetAction = getAtoms().allowedActions[i]; + targetAction = atoms.allowedActions[i]; break; } } @@ -206,12 +215,14 @@ public: return; } + const auto& atoms = getAtoms(); + dragAndDropSourceWindow = (::Window) clientMsg.data.l[0]; if ((clientMsg.data.l[1] & 1) != 0) { XWindowSystemUtilities::ScopedXLock xLock; - XWindowSystemUtilities::GetXProperty prop (dragAndDropSourceWindow, getAtoms().XdndTypeList, 0, 0x8000000L, false, XA_ATOM); + XWindowSystemUtilities::GetXProperty prop (dragAndDropSourceWindow, atoms.XdndTypeList, 0, 0x8000000L, false, XA_ATOM); if (prop.success && prop.actualType == XA_ATOM && prop.actualFormat == 32 && prop.numItems != 0) { @@ -244,9 +255,9 @@ public: } for (int i = 0; i < srcMimeTypeAtomList.size() && dragAndDropCurrentMimeType == 0; ++i) - for (int j = 0; j < numElementsInArray (getAtoms().allowedMimeTypes); ++j) - if (srcMimeTypeAtomList[i] == getAtoms().allowedMimeTypes[j]) - dragAndDropCurrentMimeType = getAtoms().allowedMimeTypes[j]; + for (int j = 0; j < numElementsInArray (atoms.allowedMimeTypes); ++j) + if (srcMimeTypeAtomList[i] == atoms.allowedMimeTypes[j]) + dragAndDropCurrentMimeType = atoms.allowedMimeTypes[j]; handleDragAndDropPosition (clientMsg, peer); } @@ -326,22 +337,26 @@ public: targetWindow = windowH; completionCallback = std::move (cb); - allowedTypes.add (XWindowSystemUtilities::Atoms::getCreating (getDisplay(), isText ? "text/plain" : "text/uri-list")); + auto* display = getDisplay(); + + allowedTypes.add (XWindowSystemUtilities::Atoms::getCreating (display, isText ? "text/plain" : "text/uri-list")); auto pointerGrabMask = (unsigned int) (Button1MotionMask | ButtonReleaseMask); XWindowSystemUtilities::ScopedXLock xLock; - if (X11Symbols::getInstance()->xGrabPointer (getDisplay(), windowH, True, pointerGrabMask, + if (X11Symbols::getInstance()->xGrabPointer (display, windowH, True, pointerGrabMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) == GrabSuccess) { + const auto& atoms = getAtoms(); + // No other method of changing the pointer seems to work, this call is needed from this very context - X11Symbols::getInstance()->xChangeActivePointerGrab (getDisplay(), pointerGrabMask, (Cursor) createDraggingHandCursor(), CurrentTime); + X11Symbols::getInstance()->xChangeActivePointerGrab (display, pointerGrabMask, (Cursor) createDraggingHandCursor(), CurrentTime); - X11Symbols::getInstance()->xSetSelectionOwner (getDisplay(), getAtoms().XdndSelection, windowH, CurrentTime); + X11Symbols::getInstance()->xSetSelectionOwner (display, atoms.XdndSelection, windowH, CurrentTime); // save the available types to XdndTypeList - X11Symbols::getInstance()->xChangeProperty (getDisplay(), windowH, getAtoms().XdndTypeList, XA_ATOM, 32, PropModeReplace, + X11Symbols::getInstance()->xChangeProperty (display, windowH, atoms.XdndTypeList, XA_ATOM, 32, PropModeReplace, reinterpret_cast (allowedTypes.getRawDataPointer()), allowedTypes.size()); dragging = true; @@ -358,32 +373,36 @@ public: private: //============================================================================== - XWindowSystemUtilities::Atoms& getAtoms() const { return XWindowSystem::getInstance()->getAtoms(); } - ::Display* getDisplay() const { return XWindowSystem::getInstance()->getDisplay(); } + const XWindowSystemUtilities::Atoms& getAtoms() const noexcept { return XWindowSystem::getInstance()->getAtoms(); } + ::Display* getDisplay() const noexcept { return XWindowSystem::getInstance()->getDisplay(); } //============================================================================== void sendDragAndDropMessage (XClientMessageEvent& msg) { + auto* display = getDisplay(); + msg.type = ClientMessage; - msg.display = getDisplay(); + msg.display = display; msg.window = dragAndDropSourceWindow; msg.format = 32; msg.data.l[0] = (long) windowH; XWindowSystemUtilities::ScopedXLock xLock; - X11Symbols::getInstance()->xSendEvent (getDisplay(), dragAndDropSourceWindow, False, 0, (XEvent*) &msg); + X11Symbols::getInstance()->xSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg); } bool sendExternalDragAndDropMessage (XClientMessageEvent& msg) { + auto* display = getDisplay(); + msg.type = ClientMessage; - msg.display = getDisplay(); + msg.display = display; msg.window = targetWindow; msg.format = 32; msg.data.l[0] = (long) windowH; XWindowSystemUtilities::ScopedXLock xLock; - return X11Symbols::getInstance()->xSendEvent (getDisplay(), targetWindow, False, 0, (XEvent*) &msg) != 0; + return X11Symbols::getInstance()->xSendEvent (display, targetWindow, False, 0, (XEvent*) &msg) != 0; } void sendExternalDragAndDropDrop() @@ -416,7 +435,9 @@ private: XClientMessageEvent msg; zerostruct (msg); - msg.message_type = getAtoms().XdndPosition; + const auto& atoms = getAtoms(); + + msg.message_type = atoms.XdndPosition; auto mousePos = Desktop::getInstance().getMousePosition(); @@ -428,7 +449,7 @@ private: msg.data.l[1] = 0; msg.data.l[2] = (mousePos.x << 16) | mousePos.y; msg.data.l[3] = CurrentTime; - msg.data.l[4] = (long) getAtoms().XdndActionCopy; // this is all JUCE currently supports + msg.data.l[4] = (long) atoms.XdndActionCopy; // this is all JUCE currently supports expectingStatus = sendExternalDragAndDropMessage (msg); } @@ -469,9 +490,11 @@ private: if (dragAndDropSourceWindow != None && dragAndDropCurrentMimeType != None) { + auto* display = getDisplay(); + XWindowSystemUtilities::ScopedXLock xLock; - X11Symbols::getInstance()->xConvertSelection (getDisplay(), getAtoms().XdndSelection, dragAndDropCurrentMimeType, - XWindowSystemUtilities::Atoms::getCreating (getDisplay(), "JXSelectionWindowProperty"), + X11Symbols::getInstance()->xConvertSelection (display, getAtoms().XdndSelection, dragAndDropCurrentMimeType, + XWindowSystemUtilities::Atoms::getCreating (display, "JXSelectionWindowProperty"), requestor, (::Time) clientMsg.data.l[2]); } } diff --git a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp index ebfbeaace3..fa6f54da56 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp +++ b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp @@ -1328,9 +1328,11 @@ namespace ClipboardHelpers int propertyFormat = 0; size_t numDataItems = 0; - if (evt.selection == XA_PRIMARY || evt.selection == XWindowSystem::getInstance()->getAtoms().clipboard) + const auto& atoms = XWindowSystem::getInstance()->getAtoms(); + + if (evt.selection == XA_PRIMARY || evt.selection == atoms.clipboard) { - if (evt.target == XA_STRING || evt.target == XWindowSystem::getInstance()->getAtoms().utf8String) + if (evt.target == XA_STRING || evt.target == atoms.utf8String) { auto localContent = XWindowSystem::getInstance()->getLocalClipboardContent(); @@ -1340,15 +1342,17 @@ namespace ClipboardHelpers localContent.copyToUTF8 (data, numDataItems); propertyFormat = 8; // bits/item } - else if (evt.target == XWindowSystem::getInstance()->getAtoms().targets) + else if (evt.target == atoms.targets) { // another application wants to know what we are able to send numDataItems = 2; propertyFormat = 32; // atoms are 32-bit data.calloc (numDataItems * 4); - Atom* atoms = unalignedPointerCast (data.getData()); - atoms[0] = XWindowSystem::getInstance()->getAtoms().utf8String; - atoms[1] = XA_STRING; + + auto* dataAtoms = unalignedPointerCast (data.getData()); + + dataAtoms[0] = atoms.utf8String; + dataAtoms[1] = XA_STRING; evt.target = XA_ATOM; } @@ -2588,14 +2592,12 @@ void XWindowSystem::copyTextToClipboard (const String& clipText) { localClipboardContent = clipText; - X11Symbols::getInstance()->xSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); + X11Symbols::getInstance()->xSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); X11Symbols::getInstance()->xSetSelectionOwner (display, atoms.clipboard, juce_messageWindowHandle, CurrentTime); } String XWindowSystem::getTextFromClipboard() const { - String content; - /* 1) try to read from the "CLIPBOARD" selection first (the "high level" clipboard that is supposed to be filled by ctrl-C etc). When a clipboard manager is running, the content of this @@ -2605,22 +2607,29 @@ String XWindowSystem::getTextFromClipboard() const 2) and then try to read from "PRIMARY" selection (the "legacy" selection filled by good old x11 apps such as xterm) */ - auto selection = XA_PRIMARY; - Window selectionOwner = None; - if ((selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selection)) == None) + auto getContentForSelection = [this] (Atom selectionAtom) -> String { - selection = atoms.clipboard; - selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selection); - } + auto selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selectionAtom); + + if (selectionOwner == None) + return {}; - if (selectionOwner != None) - { if (selectionOwner == juce_messageWindowHandle) - content = localClipboardContent; - else if (! ClipboardHelpers::requestSelectionContent (display, content, selection, atoms.utf8String)) - ClipboardHelpers::requestSelectionContent (display, content, selection, XA_STRING); - } + return localClipboardContent; + + String content; + + if (! ClipboardHelpers::requestSelectionContent (display, content, selectionAtom, atoms.utf8String)) + ClipboardHelpers::requestSelectionContent (display, content, selectionAtom, XA_STRING); + + return content; + }; + + auto content = getContentForSelection (atoms.clipboard); + + if (content.isEmpty()) + content = getContentForSelection (XA_PRIMARY); return content; } diff --git a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h index 7a78bec200..947eff4661 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h +++ b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h @@ -158,13 +158,12 @@ public: void copyTextToClipboard (const String&); String getTextFromClipboard() const; + String getLocalClipboardContent() const noexcept { return localClipboardContent; } - String getLocalClipboardContent() const { return localClipboardContent; } + ::Display* getDisplay() noexcept { return display; } + const XWindowSystemUtilities::Atoms& getAtoms() const noexcept { return atoms; } - ::Display* getDisplay() { return display; } - XWindowSystemUtilities::Atoms& getAtoms() { return atoms; } - - bool isX11Available() const noexcept { return xIsAvailable; } + bool isX11Available() const noexcept { return xIsAvailable; } //============================================================================== void handleWindowMessage (LinuxComponentPeer*, XEvent&) const;