1/************************************************************
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27			All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/***********************************************************************
48 *
49 * Extension function to close an extension input device.
50 *
51 */
52
53#ifdef HAVE_DIX_CONFIG_H
54#include <dix-config.h>
55#endif
56
57#include "inputstr.h"	/* DeviceIntPtr      */
58#include "windowstr.h"	/* window structure  */
59#include "scrnintstr.h"	/* screen structure  */
60#include <X11/extensions/XI.h>
61#include <X11/extensions/XIproto.h>
62#include "XIstubs.h"
63#include "exglobals.h"
64
65#include "closedev.h"
66
67/***********************************************************************
68 *
69 * This procedure closes an input device.
70 *
71 */
72
73int
74SProcXCloseDevice(ClientPtr client)
75{
76    char n;
77
78    REQUEST(xCloseDeviceReq);
79    swaps(&stuff->length, n);
80    REQUEST_SIZE_MATCH(xCloseDeviceReq);
81    return (ProcXCloseDevice(client));
82}
83
84/***********************************************************************
85 *
86 * Clear out event selections and passive grabs from a window for the
87 * specified device.
88 *
89 */
90
91static void
92DeleteDeviceEvents(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
93{
94    InputClientsPtr others;
95    OtherInputMasks *pOthers;
96    GrabPtr grab, next;
97
98    if ((pOthers = wOtherInputMasks(pWin)) != 0)
99	for (others = pOthers->inputClients; others; others = others->next)
100	    if (SameClient(others, client))
101		others->mask[dev->id] = NoEventMask;
102
103    for (grab = wPassiveGrabs(pWin); grab; grab = next) {
104	next = grab->next;
105	if ((grab->device == dev) &&
106	    (client->clientAsMask == CLIENT_BITS(grab->resource)))
107	    FreeResource(grab->resource, RT_NONE);
108    }
109}
110
111/***********************************************************************
112 *
113 * Walk througth the window tree, deleting event selections for this client
114 * from this device from all windows.
115 *
116 */
117
118static void
119DeleteEventsFromChildren(DeviceIntPtr dev, WindowPtr p1, ClientPtr client)
120{
121    WindowPtr p2;
122
123    while (p1) {
124	p2 = p1->firstChild;
125	DeleteDeviceEvents(dev, p1, client);
126	DeleteEventsFromChildren(dev, p2, client);
127	p1 = p1->nextSib;
128    }
129}
130
131/***********************************************************************
132 *
133 * This procedure closes an input device.
134 *
135 */
136
137int
138ProcXCloseDevice(ClientPtr client)
139{
140    int rc, i;
141    WindowPtr pWin, p1;
142    DeviceIntPtr d;
143
144    REQUEST(xCloseDeviceReq);
145    REQUEST_SIZE_MATCH(xCloseDeviceReq);
146
147    rc = dixLookupDevice(&d, stuff->deviceid, client, DixUseAccess);
148    if (rc != Success)
149	return rc;
150
151    if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
152	(*d->deviceGrab.DeactivateGrab) (d);	/* release active grab */
153
154    /* Remove event selections from all windows for events from this device
155     * and selected by this client.
156     * Delete passive grabs from all windows for this device.      */
157
158    for (i = 0; i < screenInfo.numScreens; i++) {
159	pWin = screenInfo.screens[i]->root;
160	DeleteDeviceEvents(d, pWin, client);
161	p1 = pWin->firstChild;
162	DeleteEventsFromChildren(d, p1, client);
163    }
164
165    return Success;
166}
167