Unverified Commit c0754a35 authored by Mike Gabriel's avatar Mike Gabriel

Merge branch 'uli42-pr/use_selection_callback' into 3.6.x

parents 58cd3574 848dee5c
......@@ -919,7 +919,6 @@ ProcGetAtomName(register ClientPtr client)
}
}
#ifndef NXAGENT_SERVER
int
ProcSetSelectionOwner(register ClientPtr client)
{
......@@ -1014,7 +1013,6 @@ ProcSetSelectionOwner(register ClientPtr client)
return (BadAtom);
}
}
#endif /* NXAGENT_SERVER */
int
ProcGetSelectionOwner(register ClientPtr client)
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -678,112 +678,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);
}
#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
{
client->errorValue = stuff->selection;
return (BadAtom);
}
}
int
ProcConvertSelection(register ClientPtr client)
{
Bool paramsOkay;
......
......@@ -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;
......@@ -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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment