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