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(+) (limited to 'nx-X11') 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