aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Sibiller <uli42@gmx.de>2020-12-02 23:43:53 +0100
committerUlrich Sibiller <uli42@gmx.de>2021-06-20 20:12:51 +0200
commit51dae621fcfd6e6453657591205e673f16c2df04 (patch)
tree176e3df8b019da6d958ff622786f688644087a10
parent1fd98b193c3f4cadb227017bb3434d1fd2c37a13 (diff)
downloadnx-libs-51dae621fcfd6e6453657591205e673f16c2df04.tar.gz
nx-libs-51dae621fcfd6e6453657591205e673f16c2df04.tar.bz2
nx-libs-51dae621fcfd6e6453657591205e673f16c2df04.zip
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.
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Clipboard.c93
1 files 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]));