XIProperties.c revision 10baa824
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 43Atom* 44XIListProperties(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; 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 77cleanup: 78 UnlockDisplay(dpy); 79 SyncHandle(); 80 return props; 81} 82 83 84void 85XIDeleteProperty(Display* dpy, int deviceid, Atom property) 86{ 87 xXIDeletePropertyReq *req; 88 89 XExtDisplayInfo *info = XInput_find_display(dpy); 90 91 LockDisplay(dpy); 92 if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 93 return; 94 95 GetReq(XIDeleteProperty, req); 96 req->reqType = info->codes->major_opcode; 97 req->ReqType = X_XIDeleteProperty; 98 req->deviceid = deviceid; 99 req->property = property; 100 101 UnlockDisplay(dpy); 102 SyncHandle(); 103} 104 105void 106XIChangeProperty(Display* dpy, int deviceid, Atom property, Atom type, 107 int format, int mode, unsigned char *data, int num_items) 108{ 109 xXIChangePropertyReq *req; 110 int len; 111 112 XExtDisplayInfo *info = XInput_find_display(dpy); 113 114 LockDisplay(dpy); 115 if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 116 return; 117 118 GetReq(XIChangeProperty, req); 119 req->reqType = info->codes->major_opcode; 120 req->ReqType = X_XIChangeProperty; 121 req->deviceid = deviceid; 122 req->property = property; 123 req->type = type; 124 req->mode = mode; 125 if (num_items < 0) { 126 req->num_items = 0; 127 req->format = 0; /* ask for garbage, get garbage */ 128 } else { 129 req->num_items = num_items; 130 req->format = format; 131 } 132 133 switch (req->format) { 134 case 8: 135 len = (num_items + 3)/4; 136 SetReqLen(req, len, len); 137 len = num_items; 138 break; 139 140 case 16: 141 len = (num_items + 1)/2; 142 SetReqLen(req, len, len); 143 len = num_items * 2; 144 break; 145 146 case 32: 147 len = num_items; 148 SetReqLen(req, len, len); 149 len = num_items * 4; 150 break; 151 152 default: 153 /* BadValue will be generated */ ; 154 len = 0; 155 } 156 157 /* we use data instead of Data32 and friends to avoid Xlib's braindead 158 * 64 bit handling.*/ 159 160 Data(dpy, (const char*)data, len); 161 UnlockDisplay(dpy); 162 SyncHandle(); 163} 164 165Status 166XIGetProperty(Display* dpy, int deviceid, Atom property, long offset, 167 long length, Bool delete_property, Atom type, 168 Atom *type_return, int *format_return, 169 unsigned long *num_items_return,unsigned long *bytes_after_return, 170 unsigned char **data) 171{ 172 xXIGetPropertyReq *req; 173 xXIGetPropertyReply rep; 174 unsigned long nbytes, rbytes; 175 176 XExtDisplayInfo *info = XInput_find_display(dpy); 177 178 LockDisplay(dpy); 179 if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 180 return 1; 181 182 GetReq(XIGetProperty, req); 183 req->reqType = info->codes->major_opcode; 184 req->ReqType = X_XIGetProperty; 185 req->deviceid = deviceid; 186 req->property = property; 187 req->type = type; 188 req->offset = offset; 189 req->len = length; 190 req->delete = delete_property; 191 192 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 193 { 194 UnlockDisplay (dpy); 195 SyncHandle (); 196 return 1; 197 } 198 199 *data = NULL; 200 201 if (rep.type != None) { 202 if (rep.format != 8 && rep.format != 16 && rep.format != 32) { 203 /* 204 * This part of the code should never be reached. If it is, 205 * the server sent back a property with an invalid format. 206 */ 207 _XEatDataWords(dpy, rep.length); 208 UnlockDisplay(dpy); 209 SyncHandle(); 210 return(BadImplementation); 211 } 212 213 /* 214 * One extra byte is malloced than is needed to contain the property 215 * data, but this last byte is null terminated and convenient for 216 * returning string properties, so the client doesn't then have to 217 * recopy the string to make it null terminated. 218 */ 219 220 if (rep.num_items < (INT_MAX / (rep.format/8))) { 221 nbytes = rep.num_items * rep.format/8; 222 rbytes = nbytes + 1; 223 *data = Xmalloc(rbytes); 224 } 225 226 if (!(*data)) { 227 _XEatDataWords(dpy, rep.length); 228 UnlockDisplay(dpy); 229 SyncHandle(); 230 return(BadAlloc); 231 } 232 233 _XReadPad (dpy, (char *)*data, nbytes); 234 (*data)[rbytes - 1] = '\0'; 235 } 236 237 *type_return = rep.type; 238 *format_return = rep.format; 239 *num_items_return = rep.num_items; 240 *bytes_after_return = rep.bytes_after; 241 UnlockDisplay (dpy); 242 SyncHandle(); 243 return Success; 244} 245