mirror of
https://github.com/X11Libre/xserver.git
synced 2026-09-17 19:42:21 +00:00
bugzilla 859 -merging DAMAGE-XFIXES into trunk
This commit is contained in:
parent
736e511824
commit
6ed1c38455
7 changed files with 2412 additions and 0 deletions
278
xfixes/select.c
Executable file
278
xfixes/select.c
Executable file
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright © 2002 Keith Packard
|
||||
*
|
||||
* 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, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "xfixesint.h"
|
||||
|
||||
static RESTYPE SelectionClientType, SelectionWindowType;
|
||||
static Bool SelectionCallbackRegistered = FALSE;
|
||||
|
||||
/*
|
||||
* There is a global list of windows selecting for selection events
|
||||
* on every selection. This should be plenty efficient for the
|
||||
* expected usage, if it does become a problem, it should be easily
|
||||
* replaced with a hash table of some kind keyed off the selection atom
|
||||
*/
|
||||
|
||||
typedef struct _SelectionEvent *SelectionEventPtr;
|
||||
|
||||
typedef struct _SelectionEvent {
|
||||
SelectionEventPtr next;
|
||||
Atom selection;
|
||||
CARD32 eventMask;
|
||||
ClientPtr pClient;
|
||||
WindowPtr pWindow;
|
||||
XID clientResource;
|
||||
} SelectionEventRec;
|
||||
|
||||
static SelectionEventPtr selectionEvents;
|
||||
|
||||
static void
|
||||
XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args)
|
||||
{
|
||||
SelectionEventPtr e;
|
||||
SelectionInfoRec *info = (SelectionInfoRec *) args;
|
||||
Selection *selection = info->selection;
|
||||
int subtype;
|
||||
CARD32 eventMask;
|
||||
|
||||
switch (info->kind) {
|
||||
case SelectionSetOwner:
|
||||
subtype = XFixesSetSelectionOwnerNotify;
|
||||
eventMask = XFixesSetSelectionOwnerNotifyMask;
|
||||
break;
|
||||
case SelectionWindowDestroy:
|
||||
subtype = XFixesSelectionWindowDestroyNotify;
|
||||
eventMask = XFixesSelectionWindowDestroyNotifyMask;
|
||||
break;
|
||||
case SelectionClientClose:
|
||||
subtype = XFixesSelectionClientCloseNotify;
|
||||
eventMask = XFixesSelectionClientCloseNotifyMask;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
for (e = selectionEvents; e; e = e->next)
|
||||
{
|
||||
if (e->selection == selection->selection && (e->eventMask & eventMask))
|
||||
{
|
||||
xXFixesSelectionNotifyEvent ev;
|
||||
|
||||
ev.type = XFixesEventBase + XFixesSelectionNotify;
|
||||
ev.subtype = subtype;
|
||||
ev.sequenceNumber = e->pClient->sequence;
|
||||
ev.window = e->pWindow->drawable.id;
|
||||
if (subtype == XFixesSetSelectionOwnerNotify)
|
||||
ev.owner = selection->window;
|
||||
else
|
||||
ev.owner = 0;
|
||||
ev.selection = e->selection;
|
||||
ev.timestamp = currentTime.milliseconds;
|
||||
ev.selectionTimestamp = selection->lastTimeChanged.milliseconds;
|
||||
WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Bool
|
||||
CheckSelectionCallback (void)
|
||||
{
|
||||
if (selectionEvents)
|
||||
{
|
||||
if (!SelectionCallbackRegistered)
|
||||
{
|
||||
if (!AddCallback (&SelectionCallback, XFixesSelectionCallback, NULL))
|
||||
return FALSE;
|
||||
SelectionCallbackRegistered = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SelectionCallbackRegistered)
|
||||
{
|
||||
DeleteCallback (&SelectionCallback, XFixesSelectionCallback, NULL);
|
||||
SelectionCallbackRegistered = FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
|
||||
XFixesSelectionWindowDestroyNotifyMask |\
|
||||
XFixesSelectionClientCloseNotifyMask)
|
||||
|
||||
static int
|
||||
XFixesSelectSelectionInput (ClientPtr pClient,
|
||||
Atom selection,
|
||||
WindowPtr pWindow,
|
||||
CARD32 eventMask)
|
||||
{
|
||||
SelectionEventPtr *prev, e;
|
||||
|
||||
for (prev = &selectionEvents; (e = *prev); prev = &e->next)
|
||||
{
|
||||
if (e->selection == selection &&
|
||||
e->pClient == pClient &&
|
||||
e->pWindow == pWindow)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!eventMask)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
FreeResource (e->clientResource, 0);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
if (!e)
|
||||
{
|
||||
e = (SelectionEventPtr) xalloc (sizeof (SelectionEventRec));
|
||||
if (!e)
|
||||
return BadAlloc;
|
||||
|
||||
e->next = 0;
|
||||
e->selection = selection;
|
||||
e->pClient = pClient;
|
||||
e->pWindow = pWindow;
|
||||
e->clientResource = FakeClientID(pClient->index);
|
||||
|
||||
/*
|
||||
* Add a resource hanging from the window to
|
||||
* catch window destroy
|
||||
*/
|
||||
if (!LookupIDByType(pWindow->drawable.id, SelectionWindowType))
|
||||
if (!AddResource (pWindow->drawable.id, SelectionWindowType,
|
||||
(pointer) pWindow))
|
||||
{
|
||||
xfree (e);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
if (!AddResource (e->clientResource, SelectionClientType, (pointer) e))
|
||||
return BadAlloc;
|
||||
|
||||
*prev = e;
|
||||
if (!CheckSelectionCallback ())
|
||||
{
|
||||
FreeResource (e->clientResource, 0);
|
||||
return BadAlloc;
|
||||
}
|
||||
}
|
||||
e->eventMask = eventMask;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcXFixesSelectSelectionInput (ClientPtr client)
|
||||
{
|
||||
REQUEST (xXFixesSelectSelectionInputReq);
|
||||
WindowPtr pWin;
|
||||
|
||||
REQUEST_SIZE_MATCH (xXFixesSelectSelectionInputReq);
|
||||
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
|
||||
SecurityReadAccess);
|
||||
if (!pWin)
|
||||
return(BadWindow);
|
||||
if (stuff->eventMask & ~SelectionAllEvents)
|
||||
{
|
||||
client->errorValue = stuff->eventMask;
|
||||
return( BadValue );
|
||||
}
|
||||
return XFixesSelectSelectionInput (client, stuff->selection,
|
||||
pWin, stuff->eventMask);
|
||||
}
|
||||
|
||||
int
|
||||
SProcXFixesSelectSelectionInput (ClientPtr client)
|
||||
{
|
||||
register int n;
|
||||
REQUEST(xXFixesSelectSelectionInputReq);
|
||||
|
||||
swaps(&stuff->length, n);
|
||||
swapl(&stuff->window, n);
|
||||
swapl(&stuff->selection, n);
|
||||
swapl(&stuff->eventMask, n);
|
||||
return ProcXFixesSelectSelectionInput(client);
|
||||
}
|
||||
|
||||
void
|
||||
SXFixesSelectionNotifyEvent (xXFixesSelectionNotifyEvent *from,
|
||||
xXFixesSelectionNotifyEvent *to)
|
||||
{
|
||||
to->type = from->type;
|
||||
cpswaps (from->sequenceNumber, to->sequenceNumber);
|
||||
cpswapl (from->window, to->window);
|
||||
cpswapl (from->owner, to->owner);
|
||||
cpswapl (from->selection, to->selection);
|
||||
cpswapl (from->timestamp, to->timestamp);
|
||||
cpswapl (from->selectionTimestamp, to->selectionTimestamp);
|
||||
}
|
||||
|
||||
static int
|
||||
SelectionFreeClient (pointer data, XID id)
|
||||
{
|
||||
SelectionEventPtr old = (SelectionEventPtr) data;
|
||||
SelectionEventPtr *prev, e;
|
||||
|
||||
for (prev = &selectionEvents; (e = *prev); prev = &e->next)
|
||||
{
|
||||
if (e == old)
|
||||
{
|
||||
*prev = e->next;
|
||||
xfree (e);
|
||||
CheckSelectionCallback ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
SelectionFreeWindow (pointer data, XID id)
|
||||
{
|
||||
WindowPtr pWindow = (WindowPtr) data;
|
||||
SelectionEventPtr e, next;
|
||||
|
||||
for (e = selectionEvents; e; e = next)
|
||||
{
|
||||
next = e->next;
|
||||
if (e->pWindow == pWindow)
|
||||
{
|
||||
FreeResource (e->clientResource, 0);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Bool
|
||||
XFixesSelectionInit (void)
|
||||
{
|
||||
SelectionClientType = CreateNewResourceType(SelectionFreeClient);
|
||||
SelectionWindowType = CreateNewResourceType(SelectionFreeWindow);
|
||||
return SelectionClientType && SelectionWindowType;
|
||||
}
|
||||
Loading…
Reference in a new issue