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>
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
;
50 static SelectionEventPtr selectionEvents
;
53 XFixesSelectionCallback (CallbackListPtr
*callbacks
, pointer data
, pointer args
)
56 SelectionInfoRec
*info
= (SelectionInfoRec
*) args
;
57 Selection
*selection
= info
->selection
;
62 case SelectionSetOwner
:
63 subtype
= XFixesSetSelectionOwnerNotify
;
64 eventMask
= XFixesSetSelectionOwnerNotifyMask
;
66 case SelectionWindowDestroy
:
67 subtype
= XFixesSelectionWindowDestroyNotify
;
68 eventMask
= XFixesSelectionWindowDestroyNotifyMask
;
70 case SelectionClientClose
:
71 subtype
= XFixesSelectionClientCloseNotify
;
72 eventMask
= XFixesSelectionClientCloseNotifyMask
;
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
;
87 ev
.sequenceNumber
= e
->pClient
->sequence
;
88 ev
.window
= e
->pWindow
->drawable
.id
;
89 if (subtype
== XFixesSetSelectionOwnerNotify
)
90 ev
.owner
= selection
->window
;
93 ev
.selection
= e
->selection
;
94 ev
.timestamp
= currentTime
.milliseconds
;
95 ev
.selectionTimestamp
= selection
->lastTimeChanged
.milliseconds
;
96 WriteEventsToClient (e
->pClient
, 1, (xEvent
*) &ev
);
102 CheckSelectionCallback (void)
106 if (!SelectionCallbackRegistered
)
108 if (!AddCallback (&SelectionCallback
, XFixesSelectionCallback
, NULL
))
110 SelectionCallbackRegistered
= TRUE
;
115 if (SelectionCallbackRegistered
)
117 DeleteCallback (&SelectionCallback
, XFixesSelectionCallback
, NULL
);
118 SelectionCallbackRegistered
= FALSE
;
124 #define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
125 XFixesSelectionWindowDestroyNotifyMask |\
126 XFixesSelectionClientCloseNotifyMask)
129 XFixesSelectSelectionInput (ClientPtr pClient
,
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
)
149 FreeResource (e
->clientResource
, 0);
155 e
= (SelectionEventPtr
) xalloc (sizeof (SelectionEventRec
));
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
,
177 if (!AddResource (e
->clientResource
, SelectionClientType
, (pointer
) e
))
181 if (!CheckSelectionCallback ())
183 FreeResource (e
->clientResource
, 0);
187 e
->eventMask
= eventMask
;
192 ProcXFixesSelectSelectionInput (ClientPtr client
)
194 REQUEST (xXFixesSelectSelectionInputReq
);
198 REQUEST_SIZE_MATCH (xXFixesSelectSelectionInputReq
);
199 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixReadAccess
);
202 if (stuff
->eventMask
& ~SelectionAllEvents
)
204 client
->errorValue
= stuff
->eventMask
;
207 return XFixesSelectSelectionInput (client
, stuff
->selection
,
208 pWin
, stuff
->eventMask
);
212 SProcXFixesSelectSelectionInput (ClientPtr client
)
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
);
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
);
238 SelectionFreeClient (pointer data
, XID id
)
240 SelectionEventPtr old
= (SelectionEventPtr
) data
;
241 SelectionEventPtr
*prev
, e
;
243 for (prev
= &selectionEvents
; (e
= *prev
); prev
= &e
->next
)
249 CheckSelectionCallback ();
257 SelectionFreeWindow (pointer data
, XID id
)
259 WindowPtr pWindow
= (WindowPtr
) data
;
260 SelectionEventPtr e
, next
;
262 for (e
= selectionEvents
; e
; e
= next
)
265 if (e
->pWindow
== pWindow
)
267 FreeResource (e
->clientResource
, 0);
274 XFixesSelectionInit (void)
276 SelectionClientType
= CreateNewResourceType(SelectionFreeClient
);
277 SelectionWindowType
= CreateNewResourceType(SelectionFreeWindow
);
278 return SelectionClientType
&& SelectionWindowType
;