[PATCH libinput 15/24] tablet: Add infrastructure to store and notify axis states.

Peter Hutterer peter.hutterer at who-t.net
Sun Apr 27 22:07:35 PDT 2014


On Mon, Apr 21, 2014 at 07:11:24PM +0200, Carlos Garnacho wrote:
> An axis_frame event is sent too to notify a set of simultaneous axis
> changes. Only the infrastructure is added, No axes are managed at the
> moment.
> 
> Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
> ---
>  src/evdev-tablet.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/evdev-tablet.h |  10 +++++
>  2 files changed, 117 insertions(+)
> 
> diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> index 0682563..70f3210 100644
> --- a/src/evdev-tablet.c
> +++ b/src/evdev-tablet.c
> @@ -35,6 +35,63 @@
>  #define tablet_get_disabled_buttons(tablet,field) \
>  	(tablet->prev_state.field & ~(tablet->state.field))
>  
> +static struct axis_info *
> +tablet_get_axis(struct tablet_dispatch *tablet,
> +		int32_t evcode)
> +{
> +	int pos;
> +
> +	for (pos = 0; pos < tablet->n_axes; pos++) {
> +		if (tablet->axes[pos].code == evcode)
> +			return &tablet->axes[pos];
> +	}
> +
> +	return NULL;
> +}
> +
> +static int
> +tablet_add_axis(struct tablet_dispatch *tablet,
> +		struct evdev_device *device,
> +		uint32_t evcode,
> +		uint32_t axis)
> +{
> +	const struct input_absinfo *absinfo;
> +	int current;
> +
> +	if (tablet->n_axes == MAX_AXES)
> +		return 0;
> +
> +	if (!(absinfo = libevdev_get_abs_info(device->evdev, evcode)))
> +		return 0;
> +
> +	current = tablet->n_axes++;
> +	tablet->axes[current].code = evcode;
> +	tablet->axes[current].axis = axis;
> +	tablet->axes[current].abs = *absinfo;
> +	tablet->axes[current].updated = 0;
> +
> +	return 1;
> +}
> +
> +static void
> +tablet_update_axis(struct tablet_dispatch *tablet,
> +		   int32_t code,
> +		   int32_t value)
> +{
> +	struct axis_info *axis_info;
> +
> +	if (!(axis_info = tablet_get_axis(tablet, code)))
> +		return;
> +
> +	value = max(axis_info->abs.minimum, min(value, axis_info->abs.maximum));

can we add a clip() helper for this?

> +
> +	if (value == axis_info->abs.value)
> +		return;
> +
> +	axis_info->abs.value = value;
> +	axis_info->updated = 1;

actually, you can skip much of this except for the update and just call
libevdev_get_abs_info() later. libevdev already has a copy of the state, so
you could just use that, in which case you can reduce axis_info to a
bitfield of which axes were updated.

> +}
> +
>  static void
>  tablet_process_absolute(struct tablet_dispatch *tablet,
>  			struct evdev_device *device,
> @@ -50,6 +107,17 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
>  		device->abs.y = e->value;
>  		tablet_set_status(tablet, TABLET_UPDATED);
>  		break;
> +	case ABS_PRESSURE:
> +	case ABS_DISTANCE:
> +	case ABS_TILT_X:
> +	case ABS_TILT_Y:
> +	case ABS_RX:
> +	case ABS_RY:
> +	case ABS_RZ:
> +	case ABS_WHEEL:
> +	case ABS_THROTTLE:
> +		tablet_update_axis(tablet, e->code, e->value);
> +		break;
>  	default:
>  		log_info("Unhandled ABS event code 0x%x\n", e->code);
>  		break;
> @@ -171,6 +239,43 @@ tablet_check_notify_tool(struct tablet_dispatch *tablet,
>  		base, time, tablet->state.tool, tablet->state.tool_serial);
>  }
>  
> +static double
> +normalize_axis(const struct axis_info *axis_info)
> +{
> +	double range = axis_info->abs.maximum - axis_info->abs.minimum;
> +	double value = (axis_info->abs.value + axis_info->abs.minimum) / range;
> +
> +	return value;
> +}
> +
> +static void
> +tablet_notify_axes(struct tablet_dispatch *tablet,
> +		   struct evdev_device *device,
> +		   uint32_t time)
> +{
> +	struct libinput_device *base = &device->base;
> +	int i, need_frame = 0;
> +
> +	for (i = 0; i < tablet->n_axes; i++) {
> +		struct axis_info *axis = &tablet->axes[i];
> +		double value;
> +
> +		if (!axis->updated)
> +			continue;
> +
> +		need_frame = 1;
> +		axis->updated = 0;
> +		value = normalize_axis(axis);
> +		pointer_notify_axis(base,
> +				    time,
> +				    axis->axis,
> +				    li_fixed_from_double(value));
> +	}
> +
> +	if (need_frame)
> +		pointer_notify_axis_frame(base, time);
> +}
> +
>  static void
>  tablet_notify_button_mask(struct tablet_dispatch *tablet,
>  			  struct evdev_device *device,
> @@ -253,6 +358,8 @@ tablet_flush(struct tablet_dispatch *tablet,
>  			pointer_notify_motion_absolute(base, time, x, y);
>  			tablet_unset_status(tablet, TABLET_UPDATED);
>  		}
> +
> +		tablet_notify_axes(tablet, device, time);
>  	}
>  
>  	/* post-update notifications */
> diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
> index d81c878..808dab1 100644
> --- a/src/evdev-tablet.h
> +++ b/src/evdev-tablet.h
> @@ -26,6 +26,9 @@
>  
>  #include "evdev.h"
>  
> +/* Completely unscientific, but there should be plenty of room most commonly */
> +#define MAX_AXES 20

> +
>  enum tablet_status {
>  	TABLET_NONE = 0,
>  	TABLET_UPDATED = 1 << 0,
> @@ -33,6 +36,11 @@ enum tablet_status {
>  	TABLET_HAS_CONTACT = 1 << 2,
>  };
>  
> +struct axis_info {
> +	int32_t code, axis, updated;

bool updated, and please one field per line.

> +	struct input_absinfo abs;

you can get that from libevdev, see my comment above.

> +};
> +
>  struct device_state {
>  	uint32_t pad_buttons; /* bitmask of evcode - BTN_MISC */
>  	uint32_t stylus_buttons; /* bitmask of evcode - BTN_TOUCH */
> @@ -47,7 +55,9 @@ struct tablet_dispatch {
>  	struct device_state state;
>  	struct device_state prev_state;
>  
> +	struct axis_info axes[MAX_AXES];

if you have a n_axes anyway, just allocate it on demand?
also, s/n_axes/naxes/ please, I can't find any "n_foo" in the repo but I know
for sure I've used nfoo myself.

Cheers,
   Peter

>  	enum tablet_status status;
> +	int n_axes;
>  };
>  
>  #endif
> -- 
> 1.9.0
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> 


More information about the wayland-devel mailing list