xiselectev.c revision 9ace9065
16747b715Smrg/* 26747b715Smrg * Copyright 2008 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#ifdef HAVE_DIX_CONFIG_H 276747b715Smrg#include <dix-config.h> 286747b715Smrg#endif 296747b715Smrg 306747b715Smrg 316747b715Smrg#include "dixstruct.h" 326747b715Smrg#include "windowstr.h" 336747b715Smrg#include "exglobals.h" 346747b715Smrg#include "exevents.h" 356747b715Smrg#include <X11/extensions/XI2proto.h> 366747b715Smrg 376747b715Smrg#include "xiselectev.h" 386747b715Smrg 396747b715Smrg/** 406747b715Smrg * Check the given mask (in len bytes) for invalid mask bits. 416747b715Smrg * Invalid mask bits are any bits above XI2LastEvent. 426747b715Smrg * 436747b715Smrg * @return BadValue if at least one invalid bit is set or Success otherwise. 446747b715Smrg */ 459ace9065Smrgint XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len) 466747b715Smrg{ 476747b715Smrg if (len >= XIMaskLen(XI2LASTEVENT)) 486747b715Smrg { 496747b715Smrg int i; 506747b715Smrg for (i = XI2LASTEVENT + 1; i < len * 8; i++) 519ace9065Smrg { 526747b715Smrg if (BitIsOn(mask, i)) 539ace9065Smrg { 549ace9065Smrg client->errorValue = i; 556747b715Smrg return BadValue; 569ace9065Smrg } 579ace9065Smrg } 586747b715Smrg } 596747b715Smrg 606747b715Smrg return Success; 616747b715Smrg} 626747b715Smrg 636747b715Smrgint 646747b715SmrgSProcXISelectEvents(ClientPtr client) 656747b715Smrg{ 666747b715Smrg char n; 676747b715Smrg int i; 686747b715Smrg xXIEventMask* evmask; 696747b715Smrg 706747b715Smrg REQUEST(xXISelectEventsReq); 716747b715Smrg swaps(&stuff->length, n); 726747b715Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 736747b715Smrg swapl(&stuff->win, n); 746747b715Smrg swaps(&stuff->num_masks, n); 756747b715Smrg 766747b715Smrg evmask = (xXIEventMask*)&stuff[1]; 776747b715Smrg for (i = 0; i < stuff->num_masks; i++) 786747b715Smrg { 796747b715Smrg swaps(&evmask->deviceid, n); 806747b715Smrg swaps(&evmask->mask_len, n); 816747b715Smrg evmask = (xXIEventMask*)(((char*)&evmask[1]) + evmask->mask_len * 4); 826747b715Smrg } 836747b715Smrg 846747b715Smrg return (ProcXISelectEvents(client)); 856747b715Smrg} 866747b715Smrg 876747b715Smrgint 886747b715SmrgProcXISelectEvents(ClientPtr client) 896747b715Smrg{ 906747b715Smrg int rc, num_masks; 916747b715Smrg WindowPtr win; 926747b715Smrg DeviceIntPtr dev; 936747b715Smrg DeviceIntRec dummy; 946747b715Smrg xXIEventMask *evmask; 956747b715Smrg int *types = NULL; 966747b715Smrg int len; 976747b715Smrg 986747b715Smrg REQUEST(xXISelectEventsReq); 996747b715Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 1006747b715Smrg 1016747b715Smrg if (stuff->num_masks == 0) 1026747b715Smrg return BadValue; 1036747b715Smrg 1046747b715Smrg rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess); 1056747b715Smrg if (rc != Success) 1066747b715Smrg return rc; 1076747b715Smrg 1086747b715Smrg len = sz_xXISelectEventsReq; 1096747b715Smrg 1106747b715Smrg /* check request validity */ 1116747b715Smrg evmask = (xXIEventMask*)&stuff[1]; 1126747b715Smrg num_masks = stuff->num_masks; 1136747b715Smrg while(num_masks--) 1146747b715Smrg { 1156747b715Smrg len += sizeof(xXIEventMask) + evmask->mask_len * 4; 1166747b715Smrg 1176747b715Smrg if (bytes_to_int32(len) > stuff->length) 1186747b715Smrg return BadLength; 1196747b715Smrg 1206747b715Smrg if (evmask->deviceid != XIAllDevices && 1216747b715Smrg evmask->deviceid != XIAllMasterDevices) 1226747b715Smrg rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 1236747b715Smrg else { 1246747b715Smrg /* XXX: XACE here? */ 1256747b715Smrg } 1266747b715Smrg if (rc != Success) 1276747b715Smrg return rc; 1286747b715Smrg 1296747b715Smrg /* hierarchy event mask is not allowed on devices */ 1306747b715Smrg if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) 1316747b715Smrg { 1326747b715Smrg unsigned char *bits = (unsigned char*)&evmask[1]; 1336747b715Smrg if (BitIsOn(bits, XI_HierarchyChanged)) 1349ace9065Smrg { 1359ace9065Smrg client->errorValue = XI_HierarchyChanged; 1366747b715Smrg return BadValue; 1379ace9065Smrg } 1386747b715Smrg } 1396747b715Smrg 1406747b715Smrg /* Raw events may only be selected on root windows */ 1416747b715Smrg if (win->parent && evmask->mask_len >= 1) 1426747b715Smrg { 1436747b715Smrg unsigned char *bits = (unsigned char*)&evmask[1]; 1446747b715Smrg if (BitIsOn(bits, XI_RawKeyPress) || 1456747b715Smrg BitIsOn(bits, XI_RawKeyRelease) || 1466747b715Smrg BitIsOn(bits, XI_RawButtonPress) || 1476747b715Smrg BitIsOn(bits, XI_RawButtonRelease) || 1486747b715Smrg BitIsOn(bits, XI_RawMotion)) 1499ace9065Smrg { 1509ace9065Smrg client->errorValue = XI_RawKeyPress; 1516747b715Smrg return BadValue; 1529ace9065Smrg } 1536747b715Smrg } 1546747b715Smrg 1559ace9065Smrg if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1], 1566747b715Smrg evmask->mask_len * 4) != Success) 1576747b715Smrg return BadValue; 1586747b715Smrg 1596747b715Smrg evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 1606747b715Smrg evmask++; 1616747b715Smrg } 1626747b715Smrg 1636747b715Smrg if (bytes_to_int32(len) != stuff->length) 1646747b715Smrg return BadLength; 1656747b715Smrg 1666747b715Smrg /* Set masks on window */ 1676747b715Smrg evmask = (xXIEventMask*)&stuff[1]; 1686747b715Smrg num_masks = stuff->num_masks; 1696747b715Smrg while(num_masks--) 1706747b715Smrg { 1716747b715Smrg if (evmask->deviceid == XIAllDevices || 1726747b715Smrg evmask->deviceid == XIAllMasterDevices) 1736747b715Smrg { 1746747b715Smrg dummy.id = evmask->deviceid; 1756747b715Smrg dev = &dummy; 1766747b715Smrg } else 1776747b715Smrg dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 1786747b715Smrg if (XISetEventMask(dev, win, client, evmask->mask_len * 4, 1796747b715Smrg (unsigned char*)&evmask[1]) != Success) 1806747b715Smrg return BadAlloc; 1816747b715Smrg evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 1826747b715Smrg evmask++; 1836747b715Smrg } 1846747b715Smrg 1856747b715Smrg RecalculateDeliverableEvents(win); 1866747b715Smrg 1876747b715Smrg free(types); 1886747b715Smrg return Success; 1896747b715Smrg} 1906747b715Smrg 1916747b715Smrg 1926747b715Smrgint 1936747b715SmrgSProcXIGetSelectedEvents(ClientPtr client) 1946747b715Smrg{ 1956747b715Smrg char n; 1966747b715Smrg 1976747b715Smrg REQUEST(xXIGetSelectedEventsReq); 1986747b715Smrg swaps(&stuff->length, n); 1996747b715Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 2006747b715Smrg swapl(&stuff->win, n); 2016747b715Smrg 2026747b715Smrg return (ProcXIGetSelectedEvents(client)); 2036747b715Smrg} 2046747b715Smrg 2056747b715Smrgint 2066747b715SmrgProcXIGetSelectedEvents(ClientPtr client) 2076747b715Smrg{ 2086747b715Smrg int rc, i; 2096747b715Smrg WindowPtr win; 2106747b715Smrg char n; 2116747b715Smrg char *buffer = NULL; 2126747b715Smrg xXIGetSelectedEventsReply reply; 2136747b715Smrg OtherInputMasks *masks; 2146747b715Smrg InputClientsPtr others = NULL; 2156747b715Smrg xXIEventMask *evmask = NULL; 2166747b715Smrg DeviceIntPtr dev; 2176747b715Smrg 2186747b715Smrg REQUEST(xXIGetSelectedEventsReq); 2196747b715Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 2206747b715Smrg 2216747b715Smrg rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess); 2226747b715Smrg if (rc != Success) 2236747b715Smrg return rc; 2246747b715Smrg 2256747b715Smrg reply.repType = X_Reply; 2266747b715Smrg reply.RepType = X_XIGetSelectedEvents; 2276747b715Smrg reply.length = 0; 2286747b715Smrg reply.sequenceNumber = client->sequence; 2296747b715Smrg reply.num_masks = 0; 2306747b715Smrg 2316747b715Smrg masks = wOtherInputMasks(win); 2326747b715Smrg if (masks) 2336747b715Smrg { 2346747b715Smrg for (others = wOtherInputMasks(win)->inputClients; others; 2356747b715Smrg others = others->next) { 2366747b715Smrg if (SameClient(others, client)) { 2376747b715Smrg break; 2386747b715Smrg } 2396747b715Smrg } 2406747b715Smrg } 2416747b715Smrg 2426747b715Smrg if (!others) 2436747b715Smrg { 2446747b715Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 2456747b715Smrg return Success; 2466747b715Smrg } 2476747b715Smrg 2486747b715Smrg buffer = calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE)); 2496747b715Smrg if (!buffer) 2506747b715Smrg return BadAlloc; 2516747b715Smrg 2526747b715Smrg evmask = (xXIEventMask*)buffer; 2536747b715Smrg for (i = 0; i < MAXDEVICES; i++) 2546747b715Smrg { 2556747b715Smrg int j; 2566747b715Smrg unsigned char *devmask = others->xi2mask[i]; 2576747b715Smrg 2586747b715Smrg if (i > 2) 2596747b715Smrg { 2606747b715Smrg rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess); 2616747b715Smrg if (rc != Success) 2626747b715Smrg continue; 2636747b715Smrg } 2646747b715Smrg 2656747b715Smrg 2666747b715Smrg for (j = XI2MASKSIZE - 1; j >= 0; j--) 2676747b715Smrg { 2686747b715Smrg if (devmask[j] != 0) 2696747b715Smrg { 2706747b715Smrg int mask_len = (j + 4)/4; /* j is an index, hence + 4, not + 3 */ 2716747b715Smrg evmask->deviceid = i; 2726747b715Smrg evmask->mask_len = mask_len; 2736747b715Smrg reply.num_masks++; 2746747b715Smrg reply.length += sizeof(xXIEventMask)/4 + evmask->mask_len; 2756747b715Smrg 2766747b715Smrg if (client->swapped) 2776747b715Smrg { 2786747b715Smrg swaps(&evmask->deviceid, n); 2796747b715Smrg swaps(&evmask->mask_len, n); 2806747b715Smrg } 2816747b715Smrg 2826747b715Smrg memcpy(&evmask[1], devmask, j + 1); 2836747b715Smrg evmask = (xXIEventMask*)((char*)evmask + 2846747b715Smrg sizeof(xXIEventMask) + mask_len * 4); 2856747b715Smrg break; 2866747b715Smrg } 2876747b715Smrg } 2886747b715Smrg } 2896747b715Smrg 2906747b715Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 2916747b715Smrg 2926747b715Smrg if (reply.num_masks) 2936747b715Smrg WriteToClient(client, reply.length * 4, buffer); 2946747b715Smrg 2956747b715Smrg free(buffer); 2966747b715Smrg return Success; 2976747b715Smrg} 2986747b715Smrg 2996747b715Smrgvoid SRepXIGetSelectedEvents(ClientPtr client, 3006747b715Smrg int len, xXIGetSelectedEventsReply *rep) 3016747b715Smrg{ 3026747b715Smrg char n; 3036747b715Smrg 3046747b715Smrg swaps(&rep->sequenceNumber, n); 3056747b715Smrg swapl(&rep->length, n); 3066747b715Smrg swaps(&rep->num_masks, n); 3076747b715Smrg WriteToClient(client, len, (char *)rep); 3086747b715Smrg} 3096747b715Smrg 3106747b715Smrg 311