1706f2543Smrg/* 2706f2543Smrg * Copyright 2008 Red Hat, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice (including the next 12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 13706f2543Smrg * Software. 14706f2543Smrg * 15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21706f2543Smrg * DEALINGS IN THE SOFTWARE. 22706f2543Smrg * 23706f2543Smrg * Author: Peter Hutterer 24706f2543Smrg */ 25706f2543Smrg 26706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 27706f2543Smrg#include <dix-config.h> 28706f2543Smrg#endif 29706f2543Smrg 30706f2543Smrg 31706f2543Smrg#include "dixstruct.h" 32706f2543Smrg#include "windowstr.h" 33706f2543Smrg#include "exglobals.h" 34706f2543Smrg#include "exevents.h" 35706f2543Smrg#include <X11/extensions/XI2proto.h> 36706f2543Smrg 37706f2543Smrg#include "xiselectev.h" 38706f2543Smrg 39706f2543Smrg/** 40706f2543Smrg * Check the given mask (in len bytes) for invalid mask bits. 41706f2543Smrg * Invalid mask bits are any bits above XI2LastEvent. 42706f2543Smrg * 43706f2543Smrg * @return BadValue if at least one invalid bit is set or Success otherwise. 44706f2543Smrg */ 45706f2543Smrgint XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len) 46706f2543Smrg{ 47706f2543Smrg if (len >= XIMaskLen(XI2LASTEVENT)) 48706f2543Smrg { 49706f2543Smrg int i; 50706f2543Smrg for (i = XI2LASTEVENT + 1; i < len * 8; i++) 51706f2543Smrg { 52706f2543Smrg if (BitIsOn(mask, i)) 53706f2543Smrg { 54706f2543Smrg client->errorValue = i; 55706f2543Smrg return BadValue; 56706f2543Smrg } 57706f2543Smrg } 58706f2543Smrg } 59706f2543Smrg 60706f2543Smrg return Success; 61706f2543Smrg} 62706f2543Smrg 63706f2543Smrgint 64706f2543SmrgSProcXISelectEvents(ClientPtr client) 65706f2543Smrg{ 66706f2543Smrg char n; 67706f2543Smrg int i; 68706f2543Smrg int len; 69706f2543Smrg xXIEventMask* evmask; 70706f2543Smrg 71706f2543Smrg REQUEST(xXISelectEventsReq); 72706f2543Smrg swaps(&stuff->length, n); 73706f2543Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 74706f2543Smrg swapl(&stuff->win, n); 75706f2543Smrg swaps(&stuff->num_masks, n); 76706f2543Smrg 77706f2543Smrg len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq)); 78706f2543Smrg evmask = (xXIEventMask*)&stuff[1]; 79706f2543Smrg for (i = 0; i < stuff->num_masks; i++) 80706f2543Smrg { 81706f2543Smrg if (len < bytes_to_int32(sizeof(xXIEventMask))) 82706f2543Smrg return BadLength; 83706f2543Smrg len -= bytes_to_int32(sizeof(xXIEventMask)); 84706f2543Smrg swaps(&evmask->deviceid, n); 85706f2543Smrg swaps(&evmask->mask_len, n); 86706f2543Smrg if (len < evmask->mask_len) 87706f2543Smrg return BadLength; 88706f2543Smrg len -= evmask->mask_len; 89706f2543Smrg evmask = (xXIEventMask*)(((char*)&evmask[1]) + evmask->mask_len * 4); 90706f2543Smrg } 91706f2543Smrg 92706f2543Smrg return (ProcXISelectEvents(client)); 93706f2543Smrg} 94706f2543Smrg 95706f2543Smrgint 96706f2543SmrgProcXISelectEvents(ClientPtr client) 97706f2543Smrg{ 98706f2543Smrg int rc, num_masks; 99706f2543Smrg WindowPtr win; 100706f2543Smrg DeviceIntPtr dev; 101706f2543Smrg DeviceIntRec dummy; 102706f2543Smrg xXIEventMask *evmask; 103706f2543Smrg int *types = NULL; 104706f2543Smrg int len; 105706f2543Smrg 106706f2543Smrg REQUEST(xXISelectEventsReq); 107706f2543Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 108706f2543Smrg 109706f2543Smrg if (stuff->num_masks == 0) 110706f2543Smrg return BadValue; 111706f2543Smrg 112706f2543Smrg rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess); 113706f2543Smrg if (rc != Success) 114706f2543Smrg return rc; 115706f2543Smrg 116706f2543Smrg len = sz_xXISelectEventsReq; 117706f2543Smrg 118706f2543Smrg /* check request validity */ 119706f2543Smrg evmask = (xXIEventMask*)&stuff[1]; 120706f2543Smrg num_masks = stuff->num_masks; 121706f2543Smrg while(num_masks--) 122706f2543Smrg { 123706f2543Smrg len += sizeof(xXIEventMask) + evmask->mask_len * 4; 124706f2543Smrg 125706f2543Smrg if (bytes_to_int32(len) > stuff->length) 126706f2543Smrg return BadLength; 127706f2543Smrg 128706f2543Smrg if (evmask->deviceid != XIAllDevices && 129706f2543Smrg evmask->deviceid != XIAllMasterDevices) 130706f2543Smrg rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 131706f2543Smrg else { 132706f2543Smrg /* XXX: XACE here? */ 133706f2543Smrg } 134706f2543Smrg if (rc != Success) 135706f2543Smrg return rc; 136706f2543Smrg 137706f2543Smrg /* hierarchy event mask is not allowed on devices */ 138706f2543Smrg if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) 139706f2543Smrg { 140706f2543Smrg unsigned char *bits = (unsigned char*)&evmask[1]; 141706f2543Smrg if (BitIsOn(bits, XI_HierarchyChanged)) 142706f2543Smrg { 143706f2543Smrg client->errorValue = XI_HierarchyChanged; 144706f2543Smrg return BadValue; 145706f2543Smrg } 146706f2543Smrg } 147706f2543Smrg 148706f2543Smrg /* Raw events may only be selected on root windows */ 149706f2543Smrg if (win->parent && evmask->mask_len >= 1) 150706f2543Smrg { 151706f2543Smrg unsigned char *bits = (unsigned char*)&evmask[1]; 152706f2543Smrg if (BitIsOn(bits, XI_RawKeyPress) || 153706f2543Smrg BitIsOn(bits, XI_RawKeyRelease) || 154706f2543Smrg BitIsOn(bits, XI_RawButtonPress) || 155706f2543Smrg BitIsOn(bits, XI_RawButtonRelease) || 156706f2543Smrg BitIsOn(bits, XI_RawMotion)) 157706f2543Smrg { 158706f2543Smrg client->errorValue = XI_RawKeyPress; 159706f2543Smrg return BadValue; 160706f2543Smrg } 161706f2543Smrg } 162706f2543Smrg 163706f2543Smrg if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1], 164706f2543Smrg evmask->mask_len * 4) != Success) 165706f2543Smrg return BadValue; 166706f2543Smrg 167706f2543Smrg evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 168706f2543Smrg evmask++; 169706f2543Smrg } 170706f2543Smrg 171706f2543Smrg if (bytes_to_int32(len) != stuff->length) 172706f2543Smrg return BadLength; 173706f2543Smrg 174706f2543Smrg /* Set masks on window */ 175706f2543Smrg evmask = (xXIEventMask*)&stuff[1]; 176706f2543Smrg num_masks = stuff->num_masks; 177706f2543Smrg while(num_masks--) 178706f2543Smrg { 179706f2543Smrg if (evmask->deviceid == XIAllDevices || 180706f2543Smrg evmask->deviceid == XIAllMasterDevices) 181706f2543Smrg { 182706f2543Smrg dummy.id = evmask->deviceid; 183706f2543Smrg dev = &dummy; 184706f2543Smrg } else 185706f2543Smrg dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 186706f2543Smrg if (XISetEventMask(dev, win, client, evmask->mask_len * 4, 187706f2543Smrg (unsigned char*)&evmask[1]) != Success) 188706f2543Smrg return BadAlloc; 189706f2543Smrg evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 190706f2543Smrg evmask++; 191706f2543Smrg } 192706f2543Smrg 193706f2543Smrg RecalculateDeliverableEvents(win); 194706f2543Smrg 195706f2543Smrg free(types); 196706f2543Smrg return Success; 197706f2543Smrg} 198706f2543Smrg 199706f2543Smrg 200706f2543Smrgint 201706f2543SmrgSProcXIGetSelectedEvents(ClientPtr client) 202706f2543Smrg{ 203706f2543Smrg char n; 204706f2543Smrg 205706f2543Smrg REQUEST(xXIGetSelectedEventsReq); 206706f2543Smrg swaps(&stuff->length, n); 207706f2543Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 208706f2543Smrg swapl(&stuff->win, n); 209706f2543Smrg 210706f2543Smrg return (ProcXIGetSelectedEvents(client)); 211706f2543Smrg} 212706f2543Smrg 213706f2543Smrgint 214706f2543SmrgProcXIGetSelectedEvents(ClientPtr client) 215706f2543Smrg{ 216706f2543Smrg int rc, i; 217706f2543Smrg WindowPtr win; 218706f2543Smrg char n; 219706f2543Smrg char *buffer = NULL; 220706f2543Smrg xXIGetSelectedEventsReply reply; 221706f2543Smrg OtherInputMasks *masks; 222706f2543Smrg InputClientsPtr others = NULL; 223706f2543Smrg xXIEventMask *evmask = NULL; 224706f2543Smrg DeviceIntPtr dev; 22519bbc2cfSmrg uint32_t length; 226706f2543Smrg 227706f2543Smrg REQUEST(xXIGetSelectedEventsReq); 228706f2543Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 229706f2543Smrg 230706f2543Smrg rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess); 231706f2543Smrg if (rc != Success) 232706f2543Smrg return rc; 233706f2543Smrg 234706f2543Smrg reply.repType = X_Reply; 235706f2543Smrg reply.RepType = X_XIGetSelectedEvents; 236706f2543Smrg reply.length = 0; 237706f2543Smrg reply.sequenceNumber = client->sequence; 238706f2543Smrg reply.num_masks = 0; 239706f2543Smrg 240706f2543Smrg masks = wOtherInputMasks(win); 241706f2543Smrg if (masks) 242706f2543Smrg { 243706f2543Smrg for (others = wOtherInputMasks(win)->inputClients; others; 244706f2543Smrg others = others->next) { 245706f2543Smrg if (SameClient(others, client)) { 246706f2543Smrg break; 247706f2543Smrg } 248706f2543Smrg } 249706f2543Smrg } 250706f2543Smrg 251706f2543Smrg if (!others) 252706f2543Smrg { 253706f2543Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 254706f2543Smrg return Success; 255706f2543Smrg } 256706f2543Smrg 257706f2543Smrg buffer = calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE)); 258706f2543Smrg if (!buffer) 259706f2543Smrg return BadAlloc; 260706f2543Smrg 261706f2543Smrg evmask = (xXIEventMask*)buffer; 262706f2543Smrg for (i = 0; i < MAXDEVICES; i++) 263706f2543Smrg { 264706f2543Smrg int j; 265706f2543Smrg unsigned char *devmask = others->xi2mask[i]; 266706f2543Smrg 267706f2543Smrg if (i > 2) 268706f2543Smrg { 269706f2543Smrg rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess); 270706f2543Smrg if (rc != Success) 271706f2543Smrg continue; 272706f2543Smrg } 273706f2543Smrg 274706f2543Smrg 275706f2543Smrg for (j = XI2MASKSIZE - 1; j >= 0; j--) 276706f2543Smrg { 277706f2543Smrg if (devmask[j] != 0) 278706f2543Smrg { 279706f2543Smrg int mask_len = (j + 4)/4; /* j is an index, hence + 4, not + 3 */ 280706f2543Smrg evmask->deviceid = i; 281706f2543Smrg evmask->mask_len = mask_len; 282706f2543Smrg reply.num_masks++; 283706f2543Smrg reply.length += sizeof(xXIEventMask)/4 + evmask->mask_len; 284706f2543Smrg 285706f2543Smrg if (client->swapped) 286706f2543Smrg { 287706f2543Smrg swaps(&evmask->deviceid, n); 288706f2543Smrg swaps(&evmask->mask_len, n); 289706f2543Smrg } 290706f2543Smrg 291706f2543Smrg memcpy(&evmask[1], devmask, j + 1); 292706f2543Smrg evmask = (xXIEventMask*)((char*)evmask + 293706f2543Smrg sizeof(xXIEventMask) + mask_len * 4); 294706f2543Smrg break; 295706f2543Smrg } 296706f2543Smrg } 297706f2543Smrg } 298706f2543Smrg 29919bbc2cfSmrg /* save the value before SRepXIGetSelectedEvents swaps it */ 30019bbc2cfSmrg length = reply.length; 301706f2543Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 302706f2543Smrg 303706f2543Smrg if (reply.num_masks) 30419bbc2cfSmrg WriteToClient(client, length * 4, buffer); 305706f2543Smrg 306706f2543Smrg free(buffer); 307706f2543Smrg return Success; 308706f2543Smrg} 309706f2543Smrg 310706f2543Smrgvoid SRepXIGetSelectedEvents(ClientPtr client, 311706f2543Smrg int len, xXIGetSelectedEventsReply *rep) 312706f2543Smrg{ 313706f2543Smrg char n; 314706f2543Smrg 315706f2543Smrg swaps(&rep->sequenceNumber, n); 316706f2543Smrg swapl(&rep->length, n); 317706f2543Smrg swaps(&rep->num_masks, n); 318706f2543Smrg WriteToClient(client, len, (char *)rep); 319706f2543Smrg} 320706f2543Smrg 321706f2543Smrg 322