#include "dixstruct.h"
#include "extnsionst.h"
#include "scrnintstr.h"
-#include "selection.h"
#define _VNCEXT_SERVER_
#define _VNCEXT_PROTO_
static void vncClientStateChange(CallbackListPtr*, void *, void *);
-static void vncSelectionCallback(CallbackListPtr *callbacks,
- void * data, void * args);
-
static int vncErrorBase = 0;
static int vncEventBase = 0;
FatalError("Add ClientStateCallback failed\n");
}
- if (!AddCallback(&SelectionCallback, vncSelectionCallback, 0)) {
- FatalError("Add SelectionCallback failed\n");
- }
-
return 0;
}
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;
return ProcVncExtGetParamDesc(client);
case X_VncExtListParams:
return ProcVncExtListParams(client);
- case X_VncExtSetServerCutText:
- return ProcVncExtSetServerCutText(client);
case X_VncExtSelectInput:
return ProcVncExtSelectInput(client);
case X_VncExtConnect:
return SProcVncExtGetParamDesc(client);
case X_VncExtListParams:
return SProcVncExtListParams(client);
- case X_VncExtSetServerCutText:
- return SProcVncExtSetServerCutText(client);
case X_VncExtSelectInput:
return SProcVncExtSelectInput(client);
case X_VncExtConnect:
}
}
}
-
-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);
-}
-
#include <X11/Xatom.h>
+#include "propertyst.h"
#include "scrnintstr.h"
#include "selection.h"
#include "windowstr.h"
#include "xorg-version.h"
+#include "vncExtInit.h"
#include "vncSelection.h"
#include "RFBGlue.h"
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)
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;
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);
+}