xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xiselectev.c (14384B)


      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 #include "dixstruct.h"
     31 #include "windowstr.h"
     32 #include "exglobals.h"
     33 #include "exevents.h"
     34 #include <X11/extensions/XI2proto.h>
     35 #include "inpututils.h"
     36 
     37 #include "xiselectev.h"
     38 
     39 /**
     40  * Ruleset:
     41  * - if A has XIAllDevices, B may select on device X
     42  * - If A has XIAllDevices, B may select on XIAllMasterDevices
     43  * - If A has XIAllMasterDevices, B may select on device X
     44  * - If A has XIAllMasterDevices, B may select on XIAllDevices
     45  * - if A has device X, B may select on XIAllDevices/XIAllMasterDevices
     46  */
     47 static int
     48 check_for_touch_selection_conflicts(ClientPtr B, WindowPtr win, int deviceid,
     49                                     int evtype)
     50 {
     51     OtherInputMasks *inputMasks = wOtherInputMasks(win);
     52     InputClients *A = NULL;
     53 
     54     if (inputMasks)
     55         A = inputMasks->inputClients;
     56     for (; A; A = A->next) {
     57         DeviceIntPtr tmp;
     58 
     59         if (CLIENT_ID(A->resource) == B->index)
     60             continue;
     61 
     62         if (deviceid == XIAllDevices)
     63             tmp = inputInfo.all_devices;
     64         else if (deviceid == XIAllMasterDevices)
     65             tmp = inputInfo.all_master_devices;
     66         else
     67             dixLookupDevice(&tmp, deviceid, serverClient, DixReadAccess);
     68         if (!tmp)
     69             return BadImplementation;       /* this shouldn't happen */
     70 
     71         /* A has XIAllDevices */
     72         if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_devices, evtype)) {
     73             if (deviceid == XIAllDevices)
     74                 return BadAccess;
     75         }
     76 
     77         /* A has XIAllMasterDevices */
     78         if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_master_devices, evtype)) {
     79             if (deviceid == XIAllMasterDevices)
     80                 return BadAccess;
     81         }
     82 
     83         /* A has this device */
     84         if (xi2mask_isset_for_device(A->xi2mask, tmp, evtype))
     85             return BadAccess;
     86     }
     87 
     88     return Success;
     89 }
     90 
     91 
     92 /**
     93  * Check the given mask (in len bytes) for invalid mask bits.
     94  * Invalid mask bits are any bits above XI2LastEvent.
     95  *
     96  * @return BadValue if at least one invalid bit is set or Success otherwise.
     97  */
     98 int
     99 XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len)
    100 {
    101     if (len >= XIMaskLen(XI2LASTEVENT)) {
    102         int i;
    103 
    104         for (i = XI2LASTEVENT + 1; i < len * 8; i++) {
    105             if (BitIsOn(mask, i)) {
    106                 client->errorValue = i;
    107                 return BadValue;
    108             }
    109         }
    110     }
    111 
    112     return Success;
    113 }
    114 
    115 int _X_COLD
    116 SProcXISelectEvents(ClientPtr client)
    117 {
    118     int i;
    119     int len;
    120     xXIEventMask *evmask;
    121 
    122     REQUEST(xXISelectEventsReq);
    123     swaps(&stuff->length);
    124     REQUEST_AT_LEAST_SIZE(xXISelectEventsReq);
    125     swapl(&stuff->win);
    126     swaps(&stuff->num_masks);
    127 
    128     len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq));
    129     evmask = (xXIEventMask *) &stuff[1];
    130     for (i = 0; i < stuff->num_masks; i++) {
    131         if (len < bytes_to_int32(sizeof(xXIEventMask)))
    132             return BadLength;
    133         len -= bytes_to_int32(sizeof(xXIEventMask));
    134         swaps(&evmask->deviceid);
    135         swaps(&evmask->mask_len);
    136         if (len < evmask->mask_len)
    137             return BadLength;
    138         len -= evmask->mask_len;
    139         evmask =
    140             (xXIEventMask *) (((char *) &evmask[1]) + evmask->mask_len * 4);
    141     }
    142 
    143     return (ProcXISelectEvents(client));
    144 }
    145 
    146 int
    147 ProcXISelectEvents(ClientPtr client)
    148 {
    149     int rc, num_masks;
    150     WindowPtr win;
    151     DeviceIntPtr dev;
    152     DeviceIntRec dummy;
    153     xXIEventMask *evmask;
    154     int *types = NULL;
    155     int len;
    156 
    157     REQUEST(xXISelectEventsReq);
    158     REQUEST_AT_LEAST_SIZE(xXISelectEventsReq);
    159 
    160     if (stuff->num_masks == 0)
    161         return BadValue;
    162 
    163     rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess);
    164     if (rc != Success)
    165         return rc;
    166 
    167     len = sz_xXISelectEventsReq;
    168 
    169     /* check request validity */
    170     evmask = (xXIEventMask *) &stuff[1];
    171     num_masks = stuff->num_masks;
    172     while (num_masks--) {
    173         len += sizeof(xXIEventMask) + evmask->mask_len * 4;
    174 
    175         if (bytes_to_int32(len) > stuff->length)
    176             return BadLength;
    177 
    178         if (evmask->deviceid != XIAllDevices &&
    179             evmask->deviceid != XIAllMasterDevices)
    180             rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess);
    181         else {
    182             /* XXX: XACE here? */
    183         }
    184         if (rc != Success)
    185             return rc;
    186 
    187         /* hierarchy event mask is not allowed on devices */
    188         if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) {
    189             unsigned char *bits = (unsigned char *) &evmask[1];
    190 
    191             if (BitIsOn(bits, XI_HierarchyChanged)) {
    192                 client->errorValue = XI_HierarchyChanged;
    193                 return BadValue;
    194             }
    195         }
    196 
    197         /* Raw events may only be selected on root windows */
    198         if (win->parent && evmask->mask_len >= 1) {
    199             unsigned char *bits = (unsigned char *) &evmask[1];
    200 
    201             if (BitIsOn(bits, XI_RawKeyPress) ||
    202                 BitIsOn(bits, XI_RawKeyRelease) ||
    203                 BitIsOn(bits, XI_RawButtonPress) ||
    204                 BitIsOn(bits, XI_RawButtonRelease) ||
    205                 BitIsOn(bits, XI_RawMotion) ||
    206                 BitIsOn(bits, XI_RawTouchBegin) ||
    207                 BitIsOn(bits, XI_RawTouchUpdate) ||
    208                 BitIsOn(bits, XI_RawTouchEnd)) {
    209                 client->errorValue = XI_RawKeyPress;
    210                 return BadValue;
    211             }
    212         }
    213 
    214         if (evmask->mask_len >= 1) {
    215             unsigned char *bits = (unsigned char *) &evmask[1];
    216 
    217             /* All three touch events must be selected at once */
    218             if ((BitIsOn(bits, XI_TouchBegin) ||
    219                  BitIsOn(bits, XI_TouchUpdate) ||
    220                  BitIsOn(bits, XI_TouchOwnership) ||
    221                  BitIsOn(bits, XI_TouchEnd)) &&
    222                 (!BitIsOn(bits, XI_TouchBegin) ||
    223                  !BitIsOn(bits, XI_TouchUpdate) ||
    224                  !BitIsOn(bits, XI_TouchEnd))) {
    225                 client->errorValue = XI_TouchBegin;
    226                 return BadValue;
    227             }
    228 
    229             /* All three pinch gesture events must be selected at once */
    230             if ((BitIsOn(bits, XI_GesturePinchBegin) ||
    231                  BitIsOn(bits, XI_GesturePinchUpdate) ||
    232                  BitIsOn(bits, XI_GesturePinchEnd)) &&
    233                 (!BitIsOn(bits, XI_GesturePinchBegin) ||
    234                  !BitIsOn(bits, XI_GesturePinchUpdate) ||
    235                  !BitIsOn(bits, XI_GesturePinchEnd))) {
    236                 client->errorValue = XI_GesturePinchBegin;
    237                 return BadValue;
    238             }
    239 
    240             /* All three swipe gesture events must be selected at once. Note
    241                that the XI_GestureSwipeEnd is at index 32 which is on the next
    242                4-byte mask element */
    243             if (evmask->mask_len == 1 &&
    244                 (BitIsOn(bits, XI_GestureSwipeBegin) ||
    245                  BitIsOn(bits, XI_GestureSwipeUpdate)))
    246             {
    247                 client->errorValue = XI_GestureSwipeBegin;
    248                 return BadValue;
    249             }
    250 
    251             if (evmask->mask_len >= 2 &&
    252                 (BitIsOn(bits, XI_GestureSwipeBegin) ||
    253                  BitIsOn(bits, XI_GestureSwipeUpdate) ||
    254                  BitIsOn(bits, XI_GestureSwipeEnd)) &&
    255                 (!BitIsOn(bits, XI_GestureSwipeBegin) ||
    256                  !BitIsOn(bits, XI_GestureSwipeUpdate) ||
    257                  !BitIsOn(bits, XI_GestureSwipeEnd))) {
    258                 client->errorValue = XI_GestureSwipeBegin;
    259                 return BadValue;
    260             }
    261 
    262             /* Only one client per window may select for touch or gesture events
    263              * on the same devices, including master devices.
    264              * XXX: This breaks if a device goes from floating to attached. */
    265             if (BitIsOn(bits, XI_TouchBegin)) {
    266                 rc = check_for_touch_selection_conflicts(client,
    267                                                          win,
    268                                                          evmask->deviceid,
    269                                                          XI_TouchBegin);
    270                 if (rc != Success)
    271                     return rc;
    272             }
    273             if (BitIsOn(bits, XI_GesturePinchBegin)) {
    274                 rc = check_for_touch_selection_conflicts(client,
    275                                                          win,
    276                                                          evmask->deviceid,
    277                                                          XI_GesturePinchBegin);
    278                 if (rc != Success)
    279                     return rc;
    280             }
    281             if (BitIsOn(bits, XI_GestureSwipeBegin)) {
    282                 rc = check_for_touch_selection_conflicts(client,
    283                                                          win,
    284                                                          evmask->deviceid,
    285                                                          XI_GestureSwipeBegin);
    286                 if (rc != Success)
    287                     return rc;
    288             }
    289         }
    290 
    291         if (XICheckInvalidMaskBits(client, (unsigned char *) &evmask[1],
    292                                    evmask->mask_len * 4) != Success)
    293             return BadValue;
    294 
    295         evmask =
    296             (xXIEventMask *) (((unsigned char *) evmask) +
    297                               evmask->mask_len * 4);
    298         evmask++;
    299     }
    300 
    301     if (bytes_to_int32(len) != stuff->length)
    302         return BadLength;
    303 
    304     /* Set masks on window */
    305     evmask = (xXIEventMask *) &stuff[1];
    306     num_masks = stuff->num_masks;
    307     while (num_masks--) {
    308         if (evmask->deviceid == XIAllDevices ||
    309             evmask->deviceid == XIAllMasterDevices) {
    310             dummy.id = evmask->deviceid;
    311             dev = &dummy;
    312         }
    313         else
    314             dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess);
    315         if (XISetEventMask(dev, win, client, evmask->mask_len * 4,
    316                            (unsigned char *) &evmask[1]) != Success)
    317             return BadAlloc;
    318         evmask =
    319             (xXIEventMask *) (((unsigned char *) evmask) +
    320                               evmask->mask_len * 4);
    321         evmask++;
    322     }
    323 
    324     RecalculateDeliverableEvents(win);
    325 
    326     free(types);
    327     return Success;
    328 }
    329 
    330 int _X_COLD
    331 SProcXIGetSelectedEvents(ClientPtr client)
    332 {
    333     REQUEST(xXIGetSelectedEventsReq);
    334     swaps(&stuff->length);
    335     REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq);
    336     swapl(&stuff->win);
    337 
    338     return (ProcXIGetSelectedEvents(client));
    339 }
    340 
    341 int
    342 ProcXIGetSelectedEvents(ClientPtr client)
    343 {
    344     int rc, i;
    345     WindowPtr win;
    346     char *buffer = NULL;
    347     xXIGetSelectedEventsReply reply;
    348     OtherInputMasks *masks;
    349     InputClientsPtr others = NULL;
    350     xXIEventMask *evmask = NULL;
    351     DeviceIntPtr dev;
    352 
    353     REQUEST(xXIGetSelectedEventsReq);
    354     REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq);
    355 
    356     rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess);
    357     if (rc != Success)
    358         return rc;
    359 
    360     reply = (xXIGetSelectedEventsReply) {
    361         .repType = X_Reply,
    362         .RepType = X_XIGetSelectedEvents,
    363         .sequenceNumber = client->sequence,
    364         .length = 0,
    365         .num_masks = 0
    366     };
    367 
    368     masks = wOtherInputMasks(win);
    369     if (masks) {
    370         for (others = wOtherInputMasks(win)->inputClients; others;
    371              others = others->next) {
    372             if (SameClient(others, client)) {
    373                 break;
    374             }
    375         }
    376     }
    377 
    378     if (!others) {
    379         WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply);
    380         return Success;
    381     }
    382 
    383     buffer =
    384         calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE));
    385     if (!buffer)
    386         return BadAlloc;
    387 
    388     evmask = (xXIEventMask *) buffer;
    389     for (i = 0; i < MAXDEVICES; i++) {
    390         int j;
    391         const unsigned char *devmask = xi2mask_get_one_mask(others->xi2mask, i);
    392 
    393         if (i > 2) {
    394             rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess);
    395             if (rc != Success)
    396                 continue;
    397         }
    398 
    399         for (j = xi2mask_mask_size(others->xi2mask) - 1; j >= 0; j--) {
    400             if (devmask[j] != 0) {
    401                 int mask_len = (j + 4) / 4;     /* j is an index, hence + 4, not + 3 */
    402 
    403                 evmask->deviceid = i;
    404                 evmask->mask_len = mask_len;
    405                 reply.num_masks++;
    406                 reply.length += sizeof(xXIEventMask) / 4 + evmask->mask_len;
    407 
    408                 if (client->swapped) {
    409                     swaps(&evmask->deviceid);
    410                     swaps(&evmask->mask_len);
    411                 }
    412 
    413                 memcpy(&evmask[1], devmask, j + 1);
    414                 evmask = (xXIEventMask *) ((char *) evmask +
    415                                            sizeof(xXIEventMask) + mask_len * 4);
    416                 break;
    417             }
    418         }
    419     }
    420 
    421     WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply);
    422 
    423     if (reply.num_masks)
    424         WriteToClient(client, reply.length * 4, buffer);
    425 
    426     free(buffer);
    427     return Success;
    428 }
    429 
    430 void
    431 SRepXIGetSelectedEvents(ClientPtr client,
    432                         int len, xXIGetSelectedEventsReply * rep)
    433 {
    434     swaps(&rep->sequenceNumber);
    435     swapl(&rep->length);
    436     swaps(&rep->num_masks);
    437     WriteToClient(client, len, rep);
    438 }