880 lines
24 KiB
C
880 lines
24 KiB
C
/*
|
|
* Copyright © 2007 Peter Hutterer
|
|
* 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 <ctype.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/extensions/XIproto.h>
|
|
|
|
#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)
|
|
{
|
|
Atom act_type;
|
|
char *name;
|
|
int act_format;
|
|
unsigned long nitems, bytes_after;
|
|
unsigned char *data, *ptr;
|
|
int j, done = False, size = 0;
|
|
|
|
name = XGetAtomName(dpy, property);
|
|
printf("\t%s (%ld):\t", name, property);
|
|
XFree(name);
|
|
|
|
if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False,
|
|
AnyPropertyType, &act_type, &act_format,
|
|
&nitems, &bytes_after, &data) == Success)
|
|
{
|
|
Atom float_atom = XInternAtom(dpy, "FLOAT", True);
|
|
|
|
ptr = data;
|
|
|
|
if (nitems == 0)
|
|
printf("<no items>");
|
|
|
|
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)
|
|
{
|
|
case XA_INTEGER:
|
|
switch(act_format)
|
|
{
|
|
case 8:
|
|
printf("%d", *((char*)ptr));
|
|
break;
|
|
case 16:
|
|
printf("%d", *((short*)ptr));
|
|
break;
|
|
case 32:
|
|
printf("%ld", *((long*)ptr));
|
|
break;
|
|
}
|
|
break;
|
|
case XA_CARDINAL:
|
|
switch(act_format)
|
|
{
|
|
case 8:
|
|
printf("%u", *((unsigned char*)ptr));
|
|
break;
|
|
case 16:
|
|
printf("%u", *((unsigned short*)ptr));
|
|
break;
|
|
case 32:
|
|
printf("%lu", *((unsigned long*)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;
|
|
name = (a) ? XGetAtomName(dpy, a) : NULL;
|
|
printf("\"%s\" (%d)", name ? name : "None", (int)a);
|
|
XFree(name);
|
|
break;
|
|
}
|
|
default:
|
|
if (float_atom != None && act_type == float_atom)
|
|
{
|
|
printf("%f", *((float*)ptr));
|
|
break;
|
|
}
|
|
|
|
name = XGetAtomName(dpy, act_type);
|
|
printf("\t... of unknown type '%s'\n", name);
|
|
XFree(name);
|
|
done = True;
|
|
break;
|
|
}
|
|
|
|
ptr += size;
|
|
|
|
if (done == True)
|
|
break;
|
|
if (j < nitems - 1)
|
|
printf(", ");
|
|
}
|
|
printf("\n");
|
|
XFree(data);
|
|
} else
|
|
printf("\tFetch failure\n");
|
|
|
|
}
|
|
|
|
static int
|
|
list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
|
|
{
|
|
XDeviceInfo *info;
|
|
XDevice *dev;
|
|
int i;
|
|
int nprops;
|
|
Atom *props;
|
|
int rc = EXIT_SUCCESS;
|
|
|
|
if (argc == 0)
|
|
{
|
|
fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
info = find_device_info(dpy, argv[i], False);
|
|
if (!info)
|
|
{
|
|
fprintf(stderr, "unable to find device '%s'\n", argv[i]);
|
|
rc = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
|
|
dev = XOpenDevice(dpy, info->id);
|
|
if (!dev)
|
|
{
|
|
fprintf(stderr, "unable to open device '%s'\n", info->name);
|
|
rc = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
|
|
props = XListDeviceProperties(dpy, dev, &nprops);
|
|
if (!nprops)
|
|
{
|
|
printf("Device '%s' does not report any properties.\n", info->name);
|
|
continue;
|
|
}
|
|
|
|
printf("Device '%s':\n", info->name);
|
|
while(nprops--)
|
|
{
|
|
print_property(dpy, dev, props[nprops]);
|
|
}
|
|
|
|
XFree(props);
|
|
XCloseDevice(dpy, dev);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc)
|
|
{
|
|
XDevice *dev;
|
|
XDeviceInfo *info;
|
|
XEvent ev;
|
|
XDevicePropertyNotifyEvent *dpev;
|
|
char *name;
|
|
int type_prop;
|
|
XEventClass cls_prop;
|
|
|
|
if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS)
|
|
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", info->name);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
DevicePropertyNotify(dev, type_prop, cls_prop);
|
|
XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1);
|
|
|
|
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);
|
|
XFree(name);
|
|
print_property(dpy, dev, dpev->atom);
|
|
}
|
|
|
|
XCloseDevice(dpy, dev);
|
|
}
|
|
|
|
static int
|
|
delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc)
|
|
{
|
|
XDevice *dev;
|
|
XDeviceInfo *info;
|
|
char *name;
|
|
Atom prop;
|
|
|
|
if (argc < 2)
|
|
{
|
|
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", info->name);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
name = argv[1];
|
|
|
|
prop = parse_atom(dpy, name);
|
|
|
|
XDeleteDeviceProperty(dpy, dev, prop);
|
|
|
|
XCloseDevice(dpy, dev);
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
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;
|
|
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 < 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 (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;
|
|
}
|
|
|
|
XFree(data.c);
|
|
}
|
|
|
|
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(long));
|
|
|
|
for (i = 0; i < nelements; i++)
|
|
{
|
|
if (type == XA_INTEGER || type == XA_CARDINAL) {
|
|
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;
|
|
}
|
|
|
|
#if HAVE_XI2
|
|
static void
|
|
print_property_xi2(Display *dpy, int deviceid, Atom property)
|
|
{
|
|
Atom act_type;
|
|
char *name;
|
|
int act_format;
|
|
unsigned long nitems, bytes_after;
|
|
unsigned char *data, *ptr;
|
|
int j, done = False;
|
|
|
|
name = XGetAtomName(dpy, property);
|
|
printf("\t%s (%ld):\t", name, property);
|
|
XFree(name);
|
|
|
|
if (XIGetProperty(dpy, deviceid, property, 0, 1000, False,
|
|
AnyPropertyType, &act_type, &act_format,
|
|
&nitems, &bytes_after, &data) == Success)
|
|
{
|
|
Atom float_atom = XInternAtom(dpy, "FLOAT", True);
|
|
|
|
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_CARDINAL:
|
|
switch(act_format)
|
|
{
|
|
case 8:
|
|
printf("%u", *((uint8_t*)ptr));
|
|
break;
|
|
case 16:
|
|
printf("%u", *((uint16_t*)ptr));
|
|
break;
|
|
case 32:
|
|
printf("%u", *((uint32_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 = *(uint32_t*)ptr;
|
|
name = (a) ? XGetAtomName(dpy, a) : NULL;
|
|
printf("\"%s\" (%ld)", name ? name : "None", a);
|
|
XFree(name);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
if (float_atom != None && act_type == float_atom)
|
|
{
|
|
printf("%f", *((float*)ptr));
|
|
break;
|
|
}
|
|
|
|
name = XGetAtomName(dpy, act_type);
|
|
printf("\t... of unknown type %s\n", name);
|
|
XFree(name);
|
|
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;
|
|
int rc = EXIT_SUCCESS;
|
|
|
|
if (argc == 0)
|
|
{
|
|
fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
info = xi2_find_device_info(dpy, argv[i]);
|
|
if (!info)
|
|
{
|
|
fprintf(stderr, "unable to find device %s\n", argv[i]);
|
|
rc = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
|
|
props = XIListProperties(dpy, info->deviceid, &nprops);
|
|
if (!nprops)
|
|
{
|
|
printf("Device '%s' does not report any properties.\n", info->name);
|
|
continue;
|
|
}
|
|
|
|
printf("Device '%s':\n", info->name);
|
|
while(nprops--)
|
|
{
|
|
print_property_xi2(dpy, info->deviceid, props[nprops]);
|
|
}
|
|
|
|
XFree(props);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static int
|
|
delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc)
|
|
{
|
|
XIDeviceInfo *info;
|
|
char *name;
|
|
Atom prop;
|
|
|
|
if (argc < 2)
|
|
{
|
|
fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
info = xi2_find_device_info(dpy, argv[0]);
|
|
if (!info)
|
|
{
|
|
fprintf(stderr, "unable to find device %s\n", argv[0]);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
name = argv[1];
|
|
|
|
prop = parse_atom(dpy, name);
|
|
|
|
XIDeleteProperty(dpy, info->deviceid, prop);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
|
|
{
|
|
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 = { NULL };
|
|
int rc = EXIT_FAILURE;
|
|
|
|
if (argc < 3)
|
|
{
|
|
fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
|
|
goto out;
|
|
}
|
|
|
|
info = xi2_find_device_info(dpy, argv[0]);
|
|
if (!info)
|
|
{
|
|
fprintf(stderr, "unable to find device %s\n", argv[0]);
|
|
goto out;
|
|
}
|
|
|
|
name = argv[1];
|
|
|
|
prop = parse_atom(dpy, name);
|
|
|
|
if (prop == None) {
|
|
fprintf(stderr, "invalid property '%s'\n", name);
|
|
goto out;
|
|
}
|
|
|
|
float_atom = XInternAtom(dpy, "FLOAT", False);
|
|
|
|
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);
|
|
goto out;
|
|
} else {
|
|
if (type == None)
|
|
type = old_type;
|
|
if (format == 0)
|
|
format = old_format;
|
|
}
|
|
|
|
XFree(data.c);
|
|
}
|
|
|
|
if (type == None) {
|
|
fprintf(stderr, "property '%s' doesn't exist, you need to specify "
|
|
"its type and format\n", name);
|
|
goto out;
|
|
}
|
|
|
|
data.c = calloc(nelements, sizeof(int32_t));
|
|
|
|
for (i = 0; i < nelements; i++)
|
|
{
|
|
if (type == XA_INTEGER || type == XA_CARDINAL) {
|
|
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);
|
|
goto out;
|
|
}
|
|
} else if (type == float_atom) {
|
|
if (format != 32) {
|
|
fprintf(stderr, "unexpected format %d for property '%s'\n",
|
|
format, name);
|
|
goto out;
|
|
}
|
|
*(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]);
|
|
goto out;
|
|
}
|
|
} else if (type == XA_ATOM) {
|
|
if (format != 32) {
|
|
fprintf(stderr, "unexpected format %d for property '%s'\n",
|
|
format, name);
|
|
goto out;
|
|
}
|
|
data.l[i] = parse_atom(dpy, argv[2 + i]);
|
|
} else {
|
|
fprintf(stderr, "unexpected type for property '%s'\n", name);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace,
|
|
data.c, nelements);
|
|
rc = EXIT_SUCCESS;
|
|
out:
|
|
free(data.c);
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
int list_props(Display *display, int argc, char *argv[], char *name,
|
|
char *desc)
|
|
{
|
|
#if 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)
|
|
{
|
|
#if 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)
|
|
{
|
|
#if 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;
|
|
}
|
|
|
|
format = atoi(argv[2]);
|
|
if (format != 8 && format != 16 && format != 32)
|
|
{
|
|
fprintf(stderr, "Invalid format %d\n", format);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
int disable(Display *display, int argc, char *argv[], char *name, char *desc)
|
|
{
|
|
char *new_argv[3] = { NULL, "Device Enabled", "0" };
|
|
|
|
if (argc != 1) {
|
|
fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
new_argv[0] = argv[0];
|
|
|
|
return set_prop(display, 3, new_argv, name, desc);
|
|
}
|
|
|
|
int enable(Display *display, int argc, char *argv[], char *name, char *desc)
|
|
{
|
|
char *new_argv[3] = { NULL, "Device Enabled", "1" };
|
|
|
|
if (argc != 1) {
|
|
fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
new_argv[0] = argv[0];
|
|
|
|
return set_prop(display, 3, new_argv, name, desc);
|
|
}
|