1/* 2 * Copyright 2008 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Author: Peter Hutterer 24 */ 25 26#ifdef HAVE_DIX_CONFIG_H 27#include <dix-config.h> 28#endif 29 30 31#include "dixstruct.h" 32#include "windowstr.h" 33#include "exglobals.h" 34#include "exevents.h" 35#include <X11/extensions/XI2proto.h> 36 37#include "xiselectev.h" 38 39/** 40 * Check the given mask (in len bytes) for invalid mask bits. 41 * Invalid mask bits are any bits above XI2LastEvent. 42 * 43 * @return BadValue if at least one invalid bit is set or Success otherwise. 44 */ 45int XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len) 46{ 47 if (len >= XIMaskLen(XI2LASTEVENT)) 48 { 49 int i; 50 for (i = XI2LASTEVENT + 1; i < len * 8; i++) 51 { 52 if (BitIsOn(mask, i)) 53 { 54 client->errorValue = i; 55 return BadValue; 56 } 57 } 58 } 59 60 return Success; 61} 62 63int 64SProcXISelectEvents(ClientPtr client) 65{ 66 char n; 67 int i; 68 int len; 69 xXIEventMask* evmask; 70 71 REQUEST(xXISelectEventsReq); 72 swaps(&stuff->length, n); 73 REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 74 swapl(&stuff->win, n); 75 swaps(&stuff->num_masks, n); 76 77 len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq)); 78 evmask = (xXIEventMask*)&stuff[1]; 79 for (i = 0; i < stuff->num_masks; i++) 80 { 81 if (len < bytes_to_int32(sizeof(xXIEventMask))) 82 return BadLength; 83 len -= bytes_to_int32(sizeof(xXIEventMask)); 84 swaps(&evmask->deviceid, n); 85 swaps(&evmask->mask_len, n); 86 if (len < evmask->mask_len) 87 return BadLength; 88 len -= evmask->mask_len; 89 evmask = (xXIEventMask*)(((char*)&evmask[1]) + evmask->mask_len * 4); 90 } 91 92 return (ProcXISelectEvents(client)); 93} 94 95int 96ProcXISelectEvents(ClientPtr client) 97{ 98 int rc, num_masks; 99 WindowPtr win; 100 DeviceIntPtr dev; 101 DeviceIntRec dummy; 102 xXIEventMask *evmask; 103 int *types = NULL; 104 int len; 105 106 REQUEST(xXISelectEventsReq); 107 REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 108 109 if (stuff->num_masks == 0) 110 return BadValue; 111 112 rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess); 113 if (rc != Success) 114 return rc; 115 116 len = sz_xXISelectEventsReq; 117 118 /* check request validity */ 119 evmask = (xXIEventMask*)&stuff[1]; 120 num_masks = stuff->num_masks; 121 while(num_masks--) 122 { 123 len += sizeof(xXIEventMask) + evmask->mask_len * 4; 124 125 if (bytes_to_int32(len) > stuff->length) 126 return BadLength; 127 128 if (evmask->deviceid != XIAllDevices && 129 evmask->deviceid != XIAllMasterDevices) 130 rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 131 else { 132 /* XXX: XACE here? */ 133 } 134 if (rc != Success) 135 return rc; 136 137 /* hierarchy event mask is not allowed on devices */ 138 if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) 139 { 140 unsigned char *bits = (unsigned char*)&evmask[1]; 141 if (BitIsOn(bits, XI_HierarchyChanged)) 142 { 143 client->errorValue = XI_HierarchyChanged; 144 return BadValue; 145 } 146 } 147 148 /* Raw events may only be selected on root windows */ 149 if (win->parent && evmask->mask_len >= 1) 150 { 151 unsigned char *bits = (unsigned char*)&evmask[1]; 152 if (BitIsOn(bits, XI_RawKeyPress) || 153 BitIsOn(bits, XI_RawKeyRelease) || 154 BitIsOn(bits, XI_RawButtonPress) || 155 BitIsOn(bits, XI_RawButtonRelease) || 156 BitIsOn(bits, XI_RawMotion)) 157 { 158 client->errorValue = XI_RawKeyPress; 159 return BadValue; 160 } 161 } 162 163 if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1], 164 evmask->mask_len * 4) != Success) 165 return BadValue; 166 167 evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 168 evmask++; 169 } 170 171 if (bytes_to_int32(len) != stuff->length) 172 return BadLength; 173 174 /* Set masks on window */ 175 evmask = (xXIEventMask*)&stuff[1]; 176 num_masks = stuff->num_masks; 177 while(num_masks--) 178 { 179 if (evmask->deviceid == XIAllDevices || 180 evmask->deviceid == XIAllMasterDevices) 181 { 182 dummy.id = evmask->deviceid; 183 dev = &dummy; 184 } else 185 dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 186 if (XISetEventMask(dev, win, client, evmask->mask_len * 4, 187 (unsigned char*)&evmask[1]) != Success) 188 return BadAlloc; 189 evmask = (xXIEventMask*)(((unsigned char*)evmask) + evmask->mask_len * 4); 190 evmask++; 191 } 192 193 RecalculateDeliverableEvents(win); 194 195 free(types); 196 return Success; 197} 198 199 200int 201SProcXIGetSelectedEvents(ClientPtr client) 202{ 203 char n; 204 205 REQUEST(xXIGetSelectedEventsReq); 206 swaps(&stuff->length, n); 207 REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 208 swapl(&stuff->win, n); 209 210 return (ProcXIGetSelectedEvents(client)); 211} 212 213int 214ProcXIGetSelectedEvents(ClientPtr client) 215{ 216 int rc, i; 217 WindowPtr win; 218 char n; 219 char *buffer = NULL; 220 xXIGetSelectedEventsReply reply; 221 OtherInputMasks *masks; 222 InputClientsPtr others = NULL; 223 xXIEventMask *evmask = NULL; 224 DeviceIntPtr dev; 225 uint32_t length; 226 227 REQUEST(xXIGetSelectedEventsReq); 228 REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 229 230 rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess); 231 if (rc != Success) 232 return rc; 233 234 reply.repType = X_Reply; 235 reply.RepType = X_XIGetSelectedEvents; 236 reply.length = 0; 237 reply.sequenceNumber = client->sequence; 238 reply.num_masks = 0; 239 240 masks = wOtherInputMasks(win); 241 if (masks) 242 { 243 for (others = wOtherInputMasks(win)->inputClients; others; 244 others = others->next) { 245 if (SameClient(others, client)) { 246 break; 247 } 248 } 249 } 250 251 if (!others) 252 { 253 WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 254 return Success; 255 } 256 257 buffer = calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE)); 258 if (!buffer) 259 return BadAlloc; 260 261 evmask = (xXIEventMask*)buffer; 262 for (i = 0; i < MAXDEVICES; i++) 263 { 264 int j; 265 unsigned char *devmask = others->xi2mask[i]; 266 267 if (i > 2) 268 { 269 rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess); 270 if (rc != Success) 271 continue; 272 } 273 274 275 for (j = XI2MASKSIZE - 1; j >= 0; j--) 276 { 277 if (devmask[j] != 0) 278 { 279 int mask_len = (j + 4)/4; /* j is an index, hence + 4, not + 3 */ 280 evmask->deviceid = i; 281 evmask->mask_len = mask_len; 282 reply.num_masks++; 283 reply.length += sizeof(xXIEventMask)/4 + evmask->mask_len; 284 285 if (client->swapped) 286 { 287 swaps(&evmask->deviceid, n); 288 swaps(&evmask->mask_len, n); 289 } 290 291 memcpy(&evmask[1], devmask, j + 1); 292 evmask = (xXIEventMask*)((char*)evmask + 293 sizeof(xXIEventMask) + mask_len * 4); 294 break; 295 } 296 } 297 } 298 299 /* save the value before SRepXIGetSelectedEvents swaps it */ 300 length = reply.length; 301 WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 302 303 if (reply.num_masks) 304 WriteToClient(client, length * 4, buffer); 305 306 free(buffer); 307 return Success; 308} 309 310void SRepXIGetSelectedEvents(ClientPtr client, 311 int len, xXIGetSelectedEventsReply *rep) 312{ 313 char n; 314 315 swaps(&rep->sequenceNumber, n); 316 swapl(&rep->length, n); 317 swaps(&rep->num_masks, n); 318 WriteToClient(client, len, (char *)rep); 319} 320 321 322