diff options
Diffstat (limited to 'app/xinput/src')
-rw-r--r-- | app/xinput/src/Makefile.am | 5 | ||||
-rw-r--r-- | app/xinput/src/Makefile.in | 17 | ||||
-rw-r--r-- | app/xinput/src/hierarchy.c | 134 | ||||
-rw-r--r-- | app/xinput/src/list.c | 260 | ||||
-rw-r--r-- | app/xinput/src/property.c | 684 | ||||
-rw-r--r-- | app/xinput/src/setcp.c | 13 | ||||
-rw-r--r-- | app/xinput/src/test_xi2.c | 381 | ||||
-rw-r--r-- | app/xinput/src/version.c | 43 | ||||
-rw-r--r-- | app/xinput/src/xinput.c | 130 | ||||
-rw-r--r-- | app/xinput/src/xinput.h | 289 |
10 files changed, 1293 insertions, 663 deletions
diff --git a/app/xinput/src/Makefile.am b/app/xinput/src/Makefile.am index 1efddb888..ba0d325ac 100644 --- a/app/xinput/src/Makefile.am +++ b/app/xinput/src/Makefile.am @@ -26,8 +26,8 @@ xinput_LDADD = $(XINPUT_LIBS) if HAVE_XI2 - xinput2_files = hierarchy.c setcp.c -endif # HAVE_XI2 +xinput2_files = hierarchy.c setcp.c test_xi2.c +endif xinput_SOURCES = \ buttonmap.c \ @@ -39,7 +39,6 @@ xinput_SOURCES = \ state.c \ property.c \ test.c \ - version.c \ xinput.c \ xinput.h \ $(xinput2_files) diff --git a/app/xinput/src/Makefile.in b/app/xinput/src/Makefile.in index 040d73972..4ba411ca1 100644 --- a/app/xinput/src/Makefile.in +++ b/app/xinput/src/Makefile.in @@ -71,14 +71,14 @@ am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am__xinput_SOURCES_DIST = buttonmap.c feedback.c list.c setint.c \ - setmode.c setptr.c state.c property.c test.c version.c \ - xinput.c xinput.h hierarchy.c setcp.c -@HAVE_XI2_TRUE@am__objects_1 = hierarchy.$(OBJEXT) setcp.$(OBJEXT) + setmode.c setptr.c state.c property.c test.c xinput.c xinput.h \ + hierarchy.c setcp.c test_xi2.c +@HAVE_XI2_TRUE@am__objects_1 = hierarchy.$(OBJEXT) setcp.$(OBJEXT) \ +@HAVE_XI2_TRUE@ test_xi2.$(OBJEXT) am_xinput_OBJECTS = buttonmap.$(OBJEXT) feedback.$(OBJEXT) \ list.$(OBJEXT) setint.$(OBJEXT) setmode.$(OBJEXT) \ setptr.$(OBJEXT) state.$(OBJEXT) property.$(OBJEXT) \ - test.$(OBJEXT) version.$(OBJEXT) xinput.$(OBJEXT) \ - $(am__objects_1) + test.$(OBJEXT) xinput.$(OBJEXT) $(am__objects_1) xinput_OBJECTS = $(am_xinput_OBJECTS) am__DEPENDENCIES_1 = xinput_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -158,6 +158,8 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +XI2_CFLAGS = @XI2_CFLAGS@ +XI2_LIBS = @XI2_LIBS@ XINPUT_CFLAGS = @XINPUT_CFLAGS@ XINPUT_LIBS = @XINPUT_LIBS@ ac_ct_CC = @ac_ct_CC@ @@ -206,7 +208,7 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_CFLAGS = $(XINPUT_CFLAGS) xinput_LDADD = $(XINPUT_LIBS) -@HAVE_XI2_TRUE@xinput2_files = hierarchy.c setcp.c +@HAVE_XI2_TRUE@xinput2_files = hierarchy.c setcp.c test_xi2.c xinput_SOURCES = \ buttonmap.c \ feedback.c \ @@ -217,7 +219,6 @@ xinput_SOURCES = \ state.c \ property.c \ test.c \ - version.c \ xinput.c \ xinput.h \ $(xinput2_files) @@ -299,7 +300,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setptr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_xi2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xinput.Po@am__quote@ .c.o: diff --git a/app/xinput/src/hierarchy.c b/app/xinput/src/hierarchy.c index 869c3fd8e..7f35c3988 100644 --- a/app/xinput/src/hierarchy.c +++ b/app/xinput/src/hierarchy.c @@ -40,7 +40,7 @@ int create_master(Display* dpy, int argc, char** argv, char* name, char *desc) { - XCreateMasterInfo c; + XIAddMasterInfo c; if (argc == 0) { @@ -48,12 +48,12 @@ create_master(Display* dpy, int argc, char** argv, char* name, char *desc) return EXIT_FAILURE; } - c.type = CH_CreateMasterDevice; + c.type = XIAddMaster; c.name = argv[0]; - c.sendCore = (argc >= 2) ? atoi(argv[1]) : 1; + c.send_core = (argc >= 2) ? atoi(argv[1]) : 1; c.enable = (argc >= 3) ? atoi(argv[2]) : 1; - return XChangeDeviceHierarchy(dpy, (XAnyHierarchyChangeInfo*)&c, 1); + return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1); } /** @@ -64,9 +64,8 @@ create_master(Display* dpy, int argc, char** argv, char* name, char *desc) int remove_master(Display* dpy, int argc, char** argv, char *name, char *desc) { - XDeviceInfo *info; - XRemoveMasterInfo r; - XDevice* master = NULL, *ptr = NULL, *keybd = NULL; + XIRemoveMasterInfo r; + XIDeviceInfo *info; int ret; if (argc == 0) @@ -75,45 +74,67 @@ remove_master(Display* dpy, int argc, char** argv, char *name, char *desc) return EXIT_FAILURE; } - info = find_device_info(dpy, argv[0], False); + info = xi2_find_device_info(dpy, argv[0]); if (!info) { fprintf(stderr, "unable to find device %s\n", argv[0]); return EXIT_FAILURE; } - master = XOpenDevice(dpy, info->id); - if (!master) - Error(BadValue, "Unable to open device %s.\n", argv[0]); - - r.type = CH_RemoveMasterDevice; - r.device = master; + r.type = XIRemoveMaster; + r.deviceid = info->deviceid; if (argc >= 2) { if (!strcmp(argv[1], "Floating")) - r.returnMode = Floating; + r.return_mode = XIFloating; else if (!strcmp(argv[1], "AttachToMaster")) - r.returnMode = AttachToMaster; + r.return_mode = XIAttachToMaster; else - Error(BadValue, "Invalid returnMode.\n"); + Error(BadValue, "Invalid return_mode.\n"); } else - r.returnMode = Floating; + r.return_mode = XIFloating; - if (r.returnMode == AttachToMaster) + if (r.return_mode == XIAttachToMaster) { - ptr = XOpenDevice(dpy, atoi(argv[2])); - keybd = XOpenDevice(dpy, atoi(argv[3])); - if (!ptr || !keybd) - Error(BadValue, "Invalid fallback master.\n"); - r.returnPointer = ptr; - r.returnKeyboard = keybd; + r.return_pointer = 0; + if (argc >= 3) { + info = xi2_find_device_info(dpy, argv[2]); + if (!info) { + fprintf(stderr, "unable to find device %s\n", argv[2]); + return EXIT_FAILURE; + } + + r.return_pointer = info->deviceid; + } + + r.return_keyboard = 0; + if (argc >= 4) { + info = xi2_find_device_info(dpy, argv[3]); + if (!info) { + fprintf(stderr, "unable to find device %s\n", argv[3]); + return EXIT_FAILURE; + } + + r.return_keyboard = info->deviceid; + } + + if (!r.return_pointer || !r.return_keyboard) { + int i, ndevices; + info = XIQueryDevice(dpy, XIAllMasterDevices, &ndevices); + for(i = 0; i < ndevices; i++) { + if (info[i].use == XIMasterPointer && !r.return_pointer) + r.return_pointer = info[i].deviceid; + if (info[i].use == XIMasterKeyboard && !r.return_keyboard) + r.return_keyboard = info[i].deviceid; + if (r.return_pointer && r.return_keyboard) + break; + } + + XIFreeDeviceInfo(info); + } } - ret = XChangeDeviceHierarchy(dpy, (XAnyHierarchyChangeInfo*)&r, 1); - if (ptr) - XCloseDevice(dpy, ptr); - if (keybd) - XCloseDevice(dpy, keybd); + ret = XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&r, 1); return ret; } @@ -123,9 +144,8 @@ remove_master(Display* dpy, int argc, char** argv, char *name, char *desc) int change_attachment(Display* dpy, int argc, char** argv, char *name, char* desc) { - XDeviceInfo *info_sd, *info_md; - XChangeAttachmentInfo c; - XDevice *slave, *master; + XIDeviceInfo *sd_info, *md_info; + XIAttachSlaveInfo c; int ret; if (argc < 2) @@ -134,36 +154,24 @@ change_attachment(Display* dpy, int argc, char** argv, char *name, char* desc) return EXIT_FAILURE; } - info_sd = find_device_info(dpy, argv[0], True); - info_md = find_device_info(dpy, argv[1], False); + sd_info = xi2_find_device_info(dpy, argv[0]); + md_info= xi2_find_device_info(dpy, argv[1]); - if (!info_sd) { + if (!sd_info) { fprintf(stderr, "unable to find device %s\n", argv[0]); return EXIT_FAILURE; } - if (!info_md) { + if (!md_info) { fprintf(stderr, "unable to find device %s\n", argv[1]); return EXIT_FAILURE; } - slave = XOpenDevice(dpy, info_sd->id); - master = XOpenDevice(dpy, info_md->id); - - if (!slave) - Error(BadValue, "Invalid slave device given %d\n", atoi(argv[0])); - - if (!master) - Error(BadValue, "Invalid master device given %d\n", atoi(argv[1])); + c.type = XIAttachSlave; + c.deviceid = sd_info->deviceid; + c.new_master = md_info->deviceid; - c.type = CH_ChangeAttachment; - c.changeMode = AttachToMaster; - c.device = slave; - c.newMaster = master; - - ret = XChangeDeviceHierarchy(dpy, (XAnyHierarchyChangeInfo*)&c, 1); - XCloseDevice(dpy, slave); - XCloseDevice(dpy, master); + ret = XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1); return ret; } @@ -173,9 +181,8 @@ change_attachment(Display* dpy, int argc, char** argv, char *name, char* desc) int float_device(Display* dpy, int argc, char** argv, char* name, char* desc) { - XDeviceInfo *info; - XChangeAttachmentInfo c; - XDevice *slave; + XIDeviceInfo *info; + XIDetachSlaveInfo c; int ret; if (argc < 1) @@ -184,24 +191,17 @@ float_device(Display* dpy, int argc, char** argv, char* name, char* desc) return EXIT_FAILURE; } - info = find_device_info(dpy, argv[0], True); + info = xi2_find_device_info(dpy, argv[0]); if (!info) { fprintf(stderr, "unable to find device %s\n", argv[0]); return EXIT_FAILURE; } - slave = XOpenDevice(dpy, info->id); - - if (!slave) - return BadValue; - - c.type = CH_ChangeAttachment; - c.changeMode = Floating; - c.device = slave; + c.type = XIDetachSlave; + c.deviceid = info->deviceid; - ret = XChangeDeviceHierarchy(dpy, (XAnyHierarchyChangeInfo*)&c, 1); - XCloseDevice(dpy, slave); + ret = XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1); return ret; } diff --git a/app/xinput/src/list.c b/app/xinput/src/list.c index bd71a5ccc..ecf1f4ba5 100644 --- a/app/xinput/src/list.c +++ b/app/xinput/src/list.c @@ -34,9 +34,6 @@ print_info(Display* dpy, XDeviceInfo *info, Bool shortformat) XButtonInfoPtr b; XValuatorInfoPtr v; XAxisInfoPtr a; -#if HAVE_XI2 - XAttachInfoPtr att; -#endif printf("\"%s\"\tid=%ld\t[", info->name, info->id); @@ -98,12 +95,6 @@ print_info(Display* dpy, XDeviceInfo *info, Bool shortformat) 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"); } @@ -112,78 +103,221 @@ print_info(Display* dpy, XDeviceInfo *info, Bool shortformat) } } -int -list(Display *display, - int argc, - char *argv[], - char *name, - char *desc) +static int list_xi1(Display *display, + int shortformat) { XDeviceInfo *info; int loop; - int shortformat = False; - int daemon = False; + int num_devices; - shortformat = (argc == 1 && strcmp(argv[0], "--short") == 0); - daemon = (argc == 1 && strcmp(argv[0], "--loop") == 0); + info = XListInputDevices(display, &num_devices); + for(loop=0; loop<num_devices; loop++) { + print_info(display, info+loop, shortformat); + } + return EXIT_SUCCESS; +} - if (argc == 0 || shortformat || daemon) { - int num_devices; - XEvent ev; +#ifdef HAVE_XI2 +/* also used from test_xi2.c */ +void +print_classes_xi2(Display* display, XIAnyClassInfo **classes, + int num_classes) +{ + int i, j; -#if HAVE_XI2 - if (daemon) + printf("\tReporting %d classes:\n", num_classes); + for (i = 0; i < num_classes; i++) + { + printf("\t\tClass originated from: %d\n", classes[i]->sourceid); + switch(classes[i]->type) { - XiSelectEvent(display, DefaultRootWindow(display), NULL, - XI_DeviceHierarchyChangedMask | - XI_DeviceClassesChangedMask); + case XIButtonClass: + { + XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i]; + char *name; + printf("\t\tButtons supported: %d\n", b->num_buttons); + printf("\t\tButton labels:"); + for (j = 0; j < b->num_buttons; j++) + { + name = (b->labels[j]) ? XGetAtomName(display, b->labels[j]) : NULL; + printf(" %s", (name) ? name : "None"); + XFree(name); + } + printf("\n"); + printf("\t\tButton state:"); + for (j = 0; j < b->state.mask_len * 8; j++) + if (XIMaskIsSet(b->state.mask, j)) + printf(" %d", j); + printf("\n"); + + } + break; + case XIKeyClass: + { + XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i]; + printf("\t\tKeycodes supported: %d\n", k->num_keycodes); + } + break; + case XIValuatorClass: + { + XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i]; + char *name = v->label ? XGetAtomName(display, v->label) : NULL; + + printf("\t\tDetail for Valuator %d:\n", v->number); + printf("\t\t Label: %s\n", (name) ? name : "None"); + 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"); + if (v->mode == Absolute) + printf("\t\t Current value: %f\n", v->value); + XFree(name); + } + break; } -#endif + } - do { - info = XListInputDevices(display, &num_devices); - for(loop=0; loop<num_devices; loop++) { - print_info(display, info+loop, shortformat); - } + printf("\n"); +} -#if HAVE_XI2 - /* just wait for the next generic event to come along */ - while (daemon && !XNextEvent(display, &ev)) +static void +print_info_xi2(Display* display, XIDeviceInfo *dev, Bool shortformat) +{ + printf("%-40s\tid=%d\t[", dev->name, dev->deviceid); + switch(dev->use) + { + case XIMasterPointer: + printf("master pointer (%d)]\n", dev->attachment); + break; + case XIMasterKeyboard: + printf("master keyboard (%d)]\n", dev->attachment); + break; + case XISlavePointer: + printf("slave pointer (%d)]\n", dev->attachment); + break; + case XISlaveKeyboard: + printf("slave keyboard (%d)]\n", dev->attachment); + break; + case XIFloatingSlave: + 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); +} + + +static int +list_xi2(Display *display, + int shortformat) +{ + int major = XI_2_Major, + minor = XI_2_Minor; + int ndevices; + int i, j; + XIDeviceInfo *info, *dev; + + 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, XIAllDevices, &ndevices); + + for(i = 0; i < ndevices; i++) + { + dev = &info[i]; + if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard) + { + if (dev->use == XIMasterPointer) + printf("⎡ "); + else + printf("⎣ "); + + print_info_xi2(display, dev, shortformat); + for (j = 0; j < ndevices; j++) { - if (ev.type == GenericEvent) + XIDeviceInfo* sd = &info[j]; + + if ((sd->use == XISlavePointer || sd->use == XISlaveKeyboard) && + (sd->attachment == dev->deviceid)) { - 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; + printf("%s ↳ ", dev->use == XIMasterPointer ? "⎜" : " "); + print_info_xi2(display, sd, shortformat); } } + } + } + + for (i = 0; i < ndevices; i++) + { + dev = &info[i]; + if (dev->use == XIFloatingSlave) + { + printf("∼ "); + print_info_xi2(display, dev, shortformat); + } + } + + + XIFreeDeviceInfo(info); + return EXIT_SUCCESS; +} #endif - } while(daemon); - } else { - int ret = EXIT_SUCCESS; - for(loop=0; loop<argc; loop++) { - info = find_device_info(display, argv[loop], False); +int +list(Display *display, + int argc, + char *argv[], + char *name, + char *desc) +{ + int shortformat = (argc >= 1 && strcmp(argv[0], "--short") == 0); + int longformat = (argc >= 1 && strcmp(argv[0], "--long") == 0); + int arg_dev = shortformat || longformat; - if (!info) { - fprintf(stderr, "unable to find device %s\n", argv[loop]); - ret = EXIT_FAILURE; - } else { - print_info(display, info, shortformat); - } - } - return ret; + if (argc > arg_dev) + { +#ifdef HAVE_XI2 + if (xinput_version(display) == XI_2_Major) + { + XIDeviceInfo *info = xi2_find_device_info(display, argv[arg_dev]); + + if (!info) { + fprintf(stderr, "unable to find device %s\n", argv[arg_dev]); + return EXIT_FAILURE; + } else { + print_info_xi2(display, info, shortformat); + return EXIT_SUCCESS; + } + } else +#endif + { + XDeviceInfo *info = find_device_info(display, argv[arg_dev], False); + + if (!info) { + fprintf(stderr, "unable to find device %s\n", argv[arg_dev]); + return EXIT_FAILURE; + } else { + print_info(display, info, shortformat); + return EXIT_SUCCESS; + } + } + } else { +#ifdef HAVE_XI2 + if (xinput_version(display) == XI_2_Major) + return list_xi2(display, !longformat); +#endif + return list_xi1(display, !longformat); } - return EXIT_SUCCESS; } /* end of list.c */ diff --git a/app/xinput/src/property.c b/app/xinput/src/property.c index 60565ed5e..6cd8e7af1 100644 --- a/app/xinput/src/property.c +++ b/app/xinput/src/property.c @@ -34,6 +34,23 @@ #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) { @@ -55,6 +72,9 @@ print_property(Display *dpy, XDevice* dev, Atom property) ptr = data; + if (nitems == 0) + printf("<no items>"); + switch(act_format) { case 8: size = sizeof(char); break; @@ -94,8 +114,13 @@ print_property(Display *dpy, XDevice* dev, Atom property) the terminating 0 */ break; case XA_ATOM: - printf("\"%s\"", XGetAtomName(dpy, *(Atom*)ptr)); - break; + { + Atom a = *(Atom*)ptr; + printf("\"%s\" (%d)", + (a) ? XGetAtomName(dpy, a) : "None", + (int)a); + break; + } default: if (float_atom != None && act_type == float_atom) { @@ -111,10 +136,10 @@ print_property(Display *dpy, XDevice* dev, Atom property) ptr += size; - if (j < nitems - 1) - printf(", "); if (done == True) break; + if (j < nitems - 1) + printf(", "); } printf("\n"); XFree(data); @@ -123,7 +148,8 @@ print_property(Display *dpy, XDevice* dev, Atom property) } -int list_props(Display *dpy, int argc, char** argv, char* name, char *desc) +static int +list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc) { XDeviceInfo *info; XDevice *dev; @@ -172,23 +198,19 @@ int list_props(Display *dpy, int argc, char** argv, char* name, char *desc) return EXIT_SUCCESS; } -int -set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) + +int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) { - XDeviceInfo *info; XDevice *dev; - Atom prop; + XDeviceInfo *info; + XEvent ev; + XDevicePropertyNotifyEvent *dpev; char *name; - int i; - Bool is_atom = True; - char *data; - int format, nelements = 0; + int type_prop; + XEventClass cls_prop; - if (argc < 3) - { - fprintf(stderr, "Usage: xinput %s %s\n", n, desc); + if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) return EXIT_FAILURE; - } info = find_device_info(dpy, argv[0], False); if (!info) @@ -200,71 +222,82 @@ set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) dev = XOpenDevice(dpy, info->id); if (!dev) { - fprintf(stderr, "unable to open device %s\n", argv[0]); + fprintf(stderr, "unable to open device '%s'\n", info->name); return EXIT_FAILURE; } - name = argv[1]; + DevicePropertyNotify(dev, type_prop, cls_prop); + XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); - for(i = 0; i < strlen(name); i++) { - if (!isdigit(name[i])) { - is_atom = False; - break; - } + while(1) + { + XNextEvent(dpy, &ev); + + dpev = (XDevicePropertyNotifyEvent*)&ev; + if (dpev->type != type_prop) + continue; + + name = XGetAtomName(dpy, dpev->atom); + printf("Property '%s' changed.\n", name); + print_property(dpy, dev, dpev->atom); } - if (!is_atom) - prop = XInternAtom(dpy, name, False); - else - prop = atoi(name); + XCloseDevice(dpy, dev); +} - nelements = argc - 3; - format = atoi(argv[2]); - if (format != 8 && format != 16 && format != 32) +static int +delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc) +{ + XDevice *dev; + XDeviceInfo *info; + char *name; + Atom prop; + + info = find_device_info(dpy, argv[0], False); + if (!info) { - fprintf(stderr, "Invalid format %d\n", format); + fprintf(stderr, "unable to find device %s\n", argv[0]); return EXIT_FAILURE; } - data = calloc(nelements, sizeof(long)); - for (i = 0; i < nelements; i++) + dev = XOpenDevice(dpy, info->id); + if (!dev) { - switch(format) - { - case 8: - *(((char*)data) + i) = atoi(argv[3 + i]); - break; - case 16: - *(((short*)data) + i) = atoi(argv[3 + i]); - break; - case 32: - *(((long*)data) + i) = atoi(argv[3 + i]); - break; - } + fprintf(stderr, "unable to open device '%s'\n", info->name); + return EXIT_FAILURE; } - XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, format, PropModeReplace, - (unsigned char*)data, nelements); + name = argv[1]; + + prop = parse_atom(dpy, name); + + XDeleteDeviceProperty(dpy, dev, prop); - free(data); XCloseDevice(dpy, dev); return EXIT_SUCCESS; } -int -set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) +static int +do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) { - XDeviceInfo *info; - XDevice *dev; - Atom prop, float_atom; - char *name; - int i; - Bool is_atom = True; - long *data; - int nelements = 0; - char* endptr; + XDeviceInfo *info; + XDevice *dev; + Atom prop; + Atom old_type; + char *name; + int i; + Atom float_atom; + int old_format, nelements = 0; + unsigned long act_nitems, bytes_after; + char *endptr; + union { + unsigned char *c; + short *s; + long *l; + Atom *a; + } data; - if (argc < 2) + if (argc < 3) { fprintf(stderr, "Usage: xinput %s %s\n", n, desc); return EXIT_FAILURE; @@ -286,153 +319,263 @@ set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) name = argv[1]; - for(i = 0; i < strlen(name); i++) { - if (!isdigit(name[i])) { - is_atom = False; - break; - } + prop = parse_atom(dpy, name); + + if (prop == None) { + fprintf(stderr, "invalid property %s\n", name); + return EXIT_FAILURE; } - if (!is_atom) - prop = XInternAtom(dpy, name, False); - else - prop = atoi(name); + float_atom = XInternAtom(dpy, "FLOAT", False); nelements = argc - 2; + if (type == None || format == 0) { + if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType, + &old_type, &old_format, &act_nitems, + &bytes_after, &data.c) != Success) { + fprintf(stderr, "failed to get property type and format for %s\n", + name); + return EXIT_FAILURE; + } else { + if (type == None) + type = old_type; + if (format == 0) + format = old_format; + } - float_atom = XInternAtom(dpy, "FLOAT", False); - - if (float_atom == (Atom)0) - { - fprintf(stderr, "no FLOAT atom present in server\n"); - return EXIT_FAILURE; + XFree(data.c); } - if (sizeof(float) != 4) - { - fprintf(stderr, "sane FP required\n"); - return EXIT_FAILURE; + if (type == None) { + fprintf(stderr, "property %s doesn't exist, you need to specify " + "its type and format\n", name); + return EXIT_FAILURE; } - data = calloc(nelements, sizeof(long)); + data.c = calloc(nelements, sizeof(long)); + for (i = 0; i < nelements; i++) { - *((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; - } + 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, float_atom, 32, PropModeReplace, - (unsigned char*)data, nelements); - - free(data); + XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, + data.c, nelements); + free(data.c); XCloseDevice(dpy, dev); return EXIT_SUCCESS; } - -int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) +#if HAVE_XI2 +static void +print_property_xi2(Display *dpy, int deviceid, Atom property) { - XDevice *dev; - XDeviceInfo *info; - XEvent ev; - XDevicePropertyNotifyEvent *dpev; - char *name; - int type_prop; - XEventClass cls_prop; + Atom act_type; + char *name; + int act_format; + unsigned long nitems, bytes_after; + unsigned char *data, *ptr; + int j, done = False; - if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) - return EXIT_FAILURE; + name = XGetAtomName(dpy, property); + printf("\t%s (%ld):\t", name, property); - info = find_device_info(dpy, argv[0], False); - if (!info) + if (XIGetProperty(dpy, deviceid, property, 0, 1000, False, + AnyPropertyType, &act_type, &act_format, + &nitems, &bytes_after, &data) == Success) { - fprintf(stderr, "unable to find device %s\n", argv[0]); - return EXIT_FAILURE; - } + Atom float_atom = XInternAtom(dpy, "FLOAT", True); - dev = XOpenDevice(dpy, info->id); - if (!dev) + ptr = data; + + if (nitems == 0) + printf("<no items>"); + + for (j = 0; j < nitems; j++) + { + switch(act_type) + { + case XA_INTEGER: + switch(act_format) + { + case 8: + printf("%d", *((int8_t*)ptr)); + break; + case 16: + printf("%d", *((int16_t*)ptr)); + break; + case 32: + printf("%d", *((int32_t*)ptr)); + break; + } + break; + case XA_STRING: + if (act_format != 8) + { + 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: + { + Atom a = *(Atom*)ptr; + printf("\"%s\" (%d)", + (a) ? XGetAtomName(dpy, a) : "None", + (int)a); + break; + } + break; + default: + if (float_atom != None && act_type == float_atom) + { + printf("%f", *((float*)ptr)); + break; + } + + printf("\t... of unknown type %s\n", + XGetAtomName(dpy, act_type)); + done = True; + break; + } + + ptr += act_format/8; + + if (done == True) + break; + if (j < nitems - 1) + printf(", "); + } + printf("\n"); + XFree(data); + } else + printf("\tFetch failure\n"); + +} + +static int +list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc) +{ + XIDeviceInfo *info; + int i; + int nprops; + Atom *props; + + if (argc == 0) { - fprintf(stderr, "unable to open device '%s'\n", info->name); + fprintf(stderr, "Usage: xinput %s %s\n", name, desc); return EXIT_FAILURE; } - DevicePropertyNotify(dev, type_prop, cls_prop); - XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); - - while(1) + for (i = 0; i < argc; i++) { - XNextEvent(dpy, &ev); + info = xi2_find_device_info(dpy, argv[i]); + if (!info) + { + fprintf(stderr, "unable to find device %s\n", argv[i]); + continue; + } - dpev = (XDevicePropertyNotifyEvent*)&ev; - if (dpev->type != type_prop) + props = XIListProperties(dpy, info->deviceid, &nprops); + if (!nprops) + { + printf("Device '%s' does not report any properties.\n", info->name); continue; + } - name = XGetAtomName(dpy, dpev->atom); - printf("Property '%s' changed.\n", name); - print_property(dpy, dev, dpev->atom); - } + printf("Device '%s':\n", info->name); + while(nprops--) + { + print_property_xi2(dpy, info->deviceid, props[nprops]); + } - XCloseDevice(dpy, dev); + XFree(props); + } + return EXIT_SUCCESS; } -int delete_prop(Display *dpy, int argc, char** argv, char* n, char *desc) +static int +delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc) { - XDevice *dev; - XDeviceInfo *info; + XIDeviceInfo *info; char *name; - int i; - Bool is_atom = True; Atom prop; - info = find_device_info(dpy, argv[0], False); + info = xi2_find_device_info(dpy, argv[0]); 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", info->name); - return EXIT_FAILURE; - } - 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); + XIDeleteProperty(dpy, info->deviceid, prop); - XCloseDevice(dpy, dev); return EXIT_SUCCESS; } -int -set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) +static int +do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) { - XDeviceInfo *info; - XDevice *dev; - Atom prop; - char *name; - int i, j; - Bool is_atom = True; - Atom *data; - int nelements = 0; + XIDeviceInfo *info; + Atom prop; + Atom old_type; + char *name; + int i; + Atom float_atom; + int old_format, nelements = 0; + unsigned long act_nitems, bytes_after; + char *endptr; + union { + unsigned char *c; + int16_t *s; + int32_t *l; + } data; if (argc < 3) { @@ -440,62 +583,219 @@ set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) return EXIT_FAILURE; } - info = find_device_info(dpy, argv[0], False); + info = xi2_find_device_info(dpy, argv[0]); 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]); + name = argv[1]; + + prop = parse_atom(dpy, name); + + if (prop == None) { + fprintf(stderr, "invalid property %s\n", name); return EXIT_FAILURE; } - name = argv[1]; + float_atom = XInternAtom(dpy, "FLOAT", False); - for(i = 0; i < strlen(name); i++) { - if (!isdigit(name[i])) { - is_atom = False; - break; - } + nelements = argc - 2; + if (type == None || format == 0) { + if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False, + AnyPropertyType, &old_type, &old_format, &act_nitems, + &bytes_after, &data.c) != Success) { + fprintf(stderr, "failed to get property type and format for %s\n", + name); + return EXIT_FAILURE; + } else { + if (type == None) + type = old_type; + if (format == 0) + format = old_format; + } + + XFree(data.c); } - if (!is_atom) - prop = XInternAtom(dpy, name, False); - else - prop = atoi(name); + if (type == None) { + fprintf(stderr, "property %s doesn't exist, you need to specify " + "its type and format\n", name); + return EXIT_FAILURE; + } + + data.c = calloc(nelements, sizeof(int32_t)); - nelements = argc - 2; - data = calloc(nelements, sizeof(Atom)); for (i = 0; i < nelements; i++) { - is_atom = True; - name = argv[2 + i]; - for(j = 0; j < strlen(name); j++) { - if (!isdigit(name[j])) { - is_atom = False; - break; + 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.l[i] = parse_atom(dpy, argv[2 + i]); + } else { + fprintf(stderr, "unexpected type for property %s\n", name); + return EXIT_FAILURE; } + } - if (!is_atom) - data[i] = XInternAtom(dpy, name, False); - else - { - data[i] = atoi(name); - XFree(XGetAtomName(dpy, data[i])); - } + XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace, + data.c, nelements); + free(data.c); + return EXIT_SUCCESS; +} +#endif + +int list_props(Display *display, int argc, char *argv[], char *name, + char *desc) +{ +#ifdef HAVE_XI2 + if (xinput_version(display) == XI_2_Major) + return list_props_xi2(display, argc, argv, name, desc); +#endif + return list_props_xi1(display, argc, argv, name, desc); + +} + +int delete_prop(Display *display, int argc, char *argv[], char *name, + char *desc) +{ +#ifdef HAVE_XI2 + if (xinput_version(display) == XI_2_Major) + return delete_prop_xi2(display, argc, argv, name, desc); +#endif + return delete_prop_xi1(display, argc, argv, name, desc); + +} + +static int +do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc) +{ +#ifdef HAVE_XI2 + if (xinput_version(display) == XI_2_Major) + return do_set_prop_xi2(display, type, format, argc, argv, name, desc); +#endif + return do_set_prop_xi1(display, type, format, argc, argv, name, desc); +} + +int +set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) +{ + return do_set_prop(dpy, XA_ATOM, 32, argc, argv, n, desc); +} + +int +set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) +{ + int i; + int format; + + if (argc < 3) + { + fprintf(stderr, "Usage: xinput %s %s\n", n, desc); + return EXIT_FAILURE; } - XChangeDeviceProperty(dpy, dev, prop, XA_ATOM, 32, PropModeReplace, - (unsigned char*)data, nelements); + format = atoi(argv[2]); + if (format != 8 && format != 16 && format != 32) + { + fprintf(stderr, "Invalid format %d\n", format); + return EXIT_FAILURE; + } - free(data); - XCloseDevice(dpy, dev); - return EXIT_SUCCESS; + for (i = 3; i < argc; i++) + argv[i - 1] = argv[i]; + + return do_set_prop(dpy, XA_INTEGER, format, argc - 1, argv, n, desc); } +int +set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) +{ + Atom float_atom = XInternAtom(dpy, "FLOAT", False); + + if (sizeof(float) != 4) + { + fprintf(stderr, "sane FP required\n"); + return EXIT_FAILURE; + } + + return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc); +} +int set_prop(Display *display, int argc, char *argv[], char *name, + char *desc) +{ + Atom type = None; + int format = 0; + int i = 0, j; + + while (i < argc) { + char *option = strchr(argv[i], '='); + /* skip non-option arguments */ + if (strncmp(argv[i], "--", 2) || !option) { + i++; + continue; + } + + if (!strncmp(argv[i], "--type=", strlen("--type="))) { + if (!strcmp(option + 1, "int")) { + type = XA_INTEGER; + } else if (!strcmp(option + 1, "float")) { + type = XInternAtom(display, "FLOAT", False); + format = 32; + } else if (!strcmp(option + 1, "atom")) { + type = XA_ATOM; + format = 32; + } else { + fprintf(stderr, "unknown property type %s\n", option + 1); + return EXIT_FAILURE; + } + } else if (!strncmp(argv[i], "--format=", strlen("--format="))) { + format = atoi(option + 1); + if (format != 8 && format != 16 && format != 32) { + fprintf(stderr, "invalid property format %s\n", option + 1); + return EXIT_FAILURE; + } + } else { + fprintf(stderr, "invalid option %s\n", argv[i]); + return EXIT_FAILURE; + } + + for (j = i; j + 1 < argc; j++) + argv[j] = argv[j + 1]; + argc--; + } + + return do_set_prop(display, type, format, argc, argv, name, desc); +} diff --git a/app/xinput/src/setcp.c b/app/xinput/src/setcp.c index e44bb00fa..7a2864479 100644 --- a/app/xinput/src/setcp.c +++ b/app/xinput/src/setcp.c @@ -32,9 +32,8 @@ int set_clientpointer(Display* dpy, int argc, char** argv, char* name, char *desc) { - XDeviceInfo* info; + XIDeviceInfo *info; XID window; - XDevice* dev = NULL; char* id; char* dummy; @@ -50,19 +49,13 @@ set_clientpointer(Display* dpy, int argc, char** argv, char* name, char *desc) window = strtol(argv[0], &dummy, (*id == 'x') ? 16 : 10); - info = find_device_info(dpy, argv[1], False); + info = xi2_find_device_info(dpy, argv[1]); if (!info) { fprintf(stderr, "unable to find device %s\n", argv[1]); return EXIT_FAILURE; } - dev = XOpenDevice(dpy, info->id); - - if (!dev) - { - fprintf(stderr, "Cannot open device %s.\n", argv[1]); - } else - XSetClientPointer(dpy, window, dev); + XISetClientPointer(dpy, window, info->deviceid); return 0; } diff --git a/app/xinput/src/test_xi2.c b/app/xinput/src/test_xi2.c new file mode 100644 index 000000000..53d984f04 --- /dev/null +++ b/app/xinput/src/test_xi2.c @@ -0,0 +1,381 @@ +/* + * 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. + * + */ + + +#include "xinput.h" +#include <string.h> + +extern void print_classes_xi2(Display*, XIAnyClassInfo **classes, + int num_classes); + +static Window create_win(Display *dpy) +{ + Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200, + 200, 0, 0, WhitePixel(dpy, 0)); + Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0, + BlackPixel(dpy, 0)); + + XMapWindow(dpy, subwindow); + XSelectInput(dpy, win, ExposureMask); + return win; +} + +static void print_deviceevent(XIDeviceEvent* event) +{ + double *val; + int i; + + printf(" device: %d (%d)\n", event->deviceid, event->sourceid); + printf(" detail: %d\n", event->detail); + printf(" flags: %s\n", (event->flags & XIKeyRepeat) ? "repeat" : ""); + + printf(" root: %.2f/%.2f\n", event->root_x, event->root_y); + printf(" event: %.2f/%.2f\n", event->event_x, event->event_y); + + printf(" buttons:"); + for (i = 0; i < event->buttons.mask_len * 8; i++) + if (XIMaskIsSet(event->buttons.mask, i)) + printf(" %d", i); + printf("\n"); + + printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n", + event->mods.locked, event->mods.latched, + event->mods.base, event->mods.effective); + printf(" group: locked %#x latched %#x base %#x effective: %#x\n", + event->group.locked, event->group.latched, + event->group.base, event->group.effective); + printf(" valuators:"); + + val = event->valuators.values; + for (i = 0; i < event->valuators.mask_len * 8; i++) + if (XIMaskIsSet(event->valuators.mask, i)) + printf(" %.2f", *val++); + printf("\n"); + + printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n", + event->root, event->event, event->child); +} + +static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event) +{ + printf(" device: %d (%d)\n", event->deviceid, event->sourceid); + printf(" reason: %s\n", (event->reason == XISlaveSwitch) ? "SlaveSwitch" : + "DeviceChanged"); + print_classes_xi2(dpy, event->classes, event->num_classes); +} + +static void print_hierarchychangedevent(XIHierarchyEvent *event) +{ + int i; + printf(" Changes happened: %s %s %s %s %s %s %s %s\n", + (event->flags & XIMasterAdded) ? "[new master]" : "", + (event->flags & XIMasterRemoved) ? "[master removed]" : "", + (event->flags & XISlaveAdded) ? "[new slave]" : "", + (event->flags & XISlaveRemoved) ? "[slave removed]" : "", + (event->flags & XISlaveAttached) ? "[slave attached]" : "", + (event->flags & XISlaveDetached) ? "[slave detached]" : "", + (event->flags & XIDeviceEnabled) ? "[device enabled]" : "", + (event->flags & XIDeviceDisabled) ? "[device disabled]" : ""); + + for (i = 0; i < event->num_info; i++) + { + char *use; + switch(event->info[i].use) + { + case XIMasterPointer: use = "master pointer"; break; + case XIMasterKeyboard: use = "master keyboard"; break; + case XISlavePointer: use = "slave pointer"; break; + case XISlaveKeyboard: use = "slave keyboard"; break; + case XIFloatingSlave: use = "floating slave"; break; + break; + } + + printf(" device %d [%s (%d)] is %s\n", + event->info[i].deviceid, + use, + event->info[i].attachment, + (event->info[i].enabled) ? "enabled" : "disabled"); + if (event->info[i].flags) + { + printf(" changes: %s %s %s %s %s %s %s %s\n", + (event->info[i].flags & XIMasterAdded) ? "[new master]" : "", + (event->info[i].flags & XIMasterRemoved) ? "[master removed]" : "", + (event->info[i].flags & XISlaveAdded) ? "[new slave]" : "", + (event->info[i].flags & XISlaveRemoved) ? "[slave removed]" : "", + (event->info[i].flags & XISlaveAttached) ? "[slave attached]" : "", + (event->info[i].flags & XISlaveDetached) ? "[slave detached]" : "", + (event->info[i].flags & XIDeviceEnabled) ? "[device enabled]" : "", + (event->info[i].flags & XIDeviceDisabled) ? "[device disabled]" : ""); + } + } +} + +static void print_rawevent(XIRawEvent *event) +{ + int i; + double *val, *raw_val; + + printf(" device: %d\n", event->deviceid); + printf(" detail: %d\n", event->detail); + printf(" valuators:\n"); + + val = event->valuators.values; + raw_val = event->raw_values; + for (i = 0; i < event->valuators.mask_len * 8; i++) + if (XIMaskIsSet(event->valuators.mask, i)) + printf(" %2d: %.2f (%.2f)\n", i, *val++, *raw_val++); + printf("\n"); +} + +static void print_enterleave(XILeaveEvent* event) +{ + char *mode, *detail; + int i; + + printf(" device: %d\n", event->deviceid); + printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n", + event->root, event->event, event->child); + switch(event->mode) + { + case XINotifyNormal: mode = "NotifyNormal"; break; + case XINotifyGrab: mode = "NotifyGrab"; break; + case XINotifyUngrab: mode = "NotifyUngrab"; break; + case XINotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break; + case XINotifyPassiveGrab: mode = "NotifyPassiveGrab"; break; + case XINotifyPassiveUngrab:mode = "NotifyPassiveUngrab"; break; + } + switch (event->detail) + { + case XINotifyAncestor: detail = "NotifyAncestor"; break; + case XINotifyVirtual: detail = "NotifyVirtual"; break; + case XINotifyInferior: detail = "NotifyInferior"; break; + case XINotifyNonlinear: detail = "NotifyNonlinear"; break; + case XINotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break; + case XINotifyPointer: detail = "NotifyPointer"; break; + case XINotifyPointerRoot: detail = "NotifyPointerRoot"; break; + case XINotifyDetailNone: detail = "NotifyDetailNone"; break; + } + printf(" mode: %s (detail %s)\n", mode, detail); + printf(" flags: %s %s\n", event->focus ? "[focus]" : "", + event->same_screen ? "[same screen]" : ""); + printf(" buttons:"); + for (i = 0; i < event->buttons.mask_len * 8; i++) + if (XIMaskIsSet(event->buttons.mask, i)) + printf(" %d", i); + printf("\n"); + + printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n", + event->mods.locked, event->mods.latched, + event->mods.base, event->mods.effective); + printf(" group: locked %#x latched %#x base %#x effective: %#x\n", + event->group.locked, event->group.latched, + event->group.base, event->group.effective); + + printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y); + printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y); + +} + +static void print_propertyevent(Display *display, XIPropertyEvent* event) +{ + char *changed; + char *name; + + if (event->what == XIPropertyDeleted) + changed = "deleted"; + else if (event->what == XIPropertyCreated) + changed = "created"; + else + changed = "modified"; + name = XGetAtomName(display, event->property); + printf(" property: %ld '%s'\n", event->property, name); + printf(" changed: %s\n", changed); + + XFree(name); +} +void +test_sync_grab(Display *display, Window win) +{ + int loop = 3; + int rc; + XIEventMask mask; + + /* Select for motion events */ + mask.deviceid = XIAllDevices; + mask.mask_len = 2; + mask.mask = calloc(2, sizeof(char)); + XISetMask(mask.mask, XI_ButtonPress); + + if ((rc = XIGrabDevice(display, 2, win, CurrentTime, None, GrabModeSync, + GrabModeAsync, False, &mask)) != GrabSuccess) + { + fprintf(stderr, "Grab failed with %d\n", rc); + return; + } + free(mask.mask); + + XSync(display, True); + XIAllowEvents(display, 2, SyncPointer, CurrentTime); + XFlush(display); + + printf("Holding sync grab for %d button presses.\n", loop); + + while(loop--) + { + XIEvent ev; + + XNextEvent(display, (XEvent*)&ev); + if (ev.type == GenericEvent && ev.extension == xi_opcode ) + { + XIDeviceEvent *event = (XIDeviceEvent*)&ev; + print_deviceevent(event); + XIAllowEvents(display, 2, SyncPointer, CurrentTime); + } + } + + XIUngrabDevice(display, 2, CurrentTime); + printf("Done\n"); +} + +int +test_xi2(Display *display, + int argc, + char *argv[], + char *name, + char *desc) +{ + XIEventMask mask; + Window win; + + list(display, argc, argv, name, desc); + win = create_win(display); + + /* Select for motion events */ + mask.deviceid = XIAllDevices; + mask.mask_len = XIMaskLen(XI_RawMotion); + mask.mask = calloc(mask.mask_len, sizeof(char)); + XISetMask(mask.mask, XI_ButtonPress); + XISetMask(mask.mask, XI_ButtonRelease); + XISetMask(mask.mask, XI_KeyPress); + XISetMask(mask.mask, XI_KeyRelease); + XISetMask(mask.mask, XI_Motion); + XISetMask(mask.mask, XI_DeviceChanged); + XISetMask(mask.mask, XI_Enter); + XISetMask(mask.mask, XI_Leave); + XISetMask(mask.mask, XI_FocusIn); + XISetMask(mask.mask, XI_FocusOut); + XISetMask(mask.mask, XI_HierarchyChanged); + XISetMask(mask.mask, XI_PropertyEvent); + XISelectEvents(display, win, &mask, 1); + XMapWindow(display, win); + XSync(display, False); + + { + XIGrabModifiers modifiers[] = {{0, 0}, {0, 0x10}, {0, 0x1}, {0, 0x11}}; + int nmods = sizeof(modifiers)/sizeof(modifiers[0]); + + mask.deviceid = 2; + memset(mask.mask, 0, 2); + XISetMask(mask.mask, XI_KeyPress); + XISetMask(mask.mask, XI_KeyRelease); + XISetMask(mask.mask, XI_ButtonPress); + XISetMask(mask.mask, XI_ButtonRelease); + XISetMask(mask.mask, XI_Motion); + XIGrabButton(display, 2, 1, win, None, GrabModeAsync, GrabModeAsync, + False, &mask, nmods, modifiers); + XIGrabKeycode(display, 3, 24 /* q */, win, GrabModeAsync, GrabModeAsync, + False, &mask, nmods, modifiers); + XIUngrabButton(display, 3, 1, win, nmods - 2, &modifiers[2]); + XIUngrabKeycode(display, 3, 24 /* q */, win, nmods - 2, &modifiers[2]); + } + + mask.deviceid = XIAllMasterDevices; + memset(mask.mask, 0, 2); + XISetMask(mask.mask, XI_RawKeyPress); + XISetMask(mask.mask, XI_RawKeyRelease); + XISetMask(mask.mask, XI_RawButtonPress); + XISetMask(mask.mask, XI_RawButtonRelease); + XISetMask(mask.mask, XI_RawMotion); + XISelectEvents(display, DefaultRootWindow(display), &mask, 1); + + free(mask.mask); + + { + XEvent event; + XMaskEvent(display, ExposureMask, &event); + XSelectInput(display, win, 0); + } + + /* + test_sync_grab(display, win); + */ + + while(1) + { + XEvent ev; + XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie; + XNextEvent(display, (XEvent*)&ev); + + if (XGetEventData(display, cookie) && + cookie->type == GenericEvent && + cookie->extension == xi_opcode) + { + printf("EVENT type %d\n", cookie->evtype); + switch (cookie->evtype) + { + case XI_DeviceChanged: + print_devicechangedevent(display, cookie->data); + break; + case XI_HierarchyChanged: + print_hierarchychangedevent(cookie->data); + break; + case XI_RawKeyPress: + case XI_RawKeyRelease: + case XI_RawButtonPress: + case XI_RawButtonRelease: + case XI_RawMotion: + print_rawevent(cookie->data); + break; + case XI_Enter: + case XI_Leave: + case XI_FocusIn: + case XI_FocusOut: + print_enterleave(cookie->data); + break; + case XI_PropertyEvent: + print_propertyevent(display, cookie->data); + break; + default: + print_deviceevent(cookie->data); + break; + } + } + + XFreeEventData(display, cookie); + } + + XDestroyWindow(display, win); + + return EXIT_SUCCESS; +} diff --git a/app/xinput/src/version.c b/app/xinput/src/version.c deleted file mode 100644 index 93a50d8be..000000000 --- a/app/xinput/src/version.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 1996-1997 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the authors not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. The authors make no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "xinput.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -static const char version_id[] = VERSION; - -int -version(Display *display, - int argc, - char *argv[], - char *name, - char *desc) -{ - printf("%s %s\n", name, version_id); - return EXIT_SUCCESS; -} - -/* end of version.c */ diff --git a/app/xinput/src/xinput.c b/app/xinput/src/xinput.c index 82dc54a85..149662d20 100644 --- a/app/xinput/src/xinput.c +++ b/app/xinput/src/xinput.c @@ -25,12 +25,10 @@ #include <ctype.h> #include <string.h> -typedef int (*prog)( -#if NeedFunctionPrototypes - Display* display, int argc, char *argv[], - char *prog_name, char *prog_desc -#endif -); +int xi_opcode; + +typedef int (*prog)(Display* display, int argc, char *argv[], + char *prog_name, char *prog_desc); typedef struct { @@ -70,7 +68,7 @@ static entry drivers[] = set_mode }, {"list", - "[--loop || --short || <device name>...]", + "[--short || --long] [<device name>...]", list }, {"query-state", @@ -81,17 +79,13 @@ static entry drivers[] = "[-proximity] <device name>", test }, - {"version", - "", - version - }, #if HAVE_XI2 { "create-master", - "<id> [sendCore (dflt:1)] [enable (dflt:1)]", + "<id> [<sendCore (dflt:1)>] [<enable (dflt:1)>]", create_master }, { "remove-master", - "<id> [returnMode (dflt:Floating)] [returnPointer] [returnKeyboard]", + "<id> [Floating|AttachToMaster (dflt:Floating)] [<returnPointer>] [<returnKeyboard>]", remove_master }, { "reattach", @@ -106,6 +100,10 @@ static entry drivers[] = "<window> <device>", set_clientpointer }, + { "test-xi2", + "<device>", + test_xi2, + }, #endif { "list-props", "<device> [<device> ...]", @@ -131,29 +129,62 @@ static entry drivers[] = "<device> <property>", delete_prop }, + { "set-prop", + "<device> [--type=atom|float|int] [--format=8|16|32] <property> <val> [<val> ...]", + set_prop + }, {NULL, NULL, NULL } }; -static Bool -is_xinput_present(Display *display) +static const char version_id[] = VERSION; + +int +print_version() { XExtensionVersion *version; - Bool present; + Display *display; + + printf("xinput version %s\n", version_id); + + display = XOpenDisplay(NULL); + + printf("XI version on server: "); + + if (display == NULL) + printf("Failed to open display.\n"); + else { + version = XGetExtensionVersion(display, INAME); + if (!version || (version == (XExtensionVersion*) NoSuchExtension)) + printf(" Extension not supported.\n"); + else { + printf("%d.%d\n", version->major_version, + version->minor_version); + XFree(version); + return 0; + } + } + + return 1; +} + +int +xinput_version(Display *display) +{ + XExtensionVersion *version; + 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* @@ -200,6 +231,41 @@ find_device_info(Display *display, return found; } +#ifdef HAVE_XI2 +XIDeviceInfo* +xi2_find_device_info(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); + } + + info = XIQueryDevice(display, XIAllDevices, &ndevices); + for(i = 0; i < ndevices; i++) + { + if ((is_id && info[i].deviceid == id) || + (!is_id && strcmp(info[i].name, name) == 0)) + { + return &info[i]; + } + } + + XIFreeDeviceInfo(info); + return NULL; +} +#endif + static void usage(void) { @@ -220,12 +286,20 @@ main(int argc, char * argv[]) Display *display; entry *driver = drivers; char *func; + int event, error; if (argc < 2) { usage(); return EXIT_FAILURE; } + func = argv[1]; + while((*func) == '-') func++; + + if (strcmp("version", func) == 0) { + return print_version(argv[0]); + } + display = XOpenDisplay(NULL); if (display == NULL) { @@ -233,10 +307,12 @@ main(int argc, char * argv[]) return EXIT_FAILURE; } - func = argv[1]; - while((*func) == '-') func++; + if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) { + printf("X Input extension not available.\n"); + return EXIT_FAILURE; + } - if (!is_xinput_present(display)) { + if (!xinput_version(display)) { fprintf(stderr, "%s extension not available\n", INAME); return EXIT_FAILURE; } diff --git a/app/xinput/src/xinput.h b/app/xinput/src/xinput.h index 3c364973f..d44ce0960 100644 --- a/app/xinput/src/xinput.h +++ b/app/xinput/src/xinput.h @@ -27,6 +27,9 @@ #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> @@ -38,255 +41,41 @@ #define EXIT_FAILURE 0 #endif -XDeviceInfo* -find_device_info( -#if NeedFunctionPrototypes - Display *display, - char *name, - Bool only_extended -#endif - ); -int -get_feedbacks( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_ptr_feedback( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -get_button_map( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_button_map( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_pointer( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_mode( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -list( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -test( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -version( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_integer_feedback( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -query_state( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -create_master( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -remove_master( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -change_attachment( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -float_device( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_clientpointer( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -list_props( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - - -int -set_int_prop( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_float_prop( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -set_atom_prop( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -watch_props( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); - -int -delete_prop( -#if NeedFunctionPrototypes - Display* display, - int argc, - char *argv[], - char *prog_name, - char *prog_desc -#endif -); +extern int xi_opcode; /* xinput extension op code */ +XDeviceInfo* find_device_info( Display *display, char *name, Bool only_extended); +#if HAVE_XI2 +XIDeviceInfo* xi2_find_device_info(Display *display, char *name); +int xinput_version(Display* display); +#endif + +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); /* end of xinput.h */ |