Changed: #1038 Implement copy/paste for Linux
This commit is contained in:
parent
298dfc084e
commit
d56d0ebc1a
3 changed files with 164 additions and 176 deletions
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "types_nl.h"
|
#include "types_nl.h"
|
||||||
#include "class_id.h"
|
#include "class_id.h"
|
||||||
|
#include "ucstring.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ protected:
|
||||||
const CClassId EventKeyDownId (0x3c2643da, 0x43f802a1);
|
const CClassId EventKeyDownId (0x3c2643da, 0x43f802a1);
|
||||||
const CClassId EventKeyUpId (0x1e62e85, 0x68a35d46);
|
const CClassId EventKeyUpId (0x1e62e85, 0x68a35d46);
|
||||||
const CClassId EventCharId (0x552255fe, 0x75a2373f);
|
const CClassId EventCharId (0x552255fe, 0x75a2373f);
|
||||||
|
const CClassId EventStringId (0x49b5af8f, 0x7f52cd26);
|
||||||
|
|
||||||
// Window events
|
// Window events
|
||||||
const CClassId EventActivateId (0x7da66b0a, 0x1ef74519);
|
const CClassId EventActivateId (0x7da66b0a, 0x1ef74519);
|
||||||
|
@ -327,6 +329,20 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CEventString
|
||||||
|
*/
|
||||||
|
class CEventString : public CEventKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEventString (const ucstring &str, IEventEmitter* emitter) : CEventKey (noKeyButton, emitter, EventStringId)
|
||||||
|
{
|
||||||
|
String = str;
|
||||||
|
}
|
||||||
|
ucstring String;
|
||||||
|
|
||||||
|
virtual CEvent *clone() const {return new CEventString(*this);}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CEventMouse.
|
* CEventMouse.
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
|
|
||||||
typedef bool (*x11Proc)(NL3D::IDriver *drv, XEvent *e);
|
typedef bool (*x11Proc)(NL3D::IDriver *drv, XEvent *e);
|
||||||
|
|
||||||
|
static Atom XA_CLIPBOARD = 0;
|
||||||
|
static Atom XA_UTF8_STRING = 0;
|
||||||
|
static Atom XA_TARGETS = 0;
|
||||||
|
static Atom XA_NEL_SEL = 0;
|
||||||
|
|
||||||
namespace NLMISC {
|
namespace NLMISC {
|
||||||
|
|
||||||
CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _emulateRawMode(false), _driver(NULL)
|
CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _emulateRawMode(false), _driver(NULL)
|
||||||
|
@ -51,18 +56,12 @@ void CUnixEventEmitter::init(Display *dpy, Window win, NL3D::IDriver *driver)
|
||||||
_driver = driver;
|
_driver = driver;
|
||||||
|
|
||||||
XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
|
XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
|
||||||
_PrecomputedAtom[0] = XInternAtom(dpy, "CLIPBOARD", False);
|
|
||||||
#define XA_CLIPBOARD _PrecomputedAtom[0]
|
// define Atoms used by clipboard
|
||||||
_PrecomputedAtom[1] = XInternAtom(dpy, "UTF8_STRING", False);
|
XA_CLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False);
|
||||||
#define XA_UTF8_STRING _PrecomputedAtom[1]
|
XA_UTF8_STRING = XInternAtom(dpy, "UTF8_STRING", False);
|
||||||
_PrecomputedAtom[2] = XInternAtom(dpy, "TARGETS", False);
|
XA_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
||||||
#define XA_TARGETS _PrecomputedAtom[2]
|
XA_NEL_SEL = XInternAtom(dpy, "NeL_SEL", False);
|
||||||
_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
|
TODO: implements all useful events processing
|
||||||
|
@ -568,10 +567,23 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
|
||||||
#ifdef X_HAVE_UTF8_STRING
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
ucstring ucstr;
|
ucstring ucstr;
|
||||||
ucstr.fromUtf8(Text);
|
ucstr.fromUtf8(Text);
|
||||||
server->postEvent (new CEventChar (ucstr[0], noKeyButton, this));
|
|
||||||
|
CEventChar *charEvent = new CEventChar (ucstr[0], noKeyButton, this);
|
||||||
|
|
||||||
|
// raw if not processed by IME
|
||||||
|
charEvent->setRaw(keyCode != 0);
|
||||||
|
|
||||||
|
server->postEvent (charEvent);
|
||||||
#else
|
#else
|
||||||
for (int i = 0; i < c; i++)
|
for (int i = 0; i < c; i++)
|
||||||
server->postEvent (new CEventChar ((ucchar)(unsigned char)Text[i], noKeyButton, this));
|
{
|
||||||
|
CEventChar *charEvent = new CEventChar ((ucchar)(unsigned char)Text[i], noKeyButton, this);
|
||||||
|
|
||||||
|
// raw if not processed by IME
|
||||||
|
charEvent->setRaw(keyCode != 0);
|
||||||
|
|
||||||
|
server->postEvent (charEvent);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -612,12 +624,10 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
|
||||||
}
|
}
|
||||||
if (req.target == XA_TARGETS)
|
if (req.target == XA_TARGETS)
|
||||||
{
|
{
|
||||||
nlwarning("Client is asking for TARGETS");
|
|
||||||
|
|
||||||
Atom targets[] =
|
Atom targets[] =
|
||||||
{
|
{
|
||||||
XA_TARGETS,
|
XA_TARGETS,
|
||||||
XA_TEXT,
|
XA_STRING,
|
||||||
XA_UTF8_STRING
|
XA_UTF8_STRING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -625,23 +635,21 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
|
||||||
|
|
||||||
XChangeProperty(req.display, req.requestor, req.property, XA_ATOM, 32, PropModeReplace, (unsigned char *)targets, 3 /* number of element */);
|
XChangeProperty(req.display, req.requestor, req.property, XA_ATOM, 32, PropModeReplace, (unsigned char *)targets, 3 /* number of element */);
|
||||||
}
|
}
|
||||||
else if (req.target == XA_TEXT || req.target == XA_STRING )
|
else if (req.target == XA_STRING)
|
||||||
{
|
{
|
||||||
nlwarning("client want TEXT");
|
|
||||||
respond.xselection.property = req.property;
|
respond.xselection.property = req.property;
|
||||||
std::string str = _CopiedString.toString();
|
std::string str = _CopiedString.toString();
|
||||||
XChangeProperty(req.display, req.requestor, req.property, XA_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), str.length());
|
XChangeProperty(req.display, req.requestor, req.property, XA_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), str.length());
|
||||||
}
|
}
|
||||||
else if (req.target == XA_UTF8_STRING)
|
else if (req.target == XA_UTF8_STRING)
|
||||||
{
|
{
|
||||||
nlwarning("Client want UTF8 STRING");
|
respond.xselection.property = req.property;
|
||||||
respond.xselection.property=req.property;
|
|
||||||
std::string str = _CopiedString.toUtf8();
|
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()));
|
XChangeProperty(req.display, req.requestor, respond.xselection.property, XA_UTF8_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), str.length());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nlwarning("Target doesn't want a string %u", (uint)req.target); // Note: Calling XGetAtomName with arbitrary value crash the client, maybe req.target have been sanitized by X11 server
|
// Note: Calling XGetAtomName with arbitrary value crash the client, maybe req.target have been sanitized by X11 server
|
||||||
respond.xselection.property = None;
|
respond.xselection.property = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,156 +658,38 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SelectionClear:
|
case SelectionClear:
|
||||||
nlwarning("SelectionClear:");
|
|
||||||
_SelectionOwned = false;
|
_SelectionOwned = false;
|
||||||
_CopiedString = "";
|
_CopiedString = "";
|
||||||
break;
|
break;
|
||||||
case FocusIn:
|
case SelectionNotify:
|
||||||
// keyboard focus
|
{
|
||||||
if (_ic) XSetICFocus(_ic);
|
Atom target = event.xselection.target;
|
||||||
break;
|
|
||||||
case FocusOut:
|
Atom actualType = 0;
|
||||||
// keyboard focus
|
int actualFormat = 0;
|
||||||
if (_ic) XUnsetICFocus(_ic);
|
unsigned long nitems = 0, bytesLeft = 0;
|
||||||
break;
|
|
||||||
case KeymapNotify:
|
// some applications are sending ATOM and other TARGETS
|
||||||
break;
|
if (target == XA_TARGETS || target == XA_ATOM)
|
||||||
case MappingNotify:
|
{
|
||||||
// update keymap
|
Atom *supportedTargets = NULL;
|
||||||
XRefreshKeyboardMapping((XMappingEvent *)&event);
|
|
||||||
break;
|
// list NeL selection properties
|
||||||
case DestroyNotify:
|
if (XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft, (unsigned char**)&supportedTargets) != Success)
|
||||||
// XIM server has crashed
|
|
||||||
createIM();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// nlinfo("UnknownEvent");
|
|
||||||
// XtDispatchEvent(&event);
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (bytesLeft > 0)
|
||||||
|
{
|
||||||
|
nlwarning("Paste: Supported TARGETS list too long.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
Atom bestTarget = 0;
|
||||||
}
|
sint bestTargetElect = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
uint8 *data;
|
|
||||||
sint result;
|
|
||||||
unsigned long nitems, bytesLeft;
|
|
||||||
Atom actualType;
|
|
||||||
sint actualFormat;
|
|
||||||
sint bestTargetElect=0, bestTarget=0;
|
|
||||||
|
|
||||||
nlwarning("Selection owner is %u", (uint)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
|
// Elect best type
|
||||||
for (uint i=0; i < nitems; i++)
|
for (uint i=0; i < nitems; i++)
|
||||||
{
|
{
|
||||||
nldebug(" - Type=%s", XGetAtomName(_dpy, supportedTargets[i]));
|
// nlwarning(" - Type=%s (%u)", XGetAtomName(_dpy, supportedTargets[i]), (uint)supportedTargets[i]);
|
||||||
|
|
||||||
if (supportedTargets[i] == XA_STRING )
|
|
||||||
{
|
|
||||||
if (bestTargetElect < 1)
|
|
||||||
{
|
|
||||||
bestTarget = XA_STRING;
|
|
||||||
bestTargetElect = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportedTargets[i] == XA_UTF8_STRING )
|
if (supportedTargets[i] == XA_UTF8_STRING )
|
||||||
{
|
{
|
||||||
if (bestTargetElect < 2)
|
if (bestTargetElect < 2)
|
||||||
|
@ -808,6 +698,14 @@ bool CUnixEventEmitter::pasteTextFromClipboard(ucstring &text)
|
||||||
bestTargetElect = 2;
|
bestTargetElect = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (supportedTargets[i] == XA_STRING )
|
||||||
|
{
|
||||||
|
if (bestTargetElect < 1)
|
||||||
|
{
|
||||||
|
bestTarget = XA_STRING;
|
||||||
|
bestTargetElect = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(supportedTargets);
|
XFree(supportedTargets);
|
||||||
|
@ -818,42 +716,118 @@ bool CUnixEventEmitter::pasteTextFromClipboard(ucstring &text)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask for selection lenght && copy to buffer
|
// request string conversion
|
||||||
bres = prepareSelectionContent(XA_CLIPBOARD, bestTarget, XA_NEL_SEL);
|
XConvertSelection(_dpy, XA_CLIPBOARD, bestTarget, XA_NEL_SEL, _win, CurrentTime);
|
||||||
|
|
||||||
if (!bres)
|
|
||||||
{
|
|
||||||
nlwarning ("Paste: cannot obtain data. Aborting.");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
else if (target == XA_UTF8_STRING || target == XA_STRING)
|
||||||
|
{
|
||||||
|
uint8 *data = NULL;
|
||||||
|
|
||||||
XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft,(unsigned char**) &data);
|
// get selection
|
||||||
|
if (XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft, (unsigned char**)&data) != Success)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ucstring text;
|
||||||
std::string tmpData = (const char*)data;
|
std::string tmpData = (const char*)data;
|
||||||
XFree(data);
|
XFree(data);
|
||||||
|
|
||||||
switch (bestTargetElect)
|
// convert buffer to ucstring
|
||||||
|
if (target == XA_UTF8_STRING)
|
||||||
{
|
{
|
||||||
case 1: // XA_STRING
|
|
||||||
text = tmpData;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case 2: // XA_UTF8_STRING
|
|
||||||
text = ucstring::makeFromUtf8(tmpData);
|
text = ucstring::makeFromUtf8(tmpData);
|
||||||
return true;
|
}
|
||||||
|
else if (target == XA_STRING)
|
||||||
|
{
|
||||||
|
text = tmpData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Unknow format %u", (uint)target);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sent string event to event server
|
||||||
|
server->postEvent (new CEventString (text, this));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Unknow target %u", (uint)target);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FocusIn:
|
||||||
nlwarning("Paste: buffer is not a text buffer.");
|
// keyboard focus
|
||||||
|
server->postEvent (new CEventSetFocus (true, this));
|
||||||
|
if (_ic) XSetICFocus(_ic);
|
||||||
|
break;
|
||||||
|
case FocusOut:
|
||||||
|
// keyboard focus
|
||||||
|
server->postEvent (new CEventSetFocus (false, this));
|
||||||
|
if (_ic) XUnsetICFocus(_ic);
|
||||||
|
break;
|
||||||
|
case KeymapNotify:
|
||||||
|
break;
|
||||||
|
case MappingNotify:
|
||||||
|
// update keymap
|
||||||
|
XRefreshKeyboardMapping((XMappingEvent *)&event);
|
||||||
|
break;
|
||||||
|
case DestroyNotify:
|
||||||
|
// XIM server has crashed
|
||||||
|
createIM();
|
||||||
|
break;
|
||||||
|
case ClientMessage:
|
||||||
|
if ((xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW))
|
||||||
|
{
|
||||||
|
server->postEvent (new CEventDestroyWindow (this));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// nlinfo("UnknownEvent");
|
||||||
|
// XtDispatchEvent(&event);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nlwarning("Paste: error !");
|
return true;
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CUnixEventEmitter::copyTextToClipboard(const ucstring &text)
|
||||||
|
{
|
||||||
|
_CopiedString = text;
|
||||||
|
|
||||||
|
// NeL window is the owner of clipboard
|
||||||
|
XSetSelectionOwner(_dpy, XA_CLIPBOARD, _win, CurrentTime);
|
||||||
|
|
||||||
|
// check we are owning the clipboard
|
||||||
|
if (XGetSelectionOwner(_dpy, XA_CLIPBOARD) != _win)
|
||||||
|
{
|
||||||
|
nlwarning("Can't aquire selection");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SelectionOwned = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUnixEventEmitter::pasteTextFromClipboard(ucstring &text)
|
||||||
|
{
|
||||||
|
// check if we own the selection
|
||||||
|
if (_SelectionOwned)
|
||||||
|
{
|
||||||
|
text = _CopiedString;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if there is a data in clipboard
|
||||||
|
if (XGetSelectionOwner(_dpy, XA_CLIPBOARD) == None)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// request supported methods
|
||||||
|
XConvertSelection(_dpy, XA_CLIPBOARD, XA_TARGETS, XA_NEL_SEL, _win, CurrentTime);
|
||||||
|
|
||||||
|
// don't return result now
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // NLMISC
|
} // NLMISC
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void createIM();
|
void createIM();
|
||||||
bool prepareSelectionContent (Atom selection, Atom requestedFormat, Atom propertyName);
|
|
||||||
|
|
||||||
Display* _dpy;
|
Display* _dpy;
|
||||||
Window _win;
|
Window _win;
|
||||||
|
@ -109,7 +108,6 @@ private:
|
||||||
NL3D::IDriver* _driver;
|
NL3D::IDriver* _driver;
|
||||||
CUnixEventServer _InternalServer;
|
CUnixEventServer _InternalServer;
|
||||||
ucstring _CopiedString;
|
ucstring _CopiedString;
|
||||||
Atom _PrecomputedAtom[6];
|
|
||||||
bool _SelectionOwned;
|
bool _SelectionOwned;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue