diff options
author | Pierre Ossman <ossman@cendio.se> | 2019-07-01 11:37:50 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2019-07-01 11:37:50 +0200 |
commit | 5b8a629661c25f7c11c4b37825b0c80c633c2bf6 (patch) | |
tree | f80a2734a4fc32acb2d5d1cacf33577b3a1fe4c7 /unix | |
parent | 1d696c6bfa2ccfd6a3655602593dd3dff968aebe (diff) | |
parent | 0ff2655456097926a1720545830b1e34f072371f (diff) | |
download | tigervnc-5b8a629661c25f7c11c4b37825b0c80c633c2bf6.tar.gz tigervnc-5b8a629661c25f7c11c4b37825b0c80c633c2bf6.zip |
Merge branch 'exclipboard' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'unix')
-rw-r--r-- | unix/x0vncserver/XDesktop.cxx | 2 | ||||
-rw-r--r-- | unix/x0vncserver/XDesktop.h | 2 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/RFBGlue.cc | 34 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/RFBGlue.h | 9 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.cc | 54 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.h | 10 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.cc | 18 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.h | 6 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncSelection.c | 342 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncSelection.h | 6 |
10 files changed, 343 insertions, 140 deletions
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx index 564b2d51..8be9aa3d 100644 --- a/unix/x0vncserver/XDesktop.cxx +++ b/unix/x0vncserver/XDesktop.cxx @@ -406,7 +406,7 @@ void XDesktop::keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) { #endif } -void XDesktop::clientCutText(const char* str, int len) { +void XDesktop::clientCutText(const char* str) { } ScreenSet XDesktop::computeScreenLayout() diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h index 3e85aac3..840d4331 100644 --- a/unix/x0vncserver/XDesktop.h +++ b/unix/x0vncserver/XDesktop.h @@ -56,7 +56,7 @@ public: virtual void pointerEvent(const rfb::Point& pos, int buttonMask); KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym); virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down); - virtual void clientCutText(const char* str, int len); + virtual void clientCutText(const char* str); virtual unsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout); diff --git a/unix/xserver/hw/vnc/RFBGlue.cc b/unix/xserver/hw/vnc/RFBGlue.cc index 160177bd..f108fae4 100644 --- a/unix/xserver/hw/vnc/RFBGlue.cc +++ b/unix/xserver/hw/vnc/RFBGlue.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2015 Pierre Ossman for Cendio AB + * Copyright 2011-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -210,3 +210,35 @@ int vncIsTCPPortUsed(int port) } return 0; } + +char* vncConvertLF(const char* src, size_t bytes) +{ + try { + return convertLF(src, bytes); + } catch (...) { + return NULL; + } +} + +char* vncLatin1ToUTF8(const char* src, size_t bytes) +{ + try { + return latin1ToUTF8(src, bytes); + } catch (...) { + return NULL; + } +} + +char* vncUTF8ToLatin1(const char* src, size_t bytes) +{ + try { + return utf8ToLatin1(src, bytes); + } catch (...) { + return NULL; + } +} + +void vncStrFree(char* str) +{ + strFree(str); +} diff --git a/unix/xserver/hw/vnc/RFBGlue.h b/unix/xserver/hw/vnc/RFBGlue.h index a63afd07..112405b8 100644 --- a/unix/xserver/hw/vnc/RFBGlue.h +++ b/unix/xserver/hw/vnc/RFBGlue.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2015 Pierre Ossman for Cendio AB + * Copyright 2011-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,6 +49,13 @@ void vncListParams(int width, int nameWidth); int vncGetSocketPort(int fd); int vncIsTCPPortUsed(int port); +char* vncConvertLF(const char* src, size_t bytes); + +char* vncLatin1ToUTF8(const char* src, size_t bytes); +char* vncUTF8ToLatin1(const char* src, size_t bytes); + +void vncStrFree(char* str); + #ifdef __cplusplus } #endif diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index d8b3a4d4..4edffec7 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2017 Pierre Ossman for Cendio AB + * Copyright 2009-2019 Pierre Ossman for Cendio AB * Copyright 2014 Brian P. Hinz * * This is free software; you can redistribute it and/or modify @@ -182,25 +182,43 @@ void XserverDesktop::queryConnection(network::Socket* sock, queryConnectTimer.start(queryConnectTimeout * 1000); } -void XserverDesktop::bell() +void XserverDesktop::requestClipboard() { - server->bell(); + try { + server->requestClipboard(); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::requestClipboard: %s",e.str()); + } } -void XserverDesktop::setLEDState(unsigned int state) +void XserverDesktop::announceClipboard(bool available) { - server->setLEDState(state); + try { + server->announceClipboard(available); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::announceClipboard: %s",e.str()); + } } -void XserverDesktop::serverCutText(const char* str, int len) +void XserverDesktop::sendClipboardData(const char* data) { try { - server->serverCutText(str, len); + server->sendClipboardData(data); } catch (rdr::Exception& e) { - vlog.error("XserverDesktop::serverCutText: %s",e.str()); + vlog.error("XserverDesktop::sendClipboardData: %s",e.str()); } } +void XserverDesktop::bell() +{ + server->bell(); +} + +void XserverDesktop::setLEDState(unsigned int state) +{ + server->setLEDState(state); +} + void XserverDesktop::setDesktopName(const char* name) { try { @@ -436,11 +454,6 @@ void XserverDesktop::pointerEvent(const Point& pos, int buttonMask) vncPointerButtonAction(buttonMask); } -void XserverDesktop::clientCutText(const char* str, int len) -{ - vncClientCutText(str, len); -} - unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout) { @@ -462,6 +475,21 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, return result; } +void XserverDesktop::handleClipboardRequest() +{ + vncHandleClipboardRequest(); +} + +void XserverDesktop::handleClipboardAnnounce(bool available) +{ + vncHandleClipboardAnnounce(available); +} + +void XserverDesktop::handleClipboardData(const char* data_) +{ + vncHandleClipboardData(data_); +} + void XserverDesktop::grabRegion(const rfb::Region& region) { if (directFbptr) diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index 1253935f..6c670689 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2015 Pierre Ossman for Cendio AB + * Copyright 2009-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,9 +59,11 @@ public: void unblockUpdates(); void setFramebuffer(int w, int h, void* fbptr, int stride); void refreshScreenLayout(); + void requestClipboard(); + void announceClipboard(bool available); + void sendClipboardData(const char* data); void bell(); void setLEDState(unsigned int state); - void serverCutText(const char* str, int len); void setDesktopName(const char* name); void setCursor(int width, int height, int hotX, int hotY, const unsigned char *rgbaData); @@ -92,9 +94,11 @@ public: const char* userName); virtual void pointerEvent(const rfb::Point& pos, int buttonMask); virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); - virtual void clientCutText(const char* str, int len); virtual unsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout); + virtual void handleClipboardRequest(); + virtual void handleClipboardAnnounce(bool available); + virtual void handleClipboardData(const char* data); // rfb::PixelBuffer callbacks virtual void grabRegion(const rfb::Region& r); diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index 20072f48..6ab306b1 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2015 Pierre Ossman for Cendio AB + * Copyright 2011-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -285,10 +285,22 @@ void vncUpdateDesktopName(void) desktop[scr]->setDesktopName(desktopName); } -void vncServerCutText(const char *text, size_t len) +void vncRequestClipboard(void) { for (int scr = 0; scr < vncGetScreenCount(); scr++) - desktop[scr]->serverCutText(text, len); + desktop[scr]->requestClipboard(); +} + +void vncAnnounceClipboard(int available) +{ + for (int scr = 0; scr < vncGetScreenCount(); scr++) + desktop[scr]->announceClipboard(available); +} + +void vncSendClipboardData(const char* data) +{ + for (int scr = 0; scr < vncGetScreenCount(); scr++) + desktop[scr]->sendClipboardData(data); } int vncConnectClient(const char *addr) diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h index 5f97f96d..1fb87c19 100644 --- a/unix/xserver/hw/vnc/vncExtInit.h +++ b/unix/xserver/hw/vnc/vncExtInit.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2015 Pierre Ossman for Cendio AB + * Copyright 2011-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,7 +53,9 @@ int vncGetSendPrimary(void); void vncUpdateDesktopName(void); -void vncServerCutText(const char *text, size_t len); +void vncRequestClipboard(void); +void vncAnnounceClipboard(int available); +void vncSendClipboardData(const char* data); int vncConnectClient(const char *addr); diff --git a/unix/xserver/hw/vnc/vncSelection.c b/unix/xserver/hw/vnc/vncSelection.c index 4f3538d4..5191bb94 100644 --- a/unix/xserver/hw/vnc/vncSelection.c +++ b/unix/xserver/hw/vnc/vncSelection.c @@ -1,4 +1,4 @@ -/* Copyright 2016 Pierre Ossman for Cendio AB +/* Copyright 2016-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,15 +47,34 @@ static Atom xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT, xaUTF8_STRING; static WindowPtr pWindow; static Window wid; -static char* clientCutText; -static int clientCutTextLen; +static Bool probing; +static Atom activeSelection = None; + +struct VncDataTarget { + ClientPtr client; + Atom selection; + Atom target; + Atom property; + Window requestor; + CARD32 time; + struct VncDataTarget* next; +}; + +static struct VncDataTarget* vncDataTargetHead; static int vncCreateSelectionWindow(void); static int vncOwnSelection(Atom selection); +static int vncConvertSelection(ClientPtr client, Atom selection, + Atom target, Atom property, + Window requestor, CARD32 time, + const char* data); static int vncProcConvertSelection(ClientPtr client); +static void vncSelectionRequest(Atom selection, Atom target); static int vncProcSendEvent(ClientPtr client); static void vncSelectionCallback(CallbackListPtr *callbacks, void * data, void * args); +static void vncClientStateCallback(CallbackListPtr * l, + void * d, void * p); static int (*origProcConvertSelection)(ClientPtr); static int (*origProcSendEvent)(ClientPtr); @@ -80,34 +99,99 @@ void vncSelectionInit(void) if (!AddCallback(&SelectionCallback, vncSelectionCallback, 0)) FatalError("Add VNC SelectionCallback failed\n"); + if (!AddCallback(&ClientStateCallback, vncClientStateCallback, 0)) + FatalError("Add VNC ClientStateCallback failed\n"); } -void vncClientCutText(const char* str, int len) +void vncHandleClipboardRequest(void) { - int rc; - - if (clientCutText != NULL) - free(clientCutText); - - clientCutText = malloc(len); - if (clientCutText == NULL) { - LOG_ERROR("Could not allocate clipboard buffer"); - DeleteWindowFromAnySelections(pWindow); + if (activeSelection == None) { + LOG_DEBUG("Got request for local clipboard although no clipboard is active"); return; } - memcpy(clientCutText, str, len); - clientCutTextLen = len; + LOG_DEBUG("Got request for local clipboard, re-probing formats"); + + probing = FALSE; + vncSelectionRequest(activeSelection, xaTARGETS); +} + +void vncHandleClipboardAnnounce(int available) +{ + if (available) { + int rc; + + LOG_DEBUG("Remote clipboard announced, grabbing local ownership"); + + if (vncGetSetPrimary()) { + rc = vncOwnSelection(xaPRIMARY); + if (rc != Success) + LOG_ERROR("Could not set PRIMARY selection"); + } - if (vncGetSetPrimary()) { - rc = vncOwnSelection(xaPRIMARY); + rc = vncOwnSelection(xaCLIPBOARD); if (rc != Success) - LOG_ERROR("Could not set PRIMARY selection"); + LOG_ERROR("Could not set CLIPBOARD selection"); + } else { + struct VncDataTarget* next; + + if (pWindow == NULL) + return; + + LOG_DEBUG("Remote clipboard lost, removing local ownership"); + + DeleteWindowFromAnySelections(pWindow); + + /* Abort any pending transfer */ + while (vncDataTargetHead != NULL) { + xEvent event; + + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = vncDataTargetHead->time; + event.u.selectionNotify.requestor = vncDataTargetHead->requestor; + event.u.selectionNotify.selection = vncDataTargetHead->selection; + event.u.selectionNotify.target = vncDataTargetHead->target; + event.u.selectionNotify.property = None; + WriteEventsToClient(vncDataTargetHead->client, 1, &event); + + next = vncDataTargetHead->next; + free(vncDataTargetHead); + vncDataTargetHead = next; + } } +} - rc = vncOwnSelection(xaCLIPBOARD); - if (rc != Success) - LOG_ERROR("Could not set CLIPBOARD selection"); +void vncHandleClipboardData(const char* data) +{ + struct VncDataTarget* next; + + LOG_DEBUG("Got remote clipboard data, sending to X11 clients"); + + while (vncDataTargetHead != NULL) { + int rc; + xEvent event; + + rc = vncConvertSelection(vncDataTargetHead->client, + vncDataTargetHead->selection, + vncDataTargetHead->target, + vncDataTargetHead->property, + vncDataTargetHead->requestor, + vncDataTargetHead->time, + data); + if (rc != Success) { + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = vncDataTargetHead->time; + event.u.selectionNotify.requestor = vncDataTargetHead->requestor; + event.u.selectionNotify.selection = vncDataTargetHead->selection; + event.u.selectionNotify.target = vncDataTargetHead->target; + event.u.selectionNotify.property = None; + WriteEventsToClient(vncDataTargetHead->client, 1, &event); + } + + next = vncDataTargetHead->next; + free(vncDataTargetHead); + vncDataTargetHead = next; + } } static int vncCreateSelectionWindow(void) @@ -195,7 +279,8 @@ static int vncOwnSelection(Atom selection) static int vncConvertSelection(ClientPtr client, Atom selection, Atom target, Atom property, - Window requestor, CARD32 time) + Window requestor, CARD32 time, + const char* data) { Selection *pSel; WindowPtr pWin; @@ -205,8 +290,13 @@ static int vncConvertSelection(ClientPtr client, Atom selection, xEvent event; - LOG_DEBUG("Selection request for %s (type %s)", - NameForAtom(selection), NameForAtom(target)); + if (data == NULL) { + LOG_DEBUG("Selection request for %s (type %s)", + NameForAtom(selection), NameForAtom(target)); + } else { + LOG_DEBUG("Sending data for selection request for %s (type %s)", + NameForAtom(selection), NameForAtom(target)); + } rc = dixLookupSelection(&pSel, selection, client, DixGetAttrAccess); if (rc != Success) @@ -243,51 +333,59 @@ static int vncConvertSelection(ClientPtr client, Atom selection, TRUE); if (rc != Success) return rc; - } else if ((target == xaSTRING) || (target == xaTEXT)) { - rc = dixChangeWindowProperty(serverClient, pWin, realProperty, - XA_STRING, 8, PropModeReplace, - clientCutTextLen, clientCutText, - TRUE); - if (rc != Success) - return rc; - } else if (target == xaUTF8_STRING) { - unsigned char* buffer; - unsigned char* out; - size_t len; - - const unsigned char* in; - size_t in_len; - - buffer = malloc(clientCutTextLen*2); - if (buffer == NULL) - return BadAlloc; - - out = buffer; - len = 0; - in = clientCutText; - in_len = clientCutTextLen; - while (in_len > 0) { - if (*in & 0x80) { - *out++ = 0xc0 | (*in >> 6); - *out++ = 0x80 | (*in & 0x3f); - len += 2; - in++; - in_len--; + } else { + if (data == NULL) { + struct VncDataTarget* vdt; + + if ((target != xaSTRING) && (target != xaTEXT) && + (target != xaUTF8_STRING)) + return BadMatch; + + vdt = calloc(1, sizeof(struct VncDataTarget)); + if (vdt == NULL) + return BadAlloc; + + vdt->client = client; + vdt->selection = selection; + vdt->target = target; + vdt->property = property; + vdt->requestor = requestor; + vdt->time = time; + + vdt->next = vncDataTargetHead; + vncDataTargetHead = vdt; + + LOG_DEBUG("Requesting clipboard data from client"); + + vncRequestClipboard(); + + return Success; + } else { + if ((target == xaSTRING) || (target == xaTEXT)) { + char* latin1; + + latin1 = vncUTF8ToLatin1(data, (size_t)-1); + if (latin1 == NULL) + return BadAlloc; + + rc = dixChangeWindowProperty(serverClient, pWin, realProperty, + XA_STRING, 8, PropModeReplace, + strlen(latin1), latin1, TRUE); + + vncStrFree(latin1); + + if (rc != Success) + return rc; + } else if (target == xaUTF8_STRING) { + rc = dixChangeWindowProperty(serverClient, pWin, realProperty, + xaUTF8_STRING, 8, PropModeReplace, + strlen(data), data, TRUE); + if (rc != Success) + return rc; } else { - *out++ = *in++; - len++; - in_len--; + return BadMatch; } } - - rc = dixChangeWindowProperty(serverClient, pWin, realProperty, - xaUTF8_STRING, 8, PropModeReplace, - len, buffer, TRUE); - free(buffer); - if (rc != Success) - return rc; - } else { - return BadMatch; } event.u.u.type = SelectionNotify; @@ -326,7 +424,7 @@ static int vncProcConvertSelection(ClientPtr client) pSel->window == wid) { rc = vncConvertSelection(client, stuff->selection, stuff->target, stuff->property, - stuff->requestor, stuff->time); + stuff->requestor, stuff->time, NULL); if (rc != Success) { xEvent event; @@ -410,69 +508,61 @@ static void vncHandleSelection(Atom selection, Atom target, if (prop->type != XA_ATOM) return; - if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size)) - vncSelectionRequest(selection, xaSTRING); - else if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size)) - vncSelectionRequest(selection, xaUTF8_STRING); + if (probing) { + if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size) || + vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size)) { + LOG_DEBUG("Compatible format found, notifying clients"); + activeSelection = selection; + vncAnnounceClipboard(TRUE); + } + } else { + if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size)) + vncSelectionRequest(selection, xaUTF8_STRING); + else if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size)) + vncSelectionRequest(selection, xaSTRING); + } } else if (target == xaSTRING) { + char* filtered; + char* utf8; + if (prop->format != 8) return; if (prop->type != xaSTRING) return; - vncServerCutText(prop->data, prop->size); - } else if (target == xaUTF8_STRING) { - unsigned char* buffer; - unsigned char* out; - size_t len; + filtered = vncConvertLF(prop->data, prop->size); + if (filtered == NULL) + return; + + utf8 = vncLatin1ToUTF8(filtered, (size_t)-1); + vncStrFree(filtered); + if (utf8 == NULL) + return; + + LOG_DEBUG("Sending clipboard to clients (%d bytes)", + (int)strlen(utf8)); - const unsigned char* in; - size_t in_len; + vncSendClipboardData(utf8); + + vncStrFree(utf8); + } else if (target == xaUTF8_STRING) { + char *filtered; if (prop->format != 8) return; if (prop->type != xaUTF8_STRING) return; - buffer = malloc(prop->size); - if (buffer == NULL) + filtered = vncConvertLF(prop->data, prop->size); + if (filtered == NULL) return; - out = buffer; - len = 0; - in = prop->data; - in_len = prop->size; - while (in_len > 0) { - if ((*in & 0x80) == 0x00) { - *out++ = *in++; - len++; - in_len--; - } else if ((*in & 0xe0) == 0xc0) { - unsigned ucs; - ucs = (*in++ & 0x1f) << 6; - in_len--; - if (in_len > 0) { - ucs |= (*in++ & 0x3f); - in_len--; - } - if (ucs <= 0xff) - *out++ = ucs; - else - *out++ = '?'; - len++; - } else { - *out++ = '?'; - len++; - do { - in++; - in_len--; - } while ((in_len > 0) && ((*in & 0xc0) == 0x80)); - } - } + LOG_DEBUG("Sending clipboard to clients (%d bytes)", + (int)strlen(filtered)); - vncServerCutText((const char*)buffer, len); + vncSendClipboardData(filtered); - free(buffer); + vncStrFree(filtered); } } @@ -504,6 +594,12 @@ static void vncSelectionCallback(CallbackListPtr *callbacks, { SelectionInfoRec *info = (SelectionInfoRec *) args; + if (info->selection->selection == activeSelection) { + LOG_DEBUG("Local clipboard lost, notifying clients"); + activeSelection = None; + vncAnnounceClipboard(FALSE); + } + if (info->kind != SelectionSetOwner) return; if (info->client == serverClient) @@ -520,5 +616,25 @@ static void vncSelectionCallback(CallbackListPtr *callbacks, !vncGetSendPrimary()) return; + LOG_DEBUG("Got clipboard notification, probing for formats"); + + probing = TRUE; vncSelectionRequest(info->selection->selection, xaTARGETS); } + +static void vncClientStateCallback(CallbackListPtr * l, + void * d, void * p) +{ + ClientPtr client = ((NewClientInfoRec*)p)->client; + if (client->clientState == ClientStateGone) { + struct VncDataTarget** nextPtr = &vncDataTargetHead; + for (struct VncDataTarget* cur = vncDataTargetHead; cur; cur = *nextPtr) { + if (cur->client == client) { + *nextPtr = cur->next; + free(cur); + continue; + } + nextPtr = &cur->next; + } + } +} diff --git a/unix/xserver/hw/vnc/vncSelection.h b/unix/xserver/hw/vnc/vncSelection.h index 969f8958..ea52bf23 100644 --- a/unix/xserver/hw/vnc/vncSelection.h +++ b/unix/xserver/hw/vnc/vncSelection.h @@ -1,4 +1,4 @@ -/* Copyright 2016 Pierre Ossman for Cendio AB +/* Copyright 2016-2019 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,9 @@ extern "C" { void vncSelectionInit(void); -void vncClientCutText(const char* str, int len); +void vncHandleClipboardRequest(void); +void vncHandleClipboardAnnounce(int available); +void vncHandleClipboardData(const char* data); #ifdef __cplusplus } |