Browse Source

Add clipboard support

pull/1639/head
Cameron Leger 6 years ago
parent
commit
49ccf9a34a
1 changed files with 184 additions and 5 deletions
  1. +184
    -5
      dep/lglw/lglw_linux.c

+ 184
- 5
dep/lglw/lglw_linux.c View File

@@ -130,6 +130,11 @@ typedef struct lglw_int_s {
lglw_timer_fxn_t cbk;
} timer;

struct {
uint32_t numChars;
char *data;
} clipboard;

struct {
lglw_dropfiles_fxn_t cbk;
} dropfiles;
@@ -525,6 +530,41 @@ static void loc_eventProc(void *_xevent) {
break;
}
break;

case SelectionClear:
printf("vstgltest<lglw_linux>: xev SelectionClear\n");
lglw->clipboard.numChars = 0;
free(lglw->clipboard.data);
break;

case SelectionRequest:
printf("vstgltest<lglw_linux>: xev SelectionRequest\n");
XSelectionRequestEvent *cbReq = (XSelectionRequestEvent*)xev;
XSelectionEvent cbRes;

Atom utf8 = XInternAtom(lglw->xdsp, "UTF8_STRING", False);

cbRes.type = SelectionNotify;
cbRes.requestor = cbReq->requestor;
cbRes.selection = cbReq->selection;
cbRes.target = cbReq->target;
cbRes.time = cbReq->time;

if(cbReq->target == utf8)
{
XChangeProperty(lglw->xdsp, cbReq->requestor, cbReq->property, utf8, 8/*format*/, PropModeReplace,
(unsigned char *)lglw->clipboard.data, lglw->clipboard.numChars);

cbRes.property = cbReq->property;
}
else
{
cbRes.property = None;
}

XSendEvent(lglw->xdsp, cbReq->requestor, True, NoEventMask, (XEvent *)&cbRes);

break;
}
}
}
@@ -1569,15 +1609,44 @@ void lglw_clipboard_text_set(lglw_t _lglw, const uint32_t _numChars, const char
LGLW(_lglw);
(void)_numChars;

// (todo) implement me

if(NULL != _text)
{
(void)lglw;
if(NULL != _lglw)
{
if(0 != lglw->win.xwnd)
{
uint32_t numChars = (0u == _numChars) ? ((uint32_t)strlen(_text)+1u) : _numChars;

if(numChars > 0u)
{
lglw->clipboard.numChars = numChars;
lglw->clipboard.data = malloc(numChars+1);

uint32_t i;
for(i = 0u; i < numChars; i++)
{
lglw->clipboard.data[i] = _text[i];
}
lglw->clipboard.data[numChars - 1] = 0;

printf("xxx lglw_clipboard_text_set(%i): %s\n", lglw->clipboard.numChars, lglw->clipboard.data);

Atom clipboard = XInternAtom(lglw->xdsp, "CLIPBOARD", False);
XSetSelectionOwner(lglw->xdsp, clipboard, lglw->win.xwnd, CurrentTime);
XSync(lglw->xdsp, False);
}
}
}
}
}


// ---------------------------------------------------------------------------- loc_is_clipboard_event
static Bool loc_is_clipboard_event(Display *_display, XEvent *_xevent, XPointer _xarg) {
return _xevent->type == SelectionNotify;
}


// ---------------------------------------------------------------------------- lglw_clipboard_text_get
void lglw_clipboard_text_get(lglw_t _lglw, uint32_t _maxChars, uint32_t *_retNumChars, char *_retText) {
LGLW(_lglw);
@@ -1592,8 +1661,118 @@ void lglw_clipboard_text_get(lglw_t _lglw, uint32_t _maxChars, uint32_t *_retNum
{
if(NULL != _lglw)
{
// (todo) implement me
(void)lglw;
if(0 != lglw->win.xwnd)
{
Window owner;
XEvent xev;
XSelectionEvent *cbReq;
Atom clipboard = XInternAtom(lglw->xdsp, "CLIPBOARD", False);
Atom utf8 = XInternAtom(lglw->xdsp, "UTF8_STRING", False);
Atom target = XInternAtom(lglw->xdsp, "_clipboard_result", False);

owner = XGetSelectionOwner(lglw->xdsp, clipboard);
if(owner == None)
{
printf("xxx lglw_clipboard_text_get: No Window can provide a clipboard result\n");
return;
}

if(owner == lglw->win.xwnd)
{
printf("xxx lglw_clipboard_text_get: We are the owner of the clipboard, skip X interactions\n");

uint32_t i = 0u;
for(; i < _maxChars; i++)
{
_retText[i] = lglw->clipboard.data[i];
if(0 == _retText[i])
break;
}
_retText[_maxChars - 1u] = 0;

if(NULL != _retNumChars)
*_retNumChars = i;

printf("xxx lglw_clipboard_text_get: (result on next line)\n%s\n", _retText);
return;
}

XConvertSelection(lglw->xdsp, clipboard, utf8, target, lglw->win.xwnd, CurrentTime);
XIfEvent(lglw->xdsp, &xev, &loc_is_clipboard_event, None);

cbReq = (XSelectionEvent*)&xev;
if(None == cbReq->property)
{
printf("xxx lglw_clipboard_text_get: Clipboard was not converted to UTF-8 string\n");
return;
}

Atom returnType;
int returnFormat;
unsigned long size, returnSize, bytesLeft;
unsigned char *propertyValue = NULL;

XGetWindowProperty(lglw->xdsp, lglw->win.xwnd, target,
0/*offset*/,
0/*length*/,
False/*delete*/,
AnyPropertyType/*req_type*/,
&returnType/*actual_type_return*/,
&returnFormat/*actual_format_return*/,
&returnSize/*nitems_return*/,
&size/*bytes_after_return*/,
&propertyValue/*prop_return*/);
XFree(propertyValue);

if(utf8 != returnType)
{
printf("xxx lglw_clipboard_text_get: Clipboard result is not a UTF-8 string\n");
return;
}

if(8u != returnFormat)
{
printf("xxx lglw_clipboard_text_get: Clipboard format is not a char array\n");
return;
}

if(_maxChars < size)
size = _maxChars;
size = 1 + ((size - 1) / 4);

// TODO: Even with the largest current use-case, multiple calls aren't necessary. do it anyway just in case
XGetWindowProperty(lglw->xdsp, lglw->win.xwnd, target,
0/*offset*/,
size/*length*/,
True/*delete*/,
AnyPropertyType/*req_type*/,
&returnType/*actual_type_return*/,
&returnFormat/*actual_format_return*/,
&returnSize/*nitems_return*/,
&bytesLeft/*bytes_after_return*/,
&propertyValue/*prop_return*/);

if(returnSize == 0)
{
printf("xxx lglw_clipboard_text_get: No Clipboard result after final request\n");
return;
}

uint32_t i = 0u;
for(; i < _maxChars; i++)
{
_retText[i] = propertyValue[i];
if(0 == _retText[i])
break;
}
_retText[_maxChars - 1u] = 0;

if(NULL != _retNumChars)
*_retNumChars = i;

printf("xxx lglw_clipboard_text_get: (result on next line)\n%s\n", _retText);
XFree(propertyValue);
}
}
}
}

Loading…
Cancel
Save