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