xipassivegrab.c revision 9ace9065
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);
566747b715Smrg
576747b715Smrg    swaps(&stuff->length, n);
586747b715Smrg    swaps(&stuff->deviceid, n);
596747b715Smrg    swapl(&stuff->grab_window, n);
606747b715Smrg    swapl(&stuff->cursor, n);
616747b715Smrg    swapl(&stuff->time, n);
626747b715Smrg    swapl(&stuff->detail, n);
636747b715Smrg    swaps(&stuff->mask_len, n);
646747b715Smrg    swaps(&stuff->num_modifiers, n);
656747b715Smrg
666747b715Smrg    mods = (xXIModifierInfo*)&stuff[1];
676747b715Smrg
686747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, mods++)
696747b715Smrg    {
706747b715Smrg        swapl(&mods->base_mods, n);
716747b715Smrg        swapl(&mods->latched_mods, n);
726747b715Smrg        swapl(&mods->locked_mods, n);
736747b715Smrg    }
746747b715Smrg
756747b715Smrg    return ProcXIPassiveGrabDevice(client);
766747b715Smrg}
776747b715Smrg
786747b715Smrgint
796747b715SmrgProcXIPassiveGrabDevice(ClientPtr client)
806747b715Smrg{
816747b715Smrg    DeviceIntPtr dev, mod_dev;
826747b715Smrg    xXIPassiveGrabDeviceReply rep;
836747b715Smrg    int i, ret = Success;
846747b715Smrg    uint8_t status;
856747b715Smrg    uint32_t *modifiers;
866747b715Smrg    xXIGrabModifierInfo *modifiers_failed;
876747b715Smrg    GrabMask mask;
886747b715Smrg    GrabParameters param;
896747b715Smrg    void *tmp;
906747b715Smrg    int mask_len;
919ace9065Smrg    int n;
926747b715Smrg
936747b715Smrg    REQUEST(xXIPassiveGrabDeviceReq);
946747b715Smrg    REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
956747b715Smrg
966747b715Smrg    if (stuff->deviceid == XIAllDevices)
976747b715Smrg        dev = inputInfo.all_devices;
986747b715Smrg    else if (stuff->deviceid == XIAllMasterDevices)
996747b715Smrg        dev = inputInfo.all_master_devices;
1006747b715Smrg    else
1016747b715Smrg    {
1026747b715Smrg        ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
1036747b715Smrg        if (ret != Success)
1049ace9065Smrg        {
1059ace9065Smrg            client->errorValue = stuff->deviceid;
1066747b715Smrg            return ret;
1079ace9065Smrg        }
1086747b715Smrg    }
1096747b715Smrg
1106747b715Smrg    if (stuff->grab_type != XIGrabtypeButton &&
1116747b715Smrg        stuff->grab_type != XIGrabtypeKeycode &&
1126747b715Smrg        stuff->grab_type != XIGrabtypeEnter &&
1136747b715Smrg        stuff->grab_type != XIGrabtypeFocusIn)
1146747b715Smrg    {
1156747b715Smrg        client->errorValue = stuff->grab_type;
1166747b715Smrg        return BadValue;
1176747b715Smrg    }
1186747b715Smrg
1196747b715Smrg    if ((stuff->grab_type == XIGrabtypeEnter ||
1206747b715Smrg         stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
1216747b715Smrg    {
1226747b715Smrg        client->errorValue = stuff->detail;
1236747b715Smrg        return BadValue;
1246747b715Smrg    }
1256747b715Smrg
1269ace9065Smrg    if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
1276747b715Smrg                               stuff->mask_len * 4) != Success)
1286747b715Smrg        return BadValue;
1296747b715Smrg
1306747b715Smrg    mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
1316747b715Smrg    memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
1326747b715Smrg    memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
1336747b715Smrg
1346747b715Smrg    rep.repType = X_Reply;
1356747b715Smrg    rep.RepType = X_XIPassiveGrabDevice;
1366747b715Smrg    rep.length = 0;
1376747b715Smrg    rep.sequenceNumber = client->sequence;
1386747b715Smrg    rep.num_modifiers = 0;
1396747b715Smrg
1406747b715Smrg    memset(&param, 0, sizeof(param));
1416747b715Smrg    param.grabtype = GRABTYPE_XI2;
1426747b715Smrg    param.ownerEvents = stuff->owner_events;
1436747b715Smrg    param.this_device_mode = stuff->grab_mode;
1446747b715Smrg    param.other_devices_mode = stuff->paired_device_mode;
1456747b715Smrg    param.grabWindow = stuff->grab_window;
1466747b715Smrg    param.cursor = stuff->cursor;
1476747b715Smrg
1486747b715Smrg    if (stuff->cursor != None)
1496747b715Smrg    {
1506747b715Smrg        status = dixLookupResourceByType(&tmp, stuff->cursor,
1516747b715Smrg                                         RT_CURSOR, client, DixUseAccess);
1526747b715Smrg	if (status != Success)
1536747b715Smrg	{
1546747b715Smrg	    client->errorValue = stuff->cursor;
1556747b715Smrg	    return status;
1566747b715Smrg	}
1576747b715Smrg    }
1586747b715Smrg
1596747b715Smrg    status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
1606747b715Smrg    if (status != Success)
1616747b715Smrg	return status;
1626747b715Smrg
1636747b715Smrg    status = CheckGrabValues(client, &param);
1649ace9065Smrg    if (status != Success)
1659ace9065Smrg        return status;
1666747b715Smrg
1676747b715Smrg    modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
1686747b715Smrg    modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
1696747b715Smrg    if (!modifiers_failed)
1706747b715Smrg        return BadAlloc;
1716747b715Smrg
1726747b715Smrg    if (!IsMaster(dev) && dev->u.master)
1736747b715Smrg        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
1746747b715Smrg    else
1756747b715Smrg        mod_dev = dev;
1766747b715Smrg
1776747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
1786747b715Smrg    {
1796747b715Smrg        param.modifiers = *modifiers;
1806747b715Smrg        switch(stuff->grab_type)
1816747b715Smrg        {
1826747b715Smrg            case XIGrabtypeButton:
1836747b715Smrg                status = GrabButton(client, dev, mod_dev, stuff->detail,
1846747b715Smrg                                    &param, GRABTYPE_XI2, &mask);
1856747b715Smrg                break;
1866747b715Smrg            case XIGrabtypeKeycode:
1876747b715Smrg                status = GrabKey(client, dev, mod_dev, stuff->detail,
1886747b715Smrg                                 &param, GRABTYPE_XI2, &mask);
1896747b715Smrg                break;
1906747b715Smrg            case XIGrabtypeEnter:
1916747b715Smrg            case XIGrabtypeFocusIn:
1926747b715Smrg                status = GrabWindow(client, dev, stuff->grab_type,
1936747b715Smrg                                    &param, &mask);
1946747b715Smrg                break;
1956747b715Smrg        }
1966747b715Smrg
1976747b715Smrg        if (status != GrabSuccess)
1986747b715Smrg        {
1996747b715Smrg            xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
2006747b715Smrg
2016747b715Smrg            info->status = status;
2026747b715Smrg            info->modifiers = *modifiers;
2039ace9065Smrg            if (client->swapped)
2049ace9065Smrg                swapl(&info->modifiers, n);
2059ace9065Smrg
2066747b715Smrg            rep.num_modifiers++;
2079ace9065Smrg            rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
2086747b715Smrg        }
2096747b715Smrg    }
2106747b715Smrg
2116747b715Smrg    WriteReplyToClient(client, sizeof(rep), &rep);
2126747b715Smrg    if (rep.num_modifiers)
2139ace9065Smrg        WriteToClient(client, rep.length * 4, (char*)modifiers_failed);
2149ace9065Smrg
2156747b715Smrg    free(modifiers_failed);
2166747b715Smrg    return ret;
2176747b715Smrg}
2186747b715Smrg
2196747b715Smrgvoid
2206747b715SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size,
2216747b715Smrg                        xXIPassiveGrabDeviceReply * rep)
2226747b715Smrg{
2236747b715Smrg    char n;
2246747b715Smrg
2256747b715Smrg    swaps(&rep->sequenceNumber, n);
2266747b715Smrg    swapl(&rep->length, n);
2276747b715Smrg    swaps(&rep->num_modifiers, n);
2286747b715Smrg
2296747b715Smrg    WriteToClient(client, size, (char *)rep);
2306747b715Smrg}
2316747b715Smrg
2326747b715Smrgint
2336747b715SmrgSProcXIPassiveUngrabDevice(ClientPtr client)
2346747b715Smrg{
2356747b715Smrg    char n;
2366747b715Smrg    int i;
2376747b715Smrg    uint32_t *modifiers;
2386747b715Smrg
2396747b715Smrg    REQUEST(xXIPassiveUngrabDeviceReq);
2406747b715Smrg
2416747b715Smrg    swaps(&stuff->length, n);
2426747b715Smrg    swapl(&stuff->grab_window, n);
2436747b715Smrg    swaps(&stuff->deviceid, n);
2446747b715Smrg    swapl(&stuff->detail, n);
2456747b715Smrg    swaps(&stuff->num_modifiers, n);
2466747b715Smrg
2476747b715Smrg    modifiers = (uint32_t*)&stuff[1];
2486747b715Smrg
2496747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
2506747b715Smrg        swapl(modifiers, n);
2516747b715Smrg
2526747b715Smrg    return ProcXIPassiveUngrabDevice(client);
2536747b715Smrg}
2546747b715Smrg
2556747b715Smrgint
2566747b715SmrgProcXIPassiveUngrabDevice(ClientPtr client)
2576747b715Smrg{
2586747b715Smrg    DeviceIntPtr dev, mod_dev;
2596747b715Smrg    WindowPtr win;
2606747b715Smrg    GrabRec tempGrab;
2616747b715Smrg    uint32_t* modifiers;
2626747b715Smrg    int i, rc;
2636747b715Smrg
2646747b715Smrg    REQUEST(xXIPassiveUngrabDeviceReq);
2656747b715Smrg    REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
2666747b715Smrg
2676747b715Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
2686747b715Smrg    if (rc != Success)
2696747b715Smrg	return rc;
2706747b715Smrg
2716747b715Smrg    if (stuff->grab_type != XIGrabtypeButton &&
2726747b715Smrg        stuff->grab_type != XIGrabtypeKeycode &&
2736747b715Smrg        stuff->grab_type != XIGrabtypeEnter &&
2746747b715Smrg        stuff->grab_type != XIGrabtypeFocusIn)
2756747b715Smrg    {
2766747b715Smrg        client->errorValue = stuff->grab_type;
2776747b715Smrg        return BadValue;
2786747b715Smrg    }
2796747b715Smrg
2806747b715Smrg    if ((stuff->grab_type == XIGrabtypeEnter ||
2816747b715Smrg         stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
2826747b715Smrg    {
2836747b715Smrg        client->errorValue = stuff->detail;
2846747b715Smrg        return BadValue;
2856747b715Smrg    }
2866747b715Smrg
2876747b715Smrg    rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
2886747b715Smrg    if (rc != Success)
2896747b715Smrg        return rc;
2906747b715Smrg
2916747b715Smrg    if (!IsMaster(dev) && dev->u.master)
2926747b715Smrg        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
2936747b715Smrg    else
2946747b715Smrg        mod_dev = dev;
2956747b715Smrg
2966747b715Smrg    tempGrab.resource = client->clientAsMask;
2976747b715Smrg    tempGrab.device = dev;
2986747b715Smrg    tempGrab.window = win;
2996747b715Smrg    switch(stuff->grab_type)
3006747b715Smrg    {
3016747b715Smrg        case XIGrabtypeButton:  tempGrab.type = XI_ButtonPress; break;
3026747b715Smrg        case XIGrabtypeKeycode:  tempGrab.type = XI_KeyPress;    break;
3036747b715Smrg        case XIGrabtypeEnter:   tempGrab.type = XI_Enter;       break;
3046747b715Smrg        case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn;     break;
3056747b715Smrg    }
3066747b715Smrg    tempGrab.grabtype = GRABTYPE_XI2;
3076747b715Smrg    tempGrab.modifierDevice = mod_dev;
3086747b715Smrg    tempGrab.modifiersDetail.pMask = NULL;
3096747b715Smrg    tempGrab.detail.exact = stuff->detail;
3106747b715Smrg    tempGrab.detail.pMask = NULL;
3116747b715Smrg
3126747b715Smrg    modifiers = (uint32_t*)&stuff[1];
3136747b715Smrg
3146747b715Smrg    for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
3156747b715Smrg    {
3166747b715Smrg        tempGrab.modifiersDetail.exact = *modifiers;
3176747b715Smrg        DeletePassiveGrabFromList(&tempGrab);
3186747b715Smrg    }
3196747b715Smrg
3206747b715Smrg    return Success;
3216747b715Smrg}
322