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#include "dixstruct.h" 316747b715Smrg#include "windowstr.h" 326747b715Smrg#include "exglobals.h" 336747b715Smrg#include "exevents.h" 346747b715Smrg#include <X11/extensions/XI2proto.h> 35f7df2e56Smrg#include "inpututils.h" 366747b715Smrg 376747b715Smrg#include "xiselectev.h" 386747b715Smrg 39f7df2e56Smrg/** 40f7df2e56Smrg * Ruleset: 41f7df2e56Smrg * - if A has XIAllDevices, B may select on device X 42f7df2e56Smrg * - If A has XIAllDevices, B may select on XIAllMasterDevices 43f7df2e56Smrg * - If A has XIAllMasterDevices, B may select on device X 44f7df2e56Smrg * - If A has XIAllMasterDevices, B may select on XIAllDevices 45f7df2e56Smrg * - if A has device X, B may select on XIAllDevices/XIAllMasterDevices 46f7df2e56Smrg */ 475a112b11Smrgstatic int 485a112b11Smrgcheck_for_touch_selection_conflicts(ClientPtr B, WindowPtr win, int deviceid, 495a112b11Smrg int evtype) 50f7df2e56Smrg{ 51f7df2e56Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 52f7df2e56Smrg InputClients *A = NULL; 53f7df2e56Smrg 54f7df2e56Smrg if (inputMasks) 55f7df2e56Smrg A = inputMasks->inputClients; 56f7df2e56Smrg for (; A; A = A->next) { 57f7df2e56Smrg DeviceIntPtr tmp; 58f7df2e56Smrg 59f7df2e56Smrg if (CLIENT_ID(A->resource) == B->index) 60f7df2e56Smrg continue; 61f7df2e56Smrg 62f7df2e56Smrg if (deviceid == XIAllDevices) 63f7df2e56Smrg tmp = inputInfo.all_devices; 64f7df2e56Smrg else if (deviceid == XIAllMasterDevices) 65f7df2e56Smrg tmp = inputInfo.all_master_devices; 66f7df2e56Smrg else 67f7df2e56Smrg dixLookupDevice(&tmp, deviceid, serverClient, DixReadAccess); 68f7df2e56Smrg if (!tmp) 69f7df2e56Smrg return BadImplementation; /* this shouldn't happen */ 70f7df2e56Smrg 71f7df2e56Smrg /* A has XIAllDevices */ 725a112b11Smrg if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_devices, evtype)) { 73f7df2e56Smrg if (deviceid == XIAllDevices) 74f7df2e56Smrg return BadAccess; 75f7df2e56Smrg } 76f7df2e56Smrg 77f7df2e56Smrg /* A has XIAllMasterDevices */ 785a112b11Smrg if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_master_devices, evtype)) { 79f7df2e56Smrg if (deviceid == XIAllMasterDevices) 80f7df2e56Smrg return BadAccess; 81f7df2e56Smrg } 82f7df2e56Smrg 83f7df2e56Smrg /* A has this device */ 845a112b11Smrg if (xi2mask_isset_for_device(A->xi2mask, tmp, evtype)) 85f7df2e56Smrg return BadAccess; 86f7df2e56Smrg } 87f7df2e56Smrg 88f7df2e56Smrg return Success; 89f7df2e56Smrg} 90f7df2e56Smrg 91f7df2e56Smrg 926747b715Smrg/** 936747b715Smrg * Check the given mask (in len bytes) for invalid mask bits. 946747b715Smrg * Invalid mask bits are any bits above XI2LastEvent. 956747b715Smrg * 966747b715Smrg * @return BadValue if at least one invalid bit is set or Success otherwise. 976747b715Smrg */ 98f7df2e56Smrgint 99f7df2e56SmrgXICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len) 1006747b715Smrg{ 101f7df2e56Smrg if (len >= XIMaskLen(XI2LASTEVENT)) { 1026747b715Smrg int i; 103f7df2e56Smrg 104f7df2e56Smrg for (i = XI2LASTEVENT + 1; i < len * 8; i++) { 105f7df2e56Smrg if (BitIsOn(mask, i)) { 1069ace9065Smrg client->errorValue = i; 1076747b715Smrg return BadValue; 1089ace9065Smrg } 1099ace9065Smrg } 1106747b715Smrg } 1116747b715Smrg 1126747b715Smrg return Success; 1136747b715Smrg} 1146747b715Smrg 1157e31ba66Smrgint _X_COLD 1166747b715SmrgSProcXISelectEvents(ClientPtr client) 1176747b715Smrg{ 1186747b715Smrg int i; 1190b0d8713Smrg int len; 120f7df2e56Smrg xXIEventMask *evmask; 1216747b715Smrg 1226747b715Smrg REQUEST(xXISelectEventsReq); 123f7df2e56Smrg swaps(&stuff->length); 1246747b715Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 125f7df2e56Smrg swapl(&stuff->win); 126f7df2e56Smrg swaps(&stuff->num_masks); 1276747b715Smrg 1280b0d8713Smrg len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq)); 129f7df2e56Smrg evmask = (xXIEventMask *) &stuff[1]; 130f7df2e56Smrg for (i = 0; i < stuff->num_masks; i++) { 1310b0d8713Smrg if (len < bytes_to_int32(sizeof(xXIEventMask))) 1320b0d8713Smrg return BadLength; 1330b0d8713Smrg len -= bytes_to_int32(sizeof(xXIEventMask)); 134f7df2e56Smrg swaps(&evmask->deviceid); 135f7df2e56Smrg swaps(&evmask->mask_len); 1360b0d8713Smrg if (len < evmask->mask_len) 1370b0d8713Smrg return BadLength; 1380b0d8713Smrg len -= evmask->mask_len; 139f7df2e56Smrg evmask = 140f7df2e56Smrg (xXIEventMask *) (((char *) &evmask[1]) + evmask->mask_len * 4); 1416747b715Smrg } 1426747b715Smrg 1436747b715Smrg return (ProcXISelectEvents(client)); 1446747b715Smrg} 1456747b715Smrg 1466747b715Smrgint 1476747b715SmrgProcXISelectEvents(ClientPtr client) 1486747b715Smrg{ 1496747b715Smrg int rc, num_masks; 1506747b715Smrg WindowPtr win; 1516747b715Smrg DeviceIntPtr dev; 1526747b715Smrg DeviceIntRec dummy; 1536747b715Smrg xXIEventMask *evmask; 1546747b715Smrg int *types = NULL; 1556747b715Smrg int len; 1566747b715Smrg 1576747b715Smrg REQUEST(xXISelectEventsReq); 1586747b715Smrg REQUEST_AT_LEAST_SIZE(xXISelectEventsReq); 1596747b715Smrg 1606747b715Smrg if (stuff->num_masks == 0) 1616747b715Smrg return BadValue; 1626747b715Smrg 1636747b715Smrg rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess); 1646747b715Smrg if (rc != Success) 1656747b715Smrg return rc; 1666747b715Smrg 1676747b715Smrg len = sz_xXISelectEventsReq; 1686747b715Smrg 1696747b715Smrg /* check request validity */ 170f7df2e56Smrg evmask = (xXIEventMask *) &stuff[1]; 1716747b715Smrg num_masks = stuff->num_masks; 172f7df2e56Smrg while (num_masks--) { 1736747b715Smrg len += sizeof(xXIEventMask) + evmask->mask_len * 4; 1746747b715Smrg 1756747b715Smrg if (bytes_to_int32(len) > stuff->length) 1766747b715Smrg return BadLength; 1776747b715Smrg 1786747b715Smrg if (evmask->deviceid != XIAllDevices && 1796747b715Smrg evmask->deviceid != XIAllMasterDevices) 1806747b715Smrg rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 1816747b715Smrg else { 1826747b715Smrg /* XXX: XACE here? */ 1836747b715Smrg } 1846747b715Smrg if (rc != Success) 1856747b715Smrg return rc; 1866747b715Smrg 1876747b715Smrg /* hierarchy event mask is not allowed on devices */ 188f7df2e56Smrg if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) { 189f7df2e56Smrg unsigned char *bits = (unsigned char *) &evmask[1]; 190f7df2e56Smrg 191f7df2e56Smrg if (BitIsOn(bits, XI_HierarchyChanged)) { 1929ace9065Smrg client->errorValue = XI_HierarchyChanged; 1936747b715Smrg return BadValue; 1949ace9065Smrg } 1956747b715Smrg } 1966747b715Smrg 1976747b715Smrg /* Raw events may only be selected on root windows */ 198f7df2e56Smrg if (win->parent && evmask->mask_len >= 1) { 199f7df2e56Smrg unsigned char *bits = (unsigned char *) &evmask[1]; 200f7df2e56Smrg 2016747b715Smrg if (BitIsOn(bits, XI_RawKeyPress) || 2026747b715Smrg BitIsOn(bits, XI_RawKeyRelease) || 2036747b715Smrg BitIsOn(bits, XI_RawButtonPress) || 2046747b715Smrg BitIsOn(bits, XI_RawButtonRelease) || 205f7df2e56Smrg BitIsOn(bits, XI_RawMotion) || 206f7df2e56Smrg BitIsOn(bits, XI_RawTouchBegin) || 207f7df2e56Smrg BitIsOn(bits, XI_RawTouchUpdate) || 208f7df2e56Smrg BitIsOn(bits, XI_RawTouchEnd)) { 2099ace9065Smrg client->errorValue = XI_RawKeyPress; 2106747b715Smrg return BadValue; 2119ace9065Smrg } 2126747b715Smrg } 2136747b715Smrg 214f7df2e56Smrg if (evmask->mask_len >= 1) { 215f7df2e56Smrg unsigned char *bits = (unsigned char *) &evmask[1]; 216f7df2e56Smrg 217f7df2e56Smrg /* All three touch events must be selected at once */ 218f7df2e56Smrg if ((BitIsOn(bits, XI_TouchBegin) || 219f7df2e56Smrg BitIsOn(bits, XI_TouchUpdate) || 220f7df2e56Smrg BitIsOn(bits, XI_TouchOwnership) || 221f7df2e56Smrg BitIsOn(bits, XI_TouchEnd)) && 222f7df2e56Smrg (!BitIsOn(bits, XI_TouchBegin) || 223f7df2e56Smrg !BitIsOn(bits, XI_TouchUpdate) || 224f7df2e56Smrg !BitIsOn(bits, XI_TouchEnd))) { 225f7df2e56Smrg client->errorValue = XI_TouchBegin; 226f7df2e56Smrg return BadValue; 227f7df2e56Smrg } 228f7df2e56Smrg 2295a112b11Smrg /* All three pinch gesture events must be selected at once */ 2305a112b11Smrg if ((BitIsOn(bits, XI_GesturePinchBegin) || 2315a112b11Smrg BitIsOn(bits, XI_GesturePinchUpdate) || 2325a112b11Smrg BitIsOn(bits, XI_GesturePinchEnd)) && 2335a112b11Smrg (!BitIsOn(bits, XI_GesturePinchBegin) || 2345a112b11Smrg !BitIsOn(bits, XI_GesturePinchUpdate) || 2355a112b11Smrg !BitIsOn(bits, XI_GesturePinchEnd))) { 2365a112b11Smrg client->errorValue = XI_GesturePinchBegin; 2375a112b11Smrg return BadValue; 2385a112b11Smrg } 2395a112b11Smrg 2405a112b11Smrg /* All three swipe gesture events must be selected at once. Note 2415a112b11Smrg that the XI_GestureSwipeEnd is at index 32 which is on the next 2425a112b11Smrg 4-byte mask element */ 2435a112b11Smrg if (evmask->mask_len == 1 && 2445a112b11Smrg (BitIsOn(bits, XI_GestureSwipeBegin) || 2455a112b11Smrg BitIsOn(bits, XI_GestureSwipeUpdate))) 2465a112b11Smrg { 2475a112b11Smrg client->errorValue = XI_GestureSwipeBegin; 2485a112b11Smrg return BadValue; 2495a112b11Smrg } 2505a112b11Smrg 2515a112b11Smrg if (evmask->mask_len >= 2 && 2525a112b11Smrg (BitIsOn(bits, XI_GestureSwipeBegin) || 2535a112b11Smrg BitIsOn(bits, XI_GestureSwipeUpdate) || 2545a112b11Smrg BitIsOn(bits, XI_GestureSwipeEnd)) && 2555a112b11Smrg (!BitIsOn(bits, XI_GestureSwipeBegin) || 2565a112b11Smrg !BitIsOn(bits, XI_GestureSwipeUpdate) || 2575a112b11Smrg !BitIsOn(bits, XI_GestureSwipeEnd))) { 2585a112b11Smrg client->errorValue = XI_GestureSwipeBegin; 2595a112b11Smrg return BadValue; 2605a112b11Smrg } 2615a112b11Smrg 2625a112b11Smrg /* Only one client per window may select for touch or gesture events 2635a112b11Smrg * on the same devices, including master devices. 264f7df2e56Smrg * XXX: This breaks if a device goes from floating to attached. */ 265f7df2e56Smrg if (BitIsOn(bits, XI_TouchBegin)) { 266f7df2e56Smrg rc = check_for_touch_selection_conflicts(client, 267f7df2e56Smrg win, 2685a112b11Smrg evmask->deviceid, 2695a112b11Smrg XI_TouchBegin); 2705a112b11Smrg if (rc != Success) 2715a112b11Smrg return rc; 2725a112b11Smrg } 2735a112b11Smrg if (BitIsOn(bits, XI_GesturePinchBegin)) { 2745a112b11Smrg rc = check_for_touch_selection_conflicts(client, 2755a112b11Smrg win, 2765a112b11Smrg evmask->deviceid, 2775a112b11Smrg XI_GesturePinchBegin); 2785a112b11Smrg if (rc != Success) 2795a112b11Smrg return rc; 2805a112b11Smrg } 2815a112b11Smrg if (BitIsOn(bits, XI_GestureSwipeBegin)) { 2825a112b11Smrg rc = check_for_touch_selection_conflicts(client, 2835a112b11Smrg win, 2845a112b11Smrg evmask->deviceid, 2855a112b11Smrg XI_GestureSwipeBegin); 286f7df2e56Smrg if (rc != Success) 287f7df2e56Smrg return rc; 288f7df2e56Smrg } 289f7df2e56Smrg } 290f7df2e56Smrg 291f7df2e56Smrg if (XICheckInvalidMaskBits(client, (unsigned char *) &evmask[1], 2926747b715Smrg evmask->mask_len * 4) != Success) 2936747b715Smrg return BadValue; 2946747b715Smrg 295f7df2e56Smrg evmask = 296f7df2e56Smrg (xXIEventMask *) (((unsigned char *) evmask) + 297f7df2e56Smrg evmask->mask_len * 4); 2986747b715Smrg evmask++; 2996747b715Smrg } 3006747b715Smrg 3016747b715Smrg if (bytes_to_int32(len) != stuff->length) 3026747b715Smrg return BadLength; 3036747b715Smrg 3046747b715Smrg /* Set masks on window */ 305f7df2e56Smrg evmask = (xXIEventMask *) &stuff[1]; 3066747b715Smrg num_masks = stuff->num_masks; 307f7df2e56Smrg while (num_masks--) { 3086747b715Smrg if (evmask->deviceid == XIAllDevices || 309f7df2e56Smrg evmask->deviceid == XIAllMasterDevices) { 3106747b715Smrg dummy.id = evmask->deviceid; 3116747b715Smrg dev = &dummy; 312f7df2e56Smrg } 313f7df2e56Smrg else 3146747b715Smrg dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess); 3156747b715Smrg if (XISetEventMask(dev, win, client, evmask->mask_len * 4, 316f7df2e56Smrg (unsigned char *) &evmask[1]) != Success) 3176747b715Smrg return BadAlloc; 318f7df2e56Smrg evmask = 319f7df2e56Smrg (xXIEventMask *) (((unsigned char *) evmask) + 320f7df2e56Smrg evmask->mask_len * 4); 3216747b715Smrg evmask++; 3226747b715Smrg } 3236747b715Smrg 3246747b715Smrg RecalculateDeliverableEvents(win); 3256747b715Smrg 3266747b715Smrg free(types); 3276747b715Smrg return Success; 3286747b715Smrg} 3296747b715Smrg 3307e31ba66Smrgint _X_COLD 3316747b715SmrgSProcXIGetSelectedEvents(ClientPtr client) 3326747b715Smrg{ 3336747b715Smrg REQUEST(xXIGetSelectedEventsReq); 334f7df2e56Smrg swaps(&stuff->length); 3356747b715Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 336f7df2e56Smrg swapl(&stuff->win); 3376747b715Smrg 3386747b715Smrg return (ProcXIGetSelectedEvents(client)); 3396747b715Smrg} 3406747b715Smrg 3416747b715Smrgint 3426747b715SmrgProcXIGetSelectedEvents(ClientPtr client) 3436747b715Smrg{ 3446747b715Smrg int rc, i; 3456747b715Smrg WindowPtr win; 3466747b715Smrg char *buffer = NULL; 3476747b715Smrg xXIGetSelectedEventsReply reply; 3486747b715Smrg OtherInputMasks *masks; 3496747b715Smrg InputClientsPtr others = NULL; 3506747b715Smrg xXIEventMask *evmask = NULL; 3516747b715Smrg DeviceIntPtr dev; 352875c6e4fSmrg uint32_t length; 3536747b715Smrg 3546747b715Smrg REQUEST(xXIGetSelectedEventsReq); 3556747b715Smrg REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq); 3566747b715Smrg 3576747b715Smrg rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess); 3586747b715Smrg if (rc != Success) 3596747b715Smrg return rc; 3606747b715Smrg 361f7df2e56Smrg reply = (xXIGetSelectedEventsReply) { 362f7df2e56Smrg .repType = X_Reply, 363f7df2e56Smrg .RepType = X_XIGetSelectedEvents, 364f7df2e56Smrg .sequenceNumber = client->sequence, 365f7df2e56Smrg .length = 0, 366f7df2e56Smrg .num_masks = 0 367f7df2e56Smrg }; 3686747b715Smrg 3696747b715Smrg masks = wOtherInputMasks(win); 370f7df2e56Smrg if (masks) { 371f7df2e56Smrg for (others = wOtherInputMasks(win)->inputClients; others; 372f7df2e56Smrg others = others->next) { 373f7df2e56Smrg if (SameClient(others, client)) { 3746747b715Smrg break; 3756747b715Smrg } 3766747b715Smrg } 3776747b715Smrg } 3786747b715Smrg 379f7df2e56Smrg if (!others) { 3806747b715Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 3816747b715Smrg return Success; 3826747b715Smrg } 3836747b715Smrg 384f7df2e56Smrg buffer = 385f7df2e56Smrg calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE)); 3866747b715Smrg if (!buffer) 3876747b715Smrg return BadAlloc; 3886747b715Smrg 389f7df2e56Smrg evmask = (xXIEventMask *) buffer; 390f7df2e56Smrg for (i = 0; i < MAXDEVICES; i++) { 3916747b715Smrg int j; 392f7df2e56Smrg const unsigned char *devmask = xi2mask_get_one_mask(others->xi2mask, i); 3936747b715Smrg 394f7df2e56Smrg if (i > 2) { 3956747b715Smrg rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess); 3966747b715Smrg if (rc != Success) 3976747b715Smrg continue; 3986747b715Smrg } 3996747b715Smrg 400f7df2e56Smrg for (j = xi2mask_mask_size(others->xi2mask) - 1; j >= 0; j--) { 401f7df2e56Smrg if (devmask[j] != 0) { 402f7df2e56Smrg int mask_len = (j + 4) / 4; /* j is an index, hence + 4, not + 3 */ 4036747b715Smrg 4046747b715Smrg evmask->deviceid = i; 4056747b715Smrg evmask->mask_len = mask_len; 4066747b715Smrg reply.num_masks++; 407f7df2e56Smrg reply.length += sizeof(xXIEventMask) / 4 + evmask->mask_len; 4086747b715Smrg 409f7df2e56Smrg if (client->swapped) { 410f7df2e56Smrg swaps(&evmask->deviceid); 411f7df2e56Smrg swaps(&evmask->mask_len); 4126747b715Smrg } 4136747b715Smrg 4146747b715Smrg memcpy(&evmask[1], devmask, j + 1); 415f7df2e56Smrg evmask = (xXIEventMask *) ((char *) evmask + 416f7df2e56Smrg sizeof(xXIEventMask) + mask_len * 4); 4176747b715Smrg break; 4186747b715Smrg } 4196747b715Smrg } 4206747b715Smrg } 4216747b715Smrg 422875c6e4fSmrg /* save the value before SRepXIGetSelectedEvents swaps it */ 423875c6e4fSmrg length = reply.length; 4246747b715Smrg WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply); 4256747b715Smrg 4266747b715Smrg if (reply.num_masks) 427875c6e4fSmrg WriteToClient(client, length * 4, buffer); 4286747b715Smrg 4296747b715Smrg free(buffer); 4306747b715Smrg return Success; 4316747b715Smrg} 4326747b715Smrg 433f7df2e56Smrgvoid 434f7df2e56SmrgSRepXIGetSelectedEvents(ClientPtr client, 435f7df2e56Smrg int len, xXIGetSelectedEventsReply * rep) 4366747b715Smrg{ 437f7df2e56Smrg swaps(&rep->sequenceNumber); 438f7df2e56Smrg swapl(&rep->length); 439f7df2e56Smrg swaps(&rep->num_masks); 440f7df2e56Smrg WriteToClient(client, len, rep); 4416747b715Smrg} 442