xiselectev.c revision 0b0d8713
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; 680b0d8713Smrg int len; 696747b715Smrg xXIEventMask* evmask; 706747b715Smrg 716747b715Smrg REQUEST(xXISelectEventsReq); 726747b715Smrg swaps(&stuff->length, n); 736747b715Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 746747b715Smrg swapl(&stuff->win, n); 756747b715Smrg swaps(&stuff->num_masks, n); 766747b715Smrg 770b0d8713Smrg len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq)); 786747b715Smrg evmask = (xXIEventMask*)&stuff[1]; 796747b715Smrg for (i = 0; i < stuff->num_masks; i++) 806747b715Smrg { 810b0d8713Smrg if (len < bytes_to_int32(sizeof(xXIEventMask))) 820b0d8713Smrg return BadLength; 830b0d8713Smrg len -= bytes_to_int32(sizeof(xXIEventMask)); 846747b715Smrg swaps(&evmask->deviceid, n); 856747b715Smrg swaps(&evmask->mask_len, n); 860b0d8713Smrg if (len < evmask->mask_len) 870b0d8713Smrg return BadLength; 880b0d8713Smrg len -= evmask->mask_len; 896747b715Smrg evmask = (xXIEventMask*)(((char*)&evmask[1]) + evmask->mask_len * 4); 906747b715Smrg } 916747b715Smrg 926747b715Smrg return (ProcXISelectEvents(client)); 936747b715Smrg} 946747b715Smrg 956747b715Smrgint 966747b715SmrgProcXISelectEvents(ClientPtr client) 976747b715Smrg{ 986747b715Smrg int rc, num_masks; 996747b715Smrg WindowPtr win; 1006747b715Smrg DeviceIntPtr dev; 1016747b715Smrg DeviceIntRec dummy; 1026747b715Smrg xXIEventMask *evmask; 1036747b715Smrg int *types = NULL; 1046747b715Smrg int len; 1056747b715Smrg 1066747b715Smrg REQUEST(xXISelectEventsReq); 1076747b715Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 1086747b715Smrg 1096747b715Smrg if (stuff->num_masks == 0) 1106747b715Smrg return BadValue; 1116747b715Smrg 1126747b715Smrg rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess); 1136747b715Smrg if (rc != Success) 1146747b715Smrg return rc; 1156747b715Smrg 1166747b715Smrg len = sz_xXISelectEventsReq; 1176747b715Smrg 1186747b715Smrg /* check request validity */ 1196747b715Smrg evmask = (xXIEventMask*)&stuff[1]; 1206747b715Smrg num_masks = stuff->num_masks; 1216747b715Smrg while(num_masks--) 1226747b715Smrg { 1236747b715Smrg len += sizeof(xXIEventMask) + evmask->mask_len * 4; 1246747b715Smrg 1256747b715Smrg if (bytes_to_int32(len) > stuff->length) 1266747b715Smrg return BadLength; 1276747b715Smrg 1286747b715Smrg if (evmask->deviceid != XIAllDevices && 1296747b715Smrg evmask->deviceid != XIAllMasterDevices) 1306747b715Smrg rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 1316747b715Smrg else { 1326747b715Smrg /* XXX: XACE here? */ 1336747b715Smrg } 1346747b715Smrg if (rc != Success) 1356747b715Smrg return rc; 1366747b715Smrg 1376747b715Smrg /* hierarchy event mask is not allowed on devices */ 1386747b715Smrg if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) 1396747b715Smrg { 1406747b715Smrg unsigned char *bits = (unsigned char*)&evmask[1]; 1416747b715Smrg if (BitIsOn(bits, XI_HierarchyChanged)) 1429ace9065Smrg { 1439ace9065Smrg client->errorValue = XI_HierarchyChanged; 1446747b715Smrg return BadValue; 1459ace9065Smrg } 1466747b715Smrg } 1476747b715Smrg 1486747b715Smrg /* Raw events may only be selected on root windows */ 1496747b715Smrg if (win->parent && evmask->mask_len >= 1) 1506747b715Smrg { 1516747b715Smrg unsigned char *bits = (unsigned char*)&evmask[1]; 1526747b715Smrg if (BitIsOn(bits, XI_RawKeyPress) || 1536747b715Smrg BitIsOn(bits, XI_RawKeyRelease) || 1546747b715Smrg BitIsOn(bits, XI_RawButtonPress) || 1556747b715Smrg BitIsOn(bits, XI_RawButtonRelease) || 1566747b715Smrg BitIsOn(bits, XI_RawMotion)) 1579ace9065Smrg { 1589ace9065Smrg client->errorValue = XI_RawKeyPress; 1596747b715Smrg return BadValue; 1609ace9065Smrg } 1616747b715Smrg } 1626747b715Smrg 1639ace9065Smrg if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1], 1646747b715Smrg evmask->mask_len * 4) != Success) 1656747b715Smrg return BadValue; 1666747b715Smrg 1676747b715Smrg evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 1686747b715Smrg evmask++; 1696747b715Smrg } 1706747b715Smrg 1716747b715Smrg if (bytes_to_int32(len) != stuff->length) 1726747b715Smrg return BadLength; 1736747b715Smrg 1746747b715Smrg /* Set masks on window */ 1756747b715Smrg evmask = (xXIEventMask*)&stuff[1]; 1766747b715Smrg num_masks = stuff->num_masks; 1776747b715Smrg while(num_masks--) 1786747b715Smrg { 1796747b715Smrg if (evmask->deviceid == XIAllDevices || 1806747b715Smrg evmask->deviceid == XIAllMasterDevices) 1816747b715Smrg { 1826747b715Smrg dummy.id = evmask->deviceid; 1836747b715Smrg dev = &dummy; 1846747b715Smrg } else 1856747b715Smrg dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 1866747b715Smrg if (XISetEventMask(dev, win, client, evmask->mask_len * 4, 1876747b715Smrg (unsigned char*)&evmask[1]) != Success) 1886747b715Smrg return BadAlloc; 1896747b715Smrg evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 1906747b715Smrg evmask++; 1916747b715Smrg } 1926747b715Smrg 1936747b715Smrg RecalculateDeliverableEvents(win); 1946747b715Smrg 1956747b715Smrg free(types); 1966747b715Smrg return Success; 1976747b715Smrg} 1986747b715Smrg 1996747b715Smrg 2006747b715Smrgint 2016747b715SmrgSProcXIGetSelectedEvents(ClientPtr client) 2026747b715Smrg{ 2036747b715Smrg char n; 2046747b715Smrg 2056747b715Smrg REQUEST(xXIGetSelectedEventsReq); 2066747b715Smrg swaps(&stuff->length, n); 2076747b715Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 2086747b715Smrg swapl(&stuff->win, n); 2096747b715Smrg 2106747b715Smrg return (ProcXIGetSelectedEvents(client)); 2116747b715Smrg} 2126747b715Smrg 2136747b715Smrgint 2146747b715SmrgProcXIGetSelectedEvents(ClientPtr client) 2156747b715Smrg{ 2166747b715Smrg int rc, i; 2176747b715Smrg WindowPtr win; 2186747b715Smrg char n; 2196747b715Smrg char *buffer = NULL; 2206747b715Smrg xXIGetSelectedEventsReply reply; 2216747b715Smrg OtherInputMasks *masks; 2226747b715Smrg InputClientsPtr others = NULL; 2236747b715Smrg xXIEventMask *evmask = NULL; 2246747b715Smrg DeviceIntPtr dev; 2256747b715Smrg 2266747b715Smrg REQUEST(xXIGetSelectedEventsReq); 2276747b715Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 2286747b715Smrg 2296747b715Smrg rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess); 2306747b715Smrg if (rc != Success) 2316747b715Smrg return rc; 2326747b715Smrg 2336747b715Smrg reply.repType = X_Reply; 2346747b715Smrg reply.RepType = X_XIGetSelectedEvents; 2356747b715Smrg reply.length = 0; 2366747b715Smrg reply.sequenceNumber = client->sequence; 2376747b715Smrg reply.num_masks = 0; 2386747b715Smrg 2396747b715Smrg masks = wOtherInputMasks(win); 2406747b715Smrg if (masks) 2416747b715Smrg { 2426747b715Smrg for (others = wOtherInputMasks(win)->inputClients; others; 2436747b715Smrg others = others->next) { 2446747b715Smrg if (SameClient(others, client)) { 2456747b715Smrg break; 2466747b715Smrg } 2476747b715Smrg } 2486747b715Smrg } 2496747b715Smrg 2506747b715Smrg if (!others) 2516747b715Smrg { 2526747b715Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 2536747b715Smrg return Success; 2546747b715Smrg } 2556747b715Smrg 2566747b715Smrg buffer = calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE)); 2576747b715Smrg if (!buffer) 2586747b715Smrg return BadAlloc; 2596747b715Smrg 2606747b715Smrg evmask = (xXIEventMask*)buffer; 2616747b715Smrg for (i = 0; i < MAXDEVICES; i++) 2626747b715Smrg { 2636747b715Smrg int j; 2646747b715Smrg unsigned char *devmask = others->xi2mask[i]; 2656747b715Smrg 2666747b715Smrg if (i > 2) 2676747b715Smrg { 2686747b715Smrg rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess); 2696747b715Smrg if (rc != Success) 2706747b715Smrg continue; 2716747b715Smrg } 2726747b715Smrg 2736747b715Smrg 2746747b715Smrg for (j = XI2MASKSIZE - 1; j >= 0; j--) 2756747b715Smrg { 2766747b715Smrg if (devmask[j] != 0) 2776747b715Smrg { 2786747b715Smrg int mask_len = (j + 4)/4; /* j is an index, hence + 4, not + 3 */ 2796747b715Smrg evmask->deviceid = i; 2806747b715Smrg evmask->mask_len = mask_len; 2816747b715Smrg reply.num_masks++; 2826747b715Smrg reply.length += sizeof(xXIEventMask)/4 + evmask->mask_len; 2836747b715Smrg 2846747b715Smrg if (client->swapped) 2856747b715Smrg { 2866747b715Smrg swaps(&evmask->deviceid, n); 2876747b715Smrg swaps(&evmask->mask_len, n); 2886747b715Smrg } 2896747b715Smrg 2906747b715Smrg memcpy(&evmask[1], devmask, j + 1); 2916747b715Smrg evmask = (xXIEventMask*)((char*)evmask + 2926747b715Smrg sizeof(xXIEventMask) + mask_len * 4); 2936747b715Smrg break; 2946747b715Smrg } 2956747b715Smrg } 2966747b715Smrg } 2976747b715Smrg 2986747b715Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 2996747b715Smrg 3006747b715Smrg if (reply.num_masks) 3016747b715Smrg WriteToClient(client, reply.length * 4, buffer); 3026747b715Smrg 3036747b715Smrg free(buffer); 3046747b715Smrg return Success; 3056747b715Smrg} 3066747b715Smrg 3076747b715Smrgvoid SRepXIGetSelectedEvents(ClientPtr client, 3086747b715Smrg int len, xXIGetSelectedEventsReply *rep) 3096747b715Smrg{ 3106747b715Smrg char n; 3116747b715Smrg 3126747b715Smrg swaps(&rep->sequenceNumber, n); 3136747b715Smrg swapl(&rep->length, n); 3146747b715Smrg swaps(&rep->num_masks, n); 3156747b715Smrg WriteToClient(client, len, (char *)rep); 3166747b715Smrg} 3176747b715Smrg 3186747b715Smrg 319