Home | History | Annotate | Line # | Download | only in src
      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  */
     24 
     25 /***********************************************************************
     26  * XI2 property requests, list, change, delete and get properties.
     27  */
     28 
     29 
     30 #ifdef HAVE_CONFIG_H
     31 #include <config.h>
     32 #endif
     33 
     34 #include <stdint.h>
     35 #include <X11/Xlibint.h>
     36 #include <X11/extensions/XI2.h>
     37 #include <X11/extensions/XI2proto.h>
     38 #include <X11/extensions/XInput2.h>
     39 #include <X11/extensions/extutil.h>
     40 #include "XIint.h"
     41 #include <limits.h>
     42 
     43 Atom*
     44 XIListProperties(Display* dpy, int deviceid, int *num_props_return)
     45 {
     46     xXIListPropertiesReq        *req;
     47     xXIListPropertiesReply      rep;
     48     XExtDisplayInfo             *info = XInput_find_display(dpy);
     49     Atom                        *props = NULL;
     50 
     51     LockDisplay(dpy);
     52     *num_props_return = 0;
     53     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
     54         goto cleanup_unlocked;
     55 
     56     GetReq(XIListProperties, req);
     57     req->reqType = info->codes->major_opcode;
     58     req->ReqType = X_XIListProperties;
     59     req->deviceid = deviceid;
     60 
     61     if (!_XReply(dpy, (xReply*)&rep, 0, xFalse))
     62         goto cleanup;
     63 
     64     if (rep.num_properties) {
     65         props = (Atom*)Xmalloc(rep.num_properties * sizeof(Atom));
     66         if (!props)
     67         {
     68             _XEatDataWords(dpy, rep.length);
     69             goto cleanup;
     70         }
     71 
     72         _XRead32(dpy, (long*)props, rep.num_properties << 2);
     73     }
     74 
     75     *num_props_return = rep.num_properties;
     76 
     77 cleanup:
     78     UnlockDisplay(dpy);
     79 cleanup_unlocked:
     80     SyncHandle();
     81     return props;
     82 }
     83 
     84 
     85 void
     86 XIDeleteProperty(Display* dpy, int deviceid, Atom property)
     87 {
     88     xXIDeletePropertyReq   *req;
     89 
     90     XExtDisplayInfo *info = XInput_find_display(dpy);
     91 
     92     LockDisplay(dpy);
     93     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
     94 	return;
     95 
     96     GetReq(XIDeleteProperty, req);
     97     req->reqType    = info->codes->major_opcode;
     98     req->ReqType    = X_XIDeleteProperty;
     99     req->deviceid   = deviceid;
    100     req->property   = property;
    101 
    102     UnlockDisplay(dpy);
    103     SyncHandle();
    104 }
    105 
    106 void
    107 XIChangeProperty(Display* dpy, int deviceid, Atom property, Atom type,
    108                  int format, int mode, unsigned char *data, int num_items)
    109 {
    110     xXIChangePropertyReq *req;
    111     int len;
    112 
    113     XExtDisplayInfo *info = XInput_find_display(dpy);
    114 
    115     LockDisplay(dpy);
    116     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
    117 	return;
    118 
    119     GetReq(XIChangeProperty, req);
    120     req->reqType    = info->codes->major_opcode;
    121     req->ReqType    = X_XIChangeProperty;
    122     req->deviceid   = deviceid;
    123     req->property   = property;
    124     req->type       = type;
    125     req->mode       = mode;
    126     if (num_items < 0) {
    127 	req->num_items = 0;
    128 	req->format = 0; /* ask for garbage, get garbage */
    129     } else {
    130 	req->num_items = num_items;
    131 	req->format = format;
    132     }
    133 
    134     switch (req->format) {
    135     case 8:
    136 	len = (num_items + 3)/4;
    137         SetReqLen(req, len, len);
    138         len = num_items;
    139 	break;
    140 
    141     case 16:
    142 	len = (num_items + 1)/2;
    143         SetReqLen(req, len, len);
    144         len = num_items * 2;
    145 	break;
    146 
    147     case 32:
    148 	len = num_items;
    149         SetReqLen(req, len, len);
    150         len = num_items * 4;
    151 	break;
    152 
    153     default:
    154 	/* BadValue will be generated */ ;
    155         len = 0;
    156     }
    157 
    158     /* we use data instead of Data32 and friends to avoid Xlib's braindead
    159      * 64 bit handling.*/
    160 
    161     Data(dpy, (const char*)data, len);
    162     UnlockDisplay(dpy);
    163     SyncHandle();
    164 }
    165 
    166 Status
    167 XIGetProperty(Display* dpy, int deviceid, Atom property, long offset,
    168               long length, Bool delete_property, Atom type,
    169               Atom *type_return, int *format_return,
    170               unsigned long *num_items_return,unsigned long *bytes_after_return,
    171               unsigned char **data)
    172 {
    173     xXIGetPropertyReq   *req;
    174     xXIGetPropertyReply rep;
    175     unsigned long       nbytes, rbytes;
    176 
    177     XExtDisplayInfo *info = XInput_find_display(dpy);
    178 
    179     LockDisplay(dpy);
    180     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
    181 	return 1;
    182 
    183     GetReq(XIGetProperty, req);
    184     req->reqType    = info->codes->major_opcode;
    185     req->ReqType    = X_XIGetProperty;
    186     req->deviceid   = deviceid;
    187     req->property   = property;
    188     req->type       = type;
    189     req->offset     = offset;
    190     req->len        = length;
    191     req->delete     = delete_property;
    192 
    193     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
    194     {
    195 	UnlockDisplay (dpy);
    196 	SyncHandle ();
    197 	return 1;
    198     }
    199 
    200     *data = NULL;
    201 
    202     if (rep.type != None) {
    203         if (rep.format != 8 && rep.format != 16 && rep.format != 32) {
    204 	    /*
    205 	     * This part of the code should never be reached.  If it is,
    206 	     * the server sent back a property with an invalid format.
    207 	     */
    208 	    _XEatDataWords(dpy, rep.length);
    209 	    UnlockDisplay(dpy);
    210 	    SyncHandle();
    211 	    return(BadImplementation);
    212         }
    213 
    214 	/*
    215 	 * One extra byte is malloced than is needed to contain the property
    216 	 * data, but this last byte is null terminated and convenient for
    217 	 * returning string properties, so the client doesn't then have to
    218 	 * recopy the string to make it null terminated.
    219 	 */
    220 
    221 	if (rep.num_items < (INT_MAX / (rep.format/8))) {
    222 	    nbytes = rep.num_items * rep.format/8;
    223 	    rbytes = nbytes + 1;
    224 	    *data = Xmalloc(rbytes);
    225 	}
    226 
    227 	if (!(*data)) {
    228 	    _XEatDataWords(dpy, rep.length);
    229 	    UnlockDisplay(dpy);
    230 	    SyncHandle();
    231 	    return(BadAlloc);
    232 	}
    233 
    234         _XReadPad (dpy, (char *)*data, nbytes);
    235 	(*data)[rbytes - 1] = '\0';
    236     }
    237 
    238     *type_return        = rep.type;
    239     *format_return      = rep.format;
    240     *num_items_return   = rep.num_items;
    241     *bytes_after_return = rep.bytes_after;
    242     UnlockDisplay (dpy);
    243     SyncHandle();
    244     return Success;
    245 }
    246