[PATCH 2/2] Add support for per-axis valuator modes (Relative/Absolute)

Peter Hutterer peter.hutterer at who-t.net
Tue Jul 27 21:55:32 PDT 2010


On Fri, Jul 16, 2010 at 09:21:19AM -0400, Chase Douglas wrote:
> The XI2 protocol supports per-axis modes, but the server so far does
> not. This change adds support in the server.
> 
> A complication is the fact that XI1 does not support per-axis modes.
> The solution provided here is to set a per-device mode that defines the
> mode of at least the first two valuators (X and Y). The per-axis
> valuator mode defaults to Relative, so any absolute axes must be
> explicitly set. Note that initializing the first two axes to a different
> mode than the device mode will fail.
> 
> For XI1 events, any axes following the first two that have the same mode
> will be sent to clients, up to the first axis that has a different mode.
> Thus, if a device has relative, then absolute, then relative mode axes,
> only the first block of relative axes will be sent over XI1.
> 
> Since the XI2 protocol supports per-axis modes, all axes are sent to the
> client.
> 
> Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
> ---
>  Xi/exevents.c            |    1 +
>  Xi/xiquerydevice.c       |    2 +-
>  dix/devices.c            |    3 +--
>  dix/eventconvert.c       |   14 +++++++++++++-
>  dix/getevents.c          |   23 ++++++++++++++++-------
>  hw/dmx/input/dmxmotion.c |    7 +++----
>  include/inputstr.h       |    1 +
>  7 files changed, 36 insertions(+), 15 deletions(-)
> 
> diff --git a/Xi/exevents.c b/Xi/exevents.c
> index e990aeb..26084f5 100644
> --- a/Xi/exevents.c
> +++ b/Xi/exevents.c
> @@ -1145,6 +1145,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int
>      ax->min_resolution = min_res;
>      ax->max_resolution = max_res;
>      ax->label = label;
> +    ax->mode = dev->valuator->mode;

shouldn't this be another parameter then?

>  }
>  
>  static void
> diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
> index 303c8b2..c8b3d7e 100644
> --- a/Xi/xiquerydevice.c
> +++ b/Xi/xiquerydevice.c
> @@ -349,7 +349,7 @@ ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber,
>      info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16));
>      info->resolution = v->axes[axisnumber].resolution;
>      info->number = axisnumber;
> -    info->mode = v->mode; /* Server doesn't have per-axis mode yet */
> +    info->mode = v->axes[axisnumber].mode;
>      info->sourceid = v->sourceid;
>  
>      if (!reportState)
> diff --git a/dix/devices.c b/dix/devices.c
> index ac5806a..e4048e4 100644
> --- a/dix/devices.c
> +++ b/dix/devices.c
> @@ -2366,8 +2366,7 @@ RecalculateMasterButtons(DeviceIntPtr slave)
>                  event.valuators[i].min = master->valuator->axes[i].min_value;
>                  event.valuators[i].max = master->valuator->axes[i].max_value;
>                  event.valuators[i].resolution = master->valuator->axes[i].resolution;
> -                /* This should, eventually, be a per-axis mode */
> -                event.valuators[i].mode = master->valuator->mode;
> +                event.valuators[i].mode = master->valuator->axes[i].mode;
>                  event.valuators[i].name = master->valuator->axes[i].label;
>              }
>          }
> diff --git a/dix/eventconvert.c b/dix/eventconvert.c
> index 4e3de0b..991298e 100644
> --- a/dix/eventconvert.c
> +++ b/dix/eventconvert.c
> @@ -252,6 +252,12 @@ eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count)
>      }
>  
>      num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */
> +    if (num_events <= 0)
> +    {
> +        *count = 0;
> +        return BadMatch;
> +    }
> +
>      num_events++; /* the actual event event */
>  
>      *xi = calloc(num_events, sizeof(xEvent));
> @@ -309,6 +315,12 @@ countValuators(DeviceEvent *ev, int *first)
>  
>      for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
>      {
> +        /* Assume mode of 0th valuator matches XI1 device mode. Stop when the
> +         * event mode changes since XI1 can't handle mixed mode devices.
> +         */

why is this assumption necessary? valuator->mode still stores what the XI1
device mode is.

> +        if (ev->valuators.mode[i] != ev->valuators.mode[0])
> +            break;
> +
>          if (BitIsOn(ev->valuators.mask, i))
>          {
>              if (first_valuator == -1)
> @@ -431,7 +443,7 @@ appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumbe
>      info->value.frac = 0;
>      info->resolution = dce->valuators[axisnumber].resolution;
>      info->number = axisnumber;
> -    info->mode = dce->valuators[axisnumber].mode; /* Server doesn't have per-axis mode yet */
> +    info->mode = dce->valuators[axisnumber].mode;
>      info->sourceid = dce->sourceid;
>  
>      return info->length * 4;
> diff --git a/dix/getevents.c b/dix/getevents.c
> index 20cc79b..72daa16 100644
> --- a/dix/getevents.c
> +++ b/dix/getevents.c
> @@ -208,7 +208,7 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, uint8_t *mask,
>          if (BitIsOn(mask, i))
>          {
>              SetBit(event->valuators.mask, i);
> -            if (dev->valuator->mode == Absolute)
> +            if (dev->valuator->axes[i].mode == Absolute)
>                  SetBit(event->valuators.mode, i);
>              event->valuators.data[i] = valuators[i];
>              event->valuators.data_frac[i] =
> @@ -253,8 +253,7 @@ CreateClassesChangedEvent(EventList* event,
>              dce->valuators[i].min = slave->valuator->axes[i].min_value;
>              dce->valuators[i].max = slave->valuator->axes[i].max_value;
>              dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
> -            /* This should, eventually, be a per-axis mode */
> -            dce->valuators[i].mode = slave->valuator->mode;
> +            dce->valuators[i].mode = slave->valuator->axes[i].mode;
>              dce->valuators[i].name = slave->valuator->axes[i].label;
>          }
>      }
> @@ -372,8 +371,15 @@ AllocateMotionHistory(DeviceIntPtr pDev)
>       */
>      if (IsMaster(pDev))
>          size = sizeof(INT32) * 3 * MAX_VALUATORS;
> -    else
> -        size = sizeof(INT32) * pDev->valuator->numAxes;
> +    else {
> +        int numAxes;
> +        /* XI1 doesn't understand mixed mode devices */
> +        for (numAxes = 0; numAxes < pDev->valuator->numAxes; numAxes++)
> +            if ((pDev->valuator->axes[numAxes].mode & DeviceMode) !=
> +                (pDev->valuator->mode & DeviceMode))
> +                break;

i think having a ValuatorClassPtr v = pDev->valuator would make the code
easier to read.

> +        size = sizeof(INT32) * numAxes;
> +    }
>  
>      size += sizeof(Time);
>  
> @@ -554,7 +560,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, uint8_t *mask,
>  
>          for (i = 0; i < MAX_VALUATORS; i++)
>          {
> -            if (i >= v->numAxes)
> +            /* XI1 doesn't support mixed mode devices */
> +            if (i >= v->numAxes ||
> +                (pDev->valuator->axes[i].mode & DeviceMode) !=
> +                (pDev->valuator->mode & DeviceMode))
>                  break;
>              if (!BitIsOn(mask, i))
>              {
> @@ -768,7 +777,7 @@ moveRelative(DeviceIntPtr dev, int *x, int *y,
>          if (BitIsOn(mask, i))
>          {
>              dev->last.valuators[i] += valuators[i];
> -            if (dev->valuator->mode == Absolute)
> +            if (dev->valuator->axes[i].mode == Absolute)
>                  clipAxis(dev, i, &dev->last.valuators[i]);
>              valuators[i] = dev->last.valuators[i];
>          }
> diff --git a/hw/dmx/input/dmxmotion.c b/hw/dmx/input/dmxmotion.c
> index a86b62e..1aae5fe 100644
> --- a/hw/dmx/input/dmxmotion.c
> +++ b/hw/dmx/input/dmxmotion.c
> @@ -125,12 +125,11 @@ void dmxPointerPutMotionEvent(DeviceIntPtr pDevice,
>                                  /* Initialize the data from the known
>                                   * values (if Absolute) or to zero (if
>                                   * Relative) */
> -    if (pDevice->valuator->mode == Absolute) {
> -        for (i = 0; i < numAxes; i++) 
> +    for (i = 0; i < numAxes; i++) {
> +        if (pDevice->valuator->axes[i].mode == Absolute)
>              dmxLocal->history[OFFSET(dmxLocal->tail,i+1)]
>                  = dmxLocal->valuators[i];
> -    } else {
> -        for (i = 0; i < numAxes; i++) 
> +        else
>              dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0;
>      }
>      
> diff --git a/include/inputstr.h b/include/inputstr.h
> index 1b504e9..d0e9f45 100644
> --- a/include/inputstr.h
> +++ b/include/inputstr.h
> @@ -217,6 +217,7 @@ typedef struct _AxisInfo {
>      int		min_value;
>      int		max_value;
>      Atom	label;
> +    CARD8	mode;
>  } AxisInfo, *AxisInfoPtr;
>  
>  typedef struct _ValuatorAccelerationRec {
> -- 
> 1.7.0.4
> 
Cheers,
  Peter


More information about the xorg-devel mailing list