From 2221cee889ffe33a442cf68e7aa8a9e28d16dd9a Mon Sep 17 00:00:00 2001 From: cutealien Date: Wed, 24 Jun 2009 14:44:51 +0000 Subject: [PATCH] - IOSOperator::getTextFromClipboard returns now const c8* instead of c8* - Support for copy&paste on linux (X11) added (fixing bug 2804014 found by Pan) git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2430 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 4 + include/IOSOperator.h | 2 +- source/Irrlicht/CIrrDeviceLinux.cpp | 135 +++++++++++++++++++++++++++- source/Irrlicht/CIrrDeviceLinux.h | 13 ++- source/Irrlicht/COSOperator.cpp | 39 +++++--- source/Irrlicht/COSOperator.h | 16 +++- 6 files changed, 191 insertions(+), 18 deletions(-) diff --git a/changes.txt b/changes.txt index 669630e3..3a19852f 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,9 @@ Changes in 1.6 + - IOSOperator::getTextFromClipboard returns now const c8* instead of c8* + + - Support for copy&paste on linux (X11) added (fixing bug 2804014 found by Pan) + - bugfix for 2795321 found by egrath: Don't rely anymore on broken XkbSetDetectableAutoRepeat. - bugfix: Use make_lower throughout for spritebank filenames (found and patched by Ion Dune) diff --git a/include/IOSOperator.h b/include/IOSOperator.h index 3bc1737b..21ff0877 100644 --- a/include/IOSOperator.h +++ b/include/IOSOperator.h @@ -26,7 +26,7 @@ public: //! Get text from the clipboard /** \return Returns 0 if no string is in there. */ - virtual c8* getTextFromClipboard() const = 0; + virtual const c8* getTextFromClipboard() const = 0; //! Get the processor speed in megahertz /** \param MHz The integer variable to store the speed in. diff --git a/source/Irrlicht/CIrrDeviceLinux.cpp b/source/Irrlicht/CIrrDeviceLinux.cpp index 779a3001..1058f90e 100644 --- a/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/source/Irrlicht/CIrrDeviceLinux.cpp @@ -19,6 +19,7 @@ #include "CColorConverter.h" #include "SIrrCreationParameters.h" #include +#include #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #include @@ -43,7 +44,13 @@ namespace irr } } // end namespace irr - +namespace +{ + Atom X_ATOM_CLIPBOARD; + Atom X_ATOM_TARGETS; + Atom X_ATOM_UTF8_STRING; + Atom X_ATOM_TEXT; +}; namespace irr { @@ -82,7 +89,7 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param) linuxversion += " "; linuxversion += LinuxInfo.machine; - Operator = new COSOperator(linuxversion.c_str()); + Operator = new COSOperator(linuxversion.c_str(), this); os::Printer::log(linuxversion.c_str(), ELL_INFORMATION); // create keymap @@ -580,7 +587,7 @@ bool CIrrDeviceLinux::createWindow() } WindowMinimized=false; // Currently broken in X, see Bug ID 2795321 - // XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport); + // XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport); #ifdef _IRR_COMPILE_WITH_OPENGL_ @@ -658,6 +665,8 @@ bool CIrrDeviceLinux::createWindow() SoftwareImage->data = (char*) malloc(SoftwareImage->bytes_per_line * SoftwareImage->height * sizeof(char)); } + initXAtoms(); + #endif // #ifdef _IRR_COMPILE_WITH_X11_ return true; } @@ -918,6 +927,53 @@ bool CIrrDeviceLinux::run() } break; + case SelectionRequest: + { + XEvent respond; + XSelectionRequestEvent *req = &(event.xselectionrequest); + Atom target = req->target; // debugging + if ( req->target == XA_STRING) + { + XChangeProperty (display, + req->requestor, + req->property, req->target, + 8, // format + PropModeReplace, + (unsigned char*) Clipboard.c_str(), + Clipboard.size()); + respond.xselection.property = req->property; + } + else if ( req->target == X_ATOM_TARGETS ) + { + long data[2]; + + data[0] = X_ATOM_TEXT; + data[1] = XA_STRING; + + XChangeProperty (display, req->requestor, + req->property, req->target, + 8, PropModeReplace, (unsigned char *) &data, + sizeof (data)); + respond.xselection.property = req->property; + } + else + { + char * name = XGetAtomName(display, req->target); // debugging + XFree(name); + + respond.xselection.property= None; + } + respond.xselection.type= SelectionNotify; + respond.xselection.display= req->display; + respond.xselection.requestor= req->requestor; + respond.xselection.selection=req->selection; + respond.xselection.target= req->target; + respond.xselection.time = req->time; + XSendEvent (display, req->requestor,0,0,&respond); + XFlush (display); + } + break; + default: break; } // end switch @@ -1496,6 +1552,79 @@ void CIrrDeviceLinux::pollJoysticks() #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ } +//! gets text from the clipboard +//! \return Returns 0 if no string is in there. +const c8* CIrrDeviceLinux::getTextFromClipboard() const +{ +#if defined(_IRR_COMPILE_WITH_X11_) + Window ownerWindow = XGetSelectionOwner (display, X_ATOM_CLIPBOARD); + if ( ownerWindow == window ) + { + return Clipboard.c_str(); + } + Clipboard = ""; + if (ownerWindow != None ) + { + XConvertSelection (display, X_ATOM_CLIPBOARD, XA_STRING, None, ownerWindow, CurrentTime); + XFlush (display); + + // check for data + Atom type; + int format; + unsigned long numItems, bytesLeft, dummy; + unsigned char *data; + XGetWindowProperty (display, ownerWindow, + XA_STRING, // property name + 0, // offset + 0, // length (we only check for data, so 0) + 0, // Delete 0==false + AnyPropertyType, // AnyPropertyType or property identifier + &type, // return type + &format, // return format + &numItems, // number items + &bytesLeft, // remaining bytes for partial reads + &data); // data + if ( bytesLeft > 0 ) + { + // there is some data to get + int result = XGetWindowProperty (display, ownerWindow, XA_STRING, 0, + bytesLeft, 0, AnyPropertyType, &type, &format, + &numItems, &dummy, &data); + if (result == Success) + Clipboard = (irr::c8*)data; + XFree (data); + } + } + + return Clipboard.c_str(); + +#else + return 0; +#endif +} + +//! copies text to the clipboard +void CIrrDeviceLinux::copyToClipboard(const c8* text) const +{ +#if defined(_IRR_COMPILE_WITH_X11_) + // Actually there is no clipboard on X but applications just say they own the clipboard and return text when asked. + // Which btw. also means that on X you lose clipboard content when closing applications. + Clipboard = text; + XSetSelectionOwner (display, X_ATOM_CLIPBOARD, window, CurrentTime); + XFlush (display); +#endif +} + +void CIrrDeviceLinux::initXAtoms() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + X_ATOM_CLIPBOARD = XInternAtom(display, "CLIPBOARD", False); + X_ATOM_TARGETS = XInternAtom(display, "TARGETS", False); + X_ATOM_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); + X_ATOM_TEXT = XInternAtom (display, "TEXT", False); +#endif +} + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx(const SIrrlichtCreationParameters& param) { diff --git a/source/Irrlicht/CIrrDeviceLinux.h b/source/Irrlicht/CIrrDeviceLinux.h index ba4b6270..e2d6588b 100644 --- a/source/Irrlicht/CIrrDeviceLinux.h +++ b/source/Irrlicht/CIrrDeviceLinux.h @@ -96,6 +96,14 @@ namespace irr //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); + //! gets text from the clipboard + //! \return Returns 0 if no string is in there. + virtual const c8* getTextFromClipboard() const; + + //! copies text to the clipboard + //! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button. + virtual void copyToClipboard(const c8* text) const; + private: //! create the driver @@ -105,7 +113,9 @@ namespace irr void createKeyMap(); - void pollJoysticks(); + void pollJoysticks(); + + void initXAtoms(); //! Implementation of the linux cursor control class CCursorControl : public gui::ICursorControl @@ -310,6 +320,7 @@ namespace irr XSetWindowAttributes attributes; XSizeHints* StdHints; XImage* SoftwareImage; + mutable core::stringc Clipboard; #ifdef _IRR_LINUX_X11_VIDMODE_ XF86VidModeModeInfo oldVideoMode; #endif diff --git a/source/Irrlicht/COSOperator.cpp b/source/Irrlicht/COSOperator.cpp index 72f3f909..42169877 100644 --- a/source/Irrlicht/COSOperator.cpp +++ b/source/Irrlicht/COSOperator.cpp @@ -3,7 +3,6 @@ // For conditions of distribution and use, see copyright notice in irrlicht.h #include "COSOperator.h" -#include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_XBOX_PLATFORM_ @@ -22,10 +21,21 @@ #endif #endif +#if defined(_IRR_USE_LINUX_DEVICE_) +#include "CIrrDeviceLinux.h" +#endif + namespace irr { +#if defined(_IRR_USE_LINUX_DEVICE_) +// constructor linux +COSOperator::COSOperator(const c8* osversion, CIrrDeviceLinux* device) +: IrrDeviceLinux(device) +{ +} +#else // not linux // constructor COSOperator::COSOperator(const c8* osVersion) : OperatingSystem(osVersion) { @@ -33,7 +43,7 @@ COSOperator::COSOperator(const c8* osVersion) : OperatingSystem(osVersion) setDebugName("COSOperator"); #endif } - +#endif //! returns the current operating system version as string. const wchar_t* COSOperator::getOperationSystemVersion() const @@ -72,23 +82,26 @@ void COSOperator::copyToClipboard(const c8* text) const #elif defined(_IRR_USE_OSX_DEVICE_) OSXCopyToClipboard(text); + +#elif defined(_IRR_USE_LINUX_DEVICE_) + if ( IrrDeviceLinux ) + IrrDeviceLinux->copyToClipboard(text); #else -// todo: Linux version #endif } //! gets text from the clipboard //! \return Returns 0 if no string is in there. -c8* COSOperator::getTextFromClipboard() const +const c8* COSOperator::getTextFromClipboard() const { #if defined(_IRR_XBOX_PLATFORM_) return 0; #elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL)) return 0; - + char * buffer = 0; HANDLE hData = GetClipboardData( CF_TEXT ); @@ -99,9 +112,13 @@ c8* COSOperator::getTextFromClipboard() const #elif defined(_IRR_USE_OSX_DEVICE_) return (OSXCopyFromClipboard()); -#else -// todo: Linux version +#elif defined(_IRR_USE_LINUX_DEVICE_) + if ( IrrDeviceLinux ) + return IrrDeviceLinux->getTextFromClipboard(); + return 0; + +#else return 0; #endif @@ -112,7 +129,7 @@ bool COSOperator::getProcessorSpeedMHz(u32* MHz) const { #if defined(_IRR_WINDOWS_API_) && !defined(_WIN32_WCE ) && !defined (_IRR_XBOX_PLATFORM_) LONG Error; - + HKEY Key; Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", @@ -163,7 +180,7 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const *Total = (u32)(MemoryStatus.dwTotalPhys>>10); if (Avail) *Avail = (u32)(MemoryStatus.dwAvailPhys>>10); - + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return true; @@ -172,7 +189,7 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const long ps = sysconf(_SC_PAGESIZE); long pp = sysconf(_SC_PHYS_PAGES); long ap = sysconf(_SC_AVPHYS_PAGES); - + if ((ps==-1)||(pp==-1)||(ap==-1)) return false; @@ -186,7 +203,7 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const return false; #endif #else - // TODO: implement for OSX + // TODO: implement for OSX return false; #endif } diff --git a/source/Irrlicht/COSOperator.h b/source/Irrlicht/COSOperator.h index 9f5a4640..a4cbccfe 100644 --- a/source/Irrlicht/COSOperator.h +++ b/source/Irrlicht/COSOperator.h @@ -7,17 +7,24 @@ #include "IOSOperator.h" #include "irrString.h" +#include "IrrCompileConfig.h" namespace irr { +class CIrrDeviceLinux; + //! The Operating system operator provides operation system specific methods and informations. class COSOperator : public IOSOperator { public: // constructor - COSOperator(const c8* osversion); +#if defined(_IRR_USE_LINUX_DEVICE_) + COSOperator(const c8* osversion, CIrrDeviceLinux* device); +#else + COSOperator(const c8* osversion); +#endif //! returns the current operation system version as string. virtual const wchar_t* getOperationSystemVersion() const; @@ -27,7 +34,7 @@ public: //! gets text from the clipboard //! \return Returns 0 if no string is in there. - virtual c8* getTextFromClipboard() const; + virtual const c8* getTextFromClipboard() const; //! gets the processor speed in megahertz //! \param Mhz: @@ -43,6 +50,11 @@ public: private: core::stringw OperatingSystem; + +#if defined(_IRR_USE_LINUX_DEVICE_) + CIrrDeviceLinux * IrrDeviceLinux; +#endif + }; } // end namespace