Initial commit
[xorg_rtime.git] / xorg-server-1.4 / xfixes / select.c
blobc0076801d1f7b22d8017d67326dd31a79af5a91f
1 /*
2 * Copyright © 2002 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include "xfixesint.h"
29 static RESTYPE SelectionClientType, SelectionWindowType;
30 static Bool SelectionCallbackRegistered = FALSE;
33 * There is a global list of windows selecting for selection events
34 * on every selection. This should be plenty efficient for the
35 * expected usage, if it does become a problem, it should be easily
36 * replaced with a hash table of some kind keyed off the selection atom
39 typedef struct _SelectionEvent *SelectionEventPtr;
41 typedef struct _SelectionEvent {
42 SelectionEventPtr next;
43 Atom selection;
44 CARD32 eventMask;
45 ClientPtr pClient;
46 WindowPtr pWindow;
47 XID clientResource;
48 } SelectionEventRec;
50 static SelectionEventPtr selectionEvents;
52 static void
53 XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args)
55 SelectionEventPtr e;
56 SelectionInfoRec *info = (SelectionInfoRec *) args;
57 Selection *selection = info->selection;
58 int subtype;
59 CARD32 eventMask;
61 switch (info->kind) {
62 case SelectionSetOwner:
63 subtype = XFixesSetSelectionOwnerNotify;
64 eventMask = XFixesSetSelectionOwnerNotifyMask;
65 break;
66 case SelectionWindowDestroy:
67 subtype = XFixesSelectionWindowDestroyNotify;
68 eventMask = XFixesSelectionWindowDestroyNotifyMask;
69 break;
70 case SelectionClientClose:
71 subtype = XFixesSelectionClientCloseNotify;
72 eventMask = XFixesSelectionClientCloseNotifyMask;
73 break;
74 default:
75 return;
77 for (e = selectionEvents; e; e = e->next)
79 if (e->selection == selection->selection &&
80 (e->eventMask & eventMask) &&
81 !e->pClient->clientGone)
83 xXFixesSelectionNotifyEvent ev;
85 ev.type = XFixesEventBase + XFixesSelectionNotify;
86 ev.subtype = subtype;
87 ev.sequenceNumber = e->pClient->sequence;
88 ev.window = e->pWindow->drawable.id;
89 if (subtype == XFixesSetSelectionOwnerNotify)
90 ev.owner = selection->window;
91 else
92 ev.owner = 0;
93 ev.selection = e->selection;
94 ev.timestamp = currentTime.milliseconds;
95 ev.selectionTimestamp = selection->lastTimeChanged.milliseconds;
96 WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
101 static Bool
102 CheckSelectionCallback (void)
104 if (selectionEvents)
106 if (!SelectionCallbackRegistered)
108 if (!AddCallback (&SelectionCallback, XFixesSelectionCallback, NULL))
109 return FALSE;
110 SelectionCallbackRegistered = TRUE;
113 else
115 if (SelectionCallbackRegistered)
117 DeleteCallback (&SelectionCallback, XFixesSelectionCallback, NULL);
118 SelectionCallbackRegistered = FALSE;
121 return TRUE;
124 #define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
125 XFixesSelectionWindowDestroyNotifyMask |\
126 XFixesSelectionClientCloseNotifyMask)
128 static int
129 XFixesSelectSelectionInput (ClientPtr pClient,
130 Atom selection,
131 WindowPtr pWindow,
132 CARD32 eventMask)
134 SelectionEventPtr *prev, e;
136 for (prev = &selectionEvents; (e = *prev); prev = &e->next)
138 if (e->selection == selection &&
139 e->pClient == pClient &&
140 e->pWindow == pWindow)
142 break;
145 if (!eventMask)
147 if (e)
149 FreeResource (e->clientResource, 0);
151 return Success;
153 if (!e)
155 e = (SelectionEventPtr) xalloc (sizeof (SelectionEventRec));
156 if (!e)
157 return BadAlloc;
159 e->next = 0;
160 e->selection = selection;
161 e->pClient = pClient;
162 e->pWindow = pWindow;
163 e->clientResource = FakeClientID(pClient->index);
166 * Add a resource hanging from the window to
167 * catch window destroy
169 if (!LookupIDByType(pWindow->drawable.id, SelectionWindowType))
170 if (!AddResource (pWindow->drawable.id, SelectionWindowType,
171 (pointer) pWindow))
173 xfree (e);
174 return BadAlloc;
177 if (!AddResource (e->clientResource, SelectionClientType, (pointer) e))
178 return BadAlloc;
180 *prev = e;
181 if (!CheckSelectionCallback ())
183 FreeResource (e->clientResource, 0);
184 return BadAlloc;
187 e->eventMask = eventMask;
188 return Success;
192 ProcXFixesSelectSelectionInput (ClientPtr client)
194 REQUEST (xXFixesSelectSelectionInputReq);
195 WindowPtr pWin;
196 int rc;
198 REQUEST_SIZE_MATCH (xXFixesSelectSelectionInputReq);
199 rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
200 if (rc != Success)
201 return rc;
202 if (stuff->eventMask & ~SelectionAllEvents)
204 client->errorValue = stuff->eventMask;
205 return( BadValue );
207 return XFixesSelectSelectionInput (client, stuff->selection,
208 pWin, stuff->eventMask);
212 SProcXFixesSelectSelectionInput (ClientPtr client)
214 register int n;
215 REQUEST(xXFixesSelectSelectionInputReq);
217 swaps(&stuff->length, n);
218 swapl(&stuff->window, n);
219 swapl(&stuff->selection, n);
220 swapl(&stuff->eventMask, n);
221 return ProcXFixesSelectSelectionInput(client);
224 void
225 SXFixesSelectionNotifyEvent (xXFixesSelectionNotifyEvent *from,
226 xXFixesSelectionNotifyEvent *to)
228 to->type = from->type;
229 cpswaps (from->sequenceNumber, to->sequenceNumber);
230 cpswapl (from->window, to->window);
231 cpswapl (from->owner, to->owner);
232 cpswapl (from->selection, to->selection);
233 cpswapl (from->timestamp, to->timestamp);
234 cpswapl (from->selectionTimestamp, to->selectionTimestamp);
237 static int
238 SelectionFreeClient (pointer data, XID id)
240 SelectionEventPtr old = (SelectionEventPtr) data;
241 SelectionEventPtr *prev, e;
243 for (prev = &selectionEvents; (e = *prev); prev = &e->next)
245 if (e == old)
247 *prev = e->next;
248 xfree (e);
249 CheckSelectionCallback ();
250 break;
253 return 1;
256 static int
257 SelectionFreeWindow (pointer data, XID id)
259 WindowPtr pWindow = (WindowPtr) data;
260 SelectionEventPtr e, next;
262 for (e = selectionEvents; e; e = next)
264 next = e->next;
265 if (e->pWindow == pWindow)
267 FreeResource (e->clientResource, 0);
270 return 1;
273 Bool
274 XFixesSelectionInit (void)
276 SelectionClientType = CreateNewResourceType(SelectionFreeClient);
277 SelectionWindowType = CreateNewResourceType(SelectionFreeWindow);
278 return SelectionClientType && SelectionWindowType;