xipassivegrab.c revision 0b0d8713
16747b715Smrg/*
26747b715Smrg * Copyright © 2009 Red Hat, Inc.
36747b715Smrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
106747b715Smrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
226747b715Smrg *
236747b715Smrg * Author: Peter Hutterer
246747b715Smrg */
256747b715Smrg
266747b715Smrg/***********************************************************************
276747b715Smrg *
286747b715Smrg * Request to grab or ungrab input device.
296747b715Smrg *
306747b715Smrg */
316747b715Smrg
326747b715Smrg#ifdef HAVE_DIX_CONFIG_H
336747b715Smrg#include <dix-config.h>
346747b715Smrg#endif
356747b715Smrg
366747b715Smrg#include "inputstr.h"	/* DeviceIntPtr      */
376747b715Smrg#include "windowstr.h"	/* window structure  */
386747b715Smrg#include <X11/extensions/XI2.h>
396747b715Smrg#include <X11/extensions/XI2proto.h>
406747b715Smrg#include "swaprep.h"
416747b715Smrg
426747b715Smrg#include "exglobals.h" /* BadDevice */
436747b715Smrg#include "exevents.h"
446747b715Smrg#include "xipassivegrab.h"
456747b715Smrg#include "dixgrabs.h"
469ace9065Smrg#include "misc.h"
476747b715Smrg
486747b715Smrgint
496747b715SmrgSProcXIPassiveGrabDevice(ClientPtr client)
506747b715Smrg{
516747b715Smrg    int i;
526747b715Smrg    char n;
536747b715Smrg    xXIModifierInfo *mods;
546747b715Smrg
556747b715Smrg    REQUEST(xXIPassiveGrabDeviceReq);
560b0d8713Smrg    REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
576747b715Smrg
586747b715Smrg    swaps(&stuff->length, n);
596747b715Smrg    swaps(&stuff->deviceid, n);
606747b715Smrg    swapl(&stuff->grab_window, n);
616747b715Smrg    swapl(&stuff->cursor, n);
626747b715Smrg    swapl(&stuff->time, n);
636747b715Smrg    swapl(&stuff->detail, n);
646747b715Smrg    swaps(&stuff->mask_len, n);
656747b715Smrg    swaps(&stuff->num_modifiers, n);
666747b715Smrg
670b0d8713Smrg    REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
680b0d8713Smrg        ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4);
696747b715Smrg    mods = (xXIModifierInfo*)&stuff[1];
706747b715Smrg
716747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, mods++)
726747b715Smrg    {
736747b715Smrg        swapl(&mods->base_mods, n);
746747b715Smrg        swapl(&mods->latched_mods, n);
756747b715Smrg        swapl(&mods->locked_mods, n);
766747b715Smrg    }
776747b715Smrg
786747b715Smrg    return ProcXIPassiveGrabDevice(client);
796747b715Smrg}
806747b715Smrg
816747b715Smrgint
826747b715SmrgProcXIPassiveGrabDevice(ClientPtr client)
836747b715Smrg{
846747b715Smrg    DeviceIntPtr dev, mod_dev;
856747b715Smrg    xXIPassiveGrabDeviceReply rep;
866747b715Smrg    int i, ret = Success;
876747b715Smrg    uint8_t status;
886747b715Smrg    uint32_t *modifiers;
896747b715Smrg    xXIGrabModifierInfo *modifiers_failed;
906747b715Smrg    GrabMask mask;
916747b715Smrg    GrabParameters param;
926747b715Smrg    void *tmp;
936747b715Smrg    int mask_len;
949ace9065Smrg    int n;
956747b715Smrg
966747b715Smrg    REQUEST(xXIPassiveGrabDeviceReq);
970b0d8713Smrg    REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
980b0d8713Smrg        ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4);
996747b715Smrg
1006747b715Smrg    if (stuff->deviceid == XIAllDevices)
1016747b715Smrg        dev = inputInfo.all_devices;
1026747b715Smrg    else if (stuff->deviceid == XIAllMasterDevices)
1036747b715Smrg        dev = inputInfo.all_master_devices;
1046747b715Smrg    else
1056747b715Smrg    {
1066747b715Smrg        ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
1076747b715Smrg        if (ret != Success)
1089ace9065Smrg        {
1099ace9065Smrg            client->errorValue = stuff->deviceid;
1106747b715Smrg            return ret;
1119ace9065Smrg        }
1126747b715Smrg    }
1136747b715Smrg
1146747b715Smrg    if (stuff->grab_type != XIGrabtypeButton &&
1156747b715Smrg        stuff->grab_type != XIGrabtypeKeycode &&
1166747b715Smrg        stuff->grab_type != XIGrabtypeEnter &&
1176747b715Smrg        stuff->grab_type != XIGrabtypeFocusIn)
1186747b715Smrg    {
1196747b715Smrg        client->errorValue = stuff->grab_type;
1206747b715Smrg        return BadValue;
1216747b715Smrg    }
1226747b715Smrg
1236747b715Smrg    if ((stuff->grab_type == XIGrabtypeEnter ||
1246747b715Smrg         stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
1256747b715Smrg    {
1266747b715Smrg        client->errorValue = stuff->detail;
1276747b715Smrg        return BadValue;
1286747b715Smrg    }
1296747b715Smrg
1309ace9065Smrg    if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
1316747b715Smrg                               stuff->mask_len * 4) != Success)
1326747b715Smrg        return BadValue;
1336747b715Smrg
1346747b715Smrg    mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
1356747b715Smrg    memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
1366747b715Smrg    memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
1376747b715Smrg
1386747b715Smrg    rep.repType = X_Reply;
1396747b715Smrg    rep.RepType = X_XIPassiveGrabDevice;
1406747b715Smrg    rep.length = 0;
1416747b715Smrg    rep.sequenceNumber = client->sequence;
1426747b715Smrg    rep.num_modifiers = 0;
1436747b715Smrg
1446747b715Smrg    memset(&param, 0, sizeof(param));
1456747b715Smrg    param.grabtype = GRABTYPE_XI2;
1466747b715Smrg    param.ownerEvents = stuff->owner_events;
1476747b715Smrg    param.grabWindow = stuff->grab_window;
1486747b715Smrg    param.cursor = stuff->cursor;
1496747b715Smrg
150475c125cSmrg    if (IsKeyboardDevice(dev)) {
151475c125cSmrg        param.this_device_mode = stuff->grab_mode;
152475c125cSmrg        param.other_devices_mode = stuff->paired_device_mode;
153475c125cSmrg    } else {
154475c125cSmrg        param.this_device_mode = stuff->paired_device_mode;
155475c125cSmrg        param.other_devices_mode = stuff->grab_mode;
156475c125cSmrg    }
157475c125cSmrg
1586747b715Smrg    if (stuff->cursor != None)
1596747b715Smrg    {
1606747b715Smrg        status = dixLookupResourceByType(&tmp, stuff->cursor,
1616747b715Smrg                                         RT_CURSOR, client, DixUseAccess);
1626747b715Smrg	if (status != Success)
1636747b715Smrg	{
1646747b715Smrg	    client->errorValue = stuff->cursor;
1656747b715Smrg	    return status;
1666747b715Smrg	}
1676747b715Smrg    }
1686747b715Smrg
1696747b715Smrg    status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
1706747b715Smrg    if (status != Success)
1716747b715Smrg	return status;
1726747b715Smrg
1736747b715Smrg    status = CheckGrabValues(client, &param);
1749ace9065Smrg    if (status != Success)
1759ace9065Smrg        return status;
1766747b715Smrg
1776747b715Smrg    modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
1786747b715Smrg    modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
1796747b715Smrg    if (!modifiers_failed)
1806747b715Smrg        return BadAlloc;
1816747b715Smrg
1826747b715Smrg    if (!IsMaster(dev) && dev->u.master)
1836747b715Smrg        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
1846747b715Smrg    else
1856747b715Smrg        mod_dev = dev;
1866747b715Smrg
1876747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
1886747b715Smrg    {
1896747b715Smrg        param.modifiers = *modifiers;
1906747b715Smrg        switch(stuff->grab_type)
1916747b715Smrg        {
1926747b715Smrg            case XIGrabtypeButton:
1936747b715Smrg                status = GrabButton(client, dev, mod_dev, stuff->detail,
1946747b715Smrg                                    &param, GRABTYPE_XI2, &mask);
1956747b715Smrg                break;
1966747b715Smrg            case XIGrabtypeKeycode:
1976747b715Smrg                status = GrabKey(client, dev, mod_dev, stuff->detail,
1986747b715Smrg                                 &param, GRABTYPE_XI2, &mask);
1996747b715Smrg                break;
2006747b715Smrg            case XIGrabtypeEnter:
2016747b715Smrg            case XIGrabtypeFocusIn:
2026747b715Smrg                status = GrabWindow(client, dev, stuff->grab_type,
2036747b715Smrg                                    &param, &mask);
2046747b715Smrg                break;
2056747b715Smrg        }
2066747b715Smrg
2076747b715Smrg        if (status != GrabSuccess)
2086747b715Smrg        {
2096747b715Smrg            xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
2106747b715Smrg
2116747b715Smrg            info->status = status;
2126747b715Smrg            info->modifiers = *modifiers;
2139ace9065Smrg            if (client->swapped)
2149ace9065Smrg                swapl(&info->modifiers, n);
2159ace9065Smrg
2166747b715Smrg            rep.num_modifiers++;
2179ace9065Smrg            rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
2186747b715Smrg        }
2196747b715Smrg    }
2206747b715Smrg
2216747b715Smrg    WriteReplyToClient(client, sizeof(rep), &rep);
2226747b715Smrg    if (rep.num_modifiers)
2239ace9065Smrg        WriteToClient(client, rep.length * 4, (char*)modifiers_failed);
2249ace9065Smrg
2256747b715Smrg    free(modifiers_failed);
2266747b715Smrg    return ret;
2276747b715Smrg}
2286747b715Smrg
2296747b715Smrgvoid
2306747b715SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size,
2316747b715Smrg                        xXIPassiveGrabDeviceReply * rep)
2326747b715Smrg{
2336747b715Smrg    char n;
2346747b715Smrg
2356747b715Smrg    swaps(&rep->sequenceNumber, n);
2366747b715Smrg    swapl(&rep->length, n);
2376747b715Smrg    swaps(&rep->num_modifiers, n);
2386747b715Smrg
2396747b715Smrg    WriteToClient(client, size, (char *)rep);
2406747b715Smrg}
2416747b715Smrg
2426747b715Smrgint
2436747b715SmrgSProcXIPassiveUngrabDevice(ClientPtr client)
2446747b715Smrg{
2456747b715Smrg    char n;
2466747b715Smrg    int i;
2476747b715Smrg    uint32_t *modifiers;
2486747b715Smrg
2496747b715Smrg    REQUEST(xXIPassiveUngrabDeviceReq);
2500b0d8713Smrg    REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
2516747b715Smrg
2526747b715Smrg    swaps(&stuff->length, n);
2536747b715Smrg    swapl(&stuff->grab_window, n);
2546747b715Smrg    swaps(&stuff->deviceid, n);
2556747b715Smrg    swapl(&stuff->detail, n);
2566747b715Smrg    swaps(&stuff->num_modifiers, n);
2576747b715Smrg
2580b0d8713Smrg    REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
2590b0d8713Smrg                       ((uint32_t) stuff->num_modifiers) << 2);
2606747b715Smrg    modifiers = (uint32_t*)&stuff[1];
2616747b715Smrg
2626747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
2636747b715Smrg        swapl(modifiers, n);
2646747b715Smrg
2656747b715Smrg    return ProcXIPassiveUngrabDevice(client);
2666747b715Smrg}
2676747b715Smrg
2686747b715Smrgint
2696747b715SmrgProcXIPassiveUngrabDevice(ClientPtr client)
2706747b715Smrg{
2716747b715Smrg    DeviceIntPtr dev, mod_dev;
2726747b715Smrg    WindowPtr win;
2736747b715Smrg    GrabRec tempGrab;
2746747b715Smrg    uint32_t* modifiers;
2756747b715Smrg    int i, rc;
2766747b715Smrg
2776747b715Smrg    REQUEST(xXIPassiveUngrabDeviceReq);
2780b0d8713Smrg    REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
2790b0d8713Smrg                       ((uint32_t) stuff->num_modifiers) << 2);
2806747b715Smrg
281475c125cSmrg    if (stuff->deviceid == XIAllDevices)
282475c125cSmrg        dev = inputInfo.all_devices;
283475c125cSmrg    else if (stuff->deviceid == XIAllMasterDevices)
284475c125cSmrg        dev = inputInfo.all_master_devices;
285475c125cSmrg    else
286475c125cSmrg    {
287475c125cSmrg        rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
288475c125cSmrg        if (rc != Success)
289475c125cSmrg	    return rc;
290475c125cSmrg    }
2916747b715Smrg
2926747b715Smrg    if (stuff->grab_type != XIGrabtypeButton &&
2936747b715Smrg        stuff->grab_type != XIGrabtypeKeycode &&
2946747b715Smrg        stuff->grab_type != XIGrabtypeEnter &&
2956747b715Smrg        stuff->grab_type != XIGrabtypeFocusIn)
2966747b715Smrg    {
2976747b715Smrg        client->errorValue = stuff->grab_type;
2986747b715Smrg        return BadValue;
2996747b715Smrg    }
3006747b715Smrg
3016747b715Smrg    if ((stuff->grab_type == XIGrabtypeEnter ||
3026747b715Smrg         stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
3036747b715Smrg    {
3046747b715Smrg        client->errorValue = stuff->detail;
3056747b715Smrg        return BadValue;
3066747b715Smrg    }
3076747b715Smrg
3086747b715Smrg    rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
3096747b715Smrg    if (rc != Success)
3106747b715Smrg        return rc;
3116747b715Smrg
3126747b715Smrg    if (!IsMaster(dev) && dev->u.master)
3136747b715Smrg        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
3146747b715Smrg    else
3156747b715Smrg        mod_dev = dev;
3166747b715Smrg
3176747b715Smrg    tempGrab.resource = client->clientAsMask;
3186747b715Smrg    tempGrab.device = dev;
3196747b715Smrg    tempGrab.window = win;
3206747b715Smrg    switch(stuff->grab_type)
3216747b715Smrg    {
3226747b715Smrg        case XIGrabtypeButton:  tempGrab.type = XI_ButtonPress; break;
3236747b715Smrg        case XIGrabtypeKeycode:  tempGrab.type = XI_KeyPress;    break;
3246747b715Smrg        case XIGrabtypeEnter:   tempGrab.type = XI_Enter;       break;
3256747b715Smrg        case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn;     break;
3266747b715Smrg    }
3276747b715Smrg    tempGrab.grabtype = GRABTYPE_XI2;
3286747b715Smrg    tempGrab.modifierDevice = mod_dev;
3296747b715Smrg    tempGrab.modifiersDetail.pMask = NULL;
3306747b715Smrg    tempGrab.detail.exact = stuff->detail;
3316747b715Smrg    tempGrab.detail.pMask = NULL;
3326747b715Smrg
3336747b715Smrg    modifiers = (uint32_t*)&stuff[1];
3346747b715Smrg
3356747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
3366747b715Smrg    {
3376747b715Smrg        tempGrab.modifiersDetail.exact = *modifiers;
3386747b715Smrg        DeletePassiveGrabFromList(&tempGrab);
3396747b715Smrg    }
3406747b715Smrg
3416747b715Smrg    return Success;
3426747b715Smrg}
343