dnl Process this file with autoconf to create configure.
AC_PREREQ([2.57])
- AC_INIT(xinput,[1.4.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],xinput)
+ AC_INIT(xinput,[1.4.1], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],xinput)
AM_INIT_AUTOMAKE([dist-bzip2])
AM_MAINTAINER_MODE
# Checks for pkg-config packages
PKG_CHECK_MODULES(XINPUT, x11 xext [xi >= 1.2] [inputproto >= 1.5])
-LIBS="$XINPUT_LIBS $LIBS"
-AC_CHECK_FUNC(XSetClientPointer,AC_DEFINE(HAVE_XI2,1,[XInput Version 2 Enabled]))
-AM_CONDITIONAL(HAVE_XI2, [test "x$ac_cv_func_XSetClientPointer" = "xyes"] )
+# XI2 support
+PKG_CHECK_MODULES(XI2, [xi >= 1.2.99],
+ HAVE_XI2="yes"; AC_DEFINE(HAVE_XI2, 1, "foo"),
+ HAVE_XI2="no");
+AM_CONDITIONAL(HAVE_XI2, [ test "$HAVE_XI2" = "yes" ])
-XINPUT_CFLAGS="$CWARNFLAGS $XINPUT_CFLAGS"
AC_SUBST(XINPUT_CFLAGS)
AC_SUBST(XINPUT_LIBS)
AC_SUBST(HAVE_XI2)
#include <X11/extensions/XIproto.h> /* for XI_Device***ChangedNotify */
static void
- print_info(XDeviceInfo *info, Bool shortformat)
+ print_info(Display* dpy, XDeviceInfo *info, Bool shortformat)
{
int i,j;
XAnyClassPtr any;
XButtonInfoPtr b;
XValuatorInfoPtr v;
XAxisInfoPtr a;
-#if HAVE_XI2
- XAttachInfoPtr att;
-#endif
printf("\"%s\"\tid=%ld\t[", info->name, info->id);
if (shortformat)
return;
+ if(info->type != None)
+ printf("\tType is %s\n", XGetAtomName(dpy, info->type));
+
if (info->num_classes > 0) {
any = (XAnyClassPtr) (info->inputclassinfo);
for (i=0; i<info->num_classes; i++) {
printf ("\t\tResolution is %d\n", a->resolution);
}
break;
-#if HAVE_XI2
- case AttachClass:
- att = (XAttachInfoPtr)any;
- printf("\tAttached to %d\n", att->attached);
- break;
-#endif
default:
printf ("unknown class\n");
}
}
}
-int
-list(Display *display,
- int argc,
- char *argv[],
- char *name,
- char *desc)
+static int list_xi1(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
{
XDeviceInfo *info;
int loop;
if (argc == 0 || shortformat || daemon) {
int num_devices;
- XEvent ev;
-
-#if HAVE_XI2
- if (daemon)
- {
- XiSelectEvent(display, DefaultRootWindow(display), NULL,
- XI_DeviceHierarchyChangedMask |
- XI_DeviceClassesChangedMask);
- }
-#endif
do {
info = XListInputDevices(display, &num_devices);
for(loop=0; loop<num_devices; loop++) {
- print_info(info+loop, shortformat);
+ print_info(display, info+loop, shortformat);
}
-
-#if HAVE_XI2
- /* just wait for the next generic event to come along */
- while (daemon && !XNextEvent(display, &ev))
- {
- if (ev.type == GenericEvent)
- {
- XGenericEvent* gev = (XGenericEvent*)&ev;
- /* we just assume that extension is IReqCode, pretty save
- since we don't register for other events. */
- if (gev->evtype == XI_DeviceHierarchyChangedNotify)
- {
- printf("Hierarchy change.\n");
- } else if (gev->evtype == XI_DeviceClassesChangedNotify)
- {
- printf("Device classes changed.\n");
- free(((XDeviceClassesChangedEvent*)&ev)->inputclassinfo);
- }
- break;
- }
- }
-#endif
} while(daemon);
} else {
int ret = EXIT_SUCCESS;
fprintf(stderr, "unable to find device %s\n", argv[loop]);
ret = EXIT_FAILURE;
} else {
- print_info(info, shortformat);
+ print_info(display, info, shortformat);
}
}
return ret;
return EXIT_SUCCESS;
}
+#ifdef HAVE_XI2
+/* also used from test_xi2.c */
+void
+print_classes_xi2(Display* display, XIAnyClassInfo **classes,
+ int num_classes)
+{
+ int i;
+
+ printf("\tReporting %d classes:\n", num_classes);
+ for (i = 0; i < num_classes; i++)
+ {
+ switch(classes[i]->type)
+ {
+ case ButtonClass:
+ {
+ XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i];
+ printf("\t\tButtons supported: %d\n", b->num_buttons);
+
+ }
+ break;
+ case KeyClass:
+ {
+ XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i];
+ printf("\t\tKeycodes supported: %d\n", k->num_keycodes);
+ }
+ break;
+ case ValuatorClass:
+ {
+ XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i];
+ printf("\t\tDetail for Valuator %d:\n", v->number);
+ printf("\t\t Name: %s\n", XGetAtomName(display, v->name));
+ printf("\t\t Range: %f - %f\n", v->min, v->max);
+ printf("\t\t Resolution: %d units/m\n", v->resolution);
+ printf("\t\t Mode: %s\n", v->mode == Absolute ? "absolute" :
+ "relative");
+ }
+ break;
+ }
+ }
+
+ printf("\n");
+}
+
+static void
+print_info_xi2(Display* display, XIDeviceInfo *dev, Bool shortformat)
+{
+ printf("%-40s\tid=%d\t[", dev->name, dev->deviceid);
+ switch(dev->use)
+ {
+ case MasterPointer:
+ printf("master pointer (%d)]\n", dev->attachment);
+ break;
+ case MasterKeyboard:
+ printf("master keyboard (%d)]\n", dev->attachment);
+ break;
+ case SlavePointer:
+ printf("slave pointer (%d)]\n", dev->attachment);
+ break;
+ case SlaveKeyboard:
+ printf("slave keyboard (%d)]\n", dev->attachment);
+ break;
+ case FloatingSlave:
+ printf("floating slave]\n");
+ break;
+ }
+
+ if (shortformat)
+ return;
+
+ if (!dev->enabled)
+ printf("\tThis device is disabled\n");
+
+ print_classes_xi2(display, dev->classes, dev->num_classes);
+}
+
+
+int
+list_xi2(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ int major = XI_2_Major,
+ minor = XI_2_Minor;
+ int ndevices;
+ int i, j, shortformat;
+ XIDeviceInfo *info, *dev;
+
+ shortformat = (argc == 1 && strcmp(argv[0], "--short") == 0);
+
+ if (XIQueryVersion(display, &major, &minor) != Success ||
+ (major * 1000 + minor) < (XI_2_Major * 1000 + XI_2_Minor))
+ {
+ fprintf(stderr, "XI2 not supported.\n");
+ return EXIT_FAILURE;
+ }
+
+ info = XIQueryDevice(display, AllDevices, &ndevices);
+ dev = info;
+
+ for(i = 0; i < ndevices; i++)
+ {
+ dev = &info[i];
+ if (dev->use == MasterPointer || dev->use == MasterKeyboard)
+ {
+ if (dev->use == MasterPointer)
+ printf("⎡ ");
+ else
+ printf("⎣ ");
+
+ print_info_xi2(display, dev, shortformat);
+ for (j = 0; j < ndevices; j++)
+ {
+ XIDeviceInfo* sd = &info[j];
+
+ if ((sd->use == SlavePointer || sd->use == SlaveKeyboard) &&
+ (sd->attachment == dev->deviceid))
+ {
+ printf("%s ↳ ", dev->use == MasterPointer ? "⎜" : " ");
+ print_info_xi2(display, sd, shortformat);
+ }
+ }
+ }
+ }
+
+
+ XIFreeDeviceInfo(info);
+ return EXIT_SUCCESS;
+}
+#endif
+
+int
+list(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+#ifdef HAVE_XI2
+ if (xinput_version(display) == XI_2_Major)
+ return list_xi2(display, argc, argv, name, desc);
+#endif
+ return list_xi1(display, argc, argv, name, desc);
+}
+
/* end of list.c */
#include "xinput.h"
+ static Atom parse_atom(Display *dpy, char *name) {
+ Bool is_atom = True;
+ int i;
+
+ for (i = 0; name[i] != '\0'; i++) {
+ if (!isdigit(name[i])) {
+ is_atom = False;
+ break;
+ }
+ }
+
+ if (is_atom)
+ return atoi(name);
+ else
+ return XInternAtom(dpy, name, False);
+ }
+
static void
print_property(Display *dpy, XDevice* dev, Atom property)
{
int act_format;
unsigned long nitems, bytes_after;
unsigned char *data, *ptr;
- int j, done = False;
+ int j, done = False, size;
name = XGetAtomName(dpy, property);
printf("\t%s (%ld):\t", name, property);
AnyPropertyType, &act_type, &act_format,
&nitems, &bytes_after, &data) == Success)
{
- int float_atom = XInternAtom(dpy, "FLOAT", False);
+ Atom float_atom = XInternAtom(dpy, "FLOAT", True);
ptr = data;
+ switch(act_format)
+ {
+ case 8: size = sizeof(char); break;
+ case 16: size = sizeof(short); break;
+ case 32: size = sizeof(long); break;
+ }
+
for (j = 0; j < nitems; j++)
{
switch(act_type)
switch(act_format)
{
case 8:
- printf("%d", *((int8_t*)ptr));
+ printf("%d", *((char*)ptr));
break;
case 16:
- printf("%d", *((int16_t*)ptr));
+ printf("%d", *((short*)ptr));
break;
case 32:
printf("%ld", *((long*)ptr));
}
break;
case XA_STRING:
+ if (act_format != 8)
{
- int len = 0;
- unsigned char *p = ptr;
- while(len < nitems)
- {
- printf("'%s' ", &p[len]);
- len += (strlen(&p[len]) + 1);
- }
+ printf("Unknown string format.\n");
done = True;
break;
}
+ printf("\"%s\"", ptr);
+ j += strlen((char*)ptr); /* The loop's j++ jumps over the
+ terminating 0 */
+ ptr += strlen((char*)ptr); /* ptr += size below jumps over
+ the terminating 0 */
+ break;
case XA_ATOM:
printf("\"%s\"", XGetAtomName(dpy, *(Atom*)ptr));
break;
break;
}
- ptr += act_format/8;
+ ptr += size;
- if (j < nitems - 1)
- printf(", ");
if (done == True)
break;
+ if (j < nitems - 1)
+ printf(", ");
}
printf("\n");
XFree(data);
Atom prop;
char *name;
int i;
- Bool is_atom = True;
char *data;
int format, nelements = 0;
name = argv[1];
- for(i = 0; i < strlen(name); i++) {
- if (!isdigit(name[i])) {
- is_atom = False;
- break;
- }
- }
-
- if (!is_atom)
- prop = XInternAtom(dpy, name, False);
- else
- prop = atoi(name);
+ prop = parse_atom(dpy, name);
nelements = argc - 3;
format = atoi(argv[2]);
return EXIT_FAILURE;
}
- data = calloc(nelements, format/8);
+ data = calloc(nelements, sizeof(long));
for (i = 0; i < nelements; i++)
{
switch(format)
{
case 8:
- *(((int8_t*)data) + i) = atoi(argv[3 + i]);
+ *(((char*)data) + i) = atoi(argv[3 + i]);
break;
case 16:
- *(((int16_t*)data) + i) = atoi(argv[3 + i]);
+ *(((short*)data) + i) = atoi(argv[3 + i]);
break;
case 32:
*(((long*)data) + i) = atoi(argv[3 + i]);
Atom prop, float_atom;
char *name;
int i;
- Bool is_atom = True;
- float *data;
+ long *data;
int nelements = 0;
char* endptr;
name = argv[1];
- for(i = 0; i < strlen(name); i++) {
- if (!isdigit(name[i])) {
- is_atom = False;
- break;
- }
- }
-
- if (!is_atom)
- prop = XInternAtom(dpy, name, False);
- else
- prop = atoi(name);
+ prop = parse_atom(dpy, name);
nelements = argc - 2;
return EXIT_FAILURE;
}
- data = calloc(nelements, 4);
+ data = calloc(nelements, sizeof(long));
for (i = 0; i < nelements; i++)
{
- *(data + i) = strtod(argv[2 + i], &endptr);
+ *((float*)(data + i)) = strtod(argv[2 + i], &endptr);
if(endptr == argv[2 + i]){
fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
return EXIT_FAILURE;
XDevice *dev;
XDeviceInfo *info;
char *name;
- int i;
- Bool is_atom = True;
Atom prop;
info = find_device_info(dpy, argv[0], False);
name = argv[1];
- for(i = 0; i < strlen(name); i++) {
- if (!isdigit(name[i])) {
- is_atom = False;
- break;
- }
- }
-
- if (!is_atom)
- prop = XInternAtom(dpy, name, False);
- else
- prop = atoi(name);
+ prop = parse_atom(dpy, name);
XDeleteDeviceProperty(dpy, dev, prop);
Atom prop;
char *name;
int i, j;
- Bool is_atom = True;
+ Bool is_atom;
Atom *data;
int nelements = 0;
name = argv[1];
- for(i = 0; i < strlen(name); i++) {
- if (!isdigit(name[i])) {
- is_atom = False;
- break;
- }
- }
-
- if (!is_atom)
- prop = XInternAtom(dpy, name, False);
- else
- prop = atoi(name);
+ prop = parse_atom(dpy, name);
nelements = argc - 2;
data = calloc(nelements, sizeof(Atom));
return EXIT_SUCCESS;
}
+ int
+ set_prop(Display *dpy, int argc, char **argv, char *n, char *desc)
+ {
+ XDeviceInfo *info;
+ XDevice *dev;
+ Atom prop;
+ Atom type;
+ char *name;
+ int i;
+ Atom float_atom;
+ int format, nelements = 0;
+ unsigned long act_nitems, bytes_after;
+ char *endptr;
+ union {
+ unsigned char *c;
+ short *s;
+ long *l;
+ Atom *a;
+ } data;
+
+ if (argc < 3)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = find_device_info(dpy, argv[0], False);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device %s\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ dev = XOpenDevice(dpy, info->id);
+ if (!dev)
+ {
+ fprintf(stderr, "unable to open device %s\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ name = argv[1];
+
+ prop = parse_atom(dpy, name);
+
+ if (prop == None) {
+ fprintf(stderr, "invalid property %s\n", name);
+ return EXIT_FAILURE;
+ }
+
+ float_atom = XInternAtom(dpy, "FLOAT", False);
+
+ nelements = argc - 2;
+ if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType,
+ &type, &format, &act_nitems, &bytes_after, &data.c)
+ != Success) {
+ fprintf(stderr, "failed to get property type and format for %s\n", name);
+ return EXIT_FAILURE;
+ }
+
+ XFree(data.c);
+
+ if (type == None) {
+ fprintf(stderr, "property %s doesn't exist\n", name);
+ return EXIT_FAILURE;
+ }
+
+ data.c = calloc(nelements, sizeof(long));
+
+ for (i = 0; i < nelements; i++)
+ {
+ if (type == XA_INTEGER) {
+ switch (format)
+ {
+ case 8:
+ data.c[i] = atoi(argv[2 + i]);
+ break;
+ case 16:
+ data.s[i] = atoi(argv[2 + i]);
+ break;
+ case 32:
+ data.l[i] = atoi(argv[2 + i]);
+ break;
+ default:
+ fprintf(stderr, "unexpected size for property %s", name);
+ return EXIT_FAILURE;
+ }
+ } else if (type == float_atom) {
+ if (format != 32) {
+ fprintf(stderr, "unexpected format %d for property %s\n",
+ format, name);
+ return EXIT_FAILURE;
+ }
+ *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
+ if (endptr == argv[2 + i]) {
+ fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
+ return EXIT_FAILURE;
+ }
+ } else if (type == XA_ATOM) {
+ if (format != 32) {
+ fprintf(stderr, "unexpected format %d for property %s\n",
+ format, name);
+ return EXIT_FAILURE;
+ }
+ data.a[i] = parse_atom(dpy, argv[2 + i]);
+ } else {
+ fprintf(stderr, "unexpected type for property %s\n", name);
+ return EXIT_FAILURE;
+ }
+ }
+ XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace,
+ data.c, nelements);
+ free(data.c);
+ XCloseDevice(dpy, dev);
+ return EXIT_SUCCESS;
+ }
"<window> <device>",
set_clientpointer
},
+ { "test-xi2",
+ "<device>",
+ test_xi2,
+ },
#endif
{ "list-props",
"<device> [<device> ...]",
"<device> <property>",
delete_prop
},
+ { "set-prop",
+ "<device> <property> <val> [<val> ...]",
+ set_prop
+ },
{NULL, NULL, NULL
}
};
-static Bool
-is_xinput_present(Display *display)
+int
+xinput_version(Display *display)
{
XExtensionVersion *version;
- Bool present;
+ static int vers = -1;
+
+ if (vers != -1)
+ return vers;
-#if HAVE_XI2
- version = XQueryInputVersion(display, XI_2_Major, XI_2_Minor);
-#else
version = XGetExtensionVersion(display, INAME);
-#endif
if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
- present = version->present;
+ vers = version->major_version;
XFree(version);
- return present;
- } else {
- return False;
}
+
+ return vers;
}
XDeviceInfo*
"Warning: There are multiple devices named \"%s\".\n"
"To ensure the correct one is selected, please use "
"the device ID instead.\n\n", name);
- return NULL;
+ return NULL;
} else {
found = &devices[loop];
}
return found;
}
+#ifdef HAVE_XI2
+int
+xi2_find_device_id(Display *display, char *name)
+{
+ XIDeviceInfo *info;
+ int ndevices;
+ Bool is_id = True;
+ int i, id = -1;
+
+ for(i = 0; i < strlen(name); i++) {
+ if (!isdigit(name[i])) {
+ is_id = False;
+ break;
+ }
+ }
+
+ if (is_id) {
+ id = atoi(name);
+ } else
+ {
+ info = XIQueryDevice(display, AllDevices, &ndevices);
+ for(i = 0; i < ndevices; i++)
+ {
+ if ((is_id && info[i].deviceid == id) ||
+ (!is_id && strcmp(info[i].name, name) == 0))
+ {
+ id = info[i].deviceid;
+ break;
+ }
+ }
+
+ XIFreeDeviceInfo(info);
+ }
+ return id;;
+}
+#endif
+
static void
usage(void)
{
func = argv[1];
while((*func) == '-') func++;
- if (!is_xinput_present(display)) {
+ if (!xinput_version(display)) {
fprintf(stderr, "%s extension not available\n", INAME);
return EXIT_FAILURE;
}
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
+#ifdef HAVE_XI2
+#include <X11/extensions/XInput2.h>
+#endif
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#define EXIT_FAILURE 0
#endif
- XDeviceInfo*
- find_device_info(
- Display *display,
- char *name,
- Bool only_extended
- );
- int
- xi2_find_device_id(Display *display, char *name);
+
+ XDeviceInfo* find_device_info( Display *display, char *name, Bool only_extended);
++int xi2_find_device_id(Display *display, char *name);
+int xinput_version(Display* display);
- #define DECLARE(name) \
- int (name) ( \
- Display* display, \
- int argc, \
- char *argv[], \
- char *prog_name, \
- char *prog_desc \
- )
+ int get_feedbacks( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_ptr_feedback( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int get_button_map( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_button_map( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_pointer( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+ int set_mode( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int list( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int test( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int version( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_integer_feedback( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int query_state( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+ /* X Input 1.5 */
+ int list_props( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_int_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_float_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_atom_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int watch_props( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int delete_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+ /* X Input 2.0 */
+ int create_master( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int remove_master( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int change_attachment( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int float_device( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+ int set_clientpointer( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
++int test_xi2( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
- DECLARE(get_feedbacks);
- DECLARE(set_ptr_feedback);
- DECLARE(get_button_map);
- DECLARE(set_button_map);
- DECLARE(set_pointer);
- DECLARE(set_mode);
- DECLARE(list);
- DECLARE(test);
- DECLARE(version);
- DECLARE(set_integer_feedback);
- DECLARE(query_state);
- DECLARE(create_master);
- DECLARE(remove_master);
- DECLARE(change_attachment);
- DECLARE(float_device);
- DECLARE(set_clientpointer);
- DECLARE(test_xi2);
- DECLARE(list_props);
- DECLARE(set_int_prop);
- DECLARE(set_float_prop);
- DECLARE(set_atom_prop);
- DECLARE(watch_props);
- DECLARE(delete_prop);
/* end of xinput.h */