summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2009-05-07 11:41:46 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2009-05-07 11:41:46 +1000
commit92cfef2cebfa85bdb0c1b3b6ee2f78520b003eb7 (patch)
treef9a191b5801aa805fab0d3aafd802b5346926229 /src
parent130774c208a2f331d6110b255676ad6cb8a1a414 (diff)
Add XI2 property requests.
Without Xlib's 64-bit hilarity. A property claiming to be 32 bit is treated as 32 bit value.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/XIProperties.c255
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;
+}