From 972a92cab16a99d86a5b66b03967229799f1216d Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 2 Oct 2020 22:48:51 +0200 Subject: Clipboard.c: add/fix comments --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 22fc96f4f..bb8ca5843 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -827,9 +827,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * * The list is aligned with the one in nxagentConvertSelection. * - * FIXME: the perfect solution should not just answer with - * XA_STRING but ask the real owner what format it supports. The - * result should then be sent to the original requestor. + * FIXME: the perfect solution should not just answer with a + * hardcoded list but ask the real owner what format it + * supports. The result should then be sent to the original + * requestor. */ long targets[] = {XA_STRING, serverUTF8_STRING, serverTEXT, serverCOMPOUND_TEXT, serverTARGETS, serverTIMESTAMP}; @@ -877,6 +878,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * * FIXME: ensure we are reporting an _external_ timestamp * FIXME: for a 32 bit property list we need to pass a "long" array, not "char"! + * FIXME: selection has already been checked above, so we do not need to check again here */ int i = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); @@ -1784,6 +1786,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, __func__, nxagentClientInfoString(client)); #endif + /* notify the sender of the new request of failure */ sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); return 1; -- cgit v1.2.3 From 18c91fd94c8bba7de44110e9db9daf41ee6f916d Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 2 Oct 2020 22:59:12 +0200 Subject: Clipboard.c: improve error message if we get an unexpected property print that as an error. Before we saw "unexpected stage" in that case which does not really help in debugging... --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 57 +++++++++++++++++--------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index bb8ca5843..f704e4702 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1330,8 +1330,8 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } #ifdef DEBUG + XSelectionEvent * e = (XSelectionEvent *)X; { - XSelectionEvent * e = (XSelectionEvent *)X; char * s = XGetAtomName(nxagentDisplay, e->property); char * t = XGetAtomName(nxagentDisplay, e->target); fprintf(stderr, "%s: SelectionNotify event from real X server, property "\ @@ -1355,29 +1355,46 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * the real X server). We now need to transfer it to the original * requestor, which is stored in the lastClient* variables. */ - if (lastClientStage == SelectionStageNone && - X->xselection.property == serverTransToAgentProperty) + + #ifdef DEBUG + fprintf(stderr, "%s: event selection is [%s]\n", __func__, XGetAtomName(nxagentDisplay, e->selection)); + nxagentDumpClipboardStat(); + #endif + if (lastClientStage == SelectionStageNone) { - #ifdef DEBUG - fprintf(stderr, "%s: Starting selection transferral for client %s.\n", __func__, - nxagentClientInfoString(lastClientClientPtr)); - #endif + if (X->xselection.property == serverTransToAgentProperty) + { + #ifdef DEBUG + fprintf(stderr, "%s: Starting selection transferral for client %s.\n", __func__, + nxagentClientInfoString(lastClientClientPtr)); + #endif - /* - * The state machine is able to work in two phases. In the first - * phase we get the size of property data, in the second we get - * the actual data. We save a round-trip by requesting a prede- - * termined amount of data in a single GetProperty and by discar- - * ding the remaining part. This is not the optimal solution (we - * could get the remaining part if it doesn't fit in a single - * reply) but, at least with text, it should work in most situa- - * tions. - */ + /* + * The state machine is able to work in two phases. In the first + * phase we get the size of property data, in the second we get + * the actual data. We save a round-trip by requesting a prede- + * termined amount of data in a single GetProperty and by discar- + * ding the remaining part. This is not the optimal solution (we + * could get the remaining part if it doesn't fit in a single + * reply) but, at least with text, it should work in most situa- + * tions. + */ - setClientSelectionStage(SelectionStageQueryData); - lastClientPropertySize = 262144; + setClientSelectionStage(SelectionStageQueryData); + lastClientPropertySize = 262144; - transferSelection(lastClientClientPtr -> index); + transferSelection(lastClientClientPtr -> index); + } + else + { + #ifdef DEBUG + char *s = XGetAtomName(nxagentDisplay, X->xselection.property); + fprintf(stderr, "%s: Unexpected property [%ld][%s] - reporting conversion failure.\n", + __func__, X->xselection.property, s); + SAFE_XFree(s); + #endif + endTransfer(SELECTION_FAULT); + } } else { -- cgit v1.2.3 From 32e194d460d82313706c72110652782e6c26b872 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 2 Oct 2020 22:50:08 +0200 Subject: Clipboard.c: improve debugging output --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 56 +++++++++++++++++--------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f704e4702..a72449633 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -765,8 +765,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) char *strSelection = XGetAtomName(nxagentDisplay, X->xselectionrequest.selection); char *strProperty = XGetAtomName(nxagentDisplay, X->xselectionrequest.property); - fprintf(stderr, "%s: Received SelectionRequest from real server: selection [%ld][%s] " \ - "target [%ld][%s] requestor [%s/0x%lx] destination [%ld][%s] lastServerRequestor [0x%x]\n", + fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ + "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s] lastServerRequestor [0x%x]\n", __func__, X->xselectionrequest.selection, validateString(strSelection), X->xselectionrequest.target, validateString(strTarget), @@ -935,8 +935,18 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) serverWindow, lastClientTime); #ifdef DEBUG - fprintf(stderr, "%s: Sent XConvertSelection.\n", __func__); + char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); + char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[i].selection); + char *strProperty = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); + fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, + CurrentSelections[i].selection, strSelection, + X->xselectionrequest.target, strTarget, + serverTransToAgentProperty, strProperty, + serverWindow, lastClientTime); #endif + SAFE_XFree(strTarget); + SAFE_XFree(strSelection); + SAFE_XFree(strProperty); } else { @@ -1305,7 +1315,7 @@ void nxagentCollectPropertyEvent(int resource) { #ifdef DEBUG fprintf (stderr, "%s: WARNING! Inconsistent state [%s] for client %s.\n", __func__, - getClientSelectionStageString(lastClientStage), nxagentClientInfoString(lastClientClientPtr)); + getClientSelectionStageString(lastClientStage), nxagentClientInfoString(lastClientClientPtr)); #endif break; } @@ -1332,14 +1342,17 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) #ifdef DEBUG XSelectionEvent * e = (XSelectionEvent *)X; { - char * s = XGetAtomName(nxagentDisplay, e->property); + char * p = XGetAtomName(nxagentDisplay, e->property); char * t = XGetAtomName(nxagentDisplay, e->target); - fprintf(stderr, "%s: SelectionNotify event from real X server, property "\ - "[%ld][%s] requestor [0x%lx] target [%ld][%s] time [%ld] send_event [%d].\n", - __func__, e->property, validateString(s), e->requestor, e->target, + char * s = XGetAtomName(nxagentDisplay, e->selection); + fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ + "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%ld] send_event [%d].\n", + __func__, e->property, validateString(p), e->requestor, + validateString(s), e->target, validateString(t), e->time, e->send_event); - SAFE_XFree(s); + SAFE_XFree(p); SAFE_XFree(t); + SAFE_XFree(s); } #endif @@ -1357,7 +1370,6 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) */ #ifdef DEBUG - fprintf(stderr, "%s: event selection is [%s]\n", __func__, XGetAtomName(nxagentDisplay, e->selection)); nxagentDumpClipboardStat(); #endif if (lastClientStage == SelectionStageNone) @@ -1399,7 +1411,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) else { #ifdef DEBUG - fprintf(stderr, "%s: WARNING! Resetting selection transferral for client [%d].\n", __func__, + fprintf(stderr, "%s: WARNING! Resetting selection transferral for client [%d] because of unexpected stage.\n", __func__, CLINDEX(lastClientClientPtr)); #endif @@ -1781,6 +1793,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, fprintf(stderr, "%s: lastClientWindowPtr != NULL.\n", __func__); #endif + #ifdef DEBUG + fprintf(stderr, "%s: lastClientSelection [%d] - selection [%d]\n", __func__, lastClientSelection, selection); + #endif + if ((GetTimeInMillis() - lastClientReqTime) >= CONVERSION_TIMEOUT) { #ifdef DEBUG @@ -1798,8 +1814,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * which we cannot handle (yet). So return an error. */ #ifdef DEBUG - fprintf(stderr, "%s: got request " - "before timeout expired on last request, notifying failure to client %s\n", + fprintf(stderr, "%s: got new request " + "before timeout expired on previous request, notifying failure to client %s\n", __func__, nxagentClientInfoString(client)); #endif @@ -1810,16 +1826,16 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } } + const char *strTarget = NameForAtom(target); + #ifdef DEBUG fprintf(stderr, "%s: client %s requests sel [%s] " - "on window [%x] prop [%d][%s] target [%d][%s].\n", __func__, + "on window [0x%x] prop [%d][%s] target [%d][%s].\n", __func__, nxagentClientInfoString(client), validateString(NameForAtom(selection)), requestor, property, validateString(NameForAtom(property)), - target, validateString(NameForAtom(target))); + target, validateString(strTarget)); #endif - const char *strTarget = NameForAtom(target); - if (strTarget == NULL) { #ifdef DEBUG @@ -1840,7 +1856,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, int numTargets = sizeof(targets) / sizeof(targets[0]); #ifdef DEBUG - fprintf(stderr, "%s: available targets:\n", __func__); + fprintf(stderr, "%s: available targets [%d]:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) fprintf(stderr, "%s: %s\n", __func__, NameForAtom(targets[i])); fprintf(stderr, "\n"); @@ -1977,8 +1993,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } #ifdef DEBUG - fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] time [%ld]\n", __func__, - serverWindow, t, tstr, p, pstr, CurrentTime); + fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] time [0][CurrentTime]\n", __func__, + serverWindow, t, tstr, p, pstr); #endif XConvertSelection(nxagentDisplay, selection, t, p, serverWindow, CurrentTime); -- cgit v1.2.3 From 2742fde0043d2690c3c7b22f137679d0b91dac6c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 20 Sep 2020 16:45:51 +0200 Subject: Clipboard.c: improve explanations/FIXMEs --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index a72449633..a4f61ef19 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -923,12 +923,18 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) int i = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); if (i < nxagentMaxSelections) { +#if 0 if (lastClientWindowPtr != NULL && IS_INTERNAL_OWNER(i)) { /* * Request the real X server to transfer the selection content * to the NX_CUT_BUFFER_SERVER property of the serverWindow. * FIXME: document how we can end up here + * + * It looks like this is only reached when the real X server is + * on Windows. I suspect that this is connected to the windows X + * server (VcXSrv in my test) pushing PRIMARY or CLIPBOARD + * content to the Windows clipboard whenever they change. */ XConvertSelection(nxagentDisplay, CurrentSelections[i].selection, X->xselectionrequest.target, serverTransToAgentProperty, @@ -949,6 +955,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) SAFE_XFree(strProperty); } else +#endif { /* * if one of our clients owns the selection we ask it to copy @@ -1683,6 +1690,7 @@ static void setSelectionOwner(Selection *pSelection) /* * we are in the process of communicating back and forth between * real X server and nxagent's clients - let's not disturb + * FIXME: by continuing after the warning were ARE disturbing! */ fprintf (stderr, "%s: WARNING! Requestor window [0x%x] already set.\n", __func__, lastServerRequestor); @@ -1804,6 +1812,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, "notifying failure to client %s\n", __func__, nxagentClientInfoString(client)); #endif + /* notify the waiting client of failure */ endTransfer(SELECTION_FAULT); } else @@ -1999,7 +2008,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, XConvertSelection(nxagentDisplay, selection, t, p, serverWindow, CurrentTime); - /* FIXME: check returncode of XConvertSelection */ + /* FIXME: check result of XConvertSelection? */ #ifdef DEBUG fprintf(stderr, "%s: Sent XConvertSelection with target [%s], property [%s]\n", __func__, tstr, pstr); -- cgit v1.2.3 From 12ed2c635b6979f84832655ffe66171482d80469 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 19 Sep 2020 22:15:03 +0200 Subject: Clipboard.c: print times unsigned there are no negative times... --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index a4f61ef19..11c6ae013 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1353,7 +1353,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) char * t = XGetAtomName(nxagentDisplay, e->target); char * s = XGetAtomName(nxagentDisplay, e->selection); fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ - "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%ld] send_event [%d].\n", + "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", __func__, e->property, validateString(p), e->requestor, validateString(s), e->target, validateString(t), e->time, e->send_event); @@ -1709,7 +1709,7 @@ static void setSelectionOwner(Selection *pSelection) fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%x])\n", __func__, (void *)lastSelectionOwner[i].windowPtr, (void *)pSelection->pWin, nxagentWindow(pSelection->pWin), serverWindow); - fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%d]\n", __func__, + fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, lastSelectionOwner[i].lastTimeChanged); #endif @@ -2199,7 +2199,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) #ifdef NXAGENT_TIMESTAMP { - fprintf(stderr, "%s: Clipboard init starts at [%ld] ms.\n", __func__, + fprintf(stderr, "%s: Clipboard init starts at [%lu] ms.\n", __func__, GetTimeInMillis() - startTime); } #endif @@ -2367,7 +2367,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) #ifdef NXAGENT_TIMESTAMP { - fprintf(stderr, "%s: Clipboard init ends at [%ld] ms.\n", __func__, + fprintf(stderr, "%s: Clipboard init ends at [%lu] ms.\n", __func__, GetTimeInMillis() - startTime); } #endif -- cgit v1.2.3 From 60380a6a5ed99680f86c5daf14bb412b6d3383a4 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 20 Sep 2020 16:41:56 +0200 Subject: Clipboard.c: do not set stage to new value if already set to that value --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 11c6ae013..fddb53b97 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -394,6 +394,15 @@ void nxagentDumpClipboardStat(void) */ static void setClientSelectionStage(int stage) { + if (lastClientStage == stage) + { + #ifdef DEBUG + fprintf(stderr, "%s: selection stage already set to [%s] - doing nothing\n", __func__, + getClientSelectionStageString(lastClientStage)); + #endif + return; + } + #ifdef DEBUG fprintf(stderr, "%s: Changing selection stage from [%s] to [%s]\n", __func__, getClientSelectionStageString(lastClientStage), getClientSelectionStageString(stage)); -- cgit v1.2.3 From e9a25e7945a119a8843059dcc8e6ff621b6fb03e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 3 Oct 2020 00:10:27 +0200 Subject: Clipboard.c: catch selection failure from real X server --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index fddb53b97..4197dcebd 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1413,6 +1413,14 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) transferSelection(lastClientClientPtr -> index); } + else if (X->xselection.property == 0) + { + #ifdef DEBUG + fprintf(stderr, "%s: WARNING! Resetting selection transferral for client [%d] because of failure notification from real X server.\n", __func__, + CLINDEX(lastClientClientPtr)); + #endif + endTransfer(SELECTION_FAULT); + } else { #ifdef DEBUG -- cgit v1.2.3 From 94fd5f5905329777ba34345f93cc6ce9d19448fe Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 20 Sep 2020 19:48:46 +0200 Subject: Clipboard.c: rework LastClient stuff to work _per selection_ --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 547 +++++++++++++++---------- nx-X11/programs/Xserver/hw/nxagent/Clipboard.h | 2 +- nx-X11/programs/Xserver/hw/nxagent/Events.c | 8 +- 3 files changed, 325 insertions(+), 232 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 4197dcebd..b9af7e199 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -66,8 +66,6 @@ extern int NumCurrentSelections; extern Selection *CurrentSelections; -int nxagentLastClipboardClient = -1; - static int agentClipboardInitialized = False; static int clientAccum; @@ -114,17 +112,22 @@ typedef enum SelectionStageWaitData } ClientSelectionStage; -static WindowPtr lastClientWindowPtr; -static ClientPtr lastClientClientPtr; -static Window lastClientRequestor; -static Atom lastClientProperty; -static Atom lastClientSelection; -static Atom lastClientTarget; -static Time lastClientTime; -static Time lastClientReqTime; -static unsigned long lastClientPropertySize; - -static ClientSelectionStage lastClientStage; +typedef struct _lastClient +{ + WindowPtr windowPtr; + ClientPtr clientPtr; + Window requestor; + Atom property; + Atom selection; + Atom target; + Time time; + Time reqTime; + unsigned long propertySize; + ClientSelectionStage stage; + int resource; /* nxcompext resource where collected proeprty data is stored */ +} lastClient; + +static lastClient *lastClients; static Window lastServerRequestor; static XlibAtom lastServerProperty; @@ -179,9 +182,9 @@ static const char * getClientSelectionStageString(int stage) } #ifdef DEBUG -#define printClientSelectionStage() do {fprintf(stderr, "%s: Current selection stage [%s]\n", __func__, getClientSelectionStageString(lastClientStage));} while (0) +#define printClientSelectionStage(_index) do {fprintf(stderr, "%s: Current selection stage for selection [%d] is [%s]\n", __func__, _index, getClientSelectionStageString(lastClients[_index].stage));} while (0) #else -#define printClientSelectionStage() +#define printClientSelectionStage(_index) #endif #define WINDOWID(ptr) (ptr) ? (ptr->drawable.id) : 0 @@ -230,11 +233,11 @@ XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, False }; extern Display *nxagentDisplay; static Bool validServerTargets(XlibAtom target); -static void setClientSelectionStage(int stage); -static void endTransfer(Bool success); +static void setClientSelectionStage(int stage, int index); +static void endTransfer(Bool success, int index); #define SELECTION_SUCCESS True #define SELECTION_FAULT False -static void transferSelection(int resource); +static void transferSelection(int resource, int index); #if 0 static void resetSelectionOwner(void); #endif @@ -262,6 +265,7 @@ void nxagentPrintClipboardStat(char *); extern unsigned long startTime; #endif +// FIXME: change sel to index static void printSelectionStat(int sel) { SelectionOwner lOwner = lastSelectionOwner[sel]; @@ -298,6 +302,32 @@ static void printSelectionStat(int sel) return; } +static void printLastClientStat(int index) +{ + lastClient lc = lastClients[index]; + if (lc.windowPtr) + fprintf(stderr, " lastClients[].windowPtr (WindowPtr) [%p] ([0x%x])\n", (void *)lc.windowPtr, WINDOWID(lc.windowPtr)); + else + fprintf(stderr, " lastClients[].windowPtr (WindowPtr) -\n"); + fprintf(stderr, " lastClients[].clientPtr (ClientPtr) %s\n", nxagentClientInfoString(lc.clientPtr)); + fprintf(stderr, " lastClients[].requestor (Window) [0x%x]\n", lc.requestor); + fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForAtom(lc.property)); + fprintf(stderr, " lastClients[].selection (Atom) [% 4d][%s]\n", lc.selection, NameForAtom(lc.selection)); + fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForAtom(lc.target)); + if (lc.time > 0) + fprintf(stderr, " lastClients[].time (Time) [%u] ([%u]ms ago)\n", lc.time, GetTimeInMillis() - lc.time); + else + fprintf(stderr, " lastClients[].time (Time) [%u]\n", lc.time); + if (lc.reqTime > 0) + fprintf(stderr, " lastClients[].reqTime (Time) [%u] ([%u]ms ago)\n", lc.reqTime, GetTimeInMillis() - lc.reqTime); + else + fprintf(stderr, " lastClients[].reqTime (Time) [%u]\n", lc.reqTime); + fprintf(stderr, " lastClients[].propertySize (ulong) [%lu]\n", lc.propertySize); + fprintf(stderr, " lastClients[].stage (ClientSelStage) [%d][%s]\n", lc.stage, getClientSelectionStageString(lc.stage)); + fprintf(stderr, " lastClients[].resource (int) [%d]\n", lc.resource); +} + + void nxagentDumpClipboardStat(void) { char *s = NULL; @@ -310,7 +340,6 @@ void nxagentDumpClipboardStat(void) fprintf(stderr, " nxagentMaxSelections (int) [%d]\n", nxagentMaxSelections); fprintf(stderr, " NumCurrentSelections (int) [%d]\n", NumCurrentSelections); fprintf(stderr, " serverWindow (Window) [0x%x]\n", serverWindow); - fprintf(stderr, " nxagentLastClipboardClient (int) [%d]\n", nxagentLastClipboardClient); fprintf(stderr, " Clipboard mode "); switch(nxagentOption(Clipboard)) @@ -331,31 +360,12 @@ void nxagentDumpClipboardStat(void) fprintf(stderr, " lastServerTarget (Atom) [% 4ld][%s]\n", lastServerTarget, validateString(s)); fprintf(stderr, " lastServerTime (Time) [%u]\n", lastServerTime); - fprintf(stderr, "lastClient\n"); - if (lastClientWindowPtr) - fprintf(stderr, " lastClientWindowPtr (WindowPtr) [%p] ([0x%x])\n", (void *)lastClientWindowPtr, WINDOWID(lastClientWindowPtr)); - else - fprintf(stderr, " lastClientWindowPtr (WindowPtr) -\n"); - fprintf(stderr, " lastClientClientPtr (ClientPtr) %s\n", nxagentClientInfoString(lastClientClientPtr)); - fprintf(stderr, " lastClientRequestor (Window) [0x%x]\n", lastClientRequestor); - fprintf(stderr, " lastClientProperty (Atom) [% 4d][%s]\n", lastClientProperty, NameForAtom(lastClientProperty)); - fprintf(stderr, " lastClientSelection (Atom) [% 4d][%s]\n", lastClientSelection, NameForAtom(lastClientSelection)); - fprintf(stderr, " lastClientTarget (Atom) [% 4d][%s]\n", lastClientTarget, NameForAtom(lastClientTarget)); - if (lastClientTime > 0) - fprintf(stderr, " lastClientTime (Time) [%u] ([%u]ms ago)\n", lastClientTime, GetTimeInMillis() - lastClientTime); - else - fprintf(stderr, " lastClientTime (Time) [%u]\n", lastClientTime); - if (lastClientReqTime > 0) - fprintf(stderr, " lastClientReqTime (Time) [%u] ([%u]ms ago)\n", lastClientReqTime, GetTimeInMillis() - lastClientReqTime); - else - fprintf(stderr, " lastClientReqTime (Time) [%u]\n", lastClientReqTime); - fprintf(stderr, " lastClientPropertySize (unsigned long) [%lu]\n", lastClientPropertySize); - fprintf(stderr, " lastClientStage (ClientSelectionStage) [%d][%s]\n", lastClientStage, getClientSelectionStageString(lastClientStage)); - fprintf(stderr, "PRIMARY\n"); printSelectionStat(nxagentPrimarySelection); + printLastClientStat(nxagentPrimarySelection); fprintf(stderr, "CLIPBOARD\n"); printSelectionStat(nxagentClipboardSelection); + printLastClientStat(nxagentClipboardSelection); fprintf(stderr, "Atoms (remote X server)\n"); SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTARGETS); @@ -392,34 +402,49 @@ void nxagentDumpClipboardStat(void) /* * Helper to handle data transfer */ -static void setClientSelectionStage(int stage) +static void resetClientSelectionStage(int index) { - if (lastClientStage == stage) + #ifdef DEBUG + fprintf(stderr, "%s: Resetting selection stage for [%d]\n", __func__, index); + #endif + + lastClients[index].stage = SelectionStageNone; + lastClients[index].windowPtr = NULL; + lastClients[index].clientPtr = NULL; + lastClients[index].requestor = 0; + lastClients[index].property = 0; + /* NX_PRIMARY or clipboard atom */ + lastClients[index].selection = lastSelectionOwner[index].selection; + lastClients[index].target = 0; + lastClients[index].time = 0; + lastClients[index].reqTime = 0; + lastClients[index].propertySize = 0; + lastClients[index].resource = -1; +} + +static void setClientSelectionStage(int stage, int index) +{ + if (lastClients[index].stage == stage) { #ifdef DEBUG - fprintf(stderr, "%s: selection stage already set to [%s] - doing nothing\n", __func__, - getClientSelectionStageString(lastClientStage)); + fprintf(stderr, "%s: lastClient [%d] selection stage already set to [%s] - doing nothing\n", __func__, + index, getClientSelectionStageString(lastClients[index].stage)); #endif return; } #ifdef DEBUG - fprintf(stderr, "%s: Changing selection stage from [%s] to [%s]\n", __func__, - getClientSelectionStageString(lastClientStage), getClientSelectionStageString(stage)); + fprintf(stderr, "%s: Changing selection stage for [%d] from [%s] to [%s]\n", __func__, index, + getClientSelectionStageString(lastClients[index].stage), getClientSelectionStageString(stage)); #endif - lastClientStage = stage; if (stage == SelectionStageNone) { - lastClientWindowPtr = NULL; - lastClientClientPtr = NULL; - lastClientRequestor = 0; - lastClientProperty = 0; - lastClientSelection = 0; - lastClientTarget = 0; - lastClientTime = 0; - lastClientReqTime = 0; - lastClientPropertySize = 0; + resetClientSelectionStage(index); + } + else + { + lastClients[index].stage = stage; } } @@ -629,21 +654,21 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) if (matchSelectionOwner(i, pClient, pWindow)) { #ifdef TEST - fprintf(stderr, "%s: Resetting state with client [%p] window [%p].\n", __func__, - (void *) pClient, (void *) pWindow); + fprintf(stderr, "%s: Resetting state [%d] with client [%p] window [%p].\n", __func__, + i, (void *) pClient, (void *) pWindow); #endif clearSelectionOwner(i); - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(SelectionStageNone, i); lastServerRequestor = None; } - } - if (pWindow && pWindow == lastClientWindowPtr) - { - setClientSelectionStage(SelectionStageNone); + if (pWindow && pWindow == lastClients[i].windowPtr) + { + setClientSelectionStage(SelectionStageNone, i); + } } } @@ -728,9 +753,9 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) CurrentSelections[i].client = NullClient; clearSelectionOwner(i); - } - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(SelectionStageNone, i); + } } /* @@ -933,31 +958,32 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) if (i < nxagentMaxSelections) { #if 0 - if (lastClientWindowPtr != NULL && IS_INTERNAL_OWNER(i)) + if (lastClients[i].windowPtr != NULL && IS_INTERNAL_OWNER(i)) { /* * Request the real X server to transfer the selection content * to the NX_CUT_BUFFER_SERVER property of the serverWindow. - * FIXME: document how we can end up here - * - * It looks like this is only reached when the real X server is - * on Windows. I suspect that this is connected to the windows X - * server (VcXSrv in my test) pushing PRIMARY or CLIPBOARD - * content to the Windows clipboard whenever they change. + * We reach here as follows: + * - mark someting in the nx session + * -> nxagent claims ownership of PRIMARY on real X server + * - at the same time paste _clipboard_ to the client (now) owning primary + * ->vcxsrv will ask for primary contents to store them to Windows clipboard + * - vcxsrv request is for _primary_ and takes this path as the _clipboard_ transfer + * has set lastClients[i].windowPtr */ XConvertSelection(nxagentDisplay, CurrentSelections[i].selection, X->xselectionrequest.target, serverTransToAgentProperty, - serverWindow, lastClientTime); + serverWindow, lastClients[i].time); #ifdef DEBUG char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[i].selection); char *strProperty = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, - CurrentSelections[i].selection, strSelection, - X->xselectionrequest.target, strTarget, - serverTransToAgentProperty, strProperty, - serverWindow, lastClientTime); + CurrentSelections[i].selection, strSelection, + X->xselectionrequest.target, strTarget, + serverTransToAgentProperty, strProperty, + serverWindow, lastClients[i].time); #endif SAFE_XFree(strTarget); SAFE_XFree(strSelection); @@ -973,8 +999,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * content to the real X server. */ if (IS_INTERNAL_OWNER(i) && - (nxagentOption(Clipboard) == ClipboardServer || - nxagentOption(Clipboard) == ClipboardBoth)) + (nxagentOption(Clipboard) == ClipboardServer || + nxagentOption(Clipboard) == ClipboardBoth)) { /* * store who on the real X server requested the data and how @@ -1039,12 +1065,12 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * denied/failed" * Use SELECTION_SUCCESS and SELECTION_FAULT macros for success. */ -static void endTransfer(Bool success) +static void endTransfer(Bool success, int index) { - if (lastClientClientPtr == NULL) + if (lastClients[index].clientPtr == NULL) { #ifdef DEBUG - fprintf(stderr, "%s: lastClientClientPtr is NULL - doing nothing.\n", __func__); + fprintf(stderr, "%s: lastClients[%d].clientPtr is NULL - doing nothing.\n", __func__, index); #endif } else @@ -1052,56 +1078,64 @@ static void endTransfer(Bool success) #ifdef DEBUG if (success == SELECTION_SUCCESS) fprintf(stderr, "%s: sending notification to client %s, property [%d][%s]\n", __func__, - nxagentClientInfoString(lastClientClientPtr), lastClientProperty, NameForAtom(lastClientProperty)); + nxagentClientInfoString(lastClients[index].clientPtr), lastClients[index].property, NameForAtom(lastClients[index].property)); else fprintf(stderr, "%s: sending negative notification to client %s\n", __func__, - nxagentClientInfoString(lastClientClientPtr)); + nxagentClientInfoString(lastClients[index].clientPtr)); #endif - sendSelectionNotifyEventToClient(lastClientClientPtr, - lastClientTime, - lastClientRequestor, - lastClientSelection, - lastClientTarget, - success == SELECTION_SUCCESS ? lastClientProperty : None); + sendSelectionNotifyEventToClient(lastClients[index].clientPtr, + lastClients[index].time, + lastClients[index].requestor, + lastClients[index].selection, + lastClients[index].target, + success == SELECTION_SUCCESS ? lastClients[index].property : None); } /* * Enable further requests from clients. */ - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(SelectionStageNone, index); } -static void transferSelection(int resource) +static void transferSelection(int resource, int index) { - if (lastClientClientPtr -> index != resource) + #ifdef DEBUG + fprintf(stderr, "%s: resource [%d] lastClients[%d].clientPtr->index [%d].\n", __func__, + resource, index, lastClients[index].clientPtr -> index); + #endif + /* FIXME: can we use this instead of lastClients[index].resource? */ + if (lastClients[index].clientPtr -> index != resource) { #ifdef DEBUG fprintf (stderr, "%s: WARNING! Inconsistent resource [%d] with current client %s.\n", __func__, - resource, nxagentClientInfoString(lastClientClientPtr)); + resource, nxagentClientInfoString(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); return; } - switch (lastClientStage) + switch (lastClients[index].stage) { case SelectionStageQuerySize: { int result; - printClientSelectionStage(); + printClientSelectionStage(index); /* * Don't get data yet, just get size. We skip this stage in * current implementation and go straight to the data. */ - nxagentLastClipboardClient = NXGetCollectPropertyResource(nxagentDisplay); + /* get next free resource index */ + int free_resource = NXGetCollectPropertyResource(nxagentDisplay); + + lastClients[index].resource = free_resource; - if (nxagentLastClipboardClient == -1) + if (free_resource == -1) { #ifdef WARNING fprintf(stderr, "%s: WARNING! Asynchronous GetProperty queue full.\n", __func__); @@ -1111,8 +1145,9 @@ static void transferSelection(int resource) } else { + /* collect property and store with index "resource" */ result = NXCollectProperty(nxagentDisplay, - nxagentLastClipboardClient, + free_resource, serverWindow, serverTransToAgentProperty, 0, @@ -1125,15 +1160,15 @@ static void transferSelection(int resource) { #ifdef DEBUG fprintf (stderr, "%s: Aborting selection notify procedure for client %s.\n", __func__, - nxagentClientInfoString(lastClientClientPtr)); + nxagentClientInfoString(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); return; } - setClientSelectionStage(SelectionStageWaitSize); + setClientSelectionStage(SelectionStageWaitSize, index); NXFlushDisplay(nxagentDisplay, NXFlushLink); @@ -1143,7 +1178,7 @@ static void transferSelection(int resource) { int result; - printClientSelectionStage(); + printClientSelectionStage(index); /* * Request the selection data now. @@ -1153,9 +1188,12 @@ static void transferSelection(int resource) fprintf(stderr, "%s: Getting property content from remote server.\n", __func__); #endif - nxagentLastClipboardClient = NXGetCollectPropertyResource(nxagentDisplay); + /* get next free resouce index */ + resource = NXGetCollectPropertyResource(nxagentDisplay); + + lastClients[index].resource = resource; - if (nxagentLastClipboardClient == -1) + if (resource == -1) { #ifdef WARNING fprintf(stderr, "%s: WARNING! Asynchronous GetProperty queue full.\n", __func__); @@ -1166,11 +1204,11 @@ static void transferSelection(int resource) else { result = NXCollectProperty(nxagentDisplay, - nxagentLastClipboardClient, + resource, serverWindow, serverTransToAgentProperty, 0, - lastClientPropertySize, + lastClients[index].propertySize, False, AnyPropertyType); } @@ -1179,15 +1217,15 @@ static void transferSelection(int resource) { #ifdef DEBUG fprintf (stderr, "%s: Aborting selection notify procedure for client %s.\n", __func__, - nxagentClientInfoString(lastClientClientPtr)); + nxagentClientInfoString(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); return; } - setClientSelectionStage(SelectionStageWaitData); + setClientSelectionStage(SelectionStageWaitData, index); /* we've seen situations where you had to move the mouse or press a key to let the transfer complete. Flushing here fixed it */ @@ -1198,8 +1236,9 @@ static void transferSelection(int resource) default: { #ifdef DEBUG - fprintf (stderr, "%s: WARNING! Inconsistent state [%s] for client %s.\n", __func__, - getClientSelectionStageString(lastClientStage), nxagentClientInfoString(lastClientClientPtr)); + fprintf (stderr, "%s: WARNING! Inconsistent state [%s] for selection [%d] for client %s.\n", __func__, + getClientSelectionStageString(lastClients[index].stage), index, + nxagentClientInfoString(lastClients[index].clientPtr)); #endif break; @@ -1208,13 +1247,16 @@ static void transferSelection(int resource) } /* - Called from Events.c/nxagentHandlePropertyNotify - + Called from Events.c/nxagentHandleCollectPropertyEvent This event is generated after XChangeProperty(), XDeleteProperty() or XGetWindowProperty(delete=True) + + Returncode: + True: processed + False: not processed, resource is not ours */ -void nxagentCollectPropertyEvent(int resource) +Bool nxagentCollectPropertyEvent(int resource) { XlibAtom atomReturnType; int resultFormat; @@ -1222,6 +1264,28 @@ void nxagentCollectPropertyEvent(int resource) unsigned long ulReturnBytesLeft; unsigned char *pszReturnData = NULL; + int index = 0; + + /* determine the selection we are talking about here */ + for (index = 0; index < nxagentMaxSelections; index++) + { + #ifdef DEBUG + fprintf(stderr, "%s: lastClients[%d].resource [%d] resource [%d]\n", __func__, index, lastClients[index].resource, resource); + #endif + if (lastClients[index].resource == resource) + { + break; + } + } + + if (index == nxagentMaxSelections) + { + #ifdef DEBUG + fprintf (stderr, "%s: resource does not belong to any selection we handle.\n", __func__); + #endif + return False; + } + /* * We have received the notification so we can safely retrieve data * from the client structure. @@ -1235,7 +1299,7 @@ void nxagentCollectPropertyEvent(int resource) &ulReturnBytesLeft, &pszReturnData); - nxagentLastClipboardClient = -1; + lastClients[index].resource = -1; if (result == 0) { @@ -1243,25 +1307,26 @@ void nxagentCollectPropertyEvent(int resource) fprintf (stderr, "%s: Failed to get reply data.\n", __func__); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } else if (resultFormat != 8 && resultFormat != 16 && resultFormat != 32) { #ifdef DEBUG - fprintf (stderr, "%s: WARNING! Invalid property format.\n", __func__); + fprintf(stderr, "%s: WARNING! Invalid property format.\n", __func__); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } else { - switch (lastClientStage) + switch (lastClients[index].stage) { case SelectionStageWaitSize: { - printClientSelectionStage(); + printClientSelectionStage(index); #ifdef DEBUG - fprintf (stderr, "%s: Got size notify event for client %s.\n", __func__, nxagentClientInfoString(lastClientClientPtr)); + fprintf (stderr, "%s: Got size notify event for client %s.\n", __func__, + nxagentClientInfoString(lastClients[index].clientPtr)); #endif if (ulReturnBytesLeft == 0) @@ -1270,7 +1335,7 @@ void nxagentCollectPropertyEvent(int resource) fprintf (stderr, "%s: data size is [0] - aborting selection notify procedure.\n", __func__); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } else { @@ -1281,18 +1346,19 @@ void nxagentCollectPropertyEvent(int resource) /* * Request the selection data now. */ - lastClientPropertySize = ulReturnBytesLeft; - setClientSelectionStage(SelectionStageQueryData); + lastClients[index].propertySize = ulReturnBytesLeft; + setClientSelectionStage(SelectionStageQueryData, index); - transferSelection(resource); + transferSelection(resource, index); } break; } case SelectionStageWaitData: { - printClientSelectionStage(); + printClientSelectionStage(index); #ifdef DEBUG - fprintf (stderr, "%s: Got data notify event for waiting client %s.\n", __func__, nxagentClientInfoString(lastClientClientPtr)); + fprintf (stderr, "%s: Got data notify event for waiting client %s.\n", __func__, + nxagentClientInfoString(lastClients[index].clientPtr)); #endif if (ulReturnBytesLeft != 0) @@ -1301,7 +1367,7 @@ void nxagentCollectPropertyEvent(int resource) fprintf (stderr, "%s: not all content could be retrieved - [%lu] bytes left - aborting selection notify procedure.\n", __func__, ulReturnBytesLeft); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } else { @@ -1309,35 +1375,39 @@ void nxagentCollectPropertyEvent(int resource) fprintf(stderr, "%s: Got property content from remote server. size [%lu] bytes.\n", __func__, (ulReturnItems * resultFormat / 8)); #endif - ChangeWindowProperty(lastClientWindowPtr, - lastClientProperty, - lastClientTarget, + ChangeWindowProperty(lastClients[index].windowPtr, + lastClients[index].property, + lastClients[index].target, resultFormat, PropModeReplace, ulReturnItems, pszReturnData, 1); #ifdef DEBUG fprintf(stderr, "%s: Selection property [%d][%s] changed to [\"%*.*s\"...]\n", __func__, - lastClientProperty, validateString(NameForAtom(lastClientProperty)), - (int)(min(20, ulReturnItems * resultFormat / 8)), + lastClients[index].property, + validateString(NameForAtom(lastClients[index].property)), (int)(min(20, ulReturnItems * resultFormat / 8)), - pszReturnData); + (int)(min(20, ulReturnItems * resultFormat / 8)), + pszReturnData); #endif - endTransfer(SELECTION_SUCCESS); + endTransfer(SELECTION_SUCCESS, index); } break; } default: { #ifdef DEBUG - fprintf (stderr, "%s: WARNING! Inconsistent state [%s] for client %s.\n", __func__, - getClientSelectionStageString(lastClientStage), nxagentClientInfoString(lastClientClientPtr)); + fprintf(stderr, "%s: WARNING! Inconsistent state [%s] for client %s.\n", __func__, + getClientSelectionStageString(lastClients[index].stage), + nxagentClientInfoString(lastClients[index].clientPtr)); #endif break; } } } SAFE_XFree(pszReturnData); + + return True; } /* @@ -1362,19 +1432,42 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) char * t = XGetAtomName(nxagentDisplay, e->target); char * s = XGetAtomName(nxagentDisplay, e->selection); fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ - "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", - __func__, e->property, validateString(p), e->requestor, - validateString(s), e->target, - validateString(t), e->time, e->send_event); + "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", + __func__, e->property, validateString(p), e->requestor, + validateString(s), e->target, + validateString(t), e->time, e->send_event); SAFE_XFree(p); SAFE_XFree(t); SAFE_XFree(s); } #endif - printClientSelectionStage(); + /* determine the selection we are talking about here */ + int index = 0; + for (index = 0; index < nxagentMaxSelections; index++) + { + #ifdef DEBUG + fprintf (stderr, "%s: lastClients[%d].selection [%d] selection [%d] .\n", + __func__, index, lastClients[index].selection, + nxagentRemoteToLocalAtom(e->selection)); + #endif + if (lastClients[index].selection == nxagentRemoteToLocalAtom(e->selection)) + { + break; + } + } + + if (index == nxagentMaxSelections) + { + #ifdef DEBUG + fprintf (stderr, "%s: unknown selection [%ld] .\n", __func__, e->selection); + #endif + return; + } - if (lastClientWindowPtr != NULL) + printClientSelectionStage(index); + + if (lastClients[index].windowPtr != NULL) { /* * We reach here after a paste inside the nxagent, triggered by @@ -1382,19 +1475,19 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * means that data we need has been transferred to the * serverTransToAgentProperty of the serverWindow (our window on * the real X server). We now need to transfer it to the original - * requestor, which is stored in the lastClient* variables. + * requestor, which is stored in the lastClients[index].* variables. */ #ifdef DEBUG nxagentDumpClipboardStat(); #endif - if (lastClientStage == SelectionStageNone) + if (lastClients[index].stage == SelectionStageNone) { if (X->xselection.property == serverTransToAgentProperty) { #ifdef DEBUG fprintf(stderr, "%s: Starting selection transferral for client %s.\n", __func__, - nxagentClientInfoString(lastClientClientPtr)); + nxagentClientInfoString(lastClients[index].clientPtr)); #endif /* @@ -1408,18 +1501,18 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * tions. */ - setClientSelectionStage(SelectionStageQueryData); - lastClientPropertySize = 262144; + setClientSelectionStage(SelectionStageQueryData, index); + lastClients[index].propertySize = 262144; - transferSelection(lastClientClientPtr -> index); + transferSelection(lastClients[index].clientPtr -> index, index); } else if (X->xselection.property == 0) { #ifdef DEBUG fprintf(stderr, "%s: WARNING! Resetting selection transferral for client [%d] because of failure notification from real X server.\n", __func__, - CLINDEX(lastClientClientPtr)); + CLINDEX(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } else { @@ -1429,17 +1522,17 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) __func__, X->xselection.property, s); SAFE_XFree(s); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } } else { #ifdef DEBUG fprintf(stderr, "%s: WARNING! Resetting selection transferral for client [%d] because of unexpected stage.\n", __func__, - CLINDEX(lastClientClientPtr)); + CLINDEX(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); } } else @@ -1596,9 +1689,9 @@ static void resetSelectionOwner(void) #endif clearSelectionOwner(i); - } - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(SelectionStageNone, i); + } /* Hmm, this is already None when reaching this */ lastServerRequestor = None; @@ -1743,9 +1836,9 @@ static void setSelectionOwner(Selection *pSelection) * owner window. */ storeSelectionOwner(i, pSelection); - } - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(SelectionStageNone, i); + } lastServerRequestor = None; @@ -1795,34 +1888,40 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 0; } + int index = nxagentFindCurrentSelectionIndex(selection); + if (index == NumCurrentSelections) { - int i = nxagentFindCurrentSelectionIndex(selection); - if (i < NumCurrentSelections && IS_INTERNAL_OWNER(i)) - { - /* - * There is a client owner on the agent side, let normal dix stuff happen. - */ - return 0; - } + #ifdef DEBUG + fprintf(stderr, "%s: cannot find index for selection [%u]\n", __func__, selection); + #endif + return 0; + } + + if (IS_INTERNAL_OWNER(index)) + { + /* + * There is a client owner on the agent side, let normal dix stuff happen. + */ + return 0; } /* - * if lastClientWindowPtr is set we are waiting for an answer from + * if lastClients[index].windowPtr is set we are waiting for an answer from * the real X server. If that answer takes more than 5 seconds we * consider the conversion failed and tell our client about that. * The new request that lead us here is then processed. */ - if (lastClientWindowPtr != NULL) + if (lastClients[index].windowPtr != NULL) { #ifdef TEST - fprintf(stderr, "%s: lastClientWindowPtr != NULL.\n", __func__); + fprintf(stderr, "%s: lastClients[%d].windowPtr != NULL.\n", __func__, index); #endif #ifdef DEBUG - fprintf(stderr, "%s: lastClientSelection [%d] - selection [%d]\n", __func__, lastClientSelection, selection); + fprintf(stderr, "%s: lastClients[%d].selection [%d] - selection [%d]\n", __func__, index, lastClients[index].selection, selection); #endif - if ((GetTimeInMillis() - lastClientReqTime) >= CONVERSION_TIMEOUT) + if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) { #ifdef DEBUG fprintf(stderr, "%s: timeout expired on last request, " @@ -1830,7 +1929,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif /* notify the waiting client of failure */ - endTransfer(SELECTION_FAULT); + endTransfer(SELECTION_FAULT, index); + return 1; } else { @@ -1883,8 +1983,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #ifdef DEBUG fprintf(stderr, "%s: available targets [%d]:\n", __func__, numTargets); - for (int i = 0; i < numTargets; i++) - fprintf(stderr, "%s: %s\n", __func__, NameForAtom(targets[i])); + for (int j = 0; j < numTargets; j++) + fprintf(stderr, "%s: %s\n", __func__, NameForAtom(targets[j])); fprintf(stderr, "\n"); #endif @@ -1914,52 +2014,43 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, */ if (target == clientTIMESTAMP) { - int i = nxagentFindCurrentSelectionIndex(selection); - if (i < NumCurrentSelections) - { - /* - * "If the specified property is not None, the owner should place - * the data resulting from converting the selection into the - * specified property on the requestor window and should set the - * property's type to some appropriate value, which need not be - * the same as the specified target." - */ - ChangeWindowProperty(pWin, - property, - XA_INTEGER, - 32, - PropModeReplace, - 1, - (unsigned char *) &lastSelectionOwner[i].lastTimeChanged, - 1); - - sendSelectionNotifyEventToClient(client, time, requestor, selection, target, property); - - return 1; - } + /* + * "If the specified property is not None, the owner should place + * the data resulting from converting the selection into the + * specified property on the requestor window and should set the + * property's type to some appropriate value, which need not be + * the same as the specified target." + */ + ChangeWindowProperty(pWin, + property, + XA_INTEGER, + 32, + PropModeReplace, + 1, + (unsigned char *) &lastSelectionOwner[index].lastTimeChanged, + 1); + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, property); + return 1; } - if (lastClientClientPtr == client && (GetTimeInMillis() - lastClientReqTime < ACCUM_TIME)) + if (lastClients[index].clientPtr == client && (GetTimeInMillis() - lastClients[index].reqTime < ACCUM_TIME)) { /* * The same client made consecutive requests of clipboard content * with less than 5 seconds time interval between them. - * FIXME: this does not take the selection into account, so a - * client requesting PRIMARY and CLIPBOARD would match here, too */ - - #ifdef DEBUG - fprintf(stderr, "%s: Consecutives request from client %s selection [%u] " + #ifdef DEBUG + fprintf(stderr, "%s: Consecutives request from client %s selection [%u] " "elapsed time [%u] clientAccum [%d]\n", __func__, nxagentClientInfoString(client), - selection, GetTimeInMillis() - lastClientReqTime, clientAccum); - #endif + selection, GetTimeInMillis() - lastClients[index].reqTime, clientAccum); + #endif - clientAccum++; + clientAccum++; } else { /* reset clientAccum as now another client requested the clipboard content */ - if (lastClientClientPtr != client) + if (lastClients[index].clientPtr != client) { clientAccum = 0; } @@ -1970,23 +2061,22 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, target == clientCOMPOUND_TEXT || target == clientUTF8_STRING) { - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(SelectionStageNone, index); /* * store the original requestor, we need that later after * serverTransToAgentProperty contains the desired selection content */ - lastClientRequestor = requestor; - lastClientWindowPtr = pWin; - lastClientClientPtr = client; - lastClientTime = time; - lastClientProperty = property; - lastClientSelection = selection; - lastClientTarget = target; - + lastClients[index].requestor = requestor; + lastClients[index].windowPtr = pWin; + lastClients[index].clientPtr = client; + lastClients[index].time = time; + lastClients[index].property = property; + lastClients[index].selection = selection; + lastClients[index].target = target; /* if the last client request time is more than 5s ago update it. Why? */ - if ((GetTimeInMillis() - lastClientReqTime) >= CONVERSION_TIMEOUT) - lastClientReqTime = GetTimeInMillis(); + if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) + lastClients[index].reqTime = GetTimeInMillis(); if (selection == clientCLIPBOARD) { @@ -2044,6 +2134,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 1; } + return 0; } @@ -2236,6 +2327,14 @@ Bool nxagentInitClipboard(WindowPtr pWin) } initSelectionOwner(nxagentPrimarySelection, XA_PRIMARY); initSelectionOwner(nxagentClipboardSelection, nxagentAtoms[10]); /* CLIPBOARD */ + + SAFE_free(lastClients); + + lastClients = (lastClient *) malloc(nxagentMaxSelections * sizeof(lastClient)); + if (lastClients == NULL) + { + FatalError("nxagentInitClipboard: Failed to allocate memory for the last client array.\n"); + } } else { @@ -2342,20 +2441,20 @@ Bool nxagentInitClipboard(WindowPtr pWin) } } } - /* FIXME: Shouldn't we reset lastServer* and lastClient* here? */ + /* FIXME: Shouldn't we reset lastServer* and lastClients[index].* here? */ } else { for (int i = 0; i < nxagentMaxSelections; i++) { clearSelectionOwner(i); + resetClientSelectionStage(i); + /* FIXME: required? move to setSelctionStage? */ + lastClients[i].reqTime = GetTimeInMillis(); } lastServerRequestor = None; - setClientSelectionStage(SelectionStageNone); - lastClientReqTime = GetTimeInMillis(); - clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h index d401dae51..18d0094d2 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h @@ -72,7 +72,7 @@ extern int nxagentFindCurrentSelectionIndex(Atom sel); * Handle the selection property received in the event loop in * Events.c. */ -extern void nxagentCollectPropertyEvent(int resource); +extern Bool nxagentCollectPropertyEvent(int resource); extern WindowPtr nxagentGetClipboardWindow(Atom property); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 2a3654731..0918073a9 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -131,8 +131,6 @@ extern Bool nxagentOnce; -extern int nxagentLastClipboardClient; - #ifdef NX_DEBUG_INPUT int nxagentDebugInput = 0; #endif @@ -3984,11 +3982,7 @@ void nxagentHandleCollectPropertyEvent(XEvent *X) return; } - if (resource == nxagentLastClipboardClient) - { - nxagentCollectPropertyEvent(resource); - } - else + if (!nxagentCollectPropertyEvent(resource)) { XlibAtom atomReturnType; int resultFormat; -- cgit v1.2.3 From 717661b1d6d3e0ecd30611121d12ac637878fe64 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 3 Oct 2020 00:21:46 +0200 Subject: Clipboard.c: improve function names once more --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 74 +++++++++++++------------- nx-X11/programs/Xserver/hw/nxagent/Clipboard.h | 2 +- nx-X11/programs/Xserver/hw/nxagent/Events.c | 2 +- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index b9af7e199..89d190451 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -237,15 +237,15 @@ static void setClientSelectionStage(int stage, int index); static void endTransfer(Bool success, int index); #define SELECTION_SUCCESS True #define SELECTION_FAULT False -static void transferSelection(int resource, int index); +static void transferSelectionFromXServer(int resource, int index); #if 0 -static void resetSelectionOwner(void); +static void resetSelectionOwnerOnXServer(void); #endif -static void initSelectionOwner(int index, Atom selection); -static void clearSelectionOwner(int index); -static void storeSelectionOwner(int index, Selection *sel); +static void initSelectionOwnerData(int index, Atom selection); +static void clearSelectionOwnerData(int index); +static void storeSelectionOwnerData(int index, Selection *sel); static Bool matchSelectionOwner(int index, ClientPtr pClient, WindowPtr pWindow); -static void setSelectionOwner(Selection *pSelection); +static void setSelectionOwnerOnXServer(Selection *pSelection); static int sendEventToClient(ClientPtr client, xEvent *pEvents); static void sendSelectionNotifyEventToClient(ClientPtr client, Time time, @@ -253,11 +253,11 @@ static void sendSelectionNotifyEventToClient(ClientPtr client, Atom selection, Atom target, Atom property); -static Status sendSelectionNotifyEventToServer(XSelectionEvent *event_to_send); +static Status sendSelectionNotifyEventToXServer(XSelectionEvent *event_to_send); #ifdef DEBUG static void printSelectionStat(int sel); #endif -static void replyRequestSelection(XEvent *X, Bool success); +static void replyRequestSelectionToXServer(XEvent *X, Bool success); void nxagentPrintClipboardStat(char *); @@ -461,7 +461,7 @@ int GetWindowProperty(WindowPtr pWin, Atom property, long longOffset, long longL * Send a SelectionNotify event to the real X server and do some error * handling (in DEBUG mode) */ -static Status sendSelectionNotifyEventToServer(XSelectionEvent *event_to_send) +static Status sendSelectionNotifyEventToXServer(XSelectionEvent *event_to_send) { Window w = event_to_send->requestor; @@ -600,7 +600,7 @@ static Bool validServerTargets(XlibAtom target) return False; } -static void initSelectionOwner(int index, Atom selection) +static void initSelectionOwnerData(int index, Atom selection) { lastSelectionOwner[index].selection = selection; lastSelectionOwner[index].client = NullClient; @@ -610,7 +610,7 @@ static void initSelectionOwner(int index, Atom selection) } /* there's no owner on nxagent side anymore */ -static void clearSelectionOwner(int index) +static void clearSelectionOwnerData(int index) { lastSelectionOwner[index].client = NULL; lastSelectionOwner[index].window = None; @@ -618,7 +618,7 @@ static void clearSelectionOwner(int index) lastSelectionOwner[index].lastTimeChanged = GetTimeInMillis(); } -static void storeSelectionOwner(int index, Selection *sel) +static void storeSelectionOwnerData(int index, Selection *sel) { lastSelectionOwner[index].client = sel->client; lastSelectionOwner[index].window = sel->window; @@ -658,7 +658,7 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) i, (void *) pClient, (void *) pWindow); #endif - clearSelectionOwner(i); + clearSelectionOwnerData(i); setClientSelectionStage(SelectionStageNone, i); @@ -752,7 +752,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) CurrentSelections[i].window = screenInfo.screens[0]->root->drawable.id; CurrentSelections[i].client = NullClient; - clearSelectionOwner(i); + clearSelectionOwnerData(i); setClientSelectionStage(SelectionStageNone, i); } @@ -763,7 +763,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) * event X. If success is True take the property from the event, else * take None (which reports "failed/denied" to the requestor). */ -static void replyRequestSelection(XEvent *X, Bool success) +static void replyRequestSelectionToXServer(XEvent *X, Bool success) { XSelectionEvent eventSelection = { .requestor = X->xselectionrequest.requestor, @@ -781,7 +781,7 @@ static void replyRequestSelection(XEvent *X, Bool success) eventSelection.property = None; } - sendSelectionNotifyEventToServer(&eventSelection); + sendSelectionNotifyEventToXServer(&eventSelection); } /* @@ -829,7 +829,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: denying additional request during transfer phase.\n", __func__); #endif - replyRequestSelection(X, False); + replyRequestSelectionToXServer(X, False); return; } @@ -842,7 +842,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); #endif - replyRequestSelection(X, False); + replyRequestSelectionToXServer(X, False); return; } } @@ -896,7 +896,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) (unsigned char*)&targets, numTargets); - replyRequestSelection(X, True); + replyRequestSelectionToXServer(X, True); } else if (X->xselectionrequest.target == serverTIMESTAMP) { @@ -926,7 +926,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) PropModeReplace, (unsigned char *) &lastSelectionOwner[i].lastTimeChanged, 1); - replyRequestSelection(X, True); + replyRequestSelectionToXServer(X, True); } } else @@ -938,7 +938,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) #ifdef DEBUG fprintf(stderr, "%s: unknown special target [%ld] - denying request.\n", __func__, X->xselectionrequest.target); #endif - replyRequestSelection(X, False); + replyRequestSelectionToXServer(X, False); } return; } @@ -1052,7 +1052,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else { /* deny the request */ - replyRequestSelection(X, False); + replyRequestSelectionToXServer(X, False); } } } @@ -1098,7 +1098,7 @@ static void endTransfer(Bool success, int index) setClientSelectionStage(SelectionStageNone, index); } -static void transferSelection(int resource, int index) +static void transferSelectionFromXServer(int resource, int index) { #ifdef DEBUG fprintf(stderr, "%s: resource [%d] lastClients[%d].clientPtr->index [%d].\n", __func__, @@ -1256,7 +1256,7 @@ static void transferSelection(int resource, int index) False: not processed, resource is not ours */ -Bool nxagentCollectPropertyEvent(int resource) +Bool nxagentCollectPropertyEventFromXServer(int resource) { XlibAtom atomReturnType; int resultFormat; @@ -1349,7 +1349,7 @@ Bool nxagentCollectPropertyEvent(int resource) lastClients[index].propertySize = ulReturnBytesLeft; setClientSelectionStage(SelectionStageQueryData, index); - transferSelection(resource, index); + transferSelectionFromXServer(resource, index); } break; } @@ -1504,7 +1504,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) setClientSelectionStage(SelectionStageQueryData, index); lastClients[index].propertySize = 262144; - transferSelection(lastClients[index].clientPtr -> index, index); + transferSelectionFromXServer(lastClients[index].clientPtr -> index, index); } else if (X->xselection.property == 0) { @@ -1644,7 +1644,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) (void *)eventSelection.requestor); #endif - sendSelectionNotifyEventToServer(&eventSelection); + sendSelectionNotifyEventToXServer(&eventSelection); lastServerRequestor = None; /* allow further request */ } @@ -1659,7 +1659,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * the real X server (or its clients) will be sent to this window. The * real X server never communicates with our windows directly. */ -static void resetSelectionOwner(void) +static void resetSelectionOwnerOnXServer(void) { if (lastServerRequestor != None) { @@ -1688,7 +1688,7 @@ static void resetSelectionOwner(void) fprintf(stderr, "%s: Reset selection state for selection [%d].\n", __func__, i); #endif - clearSelectionOwner(i); + clearSelectionOwnerData(i); setClientSelectionStage(SelectionStageNone, i); } @@ -1749,9 +1749,9 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, pCurSel->selection == clientCLIPBOARD)) { #ifdef DEBUG - fprintf(stderr, "%s: calling setSelectionOwner\n", __func__); + fprintf(stderr, "%s: calling setSelectionOwnerOnXServer\n", __func__); #endif - setSelectionOwner(pCurSel); + setSelectionOwnerOnXServer(pCurSel); } } else if (info->kind == SelectionWindowDestroy) @@ -1779,7 +1779,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, * This is called from the nxagentSetSelectionCallback, so it is using * internal Atoms */ -static void setSelectionOwner(Selection *pSelection) +static void setSelectionOwnerOnXServer(Selection *pSelection) { if (!agentClipboardInitialized) { @@ -1835,7 +1835,7 @@ static void setSelectionOwner(Selection *pSelection) * points to the struct that contains all information about the * owner window. */ - storeSelectionOwner(i, pSelection); + storeSelectionOwnerData(i, pSelection); setClientSelectionStage(SelectionStageNone, i); } @@ -2263,7 +2263,7 @@ int nxagentSendNotify(xEvent *event) NameForAtom(event->u.selectionNotify.property)); #endif - sendSelectionNotifyEventToServer(&eventSelection); + sendSelectionNotifyEventToXServer(&eventSelection); return 1; } @@ -2325,8 +2325,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) { FatalError("nxagentInitClipboard: Failed to allocate memory for the clipboard selections.\n"); } - initSelectionOwner(nxagentPrimarySelection, XA_PRIMARY); - initSelectionOwner(nxagentClipboardSelection, nxagentAtoms[10]); /* CLIPBOARD */ + initSelectionOwnerData(nxagentPrimarySelection, XA_PRIMARY); + initSelectionOwnerData(nxagentClipboardSelection, nxagentAtoms[10]); /* CLIPBOARD */ SAFE_free(lastClients); @@ -2447,7 +2447,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) { for (int i = 0; i < nxagentMaxSelections; i++) { - clearSelectionOwner(i); + clearSelectionOwnerData(i); resetClientSelectionStage(i); /* FIXME: required? move to setSelctionStage? */ lastClients[i].reqTime = GetTimeInMillis(); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h index 18d0094d2..f902bb50b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h @@ -72,7 +72,7 @@ extern int nxagentFindCurrentSelectionIndex(Atom sel); * Handle the selection property received in the event loop in * Events.c. */ -extern Bool nxagentCollectPropertyEvent(int resource); +extern Bool nxagentCollectPropertyEventFromXServer(int resource); extern WindowPtr nxagentGetClipboardWindow(Atom property); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 0918073a9..4e45e0d24 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -3982,7 +3982,7 @@ void nxagentHandleCollectPropertyEvent(XEvent *X) return; } - if (!nxagentCollectPropertyEvent(resource)) + if (!nxagentCollectPropertyEventFromXServer(resource)) { XlibAtom atomReturnType; int resultFormat; -- cgit v1.2.3 From 619236b9880f608e50b69fa5924a3a6e96942530 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 3 Oct 2020 00:48:27 +0200 Subject: Clipboard.c: reformat for better readability --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 89d190451..c0fe74c25 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -129,10 +129,10 @@ typedef struct _lastClient static lastClient *lastClients; -static Window lastServerRequestor; -static XlibAtom lastServerProperty; -static XlibAtom lastServerTarget; -static Time lastServerTime; +static Window lastServerRequestor; +static XlibAtom lastServerProperty; +static XlibAtom lastServerTarget; +static Time lastServerTime; static XlibAtom serverTARGETS; static XlibAtom serverTIMESTAMP; @@ -140,20 +140,20 @@ static XlibAtom serverTEXT; static XlibAtom serverCOMPOUND_TEXT; static XlibAtom serverUTF8_STRING; static XlibAtom serverTransFromAgentProperty; -static Atom clientTARGETS; -static Atom clientTIMESTAMP; -static Atom clientTEXT; -static Atom clientCOMPOUND_TEXT; -static Atom clientUTF8_STRING; -static Atom clientCLIPBOARD; - -static char szAgentTARGETS[] = "TARGETS"; -static char szAgentTEXT[] = "TEXT"; -static char szAgentTIMESTAMP[] = "TIMESTAMP"; -static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; -static char szAgentUTF8_STRING[] = "UTF8_STRING"; -static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; -static char szAgentCLIPBOARD[] = "CLIPBOARD"; +static Atom clientTARGETS; +static Atom clientTIMESTAMP; +static Atom clientTEXT; +static Atom clientCOMPOUND_TEXT; +static Atom clientUTF8_STRING; +static Atom clientCLIPBOARD; + +static char szAgentTARGETS[] = "TARGETS"; +static char szAgentTEXT[] = "TEXT"; +static char szAgentTIMESTAMP[] = "TIMESTAMP"; +static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; +static char szAgentUTF8_STRING[] = "UTF8_STRING"; +static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; +static char szAgentCLIPBOARD[] = "CLIPBOARD"; /* number of milliseconds to wait for a conversion from the real X server. */ #define CONVERSION_TIMEOUT 5000 @@ -505,11 +505,11 @@ static int sendEventToClient(ClientPtr client, xEvent *pEvents) } static void sendSelectionNotifyEventToClient(ClientPtr client, - Time time, - Window requestor, - Atom selection, - Atom target, - Atom property) + Time time, + Window requestor, + Atom selection, + Atom target, + Atom property) { /* * Check if the client is still valid. -- cgit v1.2.3 From 550742511cc6d546b3618c0944396767e53d3829 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 22 Sep 2020 21:36:03 +0200 Subject: Clipboard.c: rename selection fields to {int,rem}Selection This helps in avoiding storing the wrong value in a field. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 140 ++++++++++++++++--------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index c0fe74c25..f35ab583a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -79,11 +79,12 @@ const int nxagentMaxSelections = 2; typedef struct _SelectionOwner { - XlibAtom selection; /* _external_ Atom */ - ClientPtr client; /* internal client */ - Window window; /* internal window id */ - WindowPtr windowPtr; /* internal window struct */ - Time lastTimeChanged; /* internal time */ + ClientPtr client; /* internal client */ + Atom intSelection; /* internal Atom */ + XlibAtom remSelection; /* _external_ Atom */ + Window window; /* internal window id */ + WindowPtr windowPtr; /* internal window struct */ + Time lastTimeChanged; /* internal time */ } SelectionOwner; /* @@ -118,7 +119,7 @@ typedef struct _lastClient ClientPtr clientPtr; Window requestor; Atom property; - Atom selection; + Atom intSelection; Atom target; Time time; Time reqTime; @@ -241,7 +242,7 @@ static void transferSelectionFromXServer(int resource, int index); #if 0 static void resetSelectionOwnerOnXServer(void); #endif -static void initSelectionOwnerData(int index, Atom selection); +static void initSelectionOwnerData(int index, Atom intSelection, XlibAtom remSelection); static void clearSelectionOwnerData(int index); static void storeSelectionOwnerData(int index, Selection *sel); static Bool matchSelectionOwner(int index, ClientPtr pClient, WindowPtr pWindow); @@ -281,11 +282,9 @@ static void printSelectionStat(int sel) fprintf(stderr, " lastSelectionOwner[].windowPtr -\n"); fprintf(stderr, " lastSelectionOwner[].lastTimeChanged [%u]\n", lOwner.lastTimeChanged); - /* - print the selection name. selection is _always_ a a remote Atom! - */ - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, lOwner.selection); - fprintf(stderr, " lastSelectionOwner[].selection [% 4ld][%s] (%s)\n", lOwner.selection, validateString(s), lOwner.client ? "inside nxagent" : "remote X server"); + fprintf(stderr, " lastSelectionOwner[].intSelection [% 4d][%s] (%s)\n", lOwner.intSelection, validateString(NameForAtom(lOwner.intSelection)), "inside nxagent"); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, lOwner.remSelection); + fprintf(stderr, " lastSelectionOwner[].remSelection [% 4ld][%s] (%s)\n", lOwner.remSelection, validateString(s), "remote X server"); SAFE_XFree(s); #ifdef CLIENTIDS fprintf(stderr, " CurrentSelections[].client [%p] index [%d] PID [%d] Cmd [%s]\n", @@ -312,7 +311,7 @@ static void printLastClientStat(int index) fprintf(stderr, " lastClients[].clientPtr (ClientPtr) %s\n", nxagentClientInfoString(lc.clientPtr)); fprintf(stderr, " lastClients[].requestor (Window) [0x%x]\n", lc.requestor); fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForAtom(lc.property)); - fprintf(stderr, " lastClients[].selection (Atom) [% 4d][%s]\n", lc.selection, NameForAtom(lc.selection)); + fprintf(stderr, " lastClients[].intSelection (Atom) [% 4d][%s]\n", lc.intSelection, NameForAtom(lc.intSelection)); fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForAtom(lc.target)); if (lc.time > 0) fprintf(stderr, " lastClients[].time (Time) [%u] ([%u]ms ago)\n", lc.time, GetTimeInMillis() - lc.time); @@ -414,7 +413,8 @@ static void resetClientSelectionStage(int index) lastClients[index].requestor = 0; lastClients[index].property = 0; /* NX_PRIMARY or clipboard atom */ - lastClients[index].selection = lastSelectionOwner[index].selection; + /* FIXME: we should only set the once on init and then never touch it again */ + lastClients[index].intSelection = lastSelectionOwner[index].intSelection; lastClients[index].target = 0; lastClients[index].time = 0; lastClients[index].reqTime = 0; @@ -600,9 +600,10 @@ static Bool validServerTargets(XlibAtom target) return False; } -static void initSelectionOwnerData(int index, Atom selection) +static void initSelectionOwnerData(int index, Atom intSelection, XlibAtom remSelection) { - lastSelectionOwner[index].selection = selection; + lastSelectionOwner[index].intSelection = intSelection; + lastSelectionOwner[index].remSelection = remSelection; lastSelectionOwner[index].client = NullClient; lastSelectionOwner[index].window = screenInfo.screens[0]->root->drawable.id; lastSelectionOwner[index].windowPtr = NULL; @@ -680,7 +681,7 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { int i = 0; while (i < nxagentMaxSelections && - lastSelectionOwner[i].selection != sel) + lastSelectionOwner[i].remSelection != sel) { i++; } @@ -1087,7 +1088,7 @@ static void endTransfer(Bool success, int index) sendSelectionNotifyEventToClient(lastClients[index].clientPtr, lastClients[index].time, lastClients[index].requestor, - lastClients[index].selection, + lastClients[index].intSelection, lastClients[index].target, success == SELECTION_SUCCESS ? lastClients[index].property : None); } @@ -1447,11 +1448,11 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) for (index = 0; index < nxagentMaxSelections; index++) { #ifdef DEBUG - fprintf (stderr, "%s: lastClients[%d].selection [%d] selection [%d] .\n", - __func__, index, lastClients[index].selection, - nxagentRemoteToLocalAtom(e->selection)); + fprintf (stderr, "%s: lastClients[%d].intSelection [%d] selection [%d] .\n", + __func__, index, lastClients[index].intSelection, + nxagentRemoteToLocalAtom(e->selection)); #endif - if (lastClients[index].selection == nxagentRemoteToLocalAtom(e->selection)) + if (lastClients[index].intSelection == nxagentRemoteToLocalAtom(e->selection)) { break; } @@ -1682,7 +1683,7 @@ static void resetSelectionOwnerOnXServer(void) for (int i = 0; i < nxagentMaxSelections; i++) { - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].remSelection, serverWindow, CurrentTime); #ifdef DEBUG fprintf(stderr, "%s: Reset selection state for selection [%d].\n", __func__, i); @@ -1827,7 +1828,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * inform the real X server that our serverWindow is the * clipboard owner. */ - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].remSelection, serverWindow, CurrentTime); /* * The real owner window (inside nxagent) is stored in @@ -1918,7 +1919,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif #ifdef DEBUG - fprintf(stderr, "%s: lastClients[%d].selection [%d] - selection [%d]\n", __func__, index, lastClients[index].selection, selection); + fprintf(stderr, "%s: lastClients[%d].intSelection [%d] - selection [%d]\n", __func__, index, lastClients[index].intSelection, selection); #endif if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) @@ -2072,50 +2073,75 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, lastClients[index].clientPtr = client; lastClients[index].time = time; lastClients[index].property = property; - lastClients[index].selection = selection; + lastClients[index].intSelection = selection; lastClients[index].target = target; /* if the last client request time is more than 5s ago update it. Why? */ if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) lastClients[index].reqTime = GetTimeInMillis(); - if (selection == clientCLIPBOARD) + XlibAtom remSelection = 0; + + /* FIXME: we should use/have a function for stuff like that */ + if (selection == XA_PRIMARY) + { + remSelection = XA_PRIMARY; + } + else if (selection == clientCLIPBOARD) + { + remSelection = lastSelectionOwner[nxagentClipboardSelection].remSelection; + } + else { - selection = lastSelectionOwner[nxagentClipboardSelection].selection; + remSelection = nxagentLocalToRemoteAtom(selection); } /* * we only convert to either UTF8 or XA_STRING, despite accepting * TEXT and COMPOUND_TEXT. */ - XlibAtom p = serverTransToAgentProperty; - XlibAtom t; + XlibAtom remProperty = serverTransToAgentProperty; + XlibAtom remTarget; #ifdef DEBUG char * pstr = "NX_CUT_BUFFER_SERVER"; const char * tstr; #endif if (target == clientUTF8_STRING) { - t = serverUTF8_STRING; + remTarget = serverUTF8_STRING; #ifdef DEBUG tstr = szAgentUTF8_STRING; #endif } else { - t = XA_STRING; + remTarget = XA_STRING; #ifdef DEBUG tstr = validateString(NameForAtom(XA_STRING)); #endif } #ifdef DEBUG - fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] time [0][CurrentTime]\n", __func__, - serverWindow, t, tstr, p, pstr); + /* FIXME: check Atoms.c for alternative to XGetAtomName */ + fprintf(stderr, "%s: mapping local to remote Atom: [%d][%s] -> [%ld][%s]\n", + __func__, selection, NameForAtom(selection), remSelection, + XGetAtomName(nxagentDisplay, remSelection)); + fprintf(stderr, "%s: mapping local to remote Atom: [%d][%s] -> [%ld][%s]\n", + __func__, target, NameForAtom(target), remTarget, tstr); + fprintf(stderr, "%s: mapping local to remote Atom: [%d][%s] -> [%ld][%s]\n", + __func__, property, NameForAtom(property), remProperty, pstr); #endif - XConvertSelection(nxagentDisplay, selection, t, p, serverWindow, CurrentTime); + /* FIXME: check why using CurrentTime will not replace the value + * by a real time. The reply also contains time "0" which is + * unexpected (for me) */ + #ifdef DEBUG + fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld] time [0][CurrentTime]\n", __func__, + serverWindow, remTarget, tstr, remProperty, pstr, remSelection); + #endif - /* FIXME: check result of XConvertSelection? */ + XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); + + /* XConvertSelection will always return (check the source!), so no need to check */ #ifdef DEBUG fprintf(stderr, "%s: Sent XConvertSelection with target [%s], property [%s]\n", __func__, tstr, pstr); @@ -2223,9 +2249,17 @@ int nxagentSendNotify(xEvent *event) * X servers (defined in Xatom.h). */ - if (event->u.selectionNotify.selection == clientCLIPBOARD) + if (event->u.selectionNotify.selection == XA_PRIMARY) + { + eventSelection.selection = XA_PRIMARY; + } + else if (event->u.selectionNotify.selection == clientCLIPBOARD) + { + eventSelection.selection = lastSelectionOwner[nxagentClipboardSelection].remSelection; + } + else { - eventSelection.selection = lastSelectionOwner[nxagentClipboardSelection].selection; + eventSelection.selection = nxagentLocalToRemoteAtom(event->u.selectionNotify.selection); } /* @@ -2282,8 +2316,8 @@ WindowPtr nxagentGetClipboardWindow(Atom property) lastSelectionOwner[i].windowPtr != NULL) { #ifdef DEBUG - fprintf(stderr, "%s: Returning last [%ld] selection owner window [%p] (0x%x).\n", __func__, - lastSelectionOwner[i].selection, + fprintf(stderr, "%s: Returning last [%d] selection owner window [%p] (0x%x).\n", __func__, + lastSelectionOwner[i].intSelection, (void *)lastSelectionOwner[i].windowPtr, WINDOWID(lastSelectionOwner[i].windowPtr)); #endif @@ -2317,6 +2351,15 @@ Bool nxagentInitClipboard(WindowPtr pWin) if (!nxagentReconnectTrap) { + /* cannot move that down to others - we need it for + * initSelectionOwnerData ! */ + clientCLIPBOARD = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); + clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); + clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); + clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); + clientUTF8_STRING = MakeAtom(szAgentUTF8_STRING, strlen(szAgentUTF8_STRING), True); + clientTIMESTAMP = MakeAtom(szAgentTIMESTAMP, strlen(szAgentTIMESTAMP), True); + SAFE_free(lastSelectionOwner); lastSelectionOwner = (SelectionOwner *) malloc(nxagentMaxSelections * sizeof(SelectionOwner)); @@ -2325,8 +2368,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) { FatalError("nxagentInitClipboard: Failed to allocate memory for the clipboard selections.\n"); } - initSelectionOwnerData(nxagentPrimarySelection, XA_PRIMARY); - initSelectionOwnerData(nxagentClipboardSelection, nxagentAtoms[10]); /* CLIPBOARD */ + initSelectionOwnerData(nxagentPrimarySelection, XA_PRIMARY, XA_PRIMARY); + initSelectionOwnerData(nxagentClipboardSelection, clientCLIPBOARD, nxagentAtoms[10]); /* CLIPBOARD */ SAFE_free(lastClients); @@ -2340,7 +2383,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) { /* the clipboard selection atom might have changed on a new X server. Primary is constant. */ - lastSelectionOwner[nxagentClipboardSelection].selection = nxagentAtoms[10]; /* CLIPBOARD */ + lastSelectionOwner[nxagentClipboardSelection].remSelection = nxagentAtoms[10]; /* CLIPBOARD */ } serverTARGETS = nxagentAtoms[6]; /* TARGETS */ @@ -2389,7 +2432,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) for (int i = 0; i < nxagentMaxSelections; i++) { XFixesSelectSelectionInput(nxagentDisplay, serverWindow, - lastSelectionOwner[i].selection, + lastSelectionOwner[i].remSelection, XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask); @@ -2437,7 +2480,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) */ if (IS_INTERNAL_OWNER(i) && lastSelectionOwner[i].window) { - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].remSelection, serverWindow, CurrentTime); } } } @@ -2455,13 +2498,6 @@ Bool nxagentInitClipboard(WindowPtr pWin) lastServerRequestor = None; - clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); - clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); - clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); - clientUTF8_STRING = MakeAtom(szAgentUTF8_STRING, strlen(szAgentUTF8_STRING), True); - clientTIMESTAMP = MakeAtom(szAgentTIMESTAMP, strlen(szAgentTIMESTAMP), True); - clientCLIPBOARD = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); - clientCutProperty = MakeAtom(szAgentNX_CUT_BUFFER_CLIENT, strlen(szAgentNX_CUT_BUFFER_CLIENT), True); if (clientCutProperty == None) -- cgit v1.2.3 From edfea3cd18853ff82d866168186dd5687dba56f9 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 22 Sep 2020 22:00:20 +0200 Subject: Clipboard.c: introduce translateLocalToRemote* helpers This also unifies target handling to never use TEXT or COMPOUND_TEXT (despite announcing it) --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 198 +++++++++++-------------- 1 file changed, 90 insertions(+), 108 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f35ab583a..a07e5a5e8 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -262,6 +262,9 @@ static void replyRequestSelectionToXServer(XEvent *X, Bool success); void nxagentPrintClipboardStat(char *); +XlibAtom translateLocalToRemoteSelection(Atom local); +XlibAtom translateLocalToRemoteTarget(Atom local); + #ifdef NXAGENT_TIMESTAMP extern unsigned long startTime; #endif @@ -2079,64 +2082,24 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) lastClients[index].reqTime = GetTimeInMillis(); - XlibAtom remSelection = 0; - - /* FIXME: we should use/have a function for stuff like that */ - if (selection == XA_PRIMARY) - { - remSelection = XA_PRIMARY; - } - else if (selection == clientCLIPBOARD) - { - remSelection = lastSelectionOwner[nxagentClipboardSelection].remSelection; - } - else - { - remSelection = nxagentLocalToRemoteAtom(selection); - } - - /* - * we only convert to either UTF8 or XA_STRING, despite accepting - * TEXT and COMPOUND_TEXT. - */ + XlibAtom remSelection = translateLocalToRemoteSelection(selection); + XlibAtom remTarget = translateLocalToRemoteTarget(target); XlibAtom remProperty = serverTransToAgentProperty; - XlibAtom remTarget; - #ifdef DEBUG - char * pstr = "NX_CUT_BUFFER_SERVER"; - const char * tstr; - #endif - if (target == clientUTF8_STRING) - { - remTarget = serverUTF8_STRING; - #ifdef DEBUG - tstr = szAgentUTF8_STRING; - #endif - } - else - { - remTarget = XA_STRING; - #ifdef DEBUG - tstr = validateString(NameForAtom(XA_STRING)); - #endif - } #ifdef DEBUG - /* FIXME: check Atoms.c for alternative to XGetAtomName */ - fprintf(stderr, "%s: mapping local to remote Atom: [%d][%s] -> [%ld][%s]\n", - __func__, selection, NameForAtom(selection), remSelection, - XGetAtomName(nxagentDisplay, remSelection)); - fprintf(stderr, "%s: mapping local to remote Atom: [%d][%s] -> [%ld][%s]\n", - __func__, target, NameForAtom(target), remTarget, tstr); - fprintf(stderr, "%s: mapping local to remote Atom: [%d][%s] -> [%ld][%s]\n", - __func__, property, NameForAtom(property), remProperty, pstr); + fprintf(stderr, "%s: replacing local by remote property: [%d][%s] -> [%ld][%s]\n", + __func__, property, NameForAtom(property), + remProperty, "NX_CUT_BUFFER_SERVER"); #endif /* FIXME: check why using CurrentTime will not replace the value * by a real time. The reply also contains time "0" which is * unexpected (for me) */ #ifdef DEBUG - fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld] time [0][CurrentTime]\n", __func__, - serverWindow, remTarget, tstr, remProperty, pstr, remSelection); + fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, + serverWindow, remTarget, XGetAtomName(nxagentDisplay, remTarget), + remProperty, XGetAtomName(nxagentDisplay, remProperty), + remSelection, XGetAtomName(nxagentDisplay, remSelection)); #endif XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); @@ -2144,7 +2107,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, /* XConvertSelection will always return (check the source!), so no need to check */ #ifdef DEBUG - fprintf(stderr, "%s: Sent XConvertSelection with target [%s], property [%s]\n", __func__, tstr, pstr); + fprintf(stderr, "%s: Sent XConvertSelection\n", __func__); #endif return 1; @@ -2164,6 +2127,81 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 0; } +XlibAtom translateLocalToRemoteSelection(Atom local) +{ + /* + * On the real server, the right CLIPBOARD atom is + * XInternAtom(nxagentDisplay, "CLIPBOARD", 1), which is stored in + * lastSelectionOwner[nxagentClipboardSelection].remSelection. For + * PRIMARY there's nothing to map because that is identical on all + * X servers (defined in Xatom.h). + */ + + XlibAtom remote; + + if (local == XA_PRIMARY) + { + remote = XA_PRIMARY; + } + else if (local == clientCLIPBOARD) + { + remote = lastSelectionOwner[nxagentClipboardSelection].remSelection; + } + else + { + remote = nxagentLocalToRemoteAtom(local); + } + + #ifdef DEBUG + fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld] [%s]\n", __func__, + local, NameForAtom(local), remote, XGetAtomName(nxagentDisplay, remote)); + #endif + + return remote; +} + +XlibAtom translateLocalToRemoteTarget(Atom local) +{ + /* + * .target must be translated, too, as a client on the real + * server is requested to fill our property and it needs to know + * the format. + */ + + XlibAtom remote; + + /* + * we only convert to either UTF8 or XA_STRING, despite accepting + * TEXT and COMPOUND_TEXT. + */ + + if (local == clientUTF8_STRING) + { + remote = serverUTF8_STRING; + } +#if 0 + else if (local == clientTEXT) + { + remote = serverTEXT; + } + else if (local == clientCOMPOUND_TEXT) + { + remote = serverCOMPOUND_TEXT; + } +#endif + else + { + remote = XA_STRING; + } + + #ifdef DEBUG + fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld] [%s]\n", __func__, + local, NameForAtom(local), remote, XGetAtomName(nxagentDisplay, remote)); + #endif + + return remote; +} + /* * This is _only_ called from ProcSendEvent in NXevents.c. It is used * to send a SelectionNotify event to our server window which will @@ -2235,68 +2273,12 @@ int nxagentSendNotify(xEvent *event) XSelectionEvent eventSelection = { .requestor = serverWindow, - .selection = event->u.selectionNotify.selection, - .target = event->u.selectionNotify.target, + .selection = translateLocalToRemoteSelection(event->u.selectionNotify.selection), + .target = translateLocalToRemoteTarget(event->u.selectionNotify.target), .property = serverTransFromAgentProperty, .time = CurrentTime, }; - /* - * On the real server, the right CLIPBOARD atom is - * XInternAtom(nxagentDisplay, "CLIPBOARD", 1), which is stored in - * lastSelectionOwner[nxagentClipboardSelection].selection. For - * PRIMARY there's nothing to map because that is identical on all - * X servers (defined in Xatom.h). - */ - - if (event->u.selectionNotify.selection == XA_PRIMARY) - { - eventSelection.selection = XA_PRIMARY; - } - else if (event->u.selectionNotify.selection == clientCLIPBOARD) - { - eventSelection.selection = lastSelectionOwner[nxagentClipboardSelection].remSelection; - } - else - { - eventSelection.selection = nxagentLocalToRemoteAtom(event->u.selectionNotify.selection); - } - - /* - * .target must be translated, too, as a client on the real - * server is requested to fill our property and it needs to know - * the format. - */ - - if (event->u.selectionNotify.target == clientUTF8_STRING) - { - eventSelection.target = serverUTF8_STRING; - } - else if (event->u.selectionNotify.target == clientTEXT) - { - eventSelection.target = serverTEXT; - } - else if (event->u.selectionNotify.target == clientCOMPOUND_TEXT) - { - eventSelection.target = serverCOMPOUND_TEXT; - } - else - { - eventSelection.target = XA_STRING; - } - - #ifdef DEBUG - fprintf(stderr, "%s: mapping local to remote Atom: [%d] -> [%ld] [%s]\n", __func__, - event->u.selectionNotify.selection, eventSelection.selection, - NameForAtom(event->u.selectionNotify.selection)); - fprintf(stderr, "%s: mapping local to remote Atom: [%d] -> [%ld] [%s]\n", __func__, - event->u.selectionNotify.target, eventSelection.target, - NameForAtom(event->u.selectionNotify.target)); - fprintf(stderr, "%s: mapping local to remote Atom: [%d] -> [%ld] [%s]\n", __func__, - event->u.selectionNotify.property, eventSelection.property, - NameForAtom(event->u.selectionNotify.property)); - #endif - sendSelectionNotifyEventToXServer(&eventSelection); return 1; -- cgit v1.2.3 From 0ad6b8bd6013bb3040343188e0258488b6434710 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 3 Oct 2020 00:48:45 +0200 Subject: Clipboard.c: use index everywhere --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 175 ++++++++++++------------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index a07e5a5e8..01cdcad21 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -269,14 +269,13 @@ XlibAtom translateLocalToRemoteTarget(Atom local); extern unsigned long startTime; #endif -// FIXME: change sel to index -static void printSelectionStat(int sel) +static void printSelectionStat(int index) { - SelectionOwner lOwner = lastSelectionOwner[sel]; - Selection curSel = CurrentSelections[sel]; + SelectionOwner lOwner = lastSelectionOwner[index]; + Selection curSel = CurrentSelections[index]; char *s = NULL; - fprintf(stderr, " owner is inside nxagent? %s\n", IS_INTERNAL_OWNER(sel) ? "yes" : "no"); + fprintf(stderr, " owner is inside nxagent? %s\n", IS_INTERNAL_OWNER(index) ? "yes" : "no"); fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); fprintf(stderr, " lastSelectionOwner[].window [0x%x]\n", lOwner.window); if (lOwner.windowPtr) @@ -653,25 +652,25 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) * Only for PRIMARY and CLIPBOARD selections. */ - for (int i = 0; i < nxagentMaxSelections; i++) + for (int index = 0; index < nxagentMaxSelections; index++) { - if (matchSelectionOwner(i, pClient, pWindow)) + if (matchSelectionOwner(index, pClient, pWindow)) { #ifdef TEST fprintf(stderr, "%s: Resetting state [%d] with client [%p] window [%p].\n", __func__, - i, (void *) pClient, (void *) pWindow); + index, (void *) pClient, (void *) pWindow); #endif - clearSelectionOwnerData(i); + clearSelectionOwnerData(index); - setClientSelectionStage(SelectionStageNone, i); + setClientSelectionStage(SelectionStageNone, index); lastServerRequestor = None; } - if (pWindow && pWindow == lastClients[i].windowPtr) + if (pWindow && pWindow == lastClients[index].windowPtr) { - setClientSelectionStage(SelectionStageNone, i); + setClientSelectionStage(SelectionStageNone, index); } } } @@ -682,13 +681,13 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) */ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { - int i = 0; - while (i < nxagentMaxSelections && - lastSelectionOwner[i].remSelection != sel) + int index = 0; + while (index < nxagentMaxSelections && + lastSelectionOwner[index].remSelection != sel) { - i++; + index++; } - return i; + return index; } /* @@ -697,13 +696,13 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) */ int nxagentFindCurrentSelectionIndex(Atom sel) { - int i = 0; - while (i < NumCurrentSelections && - CurrentSelections[i].selection != sel) + int index = 0; + while (index < NumCurrentSelections && + CurrentSelections[index].selection != sel) { - i++; + index++; } - return i; + return index; } /* @@ -733,19 +732,19 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) return; } - int i = nxagentFindLastSelectionOwnerIndex(X->xselectionclear.selection); - if (i < nxagentMaxSelections) + int index = nxagentFindLastSelectionOwnerIndex(X->xselectionclear.selection); + if (index < nxagentMaxSelections) { - if (IS_INTERNAL_OWNER(i)) + if (IS_INTERNAL_OWNER(index)) { /* send a SelectionClear event to (our) previous owner */ xEvent x = {0}; x.u.u.type = SelectionClear; x.u.selectionClear.time = GetTimeInMillis(); - x.u.selectionClear.window = lastSelectionOwner[i].window; - x.u.selectionClear.atom = CurrentSelections[i].selection; + x.u.selectionClear.window = lastSelectionOwner[index].window; + x.u.selectionClear.atom = CurrentSelections[index].selection; - sendEventToClient(lastSelectionOwner[i].client, &x); + sendEventToClient(lastSelectionOwner[index].client, &x); } /* @@ -753,12 +752,12 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) * clients asking for the owner via XGetSelectionOwner() will get * these for an answer */ - CurrentSelections[i].window = screenInfo.screens[0]->root->drawable.id; - CurrentSelections[i].client = NullClient; + CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; + CurrentSelections[index].client = NullClient; - clearSelectionOwnerData(i); + clearSelectionOwnerData(index); - setClientSelectionStage(SelectionStageNone, i); + setClientSelectionStage(SelectionStageNone, index); } } @@ -839,8 +838,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) /* the selection in this request is none we own. */ { - int i = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (i == nxagentMaxSelections) + int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); + if (index == nxagentMaxSelections) { #ifdef DEBUG fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); @@ -919,8 +918,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * FIXME: selection has already been checked above, so we do not need to check again here */ - int i = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (i < nxagentMaxSelections) + int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); + if (index < nxagentMaxSelections) { XChangeProperty(nxagentDisplay, X->xselectionrequest.requestor, @@ -928,7 +927,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) XA_INTEGER, 32, PropModeReplace, - (unsigned char *) &lastSelectionOwner[i].lastTimeChanged, + (unsigned char *) &lastSelectionOwner[index].lastTimeChanged, 1); replyRequestSelectionToXServer(X, True); } @@ -958,11 +957,11 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) serverLastRequestedSelection = X->xselectionrequest.selection; /* find the index of the requested selection */ - int i = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (i < nxagentMaxSelections) + int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); + if (index < nxagentMaxSelections) { #if 0 - if (lastClients[i].windowPtr != NULL && IS_INTERNAL_OWNER(i)) + if (lastClients[index].windowPtr != NULL && IS_INTERNAL_OWNER(index)) { /* * Request the real X server to transfer the selection content @@ -973,21 +972,21 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * - at the same time paste _clipboard_ to the client (now) owning primary * ->vcxsrv will ask for primary contents to store them to Windows clipboard * - vcxsrv request is for _primary_ and takes this path as the _clipboard_ transfer - * has set lastClients[i].windowPtr + * has set lastClients[index].windowPtr */ - XConvertSelection(nxagentDisplay, CurrentSelections[i].selection, + XConvertSelection(nxagentDisplay, CurrentSelections[index].selection, X->xselectionrequest.target, serverTransToAgentProperty, - serverWindow, lastClients[i].time); + serverWindow, lastClients[index].time); #ifdef DEBUG char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); - char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[i].selection); + char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[index].selection); char *strProperty = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, - CurrentSelections[i].selection, strSelection, + CurrentSelections[index].selection, strSelection, X->xselectionrequest.target, strTarget, serverTransToAgentProperty, strProperty, - serverWindow, lastClients[i].time); + serverWindow, lastClients[index].time); #endif SAFE_XFree(strTarget); SAFE_XFree(strSelection); @@ -1002,7 +1001,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * window in the first step. We then later push that property's * content to the real X server. */ - if (IS_INTERNAL_OWNER(i) && + if (IS_INTERNAL_OWNER(index) && (nxagentOption(Clipboard) == ClipboardServer || nxagentOption(Clipboard) == ClipboardBoth)) { @@ -1023,8 +1022,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) xEvent x = {0}; x.u.u.type = SelectionRequest; x.u.selectionRequest.time = GetTimeInMillis(); - x.u.selectionRequest.owner = lastSelectionOwner[i].window; - x.u.selectionRequest.selection = CurrentSelections[i].selection; + x.u.selectionRequest.owner = lastSelectionOwner[index].window; + x.u.selectionRequest.selection = CurrentSelections[index].selection; x.u.selectionRequest.property = clientCutProperty; x.u.selectionRequest.requestor = screenInfo.screens[0]->root->drawable.id; /* Fictitious window.*/ @@ -1042,12 +1041,12 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else x.u.selectionRequest.target = XA_STRING; - sendEventToClient(lastSelectionOwner[i].client, &x); + sendEventToClient(lastSelectionOwner[index].client, &x); #ifdef DEBUG fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s]" \ "target [%d][%s] requestor [0x%x].\n", __func__, - nxagentClientInfoString(lastSelectionOwner[i].client), + nxagentClientInfoString(lastSelectionOwner[index].client), x.u.selectionRequest.property, NameForAtom(x.u.selectionRequest.property), x.u.selectionRequest.target, NameForAtom(x.u.selectionRequest.target), x.u.selectionRequest.requestor); @@ -1541,15 +1540,15 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } else { - int i = nxagentFindLastSelectionOwnerIndex(X->xselection.selection); - if (i < nxagentMaxSelections) + int index = nxagentFindLastSelectionOwnerIndex(X->xselection.selection); + if (index < nxagentMaxSelections) { /* if the last owner was an internal one, read the * clientCutProperty and push the contents to the * lastServerRequestor on the real X server. */ - if (IS_INTERNAL_OWNER(i) && - lastSelectionOwner[i].windowPtr != NULL && + if (IS_INTERNAL_OWNER(index) && + lastSelectionOwner[index].windowPtr != NULL && X->xselection.property == serverTransFromAgentProperty) { Atom atomReturnType; @@ -1559,13 +1558,13 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) unsigned char *pszReturnData = NULL; /* first get size values ... */ - int result = GetWindowProperty(lastSelectionOwner[i].windowPtr, clientCutProperty, 0, 0, False, + int result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, 0, False, AnyPropertyType, &atomReturnType, &resultFormat, &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); #ifdef DEBUG fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, - lastSelectionOwner[i].window, clientCutProperty, getXErrorString(result)); + lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); #endif if (result == BadAlloc || result == BadAtom || result == BadWindow || result == BadValue) @@ -1575,13 +1574,13 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) else { /* ... then use the size values for the actual request */ - result = GetWindowProperty(lastSelectionOwner[i].windowPtr, clientCutProperty, 0, + result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, &resultFormat, &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); #ifdef DEBUG fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, - lastSelectionOwner[i].window, clientCutProperty, getXErrorString(result)); + lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); #endif if (result == BadAlloc || result == BadAtom || @@ -1684,17 +1683,17 @@ static void resetSelectionOwnerOnXServer(void) * Only for PRIMARY and CLIPBOARD selections. */ - for (int i = 0; i < nxagentMaxSelections; i++) + for (int index = 0; index < nxagentMaxSelections; index++) { - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].remSelection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); #ifdef DEBUG - fprintf(stderr, "%s: Reset selection state for selection [%d].\n", __func__, i); + fprintf(stderr, "%s: Reset selection state for selection [%d].\n", __func__, index); #endif - clearSelectionOwnerData(i); + clearSelectionOwnerData(index); - setClientSelectionStage(SelectionStageNone, i); + setClientSelectionStage(SelectionStageNone, index); } /* Hmm, this is already None when reaching this */ @@ -1811,27 +1810,27 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) } #endif - int i = nxagentFindCurrentSelectionIndex(pSelection->selection); - if (i < NumCurrentSelections) + int index = nxagentFindCurrentSelectionIndex(pSelection->selection); + if (index < NumCurrentSelections) { #ifdef DEBUG fprintf(stderr, "%s: lastSelectionOwner.client %s -> %s\n", __func__, - nxagentClientInfoString(lastSelectionOwner[i].client), + nxagentClientInfoString(lastSelectionOwner[index].client), nxagentClientInfoString(pSelection->client)); fprintf(stderr, "%s: lastSelectionOwner.window [0x%x] -> [0x%x]\n", __func__, - lastSelectionOwner[i].window, pSelection->window); + lastSelectionOwner[index].window, pSelection->window); fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%x])\n", __func__, - (void *)lastSelectionOwner[i].windowPtr, (void *)pSelection->pWin, + (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, nxagentWindow(pSelection->pWin), serverWindow); fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, - lastSelectionOwner[i].lastTimeChanged); + lastSelectionOwner[index].lastTimeChanged); #endif /* * inform the real X server that our serverWindow is the * clipboard owner. */ - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].remSelection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); /* * The real owner window (inside nxagent) is stored in @@ -1839,9 +1838,9 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * points to the struct that contains all information about the * owner window. */ - storeSelectionOwnerData(i, pSelection); + storeSelectionOwnerData(index, pSelection); - setClientSelectionStage(SelectionStageNone, i); + setClientSelectionStage(SelectionStageNone, index); } lastServerRequestor = None; @@ -2292,18 +2291,18 @@ int nxagentSendNotify(xEvent *event) */ WindowPtr nxagentGetClipboardWindow(Atom property) { - int i = nxagentFindLastSelectionOwnerIndex(serverLastRequestedSelection); - if (i < nxagentMaxSelections && + int index = nxagentFindLastSelectionOwnerIndex(serverLastRequestedSelection); + if (index < nxagentMaxSelections && property == clientCutProperty && - lastSelectionOwner[i].windowPtr != NULL) + lastSelectionOwner[index].windowPtr != NULL) { #ifdef DEBUG fprintf(stderr, "%s: Returning last [%d] selection owner window [%p] (0x%x).\n", __func__, - lastSelectionOwner[i].intSelection, - (void *)lastSelectionOwner[i].windowPtr, WINDOWID(lastSelectionOwner[i].windowPtr)); + lastSelectionOwner[index].intSelection, + (void *)lastSelectionOwner[index].windowPtr, WINDOWID(lastSelectionOwner[index].windowPtr)); #endif - return lastSelectionOwner[i].windowPtr; + return lastSelectionOwner[index].windowPtr; } else { @@ -2411,10 +2410,10 @@ Bool nxagentInitClipboard(WindowPtr pWin) fprintf(stderr, "%s: Registering for XFixesSelectionNotify events.\n", __func__); #endif - for (int i = 0; i < nxagentMaxSelections; i++) + for (int index = 0; index < nxagentMaxSelections; index++) { XFixesSelectSelectionInput(nxagentDisplay, serverWindow, - lastSelectionOwner[i].remSelection, + lastSelectionOwner[index].remSelection, XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask); @@ -2453,16 +2452,16 @@ Bool nxagentInitClipboard(WindowPtr pWin) if (nxagentOption(Clipboard) == ClipboardServer || nxagentOption(Clipboard) == ClipboardBoth) { - for (int i = 0; i < nxagentMaxSelections; i++) + for (int index = 0; index < nxagentMaxSelections; index++) { /* * if we have a selection inform the (new) real Xserver and * claim the ownership. Note that we report our serverWindow as * owner, not the real window! */ - if (IS_INTERNAL_OWNER(i) && lastSelectionOwner[i].window) + if (IS_INTERNAL_OWNER(index) && lastSelectionOwner[index].window) { - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].remSelection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); } } } @@ -2470,12 +2469,12 @@ Bool nxagentInitClipboard(WindowPtr pWin) } else { - for (int i = 0; i < nxagentMaxSelections; i++) + for (int index = 0; index < nxagentMaxSelections; index++) { - clearSelectionOwnerData(i); - resetClientSelectionStage(i); + clearSelectionOwnerData(index); + resetClientSelectionStage(index); /* FIXME: required? move to setSelctionStage? */ - lastClients[i].reqTime = GetTimeInMillis(); + lastClients[index].reqTime = GetTimeInMillis(); } lastServerRequestor = None; -- cgit v1.2.3 From e8b00edb59400d63d3c849dee6a2705228815e97 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 22 Sep 2020 23:12:25 +0200 Subject: Clipboard.c: simplify nxagentHandleSelectionRequestFromXServer - remove redundant calls to nxagentFindLastSelectionOwnerIndex which reduce indentation level - scope improvements --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 227 ++++++++++++------------- 1 file changed, 107 insertions(+), 120 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 01cdcad21..5a85b0f87 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -837,17 +837,15 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } /* the selection in this request is none we own. */ + int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); + if (index == nxagentMaxSelections) { - int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (index == nxagentMaxSelections) - { - #ifdef DEBUG - fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); - #endif + #ifdef DEBUG + fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); + #endif - replyRequestSelectionToXServer(X, False); - return; - } + replyRequestSelectionToXServer(X, False); + return; } /* this is a special request like TARGETS or TIMESTAMP */ @@ -874,16 +872,14 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) int numTargets = sizeof(targets) / sizeof(targets[0]); #ifdef DEBUG + fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); + for (int i = 0; i < numTargets; i++) { - fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); - for (int i = 0; i < numTargets; i++) - { - char *s = XGetAtomName(nxagentDisplay, targets[i]); - fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], s); - SAFE_XFree(s); - } - fprintf(stderr, "\n"); + char *s = XGetAtomName(nxagentDisplay, targets[i]); + fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], s); + SAFE_XFree(s); } + fprintf(stderr, "\n"); #endif /* @@ -918,19 +914,15 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * FIXME: selection has already been checked above, so we do not need to check again here */ - int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (index < nxagentMaxSelections) - { - XChangeProperty(nxagentDisplay, - X->xselectionrequest.requestor, - X->xselectionrequest.property, - XA_INTEGER, - 32, - PropModeReplace, - (unsigned char *) &lastSelectionOwner[index].lastTimeChanged, - 1); - replyRequestSelectionToXServer(X, True); - } + XChangeProperty(nxagentDisplay, + X->xselectionrequest.requestor, + X->xselectionrequest.property, + XA_INTEGER, + 32, + PropModeReplace, + (unsigned char *) &lastSelectionOwner[index].lastTimeChanged, + 1); + replyRequestSelectionToXServer(X, True); } else { @@ -956,107 +948,102 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) */ serverLastRequestedSelection = X->xselectionrequest.selection; - /* find the index of the requested selection */ - int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (index < nxagentMaxSelections) - { #if 0 - if (lastClients[index].windowPtr != NULL && IS_INTERNAL_OWNER(index)) - { - /* - * Request the real X server to transfer the selection content - * to the NX_CUT_BUFFER_SERVER property of the serverWindow. - * We reach here as follows: - * - mark someting in the nx session - * -> nxagent claims ownership of PRIMARY on real X server - * - at the same time paste _clipboard_ to the client (now) owning primary - * ->vcxsrv will ask for primary contents to store them to Windows clipboard - * - vcxsrv request is for _primary_ and takes this path as the _clipboard_ transfer - * has set lastClients[index].windowPtr - */ - XConvertSelection(nxagentDisplay, CurrentSelections[index].selection, - X->xselectionrequest.target, serverTransToAgentProperty, - serverWindow, lastClients[index].time); - - #ifdef DEBUG - char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); - char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[index].selection); - char *strProperty = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); - fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, - CurrentSelections[index].selection, strSelection, - X->xselectionrequest.target, strTarget, - serverTransToAgentProperty, strProperty, + if (lastClients[index].windowPtr != NULL && IS_INTERNAL_OWNER(index)) + { + /* + * Request the real X server to transfer the selection content + * to the NX_CUT_BUFFER_SERVER property of the serverWindow. + * We reach here as follows: + * - mark someting in the nx session + * -> nxagent claims ownership of PRIMARY on real X server + * - at the same time paste _clipboard_ to the client (now) owning primary + * ->vcxsrv will ask for primary contents to store them to Windows clipboard + * - vcxsrv request is for _primary_ and takes this path as the _clipboard_ transfer + * has set lastClients[index].windowPtr + */ + XConvertSelection(nxagentDisplay, CurrentSelections[index].selection, + X->xselectionrequest.target, serverTransToAgentProperty, serverWindow, lastClients[index].time); - #endif - SAFE_XFree(strTarget); - SAFE_XFree(strSelection); - SAFE_XFree(strProperty); - } - else + + #ifdef DEBUG + char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); + char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[index].selection); + char *strProperty = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); + fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, + CurrentSelections[index].selection, strSelection, + X->xselectionrequest.target, strTarget, + serverTransToAgentProperty, strProperty, + serverWindow, lastClients[index].time); + SAFE_XFree(strTarget); + SAFE_XFree(strSelection); + SAFE_XFree(strProperty); + #endif + } + else #endif + { + /* + * if one of our clients owns the selection we ask it to copy + * the selection to the clientCutProperty on nxagent's root + * window in the first step. We then later push that property's + * content to the real X server. + */ + if (IS_INTERNAL_OWNER(index) && + (nxagentOption(Clipboard) == ClipboardServer || + nxagentOption(Clipboard) == ClipboardBoth)) { /* - * if one of our clients owns the selection we ask it to copy - * the selection to the clientCutProperty on nxagent's root - * window in the first step. We then later push that property's - * content to the real X server. + * store who on the real X server requested the data and how + * and where it wants to have it */ - if (IS_INTERNAL_OWNER(index) && - (nxagentOption(Clipboard) == ClipboardServer || - nxagentOption(Clipboard) == ClipboardBoth)) - { - /* - * store who on the real X server requested the data and how - * and where it wants to have it - */ - lastServerProperty = X->xselectionrequest.property; - lastServerRequestor = X->xselectionrequest.requestor; - lastServerTarget = X->xselectionrequest.target; - lastServerTime = X->xselectionrequest.time; - - /* by dimbor */ - if (lastServerTarget != XA_STRING) - lastServerTarget = serverUTF8_STRING; - - /* prepare the request (like XConvertSelection, but internally) */ - xEvent x = {0}; - x.u.u.type = SelectionRequest; - x.u.selectionRequest.time = GetTimeInMillis(); - x.u.selectionRequest.owner = lastSelectionOwner[index].window; - x.u.selectionRequest.selection = CurrentSelections[index].selection; - x.u.selectionRequest.property = clientCutProperty; - x.u.selectionRequest.requestor = screenInfo.screens[0]->root->drawable.id; /* Fictitious window.*/ + lastServerProperty = X->xselectionrequest.property; + lastServerRequestor = X->xselectionrequest.requestor; + lastServerTarget = X->xselectionrequest.target; + lastServerTime = X->xselectionrequest.time; - /* - * Don't send the same window, some programs are clever and - * verify cut and paste operations inside the same window and - * don't Notify at all. - * - * x.u.selectionRequest.requestor = lastSelectionOwnerWindow; - */ + /* by dimbor */ + if (lastServerTarget != XA_STRING) + lastServerTarget = serverUTF8_STRING; - /* by dimbor (idea from zahvatov) */ - if (X->xselectionrequest.target != XA_STRING) - x.u.selectionRequest.target = clientUTF8_STRING; - else - x.u.selectionRequest.target = XA_STRING; + /* prepare the request (like XConvertSelection, but internally) */ + xEvent x = {0}; + x.u.u.type = SelectionRequest; + x.u.selectionRequest.time = GetTimeInMillis(); + x.u.selectionRequest.owner = lastSelectionOwner[index].window; + x.u.selectionRequest.selection = CurrentSelections[index].selection; + x.u.selectionRequest.property = clientCutProperty; + x.u.selectionRequest.requestor = screenInfo.screens[0]->root->drawable.id; /* Fictitious window.*/ - sendEventToClient(lastSelectionOwner[index].client, &x); + /* + * Don't send the same window, some programs are clever and + * verify cut and paste operations inside the same window and + * don't Notify at all. + * + * x.u.selectionRequest.requestor = lastSelectionOwner[index].window; + */ - #ifdef DEBUG - fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s]" \ - "target [%d][%s] requestor [0x%x].\n", __func__, - nxagentClientInfoString(lastSelectionOwner[index].client), - x.u.selectionRequest.property, NameForAtom(x.u.selectionRequest.property), - x.u.selectionRequest.target, NameForAtom(x.u.selectionRequest.target), - x.u.selectionRequest.requestor); - #endif - } + /* by dimbor (idea from zahvatov) */ + if (X->xselectionrequest.target != XA_STRING) + x.u.selectionRequest.target = clientUTF8_STRING; else - { - /* deny the request */ - replyRequestSelectionToXServer(X, False); - } + x.u.selectionRequest.target = XA_STRING; + + sendEventToClient(lastSelectionOwner[index].client, &x); + + #ifdef DEBUG + fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s]" \ + "target [%d][%s] requestor [0x%x].\n", __func__, + nxagentClientInfoString(lastSelectionOwner[index].client), + x.u.selectionRequest.property, NameForAtom(x.u.selectionRequest.property), + x.u.selectionRequest.target, NameForAtom(x.u.selectionRequest.target), + x.u.selectionRequest.requestor); + #endif + } + else + { + /* deny the request */ + replyRequestSelectionToXServer(X, False); } } } -- cgit v1.2.3 From 4701db7bcf0c66f153c172aa9a31197ab4a48bbd Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 22 Sep 2020 23:19:55 +0200 Subject: Clipboard.c: improve debug/test messages --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 5a85b0f87..60792bb44 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1032,12 +1032,13 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) sendEventToClient(lastSelectionOwner[index].client, &x); #ifdef DEBUG - fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s]" \ - "target [%d][%s] requestor [0x%x].\n", __func__, + fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s] " \ + "target [%d][%s] requestor [0x%x] selection [%d][%s].\n", __func__, nxagentClientInfoString(lastSelectionOwner[index].client), x.u.selectionRequest.property, NameForAtom(x.u.selectionRequest.property), x.u.selectionRequest.target, NameForAtom(x.u.selectionRequest.target), - x.u.selectionRequest.requestor); + x.u.selectionRequest.requestor, + x.u.selectionRequest.selection, NameForAtom(x.u.selectionRequest.selection)); #endif } else @@ -2377,7 +2378,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) } #ifdef TEST - fprintf(stderr, "%s: Setting owner of selection [%d][%s] on window 0x%x\n", __func__, + fprintf(stderr, "%s: Setting owner of selection [%d][%s] to serverwindow [0x%x]\n", __func__, (int) serverTransToAgentProperty, "NX_CUT_BUFFER_SERVER", serverWindow); #endif -- cgit v1.2.3 From e526e1cd0fec37b35a746d600170e923e8e86041 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 22 Sep 2020 23:33:35 +0200 Subject: Clipboard.c: fix nxagentConvertSelection - debug output was not printed at the beginning but later and was therefore missing sometimes - add comments/FIXMEs - re-enable failure notification for second call --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 46 ++++++++++++++------------ 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 60792bb44..fe6d39281 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1863,6 +1863,24 @@ FIXME int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, Window requestor, Atom property, Atom target, Time time) { + const char *strTarget = NameForAtom(target); + + #ifdef DEBUG + fprintf(stderr, "%s: client %s requests sel [%s] " + "on window [0x%x] prop [%d][%s] target [%d][%s].\n", __func__, + nxagentClientInfoString(client), validateString(NameForAtom(selection)), requestor, + property, validateString(NameForAtom(property)), + target, validateString(strTarget)); + #endif + + if (strTarget == NULL) + { + #ifdef DEBUG + fprintf(stderr, "%s: cannot find name for target Atom [%d] - returning\n", __func__, target); + #endif + return 1; + } + if (!agentClipboardInitialized) { #ifdef DEBUG @@ -1915,20 +1933,22 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) { #ifdef DEBUG - fprintf(stderr, "%s: timeout expired on last request, " + fprintf(stderr, "%s: timeout expired on previous request, " "notifying failure to client %s\n", __func__, nxagentClientInfoString(client)); #endif /* notify the waiting client of failure */ endTransfer(SELECTION_FAULT, index); - return 1; + + /* do NOT return here but process the new request instead! */ } else { /* * we got another convert request while already waiting for an - * answer from the real X server to a previous convert request, - * which we cannot handle (yet). So return an error. + * answer from the real X server to a previous convert request + * for this selection, which we cannot handle (yet). So return + * an error for the new request. */ #ifdef DEBUG fprintf(stderr, "%s: got new request " @@ -1943,24 +1963,6 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } } - const char *strTarget = NameForAtom(target); - - #ifdef DEBUG - fprintf(stderr, "%s: client %s requests sel [%s] " - "on window [0x%x] prop [%d][%s] target [%d][%s].\n", __func__, - nxagentClientInfoString(client), validateString(NameForAtom(selection)), requestor, - property, validateString(NameForAtom(property)), - target, validateString(strTarget)); - #endif - - if (strTarget == NULL) - { - #ifdef DEBUG - fprintf(stderr, "%s: cannot find name for target Atom [%d] - returning\n", __func__, target); - #endif - return 1; - } - /* * The selection request target is TARGETS. The requestor is asking * for a list of supported data formats. -- cgit v1.2.3 From a8d09f81501b76b507f080e6a812101f6cc2ada5 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 15:48:43 +0200 Subject: Clipboard.c: have lastServer* per selection This will help in PRIMARY content appearing in CLIPBOARD and vice versa. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 183 +++++++++++++++---------- 1 file changed, 110 insertions(+), 73 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index fe6d39281..fefb0286e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -93,6 +93,8 @@ typedef struct _SelectionOwner * owner is outside nxagent. .selection will _always_ contain the * external atom of the selection */ + +/* FIXME: these should also be stored per selection */ static SelectionOwner *lastSelectionOwner; static XlibAtom serverLastRequestedSelection; @@ -130,10 +132,14 @@ typedef struct _lastClient static lastClient *lastClients; -static Window lastServerRequestor; -static XlibAtom lastServerProperty; -static XlibAtom lastServerTarget; -static Time lastServerTime; +typedef struct _lastServer { + Window requestor; + XlibAtom property; + XlibAtom target; + Time time; +} lastServer; + +static lastServer *lastServers; static XlibAtom serverTARGETS; static XlibAtom serverTIMESTAMP; @@ -328,6 +334,19 @@ static void printLastClientStat(int index) fprintf(stderr, " lastClients[].resource (int) [%d]\n", lc.resource); } +static void printLastServerStat(int index) +{ + lastServer ls = lastServers[index]; + char *s = NULL; + + fprintf(stderr, " lastServer[].requestor (Window) [0x%x]\n", ls.requestor); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, ls.property); + fprintf(stderr, " lastServer[].property (Atom) [% 4ld][%s]\n", ls.property, validateString(s)); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, ls.target); + fprintf(stderr, " lastServer[].target (Atom) [% 4ld][%s]\n", ls.target, validateString(s)); + fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); + SAFE_XFree(s); +} void nxagentDumpClipboardStat(void) { @@ -353,20 +372,14 @@ void nxagentDumpClipboardStat(void) } fprintf(stderr, "\n"); - fprintf(stderr, "lastServer\n"); - fprintf(stderr, " lastServerRequestor (Window) [0x%x]\n", lastServerRequestor); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, lastServerProperty); - fprintf(stderr, " lastServerProperty (Atom) [% 4ld][%s]\n", lastServerProperty, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, lastServerTarget); - fprintf(stderr, " lastServerTarget (Atom) [% 4ld][%s]\n", lastServerTarget, validateString(s)); - fprintf(stderr, " lastServerTime (Time) [%u]\n", lastServerTime); - fprintf(stderr, "PRIMARY\n"); printSelectionStat(nxagentPrimarySelection); printLastClientStat(nxagentPrimarySelection); + printLastServerStat(nxagentPrimarySelection); fprintf(stderr, "CLIPBOARD\n"); printSelectionStat(nxagentClipboardSelection); printLastClientStat(nxagentClipboardSelection); + printLastServerStat(nxagentClipboardSelection); fprintf(stderr, "Atoms (remote X server)\n"); SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTARGETS); @@ -665,7 +678,7 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) setClientSelectionStage(SelectionStageNone, index); - lastServerRequestor = None; + lastServers[index].requestor = None; } if (pWindow && pWindow == lastClients[index].windowPtr) @@ -803,13 +816,12 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) char *strProperty = XGetAtomName(nxagentDisplay, X->xselectionrequest.property); fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ - "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s] lastServerRequestor [0x%x]\n", + "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", __func__, X->xselectionrequest.selection, validateString(strSelection), X->xselectionrequest.target, validateString(strTarget), DisplayString(nxagentDisplay), X->xselectionrequest.requestor, - X->xselectionrequest.property, validateString(strProperty), - lastServerRequestor); + X->xselectionrequest.property, validateString(strProperty)); SAFE_XFree(strTarget); SAFE_XFree(strSelection); @@ -825,23 +837,27 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) return; } - /* lastServerRequestor in non-NULL (= we are currently in the transfer phase) */ - if (lastServerRequestor != None) + /* the selection in this request is none we own. */ + int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); + if (index == nxagentMaxSelections) { #ifdef DEBUG - fprintf(stderr, "%s: denying additional request during transfer phase.\n", __func__); + fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); #endif replyRequestSelectionToXServer(X, False); return; } - /* the selection in this request is none we own. */ - int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (index == nxagentMaxSelections) + #ifdef DEBUG + fprintf(stderr, "%s: lastServers[%d].requestor [0x%x].\n", __func__, index, lastServers[index].requestor); + #endif + + /* lastServers[index].requestor in non-NULL (= we are currently in the transfer phase) */ + if (lastServers[index].requestor != None) { #ifdef DEBUG - fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); + fprintf(stderr, "%s: denying additional request during transfer phase.\n", __func__); #endif replyRequestSelectionToXServer(X, False); @@ -997,14 +1013,14 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * store who on the real X server requested the data and how * and where it wants to have it */ - lastServerProperty = X->xselectionrequest.property; - lastServerRequestor = X->xselectionrequest.requestor; - lastServerTarget = X->xselectionrequest.target; - lastServerTime = X->xselectionrequest.time; + lastServers[index].property = X->xselectionrequest.property; + lastServers[index].requestor = X->xselectionrequest.requestor; + lastServers[index].target = X->xselectionrequest.target; + lastServers[index].time = X->xselectionrequest.time; /* by dimbor */ - if (lastServerTarget != XA_STRING) - lastServerTarget = serverUTF8_STRING; + if (lastServers[index].target != XA_STRING) + lastServers[index].target = serverUTF8_STRING; /* prepare the request (like XConvertSelection, but internally) */ xEvent x = {0}; @@ -1029,6 +1045,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else x.u.selectionRequest.target = XA_STRING; + x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); sendEventToClient(lastSelectionOwner[index].client, &x); #ifdef DEBUG @@ -1533,7 +1550,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) { /* if the last owner was an internal one, read the * clientCutProperty and push the contents to the - * lastServerRequestor on the real X server. + * lastServers[index].requestor on the real X server. */ if (IS_INTERNAL_OWNER(index) && lastSelectionOwner[index].windowPtr != NULL && @@ -1557,7 +1574,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) if (result == BadAlloc || result == BadAtom || result == BadWindow || result == BadValue) { - lastServerProperty = None; + lastServers[index].property = None; } else { @@ -1574,7 +1591,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) if (result == BadAlloc || result == BadAtom || result == BadWindow || result == BadValue) { - lastServerProperty = None; + lastServers[index].property = None; } else { @@ -1583,9 +1600,9 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) return 1, no matter what, so no need to check the result */ /* FIXME: better use the format returned by above request */ XChangeProperty(nxagentDisplay, - lastServerRequestor, - lastServerProperty, - lastServerTarget, + lastServers[index].requestor, + lastServers[index].property, + lastServers[index].target, 8, PropModeReplace, pszReturnData, @@ -1593,11 +1610,11 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) #ifdef DEBUG { - char *s = XGetAtomName(nxagentDisplay, lastServerProperty); + char *s = XGetAtomName(nxagentDisplay, lastServers[index].property); fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", __func__, - lastServerRequestor, - lastServerProperty, + lastServers[index].requestor, + lastServers[index].property, s, (int)(min(20, ulReturnItems * 8 / 8)), (int)(min(20, ulReturnItems * 8 / 8)), @@ -1617,17 +1634,17 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * inform the initial requestor that the requested data has * arrived in the desired property. If we have been unable to * get the data from the owner XChangeProperty will not have - * been called and lastServerProperty will be None which + * been called and lastServers[index].property will be None which * effectively will send a "Request denied" to the initial * requestor. */ XSelectionEvent eventSelection = { - .requestor = lastServerRequestor, + .requestor = lastServers[index].requestor, .selection = X->xselection.selection, /* .target = X->xselection.target, */ - .target = lastServerTarget, - .property = lastServerProperty, - .time = lastServerTime, + .target = lastServers[index].target, + .property = lastServers[index].property, + .time = lastServers[index].time, /* .time = CurrentTime */ }; #ifdef DEBUG @@ -1637,7 +1654,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) sendSelectionNotifyEventToXServer(&eventSelection); - lastServerRequestor = None; /* allow further request */ + lastServers[index].requestor = None; /* allow further request */ } } } @@ -1652,15 +1669,15 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) */ static void resetSelectionOwnerOnXServer(void) { - if (lastServerRequestor != None) + if (lastServers[index].requestor != None) { /* * we are in the process of communicating back and forth between * real X server and nxagent's clients - let's not disturb. */ #if defined(TEST) || defined(DEBUG) - fprintf(stderr, "%s: WARNING! Requestor window [0x%x] already found.\n", __func__, - lastServerRequestor); + fprintf(stderr, "%s: WARNING! Requestor window [0x%x] already set.\n", __func__, + lastServers[index].requestor); #endif /* FIXME: maybe we should put back the event that lead us here. */ @@ -1685,7 +1702,7 @@ static void resetSelectionOwnerOnXServer(void) } /* Hmm, this is already None when reaching this */ - lastServerRequestor = None; + lastServers[index].requestor = None; } #endif @@ -1785,19 +1802,6 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) serverWindow); #endif - #if defined(TEST) || defined(DEBUG) - if (lastServerRequestor != None) - { - /* - * we are in the process of communicating back and forth between - * real X server and nxagent's clients - let's not disturb - * FIXME: by continuing after the warning were ARE disturbing! - */ - fprintf (stderr, "%s: WARNING! Requestor window [0x%x] already set.\n", __func__, - lastServerRequestor); - } - #endif - int index = nxagentFindCurrentSelectionIndex(pSelection->selection); if (index < NumCurrentSelections) { @@ -1814,6 +1818,19 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) lastSelectionOwner[index].lastTimeChanged); #endif + #if defined(TEST) || defined(DEBUG) + if (lastServers[index].requestor != None) + { + /* + * we are in the process of communicating back and forth between + * real X server and nxagent's clients - let's not disturb + * FIXME: by continuing after the warning were ARE disturbing! + */ + fprintf (stderr, "%s: WARNING! lastServers[%d].requestor window [0x%x] already set.\n", + __func__, index, lastServers[index].requestor); + } + #endif + /* * inform the real X server that our serverWindow is the * clipboard owner. @@ -1831,7 +1848,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) setClientSelectionStage(SelectionStageNone, index); } - lastServerRequestor = None; + lastServers[index].requestor = None; /* FIXME @@ -1847,7 +1864,7 @@ FIXME setClientSelectionStage(SelectionStageNone); - lastServerRequestor = None; + lastServers[index].requestor = None; } else fprintf (stderr, "%s: SetSelectionOwner failed\n", __func__); */ @@ -2227,8 +2244,24 @@ int nxagentSendNotify(xEvent *event) fprintf(stderr, "%s: property is [%d][%s].\n", __func__, event->u.selectionNotify.property, NameForAtom(event->u.selectionNotify.property)); + fprintf(stderr, "%s: selection is [%d][%s].\n", __func__, + event->u.selectionNotify.selection, + NameForAtom(event->u.selectionNotify.selection)); fprintf(stderr, "%s: requestor is [0x%x].\n", __func__, event->u.selectionNotify.requestor); - fprintf(stderr, "%s: lastServerRequestor is [0x%x].\n", __func__, lastServerRequestor); + #endif + + int index = nxagentFindCurrentSelectionIndex(event->u.selectionNotify.selection); + if (index == nxagentMaxSelections) + { + #ifdef DEBUG + fprintf(stderr, "%s: unknown selection [%d]\n", __func__, + event->u.selectionNotify.selection); + #endif + return 0; + } + + #ifdef DEBUG + fprintf(stderr, "%s: lastServers[index].requestor is [0x%x].\n", __func__, lastServers[index].requestor); #endif /* @@ -2239,7 +2272,7 @@ int nxagentSendNotify(xEvent *event) * dix to go on) and do nothing! * Be sure to not let this trigger for the failure answer (property 0) */ - if (!(event->u.selectionNotify.property == clientCutProperty || event->u.selectionNotify.property == 0) || lastServerRequestor == None) + if (!(event->u.selectionNotify.property == clientCutProperty || event->u.selectionNotify.property == 0) || lastServers[index].requestor == None) { #ifdef DEBUG fprintf(stderr, "%s: sent nothing - message to real X server is not required.\n", __func__); @@ -2332,7 +2365,6 @@ Bool nxagentInitClipboard(WindowPtr pWin) clientTIMESTAMP = MakeAtom(szAgentTIMESTAMP, strlen(szAgentTIMESTAMP), True); SAFE_free(lastSelectionOwner); - lastSelectionOwner = (SelectionOwner *) malloc(nxagentMaxSelections * sizeof(SelectionOwner)); if (lastSelectionOwner == NULL) @@ -2343,11 +2375,17 @@ Bool nxagentInitClipboard(WindowPtr pWin) initSelectionOwnerData(nxagentClipboardSelection, clientCLIPBOARD, nxagentAtoms[10]); /* CLIPBOARD */ SAFE_free(lastClients); - - lastClients = (lastClient *) malloc(nxagentMaxSelections * sizeof(lastClient)); + lastClients = (lastClient *) calloc(nxagentMaxSelections, sizeof(lastClient)); if (lastClients == NULL) { - FatalError("nxagentInitClipboard: Failed to allocate memory for the last client array.\n"); + FatalError("nxagentInitClipboard: Failed to allocate memory for the last clients array.\n"); + } + + SAFE_free(lastServers); + lastServers = (lastServer *) calloc(nxagentMaxSelections, sizeof(lastServer)); + if (lastServers == NULL) + { + FatalError("nxagentInitClipboard: Failed to allocate memory for the last servers array.\n"); } } else @@ -2455,7 +2493,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) } } } - /* FIXME: Shouldn't we reset lastServer* and lastClients[index].* here? */ + /* FIXME: Shouldn't we reset lastServers[index].* and lastClients[index].* here? */ } else { @@ -2463,12 +2501,11 @@ Bool nxagentInitClipboard(WindowPtr pWin) { clearSelectionOwnerData(index); resetClientSelectionStage(index); - /* FIXME: required? move to setSelctionStage? */ + /* FIXME: required? move to setSelectionStage? */ lastClients[index].reqTime = GetTimeInMillis(); + lastServers[index].requestor = None; } - lastServerRequestor = None; - clientCutProperty = MakeAtom(szAgentNX_CUT_BUFFER_CLIENT, strlen(szAgentNX_CUT_BUFFER_CLIENT), True); if (clientCutProperty == None) -- cgit v1.2.3 From d2370a1ba10faffeca51d78695e8c58f4715f06e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 16:36:42 +0200 Subject: Clipboard.c: rename function to better reflect meaning Also improve Debug output. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 29 +++++++++++--------------- nx-X11/programs/Xserver/hw/nxagent/Clipboard.h | 2 +- nx-X11/programs/Xserver/hw/nxagent/NXevents.c | 4 ++-- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index fefb0286e..e53b454da 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1699,10 +1699,10 @@ static void resetSelectionOwnerOnXServer(void) clearSelectionOwnerData(index); setClientSelectionStage(SelectionStageNone, index); - } - /* Hmm, this is already None when reaching this */ - lastServers[index].requestor = None; + /* Hmm, this is already None when reaching this */ + lastServers[index].requestor = None; + } } #endif @@ -1848,7 +1848,8 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) setClientSelectionStage(SelectionStageNone, index); } - lastServers[index].requestor = None; + /* FIXME: commented because index is invalid here! */ + /* lastServers[index].requestor = None; */ /* FIXME @@ -2226,12 +2227,8 @@ XlibAtom translateLocalToRemoteTarget(Atom local) * selection. When there is an owner, it should be generated by the * owner of the selection by using XSendEvent()." */ -int nxagentSendNotify(xEvent *event) +int nxagentSendNotificationToSelfViaXServer(xEvent *event) { - #ifdef DEBUG - fprintf(stderr, "%s: Got called.\n", __func__); - #endif - if (!agentClipboardInitialized) { #ifdef DEBUG @@ -2241,13 +2238,11 @@ int nxagentSendNotify(xEvent *event) } #ifdef DEBUG - fprintf(stderr, "%s: property is [%d][%s].\n", __func__, - event->u.selectionNotify.property, - NameForAtom(event->u.selectionNotify.property)); - fprintf(stderr, "%s: selection is [%d][%s].\n", __func__, - event->u.selectionNotify.selection, - NameForAtom(event->u.selectionNotify.selection)); - fprintf(stderr, "%s: requestor is [0x%x].\n", __func__, event->u.selectionNotify.requestor); + fprintf(stderr, "%s: Received SendNotify by client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, + event->u.selectionNotify.property, NameForAtom(event->u.selectionNotify.property), + event->u.selectionNotify.target, NameForAtom(event->u.selectionNotify.target), + event->u.selectionNotify.selection, NameForAtom(event->u.selectionNotify.selection), + event->u.selectionNotify.requestor, event->u.selectionNotify.time); #endif int index = nxagentFindCurrentSelectionIndex(event->u.selectionNotify.selection); @@ -2403,7 +2398,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) /* * Server side properties to hold pasted data. - * see nxagentSendNotify for an explanation + * see nxagentSendNotificationToSelfViaXServer for an explanation */ serverTransFromAgentProperty = nxagentAtoms[15]; /* NX_SELTRANS_FROM_AGENT */ serverTransToAgentProperty = nxagentAtoms[5]; /* NX_CUT_BUFFER_SERVER */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h index f902bb50b..aca8d94af 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h @@ -76,7 +76,7 @@ extern Bool nxagentCollectPropertyEventFromXServer(int resource); extern WindowPtr nxagentGetClipboardWindow(Atom property); -extern int nxagentSendNotify(xEvent *event); +extern int nxagentSendNotificationToSelfViaXServer(xEvent *event); extern void nxagentDumpClipboardStat(void); diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c index fccc718b0..50ecef09b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c @@ -433,8 +433,8 @@ ProcSendEvent(ClientPtr client) if (stuff -> event.u.u.type == SelectionNotify) { - if (nxagentSendNotify(&stuff->event) == 1) - return Success; + if (nxagentSendNotificationToSelfViaXServer(&stuff->event) == 1) + return Success; } #endif return xorg_ProcSendEvent(client); -- cgit v1.2.3 From 3682be5941c549c9fc215575d01261fae6c1fa63 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 16:51:37 +0200 Subject: Clipboard.c: mark self-initiated event --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index e53b454da..605716e9d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1439,6 +1439,11 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) char * p = XGetAtomName(nxagentDisplay, e->property); char * t = XGetAtomName(nxagentDisplay, e->target); char * s = XGetAtomName(nxagentDisplay, e->selection); + if (e->requestor == serverWindow) + { + fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; + } + fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", __func__, e->property, validateString(p), e->requestor, -- cgit v1.2.3 From d79db429dd1db5a507dcecb2bd8f79d4e3545be4 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 17:03:00 +0200 Subject: Clipboard.c: always print SelectionCallBackKind in debug output --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 38 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 605716e9d..40a812b9b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -815,6 +815,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) char *strSelection = XGetAtomName(nxagentDisplay, X->xselectionrequest.selection); char *strProperty = XGetAtomName(nxagentDisplay, X->xselectionrequest.property); + if (X->xselectionrequest.requestor == serverWindow) + { + fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; + } fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", __func__, @@ -1732,6 +1736,28 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, * way to identify that situation during callback processing we * could get rid of the Trap... */ + + SelectionInfoRec *info = (SelectionInfoRec *)args; + + #ifdef DEBUG + if (info->kind == SelectionSetOwner) + { + fprintf(stderr, "%s: SelectionCallbackKind [SelectionSetOwner]\n", __func__); + } + else if (info->kind == SelectionWindowDestroy) + { + fprintf(stderr, "%s: SelectionCallbackKind [SelectionWindowDestroy]\n", __func__); + } + else if (info->kind == SelectionClientClose) + { + fprintf(stderr, "%s: SelectionCallbackKind [SelectionClientClose]\n", __func__); + } + else + { + fprintf(stderr, "%s: SelectionCallbackKind [unknown]\n", __func__); + } + #endif + if (nxagentExternalClipboardEventTrap) { #ifdef DEBUG @@ -1740,8 +1766,6 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, return; } - SelectionInfoRec *info = (SelectionInfoRec *)args; - Selection * pCurSel = (Selection *)info->selection; #ifdef DEBUG @@ -1751,7 +1775,6 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, if (info->kind == SelectionSetOwner) { #ifdef DEBUG - fprintf(stderr, "%s: called with SelectionCallbackKind SelectionSetOwner\n", __func__); fprintf(stderr, "%s: pCurSel->pWin [0x%x]\n", __func__, WINDOWID(pCurSel->pWin)); fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForAtom(pCurSel->selection)); #endif @@ -1769,21 +1792,12 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, } else if (info->kind == SelectionWindowDestroy) { - #ifdef DEBUG - fprintf(stderr, "%s: called with SelectionCallbackKind SelectionWindowDestroy\n", __func__); - #endif } else if (info->kind == SelectionClientClose) { - #ifdef DEBUG - fprintf(stderr, "%s: called with SelectionCallbackKind SelectionClientClose\n", __func__); - #endif } else { - #ifdef DEBUG - fprintf(stderr, "%s: called with unknown SelectionCallbackKind\n", __func__); - #endif } } #endif -- cgit v1.2.3 From a3adf6641e9d93fdeb7d345b28f59f6415bb9aa6 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 23:21:37 +0200 Subject: Clipboard.c: remove superflous index determination we already have it at that stage --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 172 ++++++++++++------------- 1 file changed, 84 insertions(+), 88 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 40a812b9b..da07cad40 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1554,32 +1554,46 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } else { - int index = nxagentFindLastSelectionOwnerIndex(X->xselection.selection); - if (index < nxagentMaxSelections) + /* if the last owner was an internal one, read the + * clientCutProperty and push the contents to the + * lastServers[index].requestor on the real X server. + */ + if (IS_INTERNAL_OWNER(index) && + lastSelectionOwner[index].windowPtr != NULL && + X->xselection.property == serverTransFromAgentProperty) { - /* if the last owner was an internal one, read the - * clientCutProperty and push the contents to the - * lastServers[index].requestor on the real X server. - */ - if (IS_INTERNAL_OWNER(index) && - lastSelectionOwner[index].windowPtr != NULL && - X->xselection.property == serverTransFromAgentProperty) - { - Atom atomReturnType; - int resultFormat; - unsigned long ulReturnItems; - unsigned long ulReturnBytesLeft; - unsigned char *pszReturnData = NULL; + Atom atomReturnType; + int resultFormat; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; - /* first get size values ... */ - int result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, 0, False, - AnyPropertyType, &atomReturnType, &resultFormat, - &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); + /* first get size values ... */ + int result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, 0, False, + AnyPropertyType, &atomReturnType, &resultFormat, + &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); + #ifdef DEBUG + fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, + lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); + #endif + if (result == BadAlloc || result == BadAtom || + result == BadWindow || result == BadValue) + { + lastServers[index].property = None; + } + else + { + /* ... then use the size values for the actual request */ + result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, + ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, + &resultFormat, &ulReturnItems, &ulReturnBytesLeft, + &pszReturnData); #ifdef DEBUG fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); #endif + if (result == BadAlloc || result == BadAtom || result == BadWindow || result == BadValue) { @@ -1587,84 +1601,66 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } else { - /* ... then use the size values for the actual request */ - result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, - ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, - &resultFormat, &ulReturnItems, &ulReturnBytesLeft, - &pszReturnData); - #ifdef DEBUG - fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, - lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); - #endif + /* Fill the property on the initial requestor with the requested data */ + /* The XChangeProperty source code reveals it will always + return 1, no matter what, so no need to check the result */ + /* FIXME: better use the format returned by above request */ + XChangeProperty(nxagentDisplay, + lastServers[index].requestor, + lastServers[index].property, + lastServers[index].target, + 8, + PropModeReplace, + pszReturnData, + ulReturnItems); - if (result == BadAlloc || result == BadAtom || - result == BadWindow || result == BadValue) - { - lastServers[index].property = None; - } - else + #ifdef DEBUG { - /* Fill the property on the initial requestor with the requested data */ - /* The XChangeProperty source code reveals it will always - return 1, no matter what, so no need to check the result */ - /* FIXME: better use the format returned by above request */ - XChangeProperty(nxagentDisplay, - lastServers[index].requestor, - lastServers[index].property, - lastServers[index].target, - 8, - PropModeReplace, - pszReturnData, - ulReturnItems); - - #ifdef DEBUG - { - char *s = XGetAtomName(nxagentDisplay, lastServers[index].property); - fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", - __func__, - lastServers[index].requestor, - lastServers[index].property, - s, - (int)(min(20, ulReturnItems * 8 / 8)), - (int)(min(20, ulReturnItems * 8 / 8)), - pszReturnData); - SAFE_XFree(s); - } - #endif + char *s = XGetAtomName(nxagentDisplay, lastServers[index].property); + fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", + __func__, + lastServers[index].requestor, + lastServers[index].property, + s, + (int)(min(20, ulReturnItems * 8 / 8)), + (int)(min(20, ulReturnItems * 8 / 8)), + pszReturnData); + SAFE_XFree(s); } - - /* FIXME: free it or not? */ - /* - * SAFE_XFree(pszReturnData); - */ + #endif } + /* FIXME: free it or not? */ /* - * inform the initial requestor that the requested data has - * arrived in the desired property. If we have been unable to - * get the data from the owner XChangeProperty will not have - * been called and lastServers[index].property will be None which - * effectively will send a "Request denied" to the initial - * requestor. + * SAFE_XFree(pszReturnData); */ - XSelectionEvent eventSelection = { - .requestor = lastServers[index].requestor, - .selection = X->xselection.selection, - /* .target = X->xselection.target, */ - .target = lastServers[index].target, - .property = lastServers[index].property, - .time = lastServers[index].time, - /* .time = CurrentTime */ - }; - #ifdef DEBUG - fprintf(stderr, "%s: Sending SelectionNotify event to requestor [%p].\n", __func__, - (void *)eventSelection.requestor); - #endif + } - sendSelectionNotifyEventToXServer(&eventSelection); + /* + * inform the initial requestor that the requested data has + * arrived in the desired property. If we have been unable to + * get the data from the owner XChangeProperty will not have + * been called and lastServers[index].property will be None which + * effectively will send a "Request denied" to the initial + * requestor. + */ + XSelectionEvent eventSelection = { + .requestor = lastServers[index].requestor, + .selection = X->xselection.selection, + /* .target = X->xselection.target, */ + .target = lastServers[index].target, + .property = lastServers[index].property, + .time = lastServers[index].time, + /* .time = CurrentTime */ + }; + #ifdef DEBUG + fprintf(stderr, "%s: Sending SelectionNotify event to requestor [%p].\n", __func__, + (void *)eventSelection.requestor); + #endif - lastServers[index].requestor = None; /* allow further request */ - } + sendSelectionNotifyEventToXServer(&eventSelection); + + lastServers[index].requestor = None; /* allow further request */ } } } -- cgit v1.2.3 From 278ebeb70d7183ba62c6bbbcfce08ff08e205117 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 3 Oct 2020 01:24:11 +0200 Subject: Clipboard.c: split if clause this allows better error messages --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index da07cad40..202eb1baa 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1003,15 +1003,24 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else #endif { + if (!(nxagentOption(Clipboard) == ClipboardServer || + nxagentOption(Clipboard) == ClipboardBoth)) + { + #ifdef DEBUG + fprintf (stderr, "%s: clipboard (partly) disabled - denying request.\n", __func__); + #endif + + /* deny the request */ + replyRequestSelectionToXServer(X, False); + } + /* * if one of our clients owns the selection we ask it to copy * the selection to the clientCutProperty on nxagent's root * window in the first step. We then later push that property's * content to the real X server. */ - if (IS_INTERNAL_OWNER(index) && - (nxagentOption(Clipboard) == ClipboardServer || - nxagentOption(Clipboard) == ClipboardBoth)) + if (IS_INTERNAL_OWNER(index)) { /* * store who on the real X server requested the data and how @@ -1061,9 +1070,18 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) x.u.selectionRequest.requestor, x.u.selectionRequest.selection, NameForAtom(x.u.selectionRequest.selection)); #endif + /* no reply to Xserver yet - we will do that once the answer of + the above sendEventToClient arrives */ } else { + #ifdef DEBUG + char *s = XGetAtomName(nxagentDisplay, X->xselectionrequest.selection); + fprintf (stderr, "%s: no internal owner for selection [%ld][%s] - denying request.\n", __func__, + X->xselectionrequest.selection, s); + SAFE_XFree(s); + #endif + /* deny the request */ replyRequestSelectionToXServer(X, False); } -- cgit v1.2.3 From d32b4f5b1a55e0bbca79701d2b89bede331fed75 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 3 Oct 2020 01:57:58 +0200 Subject: Clipboard.c: fix memleaks in DEBUG mode --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 202eb1baa..74ed61d7f 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2136,10 +2136,16 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * by a real time. The reply also contains time "0" which is * unexpected (for me) */ #ifdef DEBUG + char *t = XGetAtomName(nxagentDisplay, remTarget); + char *p = XGetAtomName(nxagentDisplay, remProperty); + char *s = XGetAtomName(nxagentDisplay, remSelection); fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, - serverWindow, remTarget, XGetAtomName(nxagentDisplay, remTarget), - remProperty, XGetAtomName(nxagentDisplay, remProperty), - remSelection, XGetAtomName(nxagentDisplay, remSelection)); + serverWindow, remTarget, validateString(t), + remProperty, validateString(p), + remSelection, validateString(s)); + SAFE_XFree(t); + SAFE_XFree(p); + SAFE_XFree(s); #endif XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); @@ -2193,8 +2199,10 @@ XlibAtom translateLocalToRemoteSelection(Atom local) } #ifdef DEBUG + char *r = XGetAtomName(nxagentDisplay, remote); fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld] [%s]\n", __func__, - local, NameForAtom(local), remote, XGetAtomName(nxagentDisplay, remote)); + local, NameForAtom(local), remote, validateString(r)); + SAFE_XFree(r); #endif return remote; @@ -2235,8 +2243,10 @@ XlibAtom translateLocalToRemoteTarget(Atom local) } #ifdef DEBUG + char *r = XGetAtomName(nxagentDisplay, remote); fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld] [%s]\n", __func__, - local, NameForAtom(local), remote, XGetAtomName(nxagentDisplay, remote)); + local, NameForAtom(local), remote, validateString(r)); + SAFE_XFree(r); #endif return remote; -- cgit v1.2.3 From 6753eb5928cf8a70317f0b1304bf4705309548ef Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 11 Oct 2020 18:03:53 +0200 Subject: Clipboard.c: use for loops everywhere. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 74ed61d7f..cd3a890d0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -665,6 +665,7 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) * Only for PRIMARY and CLIPBOARD selections. */ + /* FIXME: there's almost identical code in nxagentClipboardInit */ for (int index = 0; index < nxagentMaxSelections; index++) { if (matchSelectionOwner(index, pClient, pWindow)) @@ -694,13 +695,14 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) */ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { - int index = 0; - while (index < nxagentMaxSelections && - lastSelectionOwner[index].remSelection != sel) + for (int index = 0; index < nxagentMaxSelections; index++) { - index++; + if (lastSelectionOwner[index].remSelection == sel) + { + return index; + } } - return index; + return nxagentMaxSelections; } /* @@ -709,13 +711,14 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) */ int nxagentFindCurrentSelectionIndex(Atom sel) { - int index = 0; - while (index < NumCurrentSelections && - CurrentSelections[index].selection != sel) + for (int index = 0; index < NumCurrentSelections; index++) { - index++; + if (CurrentSelections[index].selection == sel) + { + return index; + } } - return index; + return NumCurrentSelections; } /* -- cgit v1.2.3 From bf0e05fd166012b5fb38eb7533c27359b8d954f3 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 12 Oct 2020 20:12:28 +0200 Subject: Clipboard.c: restructure request accumulation code --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 39 +++++++++++++++----------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index cd3a890d0..30b781590 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2080,27 +2080,32 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 1; } - if (lastClients[index].clientPtr == client && (GetTimeInMillis() - lastClients[index].reqTime < ACCUM_TIME)) + if (lastClients[index].clientPtr == client) { - /* - * The same client made consecutive requests of clipboard content - * with less than 5 seconds time interval between them. - */ - #ifdef DEBUG - fprintf(stderr, "%s: Consecutives request from client %s selection [%u] " - "elapsed time [%u] clientAccum [%d]\n", __func__, nxagentClientInfoString(client), - selection, GetTimeInMillis() - lastClients[index].reqTime, clientAccum); - #endif - - clientAccum++; + if (GetTimeInMillis() - lastClients[index].reqTime < ACCUM_TIME) + { + /* + * The same client made consecutive requests of clipboard content + * with less than 5 seconds time interval between them. + */ + #ifdef DEBUG + fprintf(stderr, "%s: Consecutives request from client %s selection [%u] " + "elapsed time [%u] clientAccum [%d]\n", __func__, + nxagentClientInfoString(client), + selection, GetTimeInMillis() - lastClients[index].reqTime, + clientAccum); + #endif + + clientAccum++; + } } else { - /* reset clientAccum as now another client requested the clipboard content */ - if (lastClients[index].clientPtr != client) - { - clientAccum = 0; - } + /* + * reset clientAccum as now another client requested the clipboard + * content + */ + clientAccum = 0; } if (target == clientTEXT || -- cgit v1.2.3 From bff23cb94bc2fc3befe8d375c761b7e96b16984c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 12 Oct 2020 20:14:16 +0200 Subject: Clipboard.c: rephrase FIXME --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 30b781590..3e396d2c4 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2533,13 +2533,19 @@ Bool nxagentInitClipboard(WindowPtr pWin) * claim the ownership. Note that we report our serverWindow as * owner, not the real window! */ - if (IS_INTERNAL_OWNER(index) && lastSelectionOwner[index].window) - { - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); - } + if (IS_INTERNAL_OWNER(index) && lastSelectionOwner[index].window) + { + /* remSelection has already be adjusted above */ + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); + } + /* + * FIXME: Shouldn't we reset lastServers[index].* and + * lastClients[index].* here? Problem is that (internal) + * clients might still be waiting for answers. Should reply + * with failure then + */ } } - /* FIXME: Shouldn't we reset lastServers[index].* and lastClients[index].* here? */ } else { -- cgit v1.2.3 From 9d3683896885a43e693c0fd3c7165992633e5b7f Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 12 Oct 2020 21:09:31 +0200 Subject: Clipboard.c: move selection Atoms into separate arrays They really only change on startup and reconnect. Also with this change we now only have internal Atoms in the LastSelectionOwner array. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 88 ++++++++++++++------------ 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3e396d2c4..a92573f9d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -77,11 +77,13 @@ const int nxagentPrimarySelection = 0; const int nxagentClipboardSelection = 1; const int nxagentMaxSelections = 2; +/* store the remote atom for all selections */ +static XlibAtom *remSelAtoms = NULL; +static Atom *intSelAtoms = NULL; + typedef struct _SelectionOwner { ClientPtr client; /* internal client */ - Atom intSelection; /* internal Atom */ - XlibAtom remSelection; /* _external_ Atom */ Window window; /* internal window id */ WindowPtr windowPtr; /* internal window struct */ Time lastTimeChanged; /* internal time */ @@ -90,8 +92,7 @@ typedef struct _SelectionOwner /* * this contains the last selection owner in nxagent. The * lastTimeChanged is always an internal time. If .client is NULL the - * owner is outside nxagent. .selection will _always_ contain the - * external atom of the selection + * owner is outside nxagent. */ /* FIXME: these should also be stored per selection */ @@ -121,13 +122,12 @@ typedef struct _lastClient ClientPtr clientPtr; Window requestor; Atom property; - Atom intSelection; Atom target; Time time; Time reqTime; unsigned long propertySize; ClientSelectionStage stage; - int resource; /* nxcompext resource where collected proeprty data is stored */ + int resource; /* nxcompext resource where collected property data is stored */ } lastClient; static lastClient *lastClients; @@ -248,7 +248,7 @@ static void transferSelectionFromXServer(int resource, int index); #if 0 static void resetSelectionOwnerOnXServer(void); #endif -static void initSelectionOwnerData(int index, Atom intSelection, XlibAtom remSelection); +static void initSelectionOwnerData(int index); static void clearSelectionOwnerData(int index); static void storeSelectionOwnerData(int index, Selection *sel); static Bool matchSelectionOwner(int index, ClientPtr pClient, WindowPtr pWindow); @@ -282,6 +282,8 @@ static void printSelectionStat(int index) char *s = NULL; fprintf(stderr, " owner is inside nxagent? %s\n", IS_INTERNAL_OWNER(index) ? "yes" : "no"); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, remSelAtoms[index]); + fprintf(stderr, " selection Atom internal [%d][%s] remote [%ld][%s]\n", intSelAtoms[index], NameForAtom(intSelAtoms[index]), remSelAtoms[index], s); fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); fprintf(stderr, " lastSelectionOwner[].window [0x%x]\n", lOwner.window); if (lOwner.windowPtr) @@ -290,9 +292,6 @@ static void printSelectionStat(int index) fprintf(stderr, " lastSelectionOwner[].windowPtr -\n"); fprintf(stderr, " lastSelectionOwner[].lastTimeChanged [%u]\n", lOwner.lastTimeChanged); - fprintf(stderr, " lastSelectionOwner[].intSelection [% 4d][%s] (%s)\n", lOwner.intSelection, validateString(NameForAtom(lOwner.intSelection)), "inside nxagent"); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, lOwner.remSelection); - fprintf(stderr, " lastSelectionOwner[].remSelection [% 4ld][%s] (%s)\n", lOwner.remSelection, validateString(s), "remote X server"); SAFE_XFree(s); #ifdef CLIENTIDS fprintf(stderr, " CurrentSelections[].client [%p] index [%d] PID [%d] Cmd [%s]\n", @@ -319,7 +318,6 @@ static void printLastClientStat(int index) fprintf(stderr, " lastClients[].clientPtr (ClientPtr) %s\n", nxagentClientInfoString(lc.clientPtr)); fprintf(stderr, " lastClients[].requestor (Window) [0x%x]\n", lc.requestor); fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForAtom(lc.property)); - fprintf(stderr, " lastClients[].intSelection (Atom) [% 4d][%s]\n", lc.intSelection, NameForAtom(lc.intSelection)); fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForAtom(lc.target)); if (lc.time > 0) fprintf(stderr, " lastClients[].time (Time) [%u] ([%u]ms ago)\n", lc.time, GetTimeInMillis() - lc.time); @@ -427,9 +425,6 @@ static void resetClientSelectionStage(int index) lastClients[index].clientPtr = NULL; lastClients[index].requestor = 0; lastClients[index].property = 0; - /* NX_PRIMARY or clipboard atom */ - /* FIXME: we should only set the once on init and then never touch it again */ - lastClients[index].intSelection = lastSelectionOwner[index].intSelection; lastClients[index].target = 0; lastClients[index].time = 0; lastClients[index].reqTime = 0; @@ -615,10 +610,8 @@ static Bool validServerTargets(XlibAtom target) return False; } -static void initSelectionOwnerData(int index, Atom intSelection, XlibAtom remSelection) +static void initSelectionOwnerData(int index) { - lastSelectionOwner[index].intSelection = intSelection; - lastSelectionOwner[index].remSelection = remSelection; lastSelectionOwner[index].client = NullClient; lastSelectionOwner[index].window = screenInfo.screens[0]->root->drawable.id; lastSelectionOwner[index].windowPtr = NULL; @@ -697,7 +690,7 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { for (int index = 0; index < nxagentMaxSelections; index++) { - if (lastSelectionOwner[index].remSelection == sel) + if (remSelAtoms[index] == sel) { return index; } @@ -1120,7 +1113,7 @@ static void endTransfer(Bool success, int index) sendSelectionNotifyEventToClient(lastClients[index].clientPtr, lastClients[index].time, lastClients[index].requestor, - lastClients[index].intSelection, + intSelAtoms[index], lastClients[index].target, success == SELECTION_SUCCESS ? lastClients[index].property : None); } @@ -1486,10 +1479,11 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) { #ifdef DEBUG fprintf (stderr, "%s: lastClients[%d].intSelection [%d] selection [%d] .\n", - __func__, index, lastClients[index].intSelection, + __func__, index, intSelAtoms[index], nxagentRemoteToLocalAtom(e->selection)); #endif - if (lastClients[index].intSelection == nxagentRemoteToLocalAtom(e->selection)) + /* FIXME: take remSelAtoms[index]? */ + if (intSelAtoms[index] == nxagentRemoteToLocalAtom(e->selection)) { break; } @@ -1716,7 +1710,7 @@ static void resetSelectionOwnerOnXServer(void) for (int index = 0; index < nxagentMaxSelections; index++) { - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); #ifdef DEBUG fprintf(stderr, "%s: Reset selection state for selection [%d].\n", __func__, index); @@ -1871,7 +1865,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * inform the real X server that our serverWindow is the * clipboard owner. */ - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); /* * The real owner window (inside nxagent) is stored in @@ -1981,7 +1975,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif #ifdef DEBUG - fprintf(stderr, "%s: lastClients[%d].intSelection [%d] - selection [%d]\n", __func__, index, lastClients[index].intSelection, selection); + fprintf(stderr, "%s: intSelAtoms[%d] [%d] - selection [%d]\n", __func__, index, intSelAtoms[index], selection); #endif if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) @@ -2124,7 +2118,6 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, lastClients[index].clientPtr = client; lastClients[index].time = time; lastClients[index].property = property; - lastClients[index].intSelection = selection; lastClients[index].target = target; /* if the last client request time is more than 5s ago update it. Why? */ if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) @@ -2186,7 +2179,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) /* * On the real server, the right CLIPBOARD atom is * XInternAtom(nxagentDisplay, "CLIPBOARD", 1), which is stored in - * lastSelectionOwner[nxagentClipboardSelection].remSelection. For + * remSelAtoms[nxagentClipboardSelection]. For * PRIMARY there's nothing to map because that is identical on all * X servers (defined in Xatom.h). */ @@ -2199,7 +2192,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) } else if (local == clientCLIPBOARD) { - remote = lastSelectionOwner[nxagentClipboardSelection].remSelection; + remote = remSelAtoms[nxagentClipboardSelection]; } else { @@ -2367,7 +2360,7 @@ WindowPtr nxagentGetClipboardWindow(Atom property) { #ifdef DEBUG fprintf(stderr, "%s: Returning last [%d] selection owner window [%p] (0x%x).\n", __func__, - lastSelectionOwner[index].intSelection, + intSelAtoms[index], (void *)lastSelectionOwner[index].windowPtr, WINDOWID(lastSelectionOwner[index].windowPtr)); #endif @@ -2417,8 +2410,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) { FatalError("nxagentInitClipboard: Failed to allocate memory for the clipboard selections.\n"); } - initSelectionOwnerData(nxagentPrimarySelection, XA_PRIMARY, XA_PRIMARY); - initSelectionOwnerData(nxagentClipboardSelection, clientCLIPBOARD, nxagentAtoms[10]); /* CLIPBOARD */ + initSelectionOwnerData(nxagentPrimarySelection); + initSelectionOwnerData(nxagentClipboardSelection); SAFE_free(lastClients); lastClients = (lastClient *) calloc(nxagentMaxSelections, sizeof(lastClient)); @@ -2433,13 +2426,30 @@ Bool nxagentInitClipboard(WindowPtr pWin) { FatalError("nxagentInitClipboard: Failed to allocate memory for the last servers array.\n"); } + + SAFE_free(intSelAtoms); + intSelAtoms = (Atom *) calloc(nxagentMaxSelections, sizeof(Atom)); + if (intSelAtoms == NULL) + { + FatalError("nxagentInitClipboard: Failed to allocate memory for the internal selection Atoms array.\n"); + } + intSelAtoms[nxagentPrimarySelection] = XA_PRIMARY; + intSelAtoms[nxagentClipboardSelection] = clientCLIPBOARD; + + SAFE_free(remSelAtoms); + remSelAtoms = (XlibAtom *) calloc(nxagentMaxSelections, sizeof(XlibAtom)); + if (remSelAtoms == NULL) + { + FatalError("nxagentInitClipboard: Failed to allocate memory for the remote selection Atoms array.\n"); + } } - else - { - /* the clipboard selection atom might have changed on a new X - server. Primary is constant. */ - lastSelectionOwner[nxagentClipboardSelection].remSelection = nxagentAtoms[10]; /* CLIPBOARD */ - } + + /* + * the clipboard selection atom might have changed on a new X + * server. Primary is constant. + */ + remSelAtoms[nxagentPrimarySelection] = XA_PRIMARY; + remSelAtoms[nxagentClipboardSelection] = nxagentAtoms[10]; /* CLIPBOARD */ serverTARGETS = nxagentAtoms[6]; /* TARGETS */ serverTEXT = nxagentAtoms[7]; /* TEXT */ @@ -2487,7 +2497,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) for (int index = 0; index < nxagentMaxSelections; index++) { XFixesSelectSelectionInput(nxagentDisplay, serverWindow, - lastSelectionOwner[index].remSelection, + remSelAtoms[index], XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask); @@ -2535,8 +2545,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) */ if (IS_INTERNAL_OWNER(index) && lastSelectionOwner[index].window) { - /* remSelection has already be adjusted above */ - XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[index].remSelection, serverWindow, CurrentTime); + /* remSelAtoms have already been adjusted above */ + XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); } /* * FIXME: Shouldn't we reset lastServers[index].* and -- cgit v1.2.3 From 59ee58ee79d948223e74c2a8a745565da95c64aa Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 00:14:49 +0200 Subject: Clipboard.c: drop clientCLIPBOARD read the value from the intSelAtoms array instead --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index a92573f9d..3d33cb931 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -152,7 +152,6 @@ static Atom clientTIMESTAMP; static Atom clientTEXT; static Atom clientCOMPOUND_TEXT; static Atom clientUTF8_STRING; -static Atom clientCLIPBOARD; static char szAgentTARGETS[] = "TARGETS"; static char szAgentTEXT[] = "TEXT"; @@ -1792,8 +1791,8 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, if (pCurSel->pWin != NULL && nxagentOption(Clipboard) != ClipboardNone && /* FIXME: shouldn't we also check for != ClipboardClient? */ - (pCurSel->selection == XA_PRIMARY || - pCurSel->selection == clientCLIPBOARD)) + (pCurSel->selection == intSelAtoms[nxagentPrimarySelection] || + pCurSel->selection == intSelAtoms[nxagentClipboardSelection])) { #ifdef DEBUG fprintf(stderr, "%s: calling setSelectionOwnerOnXServer\n", __func__); @@ -2181,20 +2180,22 @@ XlibAtom translateLocalToRemoteSelection(Atom local) * XInternAtom(nxagentDisplay, "CLIPBOARD", 1), which is stored in * remSelAtoms[nxagentClipboardSelection]. For * PRIMARY there's nothing to map because that is identical on all - * X servers (defined in Xatom.h). + * X servers (defined in Xatom.h). We do it anyway so we do not + * require a special treatment. */ - XlibAtom remote; + XlibAtom remote = -1; - if (local == XA_PRIMARY) - { - remote = XA_PRIMARY; - } - else if (local == clientCLIPBOARD) + for (int index = 0; index < nxagentMaxSelections; index++) { - remote = remSelAtoms[nxagentClipboardSelection]; + if (local == intSelAtoms[index]) + { + remote = remSelAtoms[index]; + break; + } } - else + + if (remote == -1) { remote = nxagentLocalToRemoteAtom(local); } @@ -2396,7 +2397,6 @@ Bool nxagentInitClipboard(WindowPtr pWin) { /* cannot move that down to others - we need it for * initSelectionOwnerData ! */ - clientCLIPBOARD = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); @@ -2434,7 +2434,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) FatalError("nxagentInitClipboard: Failed to allocate memory for the internal selection Atoms array.\n"); } intSelAtoms[nxagentPrimarySelection] = XA_PRIMARY; - intSelAtoms[nxagentClipboardSelection] = clientCLIPBOARD; + intSelAtoms[nxagentClipboardSelection] = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); SAFE_free(remSelAtoms); remSelAtoms = (XlibAtom *) calloc(nxagentMaxSelections, sizeof(XlibAtom)); -- cgit v1.2.3 From 29413b32a2b9e7abacefe812f427366c6cc61210 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 00:17:27 +0200 Subject: Clipboard.c: fix comment position and init array pointer --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3d33cb931..e316b9bbf 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -95,8 +95,9 @@ typedef struct _SelectionOwner * owner is outside nxagent. */ -/* FIXME: these should also be stored per selection */ -static SelectionOwner *lastSelectionOwner; +static SelectionOwner *lastSelectionOwner = NULL; + +/* FIXME: can this also be stored per selection? */ static XlibAtom serverLastRequestedSelection; #define IS_INTERNAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NULL) -- cgit v1.2.3 From a31353bdd2023cec7453b94438b98fac7e5fae6a Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 00:18:32 +0200 Subject: Clipboard.c: compact clipboard status output require less lines --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 93 +++++++++++++------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index e316b9bbf..1aa2c050a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -281,29 +281,21 @@ static void printSelectionStat(int index) Selection curSel = CurrentSelections[index]; char *s = NULL; - fprintf(stderr, " owner is inside nxagent? %s\n", IS_INTERNAL_OWNER(index) ? "yes" : "no"); + fprintf(stderr, "selection [%d]:\n", index); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, remSelAtoms[index]); fprintf(stderr, " selection Atom internal [%d][%s] remote [%ld][%s]\n", intSelAtoms[index], NameForAtom(intSelAtoms[index]), remSelAtoms[index], s); + fprintf(stderr, " owner side %s\n", IS_INTERNAL_OWNER(index) ? "nxagent" : "real X server/none"); fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); fprintf(stderr, " lastSelectionOwner[].window [0x%x]\n", lOwner.window); if (lOwner.windowPtr) - fprintf(stderr, " lastSelectionOwner[].windowPtr [%p] ([0x%x]\n", (void *)lOwner.windowPtr, WINDOWID(lOwner.windowPtr)); + fprintf(stderr, " lastSelectionOwner[].windowPtr [%p] (-> [0x%x]\n", (void *)lOwner.windowPtr, WINDOWID(lOwner.windowPtr)); else fprintf(stderr, " lastSelectionOwner[].windowPtr -\n"); fprintf(stderr, " lastSelectionOwner[].lastTimeChanged [%u]\n", lOwner.lastTimeChanged); SAFE_XFree(s); -#ifdef CLIENTIDS - fprintf(stderr, " CurrentSelections[].client [%p] index [%d] PID [%d] Cmd [%s]\n", - (void *)curSel.client, - CLINDEX(curSel.client), - GetClientPid(curSel.client), - GetClientCmdName(curSel.client)); -#else - fprintf(stderr, " CurrentSelections[].client [%p] index [%d]\n", - (void *)curSel.client, - CLINDEX(curSel.client)); -#endif + fprintf(stderr, " CurrentSelections[].client %s\n", nxagentClientInfoString(curSel.client)); fprintf(stderr, " CurrentSelections[].window [0x%x]\n", curSel.window); return; } @@ -370,41 +362,52 @@ void nxagentDumpClipboardStat(void) } fprintf(stderr, "\n"); - fprintf(stderr, "PRIMARY\n"); - printSelectionStat(nxagentPrimarySelection); - printLastClientStat(nxagentPrimarySelection); - printLastServerStat(nxagentPrimarySelection); - fprintf(stderr, "CLIPBOARD\n"); - printSelectionStat(nxagentClipboardSelection); - printLastClientStat(nxagentClipboardSelection); - printLastServerStat(nxagentClipboardSelection); - - fprintf(stderr, "Atoms (remote X server)\n"); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTARGETS); - fprintf(stderr, " serverTARGETS [% 4ld][%s]\n", serverTARGETS, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTIMESTAMP); - fprintf(stderr, " serverTIMESTAMP [% 4ld][%s]\n", serverTIMESTAMP, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTEXT); - fprintf(stderr, " serverTEXT [% 4ld][%s]\n", serverTEXT, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverCOMPOUND_TEXT); - fprintf(stderr, " serverCOMPOUND_TEXT [% 4ld][%s]\n", serverCOMPOUND_TEXT, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverUTF8_STRING); - fprintf(stderr, " serverUTF8_STRING [% 4ld][%s]\n", serverUTF8_STRING, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); - fprintf(stderr, " serverTransToAgentProperty [% 4ld][%s]\n", serverTransFromAgentProperty, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverTransFromAgentProperty); - fprintf(stderr, " serverTransFromAgentProperty [% 4ld][%s]\n", serverTransToAgentProperty, validateString(s)); SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverLastRequestedSelection); fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, validateString(s)); - fprintf(stderr, "Atoms (inside nxagent)\n"); - fprintf(stderr, " clientTARGETS [% 4d][%s]\n", clientTARGETS, NameForAtom(clientTARGETS)); - fprintf(stderr, " clientTIMESTAMP [% 4d][%s]\n", clientTIMESTAMP, NameForAtom(clientTIMESTAMP)); - fprintf(stderr, " clientTEXT [% 4d][%s]\n", clientTEXT, NameForAtom(clientTEXT)); - fprintf(stderr, " clientCOMPOUND_TEXT [% 4d][%s]\n", clientCOMPOUND_TEXT, NameForAtom(clientCOMPOUND_TEXT)); - fprintf(stderr, " clientUTF8_STRING [% 4d][%s]\n", clientUTF8_STRING, NameForAtom(clientUTF8_STRING)); - fprintf(stderr, " clientCLIPBOARD [% 4d][%s]\n", clientCLIPBOARD, NameForAtom(clientCLIPBOARD)); - fprintf(stderr, " clientCutProperty [% 4d][%s]\n", clientCutProperty, NameForAtom(clientCutProperty)); +#define WIDTH 32 + Atom cl = 0; + XlibAtom sv = 0; + int len = WIDTH; + + fprintf(stderr, "Atoms internal%*sremote\n", WIDTH - 8, ""); + cl = clientTARGETS; sv = serverTARGETS; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + + cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + + cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + + cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + + cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + + sv = serverTransToAgentProperty; + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(s)); + + sv = serverTransFromAgentProperty; + SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); + fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(s)); + + cl = clientCutProperty; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); + fprintf(stderr, " clientCutProperty [% 4d][%s]%*s\n", cl, NameForAtom(cl), len + 2, "-" ); + + for (int index = 0; index < nxagentMaxSelections; index++) + { + printSelectionStat(index); + printLastClientStat(index); + printLastServerStat(index); + } fprintf(stderr, "\\------------------------------------------------------------------------------\n"); -- cgit v1.2.3 From 27ecb8959669207aaab2c8d5fae12e51b4708f57 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 00:22:22 +0200 Subject: Atoms.c: add helper to easily print Atom names in debugging --- nx-X11/programs/Xserver/hw/nxagent/Atoms.c | 48 ++++++++++++++++++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/Atoms.h | 16 ++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c index 2ddf87e55..d9ee678fa 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c @@ -750,6 +750,54 @@ XlibAtom nxagentLocalToRemoteAtom(Atom local) } } +/* + * This is mainly used to simplify debug prints. It returns + * the string for a remote atom or NULL if atom is unknown/invalid + * + * The string must NOT be freed by the caller. + */ +const char *nxagentRemoteAtomToString(XlibAtom remote) +{ + if (remote == None || remote == BAD_RESOURCE) + { + #ifdef DEBUG + fprintf(stderr, "%s: remote [%d] is None or BAD_RESOURCE\n", __func__, remote); + #endif + return NULL; + } + + /* no mapping required for built-in atoms */ + if (remote <= XA_LAST_PREDEFINED) + { + #ifdef DEBUG + fprintf(stderr, "%s: remote [%d] is <= XA_LAST_PREDEFINED [%d]\n", __func__, remote, XA_LAST_PREDEFINED); + #endif + + /* simply use the builtin string that is the same on every X server */ + return NameForAtom(remote); + } + + AtomMap *current = nxagentFindAtomByRemoteValue(remote); + if (current) + { + return current->string; + } + else + { + /* fill up the cache */ + Atom local = nxagentRemoteToLocalAtom(remote); + if (local != None) + { + current = nxagentFindAtomByRemoteValue(remote); + if (current) + { + return current->string; + } + } + } + return NULL; +} + Atom nxagentRemoteToLocalAtom(XlibAtom remote) { if (remote == None || remote == BAD_RESOURCE) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h index 9006b2253..8fe79883c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h @@ -71,12 +71,24 @@ void nxagentWMDetect(void); XlibAtom nxagentMakeAtom(char *, unsigned, Bool); /* - * Converts local atoms in remote atoms and viceversa. + * Converts local atoms to remote atoms and viceversa. */ Atom nxagentRemoteToLocalAtom(XlibAtom); XlibAtom nxagentLocalToRemoteAtom(Atom); -#endif +/* + * return the string belonging to an atom. String MUST NOT + * be freed by the caller! + */ +const char *nxagentRemoteAtomToString(XlibAtom remote); + +/* + * As nxagentRemoteAtomToString() is similar to NameForAtom() we + * supply a macro for calling it. + */ +#define NameForRemAtom(arg) nxagentRemoteAtomToString(arg) + +#endif /* XlibAtom */ #endif /* __Atoms_H__ */ -- cgit v1.2.3 From 204bbef0431933dce9eb0b8d4074d723a9f7345b Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 20:48:23 +0200 Subject: Clipboard.c: make use of the new helpers from Atoms.c This saves us from having to create intermediate strings and Xfreeing them again. Which can easily be forgotten, producing memleaks. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 163 ++++++++----------------- 1 file changed, 50 insertions(+), 113 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 1aa2c050a..2d000a4f7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -279,12 +279,12 @@ static void printSelectionStat(int index) { SelectionOwner lOwner = lastSelectionOwner[index]; Selection curSel = CurrentSelections[index]; - char *s = NULL; fprintf(stderr, "selection [%d]:\n", index); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, remSelAtoms[index]); - fprintf(stderr, " selection Atom internal [%d][%s] remote [%ld][%s]\n", intSelAtoms[index], NameForAtom(intSelAtoms[index]), remSelAtoms[index], s); + fprintf(stderr, " selection Atom internal [%d][%s] remote [%ld][%s]\n", + intSelAtoms[index], NameForAtom(intSelAtoms[index]), + remSelAtoms[index], NameForRemAtom(remSelAtoms[index])); fprintf(stderr, " owner side %s\n", IS_INTERNAL_OWNER(index) ? "nxagent" : "real X server/none"); fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); fprintf(stderr, " lastSelectionOwner[].window [0x%x]\n", lOwner.window); @@ -294,7 +294,6 @@ static void printSelectionStat(int index) fprintf(stderr, " lastSelectionOwner[].windowPtr -\n"); fprintf(stderr, " lastSelectionOwner[].lastTimeChanged [%u]\n", lOwner.lastTimeChanged); - SAFE_XFree(s); fprintf(stderr, " CurrentSelections[].client %s\n", nxagentClientInfoString(curSel.client)); fprintf(stderr, " CurrentSelections[].window [0x%x]\n", curSel.window); return; @@ -327,21 +326,14 @@ static void printLastClientStat(int index) static void printLastServerStat(int index) { lastServer ls = lastServers[index]; - char *s = NULL; - fprintf(stderr, " lastServer[].requestor (Window) [0x%x]\n", ls.requestor); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, ls.property); - fprintf(stderr, " lastServer[].property (Atom) [% 4ld][%s]\n", ls.property, validateString(s)); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, ls.target); - fprintf(stderr, " lastServer[].target (Atom) [% 4ld][%s]\n", ls.target, validateString(s)); + fprintf(stderr, " lastServer[].property (Atom) [% 4ld][%s]\n", ls.property, validateString(NameForRemAtom(ls.property))); + fprintf(stderr, " lastServer[].target (Atom) [% 4ld][%s]\n", ls.target, validateString(NameForRemAtom(ls.target))); fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); - SAFE_XFree(s); } void nxagentDumpClipboardStat(void) { - char *s = NULL; - fprintf(stderr, "/----- Clipboard internal status -----\n"); fprintf(stderr, " current time (Time) [%u]\n", GetTimeInMillis()); @@ -362,8 +354,7 @@ void nxagentDumpClipboardStat(void) } fprintf(stderr, "\n"); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, serverLastRequestedSelection); - fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, validateString(s)); + fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, validateString(NameForRemAtom(serverLastRequestedSelection))); #define WIDTH 32 Atom cl = 0; @@ -372,32 +363,25 @@ void nxagentDumpClipboardStat(void) fprintf(stderr, "Atoms internal%*sremote\n", WIDTH - 8, ""); cl = clientTARGETS; sv = serverTARGETS; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(s)); + fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); sv = serverTransToAgentProperty; - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(s)); + fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(NameForRemAtom(sv))); sv = serverTransFromAgentProperty; - SAFE_XFree(s); s = XGetAtomName(nxagentDisplay, sv); - fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(s)); + fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(NameForRemAtom(sv))); cl = clientCutProperty; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); fprintf(stderr, " clientCutProperty [% 4d][%s]%*s\n", cl, NameForAtom(cl), len + 2, "-" ); @@ -410,8 +394,6 @@ void nxagentDumpClipboardStat(void) } fprintf(stderr, "\\------------------------------------------------------------------------------\n"); - - SAFE_XFree(s); } /* @@ -809,27 +791,17 @@ static void replyRequestSelectionToXServer(XEvent *X, Bool success) void nxagentHandleSelectionRequestFromXServer(XEvent *X) { #ifdef DEBUG + if (X->xselectionrequest.requestor == serverWindow) { - char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); - char *strSelection = XGetAtomName(nxagentDisplay, X->xselectionrequest.selection); - char *strProperty = XGetAtomName(nxagentDisplay, X->xselectionrequest.property); - - if (X->xselectionrequest.requestor == serverWindow) - { - fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; - } - fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ - "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", - __func__, - X->xselectionrequest.selection, validateString(strSelection), - X->xselectionrequest.target, validateString(strTarget), - DisplayString(nxagentDisplay), X->xselectionrequest.requestor, - X->xselectionrequest.property, validateString(strProperty)); - - SAFE_XFree(strTarget); - SAFE_XFree(strSelection); - SAFE_XFree(strProperty); + fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; } + fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ + "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", + __func__, + X->xselectionrequest.selection, validateString(NameForRemAtom(X->xselectionrequest.selection)), + X->xselectionrequest.target, validateString(NameForRemAtom(X->xselectionrequest.target)), + DisplayString(nxagentDisplay), X->xselectionrequest.requestor, + X->xselectionrequest.property, validateString(NameForRemAtom(X->xselectionrequest.property)));; #endif if (!agentClipboardInitialized) @@ -894,9 +866,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) { - char *s = XGetAtomName(nxagentDisplay, targets[i]); - fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], s); - SAFE_XFree(s); + fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); } fprintf(stderr, "\n"); #endif @@ -986,17 +956,11 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) serverWindow, lastClients[index].time); #ifdef DEBUG - char *strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); - char *strSelection = XGetAtomName(nxagentDisplay, CurrentSelections[index].selection); - char *strProperty = XGetAtomName(nxagentDisplay, serverTransToAgentProperty); fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, - CurrentSelections[index].selection, strSelection, - X->xselectionrequest.target, strTarget, - serverTransToAgentProperty, strProperty, + CurrentSelections[index].selection, NameForRemAtom(CurrentSelections[index].selection)), + X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), + serverTransToAgentProperty, NameForRemAtom(serverTransToAgentProperty), serverWindow, lastClients[index].time); - SAFE_XFree(strTarget); - SAFE_XFree(strSelection); - SAFE_XFree(strProperty); #endif } else @@ -1075,10 +1039,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else { #ifdef DEBUG - char *s = XGetAtomName(nxagentDisplay, X->xselectionrequest.selection); - fprintf (stderr, "%s: no internal owner for selection [%ld][%s] - denying request.\n", __func__, - X->xselectionrequest.selection, s); - SAFE_XFree(s); + fprintf(stderr, "%s: no internal owner for selection [%ld][%s] - denying request.\n", __func__, + X->xselectionrequest.selection, NameForRemAtom(X->xselectionrequest.selection)); #endif /* deny the request */ @@ -1456,24 +1418,15 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) #ifdef DEBUG XSelectionEvent * e = (XSelectionEvent *)X; + if (e->requestor == serverWindow) { - char * p = XGetAtomName(nxagentDisplay, e->property); - char * t = XGetAtomName(nxagentDisplay, e->target); - char * s = XGetAtomName(nxagentDisplay, e->selection); - if (e->requestor == serverWindow) - { - fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; - } - - fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ - "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", - __func__, e->property, validateString(p), e->requestor, - validateString(s), e->target, - validateString(t), e->time, e->send_event); - SAFE_XFree(p); - SAFE_XFree(t); - SAFE_XFree(s); + fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; } + fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ + "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", + __func__, e->property, validateString(NameForRemAtom(e->property)), e->requestor, + validateString(NameForRemAtom(e->selection)), e->target, + validateString(NameForRemAtom(e->target)), e->time, e->send_event); #endif /* determine the selection we are talking about here */ @@ -1552,10 +1505,8 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) else { #ifdef DEBUG - char *s = XGetAtomName(nxagentDisplay, X->xselection.property); fprintf(stderr, "%s: Unexpected property [%ld][%s] - reporting conversion failure.\n", - __func__, X->xselection.property, s); - SAFE_XFree(s); + __func__, X->xselection.property, validateString(NameForRemAtom(X->xselection.property))); #endif endTransfer(SELECTION_FAULT, index); } @@ -1633,18 +1584,14 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) ulReturnItems); #ifdef DEBUG - { - char *s = XGetAtomName(nxagentDisplay, lastServers[index].property); - fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", - __func__, - lastServers[index].requestor, - lastServers[index].property, - s, - (int)(min(20, ulReturnItems * 8 / 8)), - (int)(min(20, ulReturnItems * 8 / 8)), - pszReturnData); - SAFE_XFree(s); - } + fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", + __func__, + lastServers[index].requestor, + lastServers[index].property, + NameForRemAtom(lastServers[index].property), + (int)(min(20, ulReturnItems * 8 / 8)), + (int)(min(20, ulReturnItems * 8 / 8)), + pszReturnData); #endif } @@ -2140,16 +2087,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * by a real time. The reply also contains time "0" which is * unexpected (for me) */ #ifdef DEBUG - char *t = XGetAtomName(nxagentDisplay, remTarget); - char *p = XGetAtomName(nxagentDisplay, remProperty); - char *s = XGetAtomName(nxagentDisplay, remSelection); fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, - serverWindow, remTarget, validateString(t), - remProperty, validateString(p), - remSelection, validateString(s)); - SAFE_XFree(t); - SAFE_XFree(p); - SAFE_XFree(s); + serverWindow, remTarget, validateString(NameForRemAtom(remTarget)), + remProperty, validateString(NameForRemAtom(remProperty)), + remSelection, validateString(NameForRemAtom(remSelection))); #endif XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); @@ -2205,10 +2146,8 @@ XlibAtom translateLocalToRemoteSelection(Atom local) } #ifdef DEBUG - char *r = XGetAtomName(nxagentDisplay, remote); fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld] [%s]\n", __func__, - local, NameForAtom(local), remote, validateString(r)); - SAFE_XFree(r); + local, NameForAtom(local), remote, validateString(NameForRemAtom(remote))); #endif return remote; @@ -2249,10 +2188,8 @@ XlibAtom translateLocalToRemoteTarget(Atom local) } #ifdef DEBUG - char *r = XGetAtomName(nxagentDisplay, remote); fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld] [%s]\n", __func__, - local, NameForAtom(local), remote, validateString(r)); - SAFE_XFree(r); + local, NameForAtom(local), remote, validateString(NameForRemAtom(remote))); #endif return remote; @@ -2525,7 +2462,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) #ifdef TEST fprintf(stderr, "%s: setting the ownership of %s to %lx" " and registering for PropertyChangeMask events\n", __func__, - validateString(XGetAtomName(nxagentDisplay, nxagentAtoms[10])), serverWindow); + validateString(NameForRemAtom(nxagentAtoms[10])), serverWindow); #endif XSetSelectionOwner(nxagentDisplay, nxagentAtoms[10], serverWindow, CurrentTime); -- cgit v1.2.3 From a470de00099d3b8f44797cec29cc5ce95eec4f33 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 20:57:14 +0200 Subject: Atoms.c: ensure to always return a valid string... ... by providing NameFor(Int|Rem)Atom() macros This way we do not have to validate it at various other places. --- nx-X11/programs/Xserver/hw/nxagent/Atoms.h | 6 +- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 99 +++++++++++++------------- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h index 8fe79883c..4dcdf7055 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h @@ -84,10 +84,10 @@ XlibAtom nxagentLocalToRemoteAtom(Atom); const char *nxagentRemoteAtomToString(XlibAtom remote); /* - * As nxagentRemoteAtomToString() is similar to NameForAtom() we - * supply a macro for calling it. + * supply two macros that also validate the output. */ -#define NameForRemAtom(arg) nxagentRemoteAtomToString(arg) +#define NameForIntAtom(_atom) validateString(NameForAtom(_atom)) +#define NameForRemAtom(_xlibatom) validateString(nxagentRemoteAtomToString(_xlibatom)) #endif /* XlibAtom */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 2d000a4f7..f430a01d1 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -283,7 +283,7 @@ static void printSelectionStat(int index) fprintf(stderr, "selection [%d]:\n", index); fprintf(stderr, " selection Atom internal [%d][%s] remote [%ld][%s]\n", - intSelAtoms[index], NameForAtom(intSelAtoms[index]), + intSelAtoms[index], NameForIntAtom(intSelAtoms[index]), remSelAtoms[index], NameForRemAtom(remSelAtoms[index])); fprintf(stderr, " owner side %s\n", IS_INTERNAL_OWNER(index) ? "nxagent" : "real X server/none"); fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); @@ -308,8 +308,8 @@ static void printLastClientStat(int index) fprintf(stderr, " lastClients[].windowPtr (WindowPtr) -\n"); fprintf(stderr, " lastClients[].clientPtr (ClientPtr) %s\n", nxagentClientInfoString(lc.clientPtr)); fprintf(stderr, " lastClients[].requestor (Window) [0x%x]\n", lc.requestor); - fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForAtom(lc.property)); - fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForAtom(lc.target)); + fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForIntAtom(lc.property)); + fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForIntAtom(lc.target)); if (lc.time > 0) fprintf(stderr, " lastClients[].time (Time) [%u] ([%u]ms ago)\n", lc.time, GetTimeInMillis() - lc.time); else @@ -327,8 +327,8 @@ static void printLastServerStat(int index) { lastServer ls = lastServers[index]; fprintf(stderr, " lastServer[].requestor (Window) [0x%x]\n", ls.requestor); - fprintf(stderr, " lastServer[].property (Atom) [% 4ld][%s]\n", ls.property, validateString(NameForRemAtom(ls.property))); - fprintf(stderr, " lastServer[].target (Atom) [% 4ld][%s]\n", ls.target, validateString(NameForRemAtom(ls.target))); + fprintf(stderr, " lastServer[].property (Atom) [% 4ld][%s]\n", ls.property, NameForRemAtom(ls.property)); + fprintf(stderr, " lastServer[].target (Atom) [% 4ld][%s]\n", ls.target, NameForRemAtom(ls.target)); fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); } @@ -354,7 +354,7 @@ void nxagentDumpClipboardStat(void) } fprintf(stderr, "\n"); - fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, validateString(NameForRemAtom(serverLastRequestedSelection))); + fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemAtom(serverLastRequestedSelection)); #define WIDTH 32 Atom cl = 0; @@ -362,29 +362,29 @@ void nxagentDumpClipboardStat(void) int len = WIDTH; fprintf(stderr, "Atoms internal%*sremote\n", WIDTH - 8, ""); - cl = clientTARGETS; sv = serverTARGETS; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); + cl = clientTARGETS; sv = serverTARGETS; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); + fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); - cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); + cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); + fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); - cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); + cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); + fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); - cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); + cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); + fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); - cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForAtom(cl), len, "", sv, validateString(NameForRemAtom(sv))); + cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); + fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); sv = serverTransToAgentProperty; - fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(NameForRemAtom(sv))); + fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, NameForRemAtom(sv)); sv = serverTransFromAgentProperty; - fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, validateString(NameForRemAtom(sv))); + fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, NameForRemAtom(sv)); - cl = clientCutProperty; len = (int)(WIDTH - 9 - strlen(NameForAtom(cl))); - fprintf(stderr, " clientCutProperty [% 4d][%s]%*s\n", cl, NameForAtom(cl), len + 2, "-" ); + cl = clientCutProperty; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); + fprintf(stderr, " clientCutProperty [% 4d][%s]%*s\n", cl, NameForIntAtom(cl), len + 2, "-" ); for (int index = 0; index < nxagentMaxSelections; index++) { @@ -798,10 +798,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", __func__, - X->xselectionrequest.selection, validateString(NameForRemAtom(X->xselectionrequest.selection)), - X->xselectionrequest.target, validateString(NameForRemAtom(X->xselectionrequest.target)), + X->xselectionrequest.selection, NameForRemAtom(X->xselectionrequest.selection), + X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), DisplayString(nxagentDisplay), X->xselectionrequest.requestor, - X->xselectionrequest.property, validateString(NameForRemAtom(X->xselectionrequest.property)));; + X->xselectionrequest.property, NameForRemAtom(X->xselectionrequest.property)); #endif if (!agentClipboardInitialized) @@ -1028,10 +1028,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s] " \ "target [%d][%s] requestor [0x%x] selection [%d][%s].\n", __func__, nxagentClientInfoString(lastSelectionOwner[index].client), - x.u.selectionRequest.property, NameForAtom(x.u.selectionRequest.property), - x.u.selectionRequest.target, NameForAtom(x.u.selectionRequest.target), + x.u.selectionRequest.property, NameForIntAtom(x.u.selectionRequest.property), + x.u.selectionRequest.target, NameForIntAtom(x.u.selectionRequest.target), x.u.selectionRequest.requestor, - x.u.selectionRequest.selection, NameForAtom(x.u.selectionRequest.selection)); + x.u.selectionRequest.selection, NameForIntAtom(x.u.selectionRequest.selection)); #endif /* no reply to Xserver yet - we will do that once the answer of the above sendEventToClient arrives */ @@ -1069,7 +1069,7 @@ static void endTransfer(Bool success, int index) #ifdef DEBUG if (success == SELECTION_SUCCESS) fprintf(stderr, "%s: sending notification to client %s, property [%d][%s]\n", __func__, - nxagentClientInfoString(lastClients[index].clientPtr), lastClients[index].property, NameForAtom(lastClients[index].property)); + nxagentClientInfoString(lastClients[index].clientPtr), lastClients[index].property, NameForIntAtom(lastClients[index].property)); else fprintf(stderr, "%s: sending negative notification to client %s\n", __func__, nxagentClientInfoString(lastClients[index].clientPtr)); @@ -1375,7 +1375,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) #ifdef DEBUG fprintf(stderr, "%s: Selection property [%d][%s] changed to [\"%*.*s\"...]\n", __func__, lastClients[index].property, - validateString(NameForAtom(lastClients[index].property)), + NameForIntAtom(lastClients[index].property), (int)(min(20, ulReturnItems * resultFormat / 8)), (int)(min(20, ulReturnItems * resultFormat / 8)), pszReturnData); @@ -1424,9 +1424,9 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", - __func__, e->property, validateString(NameForRemAtom(e->property)), e->requestor, - validateString(NameForRemAtom(e->selection)), e->target, - validateString(NameForRemAtom(e->target)), e->time, e->send_event); + __func__, e->property, NameForRemAtom(e->property), e->requestor, + NameForRemAtom(e->selection), e->target, + NameForRemAtom(e->target), e->time, e->send_event); #endif /* determine the selection we are talking about here */ @@ -1506,7 +1506,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) { #ifdef DEBUG fprintf(stderr, "%s: Unexpected property [%ld][%s] - reporting conversion failure.\n", - __func__, X->xselection.property, validateString(NameForRemAtom(X->xselection.property))); + __func__, X->xselection.property, NameForRemAtom(X->xselection.property)); #endif endTransfer(SELECTION_FAULT, index); } @@ -1737,7 +1737,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, { #ifdef DEBUG fprintf(stderr, "%s: pCurSel->pWin [0x%x]\n", __func__, WINDOWID(pCurSel->pWin)); - fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForAtom(pCurSel->selection)); + fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForIntAtom(pCurSel->selection)); #endif if (pCurSel->pWin != NULL && @@ -1861,17 +1861,16 @@ FIXME int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, Window requestor, Atom property, Atom target, Time time) { - const char *strTarget = NameForAtom(target); - #ifdef DEBUG fprintf(stderr, "%s: client %s requests sel [%s] " "on window [0x%x] prop [%d][%s] target [%d][%s].\n", __func__, - nxagentClientInfoString(client), validateString(NameForAtom(selection)), requestor, - property, validateString(NameForAtom(property)), - target, validateString(strTarget)); + nxagentClientInfoString(client), NameForIntAtom(selection), requestor, + property, NameForIntAtom(property), + target, NameForIntAtom(target)); #endif - if (strTarget == NULL) + /* cannot use NameForIntAtom() here! */ + if (NameForAtom(target) == NULL) { #ifdef DEBUG fprintf(stderr, "%s: cannot find name for target Atom [%d] - returning\n", __func__, target); @@ -1975,7 +1974,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #ifdef DEBUG fprintf(stderr, "%s: available targets [%d]:\n", __func__, numTargets); for (int j = 0; j < numTargets; j++) - fprintf(stderr, "%s: %s\n", __func__, NameForAtom(targets[j])); + fprintf(stderr, "%s: %s\n", __func__, NameForIntAtom(targets[j])); fprintf(stderr, "\n"); #endif @@ -2079,7 +2078,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #ifdef DEBUG fprintf(stderr, "%s: replacing local by remote property: [%d][%s] -> [%ld][%s]\n", - __func__, property, NameForAtom(property), + __func__, property, NameForIntAtom(property), remProperty, "NX_CUT_BUFFER_SERVER"); #endif @@ -2088,9 +2087,9 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * unexpected (for me) */ #ifdef DEBUG fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, - serverWindow, remTarget, validateString(NameForRemAtom(remTarget)), - remProperty, validateString(NameForRemAtom(remProperty)), - remSelection, validateString(NameForRemAtom(remSelection))); + serverWindow, remTarget, NameForRemAtom(remTarget), + remProperty, NameForRemAtom(remProperty), + remSelection, NameForRemAtom(remSelection)); #endif XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); @@ -2108,7 +2107,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, /* deny request */ #ifdef DEBUG fprintf(stderr, "%s: Unsupported target [%d][%s] - denying request\n", __func__, target, - validateString(NameForAtom(target))); + NameForIntAtom(target)); #endif sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); @@ -2147,7 +2146,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) #ifdef DEBUG fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld] [%s]\n", __func__, - local, NameForAtom(local), remote, validateString(NameForRemAtom(remote))); + local, NameForIntAtom(local), remote, NameForRemAtom(remote)); #endif return remote; @@ -2189,7 +2188,7 @@ XlibAtom translateLocalToRemoteTarget(Atom local) #ifdef DEBUG fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld] [%s]\n", __func__, - local, NameForAtom(local), remote, validateString(NameForRemAtom(remote))); + local, NameForIntAtom(local), remote, NameForRemAtom(remote)); #endif return remote; @@ -2225,9 +2224,9 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) #ifdef DEBUG fprintf(stderr, "%s: Received SendNotify by client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, - event->u.selectionNotify.property, NameForAtom(event->u.selectionNotify.property), - event->u.selectionNotify.target, NameForAtom(event->u.selectionNotify.target), - event->u.selectionNotify.selection, NameForAtom(event->u.selectionNotify.selection), + event->u.selectionNotify.property, NameForIntAtom(event->u.selectionNotify.property), + event->u.selectionNotify.target, NameForIntAtom(event->u.selectionNotify.target), + event->u.selectionNotify.selection, NameForIntAtom(event->u.selectionNotify.selection), event->u.selectionNotify.requestor, event->u.selectionNotify.time); #endif -- cgit v1.2.3 From 855ddf2815b6eaeb92fb6c00de374b3b8226b5db Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 21:31:01 +0200 Subject: Clipboard.c: avoid superflous atom conversion --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f430a01d1..7fcf63a00 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1416,8 +1416,8 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) return; } - #ifdef DEBUG XSelectionEvent * e = (XSelectionEvent *)X; + #ifdef DEBUG if (e->requestor == serverWindow) { fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; @@ -1434,12 +1434,10 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) for (index = 0; index < nxagentMaxSelections; index++) { #ifdef DEBUG - fprintf (stderr, "%s: lastClients[%d].intSelection [%d] selection [%d] .\n", - __func__, index, intSelAtoms[index], - nxagentRemoteToLocalAtom(e->selection)); + fprintf (stderr, "%s: index [%d] selAtom [%ld] remselection [%ld] .\n", + __func__, index, remSelAtoms[index], e->selection); #endif - /* FIXME: take remSelAtoms[index]? */ - if (intSelAtoms[index] == nxagentRemoteToLocalAtom(e->selection)) + if (remSelAtoms[index] == e->selection) { break; } -- cgit v1.2.3 From 87eb4236a9ecf9f7ea79b3bf9b3b72a162f4e807 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 21:39:24 +0200 Subject: Clipboard.c: fix type in status output --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 7fcf63a00..e0ba9cf27 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -327,8 +327,8 @@ static void printLastServerStat(int index) { lastServer ls = lastServers[index]; fprintf(stderr, " lastServer[].requestor (Window) [0x%x]\n", ls.requestor); - fprintf(stderr, " lastServer[].property (Atom) [% 4ld][%s]\n", ls.property, NameForRemAtom(ls.property)); - fprintf(stderr, " lastServer[].target (Atom) [% 4ld][%s]\n", ls.target, NameForRemAtom(ls.target)); + fprintf(stderr, " lastServer[].property (XlibAtom) [% 4ld][%s]\n", ls.property, NameForRemAtom(ls.property)); + fprintf(stderr, " lastServer[].target (XlibAtom) [% 4ld][%s]\n", ls.target, NameForRemAtom(ls.target)); fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); } -- cgit v1.2.3 From 9dd509c01020e2d4b05d4f963ff7eef00e4f9c42 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 13 Oct 2020 22:41:36 +0200 Subject: Clipboard.c: fix: use XlibWindow instead of Window --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index e0ba9cf27..9a7e407db 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -71,7 +71,7 @@ static int clientAccum; XlibAtom serverTransToAgentProperty; Atom clientCutProperty; -static Window serverWindow; +static XlibWindow serverWindow; const int nxagentPrimarySelection = 0; const int nxagentClipboardSelection = 1; @@ -134,7 +134,7 @@ typedef struct _lastClient static lastClient *lastClients; typedef struct _lastServer { - Window requestor; + XlibWindow requestor; XlibAtom property; XlibAtom target; Time time; @@ -326,7 +326,7 @@ static void printLastClientStat(int index) static void printLastServerStat(int index) { lastServer ls = lastServers[index]; - fprintf(stderr, " lastServer[].requestor (Window) [0x%x]\n", ls.requestor); + fprintf(stderr, " lastServer[].requestor (XlibWindow) [0x%lx]\n", ls.requestor); fprintf(stderr, " lastServer[].property (XlibAtom) [% 4ld][%s]\n", ls.property, NameForRemAtom(ls.property)); fprintf(stderr, " lastServer[].target (XlibAtom) [% 4ld][%s]\n", ls.target, NameForRemAtom(ls.target)); fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); @@ -341,7 +341,7 @@ void nxagentDumpClipboardStat(void) fprintf(stderr, " clientAccum (int) [%d]\n", clientAccum); fprintf(stderr, " nxagentMaxSelections (int) [%d]\n", nxagentMaxSelections); fprintf(stderr, " NumCurrentSelections (int) [%d]\n", NumCurrentSelections); - fprintf(stderr, " serverWindow (Window) [0x%x]\n", serverWindow); + fprintf(stderr, " serverWindow (XlibWindow) [0x%lx]\n", serverWindow); fprintf(stderr, " Clipboard mode "); switch(nxagentOption(Clipboard)) @@ -458,7 +458,7 @@ int GetWindowProperty(WindowPtr pWin, Atom property, long longOffset, long longL */ static Status sendSelectionNotifyEventToXServer(XSelectionEvent *event_to_send) { - Window w = event_to_send->requestor; + XlibWindow w = event_to_send->requestor; event_to_send->type = SelectionNotify; event_to_send->send_event = True; @@ -474,17 +474,17 @@ static Status sendSelectionNotifyEventToXServer(XSelectionEvent *event_to_send) */ if (result == 0) { - fprintf(stderr, "%s: XSendEvent to [0x%x] failed.\n", __func__, w); + fprintf(stderr, "%s: XSendEvent to [0x%lx] failed.\n", __func__, w); } else { if (result == BadValue || result == BadWindow) { - fprintf(stderr, "%s: WARNING! XSendEvent to [0x%x] failed: %s\n", __func__, w, getXErrorString(result)); + fprintf(stderr, "%s: WARNING! XSendEvent to [0x%lx] failed: %s\n", __func__, w, getXErrorString(result)); } else { - fprintf(stderr, "%s: XSendEvent() successfully sent to [0x%x]\n", __func__, w); + fprintf(stderr, "%s: XSendEvent() successfully sent to [0x%lx]\n", __func__, w); } } #endif @@ -825,7 +825,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } #ifdef DEBUG - fprintf(stderr, "%s: lastServers[%d].requestor [0x%x].\n", __func__, index, lastServers[index].requestor); + fprintf(stderr, "%s: lastServers[%d].requestor [0x%lx].\n", __func__, index, lastServers[index].requestor); #endif /* lastServers[index].requestor in non-NULL (= we are currently in the transfer phase) */ @@ -956,7 +956,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) serverWindow, lastClients[index].time); #ifdef DEBUG - fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%x] time [%u] .\n", __func__, + fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%lx] time [%u] .\n", __func__, CurrentSelections[index].selection, NameForRemAtom(CurrentSelections[index].selection)), X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), serverTransToAgentProperty, NameForRemAtom(serverTransToAgentProperty), @@ -1582,7 +1582,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) ulReturnItems); #ifdef DEBUG - fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", + fprintf(stderr, "%s: XChangeProperty sent to remote window [0x%lx] for property [%ld][%s] value [\"%*.*s\"...]\n", __func__, lastServers[index].requestor, lastServers[index].property, @@ -1776,7 +1776,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) } #ifdef DEBUG - fprintf(stderr, "%s: Setting selection owner to serverwindow ([0x%x]).\n", __func__, + fprintf(stderr, "%s: Setting selection owner to serverwindow ([0x%lx]).\n", __func__, serverWindow); #endif @@ -1789,7 +1789,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) nxagentClientInfoString(pSelection->client)); fprintf(stderr, "%s: lastSelectionOwner.window [0x%x] -> [0x%x]\n", __func__, lastSelectionOwner[index].window, pSelection->window); - fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%x])\n", __func__, + fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%lx] (serverWindow: [0x%lx])\n", __func__, (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, nxagentWindow(pSelection->pWin), serverWindow); fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, @@ -1804,7 +1804,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * real X server and nxagent's clients - let's not disturb * FIXME: by continuing after the warning were ARE disturbing! */ - fprintf (stderr, "%s: WARNING! lastServers[%d].requestor window [0x%x] already set.\n", + fprintf (stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set.\n", __func__, index, lastServers[index].requestor); } #endif @@ -2084,7 +2084,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * by a real time. The reply also contains time "0" which is * unexpected (for me) */ #ifdef DEBUG - fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, + fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%lx] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, serverWindow, remTarget, NameForRemAtom(remTarget), remProperty, NameForRemAtom(remProperty), remSelection, NameForRemAtom(remSelection)); @@ -2239,7 +2239,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) } #ifdef DEBUG - fprintf(stderr, "%s: lastServers[index].requestor is [0x%x].\n", __func__, lastServers[index].requestor); + fprintf(stderr, "%s: lastServers[index].requestor is [0x%lx].\n", __func__, lastServers[index].requestor); #endif /* @@ -2412,7 +2412,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) } #ifdef TEST - fprintf(stderr, "%s: Setting owner of selection [%d][%s] to serverwindow [0x%x]\n", __func__, + fprintf(stderr, "%s: Setting owner of selection [%d][%s] to serverWindow [0x%lx]\n", __func__, (int) serverTransToAgentProperty, "NX_CUT_BUFFER_SERVER", serverWindow); #endif -- cgit v1.2.3 From eba654ea77de62c4de288e5eb3eacaf0b2b938b4 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 23:25:04 +0200 Subject: Clipboard.c: target forwarding (Part 1/2) Clients on the real X server requesting the available targets for a selection will no longer get a predefined list but a the list of targets from the owning internal client. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 298 ++++++++++--------------- 1 file changed, 118 insertions(+), 180 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 9a7e407db..56cbf5eef 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -239,7 +239,6 @@ XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, False }; extern Display *nxagentDisplay; -static Bool validServerTargets(XlibAtom target); static void setClientSelectionStage(int stage, int index); static void endTransfer(Bool success, int index); #define SELECTION_SUCCESS True @@ -538,63 +537,6 @@ static void sendSelectionNotifyEventToClient(ClientPtr client, sendEventToClient(client, &x); } -/* - * Check if target is a valid content type target sent by the real X - * server, like .e.g XA_STRING or UTF8_STRING. Other, non content type - * targets like "TARGETS" or "TIMESTAMP" will return false. - */ -static Bool validServerTargets(XlibAtom target) -{ - if (target == XA_STRING) - { - #ifdef DEBUG - fprintf(stderr, "%s: valid target [XA_STRING].\n", __func__); - #endif - return True; - } - else if (target == serverTEXT) - { - #ifdef DEBUG - fprintf(stderr, "%s: valid target [TEXT].\n", __func__); - #endif - return True; - } - /* by dimbor */ - else if (target == serverUTF8_STRING) - { - #ifdef DEBUG - fprintf(stderr, "%s: valid target [UTF8_STRING].\n", __func__); - #endif - return True; - } - else if (target == serverCOMPOUND_TEXT) - { - #ifdef DEBUG - fprintf(stderr, "%s: valid target [COMPOUND_TEXT].\n", __func__); - #endif - return True; - } - else if (target == serverTARGETS) - { - #ifdef DEBUG - fprintf(stderr, "%s: special target [TARGETS].\n", __func__); - #endif - return False; - } - else if (target == serverTIMESTAMP) - { - #ifdef DEBUG - fprintf(stderr, "%s: special target [TIMESTAMP].\n", __func__); - #endif - return False; - } - - #ifdef DEBUG - fprintf(stderr, "%s: invalid target [%lu].\n", __func__, target); - #endif - return False; -} - static void initSelectionOwnerData(int index) { lastSelectionOwner[index].client = NullClient; @@ -839,93 +781,39 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) return; } - /* this is a special request like TARGETS or TIMESTAMP */ - if (!validServerTargets(X->xselectionrequest.target)) + if (X->xselectionrequest.target == serverTIMESTAMP) { - if (X->xselectionrequest.target == serverTARGETS) - { - /* - * the selection request target is TARGETS. The requestor is - * asking for a list of supported data formats. - * - * The selection does not matter here, we will return this for - * PRIMARY and CLIPBOARD. - * - * The list is aligned with the one in nxagentConvertSelection. - * - * FIXME: the perfect solution should not just answer with a - * hardcoded list but ask the real owner what format it - * supports. The result should then be sent to the original - * requestor. - */ - - long targets[] = {XA_STRING, serverUTF8_STRING, serverTEXT, serverCOMPOUND_TEXT, serverTARGETS, serverTIMESTAMP}; - int numTargets = sizeof(targets) / sizeof(targets[0]); - - #ifdef DEBUG - fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); - for (int i = 0; i < numTargets; i++) - { - fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); - } - fprintf(stderr, "\n"); - #endif - - /* - * pass on the requested list by setting the property provided - * by the requestor accordingly. - */ - XChangeProperty(nxagentDisplay, - X->xselectionrequest.requestor, - X->xselectionrequest.property, - XInternAtom(nxagentDisplay, "ATOM", 0), - 32, - PropModeReplace, - (unsigned char*)&targets, - numTargets); - - replyRequestSelectionToXServer(X, True); - } - else if (X->xselectionrequest.target == serverTIMESTAMP) - { - /* - * Section 2.6.2 of the ICCCM states: - * TIMESTAMP - To avoid some race conditions, it is important - * that requestors be able to discover the timestamp the owner - * used to acquire ownership. Until and unless the protocol is - * changed so that a GetSelectionOwner request returns the - * timestamp used to acquire ownership, selection owners must - * support conversion to TIMESTAMP, returning the timestamp they - * used to obtain the selection. - * - * FIXME: ensure we are reporting an _external_ timestamp - * FIXME: for a 32 bit property list we need to pass a "long" array, not "char"! - * FIXME: selection has already been checked above, so we do not need to check again here - */ + /* + * Section 2.6.2 of the ICCCM states: + * TIMESTAMP - To avoid some race conditions, it is important + * that requestors be able to discover the timestamp the owner + * used to acquire ownership. Until and unless the protocol is + * changed so that a GetSelectionOwner request returns the + * timestamp used to acquire ownership, selection owners must + * support conversion to TIMESTAMP, returning the timestamp they + * used to obtain the selection. + * + * FIXME: ensure we are reporting an _external_ timestamp + * FIXME: for a 32 bit property list we need to pass a "long" array, not "char"! + * FIXME: selection has already been checked above, so we do not need to check again here + */ - XChangeProperty(nxagentDisplay, - X->xselectionrequest.requestor, - X->xselectionrequest.property, - XA_INTEGER, - 32, - PropModeReplace, - (unsigned char *) &lastSelectionOwner[index].lastTimeChanged, - 1); - replyRequestSelectionToXServer(X, True); - } - else - { - /* - * unknown special request - probably bug! Check if this code handles all cases - * that are handled in validServerTargets! - */ - #ifdef DEBUG - fprintf(stderr, "%s: unknown special target [%ld] - denying request.\n", __func__, X->xselectionrequest.target); - #endif - replyRequestSelectionToXServer(X, False); - } + XChangeProperty(nxagentDisplay, + X->xselectionrequest.requestor, + X->xselectionrequest.property, + XA_INTEGER, + 32, + PropModeReplace, + (unsigned char *) &lastSelectionOwner[index].lastTimeChanged, + 1); + replyRequestSelectionToXServer(X, True); return; } + else + { + fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, + XGetAtomName(nxagentDisplay, X->xselectionrequest.target)); + } /* * reaching this means the request is a normal, valid request. We @@ -994,10 +882,6 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) lastServers[index].target = X->xselectionrequest.target; lastServers[index].time = X->xselectionrequest.time; - /* by dimbor */ - if (lastServers[index].target != XA_STRING) - lastServers[index].target = serverUTF8_STRING; - /* prepare the request (like XConvertSelection, but internally) */ xEvent x = {0}; x.u.u.type = SelectionRequest; @@ -1015,12 +899,6 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * x.u.selectionRequest.requestor = lastSelectionOwner[index].window; */ - /* by dimbor (idea from zahvatov) */ - if (X->xselectionrequest.target != XA_STRING) - x.u.selectionRequest.target = clientUTF8_STRING; - else - x.u.selectionRequest.target = XA_STRING; - x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); sendEventToClient(lastSelectionOwner[index].client, &x); @@ -1568,35 +1446,89 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } else { - /* Fill the property on the initial requestor with the requested data */ - /* The XChangeProperty source code reveals it will always - return 1, no matter what, so no need to check the result */ - /* FIXME: better use the format returned by above request */ - XChangeProperty(nxagentDisplay, - lastServers[index].requestor, - lastServers[index].property, - lastServers[index].target, - 8, - PropModeReplace, - pszReturnData, - ulReturnItems); - - #ifdef DEBUG - fprintf(stderr, "%s: XChangeProperty sent to remote window [0x%lx] for property [%ld][%s] value [\"%*.*s\"...]\n", - __func__, - lastServers[index].requestor, - lastServers[index].property, - NameForRemAtom(lastServers[index].property), - (int)(min(20, ulReturnItems * 8 / 8)), - (int)(min(20, ulReturnItems * 8 / 8)), - pszReturnData); - #endif + if (lastServers[index].target == serverTARGETS) + { + #ifdef DEBUG + fprintf(stderr, "%s: ulReturnItems [%ld]\n", __func__, ulReturnItems); + fprintf(stderr, "%s: resultformat [%d]\n", __func__, resultFormat); + #endif + + XlibAtom * targets = calloc(sizeof(XlibAtom), ulReturnItems); + if (targets == NULL) + { + #ifdef WARNING + fprintf(stderr, "%s: WARNING! Could not alloc memory for clipboard targets transmission.\n", __func__); + #endif + /* this will effectively lead to the request being answered as failed */ + lastServers[index].property = None; + } + else + { + /* Convert the targets to remote atoms */ + XlibAtom *addr = targets; + unsigned int numTargets = ulReturnItems; + + for (int i = 0; i < numTargets; i++) + { + Atom local = *((Atom*)(pszReturnData + i*resultFormat/8)); + XlibAtom remote = nxagentLocalToRemoteAtom(local); + *(addr++) = remote; + + #ifdef DEBUG + char *s = XGetAtomName(nxagentDisplay, remote); + fprintf(stderr, "%s: converting atom: local [%d][%s] -> remote [%ld][%s]\n", __func__,local, NameForAtom(local), remote, s); + SAFE_XFree(s); + #endif + } + + /* FIXME: do we need to take care of swapping byte order here? */ + XChangeProperty(nxagentDisplay, + lastServers[index].requestor, + lastServers[index].property, + XInternAtom(nxagentDisplay, "ATOM", 0), + 32, + PropModeReplace, + (unsigned char*)targets, + numTargets); + + SAFE_free(targets); + } + } + else + { + /* Fill the property on the initial requestor with the requested data */ + /* The XChangeProperty source code reveals it will always + return 1, no matter what, so no need to check the result */ + /* FIXME: better use the format returned by above request */ + XChangeProperty(nxagentDisplay, + lastServers[index].requestor, + lastServers[index].property, + lastServers[index].target, + 8, + PropModeReplace, + pszReturnData, + ulReturnItems); + #ifdef DEBUG + { + char *s = XGetAtomName(nxagentDisplay, lastServers[index].property); + fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", + __func__, + lastServers[index].requestor, + lastServers[index].property, + s, + (int)(min(20, ulReturnItems * 8 / 8)), + (int)(min(20, ulReturnItems * 8 / 8)), + pszReturnData); + SAFE_XFree(s); + } + #endif + } + + /* FIXME: free it or not? */ + /* + * SAFE_XFree(pszReturnData); + */ } - - /* FIXME: free it or not? */ - /* - * SAFE_XFree(pszReturnData); - */ } /* @@ -1656,6 +1588,7 @@ static void resetSelectionOwnerOnXServer(void) * Only for PRIMARY and CLIPBOARD selections. */ + for (int index = 0; index < nxagentMaxSelections; index++) { XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); @@ -2179,9 +2112,13 @@ XlibAtom translateLocalToRemoteTarget(Atom local) remote = serverCOMPOUND_TEXT; } #endif + else if (local == clientTARGETS) + { + remote = serverTARGETS; + } else { - remote = XA_STRING; + remote = nxagentLocalToRemoteAtom(local); } #ifdef DEBUG @@ -2411,6 +2348,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) return False; } + /* this is probably to communicate with nomachine nxclient */ #ifdef TEST fprintf(stderr, "%s: Setting owner of selection [%d][%s] to serverWindow [0x%lx]\n", __func__, (int) serverTransToAgentProperty, "NX_CUT_BUFFER_SERVER", serverWindow); -- cgit v1.2.3 From a87ee1e8ff27e9592aa8ead83a443949f1c2fe46 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Sep 2020 23:54:36 +0200 Subject: Clipboard.c: target forwarding (Part 2/2) Internal clients asking for the available targets for a selection will no longer get a predefined list but a the list of targets from the owning client on the real X server. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 208 ++++++++++++------------- 1 file changed, 98 insertions(+), 110 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 56cbf5eef..3721ace60 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -812,7 +812,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else { fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, - XGetAtomName(nxagentDisplay, X->xselectionrequest.target)); + NameForRemAtom(X->xselectionrequest.target)); } /* @@ -1244,22 +1244,64 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) fprintf(stderr, "%s: Got property content from remote server. size [%lu] bytes.\n", __func__, (ulReturnItems * resultFormat / 8)); #endif - ChangeWindowProperty(lastClients[index].windowPtr, - lastClients[index].property, - lastClients[index].target, - resultFormat, PropModeReplace, - ulReturnItems, pszReturnData, 1); + if (lastClients[index].target == clientTARGETS) + { + Atom * targets = calloc(sizeof(Atom), ulReturnItems); + if (targets == NULL) + { + #ifdef WARNING + fprintf(stderr, "%s: WARNING! Could not alloc memory for clipboard targets transmission.\n", __func__); + #endif - #ifdef DEBUG - fprintf(stderr, "%s: Selection property [%d][%s] changed to [\"%*.*s\"...]\n", __func__, - lastClients[index].property, - NameForIntAtom(lastClients[index].property), - (int)(min(20, ulReturnItems * resultFormat / 8)), - (int)(min(20, ulReturnItems * resultFormat / 8)), - pszReturnData); - #endif + /* operation failed */ + endTransfer(SELECTION_FAULT, index); + } + else + { + /* fprintf(stderr, "sizeof(Atom) [%lu], sizeof(XlibAtom) [%lu], sizeof(long) [%lu], sizeof(CARD32) [%lu] sizeof(INT32) [%lu]\n", sizeof(Atom), sizeof(XlibAtom), sizeof(long), sizeof(CARD32), sizeof(INT32)); */ + + Atom *addr = targets; + unsigned int numTargets = ulReturnItems; + + for (int i = 0; i < numTargets; i++) + { + XlibAtom remote = *((XlibAtom*)(pszReturnData + i*resultFormat/8)); + Atom local = nxagentRemoteToLocalAtom(remote); + *(addr++) = local; + + #ifdef DEBUG + fprintf(stderr, "%s: converting atom: remote [%u][%s] -> local [%u][%s]\n", __func__, + (unsigned int)remote, NameForRemAtom(remote), local, NameForIntAtom(local)); + #endif + } + ChangeWindowProperty(lastClients[index].windowPtr, + lastClients[index].property, + MakeAtom("ATOM", 4, 1), + 32, PropModeReplace, + ulReturnItems, (unsigned char*)targets, 1); - endTransfer(SELECTION_SUCCESS, index); + endTransfer(SELECTION_SUCCESS, index); + } + } + else + { + ChangeWindowProperty(lastClients[index].windowPtr, + lastClients[index].property, + lastClients[index].target, + resultFormat, PropModeReplace, + ulReturnItems, pszReturnData, 1); + + #ifdef DEBUG + fprintf(stderr, "%s: Selection property [%d][%s] changed to [\"%*.*s\"...]\n", __func__, + lastClients[index].property, + validateString(NameForIntAtom(lastClients[index].property)), + (int)(min(20, ulReturnItems * resultFormat / 8)), + (int)(min(20, ulReturnItems * resultFormat / 8)), + pszReturnData); + #endif + + endTransfer(SELECTION_SUCCESS, index); + } } break; } @@ -1475,9 +1517,8 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) *(addr++) = remote; #ifdef DEBUG - char *s = XGetAtomName(nxagentDisplay, remote); - fprintf(stderr, "%s: converting atom: local [%d][%s] -> remote [%ld][%s]\n", __func__,local, NameForAtom(local), remote, s); - SAFE_XFree(s); + fprintf(stderr, "%s: converting atom: local [%d][%s] -> remote [%ld][%s]\n", __func__, + local, NameForIntAtom(local), remote, NameForRemAtom(remote)); #endif } @@ -1510,16 +1551,14 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) ulReturnItems); #ifdef DEBUG { - char *s = XGetAtomName(nxagentDisplay, lastServers[index].property); fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", __func__, lastServers[index].requestor, lastServers[index].property, - s, + NameForRemAtom(lastServers[index].property), (int)(min(20, ulReturnItems * 8 / 8)), (int)(min(20, ulReturnItems * 8 / 8)), pszReturnData); - SAFE_XFree(s); } #endif } @@ -1891,38 +1930,6 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } } - /* - * The selection request target is TARGETS. The requestor is asking - * for a list of supported data formats. - * - * The list is aligned with the one in nxagentHandleSelectionRequestFromXServer. - */ - if (target == clientTARGETS) - { - Atom targets[] = {XA_STRING, clientUTF8_STRING, clientTEXT, clientCOMPOUND_TEXT, clientTARGETS, clientTIMESTAMP}; - int numTargets = sizeof(targets) / sizeof(targets[0]); - - #ifdef DEBUG - fprintf(stderr, "%s: available targets [%d]:\n", __func__, numTargets); - for (int j = 0; j < numTargets; j++) - fprintf(stderr, "%s: %s\n", __func__, NameForIntAtom(targets[j])); - fprintf(stderr, "\n"); - #endif - - ChangeWindowProperty(pWin, - property, - MakeAtom("ATOM", 4, 1), - sizeof(Atom)*8, - PropModeReplace, - numTargets, - &targets, - 1); - - sendSelectionNotifyEventToClient(client, time, requestor, selection, target, property); - - return 1; - } - /* * Section 2.6.2 of the ICCCM states: * "TIMESTAMP - To avoid some race conditions, it is important @@ -1982,70 +1989,51 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, clientAccum = 0; } - if (target == clientTEXT || - target == XA_STRING || - target == clientCOMPOUND_TEXT || - target == clientUTF8_STRING) - { - setClientSelectionStage(SelectionStageNone, index); - - /* - * store the original requestor, we need that later after - * serverTransToAgentProperty contains the desired selection content - */ - lastClients[index].requestor = requestor; - lastClients[index].windowPtr = pWin; - lastClients[index].clientPtr = client; - lastClients[index].time = time; - lastClients[index].property = property; - lastClients[index].target = target; - /* if the last client request time is more than 5s ago update it. Why? */ - if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) - lastClients[index].reqTime = GetTimeInMillis(); - - XlibAtom remSelection = translateLocalToRemoteSelection(selection); - XlibAtom remTarget = translateLocalToRemoteTarget(target); - XlibAtom remProperty = serverTransToAgentProperty; - - #ifdef DEBUG - fprintf(stderr, "%s: replacing local by remote property: [%d][%s] -> [%ld][%s]\n", - __func__, property, NameForIntAtom(property), - remProperty, "NX_CUT_BUFFER_SERVER"); - #endif + setClientSelectionStage(SelectionStageNone, index); - /* FIXME: check why using CurrentTime will not replace the value - * by a real time. The reply also contains time "0" which is - * unexpected (for me) */ - #ifdef DEBUG - fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%lx] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, - serverWindow, remTarget, NameForRemAtom(remTarget), - remProperty, NameForRemAtom(remProperty), - remSelection, NameForRemAtom(remSelection)); - #endif + /* + * store the original requestor, we need that later after + * serverTransToAgentProperty contains the desired selection content + */ + lastClients[index].requestor = requestor; + lastClients[index].windowPtr = pWin; + lastClients[index].clientPtr = client; + lastClients[index].time = time; + lastClients[index].property = property; + lastClients[index].target = target; + /* if the last client request time is more than 5s ago update it. Why? */ + if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) + lastClients[index].reqTime = GetTimeInMillis(); + + XlibAtom remSelection = translateLocalToRemoteSelection(selection); + XlibAtom remTarget = translateLocalToRemoteTarget(target); + XlibAtom remProperty = serverTransToAgentProperty; - XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); + #ifdef DEBUG + fprintf(stderr, "%s: replacing local by remote property: [%d][%s] -> [%ld][%s]\n", + __func__, property, NameForIntAtom(property), + remProperty, "NX_CUT_BUFFER_SERVER"); + #endif - /* XConvertSelection will always return (check the source!), so no need to check */ + #ifdef DEBUG + fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, + serverWindow, remTarget, NameForRemAtom(remTarget), + remProperty, NameForRemAtom(remProperty), + remSelection, NameForRemAtom(remSelection)); + #endif - #ifdef DEBUG - fprintf(stderr, "%s: Sent XConvertSelection\n", __func__); - #endif + UpdateCurrentTime(); + XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, + serverWindow, CurrentTime); - return 1; - } - else - { - /* deny request */ - #ifdef DEBUG - fprintf(stderr, "%s: Unsupported target [%d][%s] - denying request\n", __func__, target, - NameForIntAtom(target)); - #endif - sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + /* XConvertSelection will always return 1 (check the source!), so no + need to check */ - return 1; - } + #ifdef DEBUG + fprintf(stderr, "%s: Sent XConvertSelection\n", __func__); + #endif - return 0; + return 1; } XlibAtom translateLocalToRemoteSelection(Atom local) -- cgit v1.2.3 From 8316d614a8d297d8b8c9d1a65346a325413b2a0d Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 24 Sep 2020 00:44:49 +0200 Subject: Clipboard.c: add some more selection atoms we currently do not support them but as they require a special treatment we need to know them and report an error if they appear. --- nx-X11/programs/Xserver/hw/nxagent/Atoms.c | 17 ++- nx-X11/programs/Xserver/hw/nxagent/Atoms.h | 2 +- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 141 ++++++++++++++++++++++--- 3 files changed, 145 insertions(+), 15 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c index d9ee678fa..86022ee62 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c @@ -76,7 +76,7 @@ Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS]; * Careful! Do not change indices here! Some of those are referenced * at other places via nxagentAtoms[index]. */ -static char *nxagentAtomNames[NXAGENT_NUMBER_OF_ATOMS + 1] = +static char *nxagentAtomNames[NXAGENT_NUMBER_OF_ATOMS + 2] = { "NX_IDENTITY", /* 0 */ /* NX_IDENTITY was used in earlier nx versions to communicate @@ -135,6 +135,21 @@ static char *nxagentAtomNames[NXAGENT_NUMBER_OF_ATOMS + 1] = "COMPOUND_TEXT", /* 16 */ /* one of the supported data formats for selections. Standard ICCCM Atom */ + "INCR", /* 17 */ + /* incremental clipboard transfers. Standard + ICCCM Atom */ + "MULTIPLE", /* 18 */ + /* request selection in multiple formats at once. Standard + ICCCM Atom */ + "DELETE", /* 19 */ + /* request to delete selection. Standard ICCCM Atom */ + "INSERT_SELECTION", /* 20 */ + /* request to insert other selection. Standard ICCCM Atom */ + "INSERT_PROPERTY", /* 21 */ + /* request to insert content of property into selection. Standard + ICCCM Atom */ + "SAVE_TARGETS", /* 22 */ + /* request tp save clipboard content to clipboard manager on exit */ NULL, NULL }; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h index 4dcdf7055..84da3ec8e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h @@ -30,7 +30,7 @@ #include "../../include/window.h" #include "screenint.h" -#define NXAGENT_NUMBER_OF_ATOMS 18 +#define NXAGENT_NUMBER_OF_ATOMS 23 extern Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS]; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3721ace60..072dd1a3d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -142,25 +142,47 @@ typedef struct _lastServer { static lastServer *lastServers; +/* + * FIXME: use (additional) Atoms.c helpers to get rid of all these + * Atoms and strings + */ static XlibAtom serverTARGETS; static XlibAtom serverTIMESTAMP; +static XlibAtom serverINCR; +static XlibAtom serverMULTIPLE; +static XlibAtom serverDELETE; +static XlibAtom serverINSERT_SELECTION; +static XlibAtom serverINSERT_PROPERTY; +static XlibAtom serverSAVE_TARGETS; static XlibAtom serverTEXT; static XlibAtom serverCOMPOUND_TEXT; static XlibAtom serverUTF8_STRING; static XlibAtom serverTransFromAgentProperty; -static Atom clientTARGETS; -static Atom clientTIMESTAMP; -static Atom clientTEXT; -static Atom clientCOMPOUND_TEXT; -static Atom clientUTF8_STRING; - -static char szAgentTARGETS[] = "TARGETS"; -static char szAgentTEXT[] = "TEXT"; -static char szAgentTIMESTAMP[] = "TIMESTAMP"; -static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; -static char szAgentUTF8_STRING[] = "UTF8_STRING"; -static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; -static char szAgentCLIPBOARD[] = "CLIPBOARD"; +static Atom clientTARGETS; +static Atom clientTIMESTAMP; +static Atom clientINCR; +static Atom clientMULTIPLE; +static Atom clientDELETE; +static Atom clientINSERT_SELECTION; +static Atom clientINSERT_PROPERTY; +static Atom clientSAVE_TARGETS; +static Atom clientTEXT; +static Atom clientCOMPOUND_TEXT; +static Atom clientUTF8_STRING; + +static char szAgentTARGETS[] = "TARGETS"; +static char szAgentTEXT[] = "TEXT"; +static char szAgentTIMESTAMP[] = "TIMESTAMP"; +static char szAgentINCR[] = "INCR"; +static char szAgentMULTIPLE[] = "MULTIPLE"; +static char szAgentDELETE[] = "DELETE"; +static char szAgentINSERT_SELECTION[] = "INSERT_SELECTION"; +static char szAgentINSERT_PROPERTY[] = "INSERT_PROPERTY"; +static char szAgentSAVE_TARGETS[] = "SAVE_TARGETS"; +static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; +static char szAgentUTF8_STRING[] = "UTF8_STRING"; +static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; +static char szAgentCLIPBOARD[] = "CLIPBOARD"; /* number of milliseconds to wait for a conversion from the real X server. */ #define CONVERSION_TIMEOUT 5000 @@ -809,6 +831,46 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, True); return; } + else if (X->xselectionrequest.target == serverMULTIPLE) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [MULTIPLE] - denying request.\n", __func__); + #endif + replyRequestSelectionToXServer(X, False); + return; + } + else if (X->xselectionrequest.target == serverDELETE) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [DELETE] - denying request.\n", __func__); + #endif + replyRequestSelectionToXServer(X, False); + return; + } + else if (X->xselectionrequest.target == serverINSERT_SELECTION) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [INSERT_SELECTION] - denying request.\n", __func__); + #endif + replyRequestSelectionToXServer(X, False); + return; + } + else if (X->xselectionrequest.target == serverINSERT_PROPERTY) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [INSERT_PROPERTY] - denying request.\n", __func__); + #endif + replyRequestSelectionToXServer(X, False); + return; + } + else if (X->xselectionrequest.target == serverSAVE_TARGETS) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [SAVE_TARGETS] - denying request.\n", __func__); + #endif + replyRequestSelectionToXServer(X, False); + return; + } else { fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, @@ -1960,6 +2022,46 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, sendSelectionNotifyEventToClient(client, time, requestor, selection, target, property); return 1; } + else if (target == clientMULTIPLE) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [MULTIPLE] - denying request.\n", __func__); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } + else if (target == clientDELETE) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [DELETE] - denying request.\n", __func__); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } + else if (target == clientINSERT_SELECTION) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [INSERT_SELECTION] - denying request.\n", __func__); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } + else if (target == clientINSERT_PROPERTY) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [INSERT_PROPERTY] - denying request.\n", __func__); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } + else if (target == clientSAVE_TARGETS) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [SAVE_TARGETS] - denying request.\n", __func__); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } if (lastClients[index].clientPtr == client) { @@ -2260,11 +2362,18 @@ Bool nxagentInitClipboard(WindowPtr pWin) { /* cannot move that down to others - we need it for * initSelectionOwnerData ! */ + /* FIXME: it is probably better to re-use the strings from Atoms.c here */ clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); clientUTF8_STRING = MakeAtom(szAgentUTF8_STRING, strlen(szAgentUTF8_STRING), True); clientTIMESTAMP = MakeAtom(szAgentTIMESTAMP, strlen(szAgentTIMESTAMP), True); + clientINCR = MakeAtom(szAgentINCR, strlen(szAgentINCR), True); + clientMULTIPLE = MakeAtom(szAgentMULTIPLE, strlen(szAgentMULTIPLE), True); + clientDELETE = MakeAtom(szAgentDELETE, strlen(szAgentDELETE), True); + clientINSERT_SELECTION = MakeAtom(szAgentINSERT_SELECTION, strlen(szAgentINSERT_SELECTION), True); + clientINSERT_PROPERTY = MakeAtom(szAgentINSERT_PROPERTY, strlen(szAgentINSERT_PROPERTY), True); + clientSAVE_TARGETS = MakeAtom(szAgentSAVE_TARGETS, strlen(szAgentSAVE_TARGETS), True); SAFE_free(lastSelectionOwner); lastSelectionOwner = (SelectionOwner *) malloc(nxagentMaxSelections * sizeof(SelectionOwner)); @@ -2319,6 +2428,12 @@ Bool nxagentInitClipboard(WindowPtr pWin) serverCOMPOUND_TEXT = nxagentAtoms[16]; /* COMPOUND_TEXT */ serverUTF8_STRING = nxagentAtoms[12]; /* UTF8_STRING */ serverTIMESTAMP = nxagentAtoms[11]; /* TIMESTAMP */ + serverINCR = nxagentAtoms[17]; /* INCR */ + serverMULTIPLE = nxagentAtoms[18]; /* MULTIPLE */ + serverDELETE = nxagentAtoms[19]; /* DELETE */ + serverINSERT_SELECTION = nxagentAtoms[20]; /* INSERT_SELECTION */ + serverINSERT_PROPERTY = nxagentAtoms[21]; /* INSERT_PROPERTY */ + serverSAVE_TARGETS = nxagentAtoms[22]; /* SAVE_TARGETS */ /* * Server side properties to hold pasted data. -- cgit v1.2.3 From ba02ad3ad65eb353734aafd6e394683c57fbe070 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 24 Sep 2020 01:01:22 +0200 Subject: Clipboard.c: add FIXMEs --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 072dd1a3d..9dc5f8ad7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2138,6 +2138,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 1; } +/* FIXME: do we still need this special treatment? Can't we just + call nxagentLocalToRemoteAtom() everywhere? */ XlibAtom translateLocalToRemoteSelection(Atom local) { /* @@ -2173,6 +2175,8 @@ XlibAtom translateLocalToRemoteSelection(Atom local) return remote; } +/* FIXME: do we still need this special treatment? Can't we just + call nxagentLocalToRemoteAtom() everywhere? */ XlibAtom translateLocalToRemoteTarget(Atom local) { /* -- cgit v1.2.3 From 533f08ddb9748c20bd736f356c3a7fe38f53a113 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 26 Oct 2020 23:18:27 +0100 Subject: Clipboard.c: add TARGET_SIZES --- nx-X11/programs/Xserver/hw/nxagent/Atoms.c | 8 +++++++- nx-X11/programs/Xserver/hw/nxagent/Atoms.h | 2 +- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c index 86022ee62..6ce8b21e8 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c @@ -149,7 +149,13 @@ static char *nxagentAtomNames[NXAGENT_NUMBER_OF_ATOMS + 2] = /* request to insert content of property into selection. Standard ICCCM Atom */ "SAVE_TARGETS", /* 22 */ - /* request tp save clipboard content to clipboard manager on exit */ + /* request to save clipboard content to clipboard manager on + exit, see + https://www.freedesktop.org/wiki/ClipboardManager */ + "TARGET_SIZES", /* 23 */ + /* request to retrieve the sizes of the clipboard content in + various formats, see + https://www.freedesktop.org/wiki/ClipboardManager */ NULL, NULL }; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h index 84da3ec8e..4a73a817d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h @@ -30,7 +30,7 @@ #include "../../include/window.h" #include "screenint.h" -#define NXAGENT_NUMBER_OF_ATOMS 23 +#define NXAGENT_NUMBER_OF_ATOMS 24 extern Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS]; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 9dc5f8ad7..dd8b049db 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -154,6 +154,7 @@ static XlibAtom serverDELETE; static XlibAtom serverINSERT_SELECTION; static XlibAtom serverINSERT_PROPERTY; static XlibAtom serverSAVE_TARGETS; +static XlibAtom serverTARGET_SIZES; static XlibAtom serverTEXT; static XlibAtom serverCOMPOUND_TEXT; static XlibAtom serverUTF8_STRING; @@ -166,6 +167,7 @@ static Atom clientDELETE; static Atom clientINSERT_SELECTION; static Atom clientINSERT_PROPERTY; static Atom clientSAVE_TARGETS; +static Atom clientTARGET_SIZES; static Atom clientTEXT; static Atom clientCOMPOUND_TEXT; static Atom clientUTF8_STRING; @@ -179,6 +181,7 @@ static char szAgentDELETE[] = "DELETE"; static char szAgentINSERT_SELECTION[] = "INSERT_SELECTION"; static char szAgentINSERT_PROPERTY[] = "INSERT_PROPERTY"; static char szAgentSAVE_TARGETS[] = "SAVE_TARGETS"; +static char szAgentTARGET_SIZES[] = "TARGET_SIZES"; static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; static char szAgentUTF8_STRING[] = "UTF8_STRING"; static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; @@ -871,6 +874,14 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } + else if (X->xselectionrequest.target == serverTARGET_SIZES) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [TARGET_SIZES] - denying request.\n", __func__); + #endif + replyRequestSelectionToXServer(X, False); + return; + } else { fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, @@ -2062,6 +2073,14 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); return 1; } + else if (target == clientTARGET_SIZES) + { + #ifdef DEBUG + fprintf(stderr, "%s: (currently) unsupported target [TARGET_SIZES] - denying request.\n", __func__); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } if (lastClients[index].clientPtr == client) { @@ -2378,6 +2397,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) clientINSERT_SELECTION = MakeAtom(szAgentINSERT_SELECTION, strlen(szAgentINSERT_SELECTION), True); clientINSERT_PROPERTY = MakeAtom(szAgentINSERT_PROPERTY, strlen(szAgentINSERT_PROPERTY), True); clientSAVE_TARGETS = MakeAtom(szAgentSAVE_TARGETS, strlen(szAgentSAVE_TARGETS), True); + clientTARGET_SIZES = MakeAtom(szAgentTARGET_SIZES, strlen(szAgentTARGET_SIZES), True); SAFE_free(lastSelectionOwner); lastSelectionOwner = (SelectionOwner *) malloc(nxagentMaxSelections * sizeof(SelectionOwner)); @@ -2438,6 +2458,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) serverINSERT_SELECTION = nxagentAtoms[20]; /* INSERT_SELECTION */ serverINSERT_PROPERTY = nxagentAtoms[21]; /* INSERT_PROPERTY */ serverSAVE_TARGETS = nxagentAtoms[22]; /* SAVE_TARGETS */ + serverTARGET_SIZES = nxagentAtoms[23]; /* TARGET_SIZES */ /* * Server side properties to hold pasted data. -- cgit v1.2.3 From 9ec41748484c5e00460a93432141a179bc158fa2 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 26 Oct 2020 23:18:55 +0100 Subject: Clipboard.c: extend comments --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index dd8b049db..28d56b758 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1857,14 +1857,19 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) /* * inform the real X server that our serverWindow is the * clipboard owner. + * https://www.freedesktop.org/wiki/ClipboardManager/ states + * "In order to support peers who use the XFIXES extension to + * watch clipboard ownership changes, clipboard owners should + * reacquire the clipboard whenever the content or metadata (e.g + * the list of supported targets) changes." */ XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); /* * The real owner window (inside nxagent) is stored in - * lastSelectionOwner.window. lastSelectionOwner.windowPtr - * points to the struct that contains all information about the - * owner window. + * lastSelectionOwner[index].window. + * lastSelectionOwner[index].windowPtr points to the struct that + * contains all information about the owner window. */ storeSelectionOwnerData(index, pSelection); -- cgit v1.2.3 From 90947c1f7c5b345447a8b991e513a60c4f70fbdd Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 26 Oct 2020 23:52:30 +0100 Subject: nxagent: add option -textclipboard textclipboard= in the options file --- nx-X11/programs/Xserver/hw/nxagent/Args.c | 19 ++ nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 228 ++++++++++++++++++++++- nx-X11/programs/Xserver/hw/nxagent/Options.c | 1 + nx-X11/programs/Xserver/hw/nxagent/Options.h | 7 + nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 | 13 ++ 5 files changed, 261 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.c b/nx-X11/programs/Xserver/hw/nxagent/Args.c index be13efacd..ea17e4813 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Args.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c @@ -972,6 +972,12 @@ int ddxProcessArgument(int argc, char *argv[], int i) return 2; } + if (!strcmp(argv[i], "-textclipboard")) + { + nxagentChangeOption(TextClipboard, True); + return 1; + } + if (!strcmp(argv[i], "-bs")) { nxagentChangeOption(BackingStore, BackingStoreNever); @@ -1487,6 +1493,18 @@ static void nxagentParseSingleOption(char *name, char *value) } return; } + else if (!strcmp(name, "textclipboard")) + { + if (!strcmp(value, "0")) + { + nxagentChangeOption(TextClipboard, False); + } + else + { + nxagentChangeOption(TextClipboard, True); + } + return; + } else { #ifdef DEBUG @@ -2129,6 +2147,7 @@ void ddxUseMsg(void) ErrorF("-nokbreset don't reset keyboard device if the session is resumed\n"); ErrorF("-noxkblock always allow applications to change layout through XKEYBOARD\n"); ErrorF("-autograb enable autograb\n"); + ErrorF("-textclipboard limit clipboard data to text only\n"); ErrorF("-irlimit maximum image data rate to the encoder input in kB/s.\n"); ErrorF("-tile WxH maximum size of image tiles (minimum allowed: 32x32)\n"); ErrorF("-keystrokefile file file with keyboard shortcut definitions\n"); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 28d56b758..fb2595e68 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -264,6 +264,7 @@ XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, False }; extern Display *nxagentDisplay; +static Bool isTextTarget(XlibAtom target); static void setClientSelectionStage(int stage, int index); static void endTransfer(Bool success, int index); #define SELECTION_SUCCESS True @@ -562,6 +563,48 @@ static void sendSelectionNotifyEventToClient(ClientPtr client, sendEventToClient(client, &x); } +/* + * Check if target is a valid text content type target sent by the real X + * server, like .e.g XA_STRING or UTF8_STRING. + */ +static Bool isTextTarget(XlibAtom target) +{ + if (target == XA_STRING) + { + #ifdef DEBUG + fprintf(stderr, "%s: valid target [XA_STRING].\n", __func__); + #endif + return True; + } + else if (target == serverTEXT) + { + #ifdef DEBUG + fprintf(stderr, "%s: valid target [TEXT].\n", __func__); + #endif + return True; + } + else if (target == serverUTF8_STRING) + { + #ifdef DEBUG + fprintf(stderr, "%s: valid target [UTF8_STRING].\n", __func__); + #endif + return True; + } + else if (target == serverCOMPOUND_TEXT) + { + #ifdef DEBUG + fprintf(stderr, "%s: valid target [COMPOUND_TEXT].\n", __func__); + #endif + return True; + } + /* FIXME: add text/plain */ + + #ifdef DEBUG + fprintf(stderr, "%s: not a text target [%lu].\n", __func__, target); + #endif + return False; +} + static void initSelectionOwnerData(int index) { lastSelectionOwner[index].client = NullClient; @@ -806,7 +849,61 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) return; } - if (X->xselectionrequest.target == serverTIMESTAMP) + if (X->xselectionrequest.target == serverTARGETS) + { + /* + * In TextClipboard mode answer with a predefined list of + * targets. This is just the previous implementation of handling + * the clipboard. + */ + if (nxagentOption(TextClipboard)) + { + /* + * the selection request target is TARGETS. The requestor is + * asking for a list of supported data formats. + * + * The selection does not matter here, we will return this for + * PRIMARY and CLIPBOARD. + * + * The list is aligned with the one in nxagentConvertSelection() + * and in isTextTarget(). + */ + + XlibAtom targets[] = {XA_STRING, serverUTF8_STRING, serverTEXT, serverCOMPOUND_TEXT, + serverTARGETS, serverTIMESTAMP}; + int numTargets = sizeof(targets) / sizeof(targets[0]); + + #ifdef DEBUG + fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); + for (int i = 0; i < numTargets; i++) + { + fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); + } + fprintf(stderr, "\n"); + #endif + + /* + * pass on the requested list by setting the property provided + * by the requestor accordingly. + */ + XChangeProperty(nxagentDisplay, + X->xselectionrequest.requestor, + X->xselectionrequest.property, + XInternAtom(nxagentDisplay, "ATOM", 0), + 32, + PropModeReplace, + (unsigned char*)targets, + numTargets); + + replyRequestSelectionToXServer(X, True); + return; + } + else + { + /* do nothing, let TARGETS be passed on to the owner later */ + } + } + else if (X->xselectionrequest.target == serverTIMESTAMP) { /* * Section 2.6.2 of the ICCCM states: @@ -882,12 +979,28 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } - else + + if (nxagentOption(TextClipboard)) { - fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, - NameForRemAtom(X->xselectionrequest.target)); + if (!isTextTarget(X->xselectionrequest.target)) + { + #ifdef DEBUG + fprintf(stderr, "%s: denying request for non-text target [%ld][%s].\n", __func__, + X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target)); + #endif + + replyRequestSelectionToXServer(X, False); + + return; + } + /* go on, target is acceptable */ } + #ifdef DEBUG + fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, + NameForRemAtom(X->xselectionrequest.target)); + #endif + /* * reaching this means the request is a normal, valid request. We * can process it now. @@ -967,12 +1080,34 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) /* * Don't send the same window, some programs are clever and * verify cut and paste operations inside the same window and - * don't Notify at all. + * don't notify at all. * * x.u.selectionRequest.requestor = lastSelectionOwner[index].window; */ - x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); + /* + * if textclipboard is requested simply use the previous clipboard + * handling code + */ + if (nxagentOption(TextClipboard)) + { + /* by dimbor */ + if (X->xselectionrequest.target != XA_STRING) + { + lastServers[index].target = serverUTF8_STRING; + /* by dimbor (idea from zahvatov) */ + x.u.selectionRequest.target = clientUTF8_STRING; + } + else + { + x.u.selectionRequest.target = XA_STRING; + } + } + else + { + x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); + } + sendEventToClient(lastSelectionOwner[index].client, &x); #ifdef DEBUG @@ -2008,6 +2143,64 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } } + /* + * The selection request target is TARGETS. The requestor is asking + * for a list of supported data formats. + */ + + if (target == clientTARGETS) + { + /* + * In TextClipboard mode answer with a predefined list that was used + * in in previous versions. + */ + if (nxagentOption(TextClipboard)) + { + /* + * The list is aligned with the one in + * nxagentHandleSelectionRequestFromXServer. + */ + Atom targets[] = {XA_STRING, + clientUTF8_STRING, +#if 0 + clientTEXT, + clientCOMPOUND_TEXT, +#endif + clientTARGETS, + clientTIMESTAMP}; + int numTargets = sizeof(targets) / sizeof(targets[0]); + + #ifdef DEBUG + fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); + for (int i = 0; i < numTargets; i++) + { + fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForIntAtom(targets[i])); + } + #endif + + ChangeWindowProperty(pWin, + property, + MakeAtom("ATOM", 4, 1), + sizeof(Atom)*8, + PropModeReplace, + numTargets, + targets, + 1); + + sendSelectionNotifyEventToClient(client, time, requestor, selection, + target, property); + + return 1; + } + else + { + /* + * do nothing - TARGETS will be handled like any other target + * and passed on to the owner on the remote side. + */ + } + } + /* * Section 2.6.2 of the ICCCM states: * "TIMESTAMP - To avoid some race conditions, it is important @@ -2018,7 +2211,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * support conversion to TIMESTAMP, returning the timestamp they * used to obtain the selection." */ - if (target == clientTIMESTAMP) + else if (target == clientTIMESTAMP) { /* * "If the specified property is not None, the owner should place @@ -2087,6 +2280,27 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 1; } + /* in TextClipboard mode reject all non-text targets */ + if (nxagentOption(TextClipboard)) + { + if (!isTextTarget(translateLocalToRemoteTarget(target))) + { + #ifdef DEBUG + fprintf(stderr, "%s: denying request for non-text target [%d][%s].\n", __func__, + target, NameForIntAtom(target)); + #endif + + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } + /* go on, target is acceptable */ + } + + #ifdef DEBUG + fprintf(stderr, "%s: target [%d][%s].\n", __func__, target, + NameForIntAtom(target)); + #endif + if (lastClients[index].clientPtr == client) { if (GetTimeInMillis() - lastClients[index].reqTime < ACCUM_TIME) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.c b/nx-X11/programs/Xserver/hw/nxagent/Options.c index be6e5d5e1..8e6249e4c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Options.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Options.c @@ -88,6 +88,7 @@ void nxagentInitOptions(void) nxagentOptions.BackingStore = BackingStoreUndefined; nxagentOptions.Clipboard = ClipboardBoth; + nxagentOptions.TextClipboard = False; nxagentOptions.SharedMemory = True; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.h b/nx-X11/programs/Xserver/hw/nxagent/Options.h index a99f4aee2..d3c8c7150 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Options.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Options.h @@ -194,6 +194,13 @@ typedef struct _AgentOptions */ ClipboardMode Clipboard; + /* + * transfer TARGETS to remote side or answer with a limited + * hardcoded text target list + * Should be Bool but we'd have to include Xlib.h for that + */ + int TextClipboard; + /* * Enable agent to use the MITSHM extension in path from remote * proxy to the real X server. diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 index 74349cda7..f373cb239 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 +++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 @@ -465,6 +465,10 @@ The session id. .B \-autograb enable autograb mode on \fBnxagent\fR startup. The autograb feature can be toggled via nxagent keystrokes .TP 8 +.B \-textclipboard +force text-only clipboard \fBnxagent\fR startup. See option file +option \fBtextclipboard=\fR for an explanation. +.TP 8 .B \-nxrealwindowprop set property NX_REAL_WINDOW for each X11 client inside \fBnxagent\fR, providing the window XID of the corresponding window object on the X @@ -721,6 +725,15 @@ Limit clipboard data exchange to work only in one direction: from nxagent to rea Disable any clipboard data exchange. Clipboard will still work inside the nxagent and on the real X server, but no data exchange will be possible. .RE .TP 8 +.B textclipboard= +enable (set to \fI1\fR) or disable (set to \fI0\fR) text-only +clipboard. Text-only clipboard is the old (<= 3.5.99.26) clipboard +behaviour where you could only copy and paste text strings (no +graphics, no rich text, ...). Using this mode been seen as a security feature +as it effectively prevents transferring dangerous binary data, +e.g. manipulated graphics by accident. On the other hand it's also +less comfortable. (default: disabled) +.TP 8 .B streaming= enable (set to \fI1\fR) or disable (set to \fI0\fR) streaming support for images, not fully implemented yet and thus non-functional. (default: disabled) .TP 8 -- cgit v1.2.3 From 710d5c5f9c354e16f6c36eeca599e579c1819b0c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 20:25:08 +0100 Subject: Clipboard.c: disable TEXT and COMPOUND_TEXT They are ancient and their use is discouraged by ICCCM --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 89 ++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 12 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index fb2595e68..8872291fd 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -59,6 +59,15 @@ #undef TEST #undef DEBUG +/* + * Define these to also support special targets TEXT and COMPOUND_TEXT + * in text-only mode. We do not have a special handling for these. See + * https://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#text_properties + * for details. + */ +#undef SUPPORT_TEXT_TARGET +#undef SUPPORT_COMPOUND_TEXT_TARGET + /* * These are defined in the dispatcher. */ @@ -155,8 +164,12 @@ static XlibAtom serverINSERT_SELECTION; static XlibAtom serverINSERT_PROPERTY; static XlibAtom serverSAVE_TARGETS; static XlibAtom serverTARGET_SIZES; +#ifdef SUPPORT_TEXT_TARGET static XlibAtom serverTEXT; +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET static XlibAtom serverCOMPOUND_TEXT; +#endif static XlibAtom serverUTF8_STRING; static XlibAtom serverTransFromAgentProperty; static Atom clientTARGETS; @@ -168,12 +181,21 @@ static Atom clientINSERT_SELECTION; static Atom clientINSERT_PROPERTY; static Atom clientSAVE_TARGETS; static Atom clientTARGET_SIZES; +#ifdef SUPPORT_TEXT_TARGET static Atom clientTEXT; +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET static Atom clientCOMPOUND_TEXT; +#endif static Atom clientUTF8_STRING; static char szAgentTARGETS[] = "TARGETS"; +#ifdef SUPPORT_TEXT_TARGET static char szAgentTEXT[] = "TEXT"; +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET +static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; +#endif static char szAgentTIMESTAMP[] = "TIMESTAMP"; static char szAgentINCR[] = "INCR"; static char szAgentMULTIPLE[] = "MULTIPLE"; @@ -182,7 +204,6 @@ static char szAgentINSERT_SELECTION[] = "INSERT_SELECTION"; static char szAgentINSERT_PROPERTY[] = "INSERT_PROPERTY"; static char szAgentSAVE_TARGETS[] = "SAVE_TARGETS"; static char szAgentTARGET_SIZES[] = "TARGET_SIZES"; -static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; static char szAgentUTF8_STRING[] = "UTF8_STRING"; static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; static char szAgentCLIPBOARD[] = "CLIPBOARD"; @@ -381,6 +402,18 @@ void nxagentDumpClipboardStat(void) fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemAtom(serverLastRequestedSelection)); + fprintf(stderr, "Compile time settings\n"); +#ifdef SUPPORT_TEXT_TARGET + fprintf(stderr, " SUPPORT_TEXT_TARGET [enabled]\n"); +#else + fprintf(stderr, " SUPPORT_TEXT_TARGET [disabled]\n"); +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET + fprintf(stderr, " SUPPORT_COMPOUND_TEXT_TARGET [enabled]\n"); +#else + fprintf(stderr, " SUPPORT_COMPOUND_TEXT_TARGET [disabled]\n"); +#endif + #define WIDTH 32 Atom cl = 0; XlibAtom sv = 0; @@ -393,11 +426,14 @@ void nxagentDumpClipboardStat(void) cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); +#ifdef SUPPORT_TEXT_TARGET cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); - +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); +#endif cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); @@ -576,6 +612,7 @@ static Bool isTextTarget(XlibAtom target) #endif return True; } +#ifdef SUPPORT_TEXT_TARGET else if (target == serverTEXT) { #ifdef DEBUG @@ -583,17 +620,20 @@ static Bool isTextTarget(XlibAtom target) #endif return True; } - else if (target == serverUTF8_STRING) +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET + else if (target == serverCOMPOUND_TEXT) { #ifdef DEBUG - fprintf(stderr, "%s: valid target [UTF8_STRING].\n", __func__); + fprintf(stderr, "%s: valid target [COMPOUND_TEXT].\n", __func__); #endif return True; } - else if (target == serverCOMPOUND_TEXT) +#endif + else if (target == serverUTF8_STRING) { #ifdef DEBUG - fprintf(stderr, "%s: valid target [COMPOUND_TEXT].\n", __func__); + fprintf(stderr, "%s: valid target [UTF8_STRING].\n", __func__); #endif return True; } @@ -869,8 +909,16 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * and in isTextTarget(). */ - XlibAtom targets[] = {XA_STRING, serverUTF8_STRING, serverTEXT, serverCOMPOUND_TEXT, - serverTARGETS, serverTIMESTAMP}; + XlibAtom targets[] = {XA_STRING, + serverUTF8_STRING, +#ifdef SUPPORT_TEXT_TARGET + serverTEXT, +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET + serverCOMPOUND_TEXT, +#endif + serverTARGETS, + serverTIMESTAMP}; int numTargets = sizeof(targets) / sizeof(targets[0]); #ifdef DEBUG @@ -2162,8 +2210,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, */ Atom targets[] = {XA_STRING, clientUTF8_STRING, -#if 0 +#ifdef SUPPORT_TEXT_TARGET clientTEXT, +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET clientCOMPOUND_TEXT, #endif clientTARGETS, @@ -2426,19 +2476,26 @@ XlibAtom translateLocalToRemoteTarget(Atom local) XlibAtom remote; /* - * we only convert to either UTF8 or XA_STRING, despite accepting - * TEXT and COMPOUND_TEXT. + * we only convert to either UTF8 or XA_STRING +#ifdef SUPPORT_TEXT_TARGET + * despite accepting TEXT +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET + * and COMPOUND_TEXT. +#endif */ if (local == clientUTF8_STRING) { remote = serverUTF8_STRING; } -#if 0 +#ifdef SUPPORT_TEXT_TARGET else if (local == clientTEXT) { remote = serverTEXT; } +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET else if (local == clientCOMPOUND_TEXT) { remote = serverCOMPOUND_TEXT; @@ -2606,8 +2663,12 @@ Bool nxagentInitClipboard(WindowPtr pWin) * initSelectionOwnerData ! */ /* FIXME: it is probably better to re-use the strings from Atoms.c here */ clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); +#ifdef SUPPORT_TEXT_TARGET clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); +#endif clientUTF8_STRING = MakeAtom(szAgentUTF8_STRING, strlen(szAgentUTF8_STRING), True); clientTIMESTAMP = MakeAtom(szAgentTIMESTAMP, strlen(szAgentTIMESTAMP), True); clientINCR = MakeAtom(szAgentINCR, strlen(szAgentINCR), True); @@ -2667,8 +2728,12 @@ Bool nxagentInitClipboard(WindowPtr pWin) remSelAtoms[nxagentClipboardSelection] = nxagentAtoms[10]; /* CLIPBOARD */ serverTARGETS = nxagentAtoms[6]; /* TARGETS */ +#ifdef SUPPORT_TEXT_TARGET serverTEXT = nxagentAtoms[7]; /* TEXT */ +#endif +#ifdef SUPPORT_COMPOUND_TEXT_TARGET serverCOMPOUND_TEXT = nxagentAtoms[16]; /* COMPOUND_TEXT */ +#endif serverUTF8_STRING = nxagentAtoms[12]; /* UTF8_STRING */ serverTIMESTAMP = nxagentAtoms[11]; /* TIMESTAMP */ serverINCR = nxagentAtoms[17]; /* INCR */ -- cgit v1.2.3 From a296b437d943529ebe3363490a84f8d640bade7a Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 23:07:59 +0100 Subject: Clipboard.c: replace loop by helper --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 8872291fd..4baec7273 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1606,19 +1606,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) #endif /* determine the selection we are talking about here */ - int index = 0; - for (index = 0; index < nxagentMaxSelections; index++) - { - #ifdef DEBUG - fprintf (stderr, "%s: index [%d] selAtom [%ld] remselection [%ld] .\n", - __func__, index, remSelAtoms[index], e->selection); - #endif - if (remSelAtoms[index] == e->selection) - { - break; - } - } - + int index = nxagentFindLastSelectionOwnerIndex(e->selection); if (index == nxagentMaxSelections) { #ifdef DEBUG -- cgit v1.2.3 From 6b659fe4a8750aaef5ae74e86cafda02ac47afa9 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 23:15:06 +0100 Subject: Clipboard.c: another round of debug improvements --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 52 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 4baec7273..d58707b2d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -335,7 +335,7 @@ static void printSelectionStat(int index) fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); fprintf(stderr, " lastSelectionOwner[].window [0x%x]\n", lOwner.window); if (lOwner.windowPtr) - fprintf(stderr, " lastSelectionOwner[].windowPtr [%p] (-> [0x%x]\n", (void *)lOwner.windowPtr, WINDOWID(lOwner.windowPtr)); + fprintf(stderr, " lastSelectionOwner[].windowPtr [%p] (-> [0x%x])\n", (void *)lOwner.windowPtr, WINDOWID(lOwner.windowPtr)); else fprintf(stderr, " lastSelectionOwner[].windowPtr -\n"); fprintf(stderr, " lastSelectionOwner[].lastTimeChanged [%u]\n", lOwner.lastTimeChanged); @@ -727,9 +727,15 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { if (remSelAtoms[index] == sel) { + #ifdef DEBUG + fprintf(stderr, "%s: selection [%ld] belongs to index [%d]\n", __func__, sel, index); + #endif return index; } } + #ifdef DEBUG + fprintf(stderr, "%s: selection [%ld] does not belong to any index!\n", __func__, sel); + #endif return nxagentMaxSelections; } @@ -743,9 +749,15 @@ int nxagentFindCurrentSelectionIndex(Atom sel) { if (CurrentSelections[index].selection == sel) { + #ifdef DEBUG + fprintf(stderr, "%s: selection [%d] belongs to index [%d]\n", __func__, sel, index); + #endif return index; } } + #ifdef DEBUG + fprintf(stderr, "%s: selection [%d] does not belong to any index!\n", __func__, sel); + #endif return NumCurrentSelections; } @@ -841,10 +853,6 @@ static void replyRequestSelectionToXServer(XEvent *X, Bool success) void nxagentHandleSelectionRequestFromXServer(XEvent *X) { #ifdef DEBUG - if (X->xselectionrequest.requestor == serverWindow) - { - fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; - } fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", __func__, @@ -852,6 +860,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), DisplayString(nxagentDisplay), X->xselectionrequest.requestor, X->xselectionrequest.property, NameForRemAtom(X->xselectionrequest.property)); + if (X->xselectionrequest.requestor == serverWindow) + { + fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; + } #endif if (!agentClipboardInitialized) @@ -927,7 +939,6 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) { fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); } - fprintf(stderr, "\n"); #endif /* @@ -1594,15 +1605,16 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) XSelectionEvent * e = (XSelectionEvent *)X; #ifdef DEBUG - if (e->requestor == serverWindow) - { - fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; - } fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", __func__, e->property, NameForRemAtom(e->property), e->requestor, NameForRemAtom(e->selection), e->target, NameForRemAtom(e->target), e->time, e->send_event); + + if (e->requestor == serverWindow) + { + fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; + } #endif /* determine the selection we are talking about here */ @@ -1705,8 +1717,9 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); #ifdef DEBUG - fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, - lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); + fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, + lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), + getXErrorString(result)); #endif if (result == BadAlloc || result == BadAtom || result == BadWindow || result == BadValue) @@ -1721,8 +1734,9 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) &resultFormat, &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); #ifdef DEBUG - fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d] returned [%s]\n", __func__, - lastSelectionOwner[index].window, clientCutProperty, getXErrorString(result)); + fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, + lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), + getXErrorString(result)); #endif if (result == BadAlloc || result == BadAtom || @@ -1795,7 +1809,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) ulReturnItems); #ifdef DEBUG { - fprintf(stderr, "%s: XChangeProperty sent to window [0x%x] for property [%ld][%s] value [\"%*.*s\"...]\n", + fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] value [\"%*.*s\"...]\n", __func__, lastServers[index].requestor, lastServers[index].property, @@ -2005,7 +2019,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) nxagentClientInfoString(pSelection->client)); fprintf(stderr, "%s: lastSelectionOwner.window [0x%x] -> [0x%x]\n", __func__, lastSelectionOwner[index].window, pSelection->window); - fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%lx] (serverWindow: [0x%lx])\n", __func__, + fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%lx])\n", __func__, (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, nxagentWindow(pSelection->pWin), serverWindow); fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, @@ -2394,7 +2408,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif #ifdef DEBUG - fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%x] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, + fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%lx] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, serverWindow, remTarget, NameForRemAtom(remTarget), remProperty, NameForRemAtom(remProperty), remSelection, NameForRemAtom(remSelection)); @@ -2444,7 +2458,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) } #ifdef DEBUG - fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld] [%s]\n", __func__, + fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld][%s]\n", __func__, local, NameForIntAtom(local), remote, NameForRemAtom(remote)); #endif @@ -2499,7 +2513,7 @@ XlibAtom translateLocalToRemoteTarget(Atom local) } #ifdef DEBUG - fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld] [%s]\n", __func__, + fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld][%s]\n", __func__, local, NameForIntAtom(local), remote, NameForRemAtom(remote)); #endif -- cgit v1.2.3 From a4f2dd3febe01bc31a4076ca46efff03a3b6b5b0 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 23:16:10 +0100 Subject: Clipboard.c: print separator when receiving events/requests in debug mode This helps reading the debug output a lot! --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index d58707b2d..6a7ce5d15 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -769,7 +769,7 @@ int nxagentFindCurrentSelectionIndex(Atom sel) void nxagentHandleSelectionClearFromXServer(XEvent *X) { #ifdef DEBUG - fprintf(stderr, "%s: SelectionClear event for selection [%lu].\n", __func__, X->xselectionclear.selection); + fprintf(stderr, "---------\n%s: SelectionClear event for selection [%lu].\n", __func__, X->xselectionclear.selection); #endif if (!agentClipboardInitialized) @@ -853,7 +853,7 @@ static void replyRequestSelectionToXServer(XEvent *X, Bool success) void nxagentHandleSelectionRequestFromXServer(XEvent *X) { #ifdef DEBUG - fprintf(stderr, "%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ + fprintf(stderr, "---------\n%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", __func__, X->xselectionrequest.selection, NameForRemAtom(X->xselectionrequest.selection), @@ -1605,7 +1605,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) XSelectionEvent * e = (XSelectionEvent *)X; #ifdef DEBUG - fprintf(stderr, "%s: SelectionNotify event from real X server, property " \ + fprintf(stderr, "---------\n%s: Received SelectionNotify event from real X server, property " \ "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", __func__, e->property, NameForRemAtom(e->property), e->requestor, NameForRemAtom(e->selection), e->target, @@ -2095,7 +2095,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, Window requestor, Atom property, Atom target, Time time) { #ifdef DEBUG - fprintf(stderr, "%s: client %s requests sel [%s] " + fprintf(stderr, "---------\n%s: client %s requests sel [%s] " "on window [0x%x] prop [%d][%s] target [%d][%s].\n", __func__, nxagentClientInfoString(client), NameForIntAtom(selection), requestor, property, NameForIntAtom(property), @@ -2549,7 +2549,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) } #ifdef DEBUG - fprintf(stderr, "%s: Received SendNotify by client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, + fprintf(stderr, "---------\n%s: Received SendNotify by client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, event->u.selectionNotify.property, NameForIntAtom(event->u.selectionNotify.property), event->u.selectionNotify.target, NameForIntAtom(event->u.selectionNotify.target), event->u.selectionNotify.selection, NameForIntAtom(event->u.selectionNotify.selection), -- cgit v1.2.3 From a8b375079af4601f3d42ff28bd57a2818a202d99 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 23:17:23 +0100 Subject: Clipboard: init variable --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 6a7ce5d15..03f9d2554 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -107,7 +107,7 @@ typedef struct _SelectionOwner static SelectionOwner *lastSelectionOwner = NULL; /* FIXME: can this also be stored per selection? */ -static XlibAtom serverLastRequestedSelection; +static XlibAtom serverLastRequestedSelection = -1; #define IS_INTERNAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NULL) @@ -2620,6 +2620,11 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) */ WindowPtr nxagentGetClipboardWindow(Atom property) { + if (serverLastRequestedSelection == -1) + { + return NULL; + } + int index = nxagentFindLastSelectionOwnerIndex(serverLastRequestedSelection); if (index < nxagentMaxSelections && property == clientCutProperty && -- cgit v1.2.3 From e42ab9831beae06e0a3a08b6c12a58b6e71e4380 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 23:18:12 +0100 Subject: Clipboard.c: fix some whitepace, comments and FIXMEs --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 03f9d2554..3842df30e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1100,7 +1100,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) #endif { if (!(nxagentOption(Clipboard) == ClipboardServer || - nxagentOption(Clipboard) == ClipboardBoth)) + nxagentOption(Clipboard) == ClipboardBoth)) { #ifdef DEBUG fprintf (stderr, "%s: clipboard (partly) disabled - denying request.\n", __func__); @@ -1164,7 +1164,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } else { - x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); + x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); } sendEventToClient(lastSelectionOwner[index].client, &x); @@ -1179,7 +1179,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) x.u.selectionRequest.selection, NameForIntAtom(x.u.selectionRequest.selection)); #endif /* no reply to Xserver yet - we will do that once the answer of - the above sendEventToClient arrives */ + the above sendEventToClient arrives */ } else { @@ -2086,7 +2086,7 @@ FIXME /* * This is called from dix (ProcConvertSelection) if an nxagent client - * issues a ConvertSelection request. So all the Atoms are internal + * issues a ConvertSelection request. So all the Atoms are internal. * return codes: * 0: let dix process the request * 1: don't let dix process the request @@ -2417,7 +2417,6 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, UpdateCurrentTime(); XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); - /* XConvertSelection will always return 1 (check the source!), so no need to check */ -- cgit v1.2.3 From 2d4b0f8464cd2b34e2ae0a8009715fcf027f9738 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 29 Oct 2020 23:19:39 +0100 Subject: Clipboard.c: fix transfer from agent to X server The code took the wrong path because of an insufficent check --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3842df30e..86b960a42 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1629,7 +1629,12 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) printClientSelectionStage(index); - if (lastClients[index].windowPtr != NULL) + /* + * if the property is serverTransFromAgentProperty this means we are + * transferring data FROM the agent TO the server. + */ + + if (X->xselection.property != serverTransFromAgentProperty && lastClients[index].windowPtr != NULL) { /* * We reach here after a paste inside the nxagent, triggered by -- cgit v1.2.3 From 9ca97270568e72fc19db5a28ac03cfd3b85ada91 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 30 Oct 2020 19:37:16 +0100 Subject: Events.c: use index instead of i we do that everywhere when handling clipboard stuff --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 4e45e0d24..617c7243b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2849,13 +2849,13 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) { Atom local = nxagentRemoteToLocalAtom(xfixesEvent -> xfixesselection.selection); - int i = nxagentFindCurrentSelectionIndex(local); - if (i < NumCurrentSelections) + int index = nxagentFindCurrentSelectionIndex(local); + if (index < NumCurrentSelections) { - if (CurrentSelections[i].client != 0) + if (CurrentSelections[index].client != 0) { #ifdef TEST - fprintf(stderr, "%s: Do nothing.\n", __func__); + fprintf(stderr, "%s: Doing nothing.\n", __func__); #endif return 1; @@ -2863,11 +2863,11 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) #ifdef TEST fprintf(stderr, "%s: Calling callbacks for %d [%s] selection.\n", __func__, - CurrentSelections[i].selection, NameForAtom(CurrentSelections[i].selection)); + CurrentSelections[index].selection, NameForAtom(CurrentSelections[index].selection)); #endif #ifdef DEBUG - fprintf(stderr, "%s: CurrentSelections[%d].lastTimeChanged [%u]\n", __func__, i, CurrentSelections[i].lastTimeChanged.milliseconds); + fprintf(stderr, "%s: CurrentSelections[%d].lastTimeChanged [%u]\n", __func__, index, CurrentSelections[index].lastTimeChanged.milliseconds); fprintf(stderr, "%s: Event timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.timestamp); fprintf(stderr, "%s: Event selection timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.selection_timestamp); fprintf(stderr, "%s: Event selection window [0x%lx]\n", __func__, xfixesEvent->xfixesselection.window); @@ -2886,7 +2886,7 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) #endif SelectionInfoRec info = { - .selection = &CurrentSelections[i], + .selection = &CurrentSelections[index], .kind = xfixesEvent->xfixesselection.subtype }; -- cgit v1.2.3 From b66b99a8310d312c53007e124a0924f5795b1b2c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 2 Nov 2020 23:10:52 +0100 Subject: Clipboard.c: use NullClient instead of NULL where appropriate --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 86b960a42..f57459882 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -109,7 +109,7 @@ static SelectionOwner *lastSelectionOwner = NULL; /* FIXME: can this also be stored per selection? */ static XlibAtom serverLastRequestedSelection = -1; -#define IS_INTERNAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NULL) +#define IS_INTERNAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NullClient) /* * Needed to handle the notify selection event to @@ -656,7 +656,7 @@ static void initSelectionOwnerData(int index) /* there's no owner on nxagent side anymore */ static void clearSelectionOwnerData(int index) { - lastSelectionOwner[index].client = NULL; + lastSelectionOwner[index].client = NullClient; lastSelectionOwner[index].window = None; lastSelectionOwner[index].windowPtr = NULL; lastSelectionOwner[index].lastTimeChanged = GetTimeInMillis(); -- cgit v1.2.3 From 177d761797b36fdadb246c0129cfb14bcc1c0c19 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 12 Nov 2020 23:22:39 +0100 Subject: Clipboard.c: fix: remove wrong optimization In the "none" case we must ensure the clipboard data is reset. This "optimization" skipped the reset part which made the code think it is waiting for an answer. Which (of course) never arrived. So any further request was rejected... Also reduce debugging output for the "none" case because resetClientSelectionStage will print it anyway. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f57459882..2856026f2 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -480,26 +480,16 @@ static void resetClientSelectionStage(int index) static void setClientSelectionStage(int stage, int index) { - if (lastClients[index].stage == stage) - { - #ifdef DEBUG - fprintf(stderr, "%s: lastClient [%d] selection stage already set to [%s] - doing nothing\n", __func__, - index, getClientSelectionStageString(lastClients[index].stage)); - #endif - return; - } - - #ifdef DEBUG - fprintf(stderr, "%s: Changing selection stage for [%d] from [%s] to [%s]\n", __func__, index, - getClientSelectionStageString(lastClients[index].stage), getClientSelectionStageString(stage)); - #endif - if (stage == SelectionStageNone) { resetClientSelectionStage(index); } else { + #ifdef DEBUG + fprintf(stderr, "%s: Changing selection stage for [%d] from [%s] to [%s]\n", __func__, index, + getClientSelectionStageString(lastClients[index].stage), getClientSelectionStageString(stage)); + #endif lastClients[index].stage = stage; } } -- cgit v1.2.3 From 6a1ee6c0b0ff7be509ca61966873644de2d7ccb1 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 13 Nov 2020 18:24:26 +0100 Subject: Clipboard.c: once again improved DEBUG output Also reduce number of certain DEBUG lines: These PropertyEvents tend to appear quite often and most of the times they have nothing to do with the clipboard. So instead of printing them everytime we turn that around and print something only if it is a clipboard related event.. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 47 +++++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 2856026f2..ae9bb0f1d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -718,13 +718,13 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) if (remSelAtoms[index] == sel) { #ifdef DEBUG - fprintf(stderr, "%s: selection [%ld] belongs to index [%d]\n", __func__, sel, index); + fprintf(stderr, "%s: remote selection [%ld][%s] belongs to index [%d]\n", __func__, sel, NameForRemAtom(sel), index); #endif return index; } } #ifdef DEBUG - fprintf(stderr, "%s: selection [%ld] does not belong to any index!\n", __func__, sel); + fprintf(stderr, "%s: remote selection [%ld][%s] does not belong to any index!\n", __func__, sel, NameForRemAtom(sel)); #endif return nxagentMaxSelections; } @@ -740,13 +740,13 @@ int nxagentFindCurrentSelectionIndex(Atom sel) if (CurrentSelections[index].selection == sel) { #ifdef DEBUG - fprintf(stderr, "%s: selection [%d] belongs to index [%d]\n", __func__, sel, index); + fprintf(stderr, "%s: selection [%d][%s] belongs to index [%d]\n", __func__, sel, NameForIntAtom(sel), index); #endif return index; } } #ifdef DEBUG - fprintf(stderr, "%s: selection [%d] does not belong to any index!\n", __func__, sel); + fprintf(stderr, "%s: selection [%d][%s] does not belong to any index!\n", __func__, sel, NameForIntAtom(sel)); #endif return NumCurrentSelections; } @@ -759,7 +759,9 @@ int nxagentFindCurrentSelectionIndex(Atom sel) void nxagentHandleSelectionClearFromXServer(XEvent *X) { #ifdef DEBUG - fprintf(stderr, "---------\n%s: SelectionClear event for selection [%lu].\n", __func__, X->xselectionclear.selection); + fprintf(stderr, "---------\n%s: SelectionClear event for selection [%lu][%s] window [0x%lx] time [%lu].\n", + __func__, X->xselectionclear.selection, NameForRemAtom(X->xselectionclear.selection), + X->xselectionclear.window, X->xselectionclear.time); #endif if (!agentClipboardInitialized) @@ -844,12 +846,13 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) { #ifdef DEBUG fprintf(stderr, "---------\n%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ - "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s]\n", + "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s] time [%lu]\n", __func__, X->xselectionrequest.selection, NameForRemAtom(X->xselectionrequest.selection), X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), DisplayString(nxagentDisplay), X->xselectionrequest.requestor, - X->xselectionrequest.property, NameForRemAtom(X->xselectionrequest.property)); + X->xselectionrequest.property, NameForRemAtom(X->xselectionrequest.property), + X->xselectionrequest.time); if (X->xselectionrequest.requestor == serverWindow) { fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; @@ -1395,20 +1398,27 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) /* determine the selection we are talking about here */ for (index = 0; index < nxagentMaxSelections; index++) { + /* #ifdef DEBUG fprintf(stderr, "%s: lastClients[%d].resource [%d] resource [%d]\n", __func__, index, lastClients[index].resource, resource); #endif + */ if (lastClients[index].resource == resource) { + #ifdef DEBUG + fprintf (stderr, "%s: resource [%d] belongs to selection [%d].\n", __func__, resource, index); + #endif break; } } if (index == nxagentMaxSelections) { + /* #ifdef DEBUG - fprintf (stderr, "%s: resource does not belong to any selection we handle.\n", __func__); + fprintf (stderr, "%s: resource [%d] does not belong to any selection we handle.\n", __func__, resource); #endif + */ return False; } @@ -1601,9 +1611,10 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) NameForRemAtom(e->selection), e->target, NameForRemAtom(e->target), e->time, e->send_event); + /* this has not been SENT by nxagent but is the answer to a request of nxagent */ if (e->requestor == serverWindow) { - fprintf(stderr, "%s: this event has been sent by nxagent!\n", __func__);; + fprintf(stderr, "%s: requestor is nxagent's serverWindow!\n", __func__);; } #endif @@ -1804,11 +1815,12 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) ulReturnItems); #ifdef DEBUG { - fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] value [\"%*.*s\"...]\n", + fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] len [%d] value [\"%*.*s\"...]\n", __func__, lastServers[index].requestor, lastServers[index].property, NameForRemAtom(lastServers[index].property), + (int)ulReturnItems * 8 / 8, (int)(min(20, ulReturnItems * 8 / 8)), (int)(min(20, ulReturnItems * 8 / 8)), pszReturnData); @@ -1924,6 +1936,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, SelectionInfoRec *info = (SelectionInfoRec *)args; #ifdef DEBUG + fprintf(stderr, "---------\n"); if (info->kind == SelectionSetOwner) { fprintf(stderr, "%s: SelectionCallbackKind [SelectionSetOwner]\n", __func__); @@ -2091,10 +2104,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, { #ifdef DEBUG fprintf(stderr, "---------\n%s: client %s requests sel [%s] " - "on window [0x%x] prop [%d][%s] target [%d][%s].\n", __func__, + "on window [0x%x] prop [%d][%s] target [%d][%s] time [%u].\n", __func__, nxagentClientInfoString(client), NameForIntAtom(selection), requestor, property, NameForIntAtom(property), - target, NameForIntAtom(target)); + target, NameForIntAtom(target), time); #endif /* cannot use NameForIntAtom() here! */ @@ -2136,6 +2149,9 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, /* * There is a client owner on the agent side, let normal dix stuff happen. */ + #ifdef DEBUG + fprintf(stderr, "%s: clipboard is owned by internal client - let dix process the request\n", __func__); + #endif return 0; } @@ -2543,7 +2559,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) } #ifdef DEBUG - fprintf(stderr, "---------\n%s: Received SendNotify by client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, + fprintf(stderr, "---------\n%s: Received SendNotify from client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, event->u.selectionNotify.property, NameForIntAtom(event->u.selectionNotify.property), event->u.selectionNotify.target, NameForIntAtom(event->u.selectionNotify.target), event->u.selectionNotify.selection, NameForIntAtom(event->u.selectionNotify.selection), @@ -2601,6 +2617,11 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) .time = CurrentTime, }; + #ifdef DEBUG + fprintf(stderr, "%s: remote property [%ld][%s].\n", __func__, + serverTransFromAgentProperty, NameForRemAtom(serverTransFromAgentProperty)); + #endif + sendSelectionNotifyEventToXServer(&eventSelection); return 1; -- cgit v1.2.3 From 7e548faa268410be607603ee36bc23fd856e7553 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 16 Nov 2020 23:51:52 +0100 Subject: Clipboard.c: remove obsolete FIXME comment --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index ae9bb0f1d..b0cd1bef3 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -679,10 +679,6 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) (void *) pClient, CLINDEX(pClient), (void *) pWindow, WINDOWID(pWindow)); #endif - /* - * Only for PRIMARY and CLIPBOARD selections. - */ - /* FIXME: there's almost identical code in nxagentClipboardInit */ for (int index = 0; index < nxagentMaxSelections; index++) { @@ -969,7 +965,6 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * * FIXME: ensure we are reporting an _external_ timestamp * FIXME: for a 32 bit property list we need to pass a "long" array, not "char"! - * FIXME: selection has already been checked above, so we do not need to check again here */ XChangeProperty(nxagentDisplay, -- cgit v1.2.3 From 53c03eaf3bfe06c445e9353c97663553afb1a3f7 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 17 Nov 2020 00:14:07 +0100 Subject: Clipboard.c: fix: return after denying request --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index b0cd1bef3..10dafcda6 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1096,6 +1096,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) /* deny the request */ replyRequestSelectionToXServer(X, False); + return; } /* -- cgit v1.2.3 From 41ea3b68425f45bdcd90a21baa84506f48332782 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 17 Nov 2020 16:20:20 +0100 Subject: Clipboard.c: correctly pass back failure to real X server --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 68 +++++++++++++++++--------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 10dafcda6..ceed43aa9 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2594,33 +2594,57 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) else { /* - * Setup selection notify event to real server. - * - * .property must be a server-side Atom. As this property is only - * set on our serverWindow and normally there are few other - * properties except serverTransToAgentProperty, the only thing - * we need to ensure is that the internal Atom clientCutProperty - * differs from the server-side serverTransToAgentProperty - * Atom. The actual name is not important. To be clean here we use - * a separate serverTransFromAgentProperty. + * if the property is 0 (reporting failure) we can directly + * answer to the lastServer about the failure! */ + if (lastServers[index].requestor != None && event->u.selectionNotify.property == 0) + { + #ifdef DEBUG + fprintf(stderr, "%s: passing on failure to lastServers[%d].requestor [%ld].\n", __func__, + index, lastServers[index].requestor); + #endif - XSelectionEvent eventSelection = { - .requestor = serverWindow, - .selection = translateLocalToRemoteSelection(event->u.selectionNotify.selection), - .target = translateLocalToRemoteTarget(event->u.selectionNotify.target), - .property = serverTransFromAgentProperty, - .time = CurrentTime, - }; + XSelectionEvent eventSelection = { + .requestor = lastServers[index].requestor, + .selection = remSelAtoms[index], + .target = lastServers[index].target, + .property = 0, + .time = lastServers[index].time, + }; + sendSelectionNotifyEventToXServer(&eventSelection); - #ifdef DEBUG - fprintf(stderr, "%s: remote property [%ld][%s].\n", __func__, - serverTransFromAgentProperty, NameForRemAtom(serverTransFromAgentProperty)); - #endif + lastServers[index].requestor = None; + return 1; + } + else + { + /* + * Setup selection notify event to real server. + * + * .property must be a server-side Atom. As this property is only + * set on our serverWindow and normally there are few other + * properties except serverTransToAgentProperty, the only thing + * we need to ensure is that the internal Atom clientCutProperty + * differs from the server-side serverTransToAgentProperty + * Atom. The actual name is not important. To be clean here we use + * a separate serverTransFromAgentProperty. + */ - sendSelectionNotifyEventToXServer(&eventSelection); + XSelectionEvent eventSelection = { + .requestor = serverWindow, + .selection = translateLocalToRemoteSelection(event->u.selectionNotify.selection), + .target = translateLocalToRemoteTarget(event->u.selectionNotify.target), + .property = serverTransFromAgentProperty, + .time = CurrentTime, + }; - return 1; + #ifdef DEBUG + fprintf(stderr, "%s: remote property [%ld][%s].\n", __func__, + serverTransFromAgentProperty, NameForRemAtom(serverTransFromAgentProperty)); + #endif + sendSelectionNotifyEventToXServer(&eventSelection); + return 1; + } } } -- cgit v1.2.3 From 63ef52c63ab376c6db068397edbc2cd295f205b7 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 18 Nov 2020 22:38:44 +0100 Subject: Clipboard.c: fix indentation --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index ceed43aa9..f8d1a5d18 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2022,12 +2022,12 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) nxagentClientInfoString(lastSelectionOwner[index].client), nxagentClientInfoString(pSelection->client)); fprintf(stderr, "%s: lastSelectionOwner.window [0x%x] -> [0x%x]\n", __func__, - lastSelectionOwner[index].window, pSelection->window); + lastSelectionOwner[index].window, pSelection->window); fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%lx])\n", __func__, - (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, - nxagentWindow(pSelection->pWin), serverWindow); + (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, + nxagentWindow(pSelection->pWin), serverWindow); fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, - lastSelectionOwner[index].lastTimeChanged); + lastSelectionOwner[index].lastTimeChanged); #endif #if defined(TEST) || defined(DEBUG) -- cgit v1.2.3 From 99a2d6e292a56ad3756348e5b8d997a2b75c7539 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 18 Nov 2020 22:41:32 +0100 Subject: Clipboard.c: implement target caching Some applications (e.g. Chrome, Firefox) send multiple TARGETS requests when they want to paste a selection (reason currently unknown). If such an application runs in an NX session and the current clipboard owner is on the real X server this triggers many (superflous) roundtrips. By caching the first answer to those requests and answering subsequent requests from the cache we can eliminate all this communication. The implemention resulted from attempting to fix ArcticaProject/nx-libs/issues/#969 (solution 1a) but it turned out that the speedup this brings does not help in reducing the number of requests by firefox. It must be a bug in the firefox code. Nevertheless I kept the code as it should speed up the whole pasting process considerably while reducing communication over the wire. This also eliminates a memory leak in the target forwarding code which was unnoticed before. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 118 +++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f8d1a5d18..18bd44099 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -106,6 +106,19 @@ typedef struct _SelectionOwner static SelectionOwner *lastSelectionOwner = NULL; +/* + * cache for targets the current selection owner + * on the real X server has to offer. We are storing the targets + * after they have been converted from XlibAtom to Atom. +*/ +typedef struct _Targets +{ + Atom *targets; + int numTargets; +} Targets; + +static Targets *targetCache = NULL; + /* FIXME: can this also be stored per selection? */ static XlibAtom serverLastRequestedSelection = -1; @@ -378,6 +391,12 @@ static void printLastServerStat(int index) fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); } +static void printTargetCacheStat(int index) +{ + fprintf(stderr, " targetCache[].targets (Atom *) [%p]\n", (void *)targetCache[index].targets); + fprintf(stderr, " targetCache[].numTargets (int) [%d]\n", targetCache[index].numTargets); +} + void nxagentDumpClipboardStat(void) { fprintf(stderr, "/----- Clipboard internal status -----\n"); @@ -452,6 +471,7 @@ void nxagentDumpClipboardStat(void) printSelectionStat(index); printLastClientStat(index); printLastServerStat(index); + printTargetCacheStat(index); } fprintf(stderr, "\\------------------------------------------------------------------------------\n"); @@ -747,6 +767,41 @@ int nxagentFindCurrentSelectionIndex(Atom sel) return NumCurrentSelections; } +void cacheTargets(int index, Atom* targets, int numTargets) +{ + #ifdef DEBUG + fprintf(stderr, "%s: caching [%d] targets\n", __func__, numTargets); + #endif + + SAFE_free(targetCache[index].targets); + targetCache[index].targets = targets; + targetCache[index].numTargets = numTargets; +} + +/* this is called on init, reconnect and SelectionClear */ +void invalidateTargetCache(int index) +{ + #ifdef DEBUG + fprintf(stderr, "%s: invalidating target cache [%d]\n", __func__, index); + #endif + + SAFE_free(targetCache[index].targets); + targetCache[index].numTargets = 0; +} + +void invalidateTargetCaches(void) +{ + #ifdef DEBUG + fprintf(stderr, "%s: invalidating all target caches\n", __func__); + #endif + + for (int index = 0; index < nxagentMaxSelections; index++) + { + SAFE_free(targetCache[index].targets); + targetCache[index].numTargets = 0; + } +} + /* * This is called from Events.c dispatch loop on reception of a * SelectionClear event. We receive this event if someone on the real @@ -802,6 +857,8 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) clearSelectionOwnerData(index); setClientSelectionStage(SelectionStageNone, index); + + invalidateTargetCache(index); } } @@ -1543,6 +1600,8 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) 32, PropModeReplace, ulReturnItems, (unsigned char*)targets, 1); + cacheTargets(index, targets, numTargets); + endTransfer(SELECTION_SUCCESS, index); } } @@ -1951,6 +2010,12 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, } #endif + /* + * We do not know index here so for now let's invalidate the + * complete cache on every owner change regardless of the selection. + */ + invalidateTargetCaches(); + if (nxagentExternalClipboardEventTrap) { #ifdef DEBUG @@ -2063,6 +2128,13 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) storeSelectionOwnerData(index, pSelection); setClientSelectionStage(SelectionStageNone, index); + + /* + * this will be repeated on reception of the SelectionOwner callback + * but we cannot be sure if there are any intermediate requests in the queue + * already so better do it here, too + */ + invalidateTargetCache(index); } /* FIXME: commented because index is invalid here! */ @@ -2253,6 +2325,42 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } else { + /* + * Shortcut: Some applications tend to post multiple + * SelectionRequests. Further it can happen that multiple + * clients are interested in clipboard content. If we already + * know the answer and no intermediate SelectionOwner event + * occured we can answer with the cached list of targets. + */ + + if (targetCache[index].targets) + { + Atom *targets = targetCache[index].targets; + int numTargets = targetCache[index].numTargets; + + #ifdef DEBUG + fprintf(stderr, "%s: Sending %d cached targets:\n", __func__, numTargets); + for (int i = 0; i < numTargets; i++) + { + fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForIntAtom(targets[i])); + } + #endif + + ChangeWindowProperty(pWin, + property, + MakeAtom("ATOM", 4, 1), + sizeof(Atom)*8, + PropModeReplace, + numTargets, + targets, + 1); + + sendSelectionNotifyEventToClient(client, time, requestor, selection, + target, property); + + return 1; + } + /* * do nothing - TARGETS will be handled like any other target * and passed on to the owner on the remote side. @@ -2760,6 +2868,13 @@ Bool nxagentInitClipboard(WindowPtr pWin) { FatalError("nxagentInitClipboard: Failed to allocate memory for the remote selection Atoms array.\n"); } + + SAFE_free(targetCache); + targetCache = (Targets *) calloc(nxagentMaxSelections, sizeof(Targets)); + if (targetCache == NULL) + { + FatalError("nxagentInitClipboard: Failed to allocate memory for target cache.\n"); + } } /* @@ -2884,6 +2999,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) * clients might still be waiting for answers. Should reply * with failure then */ + + invalidateTargetCache(index); } } } @@ -2896,6 +3013,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) /* FIXME: required? move to setSelectionStage? */ lastClients[index].reqTime = GetTimeInMillis(); lastServers[index].requestor = None; + invalidateTargetCache(index); } clientCutProperty = MakeAtom(szAgentNX_CUT_BUFFER_CLIENT, -- cgit v1.2.3 From 55f9c94b2b7672e1c4edc2bdcd14a8b892bb61eb Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 18 Nov 2020 23:12:53 +0100 Subject: Clipboard.c: improve some comments --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 18bd44099..af6f16032 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1943,11 +1943,6 @@ static void resetSelectionOwnerOnXServer(void) return; } - /* - * Only for PRIMARY and CLIPBOARD selections. - */ - - for (int index = 0; index < nxagentMaxSelections; index++) { XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); @@ -1960,7 +1955,7 @@ static void resetSelectionOwnerOnXServer(void) setClientSelectionStage(SelectionStageNone, index); - /* Hmm, this is already None when reaching this */ + /* Hmm, this is already None when reaching here */ lastServers[index].requestor = None; } } @@ -2102,6 +2097,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * we are in the process of communicating back and forth between * real X server and nxagent's clients - let's not disturb * FIXME: by continuing after the warning were ARE disturbing! + * We should cancel that communication here. */ fprintf (stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set.\n", __func__, index, lastServers[index].requestor); @@ -2178,7 +2174,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, target, NameForIntAtom(target), time); #endif - /* cannot use NameForIntAtom() here! */ + /* We cannot use NameForIntAtom() here! FIXME: Why not? */ if (NameForAtom(target) == NULL) { #ifdef DEBUG @@ -2281,7 +2277,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, { /* * In TextClipboard mode answer with a predefined list that was used - * in in previous versions. + * in previous versions. */ if (nxagentOption(TextClipboard)) { @@ -2533,7 +2529,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); /* XConvertSelection will always return 1 (check the source!), so no - need to check */ + need to check the return code. */ #ifdef DEBUG fprintf(stderr, "%s: Sent XConvertSelection\n", __func__); -- cgit v1.2.3 From cf85c725889c92ba1aa0d506649362bbfcc111b6 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 24 Nov 2020 22:23:38 +0100 Subject: Clipboard.c: reset lastServer[].requestor on reconnect --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index af6f16032..eeeb28bab 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2989,11 +2989,17 @@ Bool nxagentInitClipboard(WindowPtr pWin) /* remSelAtoms have already been adjusted above */ XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); } + + /* + * On reconnect there cannot be any external requestor + * waiting for a reply so clean this + */ + lastServers[index].requestor = None; + /* - * FIXME: Shouldn't we reset lastServers[index].* and - * lastClients[index].* here? Problem is that (internal) - * clients might still be waiting for answers. Should reply - * with failure then + * FIXME: We should reset lastClients[index].* here! Problem + * is that internal clients might still be waiting for + * answers. Should reply with failure then. */ invalidateTargetCache(index); -- cgit v1.2.3 From b7021c6754c0d4f44d81d12763c095c15c0bc882 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 24 Nov 2020 22:40:24 +0100 Subject: Events.c: use already available variable instead of repeating conversion --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 617c7243b..2ec17c328 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2872,7 +2872,7 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) fprintf(stderr, "%s: Event selection timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.selection_timestamp); fprintf(stderr, "%s: Event selection window [0x%lx]\n", __func__, xfixesEvent->xfixesselection.window); fprintf(stderr, "%s: Event selection owner [0x%lx]\n", __func__, xfixesEvent->xfixesselection.owner); - fprintf(stderr, "%s: Event selection [%s]\n", __func__, NameForAtom(nxagentRemoteToLocalAtom(xfixesEvent->xfixesselection.selection))); + fprintf(stderr, "%s: Event selection [%s]\n", __func__, NameForAtom(local)); fprintf(stderr, "%s: Subtype ", __func__); -- cgit v1.2.3 From 7746358b6536289fab9e89b525cf8329a64b731a Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 25 Nov 2020 00:23:47 +0100 Subject: Clipboard.c: move some (currently commented) code to inner scope --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index eeeb28bab..7598f9916 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2131,10 +2131,9 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * already so better do it here, too */ invalidateTargetCache(index); - } - /* FIXME: commented because index is invalid here! */ - /* lastServers[index].requestor = None; */ + /* FIXME: commented because index is invalid here! */ + /* lastServers[index].requestor = None; */ /* FIXME @@ -2154,6 +2153,7 @@ FIXME } else fprintf (stderr, "%s: SetSelectionOwner failed\n", __func__); */ + } } /* -- cgit v1.2.3 From 8f182cd74b2e1217624ed80de8f62220c09dad2e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 25 Nov 2020 00:29:37 +0100 Subject: Clipboard.c: introduce replyPendingRequestSelectionToXServer helper --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 70 ++++++++++++++------------ 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 7598f9916..6e2337a4d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -320,6 +320,7 @@ static void sendSelectionNotifyEventToClient(ClientPtr client, Atom target, Atom property); static Status sendSelectionNotifyEventToXServer(XSelectionEvent *event_to_send); +static void replyPendingRequestSelectionToXServer(int index, Bool success); #ifdef DEBUG static void printSelectionStat(int sel); #endif @@ -1898,24 +1899,45 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * effectively will send a "Request denied" to the initial * requestor. */ - XSelectionEvent eventSelection = { - .requestor = lastServers[index].requestor, - .selection = X->xselection.selection, - /* .target = X->xselection.target, */ - .target = lastServers[index].target, - .property = lastServers[index].property, - .time = lastServers[index].time, - /* .time = CurrentTime */ - }; - #ifdef DEBUG - fprintf(stderr, "%s: Sending SelectionNotify event to requestor [%p].\n", __func__, - (void *)eventSelection.requestor); - #endif + replyPendingRequestSelectionToXServer(index, True); + } + } +} - sendSelectionNotifyEventToXServer(&eventSelection); +/* + * This is similar to replyRequestSelectionToXServer(), but gets the + * required values from a stored request instead of an XEvent + * structure. + */ +void replyPendingRequestSelectionToXServer(int index, Bool success) +{ + if (lastServers[index].requestor == None) + { + #ifdef DEBUG + fprintf(stderr, "%s: no pending request for index [%d] - doing nothing\n", __func__, index); + #endif + } + else + { + XSelectionEvent eventSelection = { + .requestor = lastServers[index].requestor, + .selection = remSelAtoms[index], + .target = lastServers[index].target, + .time = lastServers[index].time, + .property = success ? lastServers[index].property : None, + }; - lastServers[index].requestor = None; /* allow further request */ - } + #ifdef DEBUG + fprintf(stderr, "%s: Sending %s SelectionNotify event to requestor [%p].\n", __func__, + success ? "positive" : "negative", (void *)eventSelection.requestor); + #endif + + sendSelectionNotifyEventToXServer(&eventSelection); + + lastServers[index].requestor = None; /* allow further request */ + lastServers[index].property = 0; + lastServers[index].target = 0; + lastServers[index].time = 0; } } @@ -2703,21 +2725,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) */ if (lastServers[index].requestor != None && event->u.selectionNotify.property == 0) { - #ifdef DEBUG - fprintf(stderr, "%s: passing on failure to lastServers[%d].requestor [%ld].\n", __func__, - index, lastServers[index].requestor); - #endif - - XSelectionEvent eventSelection = { - .requestor = lastServers[index].requestor, - .selection = remSelAtoms[index], - .target = lastServers[index].target, - .property = 0, - .time = lastServers[index].time, - }; - sendSelectionNotifyEventToXServer(&eventSelection); - - lastServers[index].requestor = None; + replyPendingRequestSelectionToXServer(index, False); return 1; } else -- cgit v1.2.3 From ff4a1967c0f98db79611d1bbf426fd7cebff0abd Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 25 Nov 2020 00:30:03 +0100 Subject: Clipboard.c: cancel pending requests in certain situations --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 6e2337a4d..d46d4c7fc 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -714,7 +714,7 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) setClientSelectionStage(SelectionStageNone, index); - lastServers[index].requestor = None; + replyPendingRequestSelectionToXServer(index, False); } if (pWindow && pWindow == lastClients[index].windowPtr) @@ -2116,13 +2116,16 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) if (lastServers[index].requestor != None) { /* - * we are in the process of communicating back and forth between - * real X server and nxagent's clients - let's not disturb - * FIXME: by continuing after the warning were ARE disturbing! - * We should cancel that communication here. + * There's an X client on the real X server waiting for a + * reply. That reply will never come because now we are the + * owner so let's be fair and cancel that request. */ - fprintf (stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set.\n", + fprintf(stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set. Cancelling pending request.\n", __func__, index, lastServers[index].requestor); + + replyPendingRequestSelectionToXServer(index, False); + + /* now we can go on */ } #endif -- cgit v1.2.3 From 1fd98b193c3f4cadb227017bb3434d1fd2c37a13 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 25 Nov 2020 00:26:16 +0100 Subject: Clipboard.c: add another FIXME --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index d46d4c7fc..682dfbab0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2163,7 +2163,11 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) /* FIXME - if (XGetSelectionOwner(nxagentDisplay,pSelection->selection) == serverWindow) +FIXME2: instead of XGetSelectionOwner we could check if the Xfixes + SetSelectionOwner event has arrived in the event queue; + possibly saving one roundtrip. + + if (XGetSelectionOwner(nxagentDisplay, pSelection->selection) == serverWindow) { fprintf (stderr, "%s: SetSelectionOwner OK\n", __func__); -- cgit v1.2.3 From 51dae621fcfd6e6453657591205e673f16c2df04 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 2 Dec 2020 23:43:53 +0100 Subject: Clipboard.c: extend target caching for the other direction This may seem unneccessary at first sight because we are only talking to our own clients which generally is quick. But if you are using nested nx sessions or clients from remote machines (e.g. via ssh X forwarding) this still can save some lenghty communication. Plus: it helps in debugging because there are fewer messages being sent around. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 93 +++++++++++++++++++++----- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 682dfbab0..f88d7588b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -108,15 +108,21 @@ static SelectionOwner *lastSelectionOwner = NULL; /* * cache for targets the current selection owner - * on the real X server has to offer. We are storing the targets - * after they have been converted from XlibAtom to Atom. + * has to offer. We are storing the targets + * after they have been converted */ typedef struct _Targets { - Atom *targets; - int numTargets; + Bool type; /* EMPTY, FORINT, FORREM */ + unsigned int numTargets; + Atom *forInt; /* Atoms converted for internal -> type Atom, not XlibAtom */ + XlibAtom *forRem; /* Atoms converted for remote -> type XlibAtom, not Atom */ } Targets; +#define EMPTY 0 +#define FORREM 1 +#define FORINT 2 + static Targets *targetCache = NULL; /* FIXME: can this also be stored per selection? */ @@ -394,7 +400,9 @@ static void printLastServerStat(int index) static void printTargetCacheStat(int index) { - fprintf(stderr, " targetCache[].targets (Atom *) [%p]\n", (void *)targetCache[index].targets); + fprintf(stderr, " targetCache[].type (int) [%d]\n", targetCache[index].type); + fprintf(stderr, " targetCache[].forInt (Atom *) [%p]\n", (void *)targetCache[index].forInt); + fprintf(stderr, " targetCache[].forRem (XlibAtom *) [%p]\n", (void *)targetCache[index].forRem); fprintf(stderr, " targetCache[].numTargets (int) [%d]\n", targetCache[index].numTargets); } @@ -768,14 +776,29 @@ int nxagentFindCurrentSelectionIndex(Atom sel) return NumCurrentSelections; } -void cacheTargets(int index, Atom* targets, int numTargets) +void cacheTargetsForInt(int index, Atom* targets, int numTargets) +{ + #ifdef DEBUG + fprintf(stderr, "%s: caching [%d] targets for internal requests\n", __func__, numTargets); + #endif + + SAFE_free(targetCache[index].forInt); + SAFE_free(targetCache[index].forRem); + targetCache[index].type = FORINT; + targetCache[index].forInt = targets; + targetCache[index].numTargets = numTargets; +} + +void cacheTargetsForRem(int index, XlibAtom* targets, int numTargets) { #ifdef DEBUG - fprintf(stderr, "%s: caching [%d] targets\n", __func__, numTargets); + fprintf(stderr, "%s: caching [%d] targets for remote requests\n", __func__, numTargets); #endif - SAFE_free(targetCache[index].targets); - targetCache[index].targets = targets; + SAFE_free(targetCache[index].forInt); + SAFE_free(targetCache[index].forRem); + targetCache[index].type = FORREM; + targetCache[index].forRem = targets; targetCache[index].numTargets = numTargets; } @@ -786,7 +809,9 @@ void invalidateTargetCache(int index) fprintf(stderr, "%s: invalidating target cache [%d]\n", __func__, index); #endif - SAFE_free(targetCache[index].targets); + SAFE_free(targetCache[index].forInt); + SAFE_free(targetCache[index].forRem); + targetCache[index].type = EMPTY; targetCache[index].numTargets = 0; } @@ -798,7 +823,9 @@ void invalidateTargetCaches(void) for (int index = 0; index < nxagentMaxSelections; index++) { - SAFE_free(targetCache[index].targets); + SAFE_free(targetCache[index].forInt); + SAFE_free(targetCache[index].forRem); + targetCache[index].type = EMPTY; targetCache[index].numTargets = 0; } } @@ -1006,7 +1033,39 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } else { - /* do nothing, let TARGETS be passed on to the owner later */ + /* + * Shortcut: Some applications tend to post multiple + * SelectionRequests. Further it can happen that multiple + * clients are interested in clipboard content. If we already + * know the answer and no intermediate SelectionOwner event + * occured we can answer with the cached list of targets. + */ + + if (targetCache[index].type == FORREM && targetCache[index].forRem) + { + XlibAtom *targets = targetCache[index].forRem; + unsigned int numTargets = targetCache[index].numTargets; + + #ifdef DEBUG + fprintf(stderr, "%s: Sending %d cached targets to remote requestor:\n", __func__, numTargets); + for (int i = 0; i < numTargets; i++) + { + fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); + } + #endif + + XChangeProperty(nxagentDisplay, + X->xselectionrequest.requestor, + X->xselectionrequest.property, + XInternAtom(nxagentDisplay, "ATOM", 0), + 32, + PropModeReplace, + (unsigned char *)targets, + numTargets); + + replyRequestSelectionToXServer(X, True); + return; + } } } else if (X->xselectionrequest.target == serverTIMESTAMP) @@ -1601,7 +1660,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) 32, PropModeReplace, ulReturnItems, (unsigned char*)targets, 1); - cacheTargets(index, targets, numTargets); + cacheTargetsForInt(index, targets, numTargets); endTransfer(SELECTION_SUCCESS, index); } @@ -1852,7 +1911,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) (unsigned char*)targets, numTargets); - SAFE_free(targets); + cacheTargetsForRem(index, targets, numTargets); } } else @@ -2358,13 +2417,13 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * occured we can answer with the cached list of targets. */ - if (targetCache[index].targets) + if (targetCache[index].type == FORINT && targetCache[index].forInt) { - Atom *targets = targetCache[index].targets; + Atom *targets = targetCache[index].forInt; int numTargets = targetCache[index].numTargets; #ifdef DEBUG - fprintf(stderr, "%s: Sending %d cached targets:\n", __func__, numTargets); + fprintf(stderr, "%s: Sending %d cached targets to internal client:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) { fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForIntAtom(targets[i])); -- cgit v1.2.3 From 7a2c743ac4d8578ddfc5baa5c6256060fe3c93c6 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 14 Dec 2020 22:16:58 +0100 Subject: Clipboard.c: move property transfer to separate function --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 230 +++++++++++++------------ 1 file changed, 118 insertions(+), 112 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f88d7588b..8a5e3606c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -331,6 +331,7 @@ static void replyPendingRequestSelectionToXServer(int index, Bool success); static void printSelectionStat(int sel); #endif static void replyRequestSelectionToXServer(XEvent *X, Bool success); +void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property); void nxagentPrintClipboardStat(char *); @@ -1818,30 +1819,54 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } else { - /* if the last owner was an internal one, read the - * clientCutProperty and push the contents to the - * lastServers[index].requestor on the real X server. - */ - if (IS_INTERNAL_OWNER(index) && - lastSelectionOwner[index].windowPtr != NULL && - X->xselection.property == serverTransFromAgentProperty) - { - Atom atomReturnType; - int resultFormat; - unsigned long ulReturnItems; - unsigned long ulReturnBytesLeft; - unsigned char *pszReturnData = NULL; + handlePropertyTransferFromAgentToXserver(index, X->xselection.property); + } +} - /* first get size values ... */ - int result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, 0, False, - AnyPropertyType, &atomReturnType, &resultFormat, - &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); +void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) +{ + /* if the last owner was an internal one, read the + * clientCutProperty and push the contents to the + * lastServers[index].requestor on the real X server. + */ + if (IS_INTERNAL_OWNER(index) && + lastSelectionOwner[index].windowPtr != NULL && + property == serverTransFromAgentProperty) + { + Atom atomReturnType; + int resultFormat; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; + /* first get size values ... */ + int result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, 0, False, + AnyPropertyType, &atomReturnType, &resultFormat, + &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); + + #ifdef DEBUG + fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, + lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), + getXErrorString(result)); + #endif + if (result == BadAlloc || result == BadAtom || + result == BadWindow || result == BadValue) + { + lastServers[index].property = None; + } + else + { + /* ... then use the size values for the actual request */ + result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, + ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, + &resultFormat, &ulReturnItems, &ulReturnBytesLeft, + &pszReturnData); #ifdef DEBUG fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), getXErrorString(result)); #endif + if (result == BadAlloc || result == BadAtom || result == BadWindow || result == BadValue) { @@ -1849,117 +1874,98 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) } else { - /* ... then use the size values for the actual request */ - result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, - ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, - &resultFormat, &ulReturnItems, &ulReturnBytesLeft, - &pszReturnData); - #ifdef DEBUG - fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, - lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), - getXErrorString(result)); - #endif - - if (result == BadAlloc || result == BadAtom || - result == BadWindow || result == BadValue) + if (lastServers[index].target == serverTARGETS) { - lastServers[index].property = None; - } - else - { - if (lastServers[index].target == serverTARGETS) + #ifdef DEBUG + fprintf(stderr, "%s: ulReturnItems [%ld]\n", __func__, ulReturnItems); + fprintf(stderr, "%s: resultformat [%d]\n", __func__, resultFormat); + #endif + + XlibAtom * targets = calloc(sizeof(XlibAtom), ulReturnItems); + if (targets == NULL) { - #ifdef DEBUG - fprintf(stderr, "%s: ulReturnItems [%ld]\n", __func__, ulReturnItems); - fprintf(stderr, "%s: resultformat [%d]\n", __func__, resultFormat); + #ifdef WARNING + fprintf(stderr, "%s: WARNING! Could not alloc memory for clipboard targets transmission.\n", __func__); #endif + /* this will effectively lead to the request being answered as failed */ + lastServers[index].property = None; + } + else + { + /* Convert the targets to remote atoms */ + XlibAtom *addr = targets; + unsigned int numTargets = ulReturnItems; - XlibAtom * targets = calloc(sizeof(XlibAtom), ulReturnItems); - if (targets == NULL) + for (int i = 0; i < numTargets; i++) { - #ifdef WARNING - fprintf(stderr, "%s: WARNING! Could not alloc memory for clipboard targets transmission.\n", __func__); + Atom local = *((Atom*)(pszReturnData + i*resultFormat/8)); + XlibAtom remote = nxagentLocalToRemoteAtom(local); + *(addr++) = remote; + + #ifdef DEBUG + fprintf(stderr, "%s: converting atom: local [%d][%s] -> remote [%ld][%s]\n", __func__, + local, NameForIntAtom(local), remote, NameForRemAtom(remote)); #endif - /* this will effectively lead to the request being answered as failed */ - lastServers[index].property = None; } - else - { - /* Convert the targets to remote atoms */ - XlibAtom *addr = targets; - unsigned int numTargets = ulReturnItems; - for (int i = 0; i < numTargets; i++) - { - Atom local = *((Atom*)(pszReturnData + i*resultFormat/8)); - XlibAtom remote = nxagentLocalToRemoteAtom(local); - *(addr++) = remote; - - #ifdef DEBUG - fprintf(stderr, "%s: converting atom: local [%d][%s] -> remote [%ld][%s]\n", __func__, - local, NameForIntAtom(local), remote, NameForRemAtom(remote)); - #endif - } - - /* FIXME: do we need to take care of swapping byte order here? */ - XChangeProperty(nxagentDisplay, - lastServers[index].requestor, - lastServers[index].property, - XInternAtom(nxagentDisplay, "ATOM", 0), - 32, - PropModeReplace, - (unsigned char*)targets, - numTargets); - - cacheTargetsForRem(index, targets, numTargets); - } - } - else - { - /* Fill the property on the initial requestor with the requested data */ - /* The XChangeProperty source code reveals it will always - return 1, no matter what, so no need to check the result */ - /* FIXME: better use the format returned by above request */ + /* FIXME: do we need to take care of swapping byte order here? */ XChangeProperty(nxagentDisplay, lastServers[index].requestor, lastServers[index].property, - lastServers[index].target, - 8, + XInternAtom(nxagentDisplay, "ATOM", 0), + 32, PropModeReplace, - pszReturnData, - ulReturnItems); - #ifdef DEBUG - { - fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] len [%d] value [\"%*.*s\"...]\n", - __func__, - lastServers[index].requestor, - lastServers[index].property, - NameForRemAtom(lastServers[index].property), - (int)ulReturnItems * 8 / 8, - (int)(min(20, ulReturnItems * 8 / 8)), - (int)(min(20, ulReturnItems * 8 / 8)), - pszReturnData); - } - #endif - } + (unsigned char*)targets, + numTargets); - /* FIXME: free it or not? */ - /* - * SAFE_XFree(pszReturnData); - */ + cacheTargetsForRem(index, targets, numTargets); + } + } + else + { + /* Fill the property on the requestor with the requested data */ + /* The XChangeProperty source code reveals it will always + return 1, no matter what, so no need to check the result */ + /* FIXME: better use the format returned by above request */ + XChangeProperty(nxagentDisplay, + lastServers[index].requestor, + lastServers[index].property, + lastServers[index].target, + 8, + PropModeReplace, + pszReturnData, + ulReturnItems); + #ifdef DEBUG + { + fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] len [%d] value [\"%*.*s\"...]\n", + __func__, + lastServers[index].requestor, + lastServers[index].property, + NameForRemAtom(lastServers[index].property), + (int)ulReturnItems * 8 / 8, + (int)(min(20, ulReturnItems * 8 / 8)), + (int)(min(20, ulReturnItems * 8 / 8)), + pszReturnData); + } + #endif } - } - /* - * inform the initial requestor that the requested data has - * arrived in the desired property. If we have been unable to - * get the data from the owner XChangeProperty will not have - * been called and lastServers[index].property will be None which - * effectively will send a "Request denied" to the initial - * requestor. - */ - replyPendingRequestSelectionToXServer(index, True); + /* FIXME: free it or not? */ + /* + * SAFE_XFree(pszReturnData); + */ + } } + + /* + * inform the initial requestor that the requested data has + * arrived in the desired property. If we have been unable to + * get the data from the owner XChangeProperty will not have + * been called and lastServers[index].property will be None which + * effectively will send a "Request denied" to the initial + * requestor. + */ + replyPendingRequestSelectionToXServer(index, True); } } -- cgit v1.2.3 From 75acbbf299b57aeae993b73927fd8b727be94c81 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 23 Dec 2020 19:49:19 +0100 Subject: Clipboard.c: make index the first argument everywhere --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 68 +++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 8a5e3606c..d54171a0d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -305,11 +305,11 @@ XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, False }; extern Display *nxagentDisplay; static Bool isTextTarget(XlibAtom target); -static void setClientSelectionStage(int stage, int index); -static void endTransfer(Bool success, int index); +static void setClientSelectionStage(int index, int stage); +static void endTransfer(int index, Bool success); #define SELECTION_SUCCESS True #define SELECTION_FAULT False -static void transferSelectionFromXServer(int resource, int index); +static void transferSelectionFromXServer(int index, int resource); #if 0 static void resetSelectionOwnerOnXServer(void); #endif @@ -508,7 +508,7 @@ static void resetClientSelectionStage(int index) lastClients[index].resource = -1; } -static void setClientSelectionStage(int stage, int index) +static void setClientSelectionStage(int index, int stage) { if (stage == SelectionStageNone) { @@ -721,14 +721,14 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) clearSelectionOwnerData(index); - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); replyPendingRequestSelectionToXServer(index, False); } if (pWindow && pWindow == lastClients[index].windowPtr) { - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); } } } @@ -885,7 +885,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) clearSelectionOwnerData(index); - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); invalidateTargetCache(index); } @@ -1308,7 +1308,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * denied/failed" * Use SELECTION_SUCCESS and SELECTION_FAULT macros for success. */ -static void endTransfer(Bool success, int index) +static void endTransfer(int index, Bool success) { if (lastClients[index].clientPtr == NULL) { @@ -1338,10 +1338,10 @@ static void endTransfer(Bool success, int index) /* * Enable further requests from clients. */ - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); } -static void transferSelectionFromXServer(int resource, int index) +static void transferSelectionFromXServer(int index, int resource) { #ifdef DEBUG fprintf(stderr, "%s: resource [%d] lastClients[%d].clientPtr->index [%d].\n", __func__, @@ -1355,7 +1355,7 @@ static void transferSelectionFromXServer(int resource, int index) resource, nxagentClientInfoString(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); return; } @@ -1406,12 +1406,12 @@ static void transferSelectionFromXServer(int resource, int index) nxagentClientInfoString(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); return; } - setClientSelectionStage(SelectionStageWaitSize, index); + setClientSelectionStage(index, SelectionStageWaitSize); NXFlushDisplay(nxagentDisplay, NXFlushLink); @@ -1463,12 +1463,12 @@ static void transferSelectionFromXServer(int resource, int index) nxagentClientInfoString(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); return; } - setClientSelectionStage(SelectionStageWaitData, index); + setClientSelectionStage(index, SelectionStageWaitData); /* we've seen situations where you had to move the mouse or press a key to let the transfer complete. Flushing here fixed it */ @@ -1557,7 +1557,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) fprintf (stderr, "%s: Failed to get reply data.\n", __func__); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } else if (resultFormat != 8 && resultFormat != 16 && resultFormat != 32) { @@ -1565,7 +1565,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) fprintf(stderr, "%s: WARNING! Invalid property format.\n", __func__); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } else { @@ -1585,7 +1585,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) fprintf (stderr, "%s: data size is [0] - aborting selection notify procedure.\n", __func__); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } else { @@ -1597,9 +1597,9 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) * Request the selection data now. */ lastClients[index].propertySize = ulReturnBytesLeft; - setClientSelectionStage(SelectionStageQueryData, index); + setClientSelectionStage(index, SelectionStageQueryData); - transferSelectionFromXServer(resource, index); + transferSelectionFromXServer(index, resource); } break; } @@ -1617,7 +1617,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) fprintf (stderr, "%s: not all content could be retrieved - [%lu] bytes left - aborting selection notify procedure.\n", __func__, ulReturnBytesLeft); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } else { @@ -1635,7 +1635,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) #endif /* operation failed */ - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } else { @@ -1663,7 +1663,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) cacheTargetsForInt(index, targets, numTargets); - endTransfer(SELECTION_SUCCESS, index); + endTransfer(index, SELECTION_SUCCESS); } } else @@ -1683,7 +1683,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) pszReturnData); #endif - endTransfer(SELECTION_SUCCESS, index); + endTransfer(index, SELECTION_SUCCESS); } } break; @@ -1785,10 +1785,10 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) * tions. */ - setClientSelectionStage(SelectionStageQueryData, index); + setClientSelectionStage(index, SelectionStageQueryData); lastClients[index].propertySize = 262144; - transferSelectionFromXServer(lastClients[index].clientPtr -> index, index); + transferSelectionFromXServer(index, lastClients[index].clientPtr -> index); } else if (X->xselection.property == 0) { @@ -1796,7 +1796,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) fprintf(stderr, "%s: WARNING! Resetting selection transferral for client [%d] because of failure notification from real X server.\n", __func__, CLINDEX(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } else { @@ -1804,7 +1804,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) fprintf(stderr, "%s: Unexpected property [%ld][%s] - reporting conversion failure.\n", __func__, X->xselection.property, NameForRemAtom(X->xselection.property)); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } } else @@ -1814,7 +1814,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) CLINDEX(lastClients[index].clientPtr)); #endif - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); } } else @@ -2040,7 +2040,7 @@ static void resetSelectionOwnerOnXServer(void) clearSelectionOwnerData(index); - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); /* Hmm, this is already None when reaching here */ lastServers[index].requestor = None; @@ -2213,7 +2213,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) */ storeSelectionOwnerData(index, pSelection); - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); /* * this will be repeated on reception of the SelectionOwner callback @@ -2241,7 +2241,7 @@ FIXME2: instead of XGetSelectionOwner we could check if the Xfixes lastSelectionOwnerWindow = pSelection->window; lastSelectionOwnerWindowPtr = pSelection->pWin; - setClientSelectionStage(SelectionStageNone); + setClientSelectionStage(index, SelectionStageNone); lastServers[index].requestor = None; } @@ -2337,7 +2337,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif /* notify the waiting client of failure */ - endTransfer(SELECTION_FAULT, index); + endTransfer(index, SELECTION_FAULT); /* do NOT return here but process the new request instead! */ } @@ -2586,7 +2586,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, clientAccum = 0; } - setClientSelectionStage(SelectionStageNone, index); + setClientSelectionStage(index, SelectionStageNone); /* * store the original requestor, we need that later after -- cgit v1.2.3 From f578b86d34f5858fa215f6eebc12fec82f16792e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 30 Jan 2021 18:38:25 +0100 Subject: Clipboard.c: rework nxagentFind*SelectionIndex() helpers Let them return -1 which makes it easier to check for successful execution. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 24 +++++++++++++----------- nx-X11/programs/Xserver/hw/nxagent/Events.c | 2 +- nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index d54171a0d..3098ebb49 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -735,7 +735,8 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) /* * Find the index of the lastSelectionOwner with the selection - * sel. sel is an atom on the real X server. + * sel. sel is an atom on the real X server. If the index cannot be + * determined it will return -1. */ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { @@ -752,12 +753,13 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) #ifdef DEBUG fprintf(stderr, "%s: remote selection [%ld][%s] does not belong to any index!\n", __func__, sel, NameForRemAtom(sel)); #endif - return nxagentMaxSelections; + return -1; } /* * Find the index of CurrentSelection with the selection - * sel. sel is an internal atom. + * sel. sel is an internal atom. If the index cannot be + * determined it will return -1. */ int nxagentFindCurrentSelectionIndex(Atom sel) { @@ -774,7 +776,7 @@ int nxagentFindCurrentSelectionIndex(Atom sel) #ifdef DEBUG fprintf(stderr, "%s: selection [%d][%s] does not belong to any index!\n", __func__, sel, NameForIntAtom(sel)); #endif - return NumCurrentSelections; + return -1; } void cacheTargetsForInt(int index, Atom* targets, int numTargets) @@ -861,7 +863,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) } int index = nxagentFindLastSelectionOwnerIndex(X->xselectionclear.selection); - if (index < nxagentMaxSelections) + if (index != -1) { if (IS_INTERNAL_OWNER(index)) { @@ -951,7 +953,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) /* the selection in this request is none we own. */ int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); - if (index == nxagentMaxSelections) + if (index == -1) { #ifdef DEBUG fprintf(stderr, "%s: not owning selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); @@ -1736,7 +1738,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) /* determine the selection we are talking about here */ int index = nxagentFindLastSelectionOwnerIndex(e->selection); - if (index == nxagentMaxSelections) + if (index == -1) { #ifdef DEBUG fprintf (stderr, "%s: unknown selection [%ld] .\n", __func__, e->selection); @@ -2162,7 +2164,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) #endif int index = nxagentFindCurrentSelectionIndex(pSelection->selection); - if (index < NumCurrentSelections) + if (index != -1) { #ifdef DEBUG fprintf(stderr, "%s: lastSelectionOwner.client %s -> %s\n", __func__, @@ -2294,7 +2296,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } int index = nxagentFindCurrentSelectionIndex(selection); - if (index == NumCurrentSelections) + if (index == -1) { #ifdef DEBUG fprintf(stderr, "%s: cannot find index for selection [%u]\n", __func__, selection); @@ -2761,7 +2763,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) #endif int index = nxagentFindCurrentSelectionIndex(event->u.selectionNotify.selection); - if (index == nxagentMaxSelections) + if (index == -1) { #ifdef DEBUG fprintf(stderr, "%s: unknown selection [%d]\n", __func__, @@ -2845,7 +2847,7 @@ WindowPtr nxagentGetClipboardWindow(Atom property) } int index = nxagentFindLastSelectionOwnerIndex(serverLastRequestedSelection); - if (index < nxagentMaxSelections && + if (index != -1 && property == clientCutProperty && lastSelectionOwner[index].windowPtr != NULL) { diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 2ec17c328..d29ed9bcd 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2850,7 +2850,7 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) Atom local = nxagentRemoteToLocalAtom(xfixesEvent -> xfixesselection.selection); int index = nxagentFindCurrentSelectionIndex(local); - if (index < NumCurrentSelections) + if (index != -1) { if (CurrentSelections[index].client != 0) { diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c index a8739fa3f..ff8330cc7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -722,8 +722,8 @@ ProcConvertSelection(register ClientPtr client) (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) && nxagentOption(Clipboard) != ClipboardNone) { - int i = nxagentFindCurrentSelectionIndex(stuff->selection); - if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None)) + int index = nxagentFindCurrentSelectionIndex(stuff->selection); + if ((index != -1) && (CurrentSelections[index].window != None)) { if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor, stuff->property, stuff->target, stuff->time)) -- cgit v1.2.3 From 9d8771562c847e957250f7df7411b9ce92dd1143 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 30 Jan 2021 18:39:14 +0100 Subject: Clipboard.c: limit selection nxagentFindCurrentSelectionIndex can return Normally you'd expect the loop going up to NumCurrentSelections. But the dix code will increase that number (but not nxagentMaxSelections) when drag and drop comes into play. In that case this helper will report a match for other selections than the ones the clipboard code knows about. The subsequent code will then use a higher index which will lead to out of range data reads (and writes!). Therefore we take nxagentMaxSelections here. The startup code ensures that both arrays will refer to the same selection for the first nxagentMaxSelections selection atoms. This way the clipboard code will not kick in for drag and drop resources. Fixes ArcticaProject/nx-libs#986 --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3098ebb49..b3598eef8 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -763,7 +763,21 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) */ int nxagentFindCurrentSelectionIndex(Atom sel) { - for (int index = 0; index < NumCurrentSelections; index++) + /* + * Normally you'd expect the loop going up to + * NumCurrentSelections. But the dix code will increase that number + * (but not nxagentMaxSelections) when drag and drop comes into + * play. In that case this helper will report a match for other + * selections than the ones the clipboard code knows about. The + * subsequent code will then use a higher index which will be used + * by the clipboard code and will lead to out of range data reads + * (and writes!). Therefore we take nxagentMaxSelections here. The + * startup code ensures that both arrays will refer to the same + * selection for the first nxagentMaxSelections selection atoms. + */ + + // for (int index = 0; index < NumCurrentSelections; index++) + for (int index = 0; index < nxagentMaxSelections; index++) { if (CurrentSelections[index].selection == sel) { -- cgit v1.2.3 From d335fc8fb04e1611352842b6f6d68f3fe43d44e9 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 30 Jan 2021 19:07:43 +0100 Subject: Clipboard.c: do not handle unknown selections in Callback handler --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index b3598eef8..b77cb181a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2108,11 +2108,23 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, } #endif + Selection * pCurSel = (Selection *)info->selection; + + int index = nxagentFindCurrentSelectionIndex(pCurSel->selection); + if (index == -1) + { + #ifdef DEBUG + fprintf(stderr, "%s: selection [%s] will not be handled by the clipboard code\n", __func__, NameForIntAtom(pCurSel->selection)); + #endif + return; + } + /* - * We do not know index here so for now let's invalidate the - * complete cache on every owner change regardless of the selection. + * always invalidate the target cache for the relevant selection, + * even if the trap is set. This ensures not having invalid data in + * the cache. */ - invalidateTargetCaches(); + invalidateTargetCache(index); if (nxagentExternalClipboardEventTrap) { @@ -2122,7 +2134,6 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, return; } - Selection * pCurSel = (Selection *)info->selection; #ifdef DEBUG fprintf(stderr, "%s: pCurSel->lastTimeChanged [%u]\n", __func__, pCurSel->lastTimeChanged.milliseconds); -- cgit v1.2.3 From 65c260edf9a02d71dbc840b867ab64a62fefedc5 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 12 Feb 2021 22:21:39 +0100 Subject: Clipboard.c: improve debugging output once more --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index b77cb181a..508ae5699 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1565,6 +1565,14 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) &ulReturnBytesLeft, &pszReturnData); + #ifdef DEBUG + fprintf(stderr, "%s: NXGetCollectedProperty: result [%d]\n", __func__, result); + fprintf(stderr, "%s: atomReturnType [%ld]\n", __func__, atomReturnType); + fprintf(stderr, "%s: resultFormat [%d]\n", __func__, resultFormat); + fprintf(stderr, "%s: ulReturnItems [%lu]\n", __func__, ulReturnItems); + fprintf(stderr, "%s: ulReturnBytesLeft [%lu]\n", __func__, ulReturnBytesLeft); + #endif + lastClients[index].resource = -1; if (result == 0) @@ -1578,7 +1586,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) else if (resultFormat != 8 && resultFormat != 16 && resultFormat != 32) { #ifdef DEBUG - fprintf(stderr, "%s: WARNING! Invalid property format.\n", __func__); + fprintf(stderr, "%s: WARNING! Invalid property format [%d].\n", __func__, resultFormat); #endif endTransfer(index, SELECTION_FAULT); @@ -1638,7 +1646,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) else { #ifdef DEBUG - fprintf(stderr, "%s: Got property content from remote server. size [%lu] bytes.\n", __func__, (ulReturnItems * resultFormat / 8)); + fprintf(stderr, "%s: Got property content from remote server. [%lu] items with format [%d] = [%lu] bytes.\n", __func__, ulReturnItems, resultFormat, (ulReturnItems * resultFormat/8)); #endif if (lastClients[index].target == clientTARGETS) @@ -2587,6 +2595,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, if (lastClients[index].clientPtr == client) { + #ifdef DEBUG + fprintf(stderr, "%s: same client as previous request\n", __func__); + #endif + if (GetTimeInMillis() - lastClients[index].reqTime < ACCUM_TIME) { /* -- cgit v1.2.3 From 6ba18093742f222363bae29b9675f8016a50d033 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 12 Feb 2021 22:29:01 +0100 Subject: Clipboard.c: delete property before/after certain operations for ICCCM conformity Fixes ArcticaProject/nx-libs#969 --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 508ae5699..ef4315e41 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1206,6 +1206,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * - vcxsrv request is for _primary_ and takes this path as the _clipboard_ transfer * has set lastClients[index].windowPtr */ + XDeleteProperty(nxagentDisplay, serverWindow, serverTransToAgentProperty); XConvertSelection(nxagentDisplay, CurrentSelections[index].selection, X->xselectionrequest.target, serverTransToAgentProperty, serverWindow, lastClients[index].time); @@ -1290,6 +1291,12 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); } + /* + * delete property before sending the request to the client - + * required by ICCCM + */ + DeleteProperty(lastSelectionOwner[index].windowPtr, clientCutProperty); + sendEventToClient(lastSelectionOwner[index].client, &x); #ifdef DEBUG @@ -1575,6 +1582,23 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) lastClients[index].resource = -1; + /* + * ICCCM states: "The requestor must delete the property named in + * the SelectionNotify once all the data has been retrieved. The + * requestor should invoke either DeleteProperty or GetProperty + * (delete==True) after it has successfully retrieved all the data + * in the selection." + * FIXME: this uses serverTransToAgentProperty which is shared between + * all the selections. Could be a problem with simultaneous transfers. + */ + if (result != 0 && ulReturnBytesLeft == 0) + { + #ifdef DEBUG + fprintf (stderr, "%s: Retrieved property data - deleting it for ICCCM conformity.\n", __func__); + #endif + XDeleteProperty(nxagentDisplay, serverWindow, serverTransToAgentProperty); + } + if (result == 0) { #ifdef DEBUG @@ -2658,7 +2682,19 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, remSelection, NameForRemAtom(remSelection)); #endif + /* + * ICCCM: "It is necessary for requestors to delete the property + * before issuing the request so that the target can later be + * extended to take parameters without introducing an + * incompatibility. Also note that the requestor of a selection need + * not know the client that owns the selection nor the window on + * which the selection was acquired." + */ + + XDeleteProperty(nxagentDisplay, serverWindow, remProperty); + UpdateCurrentTime(); + XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); /* XConvertSelection will always return 1 (check the source!), so no -- cgit v1.2.3 From 9eb76cf5d545c3b823626423c832986af4c4ac38 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 12 Feb 2021 22:45:05 +0100 Subject: Clipboard.c: move comment to correct location --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index ef4315e41..ed46f3d6a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -130,12 +130,6 @@ static XlibAtom serverLastRequestedSelection = -1; #define IS_INTERNAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NullClient) -/* - * Needed to handle the notify selection event to - * be sent to client once the selection property - * has been retrieved from the real X server. - */ - typedef enum { SelectionStageNone, @@ -145,6 +139,12 @@ typedef enum SelectionStageWaitData } ClientSelectionStage; +/* + * Needed to handle the notify selection event to be sent to the + * waiting client once the selection property has been retrieved from + * the real X server. + */ + typedef struct _lastClient { WindowPtr windowPtr; -- cgit v1.2.3 From 04ca25eb1af9b3ea3eb94ceb851e0eda2a08b535 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 12 Feb 2021 22:50:47 +0100 Subject: Clipboard.c: fix some comments, add FIXME --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index ed46f3d6a..4c0c6d320 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1521,7 +1521,6 @@ static void transferSelectionFromXServer(int index, int resource) True: processed False: not processed, resource is not ours */ - Bool nxagentCollectPropertyEventFromXServer(int resource) { XlibAtom atomReturnType; @@ -2378,6 +2377,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * consider the conversion failed and tell our client about that. * The new request that lead us here is then processed. */ + #ifdef TEST + fprintf(stderr, "%s: lastClients[%d].windowPtr [0x%lx].\n", __func__, index, (unsigned long)lastClients[index].windowPtr); + #endif + if (lastClients[index].windowPtr != NULL) { #ifdef TEST @@ -2693,6 +2696,13 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, XDeleteProperty(nxagentDisplay, serverWindow, remProperty); + /* + * FIXME: ICCCM states: "Clients should not use CurrentTime for the + * time argument of a ConvertSelection request. Instead, they should + * use the timestamp of the event that caused the request to be + * made." + */ + UpdateCurrentTime(); XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, -- cgit v1.2.3 From d97e5022e8e04f5316908dc772a491e5fe422b4c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 12 Feb 2021 23:26:16 +0100 Subject: Clipboard.c: check target cache for valid targets Instead of passing the target to the remote side and then receiving an "invalid target" reply we can do that check directly (if the target cache is filled). This way we can save some more roundtrips due to the target cache. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 98 ++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 4c0c6d320..c85e61298 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1187,6 +1187,55 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * can process it now. */ + if (!nxagentOption(TextClipboard)) + { + /* Optimization: if we have a current target cache check if the + * requested target is supported by the owner. If not we can take + * a shortcut and deny the request immediately without doing any + * further communication */ + if (targetCache[index].type == FORREM && targetCache[index].forRem) + { + XlibAtom *targets = targetCache[index].forRem; + + #ifdef DEBUG + fprintf(stderr, "%s: Checking target validity\n", __func__); + #endif + Bool match = False; + for (int i = 0; i < targetCache[index].numTargets; i++) + { + if (targets[i] == X->xselectionrequest.target) + { + match = True; + break; + } + } + if (!match) + { + #ifdef DEBUG + fprintf(stderr, "%s: target [%ld][%s] is not supported by the owner - denying request.\n", + __func__, X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target)); + #endif + replyRequestSelectionToXServer(X, False); + return; + } + } + else + { + /* + * at this stage we know a remote client has asked for a selection + * target without having retrieved the list of supported targets + * first. + */ + #ifdef DEBUG + if (X->xselectionrequest.target != serverTARGETS) + { + fprintf(stderr, "%s: WARNING: remote client has not retrieved TARGETS before asking for selection!\n", + __func__); + } + #endif + } + } + /* * This is required for nxagentGetClipboardWindow. */ @@ -2620,6 +2669,55 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, NameForIntAtom(target)); #endif + if (!nxagentOption(TextClipboard)) + { + /* Optimization: if we have a current target cache check if the + * requested target is supported by the owner. If not we can take + * a shortcut and deny the request immediately without doing any + * further communication */ + if (targetCache[index].type == FORINT && targetCache[index].forInt) + { + Atom *targets = targetCache[index].forInt; + + #ifdef DEBUG + fprintf(stderr, "%s: Checking target validity\n", __func__); + #endif + Bool match = False; + for (int i = 0; i < targetCache[index].numTargets; i++) + { + if (targets[i] == target) + { + match = True; + break; + } + } + if (!match) + { + #ifdef DEBUG + fprintf(stderr, "%s: target [%d][%s] is not supported by the owner - denying request.\n", + __func__, target, NameForIntAtom(target)); + #endif + sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); + return 1; + } + } + else + { + /* + * at this stage we know a client has asked for a selection + * target without having retrieved the list of supported targets + * first. + */ + #ifdef DEBUG + if (target != clientTARGETS) + { + fprintf(stderr, "%s: WARNING: client has not retrieved TARGETS before asking for selection!\n", + __func__); + } + #endif + } + } + if (lastClients[index].clientPtr == client) { #ifdef DEBUG -- cgit v1.2.3 From 5c205f57a76e99063f29dbe20e58019d6b39fb7e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 2 Mar 2021 21:31:07 +0100 Subject: Clipboard.c: fix wrong debug message printing the wrong client makes the debug output very confusing ;-) --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index c85e61298..4bdd32e8f 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2443,8 +2443,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) { #ifdef DEBUG - fprintf(stderr, "%s: timeout expired on previous request, " - "notifying failure to client %s\n", __func__, nxagentClientInfoString(client)); + fprintf(stderr, "%s: timeout expired on previous request - " + "notifying failure to waiting client\n", __func__); #endif /* notify the waiting client of failure */ -- cgit v1.2.3 From 03502b36edbd2390c8b93edcc6b5f57299977578 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 2 Mar 2021 22:14:52 +0100 Subject: Clipboard.c: print clipboard content only on explicit request This helps making people aware that their debug logs might contain sensible information. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 46 ++++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 4bdd32e8f..27aa49578 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -59,6 +59,13 @@ #undef TEST #undef DEBUG +/* + * define this to see the clipboard content in the debug output. As + * this can lead to information leaking it must be activated + * explicitly! + */ +#undef PRINT_CLIPBOARD_CONTENT_ON_DEBUG + /* * Define these to also support special targets TEXT and COMPOUND_TEXT * in text-only mode. We do not have a special handling for these. See @@ -432,6 +439,11 @@ void nxagentDumpClipboardStat(void) fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemAtom(serverLastRequestedSelection)); fprintf(stderr, "Compile time settings\n"); +#ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG + fprintf(stderr, " PRINT_CLIPBOARD_CONTENT_ON_DEBUG [enabled]\n"); +#else + fprintf(stderr, " PRINT_CLIPBOARD_CONTENT_ON_DEBUG [disabled]\n"); +#endif #ifdef SUPPORT_TEXT_TARGET fprintf(stderr, " SUPPORT_TEXT_TARGET [enabled]\n"); #else @@ -1771,12 +1783,19 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) ulReturnItems, pszReturnData, 1); #ifdef DEBUG - fprintf(stderr, "%s: Selection property [%d][%s] changed to [\"%*.*s\"...]\n", __func__, - lastClients[index].property, - validateString(NameForIntAtom(lastClients[index].property)), - (int)(min(20, ulReturnItems * resultFormat / 8)), - (int)(min(20, ulReturnItems * resultFormat / 8)), - pszReturnData); + fprintf(stderr, "%s: Selection property [%d][%s] changed to" + #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG + "[\"%*.*s\"...]" + #endif + "\n", __func__, + lastClients[index].property, + validateString(NameForIntAtom(lastClients[index].property)) + #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG + ,(int)(min(20, ulReturnItems * resultFormat / 8)), + (int)(min(20, ulReturnItems * resultFormat / 8)), + pszReturnData + #endif + ); #endif endTransfer(index, SELECTION_SUCCESS); @@ -2033,15 +2052,22 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) ulReturnItems); #ifdef DEBUG { - fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] len [%d] value [\"%*.*s\"...]\n", + fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] len [%d]" + #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG + "value [\"%*.*s\"...]" + #endif + "\n", __func__, lastServers[index].requestor, lastServers[index].property, NameForRemAtom(lastServers[index].property), - (int)ulReturnItems * 8 / 8, - (int)(min(20, ulReturnItems * 8 / 8)), + (int)ulReturnItems * 8 / 8 + #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG + ,(int)(min(20, ulReturnItems * 8 / 8)), (int)(min(20, ulReturnItems * 8 / 8)), - pszReturnData); + pszReturnData + #endif + ); } #endif } -- cgit v1.2.3 From 9293348c821f4939e38615853b47b8601d8e5d46 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 2 Mar 2021 23:11:11 +0100 Subject: Clipboard.c: print more debug details for reply --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 27aa49578..8844c88df 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -621,11 +621,11 @@ static void sendSelectionNotifyEventToClient(ClientPtr client, #ifdef DEBUG if (property == None) - fprintf(stderr, "%s: Denying request to client %s.\n", __func__, - nxagentClientInfoString(client)); + fprintf(stderr, "%s: Denying request to client %s - event time [%u].\n", __func__, + nxagentClientInfoString(client), time); else - fprintf(stderr, "%s: Sending event to client %s.\n", __func__, - nxagentClientInfoString(client)); + fprintf(stderr, "%s: Sending event to client %s - event time [%u].\n", __func__, + nxagentClientInfoString(client), time); #endif sendEventToClient(client, &x); -- cgit v1.2.3 From 124f5a5c6e4f37880c482d1037636ccfd7b6fca0 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 2 Mar 2021 23:12:03 +0100 Subject: Clipboard.c: sanity check for invalid resource --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 8844c88df..7fefd5ee1 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1592,6 +1592,14 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) int index = 0; + if (resource < 0) + { + #ifdef DEBUG + fprintf (stderr, "%s: resource [%d] is invalid.\n", __func__, resource); + #endif + return False; + } + /* determine the selection we are talking about here */ for (index = 0; index < nxagentMaxSelections; index++) { -- cgit v1.2.3 From 6fe8bf8fbaf955a4bffb98507a1ebeed00aff593 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 2 Mar 2021 23:14:48 +0100 Subject: Clipboard.c: always flush after XConvertSelection() call This ensures the convert will be sent out immediately. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 7fefd5ee1..d96a9946a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1272,6 +1272,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) X->xselectionrequest.target, serverTransToAgentProperty, serverWindow, lastClients[index].time); + NXFlushDisplay(nxagentDisplay, NXFlushLink); + #ifdef DEBUG fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%lx] time [%u] .\n", __func__, CurrentSelections[index].selection, NameForRemAtom(CurrentSelections[index].selection)), @@ -2839,6 +2841,9 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, XConvertSelection(nxagentDisplay, remSelection, remTarget, remProperty, serverWindow, CurrentTime); + + NXFlushDisplay(nxagentDisplay, NXFlushLink); + /* XConvertSelection will always return 1 (check the source!), so no need to check the return code. */ -- cgit v1.2.3 From 1723afb64696c41bdecdbe5c3330eb5e378c24ab Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 2 Mar 2021 23:11:44 +0100 Subject: Clipboard.c: improve comments --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index d96a9946a..17b14f728 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1517,7 +1517,7 @@ static void transferSelectionFromXServer(int index, int resource) fprintf(stderr, "%s: Getting property content from remote server.\n", __func__); #endif - /* get next free resouce index */ + /* get next free resource slot */ resource = NXGetCollectPropertyResource(nxagentDisplay); lastClients[index].resource = resource; @@ -1532,6 +1532,13 @@ static void transferSelectionFromXServer(int index, int resource) } else { + /* + * now initiate kind of an asynchronuos GetProperty() + * call. Once the property has been retrieved we will + * receive an NXCollectPropertyNotify event which will then + * be handled in + * nxagentCollectPropertyEventFromXServer(). + */ result = NXCollectProperty(nxagentDisplay, resource, serverWindow, -- cgit v1.2.3 From ba898dfcde038052c9eb9be043e9d48b18652cca Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 10 Mar 2021 10:04:50 +0100 Subject: Clipboard.c: improve debug output in special case This avoids an error message in a special case: nxagentRemoteToLocalAtom: WARNING failed to get name from remote atom. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 17b14f728..dde5506fa 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -436,7 +436,10 @@ void nxagentDumpClipboardStat(void) } fprintf(stderr, "\n"); - fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemAtom(serverLastRequestedSelection)); + if (serverLastRequestedSelection == -1) + fprintf(stderr, " serverLastRequestedSelection [-1](uninitialized)\n"); + else + fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemAtom(serverLastRequestedSelection)); fprintf(stderr, "Compile time settings\n"); #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG -- cgit v1.2.3 From 0631eece96650afb3715a5c5009005914f90a9b4 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 10 Mar 2021 10:06:29 +0100 Subject: Clipboard.c: add FIXMEs Also improve code to better match the situation described in the FIXME --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index dde5506fa..87473b221 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1670,11 +1670,16 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) * in the selection." * FIXME: this uses serverTransToAgentProperty which is shared between * all the selections. Could be a problem with simultaneous transfers. + * FIXME: NXGetCollectedProperty can return 0 and True. Some other + * functions in this field return False as well. Clean up that + * mess... */ - if (result != 0 && ulReturnBytesLeft == 0) + if (result == True && ulReturnBytesLeft == 0) { #ifdef DEBUG - fprintf (stderr, "%s: Retrieved property data - deleting it for ICCCM conformity.\n", __func__); + fprintf (stderr, "%s: Retrieved property data - deleting property [%ld][%s] " + "for ICCCM conformity.\n", __func__, serverTransToAgentProperty, + NameForRemAtom(serverTransToAgentProperty)); #endif XDeleteProperty(nxagentDisplay, serverWindow, serverTransToAgentProperty); } -- cgit v1.2.3 From bee3d3205655b5e624c1fd25816f078d0850c74c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 17 Mar 2021 22:44:35 +0100 Subject: NXEvents.c: improve debugging --- nx-X11/programs/Xserver/hw/nxagent/NXevents.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c index 50ecef09b..0249fc0a8 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c @@ -433,6 +433,9 @@ ProcSendEvent(ClientPtr client) if (stuff -> event.u.u.type == SelectionNotify) { + #ifdef DEBUG + fprintf(stderr, "%s: sending SelectionNotify to ourselves"\n, __func__); + #endif if (nxagentSendNotificationToSelfViaXServer(&stuff->event) == 1) return Success; } -- cgit v1.2.3 From 34e1413cda0c4475d9cfa45730eaf8e1cb843cb0 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 10 Jun 2021 20:54:27 +0200 Subject: Clipboard.c: improve some comments as requested by reviewer --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 200 +++++++++++++------------ 1 file changed, 104 insertions(+), 96 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 87473b221..49c10a947 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -60,7 +60,7 @@ #undef DEBUG /* - * define this to see the clipboard content in the debug output. As + * Define this to see the clipboard content in the debug output. As * this can lead to information leaking it must be activated * explicitly! */ @@ -106,7 +106,7 @@ typedef struct _SelectionOwner } SelectionOwner; /* - * this contains the last selection owner in nxagent. The + * This contains the last selection owner in nxagent. The * lastTimeChanged is always an internal time. If .client is NULL the * owner is outside nxagent. */ @@ -114,9 +114,9 @@ typedef struct _SelectionOwner static SelectionOwner *lastSelectionOwner = NULL; /* - * cache for targets the current selection owner + * Cache for targets the current selection owner * has to offer. We are storing the targets - * after they have been converted + * after they have been converted. */ typedef struct _Targets { @@ -234,7 +234,7 @@ static char szAgentUTF8_STRING[] = "UTF8_STRING"; static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; static char szAgentCLIPBOARD[] = "CLIPBOARD"; -/* number of milliseconds to wait for a conversion from the real X server. */ +/* Number of milliseconds to wait for a conversion from the real X server. */ #define CONVERSION_TIMEOUT 5000 /* @@ -244,7 +244,7 @@ static char szAgentCLIPBOARD[] = "CLIPBOARD"; #define ACCUM_TIME 5000 /* - * some helpers for debugging output + * Some helpers for debugging output */ static const char * getClientSelectionStageString(int stage) @@ -271,10 +271,11 @@ static const char * getClientSelectionStageString(int stage) #ifdef DEBUG /* - * see also nx-X11/lib/src/ErrDes.c + * See also nx-X11/lib/src/ErrDes.c * * We use our own version to avoid Xlib doing expensive calls. * FIXME: Must check if XGetErrorText() is really causing traffic over the wire. + * FIXME: move this to a Utils.c or similar */ const char * getXErrorString(int code) { @@ -550,7 +551,7 @@ int GetWindowProperty(WindowPtr pWin, Atom property, long longOffset, long longL /* * Send a SelectionNotify event to the real X server and do some error - * handling (in DEBUG mode) + * handling (in DEBUG mode). */ static Status sendSelectionNotifyEventToXServer(XSelectionEvent *event_to_send) { @@ -791,7 +792,7 @@ int nxagentFindCurrentSelectionIndex(Atom sel) * selection for the first nxagentMaxSelections selection atoms. */ - // for (int index = 0; index < NumCurrentSelections; index++) + /* for (int index = 0; index < NumCurrentSelections; index++) */ for (int index = 0; index < nxagentMaxSelections; index++) { if (CurrentSelections[index].selection == sel) @@ -834,7 +835,7 @@ void cacheTargetsForRem(int index, XlibAtom* targets, int numTargets) targetCache[index].numTargets = numTargets; } -/* this is called on init, reconnect and SelectionClear */ +/* This is called on init, reconnect and SelectionClear. */ void invalidateTargetCache(int index) { #ifdef DEBUG @@ -896,7 +897,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) { if (IS_INTERNAL_OWNER(index)) { - /* send a SelectionClear event to (our) previous owner */ + /* Send a SelectionClear event to (our) previous owner. */ xEvent x = {0}; x.u.u.type = SelectionClear; x.u.selectionClear.time = GetTimeInMillis(); @@ -907,9 +908,9 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) } /* - * set the root window with the NullClient as selection owner. Our + * Set the root window with the NullClient as selection owner. Our * clients asking for the owner via XGetSelectionOwner() will get - * these for an answer + * these for an answer. */ CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; CurrentSelections[index].client = NullClient; @@ -980,7 +981,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) return; } - /* the selection in this request is none we own. */ + /* The selection in this request is none we own. */ int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); if (index == -1) { @@ -996,7 +997,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: lastServers[%d].requestor [0x%lx].\n", __func__, index, lastServers[index].requestor); #endif - /* lastServers[index].requestor in non-NULL (= we are currently in the transfer phase) */ + /* lastServers[index].requestor is non-NULL (= we are currently in the transfer phase) */ if (lastServers[index].requestor != None) { #ifdef DEBUG @@ -1017,7 +1018,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) if (nxagentOption(TextClipboard)) { /* - * the selection request target is TARGETS. The requestor is + * The selection request target is TARGETS. The requestor is * asking for a list of supported data formats. * * The selection does not matter here, we will return this for @@ -1048,7 +1049,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) #endif /* - * pass on the requested list by setting the property provided + * Pass on the requested list by setting the property provided * by the requestor accordingly. */ XChangeProperty(nxagentDisplay, @@ -1198,8 +1199,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) #endif /* - * reaching this means the request is a normal, valid request. We - * can process it now. + * Reaching this line means the request is a normal, valid + * request. We can process it now. */ if (!nxagentOption(TextClipboard)) @@ -1207,7 +1208,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) /* Optimization: if we have a current target cache check if the * requested target is supported by the owner. If not we can take * a shortcut and deny the request immediately without doing any - * further communication */ + * further communication. */ if (targetCache[index].type == FORREM && targetCache[index].forRem) { XlibAtom *targets = targetCache[index].forRem; @@ -1237,9 +1238,9 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else { /* - * at this stage we know a remote client has asked for a selection - * target without having retrieved the list of supported targets - * first. + * At this stage we know a remote client has requested a + * selection target without having retrieved the list of + * supported targets first. */ #ifdef DEBUG if (X->xselectionrequest.target != serverTARGETS) @@ -1301,7 +1302,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } /* - * if one of our clients owns the selection we ask it to copy + * If one of our clients owns the selection we ask it to copy * the selection to the clientCutProperty on nxagent's root * window in the first step. We then later push that property's * content to the real X server. @@ -1309,15 +1310,15 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) if (IS_INTERNAL_OWNER(index)) { /* - * store who on the real X server requested the data and how - * and where it wants to have it + * Store who on the real X server requested the data and how + * and where it wants to have it. */ lastServers[index].property = X->xselectionrequest.property; lastServers[index].requestor = X->xselectionrequest.requestor; lastServers[index].target = X->xselectionrequest.target; lastServers[index].time = X->xselectionrequest.time; - /* prepare the request (like XConvertSelection, but internally) */ + /* Prepare the request (like XConvertSelection, but internally). */ xEvent x = {0}; x.u.u.type = SelectionRequest; x.u.selectionRequest.time = GetTimeInMillis(); @@ -1335,8 +1336,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) */ /* - * if textclipboard is requested simply use the previous clipboard - * handling code + * In TextClipboard mode simply use the previous clipboard + * handling code. */ if (nxagentOption(TextClipboard)) { @@ -1358,8 +1359,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } /* - * delete property before sending the request to the client - - * required by ICCCM + * Selete property before sending the request to the client as + * required by ICCCM. */ DeleteProperty(lastSelectionOwner[index].windowPtr, clientCutProperty); @@ -1374,8 +1375,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) x.u.selectionRequest.requestor, x.u.selectionRequest.selection, NameForIntAtom(x.u.selectionRequest.selection)); #endif - /* no reply to Xserver yet - we will do that once the answer of - the above sendEventToClient arrives */ + /* No reply to the Xserver yet - we will do that once the answer + of the above sendEventToClient arrives. */ } else { @@ -1391,11 +1392,12 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } /* - * end current selection transfer by sending a notification to the + * End the current selection transfer by sending a notification to the * client and resetting the corresponding variables and the state * machine. If success is False send a None reply, meaning "request - * denied/failed" - * Use SELECTION_SUCCESS and SELECTION_FAULT macros for success. + * denied/failed". + * Use SELECTION_SUCCESS and SELECTION_FAULT macros for the success + * value. */ static void endTransfer(int index, Bool success) { @@ -1462,7 +1464,7 @@ static void transferSelectionFromXServer(int index, int resource) * current implementation and go straight to the data. */ - /* get next free resource index */ + /* Get next free resource slot. */ int free_resource = NXGetCollectPropertyResource(nxagentDisplay); lastClients[index].resource = free_resource; @@ -1477,7 +1479,7 @@ static void transferSelectionFromXServer(int index, int resource) } else { - /* collect property and store with index "resource" */ + /* Collect the property and store ist with index "resource" d */ result = NXCollectProperty(nxagentDisplay, free_resource, serverWindow, @@ -1520,7 +1522,7 @@ static void transferSelectionFromXServer(int index, int resource) fprintf(stderr, "%s: Getting property content from remote server.\n", __func__); #endif - /* get next free resource slot */ + /* Get next free resource slot. */ resource = NXGetCollectPropertyResource(nxagentDisplay); lastClients[index].resource = resource; @@ -1536,7 +1538,7 @@ static void transferSelectionFromXServer(int index, int resource) else { /* - * now initiate kind of an asynchronuos GetProperty() + * Now initiate kind of an asynchronuos GetProperty() * call. Once the property has been retrieved we will * receive an NXCollectPropertyNotify event which will then * be handled in @@ -1566,7 +1568,7 @@ static void transferSelectionFromXServer(int index, int resource) setClientSelectionStage(index, SelectionStageWaitData); - /* we've seen situations where you had to move the mouse or press a + /* We've seen situations where you had to move the mouse or press a key to let the transfer complete. Flushing here fixed it */ NXFlushDisplay(nxagentDisplay, NXFlushLink); @@ -1588,7 +1590,7 @@ static void transferSelectionFromXServer(int index, int resource) /* Called from Events.c/nxagentHandleCollectPropertyEvent This event is generated after XChangeProperty(), XDeleteProperty() or - XGetWindowProperty(delete=True) + XGetWindowProperty(delete=True). Returncode: True: processed @@ -1612,7 +1614,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) return False; } - /* determine the selection we are talking about here */ + /* Determine the selection we are talking about here. */ for (index = 0; index < nxagentMaxSelections; index++) { /* @@ -1887,7 +1889,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) printClientSelectionStage(index); /* - * if the property is serverTransFromAgentProperty this means we are + * If the property is serverTransFromAgentProperty this means we are * transferring data FROM the agent TO the server. */ @@ -1965,7 +1967,8 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) { - /* if the last owner was an internal one, read the + /* + * If the last owner was an internal one, read the * clientCutProperty and push the contents to the * lastServers[index].requestor on the real X server. */ @@ -1979,7 +1982,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) unsigned long ulReturnBytesLeft; unsigned char *pszReturnData = NULL; - /* first get size values ... */ + /* First get size values ... */ int result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, 0, False, AnyPropertyType, &atomReturnType, &resultFormat, &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); @@ -1996,7 +1999,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) } else { - /* ... then use the size values for the actual request */ + /* ... then use the size values for the actual request data. */ result = GetWindowProperty(lastSelectionOwner[index].windowPtr, clientCutProperty, 0, ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, &resultFormat, &ulReturnItems, &ulReturnBytesLeft, @@ -2027,12 +2030,12 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) #ifdef WARNING fprintf(stderr, "%s: WARNING! Could not alloc memory for clipboard targets transmission.\n", __func__); #endif - /* this will effectively lead to the request being answered as failed */ + /* This will effectively lead to the request being answered as failed. */ lastServers[index].property = None; } else { - /* Convert the targets to remote atoms */ + /* Convert the targets to remote atoms. */ XlibAtom *addr = targets; unsigned int numTargets = ulReturnItems; @@ -2063,10 +2066,10 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) } else { - /* Fill the property on the requestor with the requested data */ + /* Fill the property on the requestor with the requested data. */ /* The XChangeProperty source code reveals it will always return 1, no matter what, so no need to check the result */ - /* FIXME: better use the format returned by above request */ + /* FIXME: better use the format returned by above request. */ XChangeProperty(nxagentDisplay, lastServers[index].requestor, lastServers[index].property, @@ -2105,7 +2108,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) } /* - * inform the initial requestor that the requested data has + * Inform the initial requestor that the requested data has * arrived in the desired property. If we have been unable to * get the data from the owner XChangeProperty will not have * been called and lastServers[index].property will be None which @@ -2165,7 +2168,7 @@ static void resetSelectionOwnerOnXServer(void) if (lastServers[index].requestor != None) { /* - * we are in the process of communicating back and forth between + * We are in the process of communicating back and forth between * real X server and nxagent's clients - let's not disturb. */ #if defined(TEST) || defined(DEBUG) @@ -2189,7 +2192,7 @@ static void resetSelectionOwnerOnXServer(void) setClientSelectionStage(index, SelectionStageNone); - /* Hmm, this is already None when reaching here */ + /* Hmm, this is already None when reaching here. */ lastServers[index].requestor = None; } } @@ -2251,7 +2254,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, } /* - * always invalidate the target cache for the relevant selection, + * Always invalidate the target cache for the relevant selection, * even if the trap is set. This ensures not having invalid data in * the cache. */ @@ -2302,7 +2305,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, /* * This is called from the nxagentSetSelectionCallback, so it is using - * internal Atoms + * internal Atoms. */ static void setSelectionOwnerOnXServer(Selection *pSelection) { @@ -2348,12 +2351,12 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) replyPendingRequestSelectionToXServer(index, False); - /* now we can go on */ + /* Now we can go on. */ } #endif /* - * inform the real X server that our serverWindow is the + * Inform the real X server that our serverWindow is the * clipboard owner. * https://www.freedesktop.org/wiki/ClipboardManager/ states * "In order to support peers who use the XFIXES extension to @@ -2374,9 +2377,9 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) setClientSelectionStage(index, SelectionStageNone); /* - * this will be repeated on reception of the SelectionOwner callback - * but we cannot be sure if there are any intermediate requests in the queue - * already so better do it here, too + * This will be repeated on reception of the SelectionOwner + * callback but we cannot be sure if there are any intermediate + * requests in the queue already so better do it here, too. */ invalidateTargetCache(index); @@ -2472,10 +2475,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } /* - * if lastClients[index].windowPtr is set we are waiting for an answer from - * the real X server. If that answer takes more than 5 seconds we - * consider the conversion failed and tell our client about that. - * The new request that lead us here is then processed. + * If lastClients[index].windowPtr is set we are waiting for an + * answer from the real X server. If that answer takes more than 5 + * seconds we consider the conversion failed and tell our client + * about that. The new request that lead us here is then processed. */ #ifdef TEST fprintf(stderr, "%s: lastClients[%d].windowPtr [0x%lx].\n", __func__, index, (unsigned long)lastClients[index].windowPtr); @@ -2498,15 +2501,15 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, "notifying failure to waiting client\n", __func__); #endif - /* notify the waiting client of failure */ + /* Notify the waiting client of the failure. */ endTransfer(index, SELECTION_FAULT); - /* do NOT return here but process the new request instead! */ + /* Do NOT return here but process the new request instead! */ } else { /* - * we got another convert request while already waiting for an + * We got another convert request while already waiting for an * answer from the real X server to a previous convert request * for this selection, which we cannot handle (yet). So return * an error for the new request. @@ -2517,7 +2520,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, __func__, nxagentClientInfoString(client)); #endif - /* notify the sender of the new request of failure */ + /* Notify the sender of the new request of the failure. */ sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); return 1; @@ -2614,7 +2617,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, } /* - * do nothing - TARGETS will be handled like any other target + * Do nothing - TARGETS will be handled like any other target * and passed on to the owner on the remote side. */ } @@ -2633,6 +2636,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, else if (target == clientTIMESTAMP) { /* + * From ICCCM: * "If the specified property is not None, the owner should place * the data resulting from converting the selection into the * specified property on the requestor window and should set the @@ -2699,7 +2703,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 1; } - /* in TextClipboard mode reject all non-text targets */ + /* In TextClipboard mode we reject all non-text targets. */ if (nxagentOption(TextClipboard)) { if (!isTextTarget(translateLocalToRemoteTarget(target))) @@ -2712,7 +2716,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); return 1; } - /* go on, target is acceptable */ + /* Go on, target is acceptable! */ } #ifdef DEBUG @@ -2722,10 +2726,12 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, if (!nxagentOption(TextClipboard)) { - /* Optimization: if we have a current target cache check if the + /* + * Optimization: if we have a current target cache check if the * requested target is supported by the owner. If not we can take * a shortcut and deny the request immediately without doing any - * further communication */ + * further communication + */ if (targetCache[index].type == FORINT && targetCache[index].forInt) { Atom *targets = targetCache[index].forInt; @@ -2755,7 +2761,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, else { /* - * at this stage we know a client has asked for a selection + * At this stage we know a client has asked for a selection * target without having retrieved the list of supported targets * first. */ @@ -2795,8 +2801,8 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, else { /* - * reset clientAccum as now another client requested the clipboard - * content + * Reset clientAccum as now another client requested the clipboard + * content. */ clientAccum = 0; } @@ -2804,8 +2810,9 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, setClientSelectionStage(index, SelectionStageNone); /* - * store the original requestor, we need that later after - * serverTransToAgentProperty contains the desired selection content + * Store the original requestor, we need that later after + * serverTransToAgentProperty has been filled with the desired + * selection content. */ lastClients[index].requestor = requestor; lastClients[index].windowPtr = pWin; @@ -2813,7 +2820,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, lastClients[index].time = time; lastClients[index].property = property; lastClients[index].target = target; - /* if the last client request time is more than 5s ago update it. Why? */ + /* If the last client request time is more than 5s ago update it. Why? */ if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) lastClients[index].reqTime = GetTimeInMillis(); @@ -2869,8 +2876,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 1; } -/* FIXME: do we still need this special treatment? Can't we just - call nxagentLocalToRemoteAtom() everywhere? */ +/* + * FIXME: do we still need this special treatment? Can't we just + * call nxagentLocalToRemoteAtom() everywhere? + */ XlibAtom translateLocalToRemoteSelection(Atom local) { /* @@ -3017,7 +3026,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) * communication happens completely between our own clients (some of * which can be nxagents themselves). In that case we return 0 (tell * dix to go on) and do nothing! - * Be sure to not let this trigger for the failure answer (property 0) + * Be sure to not let this trigger for the failure answer (property 0). */ if (!(event->u.selectionNotify.property == clientCutProperty || event->u.selectionNotify.property == 0) || lastServers[index].requestor == None) { @@ -3029,7 +3038,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) else { /* - * if the property is 0 (reporting failure) we can directly + * If the property is 0 (reporting failure) we can directly * answer to the lastServer about the failure! */ if (lastServers[index].requestor != None && event->u.selectionNotify.property == 0) @@ -3072,7 +3081,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) /* * This is called from NXproperty.c to determine if a client sets the * property we are waiting for. - * FIXME: in addition we should check if the client is the one we expect + * FIXME: in addition we should check if the client is the one we expect. */ WindowPtr nxagentGetClipboardWindow(Atom property) { @@ -3101,7 +3110,7 @@ WindowPtr nxagentGetClipboardWindow(Atom property) } /* - * Initialize the clipboard + * Initialize the clipboard. * Returns: True for success else False */ Bool nxagentInitClipboard(WindowPtr pWin) @@ -3122,8 +3131,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) if (!nxagentReconnectTrap) { - /* cannot move that down to others - we need it for - * initSelectionOwnerData ! */ + /* Cannot move that down to others - we need it for + * initSelectionOwnerData! */ /* FIXME: it is probably better to re-use the strings from Atoms.c here */ clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); #ifdef SUPPORT_TEXT_TARGET @@ -3191,8 +3200,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) } /* - * the clipboard selection atom might have changed on a new X - * server. Primary is constant. + * The clipboard selection atom can change with a new X + * server while Primary is constant. */ remSelAtoms[nxagentPrimarySelection] = XA_PRIMARY; remSelAtoms[nxagentClipboardSelection] = nxagentAtoms[10]; /* CLIPBOARD */ @@ -3216,7 +3225,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) /* * Server side properties to hold pasted data. - * see nxagentSendNotificationToSelfViaXServer for an explanation + * See nxagentSendNotificationToSelfViaXServer for an explanation */ serverTransFromAgentProperty = nxagentAtoms[15]; /* NX_SELTRANS_FROM_AGENT */ serverTransToAgentProperty = nxagentAtoms[5]; /* NX_CUT_BUFFER_SERVER */ @@ -3230,7 +3239,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) return False; } - /* this is probably to communicate with nomachine nxclient */ + /* This is probably to communicate with nomachine nxclient. */ #ifdef TEST fprintf(stderr, "%s: Setting owner of selection [%d][%s] to serverWindow [0x%lx]\n", __func__, (int) serverTransToAgentProperty, "NX_CUT_BUFFER_SERVER", serverWindow); @@ -3275,14 +3284,13 @@ Bool nxagentInitClipboard(WindowPtr pWin) if (nxagentSessionId[0]) { - // nxagentAtoms[10] is the CLIPBOARD atom #ifdef TEST fprintf(stderr, "%s: setting the ownership of %s to %lx" " and registering for PropertyChangeMask events\n", __func__, validateString(NameForRemAtom(nxagentAtoms[10])), serverWindow); #endif - XSetSelectionOwner(nxagentDisplay, nxagentAtoms[10], serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, nxagentAtoms[10], serverWindow, CurrentTime); // nxagentAtoms[10] is the CLIPBOARD atom pWin -> eventMask |= PropertyChangeMask; nxagentChangeWindowAttributes(pWin, CWEventMask); } @@ -3297,7 +3305,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) for (int index = 0; index < nxagentMaxSelections; index++) { /* - * if we have a selection inform the (new) real Xserver and + * If we have a selection inform the (new) real Xserver and * claim the ownership. Note that we report our serverWindow as * owner, not the real window! */ @@ -3309,7 +3317,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) /* * On reconnect there cannot be any external requestor - * waiting for a reply so clean this + * waiting for a reply so clean this. */ lastServers[index].requestor = None; -- cgit v1.2.3 From 535104db2709504bf54766cefe172bc2e306f325 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 10 Jun 2021 20:55:14 +0200 Subject: Clipboard.c: use NXAGENT_ONSTART macro on one more location --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 49c10a947..68ad68345 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -3239,6 +3239,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) return False; } +#ifdef NXAGENT_ONSTART /* This is probably to communicate with nomachine nxclient. */ #ifdef TEST fprintf(stderr, "%s: Setting owner of selection [%d][%s] to serverWindow [0x%lx]\n", __func__, @@ -3246,6 +3247,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) #endif XSetSelectionOwner(nxagentDisplay, serverTransToAgentProperty, serverWindow, CurrentTime); +#endif if (XQueryExtension(nxagentDisplay, "XFIXES", -- cgit v1.2.3 From 55af71edcf66556869f5f2b8c843818874399551 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 10 Jun 2021 23:01:37 +0200 Subject: Clipboard.c: harmonize naming regarding internal/local Use "local" everywhere instead of a mixture of "local" and "internal". Also replace abbreviations "rem" and "int" by "remote" and "local" because they are confusing readers. --- nx-X11/programs/Xserver/hw/nxagent/Atoms.h | 4 +- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 320 ++++++++++++------------- 2 files changed, 162 insertions(+), 162 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h index 4a73a817d..a9f730d76 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h @@ -86,8 +86,8 @@ const char *nxagentRemoteAtomToString(XlibAtom remote); /* * supply two macros that also validate the output. */ -#define NameForIntAtom(_atom) validateString(NameForAtom(_atom)) -#define NameForRemAtom(_xlibatom) validateString(nxagentRemoteAtomToString(_xlibatom)) +#define NameForLocalAtom(_atom) validateString(NameForAtom(_atom)) +#define NameForRemoteAtom(_xlibatom) validateString(nxagentRemoteAtomToString(_xlibatom)) #endif /* XlibAtom */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 68ad68345..3a210ac5f 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -94,20 +94,20 @@ const int nxagentClipboardSelection = 1; const int nxagentMaxSelections = 2; /* store the remote atom for all selections */ -static XlibAtom *remSelAtoms = NULL; -static Atom *intSelAtoms = NULL; +static XlibAtom *remoteSelectionAtoms = NULL; +static Atom *localSelelectionAtoms = NULL; typedef struct _SelectionOwner { - ClientPtr client; /* internal client */ - Window window; /* internal window id */ - WindowPtr windowPtr; /* internal window struct */ - Time lastTimeChanged; /* internal time */ + ClientPtr client; /* local client */ + Window window; /* local window id */ + WindowPtr windowPtr; /* local window struct */ + Time lastTimeChanged; /* local time (server time) */ } SelectionOwner; /* * This contains the last selection owner in nxagent. The - * lastTimeChanged is always an internal time. If .client is NULL the + * lastTimeChanged is always a local time. If .client is NULL the * owner is outside nxagent. */ @@ -120,22 +120,22 @@ static SelectionOwner *lastSelectionOwner = NULL; */ typedef struct _Targets { - Bool type; /* EMPTY, FORINT, FORREM */ + Bool type; /* EMPTY, FOR_LOCAL, FOR_REMOTE */ unsigned int numTargets; - Atom *forInt; /* Atoms converted for internal -> type Atom, not XlibAtom */ - XlibAtom *forRem; /* Atoms converted for remote -> type XlibAtom, not Atom */ + Atom *forLocal; /* Atoms converted for local -> type Atom, not XlibAtom */ + XlibAtom *forRemote; /* Atoms converted for remote -> type XlibAtom, not Atom */ } Targets; #define EMPTY 0 -#define FORREM 1 -#define FORINT 2 +#define FOR_REMOTE 1 +#define FOR_LOCAL 2 static Targets *targetCache = NULL; /* FIXME: can this also be stored per selection? */ static XlibAtom serverLastRequestedSelection = -1; -#define IS_INTERNAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NullClient) +#define IS_LOCAL_OWNER(lsoindex) (lastSelectionOwner[lsoindex].client != NullClient) typedef enum { @@ -357,10 +357,10 @@ static void printSelectionStat(int index) fprintf(stderr, "selection [%d]:\n", index); - fprintf(stderr, " selection Atom internal [%d][%s] remote [%ld][%s]\n", - intSelAtoms[index], NameForIntAtom(intSelAtoms[index]), - remSelAtoms[index], NameForRemAtom(remSelAtoms[index])); - fprintf(stderr, " owner side %s\n", IS_INTERNAL_OWNER(index) ? "nxagent" : "real X server/none"); + fprintf(stderr, " selection Atom local [%d][%s] remote [%ld][%s]\n", + localSelelectionAtoms[index], NameForLocalAtom(localSelelectionAtoms[index]), + remoteSelectionAtoms[index], NameForRemoteAtom(remoteSelectionAtoms[index])); + fprintf(stderr, " owner side %s\n", IS_LOCAL_OWNER(index) ? "nxagent" : "real X server/none"); fprintf(stderr, " lastSelectionOwner[].client %s\n", nxagentClientInfoString(lOwner.client)); fprintf(stderr, " lastSelectionOwner[].window [0x%x]\n", lOwner.window); if (lOwner.windowPtr) @@ -383,8 +383,8 @@ static void printLastClientStat(int index) fprintf(stderr, " lastClients[].windowPtr (WindowPtr) -\n"); fprintf(stderr, " lastClients[].clientPtr (ClientPtr) %s\n", nxagentClientInfoString(lc.clientPtr)); fprintf(stderr, " lastClients[].requestor (Window) [0x%x]\n", lc.requestor); - fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForIntAtom(lc.property)); - fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForIntAtom(lc.target)); + fprintf(stderr, " lastClients[].property (Atom) [% 4d][%s]\n", lc.property, NameForLocalAtom(lc.property)); + fprintf(stderr, " lastClients[].target (Atom) [% 4d][%s]\n", lc.target, NameForLocalAtom(lc.target)); if (lc.time > 0) fprintf(stderr, " lastClients[].time (Time) [%u] ([%u]ms ago)\n", lc.time, GetTimeInMillis() - lc.time); else @@ -402,16 +402,16 @@ static void printLastServerStat(int index) { lastServer ls = lastServers[index]; fprintf(stderr, " lastServer[].requestor (XlibWindow) [0x%lx]\n", ls.requestor); - fprintf(stderr, " lastServer[].property (XlibAtom) [% 4ld][%s]\n", ls.property, NameForRemAtom(ls.property)); - fprintf(stderr, " lastServer[].target (XlibAtom) [% 4ld][%s]\n", ls.target, NameForRemAtom(ls.target)); + fprintf(stderr, " lastServer[].property (XlibAtom) [% 4ld][%s]\n", ls.property, NameForRemoteAtom(ls.property)); + fprintf(stderr, " lastServer[].target (XlibAtom) [% 4ld][%s]\n", ls.target, NameForRemoteAtom(ls.target)); fprintf(stderr, " lastServer[].time (Time) [%u]\n", ls.time); } static void printTargetCacheStat(int index) { fprintf(stderr, " targetCache[].type (int) [%d]\n", targetCache[index].type); - fprintf(stderr, " targetCache[].forInt (Atom *) [%p]\n", (void *)targetCache[index].forInt); - fprintf(stderr, " targetCache[].forRem (XlibAtom *) [%p]\n", (void *)targetCache[index].forRem); + fprintf(stderr, " targetCache[].forLocal (Atom *) [%p]\n", (void *)targetCache[index].forLocal); + fprintf(stderr, " targetCache[].forRemote (XlibAtom *) [%p]\n", (void *)targetCache[index].forRemote); fprintf(stderr, " targetCache[].numTargets (int) [%d]\n", targetCache[index].numTargets); } @@ -440,7 +440,7 @@ void nxagentDumpClipboardStat(void) if (serverLastRequestedSelection == -1) fprintf(stderr, " serverLastRequestedSelection [-1](uninitialized)\n"); else - fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemAtom(serverLastRequestedSelection)); + fprintf(stderr, " serverLastRequestedSelection [% 4ld][%s]\n", serverLastRequestedSelection, NameForRemoteAtom(serverLastRequestedSelection)); fprintf(stderr, "Compile time settings\n"); #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG @@ -464,33 +464,33 @@ void nxagentDumpClipboardStat(void) XlibAtom sv = 0; int len = WIDTH; - fprintf(stderr, "Atoms internal%*sremote\n", WIDTH - 8, ""); - cl = clientTARGETS; sv = serverTARGETS; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); - fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); + fprintf(stderr, "Atoms local%*sremote\n", WIDTH - 5, ""); + cl = clientTARGETS; sv = serverTARGETS; len = (int)(WIDTH - 9 - strlen(NameForLocalAtom(cl))); + fprintf(stderr, " TARGETS [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForLocalAtom(cl), len, "", sv, NameForRemoteAtom(sv)); - cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); - fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); + cl = clientTIMESTAMP; sv = serverTIMESTAMP; len = (int)(WIDTH - 9 - strlen(NameForLocalAtom(cl))); + fprintf(stderr, " TIMESTAMP [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForLocalAtom(cl), len, "", sv, NameForRemoteAtom(sv)); #ifdef SUPPORT_TEXT_TARGET - cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); - fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); + cl = clientTEXT; sv = serverTEXT; len = (int)(WIDTH - 9 - strlen(NameForLocalAtom(cl))); + fprintf(stderr, " TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForLocalAtom(cl), len, "", sv, NameForRemoteAtom(sv)); #endif #ifdef SUPPORT_COMPOUND_TEXT_TARGET - cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); - fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); + cl = clientCOMPOUND_TEXT; sv = serverCOMPOUND_TEXT; len = (int)(WIDTH - 9 - strlen(NameForLocalAtom(cl))); + fprintf(stderr, " COMPOUND_TEXT [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForLocalAtom(cl), len, "", sv, NameForRemoteAtom(sv)); #endif - cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); - fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForIntAtom(cl), len, "", sv, NameForRemAtom(sv)); + cl = clientUTF8_STRING; sv = serverUTF8_STRING; len = (int)(WIDTH - 9 - strlen(NameForLocalAtom(cl))); + fprintf(stderr, " UTF8_STRING [% 4d][%s]%*s [% 4ld][%s]\n", cl, NameForLocalAtom(cl), len, "", sv, NameForRemoteAtom(sv)); sv = serverTransToAgentProperty; - fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, NameForRemAtom(sv)); + fprintf(stderr, " serverTransToAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, NameForRemoteAtom(sv)); sv = serverTransFromAgentProperty; - fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, NameForRemAtom(sv)); + fprintf(stderr, " serverTransFromAgentProperty - %*s[% 4ld][%s]\n", WIDTH - 2, "", sv, NameForRemoteAtom(sv)); - cl = clientCutProperty; len = (int)(WIDTH - 9 - strlen(NameForIntAtom(cl))); - fprintf(stderr, " clientCutProperty [% 4d][%s]%*s\n", cl, NameForIntAtom(cl), len + 2, "-" ); + cl = clientCutProperty; len = (int)(WIDTH - 9 - strlen(NameForLocalAtom(cl))); + fprintf(stderr, " clientCutProperty [% 4d][%s]%*s\n", cl, NameForLocalAtom(cl), len + 2, "-" ); for (int index = 0; index < nxagentMaxSelections; index++) { @@ -758,23 +758,23 @@ int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) { for (int index = 0; index < nxagentMaxSelections; index++) { - if (remSelAtoms[index] == sel) + if (remoteSelectionAtoms[index] == sel) { #ifdef DEBUG - fprintf(stderr, "%s: remote selection [%ld][%s] belongs to index [%d]\n", __func__, sel, NameForRemAtom(sel), index); + fprintf(stderr, "%s: remote selection [%ld][%s] belongs to index [%d]\n", __func__, sel, NameForRemoteAtom(sel), index); #endif return index; } } #ifdef DEBUG - fprintf(stderr, "%s: remote selection [%ld][%s] does not belong to any index!\n", __func__, sel, NameForRemAtom(sel)); + fprintf(stderr, "%s: remote selection [%ld][%s] does not belong to any index!\n", __func__, sel, NameForRemoteAtom(sel)); #endif return -1; } /* * Find the index of CurrentSelection with the selection - * sel. sel is an internal atom. If the index cannot be + * sel. sel is a local atom. If the index cannot be * determined it will return -1. */ int nxagentFindCurrentSelectionIndex(Atom sel) @@ -798,40 +798,40 @@ int nxagentFindCurrentSelectionIndex(Atom sel) if (CurrentSelections[index].selection == sel) { #ifdef DEBUG - fprintf(stderr, "%s: selection [%d][%s] belongs to index [%d]\n", __func__, sel, NameForIntAtom(sel), index); + fprintf(stderr, "%s: selection [%d][%s] belongs to index [%d]\n", __func__, sel, NameForLocalAtom(sel), index); #endif return index; } } #ifdef DEBUG - fprintf(stderr, "%s: selection [%d][%s] does not belong to any index!\n", __func__, sel, NameForIntAtom(sel)); + fprintf(stderr, "%s: selection [%d][%s] does not belong to any index!\n", __func__, sel, NameForLocalAtom(sel)); #endif return -1; } -void cacheTargetsForInt(int index, Atom* targets, int numTargets) +void cacheTargetsForLocal(int index, Atom* targets, int numTargets) { #ifdef DEBUG - fprintf(stderr, "%s: caching [%d] targets for internal requests\n", __func__, numTargets); + fprintf(stderr, "%s: caching [%d] targets for local requests\n", __func__, numTargets); #endif - SAFE_free(targetCache[index].forInt); - SAFE_free(targetCache[index].forRem); - targetCache[index].type = FORINT; - targetCache[index].forInt = targets; + SAFE_free(targetCache[index].forLocal); + SAFE_free(targetCache[index].forRemote); + targetCache[index].type = FOR_LOCAL; + targetCache[index].forLocal = targets; targetCache[index].numTargets = numTargets; } -void cacheTargetsForRem(int index, XlibAtom* targets, int numTargets) +void cacheTargetsForRemote(int index, XlibAtom* targets, int numTargets) { #ifdef DEBUG fprintf(stderr, "%s: caching [%d] targets for remote requests\n", __func__, numTargets); #endif - SAFE_free(targetCache[index].forInt); - SAFE_free(targetCache[index].forRem); - targetCache[index].type = FORREM; - targetCache[index].forRem = targets; + SAFE_free(targetCache[index].forLocal); + SAFE_free(targetCache[index].forRemote); + targetCache[index].type = FOR_REMOTE; + targetCache[index].forRemote = targets; targetCache[index].numTargets = numTargets; } @@ -842,8 +842,8 @@ void invalidateTargetCache(int index) fprintf(stderr, "%s: invalidating target cache [%d]\n", __func__, index); #endif - SAFE_free(targetCache[index].forInt); - SAFE_free(targetCache[index].forRem); + SAFE_free(targetCache[index].forLocal); + SAFE_free(targetCache[index].forRemote); targetCache[index].type = EMPTY; targetCache[index].numTargets = 0; } @@ -856,8 +856,8 @@ void invalidateTargetCaches(void) for (int index = 0; index < nxagentMaxSelections; index++) { - SAFE_free(targetCache[index].forInt); - SAFE_free(targetCache[index].forRem); + SAFE_free(targetCache[index].forLocal); + SAFE_free(targetCache[index].forRemote); targetCache[index].type = EMPTY; targetCache[index].numTargets = 0; } @@ -872,7 +872,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) { #ifdef DEBUG fprintf(stderr, "---------\n%s: SelectionClear event for selection [%lu][%s] window [0x%lx] time [%lu].\n", - __func__, X->xselectionclear.selection, NameForRemAtom(X->xselectionclear.selection), + __func__, X->xselectionclear.selection, NameForRemoteAtom(X->xselectionclear.selection), X->xselectionclear.window, X->xselectionclear.time); #endif @@ -895,7 +895,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) int index = nxagentFindLastSelectionOwnerIndex(X->xselectionclear.selection); if (index != -1) { - if (IS_INTERNAL_OWNER(index)) + if (IS_LOCAL_OWNER(index)) { /* Send a SelectionClear event to (our) previous owner. */ xEvent x = {0}; @@ -962,10 +962,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "---------\n%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s] time [%lu]\n", __func__, - X->xselectionrequest.selection, NameForRemAtom(X->xselectionrequest.selection), - X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), + X->xselectionrequest.selection, NameForRemoteAtom(X->xselectionrequest.selection), + X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target), DisplayString(nxagentDisplay), X->xselectionrequest.requestor, - X->xselectionrequest.property, NameForRemAtom(X->xselectionrequest.property), + X->xselectionrequest.property, NameForRemoteAtom(X->xselectionrequest.property), X->xselectionrequest.time); if (X->xselectionrequest.requestor == serverWindow) { @@ -1044,7 +1044,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) { - fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); + fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemoteAtom(targets[i])); } #endif @@ -1074,16 +1074,16 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * occured we can answer with the cached list of targets. */ - if (targetCache[index].type == FORREM && targetCache[index].forRem) + if (targetCache[index].type == FOR_REMOTE && targetCache[index].forRemote) { - XlibAtom *targets = targetCache[index].forRem; + XlibAtom *targets = targetCache[index].forRemote; unsigned int numTargets = targetCache[index].numTargets; #ifdef DEBUG fprintf(stderr, "%s: Sending %d cached targets to remote requestor:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) { - fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i])); + fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemoteAtom(targets[i])); } #endif @@ -1183,7 +1183,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) { #ifdef DEBUG fprintf(stderr, "%s: denying request for non-text target [%ld][%s].\n", __func__, - X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target)); + X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target)); #endif replyRequestSelectionToXServer(X, False); @@ -1195,7 +1195,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) #ifdef DEBUG fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, - NameForRemAtom(X->xselectionrequest.target)); + NameForRemoteAtom(X->xselectionrequest.target)); #endif /* @@ -1209,9 +1209,9 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * requested target is supported by the owner. If not we can take * a shortcut and deny the request immediately without doing any * further communication. */ - if (targetCache[index].type == FORREM && targetCache[index].forRem) + if (targetCache[index].type == FOR_REMOTE && targetCache[index].forRemote) { - XlibAtom *targets = targetCache[index].forRem; + XlibAtom *targets = targetCache[index].forRemote; #ifdef DEBUG fprintf(stderr, "%s: Checking target validity\n", __func__); @@ -1229,7 +1229,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) { #ifdef DEBUG fprintf(stderr, "%s: target [%ld][%s] is not supported by the owner - denying request.\n", - __func__, X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target)); + __func__, X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target)); #endif replyRequestSelectionToXServer(X, False); return; @@ -1258,7 +1258,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) serverLastRequestedSelection = X->xselectionrequest.selection; #if 0 - if (lastClients[index].windowPtr != NULL && IS_INTERNAL_OWNER(index)) + if (lastClients[index].windowPtr != NULL && IS_LOCAL_OWNER(index)) { /* * Request the real X server to transfer the selection content @@ -1280,9 +1280,9 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) #ifdef DEBUG fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%lx] time [%u] .\n", __func__, - CurrentSelections[index].selection, NameForRemAtom(CurrentSelections[index].selection)), - X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target), - serverTransToAgentProperty, NameForRemAtom(serverTransToAgentProperty), + CurrentSelections[index].selection, NameForRemoteAtom(CurrentSelections[index].selection)), + X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target), + serverTransToAgentProperty, NameForRemoteAtom(serverTransToAgentProperty), serverWindow, lastClients[index].time); #endif } @@ -1307,7 +1307,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * window in the first step. We then later push that property's * content to the real X server. */ - if (IS_INTERNAL_OWNER(index)) + if (IS_LOCAL_OWNER(index)) { /* * Store who on the real X server requested the data and how @@ -1318,7 +1318,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) lastServers[index].target = X->xselectionrequest.target; lastServers[index].time = X->xselectionrequest.time; - /* Prepare the request (like XConvertSelection, but internally). */ + /* Prepare the request (like XConvertSelection, but locally). */ xEvent x = {0}; x.u.u.type = SelectionRequest; x.u.selectionRequest.time = GetTimeInMillis(); @@ -1370,10 +1370,10 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s] " \ "target [%d][%s] requestor [0x%x] selection [%d][%s].\n", __func__, nxagentClientInfoString(lastSelectionOwner[index].client), - x.u.selectionRequest.property, NameForIntAtom(x.u.selectionRequest.property), - x.u.selectionRequest.target, NameForIntAtom(x.u.selectionRequest.target), + x.u.selectionRequest.property, NameForLocalAtom(x.u.selectionRequest.property), + x.u.selectionRequest.target, NameForLocalAtom(x.u.selectionRequest.target), x.u.selectionRequest.requestor, - x.u.selectionRequest.selection, NameForIntAtom(x.u.selectionRequest.selection)); + x.u.selectionRequest.selection, NameForLocalAtom(x.u.selectionRequest.selection)); #endif /* No reply to the Xserver yet - we will do that once the answer of the above sendEventToClient arrives. */ @@ -1381,8 +1381,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) else { #ifdef DEBUG - fprintf(stderr, "%s: no internal owner for selection [%ld][%s] - denying request.\n", __func__, - X->xselectionrequest.selection, NameForRemAtom(X->xselectionrequest.selection)); + fprintf(stderr, "%s: no local owner for selection [%ld][%s] - denying request.\n", __func__, + X->xselectionrequest.selection, NameForRemoteAtom(X->xselectionrequest.selection)); #endif /* deny the request */ @@ -1412,7 +1412,7 @@ static void endTransfer(int index, Bool success) #ifdef DEBUG if (success == SELECTION_SUCCESS) fprintf(stderr, "%s: sending notification to client %s, property [%d][%s]\n", __func__, - nxagentClientInfoString(lastClients[index].clientPtr), lastClients[index].property, NameForIntAtom(lastClients[index].property)); + nxagentClientInfoString(lastClients[index].clientPtr), lastClients[index].property, NameForLocalAtom(lastClients[index].property)); else fprintf(stderr, "%s: sending negative notification to client %s\n", __func__, nxagentClientInfoString(lastClients[index].clientPtr)); @@ -1421,7 +1421,7 @@ static void endTransfer(int index, Bool success) sendSelectionNotifyEventToClient(lastClients[index].clientPtr, lastClients[index].time, lastClients[index].requestor, - intSelAtoms[index], + localSelelectionAtoms[index], lastClients[index].target, success == SELECTION_SUCCESS ? lastClients[index].property : None); } @@ -1681,7 +1681,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) #ifdef DEBUG fprintf (stderr, "%s: Retrieved property data - deleting property [%ld][%s] " "for ICCCM conformity.\n", __func__, serverTransToAgentProperty, - NameForRemAtom(serverTransToAgentProperty)); + NameForRemoteAtom(serverTransToAgentProperty)); #endif XDeleteProperty(nxagentDisplay, serverWindow, serverTransToAgentProperty); } @@ -1787,7 +1787,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) #ifdef DEBUG fprintf(stderr, "%s: converting atom: remote [%u][%s] -> local [%u][%s]\n", __func__, - (unsigned int)remote, NameForRemAtom(remote), local, NameForIntAtom(local)); + (unsigned int)remote, NameForRemoteAtom(remote), local, NameForLocalAtom(local)); #endif } ChangeWindowProperty(lastClients[index].windowPtr, @@ -1796,7 +1796,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) 32, PropModeReplace, ulReturnItems, (unsigned char*)targets, 1); - cacheTargetsForInt(index, targets, numTargets); + cacheTargetsForLocal(index, targets, numTargets); endTransfer(index, SELECTION_SUCCESS); } @@ -1816,7 +1816,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) #endif "\n", __func__, lastClients[index].property, - validateString(NameForIntAtom(lastClients[index].property)) + validateString(NameForLocalAtom(lastClients[index].property)) #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG ,(int)(min(20, ulReturnItems * resultFormat / 8)), (int)(min(20, ulReturnItems * resultFormat / 8)), @@ -1865,9 +1865,9 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) #ifdef DEBUG fprintf(stderr, "---------\n%s: Received SelectionNotify event from real X server, property " \ "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", - __func__, e->property, NameForRemAtom(e->property), e->requestor, - NameForRemAtom(e->selection), e->target, - NameForRemAtom(e->target), e->time, e->send_event); + __func__, e->property, NameForRemoteAtom(e->property), e->requestor, + NameForRemoteAtom(e->selection), e->target, + NameForRemoteAtom(e->target), e->time, e->send_event); /* this has not been SENT by nxagent but is the answer to a request of nxagent */ if (e->requestor == serverWindow) @@ -1944,7 +1944,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) { #ifdef DEBUG fprintf(stderr, "%s: Unexpected property [%ld][%s] - reporting conversion failure.\n", - __func__, X->xselection.property, NameForRemAtom(X->xselection.property)); + __func__, X->xselection.property, NameForRemoteAtom(X->xselection.property)); #endif endTransfer(index, SELECTION_FAULT); } @@ -1968,11 +1968,11 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) { /* - * If the last owner was an internal one, read the + * If the last owner was a local one, read the * clientCutProperty and push the contents to the * lastServers[index].requestor on the real X server. */ - if (IS_INTERNAL_OWNER(index) && + if (IS_LOCAL_OWNER(index) && lastSelectionOwner[index].windowPtr != NULL && property == serverTransFromAgentProperty) { @@ -1989,7 +1989,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) #ifdef DEBUG fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, - lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), + lastSelectionOwner[index].window, clientCutProperty, NameForLocalAtom(clientCutProperty), getXErrorString(result)); #endif if (result == BadAlloc || result == BadAtom || @@ -2006,7 +2006,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) &pszReturnData); #ifdef DEBUG fprintf(stderr, "%s: GetWindowProperty() window [0x%x] property [%d][%s] returned [%s]\n", __func__, - lastSelectionOwner[index].window, clientCutProperty, NameForIntAtom(clientCutProperty), + lastSelectionOwner[index].window, clientCutProperty, NameForLocalAtom(clientCutProperty), getXErrorString(result)); #endif @@ -2047,7 +2047,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) #ifdef DEBUG fprintf(stderr, "%s: converting atom: local [%d][%s] -> remote [%ld][%s]\n", __func__, - local, NameForIntAtom(local), remote, NameForRemAtom(remote)); + local, NameForLocalAtom(local), remote, NameForRemoteAtom(remote)); #endif } @@ -2061,7 +2061,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) (unsigned char*)targets, numTargets); - cacheTargetsForRem(index, targets, numTargets); + cacheTargetsForRemote(index, targets, numTargets); } } else @@ -2088,7 +2088,7 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) __func__, lastServers[index].requestor, lastServers[index].property, - NameForRemAtom(lastServers[index].property), + NameForRemoteAtom(lastServers[index].property), (int)ulReturnItems * 8 / 8 #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG ,(int)(min(20, ulReturnItems * 8 / 8)), @@ -2136,7 +2136,7 @@ void replyPendingRequestSelectionToXServer(int index, Bool success) { XSelectionEvent eventSelection = { .requestor = lastServers[index].requestor, - .selection = remSelAtoms[index], + .selection = remoteSelectionAtoms[index], .target = lastServers[index].target, .time = lastServers[index].time, .property = success ? lastServers[index].property : None, @@ -2182,7 +2182,7 @@ static void resetSelectionOwnerOnXServer(void) for (int index = 0; index < nxagentMaxSelections; index++) { - XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], serverWindow, CurrentTime); #ifdef DEBUG fprintf(stderr, "%s: Reset selection state for selection [%d].\n", __func__, index); @@ -2248,7 +2248,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, if (index == -1) { #ifdef DEBUG - fprintf(stderr, "%s: selection [%s] will not be handled by the clipboard code\n", __func__, NameForIntAtom(pCurSel->selection)); + fprintf(stderr, "%s: selection [%s] will not be handled by the clipboard code\n", __func__, NameForLocalAtom(pCurSel->selection)); #endif return; } @@ -2277,13 +2277,13 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, { #ifdef DEBUG fprintf(stderr, "%s: pCurSel->pWin [0x%x]\n", __func__, WINDOWID(pCurSel->pWin)); - fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForIntAtom(pCurSel->selection)); + fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForLocalAtom(pCurSel->selection)); #endif if (pCurSel->pWin != NULL && nxagentOption(Clipboard) != ClipboardNone && /* FIXME: shouldn't we also check for != ClipboardClient? */ - (pCurSel->selection == intSelAtoms[nxagentPrimarySelection] || - pCurSel->selection == intSelAtoms[nxagentClipboardSelection])) + (pCurSel->selection == localSelelectionAtoms[nxagentPrimarySelection] || + pCurSel->selection == localSelelectionAtoms[nxagentClipboardSelection])) { #ifdef DEBUG fprintf(stderr, "%s: calling setSelectionOwnerOnXServer\n", __func__); @@ -2305,7 +2305,7 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, /* * This is called from the nxagentSetSelectionCallback, so it is using - * internal Atoms. + * local Atoms. */ static void setSelectionOwnerOnXServer(Selection *pSelection) { @@ -2364,7 +2364,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * reacquire the clipboard whenever the content or metadata (e.g * the list of supported targets) changes." */ - XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); + XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], serverWindow, CurrentTime); /* * The real owner window (inside nxagent) is stored in @@ -2413,7 +2413,7 @@ FIXME2: instead of XGetSelectionOwner we could check if the Xfixes /* * This is called from dix (ProcConvertSelection) if an nxagent client - * issues a ConvertSelection request. So all the Atoms are internal. + * issues a ConvertSelection request. So all the Atoms are local. * return codes: * 0: let dix process the request * 1: don't let dix process the request @@ -2424,12 +2424,12 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #ifdef DEBUG fprintf(stderr, "---------\n%s: client %s requests sel [%s] " "on window [0x%x] prop [%d][%s] target [%d][%s] time [%u].\n", __func__, - nxagentClientInfoString(client), NameForIntAtom(selection), requestor, - property, NameForIntAtom(property), - target, NameForIntAtom(target), time); + nxagentClientInfoString(client), NameForLocalAtom(selection), requestor, + property, NameForLocalAtom(property), + target, NameForLocalAtom(target), time); #endif - /* We cannot use NameForIntAtom() here! FIXME: Why not? */ + /* We cannot use NameForLocalAtom() here! FIXME: Why not? */ if (NameForAtom(target) == NULL) { #ifdef DEBUG @@ -2463,13 +2463,13 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, return 0; } - if (IS_INTERNAL_OWNER(index)) + if (IS_LOCAL_OWNER(index)) { /* * There is a client owner on the agent side, let normal dix stuff happen. */ #ifdef DEBUG - fprintf(stderr, "%s: clipboard is owned by internal client - let dix process the request\n", __func__); + fprintf(stderr, "%s: clipboard is owned by local client - let dix process the request\n", __func__); #endif return 0; } @@ -2491,7 +2491,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif #ifdef DEBUG - fprintf(stderr, "%s: intSelAtoms[%d] [%d] - selection [%d]\n", __func__, index, intSelAtoms[index], selection); + fprintf(stderr, "%s: localSelelectionAtoms[%d] [%d] - selection [%d]\n", __func__, index, localSelelectionAtoms[index], selection); #endif if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) @@ -2560,7 +2560,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) { - fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForIntAtom(targets[i])); + fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForLocalAtom(targets[i])); } #endif @@ -2588,16 +2588,16 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * occured we can answer with the cached list of targets. */ - if (targetCache[index].type == FORINT && targetCache[index].forInt) + if (targetCache[index].type == FOR_LOCAL && targetCache[index].forLocal) { - Atom *targets = targetCache[index].forInt; + Atom *targets = targetCache[index].forLocal; int numTargets = targetCache[index].numTargets; #ifdef DEBUG - fprintf(stderr, "%s: Sending %d cached targets to internal client:\n", __func__, numTargets); + fprintf(stderr, "%s: Sending %d cached targets to local client:\n", __func__, numTargets); for (int i = 0; i < numTargets; i++) { - fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForIntAtom(targets[i])); + fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForLocalAtom(targets[i])); } #endif @@ -2710,7 +2710,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, { #ifdef DEBUG fprintf(stderr, "%s: denying request for non-text target [%d][%s].\n", __func__, - target, NameForIntAtom(target)); + target, NameForLocalAtom(target)); #endif sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); @@ -2721,7 +2721,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #ifdef DEBUG fprintf(stderr, "%s: target [%d][%s].\n", __func__, target, - NameForIntAtom(target)); + NameForLocalAtom(target)); #endif if (!nxagentOption(TextClipboard)) @@ -2732,9 +2732,9 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * a shortcut and deny the request immediately without doing any * further communication */ - if (targetCache[index].type == FORINT && targetCache[index].forInt) + if (targetCache[index].type == FOR_LOCAL && targetCache[index].forLocal) { - Atom *targets = targetCache[index].forInt; + Atom *targets = targetCache[index].forLocal; #ifdef DEBUG fprintf(stderr, "%s: Checking target validity\n", __func__); @@ -2752,7 +2752,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, { #ifdef DEBUG fprintf(stderr, "%s: target [%d][%s] is not supported by the owner - denying request.\n", - __func__, target, NameForIntAtom(target)); + __func__, target, NameForLocalAtom(target)); #endif sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None); return 1; @@ -2830,15 +2830,15 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #ifdef DEBUG fprintf(stderr, "%s: replacing local by remote property: [%d][%s] -> [%ld][%s]\n", - __func__, property, NameForIntAtom(property), + __func__, property, NameForLocalAtom(property), remProperty, "NX_CUT_BUFFER_SERVER"); #endif #ifdef DEBUG fprintf(stderr, "%s: Sending XConvertSelection to real X server: requestor [0x%lx] target [%ld][%s] property [%ld][%s] selection [%ld][%s] time [0][CurrentTime]\n", __func__, - serverWindow, remTarget, NameForRemAtom(remTarget), - remProperty, NameForRemAtom(remProperty), - remSelection, NameForRemAtom(remSelection)); + serverWindow, remTarget, NameForRemoteAtom(remTarget), + remProperty, NameForRemoteAtom(remProperty), + remSelection, NameForRemoteAtom(remSelection)); #endif /* @@ -2885,7 +2885,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) /* * On the real server, the right CLIPBOARD atom is * XInternAtom(nxagentDisplay, "CLIPBOARD", 1), which is stored in - * remSelAtoms[nxagentClipboardSelection]. For + * remoteSelectionAtoms[nxagentClipboardSelection]. For * PRIMARY there's nothing to map because that is identical on all * X servers (defined in Xatom.h). We do it anyway so we do not * require a special treatment. @@ -2895,9 +2895,9 @@ XlibAtom translateLocalToRemoteSelection(Atom local) for (int index = 0; index < nxagentMaxSelections; index++) { - if (local == intSelAtoms[index]) + if (local == localSelelectionAtoms[index]) { - remote = remSelAtoms[index]; + remote = remoteSelectionAtoms[index]; break; } } @@ -2909,7 +2909,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) #ifdef DEBUG fprintf(stderr, "%s: mapping local to remote selection: [%d][%s] -> [%ld][%s]\n", __func__, - local, NameForIntAtom(local), remote, NameForRemAtom(remote)); + local, NameForLocalAtom(local), remote, NameForRemoteAtom(remote)); #endif return remote; @@ -2964,7 +2964,7 @@ XlibAtom translateLocalToRemoteTarget(Atom local) #ifdef DEBUG fprintf(stderr, "%s: mapping local to remote target: [%d][%s] -> [%ld][%s]\n", __func__, - local, NameForIntAtom(local), remote, NameForRemAtom(remote)); + local, NameForLocalAtom(local), remote, NameForRemoteAtom(remote)); #endif return remote; @@ -3000,9 +3000,9 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) #ifdef DEBUG fprintf(stderr, "---------\n%s: Received SendNotify from client: property [%d][%s] target [%d][%s] selection [%d][%s] requestor [0x%x] time [%u].\n", __func__, - event->u.selectionNotify.property, NameForIntAtom(event->u.selectionNotify.property), - event->u.selectionNotify.target, NameForIntAtom(event->u.selectionNotify.target), - event->u.selectionNotify.selection, NameForIntAtom(event->u.selectionNotify.selection), + event->u.selectionNotify.property, NameForLocalAtom(event->u.selectionNotify.property), + event->u.selectionNotify.target, NameForLocalAtom(event->u.selectionNotify.target), + event->u.selectionNotify.selection, NameForLocalAtom(event->u.selectionNotify.selection), event->u.selectionNotify.requestor, event->u.selectionNotify.time); #endif @@ -3054,7 +3054,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) * .property must be a server-side Atom. As this property is only * set on our serverWindow and normally there are few other * properties except serverTransToAgentProperty, the only thing - * we need to ensure is that the internal Atom clientCutProperty + * we need to ensure is that the local Atom clientCutProperty * differs from the server-side serverTransToAgentProperty * Atom. The actual name is not important. To be clean here we use * a separate serverTransFromAgentProperty. @@ -3070,7 +3070,7 @@ int nxagentSendNotificationToSelfViaXServer(xEvent *event) #ifdef DEBUG fprintf(stderr, "%s: remote property [%ld][%s].\n", __func__, - serverTransFromAgentProperty, NameForRemAtom(serverTransFromAgentProperty)); + serverTransFromAgentProperty, NameForRemoteAtom(serverTransFromAgentProperty)); #endif sendSelectionNotifyEventToXServer(&eventSelection); return 1; @@ -3097,7 +3097,7 @@ WindowPtr nxagentGetClipboardWindow(Atom property) { #ifdef DEBUG fprintf(stderr, "%s: Returning last [%d] selection owner window [%p] (0x%x).\n", __func__, - intSelAtoms[index], + localSelelectionAtoms[index], (void *)lastSelectionOwner[index].windowPtr, WINDOWID(lastSelectionOwner[index].windowPtr)); #endif @@ -3175,18 +3175,18 @@ Bool nxagentInitClipboard(WindowPtr pWin) FatalError("nxagentInitClipboard: Failed to allocate memory for the last servers array.\n"); } - SAFE_free(intSelAtoms); - intSelAtoms = (Atom *) calloc(nxagentMaxSelections, sizeof(Atom)); - if (intSelAtoms == NULL) + SAFE_free(localSelelectionAtoms); + localSelelectionAtoms = (Atom *) calloc(nxagentMaxSelections, sizeof(Atom)); + if (localSelelectionAtoms == NULL) { - FatalError("nxagentInitClipboard: Failed to allocate memory for the internal selection Atoms array.\n"); + FatalError("nxagentInitClipboard: Failed to allocate memory for the local selection Atoms array.\n"); } - intSelAtoms[nxagentPrimarySelection] = XA_PRIMARY; - intSelAtoms[nxagentClipboardSelection] = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); + localSelelectionAtoms[nxagentPrimarySelection] = XA_PRIMARY; + localSelelectionAtoms[nxagentClipboardSelection] = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); - SAFE_free(remSelAtoms); - remSelAtoms = (XlibAtom *) calloc(nxagentMaxSelections, sizeof(XlibAtom)); - if (remSelAtoms == NULL) + SAFE_free(remoteSelectionAtoms); + remoteSelectionAtoms = (XlibAtom *) calloc(nxagentMaxSelections, sizeof(XlibAtom)); + if (remoteSelectionAtoms == NULL) { FatalError("nxagentInitClipboard: Failed to allocate memory for the remote selection Atoms array.\n"); } @@ -3203,8 +3203,8 @@ Bool nxagentInitClipboard(WindowPtr pWin) * The clipboard selection atom can change with a new X * server while Primary is constant. */ - remSelAtoms[nxagentPrimarySelection] = XA_PRIMARY; - remSelAtoms[nxagentClipboardSelection] = nxagentAtoms[10]; /* CLIPBOARD */ + remoteSelectionAtoms[nxagentPrimarySelection] = XA_PRIMARY; + remoteSelectionAtoms[nxagentClipboardSelection] = nxagentAtoms[10]; /* CLIPBOARD */ serverTARGETS = nxagentAtoms[6]; /* TARGETS */ #ifdef SUPPORT_TEXT_TARGET @@ -3266,7 +3266,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) for (int index = 0; index < nxagentMaxSelections; index++) { XFixesSelectSelectionInput(nxagentDisplay, serverWindow, - remSelAtoms[index], + remoteSelectionAtoms[index], XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask); @@ -3289,7 +3289,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) #ifdef TEST fprintf(stderr, "%s: setting the ownership of %s to %lx" " and registering for PropertyChangeMask events\n", __func__, - validateString(NameForRemAtom(nxagentAtoms[10])), serverWindow); + validateString(NameForRemoteAtom(nxagentAtoms[10])), serverWindow); #endif XSetSelectionOwner(nxagentDisplay, nxagentAtoms[10], serverWindow, CurrentTime); // nxagentAtoms[10] is the CLIPBOARD atom @@ -3311,10 +3311,10 @@ Bool nxagentInitClipboard(WindowPtr pWin) * claim the ownership. Note that we report our serverWindow as * owner, not the real window! */ - if (IS_INTERNAL_OWNER(index) && lastSelectionOwner[index].window) + if (IS_LOCAL_OWNER(index) && lastSelectionOwner[index].window) { - /* remSelAtoms have already been adjusted above */ - XSetSelectionOwner(nxagentDisplay, remSelAtoms[index], serverWindow, CurrentTime); + /* remoteSelectionAtoms have already been adjusted above */ + XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], serverWindow, CurrentTime); } /* @@ -3325,7 +3325,7 @@ Bool nxagentInitClipboard(WindowPtr pWin) /* * FIXME: We should reset lastClients[index].* here! Problem - * is that internal clients might still be waiting for + * is that local clients might still be waiting for * answers. Should reply with failure then. */ -- cgit v1.2.3 From 9fb5949b017b50e55a93dcd200cafffb7602ef21 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 11 Jun 2021 00:15:20 +0200 Subject: Clipboard.c: remove old code This block has been unused for a long time now. The comment describing how to reach that path does not make sense anymore because primary and clipboard are not sharing variables anymore. So drop it. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 31 -------------------------- 1 file changed, 31 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3a210ac5f..503f42add 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1257,37 +1257,6 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) */ serverLastRequestedSelection = X->xselectionrequest.selection; -#if 0 - if (lastClients[index].windowPtr != NULL && IS_LOCAL_OWNER(index)) - { - /* - * Request the real X server to transfer the selection content - * to the NX_CUT_BUFFER_SERVER property of the serverWindow. - * We reach here as follows: - * - mark someting in the nx session - * -> nxagent claims ownership of PRIMARY on real X server - * - at the same time paste _clipboard_ to the client (now) owning primary - * ->vcxsrv will ask for primary contents to store them to Windows clipboard - * - vcxsrv request is for _primary_ and takes this path as the _clipboard_ transfer - * has set lastClients[index].windowPtr - */ - XDeleteProperty(nxagentDisplay, serverWindow, serverTransToAgentProperty); - XConvertSelection(nxagentDisplay, CurrentSelections[index].selection, - X->xselectionrequest.target, serverTransToAgentProperty, - serverWindow, lastClients[index].time); - - NXFlushDisplay(nxagentDisplay, NXFlushLink); - - #ifdef DEBUG - fprintf(stderr, "%s: Sent XConvertSelection: selection [%d][%s] target [%ld][%s] property [%ld][%s] window [0x%lx] time [%u] .\n", __func__, - CurrentSelections[index].selection, NameForRemoteAtom(CurrentSelections[index].selection)), - X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target), - serverTransToAgentProperty, NameForRemoteAtom(serverTransToAgentProperty), - serverWindow, lastClients[index].time); - #endif - } - else -#endif { if (!(nxagentOption(Clipboard) == ClipboardServer || nxagentOption(Clipboard) == ClipboardBoth)) -- cgit v1.2.3 From f03c589ab01dfb43a01e0111877a6a6f6be5ab16 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 11 Jun 2021 00:19:09 +0200 Subject: Clipboard.c: remove superfluous brackets --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 166 ++++++++++++------------- 1 file changed, 82 insertions(+), 84 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 503f42add..0f94fac46 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1257,106 +1257,104 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) */ serverLastRequestedSelection = X->xselectionrequest.selection; + if (!(nxagentOption(Clipboard) == ClipboardServer || + nxagentOption(Clipboard) == ClipboardBoth)) { - if (!(nxagentOption(Clipboard) == ClipboardServer || - nxagentOption(Clipboard) == ClipboardBoth)) - { - #ifdef DEBUG - fprintf (stderr, "%s: clipboard (partly) disabled - denying request.\n", __func__); - #endif + #ifdef DEBUG + fprintf (stderr, "%s: clipboard (partly) disabled - denying request.\n", __func__); + #endif - /* deny the request */ - replyRequestSelectionToXServer(X, False); - return; - } + /* deny the request */ + replyRequestSelectionToXServer(X, False); + return; + } + /* + * If one of our clients owns the selection we ask it to copy + * the selection to the clientCutProperty on nxagent's root + * window in the first step. We then later push that property's + * content to the real X server. + */ + if (IS_LOCAL_OWNER(index)) + { /* - * If one of our clients owns the selection we ask it to copy - * the selection to the clientCutProperty on nxagent's root - * window in the first step. We then later push that property's - * content to the real X server. + * Store who on the real X server requested the data and how + * and where it wants to have it. */ - if (IS_LOCAL_OWNER(index)) - { - /* - * Store who on the real X server requested the data and how - * and where it wants to have it. - */ - lastServers[index].property = X->xselectionrequest.property; - lastServers[index].requestor = X->xselectionrequest.requestor; - lastServers[index].target = X->xselectionrequest.target; - lastServers[index].time = X->xselectionrequest.time; - - /* Prepare the request (like XConvertSelection, but locally). */ - xEvent x = {0}; - x.u.u.type = SelectionRequest; - x.u.selectionRequest.time = GetTimeInMillis(); - x.u.selectionRequest.owner = lastSelectionOwner[index].window; - x.u.selectionRequest.selection = CurrentSelections[index].selection; - x.u.selectionRequest.property = clientCutProperty; - x.u.selectionRequest.requestor = screenInfo.screens[0]->root->drawable.id; /* Fictitious window.*/ + lastServers[index].property = X->xselectionrequest.property; + lastServers[index].requestor = X->xselectionrequest.requestor; + lastServers[index].target = X->xselectionrequest.target; + lastServers[index].time = X->xselectionrequest.time; + + /* Prepare the request (like XConvertSelection, but locally). */ + xEvent x = {0}; + x.u.u.type = SelectionRequest; + x.u.selectionRequest.time = GetTimeInMillis(); + x.u.selectionRequest.owner = lastSelectionOwner[index].window; + x.u.selectionRequest.selection = CurrentSelections[index].selection; + x.u.selectionRequest.property = clientCutProperty; + x.u.selectionRequest.requestor = screenInfo.screens[0]->root->drawable.id; /* Fictitious window.*/ - /* - * Don't send the same window, some programs are clever and - * verify cut and paste operations inside the same window and - * don't notify at all. - * - * x.u.selectionRequest.requestor = lastSelectionOwner[index].window; - */ + /* + * Don't send the same window, some programs are clever and + * verify cut and paste operations inside the same window and + * don't notify at all. + * + * x.u.selectionRequest.requestor = lastSelectionOwner[index].window; + */ - /* - * In TextClipboard mode simply use the previous clipboard - * handling code. - */ - if (nxagentOption(TextClipboard)) + /* + * In TextClipboard mode simply use the previous clipboard + * handling code. + */ + if (nxagentOption(TextClipboard)) + { + /* by dimbor */ + if (X->xselectionrequest.target != XA_STRING) { - /* by dimbor */ - if (X->xselectionrequest.target != XA_STRING) - { - lastServers[index].target = serverUTF8_STRING; - /* by dimbor (idea from zahvatov) */ - x.u.selectionRequest.target = clientUTF8_STRING; - } - else - { - x.u.selectionRequest.target = XA_STRING; - } + lastServers[index].target = serverUTF8_STRING; + /* by dimbor (idea from zahvatov) */ + x.u.selectionRequest.target = clientUTF8_STRING; } else { - x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); + x.u.selectionRequest.target = XA_STRING; } - - /* - * Selete property before sending the request to the client as - * required by ICCCM. - */ - DeleteProperty(lastSelectionOwner[index].windowPtr, clientCutProperty); - - sendEventToClient(lastSelectionOwner[index].client, &x); - - #ifdef DEBUG - fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s] " \ - "target [%d][%s] requestor [0x%x] selection [%d][%s].\n", __func__, - nxagentClientInfoString(lastSelectionOwner[index].client), - x.u.selectionRequest.property, NameForLocalAtom(x.u.selectionRequest.property), - x.u.selectionRequest.target, NameForLocalAtom(x.u.selectionRequest.target), - x.u.selectionRequest.requestor, - x.u.selectionRequest.selection, NameForLocalAtom(x.u.selectionRequest.selection)); - #endif - /* No reply to the Xserver yet - we will do that once the answer - of the above sendEventToClient arrives. */ } else { - #ifdef DEBUG - fprintf(stderr, "%s: no local owner for selection [%ld][%s] - denying request.\n", __func__, - X->xselectionrequest.selection, NameForRemoteAtom(X->xselectionrequest.selection)); - #endif - - /* deny the request */ - replyRequestSelectionToXServer(X, False); + x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); } + + /* + * Selete property before sending the request to the client as + * required by ICCCM. + */ + DeleteProperty(lastSelectionOwner[index].windowPtr, clientCutProperty); + + sendEventToClient(lastSelectionOwner[index].client, &x); + + #ifdef DEBUG + fprintf(stderr, "%s: sent SelectionRequest event to client %s property [%d][%s] " \ + "target [%d][%s] requestor [0x%x] selection [%d][%s].\n", __func__, + nxagentClientInfoString(lastSelectionOwner[index].client), + x.u.selectionRequest.property, NameForLocalAtom(x.u.selectionRequest.property), + x.u.selectionRequest.target, NameForLocalAtom(x.u.selectionRequest.target), + x.u.selectionRequest.requestor, + x.u.selectionRequest.selection, NameForLocalAtom(x.u.selectionRequest.selection)); + #endif + /* No reply to the Xserver yet - we will do that once the answer + of the above sendEventToClient arrives. */ + } + else + { + #ifdef DEBUG + fprintf(stderr, "%s: no local owner for selection [%ld][%s] - denying request.\n", __func__, + X->xselectionrequest.selection, NameForRemoteAtom(X->xselectionrequest.selection)); + #endif + + /* deny the request */ + replyRequestSelectionToXServer(X, False); } } -- cgit v1.2.3 From e8217798d513dc86008195546ed4a06f6e54a95f Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 14 Jun 2021 22:02:55 +0200 Subject: Clipboard.c: add helper variable --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 38 ++++++++++++++------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 0f94fac46..a5d74415e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -958,12 +958,14 @@ static void replyRequestSelectionToXServer(XEvent *X, Bool success) */ void nxagentHandleSelectionRequestFromXServer(XEvent *X) { + XlibAtom target = X->xselectionrequest.target; + #ifdef DEBUG fprintf(stderr, "---------\n%s: Received SelectionRequestEvent from real server: selection [%ld][%s] " \ "target [%ld][%s] requestor [display[%s]/0x%lx] destination [%ld][%s] time [%lu]\n", __func__, X->xselectionrequest.selection, NameForRemoteAtom(X->xselectionrequest.selection), - X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target), + target, NameForRemoteAtom(target), DisplayString(nxagentDisplay), X->xselectionrequest.requestor, X->xselectionrequest.property, NameForRemoteAtom(X->xselectionrequest.property), X->xselectionrequest.time); @@ -1008,7 +1010,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) return; } - if (X->xselectionrequest.target == serverTARGETS) + if (target == serverTARGETS) { /* * In TextClipboard mode answer with a predefined list of @@ -1101,7 +1103,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } } } - else if (X->xselectionrequest.target == serverTIMESTAMP) + else if (target == serverTIMESTAMP) { /* * Section 2.6.2 of the ICCCM states: @@ -1128,7 +1130,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, True); return; } - else if (X->xselectionrequest.target == serverMULTIPLE) + else if (target == serverMULTIPLE) { #ifdef DEBUG fprintf(stderr, "%s: (currently) unsupported target [MULTIPLE] - denying request.\n", __func__); @@ -1136,7 +1138,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } - else if (X->xselectionrequest.target == serverDELETE) + else if (target == serverDELETE) { #ifdef DEBUG fprintf(stderr, "%s: (currently) unsupported target [DELETE] - denying request.\n", __func__); @@ -1144,7 +1146,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } - else if (X->xselectionrequest.target == serverINSERT_SELECTION) + else if (target == serverINSERT_SELECTION) { #ifdef DEBUG fprintf(stderr, "%s: (currently) unsupported target [INSERT_SELECTION] - denying request.\n", __func__); @@ -1152,7 +1154,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } - else if (X->xselectionrequest.target == serverINSERT_PROPERTY) + else if (target == serverINSERT_PROPERTY) { #ifdef DEBUG fprintf(stderr, "%s: (currently) unsupported target [INSERT_PROPERTY] - denying request.\n", __func__); @@ -1160,7 +1162,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } - else if (X->xselectionrequest.target == serverSAVE_TARGETS) + else if (target == serverSAVE_TARGETS) { #ifdef DEBUG fprintf(stderr, "%s: (currently) unsupported target [SAVE_TARGETS] - denying request.\n", __func__); @@ -1168,7 +1170,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) replyRequestSelectionToXServer(X, False); return; } - else if (X->xselectionrequest.target == serverTARGET_SIZES) + else if (target == serverTARGET_SIZES) { #ifdef DEBUG fprintf(stderr, "%s: (currently) unsupported target [TARGET_SIZES] - denying request.\n", __func__); @@ -1179,11 +1181,11 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) if (nxagentOption(TextClipboard)) { - if (!isTextTarget(X->xselectionrequest.target)) + if (!isTextTarget(target)) { #ifdef DEBUG fprintf(stderr, "%s: denying request for non-text target [%ld][%s].\n", __func__, - X->xselectionrequest.target, NameForRemoteAtom(X->xselectionrequest.target)); + target, NameForRemoteAtom(target)); #endif replyRequestSelectionToXServer(X, False); @@ -1194,8 +1196,8 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } #ifdef DEBUG - fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target, - NameForRemoteAtom(X->xselectionrequest.target)); + fprintf(stderr, "%s: target [%ld][%s].\n", __func__, target, + NameForRemoteAtom(target)); #endif /* @@ -1219,7 +1221,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) Bool match = False; for (int i = 0; i < targetCache[index].numTargets; i++) { - if (targets[i] == X->xselectionrequest.target) + if (targets[i] == target) { match = True; break; @@ -1243,7 +1245,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * supported targets first. */ #ifdef DEBUG - if (X->xselectionrequest.target != serverTARGETS) + if (target != serverTARGETS) { fprintf(stderr, "%s: WARNING: remote client has not retrieved TARGETS before asking for selection!\n", __func__); @@ -1283,7 +1285,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) */ lastServers[index].property = X->xselectionrequest.property; lastServers[index].requestor = X->xselectionrequest.requestor; - lastServers[index].target = X->xselectionrequest.target; + lastServers[index].target = target; lastServers[index].time = X->xselectionrequest.time; /* Prepare the request (like XConvertSelection, but locally). */ @@ -1310,7 +1312,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) if (nxagentOption(TextClipboard)) { /* by dimbor */ - if (X->xselectionrequest.target != XA_STRING) + if (target != XA_STRING) { lastServers[index].target = serverUTF8_STRING; /* by dimbor (idea from zahvatov) */ @@ -1323,7 +1325,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } else { - x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target); + x.u.selectionRequest.target = nxagentRemoteToLocalAtom(target); } /* -- cgit v1.2.3 From 4eba9d6b1c2b6fb6229aebe6406de3b4564e869c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 14 Jun 2021 22:05:29 +0200 Subject: Clipboard.c: extend comment --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index a5d74415e..a891af52d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2825,7 +2825,10 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * FIXME: ICCCM states: "Clients should not use CurrentTime for the * time argument of a ConvertSelection request. Instead, they should * use the timestamp of the event that caused the request to be - * made." + * made." Well, the event that that caused this came from an + * nxagent _client_ but we are a client to the real X server, which + * has an own time., we cannot use its time there. So what time + * would be correct here? */ UpdateCurrentTime(); -- cgit v1.2.3 From ad69d4a0ec5bd1a26942a938d0d902d643b70b4e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 14 Jun 2021 23:01:28 +0200 Subject: Clipboard.c: improve output for PRINT_CLIPBOARD_CONTENT_ON_DEBUG --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 29 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index a891af52d..bb1656d7f 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1779,17 +1779,22 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) ulReturnItems, pszReturnData, 1); #ifdef DEBUG - fprintf(stderr, "%s: Selection property [%d][%s] changed to" + fprintf(stderr, "%s: Selection property [%d][%s] changed to resultFormat [%d] returnType [%d][%s] len [%d]" #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG - "[\"%*.*s\"...]" + /* FIXME: only print the string if the resultFormat is 8 */ + " value [\"%*.*s\"...] hex [0x%2.2x%2.2x%2.2x%2.2x]" #endif "\n", __func__, lastClients[index].property, - validateString(NameForLocalAtom(lastClients[index].property)) + validateString(NameForLocalAtom(lastClients[index].property)), + resultFormat, + atomReturnType, NameForRemoteAtom(atomReturnType), + (int)ulReturnItems * resultFormat / 8 #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG ,(int)(min(20, ulReturnItems * resultFormat / 8)), (int)(min(20, ulReturnItems * resultFormat / 8)), - pszReturnData + pszReturnData, + pszReturnData[0], pszReturnData[1], pszReturnData[2], pszReturnData[3] #endif ); #endif @@ -2049,22 +2054,26 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) ulReturnItems); #ifdef DEBUG { - fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] len [%d]" + fprintf(stderr, "%s: XChangeProperty sent to window [0x%lx] for property [%ld][%s] resultFormat [%d] returnType [%ld][%s] len [%d]" #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG - "value [\"%*.*s\"...]" + /* FIXME: only print the string if the resultFormat is 8 */ + " value [\"%*.*s\"...] hex [0x%2.2x%2.2x%2.2x%2.2x]" #endif - "\n", + "\n", __func__, lastServers[index].requestor, lastServers[index].property, NameForRemoteAtom(lastServers[index].property), - (int)ulReturnItems * 8 / 8 + resultFormat, + nxagentLocalToRemoteAtom(atomReturnType), NameForLocalAtom(atomReturnType), + (int)ulReturnItems * resultFormat / 8 #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG ,(int)(min(20, ulReturnItems * 8 / 8)), (int)(min(20, ulReturnItems * 8 / 8)), - pszReturnData + pszReturnData, + pszReturnData[0], pszReturnData[1], pszReturnData[2], pszReturnData[3] #endif - ); + ); } #endif } -- cgit v1.2.3 From e65e715129ddbefaf2ebb4b14a803b312632705e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 14 Jun 2021 23:59:05 +0200 Subject: Clipboard.c: Fix: forward the correct type and format now stuff like xclip -o -t LENGTH works (if the owner offers that) --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index bb1656d7f..ba26f0915 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1774,7 +1774,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) { ChangeWindowProperty(lastClients[index].windowPtr, lastClients[index].property, - lastClients[index].target, + nxagentRemoteToLocalAtom(atomReturnType), resultFormat, PropModeReplace, ulReturnItems, pszReturnData, 1); @@ -2043,12 +2043,11 @@ void handlePropertyTransferFromAgentToXserver(int index, XlibAtom property) /* Fill the property on the requestor with the requested data. */ /* The XChangeProperty source code reveals it will always return 1, no matter what, so no need to check the result */ - /* FIXME: better use the format returned by above request. */ XChangeProperty(nxagentDisplay, lastServers[index].requestor, lastServers[index].property, - lastServers[index].target, - 8, + nxagentLocalToRemoteAtom(atomReturnType), + resultFormat, PropModeReplace, pszReturnData, ulReturnItems); -- cgit v1.2.3 From 15a60b1c129707e0b8280de0ef0a2234fd50010d Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 19:16:21 +0200 Subject: Clipboard.c: fix typos in comment --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index ba26f0915..bb4907393 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1448,7 +1448,7 @@ static void transferSelectionFromXServer(int index, int resource) } else { - /* Collect the property and store ist with index "resource" d */ + /* Collect the property and store it with index "resource" */ result = NXCollectProperty(nxagentDisplay, free_resource, serverWindow, -- cgit v1.2.3 From d42ebd2aeca80efa926fedd49d2aef75bd4e28ea Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 20:20:41 +0200 Subject: Clipboard.c: fix format specifier --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index bb4907393..00a2dd1fd 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1779,7 +1779,7 @@ Bool nxagentCollectPropertyEventFromXServer(int resource) ulReturnItems, pszReturnData, 1); #ifdef DEBUG - fprintf(stderr, "%s: Selection property [%d][%s] changed to resultFormat [%d] returnType [%d][%s] len [%d]" + fprintf(stderr, "%s: Selection property [%d][%s] changed to resultFormat [%d] returnType [%ld][%s] len [%d]" #ifdef PRINT_CLIPBOARD_CONTENT_ON_DEBUG /* FIXME: only print the string if the resultFormat is 8 */ " value [\"%*.*s\"...] hex [0x%2.2x%2.2x%2.2x%2.2x]" -- cgit v1.2.3 From 62775ed673e4c3008b48dad2a4659271d5e02b02 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 20:44:16 +0200 Subject: Clipboard.c: rename intermediate variable Using a capital letter here better reflects that this is an event from the real X server. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 00a2dd1fd..326f62ca7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1835,27 +1835,27 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) return; } - XSelectionEvent * e = (XSelectionEvent *)X; + XSelectionEvent *E = (XSelectionEvent *)X; #ifdef DEBUG fprintf(stderr, "---------\n%s: Received SelectionNotify event from real X server, property " \ "[%ld][%s] requestor [0x%lx] selection [%s] target [%ld][%s] time [%lu] send_event [%d].\n", - __func__, e->property, NameForRemoteAtom(e->property), e->requestor, - NameForRemoteAtom(e->selection), e->target, - NameForRemoteAtom(e->target), e->time, e->send_event); + __func__, E->property, NameForRemoteAtom(E->property), E->requestor, + NameForRemoteAtom(E->selection), E->target, + NameForRemoteAtom(E->target), E->time, E->send_event); /* this has not been SENT by nxagent but is the answer to a request of nxagent */ - if (e->requestor == serverWindow) + if (E->requestor == serverWindow) { fprintf(stderr, "%s: requestor is nxagent's serverWindow!\n", __func__);; } #endif /* determine the selection we are talking about here */ - int index = nxagentFindLastSelectionOwnerIndex(e->selection); + int index = nxagentFindLastSelectionOwnerIndex(E->selection); if (index == -1) { #ifdef DEBUG - fprintf (stderr, "%s: unknown selection [%ld] .\n", __func__, e->selection); + fprintf (stderr, "%s: unknown selection [%ld] .\n", __func__, E->selection); #endif return; } -- cgit v1.2.3 From c775bedbcb6ead00548783b362de165b3f6968a2 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 20:47:55 +0200 Subject: Clipboard.c: rename nxagentFindLastSelectionOwnerIndex() Did not refer to LastSelectionOwner at all... --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 326f62ca7..c38c4b584 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -754,7 +754,7 @@ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) * sel. sel is an atom on the real X server. If the index cannot be * determined it will return -1. */ -int nxagentFindLastSelectionOwnerIndex(XlibAtom sel) +int nxagentFindRemoteSelectionIndex(XlibAtom sel) { for (int index = 0; index < nxagentMaxSelections; index++) { @@ -892,7 +892,7 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) return; } - int index = nxagentFindLastSelectionOwnerIndex(X->xselectionclear.selection); + int index = nxagentFindRemoteSelectionIndex(X->xselectionclear.selection); if (index != -1) { if (IS_LOCAL_OWNER(index)) @@ -984,7 +984,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) } /* The selection in this request is none we own. */ - int index = nxagentFindLastSelectionOwnerIndex(X->xselectionrequest.selection); + int index = nxagentFindRemoteSelectionIndex(X->xselectionrequest.selection); if (index == -1) { #ifdef DEBUG @@ -1851,7 +1851,7 @@ void nxagentHandleSelectionNotifyFromXServer(XEvent *X) #endif /* determine the selection we are talking about here */ - int index = nxagentFindLastSelectionOwnerIndex(E->selection); + int index = nxagentFindRemoteSelectionIndex(E->selection); if (index == -1) { #ifdef DEBUG @@ -3070,7 +3070,7 @@ WindowPtr nxagentGetClipboardWindow(Atom property) return NULL; } - int index = nxagentFindLastSelectionOwnerIndex(serverLastRequestedSelection); + int index = nxagentFindRemoteSelectionIndex(serverLastRequestedSelection); if (index != -1 && property == clientCutProperty && lastSelectionOwner[index].windowPtr != NULL) -- cgit v1.2.3 From 2b156c39769609022476e9707d286e46844b6787 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 20:50:04 +0200 Subject: Events.c: fix unused variable --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index d29ed9bcd..906915ad0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -4553,7 +4553,10 @@ void ForwardClientMessage(ClientPtr client, xSendEventReq *stuff) XlibWindow dest; dest = DefaultRootWindow(nxagentDisplay); - Status stat = XSendEvent(nxagentDisplay, dest, stuff->propagate, stuff->eventMask, &X); + #ifdef DEBUG + Status stat = + #endif + XSendEvent(nxagentDisplay, dest, stuff->propagate, stuff->eventMask, &X); XFlush(nxagentDisplay); #ifdef DEBUG fprintf(stderr, "%s: send to window [0x%lx]\n", __func__, dest); -- cgit v1.2.3 From 9b4602847ec98f695d044bef59704b5344c8869b Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 22:09:02 +0200 Subject: Clipboard.c: add missing target cache invalidation to some (currently unused) code --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index c38c4b584..b29ed3ec7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2169,6 +2169,8 @@ static void resetSelectionOwnerOnXServer(void) setClientSelectionStage(index, SelectionStageNone); + invalidateTargetCache(index); + /* Hmm, this is already None when reaching here. */ lastServers[index].requestor = None; } -- cgit v1.2.3 From 1c8869b92f4e46b608636c2f6839b317cd7ef150 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 23:43:33 +0200 Subject: Clipboard.c: remove obsolete (disabled) code Either replyPendingRequest a few lines before will set this to None or it will already be None. Also drop the wrong comment line... --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index b29ed3ec7..4e95c024d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2362,9 +2362,6 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) */ invalidateTargetCache(index); - /* FIXME: commented because index is invalid here! */ - /* lastServers[index].requestor = None; */ - /* FIXME -- cgit v1.2.3 From 423caaf0ff8826449734a04dc9038b552e6c15e5 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 23:48:32 +0200 Subject: Clipboard.c: extend setSelectionOwnerOnXServer() to let it handle a SelectionClear automatically. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 4e95c024d..c200ad64c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2296,11 +2296,6 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) return; } - #ifdef DEBUG - fprintf(stderr, "%s: Setting selection owner to serverwindow ([0x%lx]).\n", __func__, - serverWindow); - #endif - int index = nxagentFindCurrentSelectionIndex(pSelection->selection); if (index != -1) { @@ -2312,7 +2307,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) lastSelectionOwner[index].window, pSelection->window); fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%lx])\n", __func__, (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, - nxagentWindow(pSelection->pWin), serverWindow); + pSelection->pWin ? nxagentWindow(pSelection->pWin) : 0, serverWindow); fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, lastSelectionOwner[index].lastTimeChanged); #endif @@ -2342,8 +2337,16 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) * watch clipboard ownership changes, clipboard owners should * reacquire the clipboard whenever the content or metadata (e.g * the list of supported targets) changes." + * If pWin is NULL this is a SelectionClear. */ - XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], serverWindow, CurrentTime); + #ifdef DEBUG + if (pSelection->pWin) + { + fprintf(stderr, "%s: Setting selection owner to serverwindow ([0x%lx]).\n", __func__, + serverWindow); + } + #endif + XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], pSelection->pWin ? serverWindow : 0, CurrentTime); /* * The real owner window (inside nxagent) is stored in -- cgit v1.2.3 From 5e017044f69ffb821be678964764a4bfb19afe8b Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 18 Jun 2021 00:06:57 +0200 Subject: Clipboard.c: do not process requests if we do not have a local owner This can happen after having processed a SelectionClear event while the real X server still knows the nxagent serverWindow as the selection owner. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index c200ad64c..018827a0a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -995,6 +995,15 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) return; } + if (!IS_LOCAL_OWNER(index)) + { + #ifdef DEBUG + fprintf(stderr, "%s: no local owner for selection [%ld] - denying request.\n", __func__, X->xselectionrequest.selection); + #endif + replyRequestSelectionToXServer(X, False); + return; + } + #ifdef DEBUG fprintf(stderr, "%s: lastServers[%d].requestor [0x%lx].\n", __func__, index, lastServers[index].requestor); #endif -- cgit v1.2.3 From 30e9b82cef50c55e64db5ad656dbdf4a5056467c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 18 Jun 2021 00:19:52 +0200 Subject: Clipboard.c: restruct setSelectionOwnerOnXServer Immediately abort if the selection index cannot be determined. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 145 +++++++++++++------------ 1 file changed, 76 insertions(+), 69 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 018827a0a..392943066 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2306,73 +2306,78 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) } int index = nxagentFindCurrentSelectionIndex(pSelection->selection); - if (index != -1) + if (index == -1) { #ifdef DEBUG - fprintf(stderr, "%s: lastSelectionOwner.client %s -> %s\n", __func__, - nxagentClientInfoString(lastSelectionOwner[index].client), - nxagentClientInfoString(pSelection->client)); - fprintf(stderr, "%s: lastSelectionOwner.window [0x%x] -> [0x%x]\n", __func__, - lastSelectionOwner[index].window, pSelection->window); - fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%lx])\n", __func__, - (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, - pSelection->pWin ? nxagentWindow(pSelection->pWin) : 0, serverWindow); - fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, - lastSelectionOwner[index].lastTimeChanged); + fprintf(stderr, "%s: selection [%s] can/will not be handled by the clipboard code\n", __func__, NameForLocalAtom(pSelection->selection)); #endif + return; + } - #if defined(TEST) || defined(DEBUG) - if (lastServers[index].requestor != None) - { - /* - * There's an X client on the real X server waiting for a - * reply. That reply will never come because now we are the - * owner so let's be fair and cancel that request. - */ - fprintf(stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set. Cancelling pending request.\n", - __func__, index, lastServers[index].requestor); - - replyPendingRequestSelectionToXServer(index, False); - - /* Now we can go on. */ - } - #endif + #ifdef DEBUG + fprintf(stderr, "%s: lastSelectionOwner.client %s -> %s\n", __func__, + nxagentClientInfoString(lastSelectionOwner[index].client), + nxagentClientInfoString(pSelection->client)); + fprintf(stderr, "%s: lastSelectionOwner.window [0x%x] -> [0x%x]\n", __func__, + lastSelectionOwner[index].window, pSelection->window); + fprintf(stderr, "%s: lastSelectionOwner.windowPtr [%p] -> [%p] [0x%x] (serverWindow: [0x%lx])\n", __func__, + (void *)lastSelectionOwner[index].windowPtr, (void *)pSelection->pWin, + pSelection->pWin ? nxagentWindow(pSelection->pWin) : 0, serverWindow); + fprintf(stderr, "%s: lastSelectionOwner.lastTimeChanged [%u]\n", __func__, + lastSelectionOwner[index].lastTimeChanged); + #endif + #if defined(TEST) || defined(DEBUG) + if (lastServers[index].requestor != None) + { /* - * Inform the real X server that our serverWindow is the - * clipboard owner. - * https://www.freedesktop.org/wiki/ClipboardManager/ states - * "In order to support peers who use the XFIXES extension to - * watch clipboard ownership changes, clipboard owners should - * reacquire the clipboard whenever the content or metadata (e.g - * the list of supported targets) changes." - * If pWin is NULL this is a SelectionClear. + * There's an X client on the real X server waiting for a + * reply. That reply will never come because now we are the + * owner so let's be fair and cancel that request. */ - #ifdef DEBUG - if (pSelection->pWin) - { - fprintf(stderr, "%s: Setting selection owner to serverwindow ([0x%lx]).\n", __func__, - serverWindow); - } - #endif - XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], pSelection->pWin ? serverWindow : 0, CurrentTime); + fprintf(stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set. Cancelling pending request.\n", + __func__, index, lastServers[index].requestor); + replyPendingRequestSelectionToXServer(index, False); - /* - * The real owner window (inside nxagent) is stored in - * lastSelectionOwner[index].window. - * lastSelectionOwner[index].windowPtr points to the struct that - * contains all information about the owner window. - */ - storeSelectionOwnerData(index, pSelection); + /* Now we can go on. */ + } + #endif - setClientSelectionStage(index, SelectionStageNone); + /* + * Inform the real X server that our serverWindow is the + * clipboard owner. + * https://www.freedesktop.org/wiki/ClipboardManager/ states + * "In order to support peers who use the XFIXES extension to + * watch clipboard ownership changes, clipboard owners should + * reacquire the clipboard whenever the content or metadata (e.g + * the list of supported targets) changes." + * If pWin is NULL this is a SelectionClear. + */ + #ifdef DEBUG + if (pSelection->pWin) + { + fprintf(stderr, "%s: Setting selection owner to serverwindow ([0x%lx]).\n", __func__, + serverWindow); + } + #endif + XSetSelectionOwner(nxagentDisplay, remoteSelectionAtoms[index], pSelection->pWin ? serverWindow : 0, CurrentTime); - /* - * This will be repeated on reception of the SelectionOwner - * callback but we cannot be sure if there are any intermediate - * requests in the queue already so better do it here, too. - */ - invalidateTargetCache(index); + /* + * The real owner window (inside nxagent) is stored in + * lastSelectionOwner[index].window. + * lastSelectionOwner[index].windowPtr points to the struct that + * contains all information about the owner window. + */ + storeSelectionOwnerData(index, pSelection); + + setClientSelectionStage(index, SelectionStageNone); + + /* + * This will be repeated on reception of the SelectionOwner + * callback but we cannot be sure if there are any intermediate + * requests in the queue already so better do it here, too. + */ + invalidateTargetCache(index); /* FIXME @@ -2381,22 +2386,24 @@ FIXME2: instead of XGetSelectionOwner we could check if the Xfixes SetSelectionOwner event has arrived in the event queue; possibly saving one roundtrip. - if (XGetSelectionOwner(nxagentDisplay, pSelection->selection) == serverWindow) - { - fprintf (stderr, "%s: SetSelectionOwner OK\n", __func__); + if (XGetSelectionOwner(nxagentDisplay, pSelection->selection) == serverWindow) + { + fprintf (stderr, "%s: SetSelectionOwner OK\n", __func__); - lastSelectionOwnerSelection = pSelection; - lastSelectionOwnerClient = pSelection->client; - lastSelectionOwnerWindow = pSelection->window; - lastSelectionOwnerWindowPtr = pSelection->pWin; + lastSelectionOwnerSelection = pSelection; + lastSelectionOwnerClient = pSelection->client; + lastSelectionOwnerWindow = pSelection->window; + lastSelectionOwnerWindowPtr = pSelection->pWin; - setClientSelectionStage(index, SelectionStageNone); + setClientSelectionStage(index, SelectionStageNone); - lastServers[index].requestor = None; - } - else fprintf (stderr, "%s: SetSelectionOwner failed\n", __func__); -*/ + lastServers[index].requestor = None; + } + else + { + fprintf (stderr, "%s: SetSelectionOwner failed\n", __func__); } +*/ } /* -- cgit v1.2.3 From 289ac3dfd3b0f9bcefff15eb80dd04dccb0a1051 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 18 Jun 2021 00:21:41 +0200 Subject: Clipboard.c: remove superflous check replyPendingRequestSelectionToXServer already checks for None --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 392943066..735a9379a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -2327,21 +2327,13 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) lastSelectionOwner[index].lastTimeChanged); #endif - #if defined(TEST) || defined(DEBUG) - if (lastServers[index].requestor != None) - { - /* - * There's an X client on the real X server waiting for a - * reply. That reply will never come because now we are the - * owner so let's be fair and cancel that request. - */ - fprintf(stderr, "%s: WARNING! lastServers[%d].requestor window [0x%lx] already set. Cancelling pending request.\n", - __func__, index, lastServers[index].requestor); - replyPendingRequestSelectionToXServer(index, False); - /* Now we can go on. */ - } - #endif + /* + * There's an X client on the real X server waiting for a + * reply. That reply will never come because now we are the + * owner so let's be fair and cancel that request. + */ + replyPendingRequestSelectionToXServer(index, False); /* * Inform the real X server that our serverWindow is the -- cgit v1.2.3 From eae0eff3aa5c8e3601677e8395fea72be231b554 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Fri, 18 Jun 2021 00:23:30 +0200 Subject: Clipboard.c: improve some comments --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 735a9379a..85ef1ae16 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -97,6 +97,13 @@ const int nxagentMaxSelections = 2; static XlibAtom *remoteSelectionAtoms = NULL; static Atom *localSelelectionAtoms = NULL; +/* + * The real owner window (inside nxagent) is stored in + * lastSelectionOwner[index].window. + * lastSelectionOwner[index].windowPtr points to the struct that + * contains all information about the owner window. + * lastTimeChanged is always a local time. + */ typedef struct _SelectionOwner { ClientPtr client; /* local client */ @@ -106,9 +113,8 @@ typedef struct _SelectionOwner } SelectionOwner; /* - * This contains the last selection owner in nxagent. The - * lastTimeChanged is always a local time. If .client is NULL the - * owner is outside nxagent. + * This contains the last selection owner for each selection. If + * .client is NULL the owner is outside nxagent or there is no owner. */ static SelectionOwner *lastSelectionOwner = NULL; @@ -717,6 +723,7 @@ static Bool matchSelectionOwner(int index, ClientPtr pClient, WindowPtr pWindow) * Attention: does not work properly when both client AND window * are passed as setClientSelectionStage(None) will also clear * the lastClientWindowPtr! + * This is only called from Client.c and Window.c */ void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) { -- cgit v1.2.3 From 65d29df13fc4c955ddf60a200d41d8be7283c505 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 20 Jun 2021 12:58:04 +0200 Subject: Clipboard.c: Only take full clipboard clearing action if non-empty --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 85ef1ae16..09c7eb2c2 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -912,21 +912,21 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) x.u.selectionClear.atom = CurrentSelections[index].selection; sendEventToClient(lastSelectionOwner[index].client, &x); - } - /* - * Set the root window with the NullClient as selection owner. Our - * clients asking for the owner via XGetSelectionOwner() will get - * these for an answer. - */ - CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; - CurrentSelections[index].client = NullClient; + /* + * Set the root window with the NullClient as selection owner. Our + * clients asking for the owner via XGetSelectionOwner() will get + * this for an answer. + */ + CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; + CurrentSelections[index].client = NullClient; - clearSelectionOwnerData(index); + clearSelectionOwnerData(index); - setClientSelectionStage(index, SelectionStageNone); + setClientSelectionStage(index, SelectionStageNone); - invalidateTargetCache(index); + invalidateTargetCache(index); + } } } -- cgit v1.2.3 From bbf9d74c40354974cdb6023ade47bf7d8be26330 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 21 Jun 2021 22:26:12 +0200 Subject: Clipboard.c: print debug message if selection is already cleared --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 09c7eb2c2..20a380817 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -927,6 +927,12 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) invalidateTargetCache(index); } + #ifdef DEBUG + else + { + fprintf(stderr, "%s: selection already cleared - doing nothing.\n", __func__); + } + #endif } } -- cgit v1.2.3 From 15ee25b7dd259793b335723c5f66ff14054c72d0 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Tue, 22 Jun 2021 21:41:10 +0200 Subject: NXdispatch.c: add an explaining comment and restructure a bit. --- nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c index ff8330cc7..5df008bbb 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -745,10 +745,15 @@ ProcConvertSelection(register ClientPtr client) while ((i < NumCurrentSelections) && CurrentSelections[i].selection != stuff->selection) i++; if ((i < NumCurrentSelections) && -#ifdef NXAGENT_SERVER - (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient) -#else (CurrentSelections[i].window != None) +#ifdef NXAGENT_SERVER + /* + * .window can be set and pointing to our server window to + * signal the clipboard owner being on the real X + * server. Therefore we need to check .client in addition + * to ensure having a local owner. + */ + && (CurrentSelections[i].client != NullClient) #endif #ifdef XCSECURITY && (!client->CheckAccess || -- cgit v1.2.3 From 7aa969cd4ee5fe6ecf74f82442e4a0a7491191c1 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 16 Jun 2021 20:16:20 +0200 Subject: Fix Xfixes event handling Calling the callback on receptions of an EXTERNAL xfixes event was a weird idea from the start. However, since adding the protection trap around it it made no sense at all because it effectivly made the callback a noop for that case. So let's drop all the trap nonsense and implement it properly. The callback will only be used for actions by internal clients. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 166 +++++++++++++------------ nx-X11/programs/Xserver/hw/nxagent/Clipboard.h | 3 + nx-X11/programs/Xserver/hw/nxagent/Events.c | 101 +++++++-------- nx-X11/programs/Xserver/hw/nxagent/Trap.c | 8 -- nx-X11/programs/Xserver/hw/nxagent/Trap.h | 7 -- 5 files changed, 137 insertions(+), 148 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 20a380817..4a0bf9cb5 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -873,14 +873,13 @@ void invalidateTargetCaches(void) /* * This is called from Events.c dispatch loop on reception of a * SelectionClear event. We receive this event if someone on the real - * X server claims the selection ownership. + * X server claims the selection ownership we have/had. + * Three versions of this routine with different parameter types. */ -void nxagentHandleSelectionClearFromXServer(XEvent *X) +void nxagentHandleSelectionClearFromXServerByIndex(int index) { #ifdef DEBUG - fprintf(stderr, "---------\n%s: SelectionClear event for selection [%lu][%s] window [0x%lx] time [%lu].\n", - __func__, X->xselectionclear.selection, NameForRemoteAtom(X->xselectionclear.selection), - X->xselectionclear.window, X->xselectionclear.time); + fprintf(stderr, "%s: SelectionClear event for selection index [%u].\n", __func__, index); #endif if (!agentClipboardInitialized) @@ -899,43 +898,56 @@ void nxagentHandleSelectionClearFromXServer(XEvent *X) return; } - int index = nxagentFindRemoteSelectionIndex(X->xselectionclear.selection); - if (index != -1) + if (IS_LOCAL_OWNER(index)) { - if (IS_LOCAL_OWNER(index)) - { - /* Send a SelectionClear event to (our) previous owner. */ - xEvent x = {0}; - x.u.u.type = SelectionClear; - x.u.selectionClear.time = GetTimeInMillis(); - x.u.selectionClear.window = lastSelectionOwner[index].window; - x.u.selectionClear.atom = CurrentSelections[index].selection; + /* Send a SelectionClear event to (our) previous owner. */ + xEvent x = {0}; + x.u.u.type = SelectionClear; + x.u.selectionClear.time = GetTimeInMillis(); + x.u.selectionClear.window = lastSelectionOwner[index].window; + x.u.selectionClear.atom = CurrentSelections[index].selection; - sendEventToClient(lastSelectionOwner[index].client, &x); + sendEventToClient(lastSelectionOwner[index].client, &x); - /* - * Set the root window with the NullClient as selection owner. Our - * clients asking for the owner via XGetSelectionOwner() will get - * this for an answer. - */ - CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; - CurrentSelections[index].client = NullClient; + /* + * Set the root window with the NullClient as selection owner. Our + * clients asking for the owner via XGetSelectionOwner() will get + * this for an answer. + */ + CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; + CurrentSelections[index].client = NullClient; - clearSelectionOwnerData(index); + clearSelectionOwnerData(index); - setClientSelectionStage(index, SelectionStageNone); + setClientSelectionStage(index, SelectionStageNone); - invalidateTargetCache(index); - } - #ifdef DEBUG - else - { - fprintf(stderr, "%s: selection already cleared - doing nothing.\n", __func__); - } - #endif + invalidateTargetCache(index); + } +} + +void nxagentHandleSelectionClearFromXServerByAtom(XlibAtom sel) +{ + #ifdef DEBUG + fprintf(stderr, "---------\n%s: SelectionClear event for remote selection atom [%lu][%s].\n", __func__, sel, NameForRemoteAtom(sel)); + #endif + + int index = nxagentFindRemoteSelectionIndex(sel); + if (index != -1) + { + nxagentHandleSelectionClearFromXServerByIndex(index); } } +void nxagentHandleSelectionClearFromXServer(XEvent *X) +{ + #ifdef DEBUG + fprintf(stderr, "---------\n%s: SelectionClear event for selection [%lu][%s] window [0x%lx] time [%lu].\n", + __func__, X->xselectionclear.selection, NameForRemoteAtom(X->xselectionclear.selection), + X->xselectionclear.window, X->xselectionclear.time); + #endif + nxagentHandleSelectionClearFromXServerByAtom(X->xselectionclear.selection); +} + /* * Send a SelectionNotify event as reply to the RequestSelection * event X. If success is True take the property from the event, else @@ -2202,25 +2214,11 @@ static void resetSelectionOwnerOnXServer(void) #ifdef NXAGENT_CLIPBOARD /* - * The callback is called from dix. This is the normal operation - * mode. The callback is also called when nxagent gets XFixes events - * from the real X server. In that case the Trap is set and the - * callback will do nothing. + * The callback is called from dix. */ - void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, void *args) { - /* - * Only act if the trap is unset. The trap indicates that we are - * triggered by an XFixes clipboard event originating from the real - * X server. In that case we do not want to propagate back changes - * to the real X server, because it already knows about them and we - * would end up in an infinite loop of events. If there was a better - * way to identify that situation during callback processing we - * could get rid of the Trap... - */ - SelectionInfoRec *info = (SelectionInfoRec *)args; #ifdef DEBUG @@ -2249,58 +2247,66 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, if (index == -1) { #ifdef DEBUG - fprintf(stderr, "%s: selection [%s] will not be handled by the clipboard code\n", __func__, NameForLocalAtom(pCurSel->selection)); + fprintf(stderr, "%s: selection [%s] can/will not be handled by the clipboard code\n", __func__, NameForLocalAtom(pCurSel->selection)); #endif return; } /* - * Always invalidate the target cache for the relevant selection, - * even if the trap is set. This ensures not having invalid data in - * the cache. + * Always invalidate the target cache for the relevant selection. + * This ensures not having invalid data in the cache. */ invalidateTargetCache(index); - if (nxagentExternalClipboardEventTrap) - { - #ifdef DEBUG - fprintf(stderr, "%s: Trap is set, doing nothing\n", __func__); - #endif - return; - } - - #ifdef DEBUG + fprintf(stderr, "%s: pCurSel->window [0x%x]\n", __func__, pCurSel->window); + fprintf(stderr, "%s: pCurSel->pWin [0x%x]\n", __func__, WINDOWID(pCurSel->pWin)); + fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForLocalAtom(pCurSel->selection)); fprintf(stderr, "%s: pCurSel->lastTimeChanged [%u]\n", __func__, pCurSel->lastTimeChanged.milliseconds); + fprintf(stderr, "%s: pCurSel->client [%s]\n", __func__, nxagentClientInfoString(pCurSel->client)); #endif - if (info->kind == SelectionSetOwner) + if (nxagentOption(Clipboard) != ClipboardNone) /* FIXME: shouldn't we also check for != ClipboardClient? */ { - #ifdef DEBUG - fprintf(stderr, "%s: pCurSel->pWin [0x%x]\n", __func__, WINDOWID(pCurSel->pWin)); - fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForLocalAtom(pCurSel->selection)); - #endif + Selection *pSel = NULL; + Selection nullSel = { + .client = NullClient, + .window = None, + .pWin = NULL, + .selection = pCurSel->selection, + .lastTimeChanged = pCurSel->lastTimeChanged + }; + + if (info->kind == SelectionSetOwner) + { + pSel = pCurSel; + } + else if (info->kind == SelectionWindowDestroy) + { + if (pCurSel->window == lastSelectionOwner[index].window) + { + pSel = &nullSel; + } + } + else if (info->kind == SelectionClientClose) + { + if (pCurSel->client == lastSelectionOwner[index].client) + { + pSel = &nullSel; + } + } + else + { + } - if (pCurSel->pWin != NULL && - nxagentOption(Clipboard) != ClipboardNone && /* FIXME: shouldn't we also check for != ClipboardClient? */ - (pCurSel->selection == localSelelectionAtoms[nxagentPrimarySelection] || - pCurSel->selection == localSelelectionAtoms[nxagentClipboardSelection])) + if (pSel) { #ifdef DEBUG fprintf(stderr, "%s: calling setSelectionOwnerOnXServer\n", __func__); #endif - setSelectionOwnerOnXServer(pCurSel); + setSelectionOwnerOnXServer(pSel); } } - else if (info->kind == SelectionWindowDestroy) - { - } - else if (info->kind == SelectionClientClose) - { - } - else - { - } } #endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h index aca8d94af..4518595d1 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h @@ -57,11 +57,14 @@ extern void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow); extern int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, Window requestor, Atom property, Atom target, Time time); +extern void nxagentHandleSelectionClearFromXServerByIndex(int index); #ifdef XEvent +extern void nxagentHandleSelectionClearFromXServerByAtom(XlibAtom sel); extern void nxagentHandleSelectionClearFromXServer(XEvent *X); extern void nxagentHandleSelectionRequestFromXServer(XEvent *X); extern void nxagentHandleSelectionNotifyFromXServer(XEvent *X); #else +extern void nxagentHandleSelectionClearFromXServerByAtom(); extern void nxagentHandleSelectionClearFromXServer(); extern void nxagentHandleSelectionRequestFromXServer(); extern void nxagentHandleSelectionNotifyFromXServer(); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 906915ad0..a678e3841 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2841,69 +2841,64 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) return 0; } + #ifdef DEBUG + fprintf(stderr, "---------\n"); + #endif + #ifdef TEST fprintf(stderr, "%s: Handling event.\n", __func__); #endif - if (SelectionCallback) - { - Atom local = nxagentRemoteToLocalAtom(xfixesEvent -> xfixesselection.selection); - - int index = nxagentFindCurrentSelectionIndex(local); - if (index != -1) - { - if (CurrentSelections[index].client != 0) - { - #ifdef TEST - fprintf(stderr, "%s: Doing nothing.\n", __func__); - #endif - - return 1; - } - - #ifdef TEST - fprintf(stderr, "%s: Calling callbacks for %d [%s] selection.\n", __func__, - CurrentSelections[index].selection, NameForAtom(CurrentSelections[index].selection)); - #endif + #ifdef DEBUG + fprintf(stderr, "%s: Event timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.timestamp); + fprintf(stderr, "%s: Event selection timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.selection_timestamp); + fprintf(stderr, "%s: Event selection window [0x%lx]\n", __func__, xfixesEvent->xfixesselection.window); + fprintf(stderr, "%s: Event selection owner [0x%lx]\n", __func__, xfixesEvent->xfixesselection.owner); + fprintf(stderr, "%s: Event selection [%s]\n", __func__, NameForAtom(nxagentRemoteToLocalAtom(xfixesEvent->xfixesselection.selection))); - #ifdef DEBUG - fprintf(stderr, "%s: CurrentSelections[%d].lastTimeChanged [%u]\n", __func__, index, CurrentSelections[index].lastTimeChanged.milliseconds); - fprintf(stderr, "%s: Event timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.timestamp); - fprintf(stderr, "%s: Event selection timestamp [%ld]\n", __func__, xfixesEvent->xfixesselection.selection_timestamp); - fprintf(stderr, "%s: Event selection window [0x%lx]\n", __func__, xfixesEvent->xfixesselection.window); - fprintf(stderr, "%s: Event selection owner [0x%lx]\n", __func__, xfixesEvent->xfixesselection.owner); - fprintf(stderr, "%s: Event selection [%s]\n", __func__, NameForAtom(local)); + fprintf(stderr, "%s: Subtype ", __func__); - fprintf(stderr, "%s: Subtype ", __func__); + switch (xfixesEvent -> xfixesselection.subtype) + { + case SelectionSetOwner: fprintf(stderr, "SelectionSetOwner.\n"); break; + case SelectionWindowDestroy: fprintf(stderr, "SelectionWindowDestroy.\n"); break; + case SelectionClientClose: fprintf(stderr, "SelectionClientClose.\n"); break; + default: fprintf(stderr, ".\n"); break; + } + #endif - switch (xfixesEvent -> xfixesselection.subtype) - { - case SelectionSetOwner: fprintf(stderr, "SelectionSetOwner.\n"); break; - case SelectionWindowDestroy: fprintf(stderr, "SelectionWindowDestroy.\n"); break; - case SelectionClientClose: fprintf(stderr, "SelectionClientClose.\n"); break; - default: fprintf(stderr, ".\n"); break; - } - #endif + if (xfixesEvent->xfixesselection.owner && xfixesEvent->xfixesselection.owner == nxagentWindow(screenInfo.screens[0]->root)) + { + /* + * This is an event that must have been triggered by nxagent itself + * - by calling XSetSelectionOwner(). As this is no news for us we + * can ignore the event. + */ - SelectionInfoRec info = { - .selection = &CurrentSelections[index], - .kind = xfixesEvent->xfixesselection.subtype - }; + #ifdef DEBUG + fprintf(stderr, "%s: (new) owner is nxagent (window is [0x%lx]) - ignoring it.\n", __func__, xfixesEvent->xfixesselection.window); + #endif + return 0; + } - /* - * The trap indicates that we are triggered by a clipboard event - * originating from the real X server. In that case we do not - * want to propagate back changes to the real X server, because - * it already knows about them and we would end up in an - * infinite loop of events. If there was a better way to - * identify that situation during Callback processing we could - * get rid of the Trap... - */ - nxagentExternalClipboardEventTrap = True; - CallCallbacks(&SelectionCallback, &info); - nxagentExternalClipboardEventTrap = False; - } + if (xfixesEvent -> xfixesselection.subtype == SelectionSetOwner|| + xfixesEvent -> xfixesselection.subtype == SelectionWindowDestroy || + xfixesEvent -> xfixesselection.subtype == SelectionClientClose) + { + /* + * Reception of an owner change on the real X server is - for nxagent - the same as + * receiving a SelectionClear event. We just need to tell a (possible) internal + * owner that is no longer owning the selection. + */ + nxagentHandleSelectionClearFromXServerByAtom(xfixesEvent -> xfixesselection.selection); + } + else + { + #ifdef DEBUG + fprintf(stderr, "%s: WARNING unexpected xfixesselection subtype [%d]\n", __func__, xfixesEvent -> xfixesselection.subtype); + #endif } + return 1; } diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.c b/nx-X11/programs/Xserver/hw/nxagent/Trap.c index 6eade2073..c0a1fdde0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Trap.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.c @@ -103,11 +103,3 @@ Bool nxagentXkbCapsTrap = False; */ Bool nxagentXkbNumTrap = False; - -/* - * Set to indicate we are processing a clipboard event triggered by - * the real X server. This is used to avoid endless loops if callbacks - * would trigger another event by the real X server - */ - -Bool nxagentExternalClipboardEventTrap = False; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.h b/nx-X11/programs/Xserver/hw/nxagent/Trap.h index 1c10f00ea..02ad48f99 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Trap.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.h @@ -101,11 +101,4 @@ extern Bool nxagentXkbCapsTrap; */ extern Bool nxagentXkbNumTrap; -/* - * Set to indicate we are processing a clipboard event triggered by - * the real X server. This is used to avoid endless loops if callbacks - * would trigger another event by the real X server - */ -extern Bool nxagentExternalClipboardEventTrap; - #endif /* __Trap_H__ */ -- cgit v1.2.3 From 5da2be394a3961c7a6d96a3e117ffc434fe34827 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 20 Jun 2021 13:15:12 +0200 Subject: Events.c: add another comment --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index a678e3841..0340e0b57 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2881,6 +2881,11 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) return 0; } + /* + * Realistically the only situation where we can receive + * WindowDestroy or ClientClose will also end nxagent, so we do not + * need to handle them. But the code is here, so let's keep it. + */ if (xfixesEvent -> xfixesselection.subtype == SelectionSetOwner|| xfixesEvent -> xfixesselection.subtype == SelectionWindowDestroy || xfixesEvent -> xfixesselection.subtype == SelectionClientClose) -- cgit v1.2.3 From 9874023096b1940ef3df0756a0ec81d5d57e09c2 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 20 Jun 2021 13:16:29 +0200 Subject: Clipboard.c: check for invalid index We only need to check this in nxagentHandleSelectionClearFromXServerByIndex, so we can simplify nxagentHandleSelectionClearFromXServerByAtom. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 4a0bf9cb5..3b08c1133 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -882,6 +882,14 @@ void nxagentHandleSelectionClearFromXServerByIndex(int index) fprintf(stderr, "%s: SelectionClear event for selection index [%u].\n", __func__, index); #endif + if (index == -1) + { + #ifdef DEBUG + fprintf(stderr, "%s: ignoring index -1 - doing nothing.\n", __func__); + #endif + return; + } + if (!agentClipboardInitialized) { #ifdef DEBUG @@ -931,11 +939,7 @@ void nxagentHandleSelectionClearFromXServerByAtom(XlibAtom sel) fprintf(stderr, "---------\n%s: SelectionClear event for remote selection atom [%lu][%s].\n", __func__, sel, NameForRemoteAtom(sel)); #endif - int index = nxagentFindRemoteSelectionIndex(sel); - if (index != -1) - { - nxagentHandleSelectionClearFromXServerByIndex(index); - } + nxagentHandleSelectionClearFromXServerByIndex(nxagentFindRemoteSelectionIndex(sel)); } void nxagentHandleSelectionClearFromXServer(XEvent *X) -- cgit v1.2.3 From 8264b03e8df725c475e43faf34a681a199f6fa7e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 21 Jun 2021 23:14:25 +0200 Subject: Clipboard.c: Add debug output when selection is already cleared --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 3b08c1133..72ca6ac64 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -931,6 +931,12 @@ void nxagentHandleSelectionClearFromXServerByIndex(int index) invalidateTargetCache(index); } + else + { + #ifdef DEBUG + fprintf(stderr, "%s: selection already cleared - doing nothing.\n", __func__); + #endif + } } void nxagentHandleSelectionClearFromXServerByAtom(XlibAtom sel) -- cgit v1.2.3 From 46b75d81879d9b0c769230e4c3757698ad5de8b5 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Sat, 11 Sep 2021 20:43:55 +0000 Subject: debian/control: Add B-D: libtirpc-dev. --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index 00527d63e..d74f9e175 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Build-Depends: libjpeg-dev, libpixman-1-dev (>= 0.13.2), libpng-dev, + libtirpc-dev | hello, libtool, libxcomposite-dev, libxdamage-dev, -- cgit v1.2.3 From 31057d00b8cdbe97837f508c3cb0f2c521a30266 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Sat, 11 Sep 2021 20:45:16 +0000 Subject: debian/rules: Define -DUseTIRPC=1 for nx-X11 build on Debian and Ubuntu versions that already have libtirpc. --- debian/rules | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/debian/rules b/debian/rules index 9bfee93fd..3ca425f76 100755 --- a/debian/rules +++ b/debian/rules @@ -12,6 +12,44 @@ export LIBDIR = "/usr/lib/$(DEB_HOST_MULTIARCH)" export LIBEXECDIR = "$(LIBDIR)/nx/bin" export INCLUDEDIR = "/usr/include/$(DEB_HOST_MULTIARCH)" +VENDOR_DEBIAN := 0 +RELEASE_VER := 0 + +# detect VENDOR_* variables and RELEASE_VER{,_MAJOR,_MINOR} +VENDOR_DEBIAN := $(shell { dpkg-vendor --is 'Debian' && echo 'yes'; } || { dpkg-vendor --is 'Raspbian' && echo 'yes'; }) + +ifeq ($(VENDOR_DEBIAN),yes) + RELEASE_VER := $(shell /usr/bin/lsb_release -r | cut -d ':' -f'2' | sed -e 's/\s*//g' | cut -d '.' -f'1') + # Let's fake testing's and unstable's "release version"... + ifeq ($(RELEASE_VER),testing) + RELEASE_VER := 999 + endif + ifeq ($(RELEASE_VER),unstable) + RELEASE_VER := 9999 + endif +else + VENDOR_UBUNTU := $(shell dpkg-vendor --is 'Ubuntu' && echo 'yes') + + ifeq ($(VENDOR_UBUNTU),yes) + RELEASE_VER_MAJOR := $(shell lsb_release -r | cut -d ':' -f '2' | sed -e 's/\s*//g' | cut -d '.' -f '1') + RELEASE_VER_MINOR := $(shell lsb_release -r | cut -d ':' -f '2' | sed -e 's/\s*//g' | cut -d '.' -f '2') + endif +endif + +# detect when to use libtirpc and when glibc still provides rpc/rpc.h +IMAKE_EXTRA_DEFINES := "" +ifeq ($(VENDOR_DEBIAN),yes) + ifeq ($(shell /bin/bash -c '(( $(RELEASE_VER) >= 10 )) && echo '"'"'yes'"'"),yes) + IMAKE_EXTRA_DEFINES+="-DUseTIRPC=1" + endif +else + ifeq ($(VENDOR_UBUNTU),yes) + ifeq ($(shell /bin/bash -c '(( $(RELEASE_VER_MAJOR) >= 18 )) && echo '"'"'yes'"'"),yes) + IMAKE_EXTRA_DEFINES+="-DUseTIRPC=1" + endif + endif +endif + %: CONFIGURE="./configure --disable-silent-rules \ --prefix=/usr \ @@ -59,8 +97,8 @@ override_dh_auto_install: override_dh_auto_build: debian/compat.sh - PREFIX='/usr' dh_auto_build --no-parallel -- CDEBUGFLAGS="$(CPPFLAGS) $(CFLAGS)" LOCAL_LDFLAGS="$(LDFLAGS)" SHLIBGLOBALSFLAGS='$(filter-out -pie,$(LDFLAGS))' || \ - PREFIX='/usr' dh_auto_build -- CDEBUGFLAGS="$(CPPFLAGS) $(CFLAGS)" LOCAL_LDFLAGS="$(LDFLAGS)" SHLIBGLOBALSFLAGS='$(filter-out -pie,$(LDFLAGS))' + PREFIX='/usr' dh_auto_build --no-parallel -- CDEBUGFLAGS="$(CPPFLAGS) $(CFLAGS)" LOCAL_LDFLAGS="$(LDFLAGS)" SHLIBGLOBALSFLAGS='$(filter-out -pie,$(LDFLAGS))' IMAKE_DEFINES="$(IMAKE_EXTRA_DEFINES)" || \ + PREFIX='/usr' dh_auto_build -- CDEBUGFLAGS="$(CPPFLAGS) $(CFLAGS)" LOCAL_LDFLAGS="$(LDFLAGS)" SHLIBGLOBALSFLAGS='$(filter-out -pie,$(LDFLAGS))' IMAKE_DEFINES="$(IMAKE_EXTRA_DEFINES)" override_dh_strip: dh_strip -plibnx-x11-6 --dbg-package=libnx-x11-6-dbg -- cgit v1.2.3