xserver

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

xiquerydevice.c (17808B)


      1 /*
      2  * Copyright © 2009 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  * Authors: Peter Hutterer
     24  *
     25  */
     26 
     27 /**
     28  * @file Protocol handling for the XIQueryDevice request/reply.
     29  */
     30 
     31 #ifdef HAVE_DIX_CONFIG_H
     32 #include <dix-config.h>
     33 #endif
     34 
     35 #include "inputstr.h"
     36 #include <X11/X.h>
     37 #include <X11/Xatom.h>
     38 #include <X11/extensions/XI2proto.h>
     39 #include "xkbstr.h"
     40 #include "xkbsrv.h"
     41 #include "xserver-properties.h"
     42 #include "exevents.h"
     43 #include "xace.h"
     44 #include "inpututils.h"
     45 
     46 #include "exglobals.h"
     47 #include "privates.h"
     48 
     49 #include "xiquerydevice.h"
     50 
     51 static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
     52 static int
     53  ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info);
     54 static int SizeDeviceInfo(DeviceIntPtr dev);
     55 static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info);
     56 int _X_COLD
     57 SProcXIQueryDevice(ClientPtr client)
     58 {
     59     REQUEST(xXIQueryDeviceReq);
     60     REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
     61 
     62     swaps(&stuff->length);
     63     swaps(&stuff->deviceid);
     64 
     65     return ProcXIQueryDevice(client);
     66 }
     67 
     68 int
     69 ProcXIQueryDevice(ClientPtr client)
     70 {
     71     xXIQueryDeviceReply rep;
     72     DeviceIntPtr dev = NULL;
     73     int rc = Success;
     74     int i = 0, len = 0;
     75     char *info, *ptr;
     76     Bool *skip = NULL;
     77 
     78     REQUEST(xXIQueryDeviceReq);
     79     REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
     80 
     81     if (stuff->deviceid != XIAllDevices &&
     82         stuff->deviceid != XIAllMasterDevices) {
     83         rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
     84         if (rc != Success) {
     85             client->errorValue = stuff->deviceid;
     86             return rc;
     87         }
     88         len += SizeDeviceInfo(dev);
     89     }
     90     else {
     91         skip = calloc(sizeof(Bool), inputInfo.numDevices);
     92         if (!skip)
     93             return BadAlloc;
     94 
     95         for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
     96             skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
     97             if (!skip[i])
     98                 len += SizeDeviceInfo(dev);
     99         }
    100 
    101         for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
    102             skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
    103             if (!skip[i])
    104                 len += SizeDeviceInfo(dev);
    105         }
    106     }
    107 
    108     info = calloc(1, len);
    109     if (!info) {
    110         free(skip);
    111         return BadAlloc;
    112     }
    113 
    114     rep = (xXIQueryDeviceReply) {
    115         .repType = X_Reply,
    116         .RepType = X_XIQueryDevice,
    117         .sequenceNumber = client->sequence,
    118         .length = len / 4,
    119         .num_devices = 0
    120     };
    121 
    122     ptr = info;
    123     if (dev) {
    124         len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
    125         if (client->swapped)
    126             SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
    127         info += len;
    128         rep.num_devices = 1;
    129     }
    130     else {
    131         i = 0;
    132         for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
    133             if (!skip[i]) {
    134                 len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
    135                 if (client->swapped)
    136                     SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
    137                 info += len;
    138                 rep.num_devices++;
    139             }
    140         }
    141 
    142         for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
    143             if (!skip[i]) {
    144                 len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
    145                 if (client->swapped)
    146                     SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
    147                 info += len;
    148                 rep.num_devices++;
    149             }
    150         }
    151     }
    152 
    153     len = rep.length * 4;
    154     WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
    155     WriteToClient(client, len, ptr);
    156     free(ptr);
    157     free(skip);
    158     return rc;
    159 }
    160 
    161 void
    162 SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply * rep)
    163 {
    164     swaps(&rep->sequenceNumber);
    165     swapl(&rep->length);
    166     swaps(&rep->num_devices);
    167 
    168     /* Device info is already swapped, see ProcXIQueryDevice */
    169 
    170     WriteToClient(client, size, rep);
    171 }
    172 
    173 /**
    174  * @return Whether the device should be included in the returned list.
    175  */
    176 static Bool
    177 ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
    178 {
    179     /* if all devices are not being queried, only master devices are */
    180     if (deviceid == XIAllDevices || IsMaster(dev)) {
    181         int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
    182 
    183         if (rc == Success)
    184             return FALSE;
    185     }
    186     return TRUE;
    187 }
    188 
    189 /**
    190  * @return The number of bytes needed to store this device's xXIDeviceInfo
    191  * (and its classes).
    192  */
    193 static int
    194 SizeDeviceInfo(DeviceIntPtr dev)
    195 {
    196     int len = sizeof(xXIDeviceInfo);
    197 
    198     /* 4-padded name */
    199     len += pad_to_int32(strlen(dev->name));
    200 
    201     return len + SizeDeviceClasses(dev);
    202 
    203 }
    204 
    205 /*
    206  * @return The number of bytes needed to store this device's classes.
    207  */
    208 int
    209 SizeDeviceClasses(DeviceIntPtr dev)
    210 {
    211     int len = 0;
    212 
    213     if (dev->button) {
    214         len += sizeof(xXIButtonInfo);
    215         len += dev->button->numButtons * sizeof(Atom);
    216         len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
    217     }
    218 
    219     if (dev->key) {
    220         XkbDescPtr xkb = dev->key->xkbInfo->desc;
    221 
    222         len += sizeof(xXIKeyInfo);
    223         len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
    224     }
    225 
    226     if (dev->valuator) {
    227         int i;
    228 
    229         len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes;
    230 
    231         for (i = 0; i < dev->valuator->numAxes; i++) {
    232             if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE)
    233                 len += sizeof(xXIScrollInfo);
    234         }
    235     }
    236 
    237     if (dev->touch)
    238         len += sizeof(xXITouchInfo);
    239 
    240     if (dev->gesture)
    241         len += sizeof(xXIGestureInfo);
    242 
    243     return len;
    244 }
    245 
    246 /**
    247  * Get pointers to button information areas holding button mask and labels.
    248  */
    249 static void
    250 ButtonInfoData(xXIButtonInfo *info, int *mask_words, unsigned char **mask,
    251                Atom **atoms)
    252 {
    253     *mask_words = bytes_to_int32(bits_to_bytes(info->num_buttons));
    254     *mask = (unsigned char*) &info[1];
    255     *atoms = (Atom*) ((*mask) + (*mask_words) * 4);
    256 }
    257 
    258 /**
    259  * Write button information into info.
    260  * @return Number of bytes written into info.
    261  */
    262 int
    263 ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
    264 {
    265     unsigned char *bits;
    266     Atom *labels;
    267     int mask_len;
    268     int i;
    269 
    270     if (!dev || !dev->button)
    271         return 0;
    272 
    273     info->type = ButtonClass;
    274     info->num_buttons = dev->button->numButtons;
    275     ButtonInfoData(info, &mask_len, &bits, &labels);
    276     info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
    277         info->num_buttons + mask_len;
    278     info->sourceid = dev->button->sourceid;
    279 
    280     memset(bits, 0, mask_len * 4);
    281 
    282     if (reportState)
    283         for (i = 0; i < dev->button->numButtons; i++)
    284             if (BitIsOn(dev->button->down, i))
    285                 SetBit(bits, i);
    286 
    287     memcpy(labels, dev->button->labels, dev->button->numButtons * sizeof(Atom));
    288 
    289     return info->length * 4;
    290 }
    291 
    292 static void
    293 SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info)
    294 {
    295     Atom *btn;
    296     int mask_len;
    297     unsigned char *mask;
    298 
    299     int i;
    300     ButtonInfoData(info, &mask_len, &mask, &btn);
    301 
    302     swaps(&info->type);
    303     swaps(&info->length);
    304     swaps(&info->sourceid);
    305 
    306     for (i = 0 ; i < info->num_buttons; i++, btn++)
    307         swapl(btn);
    308 
    309     swaps(&info->num_buttons);
    310 }
    311 
    312 /**
    313  * Write key information into info.
    314  * @return Number of bytes written into info.
    315  */
    316 int
    317 ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
    318 {
    319     int i;
    320     XkbDescPtr xkb = dev->key->xkbInfo->desc;
    321     uint32_t *kc;
    322 
    323     info->type = KeyClass;
    324     info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
    325     info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes;
    326     info->sourceid = dev->key->sourceid;
    327 
    328     kc = (uint32_t *) &info[1];
    329     for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
    330         *kc = i;
    331 
    332     return info->length * 4;
    333 }
    334 
    335 static void
    336 SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
    337 {
    338     uint32_t *key;
    339     int i;
    340 
    341     swaps(&info->type);
    342     swaps(&info->length);
    343     swaps(&info->sourceid);
    344 
    345     for (i = 0, key = (uint32_t *) &info[1]; i < info->num_keycodes;
    346          i++, key++)
    347         swapl(key);
    348 
    349     swaps(&info->num_keycodes);
    350 }
    351 
    352 /**
    353  * List axis information for the given axis.
    354  *
    355  * @return The number of bytes written into info.
    356  */
    357 int
    358 ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info, int axisnumber,
    359                  Bool reportState)
    360 {
    361     ValuatorClassPtr v = dev->valuator;
    362 
    363     info->type = ValuatorClass;
    364     info->length = sizeof(xXIValuatorInfo) / 4;
    365     info->label = v->axes[axisnumber].label;
    366     info->min.integral = v->axes[axisnumber].min_value;
    367     info->min.frac = 0;
    368     info->max.integral = v->axes[axisnumber].max_value;
    369     info->max.frac = 0;
    370     info->value = double_to_fp3232(v->axisVal[axisnumber]);
    371     info->resolution = v->axes[axisnumber].resolution;
    372     info->number = axisnumber;
    373     info->mode = valuator_get_mode(dev, axisnumber);
    374     info->sourceid = v->sourceid;
    375 
    376     if (!reportState)
    377         info->value = info->min;
    378 
    379     return info->length * 4;
    380 }
    381 
    382 static void
    383 SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info)
    384 {
    385     swaps(&info->type);
    386     swaps(&info->length);
    387     swapl(&info->label);
    388     swapl(&info->min.integral);
    389     swapl(&info->min.frac);
    390     swapl(&info->max.integral);
    391     swapl(&info->max.frac);
    392     swapl(&info->value.integral);
    393     swapl(&info->value.frac);
    394     swapl(&info->resolution);
    395     swaps(&info->number);
    396     swaps(&info->sourceid);
    397 }
    398 
    399 int
    400 ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info, int axisnumber)
    401 {
    402     ValuatorClassPtr v = dev->valuator;
    403     AxisInfoPtr axis = &v->axes[axisnumber];
    404 
    405     if (axis->scroll.type == SCROLL_TYPE_NONE)
    406         return 0;
    407 
    408     info->type = XIScrollClass;
    409     info->length = sizeof(xXIScrollInfo) / 4;
    410     info->number = axisnumber;
    411     switch (axis->scroll.type) {
    412     case SCROLL_TYPE_VERTICAL:
    413         info->scroll_type = XIScrollTypeVertical;
    414         break;
    415     case SCROLL_TYPE_HORIZONTAL:
    416         info->scroll_type = XIScrollTypeHorizontal;
    417         break;
    418     default:
    419         ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n",
    420                axis->scroll.type);
    421         break;
    422     }
    423     info->increment = double_to_fp3232(axis->scroll.increment);
    424     info->sourceid = v->sourceid;
    425 
    426     info->flags = 0;
    427 
    428     if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE)
    429         info->flags |= XIScrollFlagNoEmulation;
    430     if (axis->scroll.flags & SCROLL_FLAG_PREFERRED)
    431         info->flags |= XIScrollFlagPreferred;
    432 
    433     return info->length * 4;
    434 }
    435 
    436 static void
    437 SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info)
    438 {
    439     swaps(&info->type);
    440     swaps(&info->length);
    441     swaps(&info->number);
    442     swaps(&info->sourceid);
    443     swaps(&info->scroll_type);
    444     swapl(&info->increment.integral);
    445     swapl(&info->increment.frac);
    446 }
    447 
    448 /**
    449  * List multitouch information
    450  *
    451  * @return The number of bytes written into info.
    452  */
    453 int
    454 ListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
    455 {
    456     touch->type = XITouchClass;
    457     touch->length = sizeof(xXITouchInfo) >> 2;
    458     touch->sourceid = dev->touch->sourceid;
    459     touch->mode = dev->touch->mode;
    460     touch->num_touches = dev->touch->num_touches;
    461 
    462     return touch->length << 2;
    463 }
    464 
    465 static void
    466 SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
    467 {
    468     swaps(&touch->type);
    469     swaps(&touch->length);
    470     swaps(&touch->sourceid);
    471 }
    472 
    473 static Bool ShouldListGestureInfo(ClientPtr client)
    474 {
    475     /* libxcb 14.1 and older are not forwards-compatible with new device classes as it does not
    476      * properly ignore unknown device classes. Since breaking libxcb would break quite a lot of
    477      * applications, we instead report Gesture device class only if the client advertised support
    478      * for XI 2.4. Clients may still not work in cases when a client advertises XI 2.4 support
    479      * and then a completely separate module within the client uses broken libxcb to call
    480      * XIQueryDevice.
    481      */
    482     XIClientPtr pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
    483     if (pXIClient->major_version) {
    484         return version_compare(pXIClient->major_version, pXIClient->minor_version, 2, 4) >= 0;
    485     }
    486     return FALSE;
    487 }
    488 
    489 /**
    490  * List gesture information
    491  *
    492  * @return The number of bytes written into info.
    493  */
    494 static int
    495 ListGestureInfo(DeviceIntPtr dev, xXIGestureInfo * gesture)
    496 {
    497     gesture->type = XIGestureClass;
    498     gesture->length = sizeof(xXIGestureInfo) >> 2;
    499     gesture->sourceid = dev->gesture->sourceid;
    500     gesture->num_touches = dev->gesture->max_touches;
    501 
    502     return gesture->length << 2;
    503 }
    504 
    505 static void
    506 SwapGestureInfo(DeviceIntPtr dev, xXIGestureInfo * gesture)
    507 {
    508     swaps(&gesture->type);
    509     swaps(&gesture->length);
    510     swaps(&gesture->sourceid);
    511 }
    512 
    513 int
    514 GetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
    515 {
    516     DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
    517     int use;
    518 
    519     if (IsMaster(dev)) {
    520         DeviceIntPtr paired = GetPairedDevice(dev);
    521 
    522         use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
    523         *attachment = (paired ? paired->id : 0);
    524     }
    525     else if (!IsFloating(dev)) {
    526         use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
    527         *attachment = master->id;
    528     }
    529     else
    530         use = XIFloatingSlave;
    531 
    532     return use;
    533 }
    534 
    535 /**
    536  * Write the info for device dev into the buffer pointed to by info.
    537  *
    538  * @return The number of bytes used.
    539  */
    540 static int
    541 ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info)
    542 {
    543     char *any = (char *) &info[1];
    544     int len = 0, total_len = 0;
    545 
    546     info->deviceid = dev->id;
    547     info->use = GetDeviceUse(dev, &info->attachment);
    548     info->num_classes = 0;
    549     info->name_len = strlen(dev->name);
    550     info->enabled = dev->enabled;
    551     total_len = sizeof(xXIDeviceInfo);
    552 
    553     len = pad_to_int32(info->name_len);
    554     memset(any, 0, len);
    555     strncpy(any, dev->name, info->name_len);
    556     any += len;
    557     total_len += len;
    558 
    559     total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
    560     return total_len;
    561 }
    562 
    563 /**
    564  * Write the class info of the device into the memory pointed to by any, set
    565  * nclasses to the number of classes in total and return the number of bytes
    566  * written.
    567  */
    568 int
    569 ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
    570                   char *any, uint16_t * nclasses)
    571 {
    572     int total_len = 0;
    573     int len;
    574     int i;
    575     int rc;
    576 
    577     /* Check if the current device state should be suppressed */
    578     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
    579 
    580     if (dev->button) {
    581         (*nclasses)++;
    582         len = ListButtonInfo(dev, (xXIButtonInfo *) any, rc == Success);
    583         any += len;
    584         total_len += len;
    585     }
    586 
    587     if (dev->key) {
    588         (*nclasses)++;
    589         len = ListKeyInfo(dev, (xXIKeyInfo *) any);
    590         any += len;
    591         total_len += len;
    592     }
    593 
    594     for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
    595         (*nclasses)++;
    596         len = ListValuatorInfo(dev, (xXIValuatorInfo *) any, i, rc == Success);
    597         any += len;
    598         total_len += len;
    599     }
    600 
    601     for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
    602         len = ListScrollInfo(dev, (xXIScrollInfo *) any, i);
    603         if (len)
    604             (*nclasses)++;
    605         any += len;
    606         total_len += len;
    607     }
    608 
    609     if (dev->touch) {
    610         (*nclasses)++;
    611         len = ListTouchInfo(dev, (xXITouchInfo *) any);
    612         any += len;
    613         total_len += len;
    614     }
    615 
    616     if (dev->gesture && ShouldListGestureInfo(client)) {
    617         (*nclasses)++;
    618         len = ListGestureInfo(dev, (xXIGestureInfo *) any);
    619         any += len;
    620         total_len += len;
    621     }
    622 
    623     return total_len;
    624 }
    625 
    626 static void
    627 SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
    628 {
    629     char *any = (char *) &info[1];
    630     int i;
    631 
    632     /* Skip over name */
    633     any += pad_to_int32(info->name_len);
    634 
    635     for (i = 0; i < info->num_classes; i++) {
    636         int len = ((xXIAnyInfo *) any)->length;
    637 
    638         switch (((xXIAnyInfo *) any)->type) {
    639         case XIButtonClass:
    640             SwapButtonInfo(dev, (xXIButtonInfo *) any);
    641             break;
    642         case XIKeyClass:
    643             SwapKeyInfo(dev, (xXIKeyInfo *) any);
    644             break;
    645         case XIValuatorClass:
    646             SwapValuatorInfo(dev, (xXIValuatorInfo *) any);
    647             break;
    648         case XIScrollClass:
    649             SwapScrollInfo(dev, (xXIScrollInfo *) any);
    650             break;
    651         case XITouchClass:
    652             SwapTouchInfo(dev, (xXITouchInfo *) any);
    653             break;
    654         case XIGestureClass:
    655             SwapGestureInfo(dev, (xXIGestureInfo *) any);
    656             break;
    657         }
    658 
    659         any += len * 4;
    660     }
    661 
    662     swaps(&info->deviceid);
    663     swaps(&info->use);
    664     swaps(&info->attachment);
    665     swaps(&info->num_classes);
    666     swaps(&info->name_len);
    667 
    668 }