]> diplodocus.org Git - xorg-xinput/blobdiff - src/property.c
gitlab CI: stop requiring Signed-off-by in commits
[xorg-xinput] / src / property.c
index e8ce611e8c24e31513164c7c9c77436cd97add79..e3baef36612981678223cdfdf22a2a06c7b60e9b 100644 (file)
@@ -1,28 +1,25 @@
 /*
- * Copyright 2007 Peter Hutterer
+ * Copyright © 2007 Peter Hutterer
+ * Copyright © 2009 Red Hat, Inc.
  *
- * 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.
+ * 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 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 AUTHOR 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.
- *
- * Except as contained in this notice, the name of the author shall
- * not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization
- * from the author.
+ * 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>
@@ -59,10 +56,11 @@ print_property(Display *dpy, XDevice* dev, Atom property)
     int                 act_format;
     unsigned long       nitems, bytes_after;
     unsigned char       *data, *ptr;
-    int                 j, done = False, size;
+    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,
@@ -100,6 +98,20 @@ print_property(Display *dpy, XDevice* dev, Atom property)
                             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)
                     {
@@ -116,9 +128,9 @@ print_property(Display *dpy, XDevice* dev, Atom property)
                 case XA_ATOM:
                     {
                         Atom a = *(Atom*)ptr;
-                        printf("\"%s\" (%d)",
-                                (a) ? XGetAtomName(dpy, a) : "None",
-                                (int)a);
+                        name = (a) ? XGetAtomName(dpy, a) : NULL;
+                        printf("\"%s\" (%d)", name ? name : "None", (int)a);
+                        XFree(name);
                         break;
                     }
                 default:
@@ -128,8 +140,9 @@ print_property(Display *dpy, XDevice* dev, Atom property)
                         break;
                     }
 
-                    printf("\t... of unknown type %s\n",
-                            XGetAtomName(dpy, act_type));
+                    name = XGetAtomName(dpy, act_type);
+                    printf("\t... of unknown type '%s'\n", name);
+                    XFree(name);
                     done = True;
                     break;
             }
@@ -156,6 +169,7 @@ list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
     int          i;
     int         nprops;
     Atom        *props;
+    int         rc = EXIT_SUCCESS;
 
     if (argc == 0)
     {
@@ -168,7 +182,8 @@ list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
         info = find_device_info(dpy, argv[i], False);
         if (!info)
         {
-            fprintf(stderr, "unable to find device %s\n", argv[i]);
+            fprintf(stderr, "unable to find device '%s'\n", argv[i]);
+            rc = EXIT_FAILURE;
             continue;
         }
 
@@ -176,6 +191,7 @@ list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
         if (!dev)
         {
             fprintf(stderr, "unable to open device '%s'\n", info->name);
+            rc = EXIT_FAILURE;
             continue;
         }
 
@@ -195,145 +211,7 @@ list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
         XFree(props);
         XCloseDevice(dpy, dev);
     }
-    return EXIT_SUCCESS;
-}
-
-int
-set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
-{
-    XDeviceInfo *info;
-    XDevice     *dev;
-    Atom         prop;
-    char        *name;
-    int          i;
-    char        *data;
-    int          format, nelements =  0;
-
-    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);
-
-    nelements = argc - 3;
-    format    = atoi(argv[2]);
-    if (format != 8 && format != 16 && format != 32)
-    {
-        fprintf(stderr, "Invalid format %d\n", format);
-        return EXIT_FAILURE;
-    }
-
-    data = calloc(nelements, sizeof(long));
-    for (i = 0; i < nelements; i++)
-    {
-        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;
-        }
-    }
-
-    XChangeDeviceProperty(dpy, dev, prop, XA_INTEGER, format, PropModeReplace,
-                          (unsigned char*)data, nelements);
-
-    free(data);
-    XCloseDevice(dpy, dev);
-    return EXIT_SUCCESS;
-}
-
-int
-set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
-{
-    XDeviceInfo *info;
-    XDevice     *dev;
-    Atom         prop, float_atom;
-    char        *name;
-    int          i;
-    long        *data;
-    int          nelements =  0;
-    char*        endptr;
-
-    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", argv[0]);
-        return EXIT_FAILURE;
-    }
-
-    name = argv[1];
-
-    prop = parse_atom(dpy, name);
-
-    nelements = argc - 2;
-
-    float_atom = XInternAtom(dpy, "FLOAT", False);
-
-    if (float_atom == (Atom)0)
-    {
-       fprintf(stderr, "no FLOAT atom present in server\n");
-       return EXIT_FAILURE;
-    }
-
-    if (sizeof(float) != 4)
-    {
-       fprintf(stderr, "sane FP required\n");
-       return EXIT_FAILURE;
-    }
-
-    data = 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;
-       }
-    }
-
-    XChangeDeviceProperty(dpy, dev, prop, float_atom, 32, PropModeReplace,
-                          (unsigned char*)data, nelements);
-
-    free(data);
-    XCloseDevice(dpy, dev);
-    return EXIT_SUCCESS;
+    return rc;
 }
 
 
@@ -353,7 +231,7 @@ int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc)
     info = find_device_info(dpy, argv[0], False);
     if (!info)
     {
-        fprintf(stderr, "unable to find device %s\n", argv[0]);
+        fprintf(stderr, "unable to find device '%s'\n", argv[0]);
         return EXIT_FAILURE;
     }
 
@@ -377,6 +255,7 @@ int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc)
 
         name = XGetAtomName(dpy, dpev->atom);
         printf("Property '%s' changed.\n", name);
+        XFree(name);
         print_property(dpy, dev, dpev->atom);
     }
 
@@ -391,43 +270,7 @@ delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc)
     char        *name;
     Atom        prop;
 
-    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;
-}
-
-int
-set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
-{
-    XDeviceInfo *info;
-    XDevice     *dev;
-    Atom         prop;
-    char        *name;
-    int          i, j;
-    Bool         is_atom;
-    Atom        *data;
-    int          nelements =  0;
-
-    if (argc < 3)
+    if (argc < 2)
     {
         fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
         return EXIT_FAILURE;
@@ -436,14 +279,14 @@ set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
     info = find_device_info(dpy, argv[0], False);
     if (!info)
     {
-        fprintf(stderr, "unable to find device %s\n", argv[0]);
+        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]);
+        fprintf(stderr, "unable to open device '%s'\n", info->name);
         return EXIT_FAILURE;
     }
 
@@ -451,47 +294,23 @@ set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
 
     prop = parse_atom(dpy, name);
 
-    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 (!is_atom)
-            data[i] = XInternAtom(dpy, name, False);
-        else
-        {
-            data[i] = atoi(name);
-            XFree(XGetAtomName(dpy, data[i]));
-        }
-    }
-
-    XChangeDeviceProperty(dpy, dev, prop, XA_ATOM, 32, PropModeReplace,
-                          (unsigned char*)data, nelements);
+    XDeleteDeviceProperty(dpy, dev, prop);
 
-    free(data);
     XCloseDevice(dpy, dev);
     return EXIT_SUCCESS;
 }
 
 static int
-set_prop_xi1(Display *dpy, int argc, char **argv, char *n, char *desc)
+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          type;
+    Atom          old_type;
     char         *name;
     int           i;
     Atom          float_atom;
-    int           format, nelements = 0;
+    int           old_format, nelements = 0;
     unsigned long act_nitems, bytes_after;
     char         *endptr;
     union {
@@ -510,14 +329,14 @@ set_prop_xi1(Display *dpy, int argc, char **argv, char *n, char *desc)
     info = find_device_info(dpy, argv[0], False);
     if (!info)
     {
-        fprintf(stderr, "unable to find device %s\n", argv[0]);
+        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]);
+        fprintf(stderr, "unable to open device '%s'\n", argv[0]);
         return EXIT_FAILURE;
     }
 
@@ -526,24 +345,33 @@ set_prop_xi1(Display *dpy, int argc, char **argv, char *n, char *desc)
     prop = parse_atom(dpy, name);
 
     if (prop == None) {
-        fprintf(stderr, "invalid property %s\n", name);
+        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;
-    }
+    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);
+        XFree(data.c);
+    }
 
     if (type == None) {
-        fprintf(stderr, "property %s doesn't exist\n", name);
+        fprintf(stderr, "property '%s' doesn't exist, you need to specify "
+                "its type and format\n", name);
         return EXIT_FAILURE;
     }
 
@@ -551,7 +379,7 @@ set_prop_xi1(Display *dpy, int argc, char **argv, char *n, char *desc)
 
     for (i = 0; i < nelements; i++)
     {
-        if (type == XA_INTEGER) {
+        if (type == XA_INTEGER || type == XA_CARDINAL) {
             switch (format)
             {
                 case 8:
@@ -564,29 +392,29 @@ set_prop_xi1(Display *dpy, int argc, char **argv, char *n, char *desc)
                     data.l[i] = atoi(argv[2 + i]);
                     break;
                 default:
-                    fprintf(stderr, "unexpected size for property %s", name);
+                    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",
+                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]);
+                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",
+                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);
+            fprintf(stderr, "unexpected type for property '%s'\n", name);
             return EXIT_FAILURE;
         }
     }
@@ -611,6 +439,7 @@ print_property_xi2(Display *dpy, int deviceid, Atom property)
 
     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,
@@ -620,6 +449,9 @@ print_property_xi2(Display *dpy, int deviceid, Atom property)
 
         ptr = data;
 
+        if (nitems == 0)
+            printf("<no items>");
+
         for (j = 0; j < nitems; j++)
         {
             switch(act_type)
@@ -638,6 +470,20 @@ print_property_xi2(Display *dpy, int deviceid, Atom property)
                             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)
                     {
@@ -653,10 +499,10 @@ print_property_xi2(Display *dpy, int deviceid, Atom property)
                     break;
                 case XA_ATOM:
                     {
-                        Atom a = *(Atom*)ptr;
-                        printf("\"%s\" (%d)",
-                                (a) ? XGetAtomName(dpy, a) : "None",
-                                (int)a);
+                        Atom a = *(uint32_t*)ptr;
+                        name = (a) ? XGetAtomName(dpy, a) : NULL;
+                        printf("\"%s\" (%ld)", name ? name : "None", a);
+                        XFree(name);
                         break;
                     }
                     break;
@@ -667,8 +513,9 @@ print_property_xi2(Display *dpy, int deviceid, Atom property)
                         break;
                     }
 
-                    printf("\t... of unknown type %s\n",
-                            XGetAtomName(dpy, act_type));
+                    name = XGetAtomName(dpy, act_type);
+                    printf("\t... of unknown type %s\n", name);
+                    XFree(name);
                     done = True;
                     break;
             }
@@ -694,6 +541,7 @@ list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc)
     int         i;
     int         nprops;
     Atom        *props;
+    int         rc = EXIT_SUCCESS;
 
     if (argc == 0)
     {
@@ -707,6 +555,7 @@ list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc)
         if (!info)
         {
             fprintf(stderr, "unable to find device %s\n", argv[i]);
+            rc = EXIT_FAILURE;
             continue;
         }
 
@@ -725,7 +574,7 @@ list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc)
 
         XFree(props);
     }
-    return EXIT_SUCCESS;
+    return rc;
 }
 
 static int
@@ -735,6 +584,12 @@ delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc)
     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)
     {
@@ -752,34 +607,35 @@ delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc)
 }
 
 static int
-set_prop_xi2(Display *dpy, int argc, char **argv, char *n, char *desc)
+do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
 {
     XIDeviceInfo *info;
     Atom          prop;
-    Atom          type;
+    Atom          old_type;
     char         *name;
     int           i;
     Atom          float_atom;
-    int           format, nelements = 0;
+    int           old_format, nelements = 0;
     unsigned long act_nitems, bytes_after;
     char         *endptr;
     union {
         unsigned char *c;
         int16_t *s;
         int32_t *l;
-    } data;
+    } data = { NULL };
+    int rc = EXIT_FAILURE;
 
     if (argc < 3)
     {
         fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
-        return EXIT_FAILURE;
+        goto out;
     }
 
     info = xi2_find_device_info(dpy, argv[0]);
     if (!info)
     {
         fprintf(stderr, "unable to find device %s\n", argv[0]);
-        return EXIT_FAILURE;
+        goto out;
     }
 
     name = argv[1];
@@ -787,32 +643,41 @@ set_prop_xi2(Display *dpy, int argc, char **argv, char *n, char *desc)
     prop = parse_atom(dpy, name);
 
     if (prop == None) {
-        fprintf(stderr, "invalid property %s\n", name);
-        return EXIT_FAILURE;
+        fprintf(stderr, "invalid property '%s'\n", name);
+        goto out;
     }
 
     float_atom = XInternAtom(dpy, "FLOAT", False);
 
     nelements = argc - 2;
-    if (XIGetProperty(dpy, info->deviceid, 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;
-    }
+    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);
+        XFree(data.c);
+    }
 
     if (type == None) {
-        fprintf(stderr, "property %s doesn't exist\n", name);
-        return EXIT_FAILURE;
+        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) {
+        if (type == XA_INTEGER || type == XA_CARDINAL) {
             switch (format)
             {
                 case 8:
@@ -826,43 +691,45 @@ set_prop_xi2(Display *dpy, int argc, char **argv, char *n, char *desc)
                     break;
                 default:
                     fprintf(stderr, "unexpected size for property %s", name);
-                    return EXIT_FAILURE;
+                    goto out;
             }
         } else if (type == float_atom) {
             if (format != 32) {
-                fprintf(stderr, "unexpected format %d for property %s\n",
+                fprintf(stderr, "unexpected format %d for property '%s'\n",
                         format, name);
-                return EXIT_FAILURE;
+                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]);
-                return EXIT_FAILURE;
+                goto out;
             }
         } else if (type == XA_ATOM) {
             if (format != 32) {
-                fprintf(stderr, "unexpected format %d for property %s\n",
+                fprintf(stderr, "unexpected format %d for property '%s'\n",
                         format, name);
-                return EXIT_FAILURE;
+                goto out;
             }
             data.l[i] = parse_atom(dpy, argv[2 + i]);
         } else {
-            fprintf(stderr, "unexpected type for property %s\n", name);
-            return EXIT_FAILURE;
+            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 EXIT_SUCCESS;
+    return rc;
 }
 #endif
 
 int list_props(Display *display, int argc, char *argv[], char *name,
                char *desc)
 {
-#ifdef HAVE_XI2
+#if HAVE_XI2
     if (xinput_version(display) == XI_2_Major)
         return list_props_xi2(display, argc, argv, name, desc);
 #endif
@@ -873,7 +740,7 @@ int list_props(Display *display, int argc, char *argv[], char *name,
 int delete_prop(Display *display, int argc, char *argv[], char *name,
                 char *desc)
 {
-#ifdef HAVE_XI2
+#if HAVE_XI2
     if (xinput_version(display) == XI_2_Major)
         return delete_prop_xi2(display, argc, argv, name, desc);
 #endif
@@ -881,12 +748,132 @@ int delete_prop(Display *display, int argc, char *argv[], char *name,
 
 }
 
-int set_prop(Display *display, int argc, char *argv[], char *name,
-             char *desc)
+static int
+do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc)
 {
-#ifdef HAVE_XI2
+#if HAVE_XI2
     if (xinput_version(display) == XI_2_Major)
-        return set_prop_xi2(display, argc, argv, name, desc);
+        return do_set_prop_xi2(display, type, format, argc, argv, name, desc);
 #endif
-    return set_prop_xi1(display, argc, argv, name, desc);
+    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);
 }