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_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 77cleanup: 78 UnlockDisplay(dpy); 79cleanup_unlocked: 80 SyncHandle(); 81 return props; 82} 83 84 85void 86XIDeleteProperty(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 106void 107XIChangeProperty(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 166Status 167XIGetProperty(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