diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-01-21 16:31:20 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-01-22 14:09:58 +1000 |
commit | 9a7554fc1673af818ce5b510b039ec4c0b7be33e (patch) | |
tree | 0baef8d3f94b781992349e2c9603332b107ebd1f | |
parent | 6981c7662b876115c7d2c4067d8aaadca78b7766 (diff) |
common: add a property helper
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | tests/common/Makefile.am | 1 | ||||
-rw-r--r-- | tests/common/xit-property.h | 202 |
2 files changed, 203 insertions, 0 deletions
diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am index 182adb7..66e1ac7 100644 --- a/tests/common/Makefile.am +++ b/tests/common/Makefile.am @@ -4,6 +4,7 @@ noinst_LIBRARIES = $(XORG_GTEST_BUILD_LIBS) libxit.a common_sources = \ $(top_srcdir)/tests/common/xit-event.h \ + $(top_srcdir)/tests/common/xit-property.h \ $(top_srcdir)/tests/common/xit-server-test.cpp \ $(top_srcdir)/tests/common/xit-server-test.h \ $(top_srcdir)/tests/common/xit-server.cpp \ diff --git a/tests/common/xit-property.h b/tests/common/xit-property.h new file mode 100644 index 0000000..b013905 --- /dev/null +++ b/tests/common/xit-property.h @@ -0,0 +1,202 @@ +#if HAVE_CONFIG_H +#include <config.h> +#endif +#ifndef _ATOM_HELPERS_H_ +#define _ATOM_HELPERS_H_ + +#include <xorg/gtest/xorg-gtest.h> +#include <X11/Xatom.h> + +#define ASSERT_PROPERTY(_type, _name, _dpy, _deviceid, _propname) \ + ASSERT_TRUE(DevicePropertyExists(_dpy, _deviceid, _propname)); \ + XITProperty<_type> _name(_dpy, _deviceid, _propname); + + +template <typename DataType> +class XITProperty { +private: + /* I'm too lazy for that right now. */ + XITProperty(const XITProperty&); + XITProperty& operator=(const XITProperty &); + + ::Display *dpy; + int deviceid; + +public: + Atom type; + int format; + unsigned long nitems; + + DataType *data; + + Atom prop; + std::string propname; + + XITProperty(::Display *dpy, int deviceid, const std::string &propname); + XITProperty(::Display *dpy, int deviceid, const std::string &propname, + Atom type, int format, unsigned long nitems, const DataType *data); + ~XITProperty(); + + /** + * Resize the data member to hold nitems. + */ + void Resize(size_t nitems); + void Update(void); + + /** + * Get value at index, throw an exception if we're OOB. + */ + DataType At(size_t index) const; + + /** + * Set value at index, resizing data as-needed. + */ + void Set(size_t index, DataType value); +}; + + +bool DevicePropertyExists(::Display *dpy, int deviceid, const std::string &propname) { + Atom prop; + + prop = XInternAtom(dpy, propname.c_str(), True); + if (prop == None) + return false; + + Atom *props; + int nprops; + props = XIListProperties(dpy, deviceid, &nprops); + + bool prop_found = false; + while (nprops-- && !prop_found) + prop_found = (props[nprops] == prop); + + XFree(props); + + return prop_found; +} + +template <typename DataType> +XITProperty<DataType>::XITProperty(::Display *dpy, int deviceid, const std::string &propname) +{ + this->dpy = dpy; + this->deviceid = deviceid; + this->format = -1; + this->data = NULL; + + if (!DevicePropertyExists(dpy, deviceid, propname)) { + ADD_FAILURE() << "Property " << propname << " does not exist on device"; + return; + } + + prop = XInternAtom(dpy, propname.c_str(), True); + + unsigned char *d; + + unsigned long bytes_after; + XIGetProperty(dpy, deviceid, prop, 0, 1000, False, + AnyPropertyType, &type, &format, &nitems, &bytes_after, &d); + + /* XI2 32-bit properties are actually 32 bit, Atom is > 4, so copy over + * where needed */ + if (d && sizeof(DataType) > 4) { + data = new DataType[nitems]; + for (unsigned int i = 0; i < nitems; i++) + data[i] = reinterpret_cast<int32_t*>(d)[i]; + XFree(d); + } else + data = reinterpret_cast<DataType*>(d); +} + +template <typename DataType> +XITProperty<DataType>::XITProperty(::Display *dpy, int deviceid, const std::string &propname, + Atom type, int format, unsigned long nitems, const DataType *data) +{ + if (format != 8 && format != 16 && format != 32) { + ADD_FAILURE() << "Invalid format " << format; + return; + } + this->format = format; + this->nitems = nitems; + this->data = new DataType[nitems]; + + memcpy(this->data, data, nitems * sizeof(data)); + + union { + unsigned char *c; + unsigned short *s; + uint32_t *i; + } d; + + d.c = new unsigned char[format/8 * nitems]; + + for (unsigned int i = 0; i < nitems; i++) { + switch(format) { + case 8: d.c[i] = data[i]; break; + case 16: d.s[i] = data[i]; break; + case 32: d.i[i] = data[i]; break; + } + } + + prop = XInternAtom(dpy, propname.c_str(), False); + XIChangeProperty(dpy, deviceid, prop, type, format, PropModeReplace, d.c, nitems); + XSync(dpy, False); + + delete[] d.c; +} + + +template <typename DataType> +void XITProperty<DataType>::Update(void) +{ + unsigned char *d; + + /* XI2 32-bit properties are actually 32 bit, Atom is > 4, so copy over + * where needed */ + if (sizeof(DataType) > 4) { + int32_t tmp[nitems]; + for (unsigned int i = 0; i < nitems; i++) + tmp[i] = data[i]; + d = reinterpret_cast<unsigned char*>(tmp); + } else + d = reinterpret_cast<unsigned char*>(data); + + XIChangeProperty(dpy, deviceid, prop, type, format, PropModeReplace, d, nitems); + XSync(dpy, False); +} + +template <typename DataType> +void XITProperty<DataType>::Resize(size_t nitems) +{ + size_t sz = (sizeof(DataType) >= 4) ? 4 : sizeof(DataType); + + data = reinterpret_cast<DataType*>(realloc(data, nitems * sz)); + + if (nitems > this->nitems) + memset(&data[this->nitems], 0, (nitems - this->nitems) * sz); + + this->nitems = nitems; +} + +template <typename DataType> +XITProperty<DataType>::~XITProperty() +{ + XFree(data); +} + +template <typename DataType> +DataType XITProperty<DataType>::At(size_t index) const +{ + if (index > nitems) + throw new std::runtime_error("Array index out of bounds"); + return data[index]; +} + +template <typename DataType> +void XITProperty<DataType>::Set(size_t index, DataType value) +{ + if (index >= nitems) + Resize(index + 1); + data[index] = value; +} + +#endif /* _ATOM_HELPERS_H_ */ |