dix: Refactoring of selection code to allow for polyinstantiation.
Introduces dixLookupSelection() API. Removes NumCurrentSelections from API.
This commit is contained in:
parent
d5715f7bea
commit
34bf308a9e
|
@ -967,8 +967,6 @@ SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
||||||
|
|
||||||
switch (rec->kind) {
|
switch (rec->kind) {
|
||||||
case SelectionSetOwner:
|
case SelectionSetOwner:
|
||||||
case SelectionGetOwner:
|
|
||||||
case SelectionConvertSelection:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ libdix_la_SOURCES = \
|
||||||
property.c \
|
property.c \
|
||||||
registry.c \
|
registry.c \
|
||||||
resource.c \
|
resource.c \
|
||||||
|
selection.c \
|
||||||
swaprep.c \
|
swaprep.c \
|
||||||
swapreq.c \
|
swapreq.c \
|
||||||
tables.c \
|
tables.c \
|
||||||
|
|
274
dix/dispatch.c
274
dix/dispatch.c
|
@ -165,10 +165,6 @@ typedef const char *string;
|
||||||
extern xConnSetupPrefix connSetupPrefix;
|
extern xConnSetupPrefix connSetupPrefix;
|
||||||
extern char *ConnectionInfo;
|
extern char *ConnectionInfo;
|
||||||
|
|
||||||
_X_EXPORT Selection *CurrentSelections;
|
|
||||||
_X_EXPORT int NumCurrentSelections;
|
|
||||||
CallbackListPtr SelectionCallback = NULL;
|
|
||||||
|
|
||||||
static ClientPtr grabClient;
|
static ClientPtr grabClient;
|
||||||
#define GrabNone 0
|
#define GrabNone 0
|
||||||
#define GrabActive 1
|
#define GrabActive 1
|
||||||
|
@ -181,8 +177,6 @@ extern int connBlockScreenStart;
|
||||||
|
|
||||||
static void KillAllClients(void);
|
static void KillAllClients(void);
|
||||||
|
|
||||||
static void DeleteClientFromAnySelections(ClientPtr client);
|
|
||||||
|
|
||||||
static int nextFreeClientID; /* always MIN free client ID */
|
static int nextFreeClientID; /* always MIN free client ID */
|
||||||
|
|
||||||
static int nClients; /* number of authorized clients */
|
static int nClients; /* number of authorized clients */
|
||||||
|
@ -246,14 +240,6 @@ UpdateCurrentTimeIf(void)
|
||||||
currentTime = systime;
|
currentTime = systime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
InitSelections(void)
|
|
||||||
{
|
|
||||||
if (CurrentSelections)
|
|
||||||
xfree(CurrentSelections);
|
|
||||||
CurrentSelections = (Selection *)NULL;
|
|
||||||
NumCurrentSelections = 0;
|
|
||||||
}
|
|
||||||
#ifdef SMART_SCHEDULE
|
#ifdef SMART_SCHEDULE
|
||||||
|
|
||||||
#undef SMART_DEBUG
|
#undef SMART_DEBUG
|
||||||
|
@ -372,7 +358,6 @@ Dispatch(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nextFreeClientID = 1;
|
nextFreeClientID = 1;
|
||||||
InitSelections();
|
|
||||||
nClients = 0;
|
nClients = 0;
|
||||||
|
|
||||||
clientReady = (int *) xalloc(sizeof(int) * MaxClients);
|
clientReady = (int *) xalloc(sizeof(int) * MaxClients);
|
||||||
|
@ -967,217 +952,6 @@ ProcGetAtomName(ClientPtr client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
ProcSetSelectionOwner(ClientPtr client)
|
|
||||||
{
|
|
||||||
WindowPtr pWin;
|
|
||||||
TimeStamp time;
|
|
||||||
int rc;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess);
|
|
||||||
if (rc != Success)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pWin = (WindowPtr)None;
|
|
||||||
if (ValidAtom(stuff->selection))
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
rc = XaceHookSelectionAccess(client, stuff->selection,
|
|
||||||
DixSetAttrAccess);
|
|
||||||
if (rc != Success)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, see if the selection is already set...
|
|
||||||
*/
|
|
||||||
while ((i < NumCurrentSelections) &&
|
|
||||||
CurrentSelections[i].selection != stuff->selection)
|
|
||||||
i++;
|
|
||||||
if (i < NumCurrentSelections)
|
|
||||||
{
|
|
||||||
xEvent event;
|
|
||||||
|
|
||||||
/* 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)))
|
|
||||||
{
|
|
||||||
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 *)xalloc(sizeof(Selection));
|
|
||||||
else
|
|
||||||
newsels = (Selection *)xrealloc(CurrentSelections,
|
|
||||||
(NumCurrentSelections + 1) * sizeof(Selection));
|
|
||||||
if (!newsels)
|
|
||||||
return BadAlloc;
|
|
||||||
NumCurrentSelections++;
|
|
||||||
CurrentSelections = newsels;
|
|
||||||
CurrentSelections[i].selection = stuff->selection;
|
|
||||||
CurrentSelections[i].devPrivates = NULL;
|
|
||||||
}
|
|
||||||
CurrentSelections[i].lastTimeChanged = time;
|
|
||||||
CurrentSelections[i].window = stuff->window;
|
|
||||||
CurrentSelections[i].pWin = pWin;
|
|
||||||
CurrentSelections[i].client = (pWin ? client : NullClient);
|
|
||||||
if (SelectionCallback)
|
|
||||||
{
|
|
||||||
SelectionInfoRec info;
|
|
||||||
|
|
||||||
info.selection = &CurrentSelections[i];
|
|
||||||
info.client = client;
|
|
||||||
info.kind= SelectionSetOwner;
|
|
||||||
CallCallbacks(&SelectionCallback, &info);
|
|
||||||
}
|
|
||||||
return (client->noClientException);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client->errorValue = stuff->selection;
|
|
||||||
return (BadAtom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ProcGetSelectionOwner(ClientPtr client)
|
|
||||||
{
|
|
||||||
REQUEST(xResourceReq);
|
|
||||||
|
|
||||||
REQUEST_SIZE_MATCH(xResourceReq);
|
|
||||||
if (ValidAtom(stuff->id))
|
|
||||||
{
|
|
||||||
int rc, i;
|
|
||||||
xGetSelectionOwnerReply reply;
|
|
||||||
|
|
||||||
rc = XaceHookSelectionAccess(client, stuff->id, DixGetAttrAccess);
|
|
||||||
if (rc != Success)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while ((i < NumCurrentSelections) &&
|
|
||||||
CurrentSelections[i].selection != stuff->id) i++;
|
|
||||||
reply.type = X_Reply;
|
|
||||||
reply.length = 0;
|
|
||||||
reply.sequenceNumber = client->sequence;
|
|
||||||
if (i < NumCurrentSelections) {
|
|
||||||
if (SelectionCallback) {
|
|
||||||
SelectionInfoRec info;
|
|
||||||
|
|
||||||
info.selection = &CurrentSelections[i];
|
|
||||||
info.client = client;
|
|
||||||
info.kind= SelectionGetOwner;
|
|
||||||
CallCallbacks(&SelectionCallback, &info);
|
|
||||||
}
|
|
||||||
reply.owner = CurrentSelections[i].window;
|
|
||||||
} else
|
|
||||||
reply.owner = None;
|
|
||||||
WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
|
|
||||||
return(client->noClientException);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client->errorValue = stuff->id;
|
|
||||||
return (BadAtom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ProcConvertSelection(ClientPtr client)
|
|
||||||
{
|
|
||||||
Bool paramsOkay;
|
|
||||||
xEvent event;
|
|
||||||
WindowPtr pWin;
|
|
||||||
REQUEST(xConvertSelectionReq);
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
REQUEST_SIZE_MATCH(xConvertSelectionReq);
|
|
||||||
rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
|
|
||||||
if (rc != Success)
|
|
||||||
return rc;
|
|
||||||
rc = XaceHookSelectionAccess(client, stuff->selection, DixReadAccess);
|
|
||||||
if (rc != Success)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target));
|
|
||||||
if (stuff->property != None)
|
|
||||||
paramsOkay &= ValidAtom(stuff->property);
|
|
||||||
if (paramsOkay)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while ((i < NumCurrentSelections) &&
|
|
||||||
CurrentSelections[i].selection != stuff->selection) i++;
|
|
||||||
if (i < NumCurrentSelections && CurrentSelections[i].window != None) {
|
|
||||||
if (SelectionCallback) {
|
|
||||||
SelectionInfoRec info;
|
|
||||||
|
|
||||||
info.selection = &CurrentSelections[i];
|
|
||||||
info.client = client;
|
|
||||||
info.kind= SelectionConvertSelection;
|
|
||||||
CallCallbacks(&SelectionCallback, &info);
|
|
||||||
}
|
|
||||||
event.u.u.type = SelectionRequest;
|
|
||||||
event.u.selectionRequest.time = stuff->time;
|
|
||||||
event.u.selectionRequest.owner = CurrentSelections[i].window;
|
|
||||||
event.u.selectionRequest.requestor = stuff->requestor;
|
|
||||||
event.u.selectionRequest.selection = stuff->selection;
|
|
||||||
event.u.selectionRequest.target = stuff->target;
|
|
||||||
event.u.selectionRequest.property = stuff->property;
|
|
||||||
if (TryClientEvents(
|
|
||||||
CurrentSelections[i].client, &event, 1, NoEventMask,
|
|
||||||
NoEventMask /* CantBeFiltered */, NullGrab))
|
|
||||||
return (client->noClientException);
|
|
||||||
}
|
|
||||||
event.u.u.type = SelectionNotify;
|
|
||||||
event.u.selectionNotify.time = stuff->time;
|
|
||||||
event.u.selectionNotify.requestor = stuff->requestor;
|
|
||||||
event.u.selectionNotify.selection = stuff->selection;
|
|
||||||
event.u.selectionNotify.target = stuff->target;
|
|
||||||
event.u.selectionNotify.property = None;
|
|
||||||
(void) TryClientEvents(client, &event, 1, NoEventMask,
|
|
||||||
NoEventMask /* CantBeFiltered */, NullGrab);
|
|
||||||
return (client->noClientException);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client->errorValue = stuff->property;
|
|
||||||
return (BadAtom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ProcGrabServer(ClientPtr client)
|
ProcGrabServer(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -3980,54 +3754,6 @@ SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
|
||||||
WriteEventsToClient (client, 1, (xEvent *)&rep);
|
WriteEventsToClient (client, 1, (xEvent *)&rep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
DeleteWindowFromAnySelections(WindowPtr pWin)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i< NumCurrentSelections; i++)
|
|
||||||
if (CurrentSelections[i].pWin == pWin)
|
|
||||||
{
|
|
||||||
if (SelectionCallback)
|
|
||||||
{
|
|
||||||
SelectionInfoRec info;
|
|
||||||
|
|
||||||
info.selection = &CurrentSelections[i];
|
|
||||||
info.kind = SelectionWindowDestroy;
|
|
||||||
CallCallbacks(&SelectionCallback, &info);
|
|
||||||
}
|
|
||||||
dixFreePrivates(CurrentSelections[i].devPrivates);
|
|
||||||
CurrentSelections[i].pWin = (WindowPtr)NULL;
|
|
||||||
CurrentSelections[i].window = None;
|
|
||||||
CurrentSelections[i].client = NullClient;
|
|
||||||
CurrentSelections[i].devPrivates = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
DeleteClientFromAnySelections(ClientPtr client)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i< NumCurrentSelections; i++)
|
|
||||||
if (CurrentSelections[i].client == client)
|
|
||||||
{
|
|
||||||
if (SelectionCallback)
|
|
||||||
{
|
|
||||||
SelectionInfoRec info;
|
|
||||||
|
|
||||||
info.selection = &CurrentSelections[i];
|
|
||||||
info.kind = SelectionWindowDestroy;
|
|
||||||
CallCallbacks(&SelectionCallback, &info);
|
|
||||||
}
|
|
||||||
dixFreePrivates(CurrentSelections[i].devPrivates);
|
|
||||||
CurrentSelections[i].pWin = (WindowPtr)NULL;
|
|
||||||
CurrentSelections[i].window = None;
|
|
||||||
CurrentSelections[i].client = NullClient;
|
|
||||||
CurrentSelections[i].devPrivates = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkClientException(ClientPtr client)
|
MarkClientException(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,6 +93,7 @@ Equipment Corporation.
|
||||||
#include "colormap.h"
|
#include "colormap.h"
|
||||||
#include "colormapst.h"
|
#include "colormapst.h"
|
||||||
#include "cursorstr.h"
|
#include "cursorstr.h"
|
||||||
|
#include "selection.h"
|
||||||
#include <X11/fonts/font.h>
|
#include <X11/fonts/font.h>
|
||||||
#include "opaque.h"
|
#include "opaque.h"
|
||||||
#include "servermd.h"
|
#include "servermd.h"
|
||||||
|
@ -346,6 +347,7 @@ main(int argc, char *argv[], char *envp[])
|
||||||
|
|
||||||
InitAtoms();
|
InitAtoms();
|
||||||
InitEvents();
|
InitEvents();
|
||||||
|
InitSelections();
|
||||||
InitGlyphCaching();
|
InitGlyphCaching();
|
||||||
if (!dixResetPrivates())
|
if (!dixResetPrivates())
|
||||||
FatalError("couldn't init private data storage");
|
FatalError("couldn't init private data storage");
|
||||||
|
|
|
@ -0,0 +1,306 @@
|
||||||
|
/************************************************************
|
||||||
|
|
||||||
|
Copyright 1987, 1989, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of The Open Group shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from The Open Group.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||||||
|
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted,
|
||||||
|
provided that the above copyright notice appear in all copies and that
|
||||||
|
both that copyright notice and this permission notice appear in
|
||||||
|
supporting documentation, and that the name of Digital not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||||
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||||||
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||||
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_DIX_CONFIG_H
|
||||||
|
#include <dix-config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "windowstr.h"
|
||||||
|
#include "dixstruct.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
#include "selection.h"
|
||||||
|
#include "xace.h"
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
* Selection Stuff
|
||||||
|
*
|
||||||
|
* dixLookupSelection
|
||||||
|
*
|
||||||
|
* Selections are global to the server. The list of selections should
|
||||||
|
* not be traversed directly. Instead, use the functions listed above.
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
_X_EXPORT Selection *CurrentSelections;
|
||||||
|
static int NumCurrentSelections;
|
||||||
|
CallbackListPtr SelectionCallback;
|
||||||
|
|
||||||
|
_X_EXPORT int
|
||||||
|
dixLookupSelection(Selection **result, Atom selectionName,
|
||||||
|
ClientPtr client, Mask access_mode)
|
||||||
|
{
|
||||||
|
Selection *pSel = NULL;
|
||||||
|
int i, rc = BadMatch;
|
||||||
|
client->errorValue = selectionName;
|
||||||
|
|
||||||
|
for (i = 0; i < NumCurrentSelections; i++)
|
||||||
|
if (CurrentSelections[i].selection == selectionName) {
|
||||||
|
pSel = CurrentSelections + i;
|
||||||
|
rc = XaceHookSelectionAccess(client, selectionName, access_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = pSel;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InitSelections(void)
|
||||||
|
{
|
||||||
|
Selection *pSel = CurrentSelections;
|
||||||
|
|
||||||
|
for (; pSel - CurrentSelections < NumCurrentSelections; pSel++)
|
||||||
|
dixFreePrivates(pSel->devPrivates);
|
||||||
|
|
||||||
|
xfree(CurrentSelections);
|
||||||
|
CurrentSelections = NULL;
|
||||||
|
NumCurrentSelections = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static _X_INLINE void
|
||||||
|
CallSelectionCallback(Selection *pSel, ClientPtr client,
|
||||||
|
SelectionCallbackKind kind)
|
||||||
|
{
|
||||||
|
SelectionInfoRec info = { pSel, client, kind };
|
||||||
|
CallCallbacks(&SelectionCallback, &info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DeleteWindowFromAnySelections(WindowPtr pWin)
|
||||||
|
{
|
||||||
|
Selection *pSel = CurrentSelections;
|
||||||
|
|
||||||
|
for (; pSel - CurrentSelections < NumCurrentSelections; pSel++)
|
||||||
|
if (pSel->pWin == pWin) {
|
||||||
|
CallSelectionCallback(pSel, NULL, SelectionWindowDestroy);
|
||||||
|
|
||||||
|
pSel->pWin = (WindowPtr)NULL;
|
||||||
|
pSel->window = None;
|
||||||
|
pSel->client = NullClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DeleteClientFromAnySelections(ClientPtr client)
|
||||||
|
{
|
||||||
|
Selection *pSel = CurrentSelections;
|
||||||
|
|
||||||
|
for (; pSel - CurrentSelections < NumCurrentSelections; pSel++)
|
||||||
|
if (pSel->client == client) {
|
||||||
|
CallSelectionCallback(pSel, NULL, SelectionClientClose);
|
||||||
|
|
||||||
|
pSel->pWin = (WindowPtr)NULL;
|
||||||
|
pSel->window = None;
|
||||||
|
pSel->client = NullClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcSetSelectionOwner(ClientPtr client)
|
||||||
|
{
|
||||||
|
WindowPtr pWin = NULL;
|
||||||
|
TimeStamp time;
|
||||||
|
Selection *pSel;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess);
|
||||||
|
if (rc != Success)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (!ValidAtom(stuff->selection)) {
|
||||||
|
client->errorValue = stuff->selection;
|
||||||
|
return BadAtom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, see if the selection is already set...
|
||||||
|
*/
|
||||||
|
rc = dixLookupSelection(&pSel, stuff->selection, client, DixSetAttrAccess);
|
||||||
|
|
||||||
|
if (rc == Success) {
|
||||||
|
xEvent event;
|
||||||
|
|
||||||
|
/* 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, pSel->lastTimeChanged) == EARLIER)
|
||||||
|
return Success;
|
||||||
|
if (pSel->client && (!pWin || (pSel->client != client)))
|
||||||
|
{
|
||||||
|
event.u.u.type = SelectionClear;
|
||||||
|
event.u.selectionClear.time = time.milliseconds;
|
||||||
|
event.u.selectionClear.window = pSel->window;
|
||||||
|
event.u.selectionClear.atom = pSel->selection;
|
||||||
|
TryClientEvents(pSel->client, &event, 1, NoEventMask,
|
||||||
|
NoEventMask /* CantBeFiltered */, NullGrab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rc == BadMatch)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* It doesn't exist, so add it...
|
||||||
|
*/
|
||||||
|
int size = (NumCurrentSelections + 1) * sizeof(Selection);
|
||||||
|
CurrentSelections = xrealloc(CurrentSelections, size);
|
||||||
|
if (!CurrentSelections) {
|
||||||
|
NumCurrentSelections = 0;
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
pSel = CurrentSelections + NumCurrentSelections;
|
||||||
|
pSel->selection = stuff->selection;
|
||||||
|
pSel->devPrivates = NULL;
|
||||||
|
pSel->next = NULL;
|
||||||
|
if (NumCurrentSelections > 0)
|
||||||
|
CurrentSelections[NumCurrentSelections - 1].next = pSel;
|
||||||
|
NumCurrentSelections++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
pSel->lastTimeChanged = time;
|
||||||
|
pSel->window = stuff->window;
|
||||||
|
pSel->pWin = pWin;
|
||||||
|
pSel->client = (pWin ? client : NullClient);
|
||||||
|
|
||||||
|
CallSelectionCallback(pSel, client, SelectionSetOwner);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcGetSelectionOwner(ClientPtr client)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
Selection *pSel;
|
||||||
|
xGetSelectionOwnerReply reply;
|
||||||
|
|
||||||
|
REQUEST(xResourceReq);
|
||||||
|
REQUEST_SIZE_MATCH(xResourceReq);
|
||||||
|
|
||||||
|
if (!ValidAtom(stuff->id)) {
|
||||||
|
client->errorValue = stuff->id;
|
||||||
|
return BadAtom;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.type = X_Reply;
|
||||||
|
reply.length = 0;
|
||||||
|
reply.sequenceNumber = client->sequence;
|
||||||
|
|
||||||
|
rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
|
||||||
|
if (rc == Success)
|
||||||
|
reply.owner = pSel->window;
|
||||||
|
else if (rc == BadMatch)
|
||||||
|
reply.owner = None;
|
||||||
|
else
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcConvertSelection(ClientPtr client)
|
||||||
|
{
|
||||||
|
Bool paramsOkay;
|
||||||
|
xEvent event;
|
||||||
|
WindowPtr pWin;
|
||||||
|
Selection *pSel;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
REQUEST(xConvertSelectionReq);
|
||||||
|
REQUEST_SIZE_MATCH(xConvertSelectionReq);
|
||||||
|
|
||||||
|
rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
|
||||||
|
if (rc != Success)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);
|
||||||
|
paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);
|
||||||
|
if (!paramsOkay) {
|
||||||
|
client->errorValue = stuff->property;
|
||||||
|
return BadAtom;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);
|
||||||
|
|
||||||
|
if (rc != Success && rc != BadMatch)
|
||||||
|
return rc;
|
||||||
|
else if (rc == Success && pSel->window != None) {
|
||||||
|
event.u.u.type = SelectionRequest;
|
||||||
|
event.u.selectionRequest.owner = pSel->window;
|
||||||
|
event.u.selectionRequest.time = stuff->time;
|
||||||
|
event.u.selectionRequest.requestor = stuff->requestor;
|
||||||
|
event.u.selectionRequest.selection = stuff->selection;
|
||||||
|
event.u.selectionRequest.target = stuff->target;
|
||||||
|
event.u.selectionRequest.property = stuff->property;
|
||||||
|
if (TryClientEvents(pSel->client, &event, 1, NoEventMask,
|
||||||
|
NoEventMask /* CantBeFiltered */, NullGrab))
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.u.u.type = SelectionNotify;
|
||||||
|
event.u.selectionNotify.time = stuff->time;
|
||||||
|
event.u.selectionNotify.requestor = stuff->requestor;
|
||||||
|
event.u.selectionNotify.selection = stuff->selection;
|
||||||
|
event.u.selectionNotify.target = stuff->target;
|
||||||
|
event.u.selectionNotify.property = None;
|
||||||
|
TryClientEvents(client, &event, 1, NoEventMask,
|
||||||
|
NoEventMask /* CantBeFiltered */, NullGrab);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
|
@ -92,9 +92,6 @@
|
||||||
extern int XkbDfltRepeatDelay, XkbDfltRepeatInterval;
|
extern int XkbDfltRepeatDelay, XkbDfltRepeatInterval;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern Selection *CurrentSelections;
|
|
||||||
extern int NumCurrentSelections;
|
|
||||||
|
|
||||||
/* DIX things */
|
/* DIX things */
|
||||||
|
|
||||||
_X_HIDDEN void *dixLookupTab[] = {
|
_X_HIDDEN void *dixLookupTab[] = {
|
||||||
|
@ -150,8 +147,6 @@ _X_HIDDEN void *dixLookupTab[] = {
|
||||||
SYMVAR(isItTimeToYield)
|
SYMVAR(isItTimeToYield)
|
||||||
SYMVAR(ClientStateCallback)
|
SYMVAR(ClientStateCallback)
|
||||||
SYMVAR(ServerGrabCallback)
|
SYMVAR(ServerGrabCallback)
|
||||||
SYMVAR(CurrentSelections)
|
|
||||||
SYMVAR(NumCurrentSelections)
|
|
||||||
/* dixfonts.c */
|
/* dixfonts.c */
|
||||||
SYMFUNC(CloseFont)
|
SYMFUNC(CloseFont)
|
||||||
SYMFUNC(FontToXError)
|
SYMFUNC(FontToXError)
|
||||||
|
@ -196,6 +191,9 @@ _X_HIDDEN void *dixLookupTab[] = {
|
||||||
SYMFUNC(dixLookupProperty)
|
SYMFUNC(dixLookupProperty)
|
||||||
SYMFUNC(ChangeWindowProperty)
|
SYMFUNC(ChangeWindowProperty)
|
||||||
SYMFUNC(dixChangeWindowProperty)
|
SYMFUNC(dixChangeWindowProperty)
|
||||||
|
/* selection.c */
|
||||||
|
SYMFUNC(dixLookupSelection)
|
||||||
|
SYMVAR(CurrentSelections)
|
||||||
/* extension.c */
|
/* extension.c */
|
||||||
SYMFUNC(AddExtension)
|
SYMFUNC(AddExtension)
|
||||||
SYMFUNC(AddExtensionAlias)
|
SYMFUNC(AddExtensionAlias)
|
||||||
|
|
|
@ -166,9 +166,6 @@ extern void SendErrorToClient(
|
||||||
XID /*resId*/,
|
XID /*resId*/,
|
||||||
int /*errorCode*/);
|
int /*errorCode*/);
|
||||||
|
|
||||||
extern void DeleteWindowFromAnySelections(
|
|
||||||
WindowPtr /*pWin*/);
|
|
||||||
|
|
||||||
extern void MarkClientException(
|
extern void MarkClientException(
|
||||||
ClientPtr /*client*/);
|
ClientPtr /*client*/);
|
||||||
|
|
||||||
|
@ -556,26 +553,6 @@ typedef struct {
|
||||||
int count;
|
int count;
|
||||||
} DeviceEventInfoRec;
|
} DeviceEventInfoRec;
|
||||||
|
|
||||||
/*
|
|
||||||
* SelectionCallback stuff
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern CallbackListPtr SelectionCallback;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SelectionSetOwner,
|
|
||||||
SelectionGetOwner,
|
|
||||||
SelectionConvertSelection,
|
|
||||||
SelectionWindowDestroy,
|
|
||||||
SelectionClientClose
|
|
||||||
} SelectionCallbackKind;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct _Selection *selection;
|
|
||||||
ClientPtr client;
|
|
||||||
SelectionCallbackKind kind;
|
|
||||||
} SelectionInfoRec;
|
|
||||||
|
|
||||||
/* strcasecmp.c */
|
/* strcasecmp.c */
|
||||||
#if NEED_STRCASECMP
|
#if NEED_STRCASECMP
|
||||||
#define strcasecmp xstrcasecmp
|
#define strcasecmp xstrcasecmp
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
|
|
||||||
#ifndef SELECTION_H
|
|
||||||
#define SELECTION_H 1
|
|
||||||
|
|
||||||
/***********************************************************
|
/***********************************************************
|
||||||
|
|
||||||
Copyright 1987, 1998 The Open Group
|
Copyright 1987, 1998 The Open Group
|
||||||
|
@ -49,10 +45,13 @@ SOFTWARE.
|
||||||
|
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
|
#ifndef SELECTION_H
|
||||||
|
#define SELECTION_H 1
|
||||||
|
|
||||||
#include "dixstruct.h"
|
#include "dixstruct.h"
|
||||||
#include "privates.h"
|
#include "privates.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
|
||||||
* Selection data structures
|
* Selection data structures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -62,11 +61,45 @@ typedef struct _Selection {
|
||||||
Window window;
|
Window window;
|
||||||
WindowPtr pWin;
|
WindowPtr pWin;
|
||||||
ClientPtr client;
|
ClientPtr client;
|
||||||
ClientPtr alt_client; /* support for redirection */
|
struct _Selection *next;
|
||||||
Window alt_window; /* support for redirection */
|
|
||||||
PrivateRec *devPrivates;
|
PrivateRec *devPrivates;
|
||||||
} Selection;
|
} Selection;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Selection API
|
||||||
|
*/
|
||||||
|
|
||||||
|
int dixLookupSelection(Selection **result, Atom name,
|
||||||
|
ClientPtr client, Mask access_mode);
|
||||||
|
|
||||||
|
extern Selection *CurrentSelections;
|
||||||
|
|
||||||
|
extern CallbackListPtr SelectionCallback;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SelectionSetOwner,
|
||||||
|
SelectionWindowDestroy,
|
||||||
|
SelectionClientClose
|
||||||
|
} SelectionCallbackKind;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct _Selection *selection;
|
||||||
|
ClientPtr client;
|
||||||
|
SelectionCallbackKind kind;
|
||||||
|
} SelectionInfoRec;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Selection server internals
|
||||||
|
*/
|
||||||
|
|
||||||
|
void InitSelections(void);
|
||||||
|
|
||||||
|
void DeleteWindowFromAnySelections(WindowPtr pWin);
|
||||||
|
|
||||||
|
void DeleteClientFromAnySelections(ClientPtr client);
|
||||||
|
|
||||||
#endif /* SELECTION_H */
|
#endif /* SELECTION_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue