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"
30 static RESTYPE SelectionClientType
, SelectionWindowType
;
31 static Bool SelectionCallbackRegistered
= FALSE
;
34 * There is a global list of windows selecting for selection events
35 * on every selection. This should be plenty efficient for the
36 * expected usage, if it does become a problem, it should be easily
37 * replaced with a hash table of some kind keyed off the selection atom
40 typedef struct _SelectionEvent
*SelectionEventPtr
;
42 typedef struct _SelectionEvent
{
43 SelectionEventPtr next
;
51 static SelectionEventPtr selectionEvents
;
54 XFixesSelectionCallback(CallbackListPtr
*callbacks
, pointer data
, pointer args
)
57 SelectionInfoRec
*info
= (SelectionInfoRec
*) args
;
58 Selection
*selection
= info
->selection
;
63 case SelectionSetOwner
:
64 subtype
= XFixesSetSelectionOwnerNotify
;
65 eventMask
= XFixesSetSelectionOwnerNotifyMask
;
67 case SelectionWindowDestroy
:
68 subtype
= XFixesSelectionWindowDestroyNotify
;
69 eventMask
= XFixesSelectionWindowDestroyNotifyMask
;
71 case SelectionClientClose
:
72 subtype
= XFixesSelectionClientCloseNotify
;
73 eventMask
= XFixesSelectionClientCloseNotifyMask
;
78 for (e
= selectionEvents
; e
; e
= e
->next
) {
79 if (e
->selection
== selection
->selection
&& (e
->eventMask
& eventMask
)) {
80 xXFixesSelectionNotifyEvent ev
= {
81 .type
= XFixesEventBase
+ XFixesSelectionNotify
,
83 .window
= e
->pWindow
->drawable
.id
,
84 .owner
= (subtype
== XFixesSetSelectionOwnerNotify
) ?
85 selection
->window
: 0,
86 .selection
= e
->selection
,
87 .timestamp
= currentTime
.milliseconds
,
88 .selectionTimestamp
= selection
->lastTimeChanged
.milliseconds
90 WriteEventsToClient(e
->pClient
, 1, (xEvent
*) &ev
);
96 CheckSelectionCallback(void)
98 if (selectionEvents
) {
99 if (!SelectionCallbackRegistered
) {
100 if (!AddCallback(&SelectionCallback
, XFixesSelectionCallback
, NULL
))
102 SelectionCallbackRegistered
= TRUE
;
106 if (SelectionCallbackRegistered
) {
107 DeleteCallback(&SelectionCallback
, XFixesSelectionCallback
, NULL
);
108 SelectionCallbackRegistered
= FALSE
;
114 #define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
115 XFixesSelectionWindowDestroyNotifyMask |\
116 XFixesSelectionClientCloseNotifyMask)
119 XFixesSelectSelectionInput(ClientPtr pClient
,
120 Atom selection
, WindowPtr pWindow
, CARD32 eventMask
)
124 SelectionEventPtr
*prev
, e
;
126 rc
= XaceHook(XACE_SELECTION_ACCESS
, pClient
, selection
, DixGetAttrAccess
);
130 for (prev
= &selectionEvents
; (e
= *prev
); prev
= &e
->next
) {
131 if (e
->selection
== selection
&&
132 e
->pClient
== pClient
&& e
->pWindow
== pWindow
) {
138 FreeResource(e
->clientResource
, 0);
143 e
= (SelectionEventPtr
) malloc(sizeof(SelectionEventRec
));
148 e
->selection
= selection
;
149 e
->pClient
= pClient
;
150 e
->pWindow
= pWindow
;
151 e
->clientResource
= FakeClientID(pClient
->index
);
154 * Add a resource hanging from the window to
155 * catch window destroy
157 rc
= dixLookupResourceByType(&val
, pWindow
->drawable
.id
,
158 SelectionWindowType
, serverClient
,
161 if (!AddResource(pWindow
->drawable
.id
, SelectionWindowType
,
162 (pointer
) pWindow
)) {
167 if (!AddResource(e
->clientResource
, SelectionClientType
, (pointer
) e
))
171 if (!CheckSelectionCallback()) {
172 FreeResource(e
->clientResource
, 0);
176 e
->eventMask
= eventMask
;
181 ProcXFixesSelectSelectionInput(ClientPtr client
)
183 REQUEST(xXFixesSelectSelectionInputReq
);
187 REQUEST_SIZE_MATCH(xXFixesSelectSelectionInputReq
);
188 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
191 if (stuff
->eventMask
& ~SelectionAllEvents
) {
192 client
->errorValue
= stuff
->eventMask
;
195 return XFixesSelectSelectionInput(client
, stuff
->selection
,
196 pWin
, stuff
->eventMask
);
200 SProcXFixesSelectSelectionInput(ClientPtr client
)
202 REQUEST(xXFixesSelectSelectionInputReq
);
204 swaps(&stuff
->length
);
205 swapl(&stuff
->window
);
206 swapl(&stuff
->selection
);
207 swapl(&stuff
->eventMask
);
208 return (*ProcXFixesVector
[stuff
->xfixesReqType
]) (client
);
212 SXFixesSelectionNotifyEvent(xXFixesSelectionNotifyEvent
* from
,
213 xXFixesSelectionNotifyEvent
* to
)
215 to
->type
= from
->type
;
216 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
217 cpswapl(from
->window
, to
->window
);
218 cpswapl(from
->owner
, to
->owner
);
219 cpswapl(from
->selection
, to
->selection
);
220 cpswapl(from
->timestamp
, to
->timestamp
);
221 cpswapl(from
->selectionTimestamp
, to
->selectionTimestamp
);
225 SelectionFreeClient(pointer data
, XID id
)
227 SelectionEventPtr old
= (SelectionEventPtr
) data
;
228 SelectionEventPtr
*prev
, e
;
230 for (prev
= &selectionEvents
; (e
= *prev
); prev
= &e
->next
) {
234 CheckSelectionCallback();
242 SelectionFreeWindow(pointer data
, XID id
)
244 WindowPtr pWindow
= (WindowPtr
) data
;
245 SelectionEventPtr e
, next
;
247 for (e
= selectionEvents
; e
; e
= next
) {
249 if (e
->pWindow
== pWindow
) {
250 FreeResource(e
->clientResource
, 0);
257 XFixesSelectionInit(void)
259 SelectionClientType
= CreateNewResourceType(SelectionFreeClient
,
260 "XFixesSelectionClient");
261 SelectionWindowType
= CreateNewResourceType(SelectionFreeWindow
,
262 "XFixesSelectionWindow");
263 return SelectionClientType
&& SelectionWindowType
;