From 3fd7e5f93fe0cc3198c5cc2fb5da9635b849c5be Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 10 Jun 2019 14:18:06 +0200 Subject: Add nxagentExternalClipboardEventTrap --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 12 ++++++++++++ nx-X11/programs/Xserver/hw/nxagent/Trap.c | 8 ++++++++ nx-X11/programs/Xserver/hw/nxagent/Trap.h | 8 ++++++++ 3 files changed, 28 insertions(+) (limited to 'nx-X11/programs/Xserver/hw/nxagent') diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 7ec97dada..4bddbba3a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -2968,7 +2968,19 @@ int nxagentHandleXFixesSelectionNotify(XEvent *X) info.selection = &CurrentSelections[i]; info.kind = xfixesEvent->xfixesselection.subtype; + + /* + * 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 = 1; CallCallbacks(&SelectionCallback, &info); + nxagentExternalClipboardEventTrap = 0; } } return 1; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.c b/nx-X11/programs/Xserver/hw/nxagent/Trap.c index c582f6a16..f219bb43c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Trap.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.c @@ -120,3 +120,11 @@ int nxagentXkbCapsTrap = 0; int nxagentXkbNumTrap = 0; + +/* + * 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 + */ + +int nxagentExternalClipboardEventTrap = 0; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.h b/nx-X11/programs/Xserver/hw/nxagent/Trap.h index f0884f657..9f0c055c8 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Trap.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.h @@ -121,4 +121,12 @@ extern int nxagentXkbCapsTrap; extern int 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 int nxagentExternalClipboardEventTrap; + #endif /* __Trap_H__ */ -- cgit v1.2.3 From 2972f6af1b63f4e98aa4504a83f756b8486c7df0 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 10 Jun 2019 14:20:47 +0200 Subject: Add nxagentSetSelectionCallback --- nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 69 ++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'nx-X11/programs/Xserver/hw/nxagent') diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c index 824c1dc47..9c518801b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -1257,6 +1257,75 @@ void nxagentResetSelectionOwner(void) return; } +#ifdef NXAGENT_CLIPBOARD +void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, + void *args) +{ + /* + * Only act if the Trap is unset. 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... + */ + if (nxagentExternalClipboardEventTrap != 0) + { + #ifdef DEBUG + fprintf(stderr, "%s: Trap is set, doing nothing\n", __func__); + #endif + return; + } + + SelectionInfoRec *info = (SelectionInfoRec *)args; + + Selection * pCurSel = (Selection *)info->selection; + + #ifdef DEBUG + fprintf(stderr, "%s: pCurSel->lastTimeChanged [%d]\n", __func__, pCurSel->lastTimeChanged.milliseconds); + #endif + + if (info->kind == SelectionSetOwner) + { + #ifdef DEBUG + fprintf(stderr, "%s: called with SelectionCallbackKind SelectionSetOwner\n", __func__); + fprintf(stderr, "%s: pCurSel->pWin [0x%x]\n", __func__, pCurSel->pWin ? pCurSel->pWin->drawable.id : NULL); + fprintf(stderr, "%s: pCurSel->selection [%s]\n", __func__, NameForAtom(pCurSel->selection)); + #endif + + if ((pCurSel->pWin != NULL) && + (nxagentOption(Clipboard) != ClipboardNone) && + ((pCurSel->selection == XA_PRIMARY) || + (pCurSel->selection == MakeAtom("CLIPBOARD", 9, 0)))) + { + #ifdef DEBUG + fprintf(stderr, "%s: calling nxagentSetSelectionOwner\n", __func__); + #endif + nxagentSetSelectionOwner(pCurSel); + } + } + 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 + void nxagentSetSelectionOwner(Selection *pSelection) { #ifdef DEBUG -- cgit v1.2.3 From 09ba97b2d0ff3e2f8203679480fe5a54020637b2 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 10 Jun 2019 14:21:43 +0200 Subject: NXdispatch.c: Use Callback instead of a modified function --- nx-X11/programs/Xserver/hw/nxagent/Init.c | 9 +++++++++ nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'nx-X11/programs/Xserver/hw/nxagent') diff --git a/nx-X11/programs/Xserver/hw/nxagent/Init.c b/nx-X11/programs/Xserver/hw/nxagent/Init.c index 80ca5fac1..1e24a618e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Init.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Init.c @@ -143,6 +143,11 @@ void OsVendorEndRedirectErrorFFunction(); static void nxagentGrabServerCallback(CallbackListPtr *callbacks, void *data, void *args); +#ifdef NXAGENT_CLIPBOARD +extern void nxagentSetSelectionCallback(CallbackListPtr *callbacks, void *data, + void *args); +#endif + void ddxInitGlobals(void) { /* @@ -411,6 +416,10 @@ FIXME: These variables, if not removed at all because have probably blackRoot = TRUE; nxagentInitKeystrokes(False); + +#ifdef NXAGENT_CLIPBOARD + AddCallback(&SelectionCallback, nxagentSetSelectionCallback, NULL); +#endif } void diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c index db055f0cd..44194ff3b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -764,15 +764,6 @@ ProcSetSelectionOwner(register ClientPtr client) CallCallbacks(&SelectionCallback, &info); } -#ifdef NXAGENT_CLIPBOARD - if ((CurrentSelections[i].pWin != NULL) && - (nxagentOption(Clipboard) != ClipboardNone) && - ((CurrentSelections[i].selection == XA_PRIMARY) || - (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0)))) - { - nxagentSetSelectionOwner(&CurrentSelections[i]); - } -#endif return (client->noClientException); } else -- cgit v1.2.3 From 848dee5c42bffdf19c4b9f01c38334bf53fefa49 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Mon, 10 Jun 2019 14:25:53 +0200 Subject: NXdispatch.c: use upstream version of ProcSetSelectionOwner --- nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 97 ------------------------- 1 file changed, 97 deletions(-) (limited to 'nx-X11/programs/Xserver/hw/nxagent') diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c index 44194ff3b..339994e6c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -677,103 +677,6 @@ ProcQueryTree(register ClientPtr client) } -int -ProcSetSelectionOwner(register ClientPtr client) -{ - WindowPtr pWin; - TimeStamp time; - REQUEST(xSetSelectionOwnerReq); - - REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); - UpdateCurrentTime(); - time = ClientTimeToServerTime(stuff->time); - - /* If the client's time stamp is in the future relative to the server's - time stamp, do not set the selection, just return success. */ - if (CompareTimeStamps(time, currentTime) == LATER) - return Success; - if (stuff->window != None) - { - pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, - DixReadAccess); - if (!pWin) - return(BadWindow); - } - else - pWin = (WindowPtr)None; - if (ValidAtom(stuff->selection)) - { - int i = 0; - - /* - * First, see if the selection is already set... - */ - while ((i < NumCurrentSelections) && - CurrentSelections[i].selection != stuff->selection) - i++; - if (i < NumCurrentSelections) - { - /* If the timestamp in client's request is in the past relative - to the time stamp indicating the last time the owner of the - selection was set, do not set the selection, just return - success. */ - if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) - == EARLIER) - return Success; - if (CurrentSelections[i].client && - (!pWin || (CurrentSelections[i].client != client))) - { - xEvent event = {0}; - event.u.u.type = SelectionClear; - event.u.selectionClear.time = time.milliseconds; - event.u.selectionClear.window = CurrentSelections[i].window; - event.u.selectionClear.atom = CurrentSelections[i].selection; - (void) TryClientEvents (CurrentSelections[i].client, &event, 1, - NoEventMask, NoEventMask /* CantBeFiltered */, - NullGrab); - } - } - else - { - /* - * It doesn't exist, so add it... - */ - Selection *newsels; - - if (i == 0) - newsels = (Selection *)malloc(sizeof(Selection)); - else - newsels = (Selection *)realloc(CurrentSelections, - (NumCurrentSelections + 1) * sizeof(Selection)); - if (!newsels) - return BadAlloc; - NumCurrentSelections++; - CurrentSelections = newsels; - CurrentSelections[i].selection = stuff->selection; - } - CurrentSelections[i].lastTimeChanged = time; - CurrentSelections[i].window = stuff->window; - CurrentSelections[i].pWin = pWin; - CurrentSelections[i].client = (pWin ? client : NullClient); - if (SelectionCallback) - { - SelectionInfoRec info = {0}; - - info.selection = &CurrentSelections[i]; - info.kind= SelectionSetOwner; - CallCallbacks(&SelectionCallback, &info); - } - - return (client->noClientException); - } - else - { - client->errorValue = stuff->selection; - return (BadAtom); - } -} - - int ProcConvertSelection(register ClientPtr client) { -- cgit v1.2.3