diff -r 4ace6f8793f6 code/nel/include/nel/3d/driver.h --- a/code/nel/include/nel/3d/driver.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/include/nel/3d/driver.h Fri Oct 15 21:33:52 2010 +0200 @@ -1215,6 +1215,10 @@ // get the number of call to swapBuffer since the driver was created virtual uint64 getSwapBufferCounter() const = 0; + virtual bool copyTextToClipboard(const ucstring &text) = 0; + + virtual bool pasteTextFromClipboard(ucstring &text) = 0; + /** Set cull mode * Useful for mirrors / cube map rendering or when the scene must be rendered upside down */ diff -r 4ace6f8793f6 code/nel/include/nel/3d/driver_user.h --- a/code/nel/include/nel/3d/driver_user.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/include/nel/3d/driver_user.h Fri Oct 15 21:33:52 2010 +0200 @@ -535,6 +535,9 @@ virtual void deleteWaterEnvMap(UWaterEnvMap *map); // @} + virtual bool copyTextToClipboard(const ucstring &text); + + virtual bool pasteTextFromClipboard(ucstring &text); virtual uint64 getSwapBufferCounter(); diff -r 4ace6f8793f6 code/nel/include/nel/3d/u_driver.h --- a/code/nel/include/nel/3d/u_driver.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/include/nel/3d/u_driver.h Fri Oct 15 21:33:52 2010 +0200 @@ -816,6 +816,10 @@ virtual uint64 getSwapBufferCounter() = 0; + virtual bool copyTextToClipboard(const ucstring &text) =0; + + virtual bool pasteTextFromClipboard(ucstring &text) =0; + public: /** diff -r 4ace6f8793f6 code/nel/include/nel/misc/event_emitter_multi.h --- a/code/nel/include/nel/misc/event_emitter_multi.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/include/nel/misc/event_emitter_multi.h Fri Oct 15 21:33:52 2010 +0200 @@ -48,6 +48,9 @@ /// From IEventEmitter. This call submitEvents on all the emitters virtual void submitEvents(CEventServer &server, bool allWindows); virtual void emulateMouseRawMode(bool enable); + virtual bool copyTextToClipboard(const ucstring &text); + + virtual bool pasteTextFromClipboard(ucstring &text); private: typedef std::vector > TEmitterCont; TEmitterCont _Emitters; diff -r 4ace6f8793f6 code/nel/src/3d/driver/direct3d/driver_direct3d.cpp --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -292,8 +292,9 @@ _SumTextureMemoryUsed = false; - _DesktopGammaRampValid = false; + // initialize COM + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); } // *************************************************************************** @@ -3831,5 +3832,13 @@ } } } - +bool CDriverD3D::copyTextToClipboard(const ucstring &text) +{ + return _EventEmitter.copyTextToClipboard(text); +} + +bool CDriverD3D::pasteTextFromClipboard(ucstring &text) +{ + return _EventEmitter.pasteTextFromClipboard(text); +} } // NL3D diff -r 4ace6f8793f6 code/nel/src/3d/driver/direct3d/driver_direct3d.h --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h Fri Oct 15 21:33:52 2010 +0200 @@ -2392,6 +2392,10 @@ void deleteIndexBuffer(CIBDrvInfosD3D *ib); // Build 16 bit index buffer for quad bool buildQuadIndexBuffer(); + virtual bool copyTextToClipboard(const ucstring &text); + + virtual bool pasteTextFromClipboard(ucstring &text); + public: #ifdef NL_DEBUG std::set _LockedBuffers; diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/driver_opengl.cpp --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -322,6 +322,10 @@ _TextureTargetCubeFace = 0; _TextureTargetUpload = false; +#ifdef NL_OS_WINDOWS + // initialize COM + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); +#endif } // *************************************************************************** @@ -2704,6 +2708,16 @@ { } +bool CDriverGL::copyTextToClipboard(const ucstring &text) +{ + return _EventEmitter.copyTextToClipboard(text); +} + +bool CDriverGL::pasteTextFromClipboard(ucstring &text) +{ + return _EventEmitter.pasteTextFromClipboard(text); +} + } // NL3D // *************************************************************************** diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/driver_opengl.h --- a/code/nel/src/3d/driver/opengl/driver_opengl.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h Fri Oct 15 21:33:52 2010 +0200 @@ -325,6 +325,9 @@ { return _win; } + virtual bool copyTextToClipboard(const ucstring &text); + + virtual bool pasteTextFromClipboard(ucstring &text); virtual uint32 getAvailableVertexAGPMemory (); virtual uint32 getAvailableVertexVRAMMemory (); diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -32,5 +32,13 @@ // just forwarding to our cocoa adapter NL3D::MAC::emulateMouseRawMode(enable); } +bool CCocoaEventEmitter::pasteTextFromClipboard(ucstring &text) +{ + return false; +} +bool CCocoaEventEmitter::copyTextToClipboard(const ucstring &text) +{ + return false; +} } diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h Fri Oct 15 21:33:52 2010 +0200 @@ -27,8 +27,15 @@ public: virtual void submitEvents(CEventServer & server, bool allWindows); virtual void emulateMouseRawMode(bool enable); -}; + /** + * + */ + virtual bool copyTextToClipboard(const ucstring &text); + /* + * + */ + virtual bool pasteTextFromClipboard(ucstring &text);}; } #endif diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/unix_event_emitter.cpp --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -19,6 +19,8 @@ #if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) +#include +#include #include #include #include @@ -33,6 +35,7 @@ { _im = 0; _ic = 0; + _SelectionOwned=false; } CUnixEventEmitter::~CUnixEventEmitter() @@ -47,12 +50,24 @@ _win = win; _driver = driver; - XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask); + XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask); + _PrecomputedAtom[0] = XInternAtom(dpy, "CLIPBOARD",False); + #define XA_CLIPBOARD _PrecomputedAtom[0] + _PrecomputedAtom[1] = XInternAtom(dpy, "UTF8_STRING",False); + #define XA_UTF8_STRING _PrecomputedAtom[1] + _PrecomputedAtom[2] = XInternAtom(dpy, "TARGETS",False); + #define XA_TARGETS _PrecomputedAtom[2] + _PrecomputedAtom[3] = XInternAtom(dpy, "ATOM",False); + //#define XA_ATOM _PrecomputedAtom[3] + _PrecomputedAtom[4] = XInternAtom(dpy, "NeL_SEL",False); + #define XA_NEL_SEL _PrecomputedAtom[4] + _PrecomputedAtom[5] = XInternAtom(dpy, "TEXT",False); + #define XA_TEXT _PrecomputedAtom[5] /* TODO: implements all useful events processing EnterWindowMask|LeaveWindowMask|ButtonMotionMask|Button1MotionMask|Button2MotionMask| - Button3MotionMask|Button4MotionMask|Button5MotionMask|KeymapStateMask|ExposureMask| + Button3MotionMask|Button4MotionMask|Button5MotionMask|KeymapStateMask| SubstructureNotifyMask|VisibilityChangeMask|FocusChangeMask|PropertyChangeMask| ColormapChangeMask|OwnerGrabButtonMask */ @@ -578,6 +593,61 @@ } break; } + case SelectionRequest: + { + XEvent respond; + XSelectionRequestEvent *req=&(event.xselectionrequest); + + 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; + respond.xselection.property = req->property; + if (req->property == None) + { + respond.xselection.property=req->target; + } + if (req->target == XA_TARGETS) + { + nlwarning("Client is asking for TARGETS"); + Atom targets[] = { + XA_TARGETS + , XA_TEXT + , XA_UTF8_STRING + }; + respond.xselection.property = req->property; + + XChangeProperty(req->display, req->requestor, req->property, XA_ATOM, 32, PropModeReplace, (unsigned char *)targets, 3 /* number of element */); + } + else if (req->target == XInternAtom(_dpy, "TEXT", False) || req->target == XA_STRING ) + { + nlwarning("client want TEXT"); + respond.xselection.property=req->property; + std::string str=_CopiedString.toString(); + XChangeProperty(req->display, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), strlen(str.c_str())); + } + else if (req->target == XInternAtom(_dpy, "UTF8_STRING", False)) + { + nlwarning("Client want UTF8 STRING"); + respond.xselection.property=req->property; + std::string str=_CopiedString.toUtf8(); + XChangeProperty(req->display, req->requestor, respond.xselection.property, XInternAtom(_dpy, "UTF8_STRING", False), 8, PropModeReplace, (const unsigned char*)str.c_str(), strlen((char*)str.c_str())); + } + else + { + nlwarning("Target doesn't want a string %u",req->target); // Note: Calling XGetAtomName with arbitrary value crash the client, maybe req->target have been sanitized by X11 server + respond.xselection.property= None; + } + XSendEvent (_dpy, req->requestor,0,0,&respond); + break; + } + case SelectionClear: + nlwarning("SelectionClear:"); + _SelectionOwned=false; + _CopiedString=""; + break; case FocusIn: // keyboard focus if (_ic) XSetICFocus(_ic); @@ -605,6 +675,146 @@ return true; } +/** + * This function copy a selection into propertyName. + * It is subject to timeout. + * + * @param selection: A Selection Atom + * @param requestedFormat: Target format Atom + * @param propertyName: Target property Atom + * @return true if successfull, false if timeout occured or X11 call failed + */ +bool CUnixEventEmitter::prepareSelectionContent (Atom selection, Atom requestedFormat, Atom propertyName) +{ + XConvertSelection(_dpy, selection, requestedFormat, propertyName, _win, CurrentTime); + XSync (_dpy, False); + int i=0; + bool gotReply=false; + do { + XEvent event; + usleep(500); + gotReply = XCheckTypedWindowEvent(_dpy, _win, SelectionNotify, &event); + if (gotReply) + { + return true; + } + i++; + } while (i<20); + return false; +} + +bool CUnixEventEmitter::copyTextToClipboard(const ucstring &text) +{ + _CopiedString=text; + XSetSelectionOwner (_dpy, XA_CLIPBOARD, _win, CurrentTime); + { + Window selectionOwner=XGetSelectionOwner (_dpy, XA_CLIPBOARD); + if ( selectionOwner != _win ) + { + nlwarning("Can't aquire selection"); + return false; + } + _SelectionOwned=true; + nlwarning("Owning selection"); + return true; + } + nlwarning("Paste: Can't acquire selection."); + return false; +} + +bool CUnixEventEmitter::pasteTextFromClipboard(ucstring &text) +{ + // check if we own the selection + if (_SelectionOwned) + { + text=_CopiedString; + return true; + } + Window selectionOwner=XGetSelectionOwner (_dpy, XA_CLIPBOARD); + if (selectionOwner!=None) + { + Atom *supportedTargets, type; + uint8 *data; + int result; + unsigned long nitems, bytesLeft; + Atom actualType; + int actualFormat; + int bestTargetElect=0, bestTarget=0; + nlwarning("Selection owner is %u",selectionOwner); + + // Find supported methods + bool bres=prepareSelectionContent(XA_CLIPBOARD, XA_TARGETS, XA_NEL_SEL); + if (!bres) + { + nlwarning("Paste: Cannot ennumerate TARGETS"); + return false; + } + result=XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft,(unsigned char**) &supportedTargets); + if (result != Success) + { + return false; + } + if ( bytesLeft>0 ) + { + nlwarning("Paste: Supported TARGETS list too long."); // We hope we find what we need in the first packet. + } + // Elect best type + for (unsigned int i=0; i < nitems; i++) + { + nldebug(" - Type=%s", XGetAtomName(_dpy, supportedTargets[i])); + if (supportedTargets[i] == XA_STRING ) + { + if (bestTargetElect < 1) + { + bestTarget=XA_STRING; + bestTargetElect=1; + } + } + if (supportedTargets[i] == XA_UTF8_STRING ) + { + if (bestTargetElect < 2) + { + bestTarget=XA_STRING; + bestTargetElect=2; + } + } + } + XFree(supportedTargets); + if (!bestTargetElect) + { + nlwarning("Paste buffer is not a text buffer."); + return false; + } + + // Ask for selection lenght && copy to buffer + bres=prepareSelectionContent(XA_CLIPBOARD, bestTarget, XA_NEL_SEL); + if (!bres) + { + nlwarning ("Paste: cannot obtain data. Aborting."); + return false; + } + XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft,(unsigned char**) &data); + switch (bestTargetElect) + { + case 1: // XA_STRING + text=(const char*)data; + XFree(data); + return true; + break; + case 2: + text=ucstring::makeFromUtf8((const char*)data); + XFree(data); + return true; + default: + break; + } + nlwarning("Paste: buffer is not a text buffer."); + } + nlwarning("Paste: error !"); + return false; +} + + } // NLMISC #endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC) diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/unix_event_emitter.h --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.h Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.h Fri Oct 15 21:33:52 2010 +0200 @@ -65,6 +65,16 @@ */ bool processMessage(XEvent &event, CEventServer *server = NULL); + /** + * + */ + virtual bool copyTextToClipboard(const ucstring &text); + + /* + * + */ + virtual bool pasteTextFromClipboard(ucstring &text); + private: // Private internal server message @@ -88,6 +98,7 @@ }; void createIM(); + bool prepareSelectionContent (Atom selection, Atom requestedFormat, Atom propertyName); Display* _dpy; Window _win; @@ -97,6 +108,9 @@ bool _emulateRawMode; NL3D::IDriver* _driver; CUnixEventServer _InternalServer; + ucstring _CopiedString; + Atom _PrecomputedAtom[6]; + bool _SelectionOwned; }; diff -r 4ace6f8793f6 code/nel/src/3d/driver_user.cpp --- a/code/nel/src/3d/driver_user.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/3d/driver_user.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -1938,5 +1938,15 @@ return result; } +bool CDriverUser::copyTextToClipboard(const ucstring &text) +{ + return _Driver->copyTextToClipboard(text); +} + +bool CDriverUser::pasteTextFromClipboard(ucstring &text) +{ + return _Driver->pasteTextFromClipboard(text); +} + } // NL3D diff -r 4ace6f8793f6 code/nel/src/misc/event_emitter_multi.cpp --- a/code/nel/src/misc/event_emitter_multi.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/nel/src/misc/event_emitter_multi.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -16,7 +16,7 @@ #include "stdmisc.h" #include "nel/misc/event_emitter_multi.h" - +#include "nel/misc/system_utils.h" namespace NLMISC { @@ -99,7 +99,16 @@ return _Emitters[index].first; } - +bool CEventEmitterMulti::copyTextToClipboard(const ucstring &text) +{ + // Naush: wrapped to old API to avoid duplicate code + return CSystemUtils::copyTextToClipboard(text); +} +bool CEventEmitterMulti::pasteTextFromClipboard(ucstring &text) +{ + // Naush: wrapped to old API to avoid duplicate code + return CSystemUtils::pasteTextFromClipboard(text); +} } // NLMISC diff -r 4ace6f8793f6 code/ryzom/client/src/interface_v3/group_editbox.cpp --- a/code/ryzom/client/src/interface_v3/group_editbox.cpp Thu Oct 14 20:41:34 2010 +0200 +++ b/code/ryzom/client/src/interface_v3/group_editbox.cpp Fri Oct 15 21:33:52 2010 +0200 @@ -332,7 +332,7 @@ stopParentBlink(); // get the selection and copy it - if (CSystemUtils::copyTextToClipboard(getSelection())) + if (Driver->copyTextToClipboard(getSelection())) nlinfo ("Chat input was copied in the clipboard"); } @@ -351,8 +351,7 @@ makeTopWindow(); ucstring sString; - - if (CSystemUtils::pasteTextFromClipboard(sString)) + if (Driver->pasteTextFromClipboard(sString)) { sint length = (sint)sString.length();