]> source.dussan.org Git - tigervnc.git/commitdiff
Move server to client clipboard out of vncconfig
authorPierre Ossman <ossman@cendio.se>
Tue, 12 Jan 2016 17:40:23 +0000 (18:40 +0100)
committerPierre Ossman <ossman@cendio.se>
Fri, 5 Feb 2016 09:34:36 +0000 (10:34 +0100)
Also handle clipboard transactions from the server to the client
directly in the server without the help of vncconfig.

unix/xserver/hw/vnc/Xvnc.man
unix/xserver/hw/vnc/vncExt.c
unix/xserver/hw/vnc/vncExtInit.cc
unix/xserver/hw/vnc/vncExtInit.h
unix/xserver/hw/vnc/vncSelection.c

index 4a833157883f49938a08844e1f0c00d8d186b673..e86bf87f7267591fba40ac22e07d567a2d89c11a 100644 (file)
@@ -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).
 .
index e07ed8656d5d356b1ae9a2008d9ae5afd2b83f00..334c88894631ce66e5076c3fbf9576cd02346be9 100644 (file)
@@ -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);
-}
-
index 32a93f0308445cc8d8ee2c04f18b8aa2cc1d7791..fda2562e44c85bdc88e432c71491e7014ed14dec 100644 (file)
@@ -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++) {
index 1057118a9047a8d95c2b906be85292c1f5003ecc..4b8568e1795dfe58d8cbecc5a64b35ef56371d7c 100644 (file)
@@ -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);
index 2369c5d7ba6ae522eaae670640bfbc273da52d72..263dbeca65fcd7eca4b1ce002cfa6cb66b192aac 100644 (file)
@@ -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);
+}