diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/XIProperties.c | 255 |
2 files changed, 256 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0ea0a7b..35ddc01 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,6 +60,7 @@ libXi_la_SOURCES = \ XISetDevFocus.c \ XIGetDevFocus.c \ XIPassiveGrab.c \ + XIProperties.c \ XIFreeEvent.c diff --git a/src/XIProperties.c b/src/XIProperties.c new file mode 100644 index 0000000..8b1bdcd --- /dev/null +++ b/src/XIProperties.c @@ -0,0 +1,255 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/*********************************************************************** + * XI2 property requests, list, change, delete and get properties. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdint.h> +#include <X11/Xlibint.h> +#include <X11/extensions/XI2.h> +#include <X11/extensions/XI2proto.h> +#include <X11/extensions/XInput2.h> +#include <X11/extensions/extutil.h> +#include "XIint.h" + +Atom* +XIListProperties(Display* dpy, int deviceid, int *num_props_return) +{ + xXIListPropertiesReq *req; + xXIListPropertiesReply rep; + XExtDisplayInfo *info = XInput_find_display(dpy); + Atom *props = NULL; + + LockDisplay(dpy); + *num_props_return = 0; + if (_XiCheckExtInit(dpy, XInput_2, info) == -1) + goto cleanup; + + GetReq(XIListProperties, req); + req->reqType = info->codes->major_opcode; + req->ReqType = X_XIListProperties; + req->deviceid = deviceid; + + if (!_XReply(dpy, (xReply*)&rep, 0, xFalse)) + goto cleanup; + + if (rep.num_properties) { + props = (Atom*)Xmalloc(rep.num_properties * sizeof(Atom)); + if (!props) + { + _XEatData(dpy, rep.num_properties << 2); + goto cleanup; + } + + _XRead32(dpy, props, rep.num_properties << 2); + } + + *num_props_return = rep.num_properties; + +cleanup: + UnlockDisplay(dpy); + SyncHandle(); + return props; +} + + +void +XIDeleteProperty(Display* dpy, int deviceid, Atom property) +{ + xXIDeletePropertyReq *req; + + XExtDisplayInfo *info = XInput_find_display(dpy); + + LockDisplay(dpy); + if (_XiCheckExtInit(dpy, XInput_2, info) == -1) + return; + + GetReq(XIDeleteProperty, req); + req->reqType = info->codes->major_opcode; + req->ReqType = X_XIDeleteProperty; + req->deviceid = deviceid; + req->property = property; + + UnlockDisplay(dpy); + SyncHandle(); +} + +void +XIChangeProperty(Display* dpy, int deviceid, Atom property, Atom type, + int format, int mode, unsigned char *data, int num_items) +{ + xXIChangePropertyReq *req; + int len; + + XExtDisplayInfo *info = XInput_find_display(dpy); + + LockDisplay(dpy); + if (_XiCheckExtInit(dpy, XInput_2, info) == -1) + return; + + GetReq(XIChangeProperty, req); + req->reqType = info->codes->major_opcode; + req->ReqType = X_XIChangeProperty; + req->deviceid = deviceid; + req->property = property; + req->type = type; + req->mode = mode; + if (num_items < 0) { + req->num_items = 0; + req->format = 0; /* ask for garbage, get garbage */ + } else { + req->num_items = num_items; + req->format = format; + } + + switch (req->format) { + case 8: + len = (num_items + 3)/4; + SetReqLen(req, len, len); + len = num_items; + break; + + case 16: + len = (num_items + 1)/2; + SetReqLen(req, len, len); + len = num_items * 2; + break; + + case 32: + len = num_items; + SetReqLen(req, len, len); + len = num_items * 4; + break; + + default: + /* BadValue will be generated */ ; + } + + /* we use data instead of Data32 and friends to avoid Xlib's braindead + * 64 bit handling.*/ + + Data(dpy, (const char*)data, len); + UnlockDisplay(dpy); + SyncHandle(); +} + +Status +XIGetProperty(Display* dpy, int deviceid, Atom property, long offset, + long length, Bool delete_property, Atom type, + Atom *type_return, int *format_return, + unsigned long *num_items_return,unsigned long *bytes_after_return, + unsigned char **data) +{ + xXIGetPropertyReq *req; + xXIGetPropertyReply rep; + long nbytes, rbytes; + + XExtDisplayInfo *info = XInput_find_display(dpy); + + LockDisplay(dpy); + if (_XiCheckExtInit(dpy, XInput_2, info) == -1) + return 1; + + GetReq(XIGetProperty, req); + req->reqType = info->codes->major_opcode; + req->ReqType = X_XIGetProperty; + req->deviceid = deviceid; + req->property = property; + req->type = type; + req->offset = offset; + req->len = length; + req->delete = delete_property; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return 1; + } + + *data = NULL; + + if (rep.type != None) { + /* + * One extra byte is malloced than is needed to contain the property + * data, but this last byte is null terminated and convenient for + * returning string properties, so the client doesn't then have to + * recopy the string to make it null terminated. + */ + switch (rep.format) { + case 8: + nbytes = rep.num_items; + rbytes = rep.num_items + 1; + if (rbytes > 0 && (*data = Xmalloc(rbytes))) + _XReadPad (dpy, (char *) *data, nbytes); + break; + + case 16: + nbytes = rep.num_items << 1; + rbytes = rep.num_items * sizeof(uint16_t) + 1; + if (rbytes > 0 && (*data = Xmalloc(rbytes))) + _XRead16Pad (dpy, (uint16_t*) *data, nbytes); + break; + + case 32: + nbytes = rep.num_items << 2; + rbytes = rep.num_items * sizeof(uint32_t) + 1; + if (rbytes > 0 && (*data = Xmalloc(rbytes))) + _XRead32 (dpy, (uint32_t*) *data, nbytes); + break; + + default: + /* + * This part of the code should never be reached. If it is, + * the server sent back a property with an invalid format. + */ + nbytes = rep.length << 2; + _XEatData(dpy, nbytes); + UnlockDisplay(dpy); + SyncHandle(); + return(BadImplementation); + } + if (!(*data)) { + _XEatData(dpy, nbytes); + UnlockDisplay(dpy); + SyncHandle(); + return(BadAlloc); + } + (*data)[rbytes - 1] = '\0'; + } + + *type_return = rep.type; + *format_return = rep.format; + *num_items_return = rep.num_items; + *bytes_after_return = rep.bytes_after; + UnlockDisplay (dpy); + SyncHandle(); + return Success; +} |