]> git.lizzy.rs Git - irrlicht.git/commitdiff
Implement X11 primary selection
authorDesour <vorunbekannt75@web.de>
Tue, 23 Aug 2022 15:19:23 +0000 (17:19 +0200)
committersfan5 <sfan5@live.de>
Fri, 24 Mar 2023 16:59:06 +0000 (17:59 +0100)
include/IOSOperator.h
source/Irrlicht/CIrrDeviceLinux.cpp
source/Irrlicht/CIrrDeviceLinux.h
source/Irrlicht/COSOperator.cpp
source/Irrlicht/COSOperator.h

index b195aed70b8afff63e35ae03cc93a6b9e9f339ca..6e5768aa61aaacb2d3e69654f9f7648fbc39f247 100644 (file)
@@ -26,12 +26,23 @@ public:
        }\r
 \r
        //! Copies text to the clipboard\r
+       //! \param text: text in utf-8\r
        virtual void copyToClipboard(const c8* text) const = 0;\r
 \r
+       //! Copies text to the primary selection\r
+       //! This is a no-op on some platforms.\r
+       //! \param text: text in utf-8\r
+       virtual void copyToPrimarySelection(const c8* text) const = 0;\r
+\r
        //! Get text from the clipboard\r
-       /** \return Returns 0 if no string is in there. */\r
+       //! \return Returns 0 if no string is in there, otherwise an utf-8 string.\r
        virtual const c8* getTextFromClipboard() const = 0;\r
 \r
+       //! Get text from the primary selection\r
+       //! This is a no-op on some platforms.\r
+       //! \return Returns 0 if no string is in there, otherwise an utf-8 string.\r
+       virtual const c8* getTextFromPrimarySelection() const = 0;\r
+\r
        //! Get the total and available system RAM\r
        /** \param totalBytes: will contain the total system memory in Kilobytes (1024 B)\r
        \param availableBytes: will contain the available memory in Kilobytes (1024 B)\r
index 3c1909917f4b5a25b53340b6ef1b516dde0ee738..0efc8f4f49451fe10f53bb9f12bb90320657eb07 100644 (file)
@@ -1000,12 +1000,15 @@ bool CIrrDeviceLinux::run()
                                                send_response(req->property);\r
                                        };\r
 \r
-                                       if (req->selection != X_ATOM_CLIPBOARD ||\r
+                                       if ((req->selection != X_ATOM_CLIPBOARD &&\r
+                                                       req->selection != XA_PRIMARY) ||\r
                                                        req->owner != XWindow) {\r
                                                // we are not the owner, refuse request\r
                                                send_response_refuse();\r
                                                break;\r
                                        }\r
+                                       const core::stringc &text_buffer = req->selection == X_ATOM_CLIPBOARD ?\r
+                                                       Clipboard : PrimarySelection;\r
 \r
                                        // for debugging:\r
                                        //~ {\r
@@ -1026,8 +1029,8 @@ bool CIrrDeviceLinux::run()
                                                                req->target, X_ATOM_UTF8_STRING,\r
                                                                8, // format = 8-bit\r
                                                                PropModeReplace,\r
-                                                               (unsigned char *)Clipboard.c_str(),\r
-                                                               Clipboard.size());\r
+                                                               (unsigned char *)text_buffer.c_str(),\r
+                                                               text_buffer.size());\r
                                                send_response(req->target);\r
                                                break;\r
                                        }\r
@@ -1052,8 +1055,8 @@ bool CIrrDeviceLinux::run()
                                                set_property_and_notify(\r
                                                                X_ATOM_UTF8_STRING,\r
                                                                8,\r
-                                                               Clipboard.c_str(),\r
-                                                               Clipboard.size()\r
+                                                               text_buffer.c_str(),\r
+                                                               text_buffer.size()\r
                                                        );\r
 \r
                                        } else {\r
@@ -1676,47 +1679,49 @@ void CIrrDeviceLinux::pollJoysticks()
 }\r
 \r
 \r
+#if defined(_IRR_COMPILE_WITH_X11_)\r
 //! gets text from the clipboard\r
 //! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
-const c8 *CIrrDeviceLinux::getTextFromClipboard() const\r
+const c8 *CIrrDeviceLinux::getTextFromSelection(Atom selection, core::stringc &text_buffer) const\r
 {\r
-#if defined(_IRR_COMPILE_WITH_X11_)\r
-       Window ownerWindow = XGetSelectionOwner(XDisplay, X_ATOM_CLIPBOARD);\r
+       Window ownerWindow = XGetSelectionOwner(XDisplay, selection);\r
        if (ownerWindow == XWindow) {\r
-               return Clipboard.c_str();\r
+               return text_buffer.c_str();\r
        }\r
 \r
-       Clipboard = "";\r
+       text_buffer = "";\r
 \r
        if (ownerWindow == None) {\r
-               return Clipboard.c_str();\r
+               return text_buffer.c_str();\r
        }\r
 \r
        // delete the property to be set beforehand\r
        XDeleteProperty(XDisplay, XWindow, XA_PRIMARY);\r
 \r
-       XConvertSelection(XDisplay, X_ATOM_CLIPBOARD, X_ATOM_UTF8_STRING, XA_PRIMARY,\r
+       XConvertSelection(XDisplay, selection, X_ATOM_UTF8_STRING, XA_PRIMARY,\r
                        XWindow, CurrentTime);\r
        XFlush(XDisplay);\r
 \r
        // wait for event via a blocking call\r
        XEvent event_ret;\r
+       std::pair<Window, Atom> args(XWindow, selection);\r
        XIfEvent(XDisplay, &event_ret, [](Display *_display, XEvent *event, XPointer arg) {\r
+               auto p = reinterpret_cast<std::pair<Window, Atom> *>(arg);\r
                return (Bool) (event->type == SelectionNotify &&\r
-                               event->xselection.requestor == *(Window *)arg &&\r
-                               event->xselection.selection == X_ATOM_CLIPBOARD &&\r
+                               event->xselection.requestor == p->first &&\r
+                               event->xselection.selection == p->second &&\r
                                event->xselection.target == X_ATOM_UTF8_STRING);\r
-       }, (XPointer)&XWindow);\r
+       }, (XPointer)&args);\r
 \r
        _IRR_DEBUG_BREAK_IF(!(event_ret.type == SelectionNotify &&\r
                        event_ret.xselection.requestor == XWindow &&\r
-                       event_ret.xselection.selection == X_ATOM_CLIPBOARD &&\r
+                       event_ret.xselection.selection == selection &&\r
                        event_ret.xselection.target == X_ATOM_UTF8_STRING));\r
 \r
        Atom property_set = event_ret.xselection.property;\r
        if (event_ret.xselection.property == None) {\r
                // request failed => empty string\r
-               return Clipboard.c_str();\r
+               return text_buffer.c_str();\r
        }\r
 \r
        // check for data\r
@@ -1743,15 +1748,15 @@ const c8 *CIrrDeviceLinux::getTextFromClipboard() const
        // for debugging:\r
        //~ {\r
                //~ char *type_name = XGetAtomName(XDisplay, type);\r
-               //~ fprintf(stderr, "CIrrDeviceLinux::getTextFromClipboard: actual type: %s (=%ld)\n",\r
+               //~ fprintf(stderr, "CIrrDeviceLinux::getTextFromSelection: actual type: %s (=%ld)\n",\r
                                //~ type_name, type);\r
                //~ XFree(type_name);\r
        //~ }\r
 \r
        if (type != X_ATOM_UTF8_STRING && type != X_ATOM_UTF8_MIME_TYPE) {\r
-               os::Printer::log("CIrrDeviceLinux::getTextFromClipboard: did not get utf-8 string",\r
+               os::Printer::log("CIrrDeviceLinux::getTextFromSelection: did not get utf-8 string",\r
                                ELL_WARNING);\r
-               return Clipboard.c_str();\r
+               return text_buffer.c_str();\r
        }\r
 \r
        if (bytesLeft > 0) {\r
@@ -1760,20 +1765,49 @@ const c8 *CIrrDeviceLinux::getTextFromClipboard() const
                                                                        bytesLeft, 0, AnyPropertyType, &type, &format,\r
                                                                        &numItems, &dummy, &data);\r
                if (result == Success)\r
-                       Clipboard = (irr::c8 *)data;\r
+                       text_buffer = (irr::c8 *)data;\r
                XFree (data);\r
        }\r
 \r
        // delete the property again, to inform the owner about the successful transfer\r
        XDeleteProperty(XDisplay, XWindow, property_set);\r
 \r
-       return Clipboard.c_str();\r
+       return text_buffer.c_str();\r
+}\r
+#endif\r
 \r
+//! gets text from the clipboard\r
+//! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
+const c8 *CIrrDeviceLinux::getTextFromClipboard() const\r
+{\r
+#if defined(_IRR_COMPILE_WITH_X11_)\r
+       return getTextFromSelection(X_ATOM_CLIPBOARD, Clipboard);\r
 #else\r
        return nullptr;\r
 #endif\r
 }\r
 \r
+//! gets text from the primary selection\r
+//! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
+const c8 *CIrrDeviceLinux::getTextFromPrimarySelection() const\r
+{\r
+#if defined(_IRR_COMPILE_WITH_X11_)\r
+       return getTextFromSelection(XA_PRIMARY, PrimarySelection);\r
+#else\r
+       return nullptr;\r
+#endif\r
+}\r
+\r
+#if defined(_IRR_COMPILE_WITH_X11_)\r
+bool CIrrDeviceLinux::becomeSelectionOwner(Atom selection) const\r
+{\r
+       XSetSelectionOwner (XDisplay, selection, XWindow, CurrentTime);\r
+       XFlush (XDisplay);\r
+       Window owner = XGetSelectionOwner(XDisplay, selection);\r
+       return owner == XWindow;\r
+}\r
+#endif\r
+\r
 //! copies text to the clipboard\r
 void CIrrDeviceLinux::copyToClipboard(const c8 *text) const\r
 {\r
@@ -1781,15 +1815,23 @@ void CIrrDeviceLinux::copyToClipboard(const c8 *text) const
        // Actually there is no clipboard on X but applications just say they own the clipboard and return text when asked.\r
        // Which btw. also means that on X you lose clipboard content when closing applications.\r
        Clipboard = text;\r
-       XSetSelectionOwner (XDisplay, X_ATOM_CLIPBOARD, XWindow, CurrentTime);\r
-       XFlush (XDisplay);\r
-       Window owner = XGetSelectionOwner(XDisplay, X_ATOM_CLIPBOARD);\r
-       if (owner != XWindow) {\r
+       if (!becomeSelectionOwner(X_ATOM_CLIPBOARD)) {\r
                os::Printer::log("CIrrDeviceLinux::copyToClipboard: failed to set owner", ELL_WARNING);\r
        }\r
 #endif\r
 }\r
 \r
+//! copies text to the primary selection\r
+void CIrrDeviceLinux::copyToPrimarySelection(const c8 *text) const\r
+{\r
+#if defined(_IRR_COMPILE_WITH_X11_)\r
+       PrimarySelection = text;\r
+       if (!becomeSelectionOwner(XA_PRIMARY)) {\r
+               os::Printer::log("CIrrDeviceLinux::copyToPrimarySelection: failed to set owner", ELL_WARNING);\r
+       }\r
+#endif\r
+}\r
+\r
 #ifdef _IRR_COMPILE_WITH_X11_\r
 // return true if the passed event has the type passed in parameter arg\r
 Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg)\r
index 2d8945c9b5d907911bde4fc9836fb8da8c3a4090..544a73645b4168ad6fa9a7e648e5bd0321299bf3 100644 (file)
@@ -97,11 +97,20 @@ namespace irr
                //! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
                virtual const c8 *getTextFromClipboard() const;\r
 \r
+               //! gets text from the primary selection\r
+               //! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
+               virtual const c8 *getTextFromPrimarySelection() const;\r
+\r
                //! copies text to the clipboard\r
-               //! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button.\r
+               //! This sets the clipboard selection and _not_ the primary selection.\r
                //! @param text The text in utf-8\r
                virtual void copyToClipboard(const c8 *text) const;\r
 \r
+               //! copies text to the primary selection\r
+               //! This sets the primary selection which you have on X on the middle mouse button.\r
+               //! @param text The text in utf-8\r
+               virtual void copyToPrimarySelection(const c8 *text) const;\r
+\r
                //! Remove all messages pending in the system message loop\r
                void clearSystemMessages() override;\r
 \r
@@ -141,6 +150,9 @@ namespace irr
                bool createInputContext();\r
                void destroyInputContext();\r
                EKEY_CODE getKeyCode(XEvent &event);\r
+\r
+               const c8 *getTextFromSelection(Atom selection, core::stringc &text_buffer) const;\r
+               bool becomeSelectionOwner(Atom selection) const;\r
 #endif\r
 \r
                //! Implementation of the linux cursor control\r
@@ -413,6 +425,7 @@ namespace irr
                bool HasNetWM;\r
                // text is utf-8\r
                mutable core::stringc Clipboard;\r
+               mutable core::stringc PrimarySelection;\r
 #endif\r
 #if defined(_IRR_LINUX_X11_XINPUT2_)\r
                int currentTouchedCount;\r
index 25b04ad88821285830da66cfc563ab6597e61dc5..906035aa147a4e526fea560e40af501e6c4dfe61 100644 (file)
@@ -54,7 +54,6 @@ const core::stringc& COSOperator::getOperatingSystemVersion() const
 \r
 \r
 //! copies text to the clipboard\r
-//! \param text: text in utf-8\r
 void COSOperator::copyToClipboard(const c8 *text) const\r
 {\r
        if (strlen(text)==0)\r
@@ -102,8 +101,20 @@ void COSOperator::copyToClipboard(const c8 *text) const
 }\r
 \r
 \r
+//! copies text to the primary selection\r
+void COSOperator::copyToPrimarySelection(const c8 *text) const\r
+{\r
+       if (strlen(text)==0)\r
+               return;\r
+\r
+#if defined(_IRR_COMPILE_WITH_X11_DEVICE_)\r
+    if ( IrrDeviceLinux )\r
+        IrrDeviceLinux->copyToPrimarySelection(text);\r
+#endif\r
+}\r
+\r
+\r
 //! gets text from the clipboard\r
-//! \return Returns 0 if no string is in there, otherwise an utf-8 string.\r
 const c8* COSOperator::getTextFromClipboard() const\r
 {\r
 #if defined(_IRR_WINDOWS_API_)\r
@@ -147,6 +158,21 @@ const c8* COSOperator::getTextFromClipboard() const
 }\r
 \r
 \r
+//! gets text from the primary selection\r
+const c8* COSOperator::getTextFromPrimarySelection() const\r
+{\r
+#if defined(_IRR_COMPILE_WITH_X11_DEVICE_)\r
+    if ( IrrDeviceLinux )\r
+        return IrrDeviceLinux->getTextFromPrimarySelection();\r
+    return 0;\r
+\r
+#else\r
+\r
+       return 0;\r
+#endif\r
+}\r
+\r
+\r
 bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const\r
 {\r
 #if defined(_IRR_WINDOWS_API_)\r
index 6ef0f9ba290f12d918ba4822c70abfa7437e818f..6510579e28030b64adb89c9f3f594b3b7ef18800 100644 (file)
@@ -27,13 +27,17 @@ public:
        const core::stringc& getOperatingSystemVersion() const override;\r
 \r
        //! copies text to the clipboard\r
-       //! \param text: text in utf-8\r
        void copyToClipboard(const c8 *text) const override;\r
 \r
+       //! copies text to the primary selection\r
+       void copyToPrimarySelection(const c8 *text) const override;\r
+\r
        //! gets text from the clipboard\r
-       //! \return Returns 0 if no string is in there, otherwise an utf-8 string.\r
        const c8* getTextFromClipboard() const override;\r
 \r
+       //! gets text from the primary selection\r
+       const c8* getTextFromPrimarySelection() const override;\r
+\r
        //! gets the total and available system RAM in kB\r
        //! \param Total: will contain the total system memory\r
        //! \param Avail: will contain the available memory\r