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