aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2016-01-12 18:40:23 +0100
committerPierre Ossman <ossman@cendio.se>2016-02-05 10:34:36 +0100
commit6f6a6c0d90c5ad9ceeff8d24299cdfc215955947 (patch)
tree23133df4a14b04106ee70a329f139daaf6e4af80
parentc62e70c5b34de478127a130384b8958ccf232504 (diff)
downloadtigervnc-6f6a6c0d90c5ad9ceeff8d24299cdfc215955947.tar.gz
tigervnc-6f6a6c0d90c5ad9ceeff8d24299cdfc215955947.zip
Move server to client clipboard out of vncconfig
Also handle clipboard transactions from the server to the client directly in the server without the help of vncconfig.
-rw-r--r--unix/xserver/hw/vnc/Xvnc.man17
-rw-r--r--unix/xserver/hw/vnc/vncExt.c74
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.cc8
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.h2
-rw-r--r--unix/xserver/hw/vnc/vncSelection.c114
5 files changed, 132 insertions, 83 deletions
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
index 4a833157..e86bf87f 100644
--- a/unix/xserver/hw/vnc/Xvnc.man
+++ b/unix/xserver/hw/vnc/Xvnc.man
@@ -126,14 +126,8 @@ screen is updated. Otherwise the delay is from the first update. Default
is off.
.
.TP
-.B \-SendCutText
-Send clipboard changes to clients (default is on). Note that you must also run
-\fBvncconfig\fP(1) to get the clipboard to work.
-.
-.TP
.B \-AcceptCutText
-Accept clipboard updates from clients (default is on). Note that you must also
-run \fBvncconfig\fP(1) to get the clipboard to work.
+Accept clipboard updates from clients (default is on).
.
.TP
.B \-MaxCutText \fIbytes\fP
@@ -141,6 +135,15 @@ The maximum size of a clipboard update that will be accepted from a client.
Default is \fB262144\fP.
.
.TP
+.B \-SendCutText
+Send clipboard changes to clients (default is on).
+.
+.TP
+.B \-SendPrimary
+Send the primary selection and cut buffer to the server as well as the
+clipboard selection. Default is on.
+.
+.TP
.B \-AcceptPointerEvents
Accept pointer press and release events from clients (default is on).
.
diff --git a/unix/xserver/hw/vnc/vncExt.c b/unix/xserver/hw/vnc/vncExt.c
index e07ed865..334c8889 100644
--- a/unix/xserver/hw/vnc/vncExt.c
+++ b/unix/xserver/hw/vnc/vncExt.c
@@ -27,7 +27,6 @@
#include "dixstruct.h"
#include "extnsionst.h"
#include "scrnintstr.h"
-#include "selection.h"
#define _VNCEXT_SERVER_
#define _VNCEXT_PROTO_
@@ -44,9 +43,6 @@ static void vncResetProc(ExtensionEntry* extEntry);
static void vncClientStateChange(CallbackListPtr*, void *, void *);
-static void vncSelectionCallback(CallbackListPtr *callbacks,
- void * data, void * args);
-
static int vncErrorBase = 0;
static int vncEventBase = 0;
@@ -80,10 +76,6 @@ int vncAddExtension(void)
FatalError("Add ClientStateCallback failed\n");
}
- if (!AddCallback(&SelectionCallback, vncSelectionCallback, 0)) {
- FatalError("Add SelectionCallback failed\n");
- }
-
return 0;
}
@@ -354,32 +346,6 @@ static int SProcVncExtListParams(ClientPtr client)
return ProcVncExtListParams(client);
}
-static int ProcVncExtSetServerCutText(ClientPtr client)
-{
- REQUEST(xVncExtSetServerCutTextReq);
- REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen);
- vncServerCutText((const char*)&stuff[1], stuff->textLen);
- return (client->noClientException);
-}
-
-static int SProcVncExtSetServerCutText(ClientPtr client)
-{
- REQUEST(xVncExtSetServerCutTextReq);
-#if XORG < 112
- register char n;
- swaps(&stuff->length, n);
-#else
- swaps(&stuff->length);
-#endif
- REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq);
-#if XORG < 112
- swapl(&stuff->textLen, n);
-#else
- swapl(&stuff->textLen);
-#endif
- return ProcVncExtSetServerCutText(client);
-}
-
static int ProcVncExtSelectInput(ClientPtr client)
{
struct VncInputSelect** nextPtr;
@@ -583,8 +549,6 @@ static int ProcVncExtDispatch(ClientPtr client)
return ProcVncExtGetParamDesc(client);
case X_VncExtListParams:
return ProcVncExtListParams(client);
- case X_VncExtSetServerCutText:
- return ProcVncExtSetServerCutText(client);
case X_VncExtSelectInput:
return ProcVncExtSelectInput(client);
case X_VncExtConnect:
@@ -610,8 +574,6 @@ static int SProcVncExtDispatch(ClientPtr client)
return SProcVncExtGetParamDesc(client);
case X_VncExtListParams:
return SProcVncExtListParams(client);
- case X_VncExtSetServerCutText:
- return SProcVncExtSetServerCutText(client);
case X_VncExtSelectInput:
return SProcVncExtSelectInput(client);
case X_VncExtConnect:
@@ -644,39 +606,3 @@ static void vncClientStateChange(CallbackListPtr * l, void * d, void * p)
}
}
}
-
-static void SendSelectionChangeEvent(Atom selection)
-{
- xVncExtSelectionChangeNotifyEvent ev;
- ev.type = vncEventBase + VncExtSelectionChangeNotify;
- for (struct VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
- if (cur->mask & VncExtSelectionChangeMask) {
- ev.sequenceNumber = cur->client->sequence;
- ev.window = cur->window;
- ev.selection = selection;
- if (cur->client->swapped) {
-#if XORG < 112
- int n;
- swaps(&ev.sequenceNumber, n);
- swapl(&ev.window, n);
- swapl(&ev.selection, n);
-#else
- swaps(&ev.sequenceNumber);
- swapl(&ev.window);
- swapl(&ev.selection);
-#endif
- }
- WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent),
- (char *)&ev);
- }
- }
-}
-
-static void vncSelectionCallback(CallbackListPtr *callbacks, void * data, void * args)
-{
- SelectionInfoRec *info = (SelectionInfoRec *) args;
- Selection *selection = info->selection;
-
- SendSelectionChangeEvent(selection->selection);
-}
-
diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc
index 32a93f03..fda2562e 100644
--- a/unix/xserver/hw/vnc/vncExtInit.cc
+++ b/unix/xserver/hw/vnc/vncExtInit.cc
@@ -70,6 +70,9 @@ rfb::StringParameter interface("interface",
rfb::BoolParameter avoidShiftNumLock("AvoidShiftNumLock",
"Avoid fake Shift presses for keys affected by NumLock.",
true);
+rfb::BoolParameter sendPrimary("SendPrimary",
+ "Send the PRIMARY as well as the CLIPBOARD selection",
+ true);
static PixelFormat vncGetPixelFormat(int scrIdx)
{
@@ -245,6 +248,11 @@ int vncGetAvoidShiftNumLock(void)
return (bool)avoidShiftNumLock;
}
+int vncGetSendPrimary(void)
+{
+ return (bool)sendPrimary;
+}
+
void vncUpdateDesktopName(void)
{
for (int scr = 0; scr < vncGetScreenCount(); scr++) {
diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h
index 1057118a..4b8568e1 100644
--- a/unix/xserver/hw/vnc/vncExtInit.h
+++ b/unix/xserver/hw/vnc/vncExtInit.h
@@ -57,6 +57,8 @@ void vncCallWriteWakeupHandlers(fd_set * fds, int nfds);
int vncGetAvoidShiftNumLock(void);
+int vncGetSendPrimary(void);
+
void vncUpdateDesktopName(void);
void vncServerCutText(const char *text, size_t len);
diff --git a/unix/xserver/hw/vnc/vncSelection.c b/unix/xserver/hw/vnc/vncSelection.c
index 2369c5d7..263dbeca 100644
--- a/unix/xserver/hw/vnc/vncSelection.c
+++ b/unix/xserver/hw/vnc/vncSelection.c
@@ -22,6 +22,7 @@
#include <X11/Xatom.h>
+#include "propertyst.h"
#include "scrnintstr.h"
#include "selection.h"
#include "windowstr.h"
@@ -29,6 +30,7 @@
#include "xorg-version.h"
+#include "vncExtInit.h"
#include "vncSelection.h"
#include "RFBGlue.h"
@@ -48,13 +50,24 @@ static int clientCutTextLen;
static int vncCreateSelectionWindow(void);
static int vncOwnSelection(Atom selection);
static int vncProcConvertSelection(ClientPtr client);
+static int vncProcSendEvent(ClientPtr client);
+static void vncSelectionCallback(CallbackListPtr *callbacks,
+ void * data, void * args);
static int (*origProcConvertSelection)(ClientPtr);
+static int (*origProcSendEvent)(ClientPtr);
void vncSelectionInit(void)
{
+ /* There are no hooks for when these are internal windows, so
+ * override the relevant handlers. */
origProcConvertSelection = ProcVector[X_ConvertSelection];
ProcVector[X_ConvertSelection] = vncProcConvertSelection;
+ origProcSendEvent = ProcVector[X_SendEvent];
+ ProcVector[X_SendEvent] = vncProcSendEvent;
+
+ if (!AddCallback(&SelectionCallback, vncSelectionCallback, 0))
+ FatalError("Add VNC SelectionCallback failed\n");
}
void vncClientCutText(const char* str, int len)
@@ -240,8 +253,6 @@ static int vncConvertSelection(ClientPtr client, Atom selection,
return Success;
}
-/* The original code cannot deal with the selection owner being
- * serverClient, so we have to reimplement this. */
static int vncProcConvertSelection(ClientPtr client)
{
Bool paramsOkay;
@@ -289,3 +300,102 @@ static int vncProcConvertSelection(ClientPtr client)
return origProcConvertSelection(client);
}
+
+static void vncHandleSelection(Atom selection, Atom target,
+ Atom property, Atom requestor,
+ TimeStamp time)
+{
+ Atom xaSTRING;
+ PropertyPtr prop;
+ int rc;
+
+ LOG_DEBUG("Selection notification for %s (target %s, property %s)",
+ NameForAtom(selection), NameForAtom(target),
+ NameForAtom(property));
+
+ xaSTRING = MakeAtom("STRING", 6, TRUE);
+
+ if (target != xaSTRING)
+ return;
+ if (property != xaSTRING)
+ return;
+
+ rc = dixLookupProperty(&prop, pWindow, xaSTRING,
+ serverClient, DixReadAccess);
+ if (rc != Success)
+ return;
+
+ if (prop->type != xaSTRING)
+ return;
+ if (prop->format != 8)
+ return;
+
+ vncServerCutText(prop->data, prop->size);
+}
+
+#define SEND_EVENT_BIT 0x80
+
+static int vncProcSendEvent(ClientPtr client)
+{
+ REQUEST(xSendEventReq);
+ REQUEST_SIZE_MATCH(xSendEventReq);
+
+ stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
+
+ if (stuff->event.u.u.type == SelectionNotify &&
+ stuff->event.u.selectionNotify.requestor == wid) {
+ TimeStamp time;
+ time = ClientTimeToServerTime(stuff->event.u.selectionNotify.time);
+ vncHandleSelection(stuff->event.u.selectionNotify.selection,
+ stuff->event.u.selectionNotify.target,
+ stuff->event.u.selectionNotify.property,
+ stuff->event.u.selectionNotify.requestor,
+ time);
+ }
+
+ return origProcSendEvent(client);
+}
+
+static void vncSelectionCallback(CallbackListPtr *callbacks,
+ void * data, void * args)
+{
+ SelectionInfoRec *info = (SelectionInfoRec *) args;
+
+ Atom xaPRIMARY, xaCLIPBOARD, xaSTRING;
+ xEvent event;
+ int rc;
+
+ if (info->kind != SelectionSetOwner)
+ return;
+ if (info->client == serverClient)
+ return;
+
+ xaPRIMARY = MakeAtom("PRIMARY", 7, TRUE);
+ xaCLIPBOARD = MakeAtom("CLIPBOARD", 9, TRUE);
+
+ if ((info->selection->selection != xaPRIMARY) &&
+ (info->selection->selection != xaCLIPBOARD))
+ return;
+
+ if ((info->selection->selection == xaPRIMARY) &&
+ !vncGetSendPrimary())
+ return;
+
+ rc = vncCreateSelectionWindow();
+ if (rc != Success)
+ return;
+
+ LOG_DEBUG("Requesting %s selection",
+ NameForAtom(info->selection->selection));
+
+ xaSTRING = MakeAtom("STRING", 6, TRUE);
+
+ event.u.u.type = SelectionRequest;
+ event.u.selectionRequest.owner = info->selection->window;
+ event.u.selectionRequest.time = currentTime.milliseconds;
+ event.u.selectionRequest.requestor = wid;
+ event.u.selectionRequest.selection = info->selection->selection;
+ event.u.selectionRequest.target = xaSTRING;
+ event.u.selectionRequest.property = xaSTRING;
+ WriteEventsToClient(info->client, 1, &event);
+}