[PATCH evdev 5/7] Handling the creation / destruction of mt subdevices by the property "Evdev MultiTouch"

Benjamin Tissoires tissoire at cena.fr
Sat Dec 19 03:34:48 PST 2009


Signed-off-by: Benjamin Tissoires <tissoire at cena.fr>
---
 src/evdev.c |  169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 167 insertions(+), 2 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index fb5c5c9..3722a1c 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -118,6 +118,7 @@ static const char *evdevDefaults[] = {
 static int EvdevOn(DeviceIntPtr);
 static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare);
 static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
+static void EvdevSetMultitouch(InputInfoPtr pInfo, int num_multitouch);
 
 #ifdef HAVE_PROPERTIES
 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
@@ -131,8 +132,11 @@ static Atom prop_swap = 0;
 static Atom prop_axis_label = 0;
 static Atom prop_btn_label = 0;
 static Atom prop_tracking_id = 0;
+static Atom prop_multitouch = 0;
 #endif
 
+static InputInfoPtr pCreatorInfo = NULL;
+
 /* All devices the evdev driver has allocated and knows about.
  * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
  * cannot be used by evdev, leaving us with a space of 2 at the end. */
@@ -1583,6 +1587,7 @@ EvdevOn(DeviceIntPtr device)
     }
 
     xf86FlushInput(pInfo->fd);
+    EvdevSetMultitouch(pInfo, pEvdev->num_multitouch);
     xf86AddEnabledDevice(pInfo);
     EvdevMBEmuOn(pInfo);
     pEvdev->flags |= EVDEV_INITIALIZED;
@@ -1616,6 +1621,7 @@ EvdevProc(DeviceIntPtr device, int what)
         if (pEvdev->flags & EVDEV_INITIALIZED)
             EvdevMBEmuFinalize(pInfo);
         if (EvdevIsCoreDevice(pInfo)){
+            EvdevSetMultitouch(pInfo, 0);
             if (pInfo->fd != -1)
             {
                 if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
@@ -2045,6 +2051,7 @@ static InputInfoPtr
 EvdevSubdevPreInit(InputInfoPtr pInfo, InputDriverPtr drv, IDevPtr dev, int flags)
 {
     EvdevPtr pEvdev;
+    EvdevPtr pCreatorEvdev;
 
     /* Initialise the InputInfoRec. */
     pInfo->name = dev->identifier;
@@ -2072,9 +2079,14 @@ EvdevSubdevPreInit(InputInfoPtr pInfo, InputDriverPtr drv, IDevPtr dev, int flag
     xf86ProcessCommonOptions(pInfo, pInfo->options);
     pEvdev->id = -1;
     
+    if (!pCreatorInfo){
+        return pInfo;
+    }
+    pCreatorEvdev = pCreatorInfo->private;
+    memcpy(pEvdev, pCreatorEvdev, sizeof(EvdevRec));
+    pInfo->type_name = pCreatorInfo->type_name;
     xf86Msg(X_INFO, "%s: Evdev subdevice found\n", dev->identifier);
-    // FIXME: need to duplicate the parent device
-
+    
     pInfo->flags |= XI86_CONFIGURED;
     pEvdev->num_multitouch = 1;
     
@@ -2624,6 +2636,17 @@ EvdevInitProperty(DeviceIntPtr dev)
                 return;
 
             XISetDevicePropertyDeletable(dev, prop_tracking_id, FALSE);
+
+            /* The number of multitouch subdevices.
+             * If 0, we emulate a touchscreen. */
+            prop_multitouch = MakeAtom(EVDEV_PROP_MULTITOUCH_SUBDEVICES,
+                    strlen(EVDEV_PROP_MULTITOUCH_SUBDEVICES), TRUE);
+            rc = XIChangeDeviceProperty(dev, prop_multitouch, XA_INTEGER, 8,
+                    PropModeReplace, 1, &pEvdev->num_multitouch, FALSE);
+            if (rc != Success)
+                return;
+
+            XISetDevicePropertyDeletable(dev, prop_multitouch, FALSE);
         }
 
 #ifdef HAVE_LABELS
@@ -2694,8 +2717,150 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 
         if (!checkonly)
             pEvdev->id = *((int*)val->data);
+    } else if (atom == prop_multitouch)
+    {
+        BOOL data;
+        if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+        if (!checkonly) {
+            data = *((BOOL*)val->data);
+            if (pEvdev->num_multitouch != data)
+                EvdevSetMultitouch(pInfo,data);
+        }
     }
 
     return Success;
 }
 #endif
+
+/* Duplicate xf86 options and convert them to InputOption */
+static InputOption *EvdevOptionDupConvert(pointer original)
+{
+    InputOption *iopts = NULL, *new;
+    InputInfoRec dummy;
+
+
+    memset(&dummy, 0, sizeof(dummy));
+    xf86CollectInputOptions(&dummy, NULL, original);
+
+    while(dummy.options)
+    {
+        new = xcalloc(1, sizeof(InputOption));
+
+        new->key = xf86OptionName(dummy.options);
+        new->value = xf86OptionValue(dummy.options);
+
+        new->next = iopts;
+        iopts = new;
+        dummy.options = xf86NextOption(dummy.options);
+    }
+    return iopts;
+}
+static void EvdevFreeInputOpts(InputOption* opts)
+{
+    InputOption *tmp = opts;
+
+    while(opts)
+    {
+        tmp = opts->next;
+        xfree(opts->key);
+        xfree(opts->value);
+        xfree(opts);
+        opts = tmp;
+    }
+}
+static void EvdevReplaceOption(InputOption *opts,const char* key, char * value)
+{
+
+    while(opts)
+    {
+        if (xf86NameCmp(opts->key, key) == 0)
+        {
+
+            xfree(opts->value);
+            opts->value = strdup(value);
+        }
+        opts = opts->next;
+    }
+}
+
+/**
+ * New device creation through xorg/input
+ *
+ * @return 0 if successful, 1 if failure
+ */
+static InputInfoPtr
+EvdevCreateSubDevice(InputInfoPtr pInfo, int id) {
+    InputInfoPtr pSubdev;
+
+    DeviceIntPtr dev; /* dummy */
+    InputOption *input_options = NULL;
+    char* name;
+    
+
+    pInfo->options = xf86AddNewOption(pInfo->options, "Type", "core");
+    pInfo->options = xf86AddNewOption(pInfo->options, "SendCoreEvents", "on");
+
+    /* Create new device */
+
+    input_options = EvdevOptionDupConvert(pInfo->options);
+
+    EvdevReplaceOption(input_options, "type","Object");
+
+    //EvdevReplaceOption(input_options, "SendCoreEvents","off"); //FIXME: bug in xserver
+    name = xalloc( (strlen(pInfo->name) + strlen(" subdev ") + 20 )*sizeof(char)); // 20 for adding the id
+    sprintf(name, "%s subdev %i", pInfo->name, id);
+    EvdevReplaceOption(input_options, "name",name);
+
+    pCreatorInfo = pInfo;
+    NewInputDeviceRequest(input_options, &dev);
+    pSubdev = dev->public.devicePrivate;
+    pCreatorInfo = NULL;
+
+    EvdevFreeInputOpts(input_options);
+
+    xfree(name);
+    return pSubdev;
+}
+static void
+EvdevDeleteSubDevice(InputInfoPtr pInfo, InputInfoPtr subdev) {
+    /* We need to explicitely flush the events so as not deleting
+     * a device that still has events in queue
+     */
+    ProcessInputEvents();
+    xf86Msg(X_INFO, "%s: Removing subdevice %s\n", pInfo->name,subdev->name);
+    DeleteInputDeviceRequest(subdev->dev);
+}
+
+/*
+ * Handle the creation/destruction of subdevices
+ * according to pEvdev->num_multitouch.
+ */
+static void
+EvdevSetMultitouch(InputInfoPtr pInfo, int num_multitouch) {
+    EvdevPtr pEvdev = pInfo->private;
+    int i;
+    
+    if (num_multitouch > MAX_VALUATORS_MT)
+        num_multitouch = MAX_VALUATORS_MT;
+    if (num_multitouch < 0)
+        num_multitouch = 0;
+
+    for (i=0;i<num_multitouch;++i) {
+        if (pEvdev->vals_mt[i].pInfo == NULL){
+            pEvdev->vals_mt[i].containsValues = FALSE;
+            pEvdev->vals_mt[i].id = -1;
+            pEvdev->vals_mt[i].pInfo = EvdevCreateSubDevice(pInfo, i);
+        }
+    }
+    for (i=num_multitouch;i<MAX_VALUATORS_MT;++i) {
+        pEvdev->vals_mt[i].containsValues = FALSE;
+        pEvdev->vals_mt[i].id = -1;
+        if (pEvdev->vals_mt[i].pInfo) {
+            EvdevDeleteSubDevice(pInfo, pEvdev->vals_mt[i].pInfo);
+            pEvdev->vals_mt[i].pInfo = NULL;
+        }
+    }
+    
+    pEvdev->num_multitouch = num_multitouch;
+}
-- 
1.6.5.2


--------------090208080606020807080800
Content-Type: text/x-patch;
 name="0006-Process-of-MT-events.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0006-Process-of-MT-events.patch"



More information about the xorg-devel mailing list