xipassivegrab.c revision 706f2543
1706f2543Smrg/*
2706f2543Smrg * Copyright © 2009 Red Hat, Inc.
3706f2543Smrg *
4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5706f2543Smrg * copy of this software and associated documentation files (the "Software"),
6706f2543Smrg * to deal in the Software without restriction, including without limitation
7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
9706f2543Smrg * Software is furnished to do so, subject to the following conditions:
10706f2543Smrg *
11706f2543Smrg * The above copyright notice and this permission notice (including the next
12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the
13706f2543Smrg * Software.
14706f2543Smrg *
15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21706f2543Smrg * DEALINGS IN THE SOFTWARE.
22706f2543Smrg *
23706f2543Smrg * Author: Peter Hutterer
24706f2543Smrg */
25706f2543Smrg
26706f2543Smrg/***********************************************************************
27706f2543Smrg *
28706f2543Smrg * Request to grab or ungrab input device.
29706f2543Smrg *
30706f2543Smrg */
31706f2543Smrg
32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
33706f2543Smrg#include <dix-config.h>
34706f2543Smrg#endif
35706f2543Smrg
36706f2543Smrg#include "inputstr.h"	/* DeviceIntPtr      */
37706f2543Smrg#include "windowstr.h"	/* window structure  */
38706f2543Smrg#include <X11/extensions/XI2.h>
39706f2543Smrg#include <X11/extensions/XI2proto.h>
40706f2543Smrg#include "swaprep.h"
41706f2543Smrg
42706f2543Smrg#include "exglobals.h" /* BadDevice */
43706f2543Smrg#include "exevents.h"
44706f2543Smrg#include "xipassivegrab.h"
45706f2543Smrg#include "dixgrabs.h"
46706f2543Smrg#include "misc.h"
47706f2543Smrg
48706f2543Smrgint
49706f2543SmrgSProcXIPassiveGrabDevice(ClientPtr client)
50706f2543Smrg{
51706f2543Smrg    int i;
52706f2543Smrg    char n;
53706f2543Smrg    xXIModifierInfo *mods;
54706f2543Smrg
55706f2543Smrg    REQUEST(xXIPassiveGrabDeviceReq);
56706f2543Smrg    REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
57706f2543Smrg
58706f2543Smrg    swaps(&stuff->length, n);
59706f2543Smrg    swaps(&stuff->deviceid, n);
60706f2543Smrg    swapl(&stuff->grab_window, n);
61706f2543Smrg    swapl(&stuff->cursor, n);
62706f2543Smrg    swapl(&stuff->time, n);
63706f2543Smrg    swapl(&stuff->detail, n);
64706f2543Smrg    swaps(&stuff->mask_len, n);
65706f2543Smrg    swaps(&stuff->num_modifiers, n);
66706f2543Smrg
67706f2543Smrg    REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
68706f2543Smrg        ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4);
69706f2543Smrg    mods = (xXIModifierInfo*)&stuff[1];
70706f2543Smrg
71706f2543Smrg    for (i = 0; i < stuff->num_modifiers; i++, mods++)
72706f2543Smrg    {
73706f2543Smrg        swapl(&mods->base_mods, n);
74706f2543Smrg        swapl(&mods->latched_mods, n);
75706f2543Smrg        swapl(&mods->locked_mods, n);
76706f2543Smrg    }
77706f2543Smrg
78706f2543Smrg    return ProcXIPassiveGrabDevice(client);
79706f2543Smrg}
80706f2543Smrg
81706f2543Smrgint
82706f2543SmrgProcXIPassiveGrabDevice(ClientPtr client)
83706f2543Smrg{
84706f2543Smrg    DeviceIntPtr dev, mod_dev;
85706f2543Smrg    xXIPassiveGrabDeviceReply rep;
86706f2543Smrg    int i, ret = Success;
87706f2543Smrg    uint8_t status;
88706f2543Smrg    uint32_t *modifiers;
89706f2543Smrg    xXIGrabModifierInfo *modifiers_failed;
90706f2543Smrg    GrabMask mask;
91706f2543Smrg    GrabParameters param;
92706f2543Smrg    void *tmp;
93706f2543Smrg    int mask_len;
94706f2543Smrg    int n;
95706f2543Smrg
96706f2543Smrg    REQUEST(xXIPassiveGrabDeviceReq);
97706f2543Smrg    REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
98706f2543Smrg        ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4);
99706f2543Smrg
100706f2543Smrg    if (stuff->deviceid == XIAllDevices)
101706f2543Smrg        dev = inputInfo.all_devices;
102706f2543Smrg    else if (stuff->deviceid == XIAllMasterDevices)
103706f2543Smrg        dev = inputInfo.all_master_devices;
104706f2543Smrg    else
105706f2543Smrg    {
106706f2543Smrg        ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
107706f2543Smrg        if (ret != Success)
108706f2543Smrg        {
109706f2543Smrg            client->errorValue = stuff->deviceid;
110706f2543Smrg            return ret;
111706f2543Smrg        }
112706f2543Smrg    }
113706f2543Smrg
114706f2543Smrg    if (stuff->grab_type != XIGrabtypeButton &&
115706f2543Smrg        stuff->grab_type != XIGrabtypeKeycode &&
116706f2543Smrg        stuff->grab_type != XIGrabtypeEnter &&
117706f2543Smrg        stuff->grab_type != XIGrabtypeFocusIn)
118706f2543Smrg    {
119706f2543Smrg        client->errorValue = stuff->grab_type;
120706f2543Smrg        return BadValue;
121706f2543Smrg    }
122706f2543Smrg
123706f2543Smrg    if ((stuff->grab_type == XIGrabtypeEnter ||
124706f2543Smrg         stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
125706f2543Smrg    {
126706f2543Smrg        client->errorValue = stuff->detail;
127706f2543Smrg        return BadValue;
128706f2543Smrg    }
129706f2543Smrg
130706f2543Smrg    if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
131706f2543Smrg                               stuff->mask_len * 4) != Success)
132706f2543Smrg        return BadValue;
133706f2543Smrg
134706f2543Smrg    mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
135706f2543Smrg    memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
136706f2543Smrg    memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
137706f2543Smrg
138706f2543Smrg    rep.repType = X_Reply;
139706f2543Smrg    rep.RepType = X_XIPassiveGrabDevice;
140706f2543Smrg    rep.length = 0;
141706f2543Smrg    rep.sequenceNumber = client->sequence;
142706f2543Smrg    rep.num_modifiers = 0;
143706f2543Smrg
144706f2543Smrg    memset(&param, 0, sizeof(param));
145706f2543Smrg    param.grabtype = GRABTYPE_XI2;
146706f2543Smrg    param.ownerEvents = stuff->owner_events;
147706f2543Smrg    param.grabWindow = stuff->grab_window;
148706f2543Smrg    param.cursor = stuff->cursor;
149706f2543Smrg
150706f2543Smrg    if (IsKeyboardDevice(dev)) {
151706f2543Smrg        param.this_device_mode = stuff->grab_mode;
152706f2543Smrg        param.other_devices_mode = stuff->paired_device_mode;
153706f2543Smrg    } else {
154706f2543Smrg        param.this_device_mode = stuff->paired_device_mode;
155706f2543Smrg        param.other_devices_mode = stuff->grab_mode;
156706f2543Smrg    }
157706f2543Smrg
158706f2543Smrg    if (stuff->cursor != None)
159706f2543Smrg    {
160706f2543Smrg        status = dixLookupResourceByType(&tmp, stuff->cursor,
161706f2543Smrg                                         RT_CURSOR, client, DixUseAccess);
162706f2543Smrg	if (status != Success)
163706f2543Smrg	{
164706f2543Smrg	    client->errorValue = stuff->cursor;
165706f2543Smrg	    return status;
166706f2543Smrg	}
167706f2543Smrg    }
168706f2543Smrg
169706f2543Smrg    status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
170706f2543Smrg    if (status != Success)
171706f2543Smrg	return status;
172706f2543Smrg
173706f2543Smrg    status = CheckGrabValues(client, &param);
174706f2543Smrg    if (status != Success)
175706f2543Smrg        return status;
176706f2543Smrg
177706f2543Smrg    modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
178706f2543Smrg    modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
179706f2543Smrg    if (!modifiers_failed)
180706f2543Smrg        return BadAlloc;
181706f2543Smrg
182706f2543Smrg    if (!IsMaster(dev) && dev->u.master)
183706f2543Smrg        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
184706f2543Smrg    else
185706f2543Smrg        mod_dev = dev;
186706f2543Smrg
187706f2543Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
188706f2543Smrg    {
189706f2543Smrg        param.modifiers = *modifiers;
190706f2543Smrg        switch(stuff->grab_type)
191706f2543Smrg        {
192706f2543Smrg            case XIGrabtypeButton:
193706f2543Smrg                status = GrabButton(client, dev, mod_dev, stuff->detail,
194706f2543Smrg                                    &param, GRABTYPE_XI2, &mask);
195706f2543Smrg                break;
196706f2543Smrg            case XIGrabtypeKeycode:
197706f2543Smrg                status = GrabKey(client, dev, mod_dev, stuff->detail,
198706f2543Smrg                                 &param, GRABTYPE_XI2, &mask);
199706f2543Smrg                break;
200706f2543Smrg            case XIGrabtypeEnter:
201706f2543Smrg            case XIGrabtypeFocusIn:
202706f2543Smrg                status = GrabWindow(client, dev, stuff->grab_type,
203706f2543Smrg                                    &param, &mask);
204706f2543Smrg                break;
205706f2543Smrg        }
206706f2543Smrg
207706f2543Smrg        if (status != GrabSuccess)
208706f2543Smrg        {
209706f2543Smrg            xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
210706f2543Smrg
211706f2543Smrg            info->status = status;
212706f2543Smrg            info->modifiers = *modifiers;
213706f2543Smrg            if (client->swapped)
214706f2543Smrg                swapl(&info->modifiers, n);
215706f2543Smrg
216706f2543Smrg            rep.num_modifiers++;
217706f2543Smrg            rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
218706f2543Smrg        }
219706f2543Smrg    }
220706f2543Smrg
221706f2543Smrg    WriteReplyToClient(client, sizeof(rep), &rep);
222706f2543Smrg    if (rep.num_modifiers)
223706f2543Smrg        WriteToClient(client, rep.length * 4, (char*)modifiers_failed);
224706f2543Smrg
225706f2543Smrg    free(modifiers_failed);
226706f2543Smrg    return ret;
227706f2543Smrg}
228706f2543Smrg
229706f2543Smrgvoid
230706f2543SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size,
231706f2543Smrg                        xXIPassiveGrabDeviceReply * rep)
232706f2543Smrg{
233706f2543Smrg    char n;
234706f2543Smrg
235706f2543Smrg    swaps(&rep->sequenceNumber, n);
236706f2543Smrg    swapl(&rep->length, n);
237706f2543Smrg    swaps(&rep->num_modifiers, n);
238706f2543Smrg
239706f2543Smrg    WriteToClient(client, size, (char *)rep);
240706f2543Smrg}
241706f2543Smrg
242706f2543Smrgint
243706f2543SmrgSProcXIPassiveUngrabDevice(ClientPtr client)
244706f2543Smrg{
245706f2543Smrg    char n;
246706f2543Smrg    int i;
247706f2543Smrg    uint32_t *modifiers;
248706f2543Smrg
249706f2543Smrg    REQUEST(xXIPassiveUngrabDeviceReq);
250706f2543Smrg    REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
251706f2543Smrg
252706f2543Smrg    swaps(&stuff->length, n);
253706f2543Smrg    swapl(&stuff->grab_window, n);
254706f2543Smrg    swaps(&stuff->deviceid, n);
255706f2543Smrg    swapl(&stuff->detail, n);
256706f2543Smrg    swaps(&stuff->num_modifiers, n);
257706f2543Smrg
258706f2543Smrg    REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
259706f2543Smrg                       ((uint32_t) stuff->num_modifiers) << 2);
260706f2543Smrg    modifiers = (uint32_t*)&stuff[1];
261706f2543Smrg
262706f2543Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
263706f2543Smrg        swapl(modifiers, n);
264706f2543Smrg
265706f2543Smrg    return ProcXIPassiveUngrabDevice(client);
266706f2543Smrg}
267706f2543Smrg
268706f2543Smrgint
269706f2543SmrgProcXIPassiveUngrabDevice(ClientPtr client)
270706f2543Smrg{
271706f2543Smrg    DeviceIntPtr dev, mod_dev;
272706f2543Smrg    WindowPtr win;
273706f2543Smrg    GrabRec tempGrab;
274706f2543Smrg    uint32_t* modifiers;
275706f2543Smrg    int i, rc;
276706f2543Smrg
277706f2543Smrg    REQUEST(xXIPassiveUngrabDeviceReq);
278706f2543Smrg    REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
279706f2543Smrg                       ((uint32_t) stuff->num_modifiers) << 2);
280706f2543Smrg
281706f2543Smrg    if (stuff->deviceid == XIAllDevices)
282706f2543Smrg        dev = inputInfo.all_devices;
283706f2543Smrg    else if (stuff->deviceid == XIAllMasterDevices)
284706f2543Smrg        dev = inputInfo.all_master_devices;
285706f2543Smrg    else
286706f2543Smrg    {
287706f2543Smrg        rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
288706f2543Smrg        if (rc != Success)
289706f2543Smrg	    return rc;
290706f2543Smrg    }
291706f2543Smrg
292706f2543Smrg    if (stuff->grab_type != XIGrabtypeButton &&
293706f2543Smrg        stuff->grab_type != XIGrabtypeKeycode &&
294706f2543Smrg        stuff->grab_type != XIGrabtypeEnter &&
295706f2543Smrg        stuff->grab_type != XIGrabtypeFocusIn)
296706f2543Smrg    {
297706f2543Smrg        client->errorValue = stuff->grab_type;
298706f2543Smrg        return BadValue;
299706f2543Smrg    }
300706f2543Smrg
301706f2543Smrg    if ((stuff->grab_type == XIGrabtypeEnter ||
302706f2543Smrg         stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
303706f2543Smrg    {
304706f2543Smrg        client->errorValue = stuff->detail;
305706f2543Smrg        return BadValue;
306706f2543Smrg    }
307706f2543Smrg
308706f2543Smrg    rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
309706f2543Smrg    if (rc != Success)
310706f2543Smrg        return rc;
311706f2543Smrg
312706f2543Smrg    if (!IsMaster(dev) && dev->u.master)
313706f2543Smrg        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
314706f2543Smrg    else
315706f2543Smrg        mod_dev = dev;
316706f2543Smrg
317706f2543Smrg    tempGrab.resource = client->clientAsMask;
318706f2543Smrg    tempGrab.device = dev;
319706f2543Smrg    tempGrab.window = win;
320706f2543Smrg    switch(stuff->grab_type)
321706f2543Smrg    {
322706f2543Smrg        case XIGrabtypeButton:  tempGrab.type = XI_ButtonPress; break;
323706f2543Smrg        case XIGrabtypeKeycode:  tempGrab.type = XI_KeyPress;    break;
324706f2543Smrg        case XIGrabtypeEnter:   tempGrab.type = XI_Enter;       break;
325706f2543Smrg        case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn;     break;
326706f2543Smrg    }
327706f2543Smrg    tempGrab.grabtype = GRABTYPE_XI2;
328706f2543Smrg    tempGrab.modifierDevice = mod_dev;
329706f2543Smrg    tempGrab.modifiersDetail.pMask = NULL;
330706f2543Smrg    tempGrab.detail.exact = stuff->detail;
331706f2543Smrg    tempGrab.detail.pMask = NULL;
332706f2543Smrg
333706f2543Smrg    modifiers = (uint32_t*)&stuff[1];
334706f2543Smrg
335706f2543Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
336706f2543Smrg    {
337706f2543Smrg        tempGrab.modifiersDetail.exact = *modifiers;
338706f2543Smrg        DeletePassiveGrabFromList(&tempGrab);
339706f2543Smrg    }
340706f2543Smrg
341706f2543Smrg    return Success;
342706f2543Smrg}
343