From 1d9ba187bcea7ba05a9c280a914eb6dc46e3113b Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 10 Nov 2021 23:18:28 +0100 Subject: Clipboard.c: re-add callbacks 7aa969cd4ee5fe6ecf74f82442e4a0a7491191c1 dropped calling the callbacks which was a mistake. However, this time we do it without an additional trap. Fixes ArcticaProject/nx-libs#1027 --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 62 ++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index f0cef595c..7e78c9758 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -377,6 +377,11 @@ static void printSelectionStat(int index) fprintf(stderr, " CurrentSelections[].client %s\n", nxagentClientInfoString(curSel.client)); fprintf(stderr, " CurrentSelections[].window [0x%x]\n", curSel.window); + if (curSel.pWin) + fprintf(stderr, " CurrentSelections[].pWin [%p] (-> [0x%x])\n", (void *)curSel.pWin, WINDOWID(curSel.pWin)); + else + fprintf(stderr, " CurrentSelections[].pWin -\n"); + fprintf(stderr, " CurrentSelections[].lastTimeChanged [%u]\n", curSel.lastTimeChanged.milliseconds); return; } @@ -906,12 +911,15 @@ void nxagentHandleSelectionClearFromXServerByIndex(int index) return; } + UpdateCurrentTime(); + TimeStamp time = ClientTimeToServerTime(CurrentTime); + 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.time = time.milliseconds; x.u.selectionClear.window = lastSelectionOwner[index].window; x.u.selectionClear.atom = CurrentSelections[index].selection; @@ -921,8 +929,11 @@ void nxagentHandleSelectionClearFromXServerByIndex(int index) * Set the root window with the NullClient as selection owner. Our * clients asking for the owner via XGetSelectionOwner() will get * this for an answer. + * Set the CurrentSelection data just as ProcSetSelectionOwner does. */ + CurrentSelections[index].lastTimeChanged = time; CurrentSelections[index].window = screenInfo.screens[0]->root->drawable.id; + CurrentSelections[index].pWin = NULL; CurrentSelections[index].client = NullClient; clearSelectionOwnerData(index); @@ -930,6 +941,22 @@ void nxagentHandleSelectionClearFromXServerByIndex(int index) setClientSelectionStage(index, SelectionStageNone); invalidateTargetCache(index); + + /* + * Now call the callbacks. This is important, especially for + * XFixes events to work properly. Keep in mind that this will + * also call our own callback so we must be prepared there to not + * communicate back to the real X server about this SelectionClear + * event. It already knows about that... + */ + if (SelectionCallback) + { + SelectionInfoRec info = {0}; + + info.selection = &CurrentSelections[index]; + info.kind = SelectionSetOwner; + CallCallbacks(&SelectionCallback, &info); + } } else { @@ -2268,20 +2295,34 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, return; } + #ifdef DEBUG + printSelectionStat(index); + #endif + + if (CurrentSelections[index].client == NullClient && + CurrentSelections[index].pWin == (WindowPtr)None && + CurrentSelections[index].window == screenInfo.screens[0]->root->drawable.id && + lastSelectionOwner[index].client == NullClient && + lastSelectionOwner[index].window == None && + lastSelectionOwner[index].windowPtr == NULL) + { + /* + * No need to propagate anything to the real X server because this + * callback was triggered by a SelectionClear from the real X + * server. See nxagentHandleSelectionClearFromXServer + */ + #ifdef DEBUG + fprintf(stderr, "%s: aborting callback because it was triggered by nxagent\n", __func__); + #endif + return; + } + /* * Always invalidate the target cache for the relevant selection. * This ensures not having invalid data in the cache. */ invalidateTargetCache(index); - #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 (nxagentOption(Clipboard) != ClipboardNone) /* FIXME: shouldn't we also check for != ClipboardClient? */ { Selection *pSel = NULL; @@ -2313,6 +2354,9 @@ void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, } else { + #ifdef WARNING + fprintf(stderr, "%s: WARNING: unknown kind [%d] - data corruption?\n", __func__, info->kind); + #endif } if (pSel) -- cgit v1.2.3 From a86957b9173ae5652323027fc9c1dab933648e3b Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 10 Nov 2021 23:40:55 +0100 Subject: Clipboard.c: fix typo in array name --- 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 7e78c9758..2e47709f7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -95,7 +95,7 @@ const int nxagentMaxSelections = 2; /* store the remote atom for all selections */ static XlibAtom *remoteSelectionAtoms = NULL; -static Atom *localSelelectionAtoms = NULL; +static Atom *localSelectionAtoms = NULL; /* * The real owner window (inside nxagent) is stored in @@ -364,7 +364,7 @@ static void printSelectionStat(int index) fprintf(stderr, "selection [%d]:\n", index); fprintf(stderr, " selection Atom local [%d][%s] remote [%ld][%s]\n", - localSelelectionAtoms[index], NameForLocalAtom(localSelelectionAtoms[index]), + localSelectionAtoms[index], NameForLocalAtom(localSelectionAtoms[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)); @@ -1465,7 +1465,7 @@ static void endTransfer(int index, Bool success) sendSelectionNotifyEventToClient(lastClients[index].clientPtr, lastClients[index].time, lastClients[index].requestor, - localSelelectionAtoms[index], + localSelectionAtoms[index], lastClients[index].target, success == SELECTION_SUCCESS ? lastClients[index].property : None); } @@ -2557,7 +2557,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, #endif #ifdef DEBUG - fprintf(stderr, "%s: localSelelectionAtoms[%d] [%d] - selection [%d]\n", __func__, index, localSelelectionAtoms[index], selection); + fprintf(stderr, "%s: localSelectionAtoms[%d] [%d] - selection [%d]\n", __func__, index, localSelectionAtoms[index], selection); #endif if ((GetTimeInMillis() - lastClients[index].reqTime) >= CONVERSION_TIMEOUT) @@ -2964,7 +2964,7 @@ XlibAtom translateLocalToRemoteSelection(Atom local) for (int index = 0; index < nxagentMaxSelections; index++) { - if (local == localSelelectionAtoms[index]) + if (local == localSelectionAtoms[index]) { remote = remoteSelectionAtoms[index]; break; @@ -3166,7 +3166,7 @@ WindowPtr nxagentGetClipboardWindow(Atom property) { #ifdef DEBUG fprintf(stderr, "%s: Returning last [%d] selection owner window [%p] (0x%x).\n", __func__, - localSelelectionAtoms[index], + localSelectionAtoms[index], (void *)lastSelectionOwner[index].windowPtr, WINDOWID(lastSelectionOwner[index].windowPtr)); #endif @@ -3244,14 +3244,14 @@ Bool nxagentInitClipboard(WindowPtr pWin) FatalError("nxagentInitClipboard: Failed to allocate memory for the last servers array.\n"); } - SAFE_free(localSelelectionAtoms); - localSelelectionAtoms = (Atom *) calloc(nxagentMaxSelections, sizeof(Atom)); - if (localSelelectionAtoms == NULL) + SAFE_free(localSelectionAtoms); + localSelectionAtoms = (Atom *) calloc(nxagentMaxSelections, sizeof(Atom)); + if (localSelectionAtoms == NULL) { FatalError("nxagentInitClipboard: Failed to allocate memory for the local selection Atoms array.\n"); } - localSelelectionAtoms[nxagentPrimarySelection] = XA_PRIMARY; - localSelelectionAtoms[nxagentClipboardSelection] = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); + localSelectionAtoms[nxagentPrimarySelection] = XA_PRIMARY; + localSelectionAtoms[nxagentClipboardSelection] = MakeAtom(szAgentCLIPBOARD, strlen(szAgentCLIPBOARD), True); SAFE_free(remoteSelectionAtoms); remoteSelectionAtoms = (XlibAtom *) calloc(nxagentMaxSelections, sizeof(XlibAtom)); -- cgit v1.2.3 From 7b22b2d40d2d5012d07059579ceeb9f0b8dcf041 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 10 Nov 2021 23:53:06 +0100 Subject: Clipboard.c: use a TimeStamp datatype for lastTimeChanged as dix does just to be consistent with dix. --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 2e47709f7..fe0267ab5 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -109,7 +109,7 @@ typedef struct _SelectionOwner ClientPtr client; /* local client */ Window window; /* local window id */ WindowPtr windowPtr; /* local window struct */ - Time lastTimeChanged; /* local time (server time) */ + TimeStamp lastTimeChanged; /* local time (server time) */ } SelectionOwner; /* @@ -373,7 +373,7 @@ static void printSelectionStat(int index) 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); + fprintf(stderr, " lastSelectionOwner[].lastTimeChanged [%u]\n", lOwner.lastTimeChanged.milliseconds); fprintf(stderr, " CurrentSelections[].client %s\n", nxagentClientInfoString(curSel.client)); fprintf(stderr, " CurrentSelections[].window [0x%x]\n", curSel.window); @@ -697,7 +697,7 @@ static void initSelectionOwnerData(int index) lastSelectionOwner[index].client = NullClient; lastSelectionOwner[index].window = screenInfo.screens[0]->root->drawable.id; lastSelectionOwner[index].windowPtr = NULL; - lastSelectionOwner[index].lastTimeChanged = GetTimeInMillis(); + lastSelectionOwner[index].lastTimeChanged = ClientTimeToServerTime(CurrentTime); } /* there's no owner on nxagent side anymore */ @@ -706,7 +706,7 @@ static void clearSelectionOwnerData(int index) lastSelectionOwner[index].client = NullClient; lastSelectionOwner[index].window = None; lastSelectionOwner[index].windowPtr = NULL; - lastSelectionOwner[index].lastTimeChanged = GetTimeInMillis(); + lastSelectionOwner[index].lastTimeChanged = ClientTimeToServerTime(CurrentTime); } static void storeSelectionOwnerData(int index, Selection *sel) @@ -714,7 +714,7 @@ static void storeSelectionOwnerData(int index, Selection *sel) lastSelectionOwner[index].client = sel->client; lastSelectionOwner[index].window = sel->window; lastSelectionOwner[index].windowPtr = sel->pWin; - lastSelectionOwner[index].lastTimeChanged = GetTimeInMillis(); + lastSelectionOwner[index].lastTimeChanged = ClientTimeToServerTime(CurrentTime); } static Bool matchSelectionOwner(int index, ClientPtr pClient, WindowPtr pWindow) @@ -2394,16 +2394,7 @@ static void setSelectionOwnerOnXServer(Selection *pSelection) } #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); + printSelectionStat(index); #endif -- cgit v1.2.3 From ce978228048bd67707a7600581cb2eebeae4d0bb Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 11 Nov 2021 00:12:07 +0100 Subject: Events.c: fix typo in comment --- 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 0340e0b57..7cadb987b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2893,7 +2893,7 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) /* * 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. + * owner that it is no longer owning the selection. */ nxagentHandleSelectionClearFromXServerByAtom(xfixesEvent -> xfixesselection.selection); } -- cgit v1.2.3 From 5ec4d7b8ae0c50ef5f7463f4d622597ab9fb37bc Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 15 Nov 2021 10:48:47 +0100 Subject: Clipboard.c: fix some comments --- 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 fe0267ab5..a45cab01e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -877,8 +877,9 @@ 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 we have/had. + * SelectionClear or XFixes selection event from the real X + * server. We receive this event if someone on the real X server + * claims the selection ownership we have/had. * Three versions of this routine with different parameter types. */ void nxagentHandleSelectionClearFromXServerByIndex(int index) @@ -1144,7 +1145,7 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X) * 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. + * occurred we can answer with the cached list of targets. */ if (targetCache[index].type == FOR_REMOTE && targetCache[index].forRemote) @@ -2642,7 +2643,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, * 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. + * occurred we can answer with the cached list of targets. */ if (targetCache[index].type == FOR_LOCAL && targetCache[index].forLocal) -- cgit v1.2.3 From a8d7b0c8c68d95e465fc05a1f49cfff4e969a0f5 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Wed, 10 Nov 2021 22:32:47 +0100 Subject: NXdispatch.c: use defined value CurrentTime instead of 0 also add another comment. --- nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c index 5df008bbb..cd57182a1 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -215,14 +215,16 @@ InitSelections(void) NumCurrentSelections += nxagentMaxSelections; CurrentSelections = newsels; + /* Note: these are the same values that will be set on a SelectionClear event */ + CurrentSelections[nxagentPrimarySelection].selection = XA_PRIMARY; - CurrentSelections[nxagentPrimarySelection].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[nxagentPrimarySelection].lastTimeChanged = ClientTimeToServerTime(CurrentTime); CurrentSelections[nxagentPrimarySelection].window = screenInfo.screens[0]->root->drawable.id; CurrentSelections[nxagentPrimarySelection].pWin = NULL; CurrentSelections[nxagentPrimarySelection].client = NullClient; CurrentSelections[nxagentClipboardSelection].selection = MakeAtom("CLIPBOARD", 9, 1); - CurrentSelections[nxagentClipboardSelection].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[nxagentClipboardSelection].lastTimeChanged = ClientTimeToServerTime(CurrentTime); CurrentSelections[nxagentClipboardSelection].window = screenInfo.screens[0]->root->drawable.id; CurrentSelections[nxagentClipboardSelection].pWin = NULL; CurrentSelections[nxagentClipboardSelection].client = NullClient; -- cgit v1.2.3