1c27c18e8Smrg/* 2c27c18e8Smrg * Copyright © 2009 Red Hat, Inc. 3c27c18e8Smrg * 4c27c18e8Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5c27c18e8Smrg * copy of this software and associated documentation files (the "Software"), 6c27c18e8Smrg * to deal in the Software without restriction, including without limitation 7c27c18e8Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c27c18e8Smrg * and/or sell copies of the Software, and to permit persons to whom the 9c27c18e8Smrg * Software is furnished to do so, subject to the following conditions: 10c27c18e8Smrg * 11c27c18e8Smrg * The above copyright notice and this permission notice (including the next 12c27c18e8Smrg * paragraph) shall be included in all copies or substantial portions of the 13c27c18e8Smrg * Software. 14c27c18e8Smrg * 15c27c18e8Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16c27c18e8Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17c27c18e8Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18c27c18e8Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19c27c18e8Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20c27c18e8Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21c27c18e8Smrg * DEALINGS IN THE SOFTWARE. 22c27c18e8Smrg * 23c27c18e8Smrg */ 24c27c18e8Smrg 25c27c18e8Smrg/*********************************************************************** 26c27c18e8Smrg * XI2 property requests, list, change, delete and get properties. 27c27c18e8Smrg */ 28c27c18e8Smrg 29c27c18e8Smrg 30c27c18e8Smrg#ifdef HAVE_CONFIG_H 31c27c18e8Smrg#include <config.h> 32c27c18e8Smrg#endif 33c27c18e8Smrg 34c27c18e8Smrg#include <stdint.h> 35c27c18e8Smrg#include <X11/Xlibint.h> 36c27c18e8Smrg#include <X11/extensions/XI2.h> 37c27c18e8Smrg#include <X11/extensions/XI2proto.h> 38c27c18e8Smrg#include <X11/extensions/XInput2.h> 39c27c18e8Smrg#include <X11/extensions/extutil.h> 40c27c18e8Smrg#include "XIint.h" 41190694daSmrg#include <limits.h> 42c27c18e8Smrg 43c27c18e8SmrgAtom* 44c27c18e8SmrgXIListProperties(Display* dpy, int deviceid, int *num_props_return) 45c27c18e8Smrg{ 46c27c18e8Smrg xXIListPropertiesReq *req; 47c27c18e8Smrg xXIListPropertiesReply rep; 48c27c18e8Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 49c27c18e8Smrg Atom *props = NULL; 50c27c18e8Smrg 51c27c18e8Smrg LockDisplay(dpy); 52c27c18e8Smrg *num_props_return = 0; 53b789ec8aSmrg if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 5464276682Smrg goto cleanup_unlocked; 55c27c18e8Smrg 56c27c18e8Smrg GetReq(XIListProperties, req); 57c27c18e8Smrg req->reqType = info->codes->major_opcode; 58c27c18e8Smrg req->ReqType = X_XIListProperties; 59c27c18e8Smrg req->deviceid = deviceid; 60c27c18e8Smrg 61c27c18e8Smrg if (!_XReply(dpy, (xReply*)&rep, 0, xFalse)) 62c27c18e8Smrg goto cleanup; 63c27c18e8Smrg 64c27c18e8Smrg if (rep.num_properties) { 65c27c18e8Smrg props = (Atom*)Xmalloc(rep.num_properties * sizeof(Atom)); 66c27c18e8Smrg if (!props) 67c27c18e8Smrg { 6810baa824Smrg _XEatDataWords(dpy, rep.length); 69c27c18e8Smrg goto cleanup; 70c27c18e8Smrg } 71c27c18e8Smrg 72c27c18e8Smrg _XRead32(dpy, (long*)props, rep.num_properties << 2); 73c27c18e8Smrg } 74c27c18e8Smrg 75c27c18e8Smrg *num_props_return = rep.num_properties; 76c27c18e8Smrg 77c27c18e8Smrgcleanup: 78c27c18e8Smrg UnlockDisplay(dpy); 7964276682Smrgcleanup_unlocked: 80c27c18e8Smrg SyncHandle(); 81c27c18e8Smrg return props; 82c27c18e8Smrg} 83c27c18e8Smrg 84c27c18e8Smrg 85c27c18e8Smrgvoid 86c27c18e8SmrgXIDeleteProperty(Display* dpy, int deviceid, Atom property) 87c27c18e8Smrg{ 88c27c18e8Smrg xXIDeletePropertyReq *req; 89c27c18e8Smrg 90c27c18e8Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 91c27c18e8Smrg 92c27c18e8Smrg LockDisplay(dpy); 93b789ec8aSmrg if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 94c27c18e8Smrg return; 95c27c18e8Smrg 96c27c18e8Smrg GetReq(XIDeleteProperty, req); 97c27c18e8Smrg req->reqType = info->codes->major_opcode; 98c27c18e8Smrg req->ReqType = X_XIDeleteProperty; 99c27c18e8Smrg req->deviceid = deviceid; 100c27c18e8Smrg req->property = property; 101c27c18e8Smrg 102c27c18e8Smrg UnlockDisplay(dpy); 103c27c18e8Smrg SyncHandle(); 104c27c18e8Smrg} 105c27c18e8Smrg 106c27c18e8Smrgvoid 107c27c18e8SmrgXIChangeProperty(Display* dpy, int deviceid, Atom property, Atom type, 108c27c18e8Smrg int format, int mode, unsigned char *data, int num_items) 109c27c18e8Smrg{ 110c27c18e8Smrg xXIChangePropertyReq *req; 111c27c18e8Smrg int len; 112c27c18e8Smrg 113c27c18e8Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 114c27c18e8Smrg 115c27c18e8Smrg LockDisplay(dpy); 116b789ec8aSmrg if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 117c27c18e8Smrg return; 118c27c18e8Smrg 119c27c18e8Smrg GetReq(XIChangeProperty, req); 120c27c18e8Smrg req->reqType = info->codes->major_opcode; 121c27c18e8Smrg req->ReqType = X_XIChangeProperty; 122c27c18e8Smrg req->deviceid = deviceid; 123c27c18e8Smrg req->property = property; 124c27c18e8Smrg req->type = type; 125c27c18e8Smrg req->mode = mode; 126c27c18e8Smrg if (num_items < 0) { 127c27c18e8Smrg req->num_items = 0; 128c27c18e8Smrg req->format = 0; /* ask for garbage, get garbage */ 129c27c18e8Smrg } else { 130c27c18e8Smrg req->num_items = num_items; 131c27c18e8Smrg req->format = format; 132c27c18e8Smrg } 133c27c18e8Smrg 134c27c18e8Smrg switch (req->format) { 135c27c18e8Smrg case 8: 136c27c18e8Smrg len = (num_items + 3)/4; 137c27c18e8Smrg SetReqLen(req, len, len); 138c27c18e8Smrg len = num_items; 139c27c18e8Smrg break; 140c27c18e8Smrg 141c27c18e8Smrg case 16: 142c27c18e8Smrg len = (num_items + 1)/2; 143c27c18e8Smrg SetReqLen(req, len, len); 144c27c18e8Smrg len = num_items * 2; 145c27c18e8Smrg break; 146c27c18e8Smrg 147c27c18e8Smrg case 32: 148c27c18e8Smrg len = num_items; 149c27c18e8Smrg SetReqLen(req, len, len); 150c27c18e8Smrg len = num_items * 4; 151c27c18e8Smrg break; 152c27c18e8Smrg 153c27c18e8Smrg default: 154c27c18e8Smrg /* BadValue will be generated */ ; 1553e256790Smrg len = 0; 156c27c18e8Smrg } 157c27c18e8Smrg 158c27c18e8Smrg /* we use data instead of Data32 and friends to avoid Xlib's braindead 159c27c18e8Smrg * 64 bit handling.*/ 160c27c18e8Smrg 161c27c18e8Smrg Data(dpy, (const char*)data, len); 162c27c18e8Smrg UnlockDisplay(dpy); 163c27c18e8Smrg SyncHandle(); 164c27c18e8Smrg} 165c27c18e8Smrg 166c27c18e8SmrgStatus 167c27c18e8SmrgXIGetProperty(Display* dpy, int deviceid, Atom property, long offset, 168c27c18e8Smrg long length, Bool delete_property, Atom type, 169c27c18e8Smrg Atom *type_return, int *format_return, 170c27c18e8Smrg unsigned long *num_items_return,unsigned long *bytes_after_return, 171c27c18e8Smrg unsigned char **data) 172c27c18e8Smrg{ 173c27c18e8Smrg xXIGetPropertyReq *req; 174c27c18e8Smrg xXIGetPropertyReply rep; 175190694daSmrg unsigned long nbytes, rbytes; 176c27c18e8Smrg 177c27c18e8Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 178c27c18e8Smrg 179c27c18e8Smrg LockDisplay(dpy); 180b789ec8aSmrg if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1) 181c27c18e8Smrg return 1; 182c27c18e8Smrg 183c27c18e8Smrg GetReq(XIGetProperty, req); 184c27c18e8Smrg req->reqType = info->codes->major_opcode; 185c27c18e8Smrg req->ReqType = X_XIGetProperty; 186c27c18e8Smrg req->deviceid = deviceid; 187c27c18e8Smrg req->property = property; 188c27c18e8Smrg req->type = type; 189c27c18e8Smrg req->offset = offset; 190c27c18e8Smrg req->len = length; 191c27c18e8Smrg req->delete = delete_property; 192c27c18e8Smrg 193c27c18e8Smrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 194c27c18e8Smrg { 195c27c18e8Smrg UnlockDisplay (dpy); 196c27c18e8Smrg SyncHandle (); 197c27c18e8Smrg return 1; 198c27c18e8Smrg } 199c27c18e8Smrg 200c27c18e8Smrg *data = NULL; 201c27c18e8Smrg 202c27c18e8Smrg if (rep.type != None) { 203c27c18e8Smrg if (rep.format != 8 && rep.format != 16 && rep.format != 32) { 204c27c18e8Smrg /* 205c27c18e8Smrg * This part of the code should never be reached. If it is, 206c27c18e8Smrg * the server sent back a property with an invalid format. 207c27c18e8Smrg */ 20810baa824Smrg _XEatDataWords(dpy, rep.length); 209c27c18e8Smrg UnlockDisplay(dpy); 210c27c18e8Smrg SyncHandle(); 211c27c18e8Smrg return(BadImplementation); 212c27c18e8Smrg } 213c27c18e8Smrg 214c27c18e8Smrg /* 215c27c18e8Smrg * One extra byte is malloced than is needed to contain the property 216c27c18e8Smrg * data, but this last byte is null terminated and convenient for 217c27c18e8Smrg * returning string properties, so the client doesn't then have to 218c27c18e8Smrg * recopy the string to make it null terminated. 219c27c18e8Smrg */ 220c27c18e8Smrg 221190694daSmrg if (rep.num_items < (INT_MAX / (rep.format/8))) { 222190694daSmrg nbytes = rep.num_items * rep.format/8; 223190694daSmrg rbytes = nbytes + 1; 224190694daSmrg *data = Xmalloc(rbytes); 225190694daSmrg } 226c27c18e8Smrg 227c27c18e8Smrg if (!(*data)) { 22810baa824Smrg _XEatDataWords(dpy, rep.length); 229c27c18e8Smrg UnlockDisplay(dpy); 230c27c18e8Smrg SyncHandle(); 231c27c18e8Smrg return(BadAlloc); 232c27c18e8Smrg } 233c27c18e8Smrg 234c27c18e8Smrg _XReadPad (dpy, (char *)*data, nbytes); 235c27c18e8Smrg (*data)[rbytes - 1] = '\0'; 236c27c18e8Smrg } 237c27c18e8Smrg 238c27c18e8Smrg *type_return = rep.type; 239c27c18e8Smrg *format_return = rep.format; 240c27c18e8Smrg *num_items_return = rep.num_items; 241c27c18e8Smrg *bytes_after_return = rep.bytes_after; 242c27c18e8Smrg UnlockDisplay (dpy); 243c27c18e8Smrg SyncHandle(); 244c27c18e8Smrg return Success; 245c27c18e8Smrg} 246