~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to xfixes/select.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: select.c,v 1.6 2005/07/03 07:37:35 daniels Exp $
 
3
 *
 
4
 * Copyright Ā© 2002 Keith Packard
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
 
 
25
#ifdef HAVE_DIX_CONFIG_H
 
26
#include <dix-config.h>
 
27
#endif
 
28
 
 
29
#include "xfixesint.h"
 
30
 
 
31
static RESTYPE          SelectionClientType, SelectionWindowType;
 
32
static Bool             SelectionCallbackRegistered = FALSE;
 
33
 
 
34
/*
 
35
 * There is a global list of windows selecting for selection events
 
36
 * on every selection.  This should be plenty efficient for the
 
37
 * expected usage, if it does become a problem, it should be easily
 
38
 * replaced with a hash table of some kind keyed off the selection atom
 
39
 */
 
40
 
 
41
typedef struct _SelectionEvent *SelectionEventPtr;
 
42
 
 
43
typedef struct _SelectionEvent {
 
44
    SelectionEventPtr   next;
 
45
    Atom                selection;
 
46
    CARD32              eventMask;
 
47
    ClientPtr           pClient;
 
48
    WindowPtr           pWindow;
 
49
    XID                 clientResource;
 
50
} SelectionEventRec;
 
51
 
 
52
static SelectionEventPtr        selectionEvents;
 
53
 
 
54
static void
 
55
XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args)
 
56
{
 
57
    SelectionEventPtr   e;
 
58
    SelectionInfoRec    *info = (SelectionInfoRec *) args;
 
59
    Selection           *selection = info->selection;
 
60
    int                 subtype;
 
61
    CARD32              eventMask;
 
62
    
 
63
    switch (info->kind) {
 
64
    case SelectionSetOwner:
 
65
        subtype = XFixesSetSelectionOwnerNotify;
 
66
        eventMask = XFixesSetSelectionOwnerNotifyMask;
 
67
        break;
 
68
    case SelectionWindowDestroy:
 
69
        subtype = XFixesSelectionWindowDestroyNotify;
 
70
        eventMask = XFixesSelectionWindowDestroyNotifyMask;
 
71
        break;
 
72
    case SelectionClientClose:
 
73
        subtype = XFixesSelectionClientCloseNotify;
 
74
        eventMask = XFixesSelectionClientCloseNotifyMask;
 
75
        break;
 
76
    default:
 
77
        return;
 
78
    }
 
79
    for (e = selectionEvents; e; e = e->next)
 
80
    {
 
81
        if (e->selection == selection->selection && (e->eventMask & eventMask))
 
82
        {
 
83
            xXFixesSelectionNotifyEvent ev;
 
84
 
 
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);
 
97
        }
 
98
    }
 
99
}
 
100
 
 
101
static Bool
 
102
CheckSelectionCallback (void)
 
103
{
 
104
    if (selectionEvents)
 
105
    {
 
106
        if (!SelectionCallbackRegistered)
 
107
        {
 
108
            if (!AddCallback (&SelectionCallback, XFixesSelectionCallback, NULL))
 
109
                return FALSE;
 
110
            SelectionCallbackRegistered = TRUE;
 
111
        }
 
112
    }
 
113
    else
 
114
    {
 
115
        if (SelectionCallbackRegistered)
 
116
        {
 
117
            DeleteCallback (&SelectionCallback, XFixesSelectionCallback, NULL);
 
118
            SelectionCallbackRegistered = FALSE;
 
119
        }
 
120
    }
 
121
    return TRUE;
 
122
}
 
123
 
 
124
#define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
 
125
                            XFixesSelectionWindowDestroyNotifyMask |\
 
126
                            XFixesSelectionClientCloseNotifyMask)
 
127
 
 
128
static int
 
129
XFixesSelectSelectionInput (ClientPtr   pClient,
 
130
                            Atom        selection,
 
131
                            WindowPtr   pWindow,
 
132
                            CARD32      eventMask)
 
133
{
 
134
    SelectionEventPtr   *prev, e;
 
135
 
 
136
    for (prev = &selectionEvents; (e = *prev); prev = &e->next)
 
137
    {
 
138
        if (e->selection == selection &&
 
139
            e->pClient == pClient &&
 
140
            e->pWindow == pWindow)
 
141
        {
 
142
            break;
 
143
        }
 
144
    }
 
145
    if (!eventMask)
 
146
    {
 
147
        if (e)
 
148
        {
 
149
            FreeResource (e->clientResource, 0);
 
150
        }
 
151
        return Success;
 
152
    }
 
153
    if (!e)
 
154
    {
 
155
        e = (SelectionEventPtr) xalloc (sizeof (SelectionEventRec));
 
156
        if (!e)
 
157
            return BadAlloc;
 
158
 
 
159
        e->next = 0;
 
160
        e->selection = selection;
 
161
        e->pClient = pClient;
 
162
        e->pWindow = pWindow;
 
163
        e->clientResource = FakeClientID(pClient->index);
 
164
 
 
165
        /*
 
166
         * Add a resource hanging from the window to
 
167
         * catch window destroy
 
168
         */
 
169
        if (!LookupIDByType(pWindow->drawable.id, SelectionWindowType))
 
170
            if (!AddResource (pWindow->drawable.id, SelectionWindowType,
 
171
                              (pointer) pWindow))
 
172
            {
 
173
                xfree (e);
 
174
                return BadAlloc;
 
175
            }
 
176
 
 
177
        if (!AddResource (e->clientResource, SelectionClientType, (pointer) e))
 
178
            return BadAlloc;
 
179
 
 
180
        *prev = e;
 
181
        if (!CheckSelectionCallback ())
 
182
        {
 
183
            FreeResource (e->clientResource, 0);
 
184
            return BadAlloc;
 
185
        }
 
186
    }
 
187
    e->eventMask = eventMask;
 
188
    return Success;
 
189
}
 
190
 
 
191
int
 
192
ProcXFixesSelectSelectionInput (ClientPtr client)
 
193
{
 
194
    REQUEST (xXFixesSelectSelectionInputReq);
 
195
    WindowPtr   pWin;
 
196
 
 
197
    REQUEST_SIZE_MATCH (xXFixesSelectSelectionInputReq);
 
198
    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
 
199
                                           SecurityReadAccess);
 
200
    if (!pWin)
 
201
        return(BadWindow);
 
202
    if (stuff->eventMask & ~SelectionAllEvents)
 
203
    {
 
204
        client->errorValue = stuff->eventMask;
 
205
        return( BadValue );
 
206
    }
 
207
    return XFixesSelectSelectionInput (client, stuff->selection,
 
208
                                       pWin, stuff->eventMask);
 
209
}
 
210
 
 
211
int
 
212
SProcXFixesSelectSelectionInput (ClientPtr client)
 
213
{
 
214
    register int n;
 
215
    REQUEST(xXFixesSelectSelectionInputReq);
 
216
 
 
217
    swaps(&stuff->length, n);
 
218
    swapl(&stuff->window, n);
 
219
    swapl(&stuff->selection, n);
 
220
    swapl(&stuff->eventMask, n);
 
221
    return ProcXFixesSelectSelectionInput(client);
 
222
}
 
223
    
 
224
void
 
225
SXFixesSelectionNotifyEvent (xXFixesSelectionNotifyEvent *from,
 
226
                             xXFixesSelectionNotifyEvent *to)
 
227
{
 
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);
 
235
}
 
236
 
 
237
static int
 
238
SelectionFreeClient (pointer data, XID id)
 
239
{
 
240
    SelectionEventPtr   old = (SelectionEventPtr) data;
 
241
    SelectionEventPtr   *prev, e;
 
242
    
 
243
    for (prev = &selectionEvents; (e = *prev); prev = &e->next)
 
244
    {
 
245
        if (e == old)
 
246
        {
 
247
            *prev = e->next;
 
248
            xfree (e);
 
249
            CheckSelectionCallback ();
 
250
            break;
 
251
        }
 
252
    }
 
253
    return 1;
 
254
}
 
255
 
 
256
static int
 
257
SelectionFreeWindow (pointer data, XID id)
 
258
{
 
259
    WindowPtr           pWindow = (WindowPtr) data;
 
260
    SelectionEventPtr   e, next;
 
261
 
 
262
    for (e = selectionEvents; e; e = next)
 
263
    {
 
264
        next = e->next;
 
265
        if (e->pWindow == pWindow)
 
266
        {
 
267
            FreeResource (e->clientResource, 0);
 
268
        }
 
269
    }
 
270
    return 1;
 
271
}
 
272
 
 
273
Bool
 
274
XFixesSelectionInit (void)
 
275
{
 
276
    SelectionClientType = CreateNewResourceType(SelectionFreeClient);
 
277
    SelectionWindowType = CreateNewResourceType(SelectionFreeWindow);
 
278
    return SelectionClientType && SelectionWindowType;
 
279
}