[PATCH 6/8] evdev-touchpad: Made hw_abs an array

Alexander E. Patrakov patrakov at gmail.com
Mon Aug 5 03:34:35 PDT 2013


From: "Alexander E. Patrakov" <patrakov at gmail.com>

In the non-multitouch case, the 0th entry tracks motion just as the old
scalar hw_abs. In the multitouch case, there will be one entry for each
slot, and relevant_touch is used to select which one is motion-tracked.
---
 src/evdev-touchpad.c | 146 +++++++++++++++++++++++++++++++++++----------------
 1 file changed, 102 insertions(+), 44 deletions(-)

diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c
index 1ed2dbb..01c52aa 100644
--- a/src/evdev-touchpad.c
+++ b/src/evdev-touchpad.c
@@ -51,6 +51,7 @@ enum touchpad_model {
 enum interaction_model {
 	INTERACTION_MODEL_SIMPLE = 0,
 	INTERACTION_MODEL_APPLE,
+	INTERACTION_MODEL_SONY,
 };
 
 struct touchpad_model_spec {
@@ -103,6 +104,8 @@ struct touchpad_dispatch {
 	enum interaction_model interaction_model;
 	int finger_state;
 	int last_finger_state;
+	int slot;
+	int relevant_touch;
 
 	double constant_accel_factor;
 	double min_accel_factor;
@@ -114,6 +117,7 @@ struct touchpad_dispatch {
 		struct wl_event_source *timer_source;
 	} fsm;
 
+	/* the extra dummy slot is used for out-of-range slots reported by mtdev */
 	struct {
 		int32_t x;
 		int32_t y;
@@ -123,7 +127,7 @@ struct touchpad_dispatch {
 
 		bool is_moving;
 		bool is_pressed;
-	} hw_abs;
+	} hw_abs[MAX_SLOTS + 1];
 
 	bool has_moved;
 	uint16_t touch_state;
@@ -436,29 +440,80 @@ fsm_timout_handler(void *data)
 	return 1;
 }
 
+static bool
+is_valid_touch(struct touchpad_dispatch *touchpad, int slot)
+{
+	if (!touchpad->hw_abs[slot].x_valid)
+		return false;
+	if (!touchpad->hw_abs[slot].y_valid)
+		return false;
+	if (!touchpad->hw_abs[slot].is_pressed)
+		return false;
+	return true;
+}
+
 static void
 touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
 {
+	int i;
 	int motion_index;
 	int center_x, center_y;
 	double dx = 0.0, dy = 0.0;
 
 	/* For multitouch case, this will be a bitmask */
-	uint16_t touch_state = touchpad->hw_abs.is_pressed;
 
-	if (touch_state && !touchpad->touch_state)
+	uint16_t touch_state = 0;
+	int last_valid_touch = -1;
+	int relevant_touch = touchpad->relevant_touch;
+	bool reset_motion = false;
+
+	for (i = 0; i < MAX_SLOTS; i++)
+		if (is_valid_touch(touchpad, i)) {
+			touch_state |= 1 << i;
+			last_valid_touch = i;
+		}
+
+	if (touch_state && !touchpad->touch_state) {
 		push_fsm_event(touchpad, FSM_EVENT_TOUCH);
+		reset_motion = true;
+	}
+
 	if (!touch_state && touchpad->touch_state) {
 		push_fsm_event(touchpad, FSM_EVENT_RELEASE);
 		touchpad->has_moved = false;
+		reset_motion = true;
 	}
 
+	if (touch_state && touchpad->touch_state &&
+	    !(touch_state & touchpad->touch_state)) {
+		push_fsm_event(touchpad, FSM_EVENT_RELEASE);
+		push_fsm_event(touchpad, FSM_EVENT_TOUCH);
+		touchpad->has_moved = false;
+		reset_motion = true;
+	}
+
+
+	if (relevant_touch != -1 && !(touch_state & (1 << relevant_touch))) {
+		reset_motion = true;
+		relevant_touch = -1;
+	}
+	if (relevant_touch == -1)
+		relevant_touch = last_valid_touch;
+
+	if (touchpad->last_finger_state != touchpad->finger_state)
+		reset_motion = true;
+
 	touchpad->touch_state = touch_state;
+	touchpad->last_finger_state = touchpad->finger_state;
+	touchpad->relevant_touch = relevant_touch;
 
-	if (touchpad->last_finger_state != touchpad->finger_state) {
+	if (reset_motion) {
 		touchpad->motion_count = 0;
-		touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false;
-		touchpad->hw_abs.is_moving = false;
+		if (touchpad->interaction_model != INTERACTION_MODEL_SONY) {
+			touchpad->hw_abs[0].x_valid = false;
+			touchpad->hw_abs[0].y_valid = false;
+			touchpad->hw_abs[0].is_moving = false;
+		}
 
 		touchpad->last_finger_state = touchpad->finger_state;
 
@@ -466,37 +521,36 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
 
 		return;
 	}
-	touchpad->last_finger_state = touchpad->finger_state;
 
-	if (!touchpad->hw_abs.x_valid || !touchpad->hw_abs.y_valid)
+	if (relevant_touch == -1)
 		return;
 
-	if (!touchpad->hw_abs.is_moving)
+	if (!touchpad->hw_abs[relevant_touch].is_moving)
 		return;
 
 	/* Avoid noice by moving center only when delta reaches a threshold
 	 * distance from the old center. */
 	if (touchpad->motion_count > 0) {
-		center_x = hysteresis(touchpad->hw_abs.x,
+		center_x = hysteresis(touchpad->hw_abs[relevant_touch].x,
 				      touchpad->hysteresis.center_x,
 				      touchpad->hysteresis.margin_x);
-		center_y = hysteresis(touchpad->hw_abs.y,
+		center_y = hysteresis(touchpad->hw_abs[relevant_touch].y,
 				      touchpad->hysteresis.center_y,
 				      touchpad->hysteresis.margin_y);
 	} else {
-		center_x = touchpad->hw_abs.x;
-		center_y = touchpad->hw_abs.y;
+		center_x = touchpad->hw_abs[relevant_touch].x;
+		center_y = touchpad->hw_abs[relevant_touch].y;
 	}
 	touchpad->hysteresis.center_x = center_x;
 	touchpad->hysteresis.center_y = center_y;
-	touchpad->hw_abs.x = center_x;
-	touchpad->hw_abs.y = center_y;
+	touchpad->hw_abs[relevant_touch].x = center_x;
+	touchpad->hw_abs[relevant_touch].y = center_y;
 
 	/* Update motion history tracker */
 	motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH;
 	touchpad->motion_index = motion_index;
-	touchpad->motion_history[motion_index].x = touchpad->hw_abs.x;
-	touchpad->motion_history[motion_index].y = touchpad->hw_abs.y;
+	touchpad->motion_history[motion_index].x = touchpad->hw_abs[relevant_touch].x;
+	touchpad->motion_history[motion_index].y = touchpad->hw_abs[relevant_touch].y;
 	if (touchpad->motion_count < 4)
 		touchpad->motion_count++;
 
@@ -534,17 +588,17 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
 }
 
 static void
-on_touch(struct touchpad_dispatch *touchpad)
+on_touch(struct touchpad_dispatch *touchpad, int slot)
 {
-	touchpad->hw_abs.is_pressed = true;
+	touchpad->hw_abs[slot].is_pressed = true;
 }
 
 static void
-on_release(struct touchpad_dispatch *touchpad)
+on_release(struct touchpad_dispatch *touchpad, int slot)
 {
-	touchpad->hw_abs.is_pressed = false;
-	touchpad->hw_abs.is_moving = false;
-	touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false;
+	touchpad->hw_abs[slot].is_pressed = false;
+	touchpad->hw_abs[slot].is_moving = false;
+	touchpad->hw_abs[slot].x_valid = touchpad->hw_abs[slot].y_valid = false;
 }
 
 static inline void
@@ -555,25 +609,25 @@ process_absolute(struct touchpad_dispatch *touchpad,
 	switch (e->code) {
 	case ABS_PRESSURE:
 		if (e->value > touchpad->pressure.touch_high &&
-		    !touchpad->hw_abs.is_pressed)
-			on_touch(touchpad);
+		    !touchpad->hw_abs[0].is_pressed)
+			on_touch(touchpad, 0);
 		else if (e->value < touchpad->pressure.touch_low &&
-			 touchpad->hw_abs.is_pressed)
-			on_release(touchpad);
+			 touchpad->hw_abs[0].is_pressed)
+			on_release(touchpad, 0);
 
 		break;
 	case ABS_X:
-		if (touchpad->hw_abs.is_pressed) {
-			touchpad->hw_abs.x = e->value;
-			touchpad->hw_abs.x_valid = true;
-			touchpad->hw_abs.is_moving = true;
+		if (touchpad->hw_abs[0].is_pressed) {
+			touchpad->hw_abs[0].x = e->value;
+			touchpad->hw_abs[0].x_valid = true;
+			touchpad->hw_abs[0].is_moving = true;
 		}
 		break;
 	case ABS_Y:
-		if (touchpad->hw_abs.is_pressed) {
-			touchpad->hw_abs.y = e->value;
-			touchpad->hw_abs.y_valid = true;
-			touchpad->hw_abs.is_moving = true;
+		if (touchpad->hw_abs[0].is_pressed) {
+			touchpad->hw_abs[0].y = e->value;
+			touchpad->hw_abs[0].y_valid = true;
+			touchpad->hw_abs[0].is_moving = true;
 		}
 		break;
 	}
@@ -590,10 +644,10 @@ process_key(struct touchpad_dispatch *touchpad,
 	switch (e->code) {
 	case BTN_TOUCH:
 		if (!touchpad->has_pressure) {
-			if (e->value && !touchpad->hw_abs.is_pressed)
-				on_touch(touchpad);
+			if (e->value && !touchpad->hw_abs[0].is_pressed)
+				on_touch(touchpad, 0);
 			else if (!e->value)
-				on_release(touchpad);
+				on_release(touchpad, 0);
 		}
 		break;
 	case BTN_LEFT:
@@ -624,8 +678,11 @@ process_key(struct touchpad_dispatch *touchpad,
 		/* The reset-logic below was copied without understanding
 		 * and may be inappropriate */
 		touchpad->motion_count = 0;
-		touchpad->hw_abs.x_valid = touchpad->hw_abs.y_valid = false;
-		touchpad->hw_abs.is_moving = false;
+		if (touchpad->interaction_model != INTERACTION_MODEL_SONY) {
+			touchpad->hw_abs[0].x_valid = false;
+			touchpad->hw_abs[0].y_valid = false;
+			touchpad->hw_abs[0].is_moving = false;
+		}
 		break;
 	case BTN_TOOL_FINGER:
 		if (e->value)
@@ -746,10 +803,11 @@ touchpad_init(struct touchpad_dispatch *touchpad,
 	touchpad->motion_index = 0;
 	touchpad->motion_count = 0;
 
-	touchpad->hw_abs.x_valid = false;
-	touchpad->hw_abs.y_valid = false;
-	touchpad->hw_abs.is_pressed = false;
-	touchpad->hw_abs.is_moving = false;
+	memset(touchpad->hw_abs, 0, sizeof touchpad->hw_abs);
+
+	touchpad->slot = MAX_SLOTS;
+	touchpad->relevant_touch = -1;
+
 	touchpad->has_moved = false;
 	touchpad->touch_state = 0;
 
-- 
1.8.3.2



More information about the wayland-devel mailing list