diff -urN vnc_unixsrc.orig/Xvnc/programs/Xserver/dix/dispatch.c vnc_unixsrc/Xvnc/programs/Xserver/dix/dispatch.c --- vnc_unixsrc.orig/Xvnc/programs/Xserver/dix/dispatch.c 1996-12-22 22:29:38.000000000 -0800 +++ vnc_unixsrc/Xvnc/programs/Xserver/dix/dispatch.c 2003-04-18 12:04:33.000000000 -0700 @@ -2,6 +2,7 @@ /* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.7 1996/12/23 06:29:38 dawes Exp $ */ /************************************************************ +Copyright (c) 2003 Workspot, Inc. Copyright (c) 1987, 1989 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy @@ -65,6 +66,7 @@ #include "swaprep.h" #include "swapreq.h" #include "dixevents.h" +#include #ifdef XCSECURITY #define _SECURITY_SERVER #include "extensions/security.h" @@ -87,6 +89,7 @@ Selection *CurrentSelections; int NumCurrentSelections; +extern Atom XA_CLIPBOARD, XA_VNC_CLIPBOARD; extern CARD32 defaultScreenSaverTime; extern CARD32 defaultScreenSaverInterval; @@ -885,6 +888,22 @@ CurrentSelections[i].window = stuff->window; CurrentSelections[i].pWin = pWin; CurrentSelections[i].client = (pWin ? client : NullClient); + + /* have owner also set VNC clipboard whenever X clipboard changes */ + if (pWin && stuff->selection == XA_CLIPBOARD) { + xEvent event; + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = stuff->window; + event.u.selectionRequest.requestor = WindowTable[0]->drawable.id; + event.u.selectionRequest.selection = XA_CLIPBOARD; + event.u.selectionRequest.target = XA_STRING; + event.u.selectionRequest.property = XA_VNC_CLIPBOARD; + (void) TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + } + return (client->noClientException); } else @@ -961,6 +980,16 @@ #endif ) { + + /* special case if VNC viewer client owns the clipboard */ + if (CurrentSelections[i].window == WindowTable[0]->drawable.id) + { + extern void rfbConvertSelection(); + rfbConvertSelection(client, pWin, stuff->time, stuff->requestor, + stuff->target, stuff->property); + return (client->noClientException); + } + event.u.u.type = SelectionRequest; event.u.selectionRequest.time = stuff->time; event.u.selectionRequest.owner = diff -urN vnc_unixsrc.orig/Xvnc/programs/Xserver/hw/vnc/cutpaste.c vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc/cutpaste.c --- vnc_unixsrc.orig/Xvnc/programs/Xserver/hw/vnc/cutpaste.c 2000-10-25 11:07:50.000000000 -0700 +++ vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc/cutpaste.c 2003-04-18 12:04:28.000000000 -0700 @@ -3,6 +3,7 @@ */ /* + * Copyright (C) 2003 Workspot, Inc. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * * This is free software; you can redistribute it and/or modify @@ -29,18 +30,19 @@ #include "selection.h" #include "input.h" #include +#include "propertyst.h" +#include "windowstr.h" extern WindowPtr *WindowTable; /* Why isn't this in a header file? */ extern Selection *CurrentSelections; extern int NumCurrentSelections; - +extern Atom XA_TEXT, XA_TARGETS, XA_TIMESTAMP, XA_CLIPBOARD, XA_VNC_CLIPBOARD; static Bool inSetXCutText = FALSE; /* - * rfbSetXCutText sets the cut buffer to be the given string. We also clear - * the primary selection. Ideally we'd like to set it to the same thing, but I - * can't work out how to do that without some kind of helper X client. + * rfbSetXCutText sets the clipboard (formerly the cut buffer) to be the + * given string. */ void @@ -49,17 +51,18 @@ int i = 0; inSetXCutText = TRUE; - ChangeWindowProperty(WindowTable[0], XA_CUT_BUFFER0, XA_STRING, + ChangeWindowProperty(WindowTable[0], XA_VNC_CLIPBOARD, XA_STRING, 8, PropModeReplace, len, (pointer)str, TRUE); while ((i < NumCurrentSelections) && - CurrentSelections[i].selection != XA_PRIMARY) + CurrentSelections[i].selection != XA_CLIPBOARD) i++; + inSetXCutText = FALSE; + if (i < NumCurrentSelections) { xEvent event; - if (CurrentSelections[i].client) { event.u.u.type = SelectionClear; event.u.selectionClear.time = GetTimeInMillis(); @@ -69,18 +72,93 @@ NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab); } - - CurrentSelections[i].window = None; - CurrentSelections[i].pWin = NULL; - CurrentSelections[i].client = NullClient; + } else { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return ; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = XA_CLIPBOARD; } - - inSetXCutText = FALSE; + UpdateCurrentTime(); + CurrentSelections[i].lastTimeChanged = currentTime; + CurrentSelections[i].window = WindowTable[0]->drawable.id; + CurrentSelections[i].pWin = WindowTable[0]; + CurrentSelections[i].client = NullClient; } void rfbGotXCutText(char *str, int len) { - if (!inSetXCutText) + if (!inSetXCutText) { rfbSendServerCutText(str, len); + } +} + +void rfbConvertSelection(ClientPtr client, WindowPtr pWin, + Time time, Window requestor, + Atom target, Atom property) +{ + xEvent event; + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = time; + event.u.selectionNotify.requestor = requestor; + event.u.selectionNotify.selection = XA_CLIPBOARD; + event.u.selectionNotify.target = target; + event.u.selectionNotify.property = None; + + if (property == None) /* old style client */ + property = target; + + if (target == XA_STRING || target == XA_TEXT) + { + PropertyPtr pProp; + pProp = wUserProps(WindowTable[0]); + while (pProp) + { + if (pProp->propertyName == XA_VNC_CLIPBOARD && pProp->type == XA_STRING) + break; + pProp = pProp->next; + } + + if (pProp) + { + ChangeWindowProperty(pWin, property, XA_STRING, 8, PropModeReplace, + pProp->size, pProp->data, TRUE); + } + + event.u.selectionNotify.target = XA_STRING; + event.u.selectionNotify.property = (pProp ? property : None); + } else if (target == XA_TARGETS) { + Atom value[2]; + value[0] = XA_STRING; + value[1] = XA_TEXT; + ChangeWindowProperty(pWin, property, XA_ATOM, 32, PropModeReplace, + 2, value, TRUE); + event.u.selectionNotify.target = XA_ATOM; + event.u.selectionNotify.property = property; + } else if (target == XA_TIMESTAMP) { + int i; + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != XA_CLIPBOARD) i++; + if (i < NumCurrentSelections) { + ChangeWindowProperty(pWin, property, XA_TIMESTAMP, 32, PropModeReplace, + sizeof(TimeStamp), + (pointer)&(CurrentSelections[i].lastTimeChanged), + TRUE); + event.u.selectionNotify.property = property; + } + } + + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); } diff -urN vnc_unixsrc.orig/Xvnc/programs/Xserver/hw/vnc/init.c vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc/init.c --- vnc_unixsrc.orig/Xvnc/programs/Xserver/hw/vnc/init.c 2003-03-04 11:18:23.000000000 -0800 +++ vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc/init.c 2003-04-18 12:04:24.000000000 -0700 @@ -3,6 +3,7 @@ */ /* + * Copyright (C) 2003 Workspot Inc. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * * This is free software; you can redistribute it and/or modify @@ -101,6 +102,11 @@ Atom VNC_LAST_CLIENT_ID; Atom VNC_CONNECT; +Atom XA_TEXT; +Atom XA_TARGETS; +Atom XA_TIMESTAMP; +Atom XA_CLIPBOARD; +Atom XA_VNC_CLIPBOARD; static HWEventQueueType alwaysCheckForInput[2] = { 0, 1 }; static HWEventQueueType *mieqCheckForInput[2]; @@ -399,6 +405,11 @@ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID", strlen("VNC_LAST_CLIENT_ID"), TRUE); VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE); + XA_TEXT = MakeAtom("TEXT", strlen("TEXT"), TRUE); + XA_TARGETS = MakeAtom("TARGETS", strlen("TARGETS"), TRUE); + XA_TIMESTAMP = MakeAtom("TIMESTAMP", strlen("TIMESTAMP"), TRUE); + XA_CLIPBOARD = MakeAtom("CLIPBOARD", strlen("CLIPBOARD"), TRUE); + XA_VNC_CLIPBOARD = MakeAtom("VNC_CLIPBOARD", strlen("VNC_CLIPBOARD"), TRUE); rfbInitSockets(); if (inetdSock == -1) httpInitSockets(); @@ -749,7 +760,7 @@ void rfbRootPropertyChange(PropertyPtr pProp) { - if ((pProp->propertyName == XA_CUT_BUFFER0) && (pProp->type == XA_STRING) + if ((pProp->propertyName == XA_VNC_CLIPBOARD) && (pProp->type == XA_STRING) && (pProp->format == 8)) { rfbGotXCutText(pProp->data, pProp->size); diff -urN vnc_unixsrc.orig/vncviewer/selection.c vnc_unixsrc/vncviewer/selection.c --- vnc_unixsrc.orig/vncviewer/selection.c 1999-08-10 09:23:24.000000000 -0700 +++ vnc_unixsrc/vncviewer/selection.c 2003-04-18 12:04:08.000000000 -0700 @@ -1,4 +1,5 @@ /* + * Copyright (C) 2003 Workspot, Inc. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * * This is free software; you can redistribute it and/or modify @@ -18,7 +19,7 @@ */ /* - * selection.c - functions to deal with the selection and cut buffer. + * selection.c - functions to deal with the selection and clipboard. */ #include @@ -35,9 +36,11 @@ Atom* selection, Atom* type, XtPointer value, unsigned long* length, int* format); +#if 0 static void SendCutBuffer(); static void CutBufferChange(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont); +#endif static Boolean ConvertSelection(Widget w, Atom* selection, Atom* target, Atom* type, XtPointer* value, unsigned long* length, int* format); @@ -49,6 +52,9 @@ #define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (INT32)((a) - (b)) > 0)) +static Atom XA_TIMESTAMP; +static Atom XA_CLIPBOARD; + /* * InitialiseSelection() must be called after realizing widgets (because @@ -72,11 +78,15 @@ #endif XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); - XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, - NULL); + /* no longer need this since we now only care about the CLIPBOARD: + * XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, + * NULL); + */ + + XA_TIMESTAMP = XInternAtom(dpy, "TIMESTAMP", False); + XA_CLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False); - XtGetSelectionValue(toplevel, XA_PRIMARY, - XInternAtom(dpy, "TIMESTAMP", False), + XtGetSelectionValue(toplevel, XA_CLIPBOARD, XA_TIMESTAMP, GetInitialSelectionTimeCallback, NULL, CurrentTime); } @@ -135,10 +145,10 @@ } if (always) { - XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, + XtGetSelectionValue(w, XA_CLIPBOARD, XA_STRING, GetSelectionCallback, NULL, TimeFromEvent(event)); } else { - XtGetSelectionValue(w, XA_PRIMARY, XInternAtom(dpy, "TIMESTAMP", False), + XtGetSelectionValue(w, XA_CLIPBOARD, XA_TIMESTAMP, GetSelectionTimeCallback, NULL, TimeFromEvent(event)); } } @@ -147,7 +157,7 @@ /* * GetSelectionCallback() is invoked when the selection has been retrieved from * the selection owner - we simply send it to the VNC server. If there is - * no PRIMARY selection available, we try sending CUT_BUFFER0 instead. + * no CLIPBOARD selection available, we don't send anything. */ static void @@ -160,8 +170,6 @@ if (str) SendClientCutText(str, len); - else - SendCutBuffer(); } @@ -170,9 +178,7 @@ * the timestamp of the selection. If the timestamp is later than that of the * previous selection then we call XtGetSelectionValue() with target "STRING" * to get the selection. GetSelectionCallback() will be invoked when the - * selection is available. If there is no selection we see if the time - * CUT_BUFFER0 was last changed is later than that of the previous selection, - * and if so, send it. + * selection is available. */ static void @@ -186,16 +192,18 @@ if (TIME_LATER(t, prevSelectionTime)) { prevSelectionTime = t; - XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, + XtGetSelectionValue(w, XA_CLIPBOARD, XA_STRING, GetSelectionCallback, NULL, CurrentTime); } +#if 0 } else { if (TIME_LATER(cutBufferTime, prevSelectionTime)) { prevSelectionTime = cutBufferTime; SendCutBuffer(); } +#endif } if (value) @@ -203,6 +211,10 @@ } +#if 0 + +now that we are using the CLIPBOARD we can remove the following two routines + /* * SendCutBuffer gets the CUT_BUFFER0 property from the root window and sends * it to the VNC server. @@ -236,14 +248,16 @@ cutBufferTime = ev->xproperty.time; } +#endif + /* * SelectionFromVNC() is an action which is usually invoked when the mouse * leaves the viewer window. With the "always" argument we always set the - * PRIMARY selection and CUT_BUFFER0 to the current value of the VNC server - * "cut text". With no argument or the "new" argument we set the selection - * only if it is "new" i.e. there has been new "cut text" since the last time - * it was called. + * CLIPBOARD selection to the current value of the VNC server "cut text". + * With no argument or the "new" argument we set the selection only if it + * is "new" i.e. there has been new "cut text" since the last time it was + * called. */ void @@ -269,13 +283,13 @@ return; } - if (!serverCutText || (!always && !newServerCutText)) + if (!serverCutText || (!always && !newServerCutText) || iAmSelectionOwner) return; newServerCutText = False; - XStoreBytes(dpy, serverCutText, strlen(serverCutText)); - if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, + /* XStoreBytes(dpy, serverCutText, strlen(serverCutText)); no longer set cutbuffer */ + if (XtOwnSelection(desktop, XA_CLIPBOARD, t, ConvertSelection, LoseSelection, NULL)) { iAmSelectionOwner = True; }