Patch against 1.2 adding touch support for the desktop and some of the clients

Rusty Lynch rusty.lynch at intel.com
Wed Jul 31 08:55:23 PDT 2013


>From 47a85346d2a6236283ea3241c626c5568225b21a Mon Sep 17 00:00:00 2001
From: Rusty Lynch <rusty.lynch at intel.com>
Date: Fri, 26 Jul 2013 08:50:27 -0700
Subject: [PATCH 2/2] Add initial touch support to clients

---
 clients/calibrator.c    |  16 ++++
 clients/desktop-shell.c |  15 ++++
 clients/smoke.c         |  22 +++--
 clients/window.c        | 226 ++++++++++++++++++++++++++++++++++++++++++++++++
 clients/window.h        |  36 +++++++-
 src/evdev.c             |   2 +-
 src/input.c             |  11 +++
 src/shell.c             |   8 +-
 8 files changed, 328 insertions(+), 8 deletions(-)

diff --git a/clients/calibrator.c b/clients/calibrator.c
index cc6f4ed..9183e3e 100644
--- a/clients/calibrator.c
+++ b/clients/calibrator.c
@@ -163,6 +163,21 @@ button_handler(struct widget *widget,
 }
 
 static void
+touch_handler(struct widget *widget, uint32_t serial, uint32_t time,
+	      int32_t id, wl_fixed_t x_w, wl_fixed_t y_w, void *data)
+{
+	struct calibrator *calibrator = data;
+	calibrator->tests[calibrator->current_test].clicked_x = wl_fixed_to_int(x_w);
+	calibrator->tests[calibrator->current_test].clicked_y = wl_fixed_to_int(y_w);
+	calibrator->current_test--;
+
+	if (calibrator->current_test < 0)
+		  finish_calibration(calibrator);
+
+	widget_schedule_redraw(widget);
+}
+
+static void
 redraw_handler(struct widget *widget, void *data)
 {
 	struct calibrator *calibrator = data;
@@ -216,6 +231,7 @@ calibrator_create(struct display *display)
 	calibrator->current_test = ARRAY_LENGTH(test_ratios) - 1;
 
 	widget_set_button_handler(calibrator->widget, button_handler);
+	widget_set_touch_down_handler(calibrator->widget, touch_handler);
 	widget_set_redraw_handler(calibrator->widget, redraw_handler);
 
 	window_set_fullscreen(calibrator->window, 1);
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 1062901..76474fe 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -318,6 +318,19 @@ panel_launcher_button_handler(struct widget *widget,
 	widget_schedule_redraw(widget);
 	if (state == WL_POINTER_BUTTON_STATE_RELEASED)
 		panel_launcher_activate(launcher);
+
+}
+
+static void
+panel_launcher_touch_down_handler(struct widget *widget, uint32_t serial,
+				  uint32_t time, int32_t id, wl_fixed_t x_w,
+				  wl_fixed_t y_w, void *data)
+{
+	struct panel_launcher *launcher;
+
+	launcher = widget_get_user_data(widget);
+	widget_schedule_redraw(widget);
+	panel_launcher_activate(launcher);
 }
 
 static void
@@ -640,6 +653,8 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path)
 				   panel_launcher_leave_handler);
 	widget_set_button_handler(launcher->widget,
 				    panel_launcher_button_handler);
+	widget_set_touch_down_handler(launcher->widget,
+				      panel_launcher_touch_down_handler);
 	widget_set_redraw_handler(launcher->widget,
 				  panel_launcher_redraw_handler);
 	widget_set_motion_handler(launcher->widget,
diff --git a/clients/smoke.c b/clients/smoke.c
index 5d7333d..bdebc25 100644
--- a/clients/smoke.c
+++ b/clients/smoke.c
@@ -226,11 +226,9 @@ redraw_handler(struct widget *widget, void *data)
 	wl_surface_commit(window_get_wl_surface(smoke->window));
 }
 
-static int
-smoke_motion_handler(struct widget *widget, struct input *input,
-		     uint32_t time, float x, float y, void *data)
+static void
+smoke_motion_handler(struct smoke *smoke,float x, float y)
 {
-	struct smoke *smoke = data;
 	int i, i0, i1, j, j0, j1, k, d = 5;
 
 	if (x - d < 1)
@@ -258,10 +256,23 @@ smoke_motion_handler(struct widget *widget, struct input *input,
 			smoke->b[0].v[k] += 256 - (random() & 512);
 			smoke->b[0].d[k] += 1;
 		}
+}
 
+static int
+mouse_motion_handler(struct widget *widget, struct input *input,
+		     uint32_t time, float x, float y, void *data)
+{
+	smoke_motion_handler((struct smoke*)data, x, y);
 	return CURSOR_HAND1;
 }
 
+static int
+touch_motion_handler(struct widget *widget, uint32_t time,
+		     int32_t id, wl_fixed_t x_w, wl_fixed_t y_w, void *data)
+{
+	smoke_motion_handler((struct smoke*)data, wl_fixed_to_int(x_w), wl_fixed_to_int(y_w));
+}
+
 static void
 resize_handler(struct widget *widget,
 	       int32_t width, int32_t height, void *data)
@@ -305,7 +316,8 @@ int main(int argc, char *argv[])
 	smoke.b[1].u = calloc(size, sizeof(float));
 	smoke.b[1].v = calloc(size, sizeof(float));
 
-	widget_set_motion_handler(smoke.widget, smoke_motion_handler);
+	widget_set_motion_handler(smoke.widget, mouse_motion_handler);
+	widget_set_touch_motion_handler(smoke.widget, touch_motion_handler);
 	widget_set_resize_handler(smoke.widget, resize_handler);
 	widget_set_redraw_handler(smoke.widget, redraw_handler);
 
diff --git a/clients/window.c b/clients/window.c
index cbfe12f..058dcb9 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -270,6 +270,11 @@ struct widget {
 	widget_leave_handler_t leave_handler;
 	widget_motion_handler_t motion_handler;
 	widget_button_handler_t button_handler;
+	widget_touch_down_handler_t touch_down_handler;
+	widget_touch_up_handler_t touch_up_handler;
+	widget_touch_motion_handler_t touch_motion_handler;
+	widget_touch_frame_handler_t touch_frame_handler;
+	widget_touch_cancel_handler_t touch_cancel_handler;
 	widget_axis_handler_t axis_handler;
 	void *user_data;
 	int opaque;
@@ -277,13 +282,22 @@ struct widget {
 	int default_cursor;
 };
 
+struct touch_point {
+	int32_t id;
+	struct widget *widget;
+	struct wl_list link;
+};
+
 struct input {
 	struct display *display;
 	struct wl_seat *seat;
 	struct wl_pointer *pointer;
 	struct wl_keyboard *keyboard;
+	struct wl_touch *touch;
+	struct wl_list touch_point_list;
 	struct window *pointer_focus;
 	struct window *keyboard_focus;
+	struct window *touch_focus;
 	int current_cursor;
 	uint32_t cursor_anim_start;
 	struct wl_callback *cursor_frame_cb;
@@ -1873,6 +1887,41 @@ widget_set_button_handler(struct widget *widget,
 }
 
 void
+widget_set_touch_up_handler(struct widget *widget,
+			    widget_touch_up_handler_t handler)
+{
+	widget->touch_up_handler = handler;
+}
+
+void
+widget_set_touch_down_handler(struct widget *widget,
+			      widget_touch_down_handler_t handler)
+{
+	widget->touch_down_handler = handler;
+}
+
+void
+widget_set_touch_motion_handler(struct widget *widget,
+				widget_touch_motion_handler_t handler)
+{
+	widget->touch_motion_handler = handler;
+}
+
+void
+widget_set_touch_frame_handler(struct widget *widget,
+			       widget_touch_frame_handler_t handler)
+{
+	widget->touch_frame_handler = handler;
+}
+
+void
+widget_set_touch_cancel_handler(struct widget *widget,
+				widget_touch_cancel_handler_t handler)
+{
+	widget->touch_cancel_handler = handler;
+}
+
+void
 widget_set_axis_handler(struct widget *widget,
 			widget_axis_handler_t handler)
 {
@@ -2286,6 +2335,35 @@ frame_button_button_handler(struct widget *widget,
 	}
 }
 
+static void
+frame_button_touch_down_handler(struct widget *widget, uint32_t serial,
+				uint32_t time, int32_t id, wl_fixed_t x_w,
+				wl_fixed_t y_w, void *data)
+{
+	struct frame_button *frame_button = data;
+	struct window *window = widget->window;
+
+	switch (frame_button->type) {
+	case FRAME_BUTTON_CLOSE:
+		if (window->close_handler)
+			window->close_handler(window->parent,
+					      window->user_data);
+		else
+			display_exit(window->display);
+		break;
+	case FRAME_BUTTON_MINIMIZE:
+		fprintf(stderr,"Minimize stub\n");
+		break;
+	case FRAME_BUTTON_MAXIMIZE:
+		window_set_maximized(window, window->type != TYPE_MAXIMIZED);
+		break;
+	default:
+		/* Unknown operation */
+		break;
+	}
+}
+
+
 static int
 frame_button_motion_handler(struct widget *widget,
                             struct input *input, uint32_t time,
@@ -2387,6 +2465,7 @@ frame_button_create(struct frame *frame, void *data, enum frame_button_action ty
 	widget_set_redraw_handler(frame_button->widget, frame_button_redraw_handler);
 	widget_set_enter_handler(frame_button->widget, frame_button_enter_handler);
 	widget_set_leave_handler(frame_button->widget, frame_button_leave_handler);
+	widget_set_touch_down_handler(frame_button->widget, frame_button_touch_down_handler);
 	widget_set_button_handler(frame_button->widget, frame_button_button_handler);
 	widget_set_motion_handler(frame_button->widget, frame_button_motion_handler);
 	return frame_button->widget;
@@ -3103,6 +3182,143 @@ static const struct wl_keyboard_listener keyboard_listener = {
 };
 
 static void
+touch_handle_down(void *data, struct wl_touch *wl_touch,
+		  uint32_t serial, uint32_t time, struct wl_surface *surface,
+		  int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+	struct input *input = data;
+	struct widget *widget;
+
+	DBG("touch_handle_down: %i %i\n", id, wl_list_length(&input->touch_point_list));
+
+	input->touch_focus = wl_surface_get_user_data(surface);
+	if (!input->touch_focus) {
+		DBG("Failed to find to touch focus for surface %p\n", surface);
+		return;
+	}
+
+	widget = window_find_widget(input->touch_focus,
+				    wl_fixed_to_double(x_w),
+				    wl_fixed_to_double(y_w));
+	if (widget) {
+		struct touch_point *tp = (struct touch_point *)malloc(sizeof(struct touch_point));
+		if (tp) {
+			tp->id = id;
+			tp->widget = widget;
+			wl_list_insert(&input->touch_point_list, &tp->link);
+
+			if (widget->touch_down_handler)
+				(*widget->touch_down_handler)(widget, serial, time, id, x_w, y_w, widget->user_data);
+		}
+	}
+}
+
+static void
+touch_handle_up(void *data, struct wl_touch *wl_touch,
+		uint32_t serial, uint32_t time, int32_t id)
+{
+	struct input *input = data;
+	struct widget *widget;
+	struct touch_point *tp, *tmp;
+
+	DBG("touch_handle_up: %i %i\n", id, wl_list_length(&input->touch_point_list));
+
+	if (!input->touch_focus) {
+		DBG("No touch focus found for touch up event!\n");
+		return;
+	}
+
+	wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
+		if (tp->id != id)
+			continue;
+
+		if (tp->widget->touch_up_handler)
+			(*tp->widget->touch_up_handler)(widget, serial, time, id, tp->widget->user_data);
+
+		wl_list_remove(&tp->link);
+		free(tp);
+
+		return;
+	}
+}
+
+static void
+touch_handle_motion(void *data, struct wl_touch *wl_touch,
+		    uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+	struct input *input = data;
+	struct touch_point *tp;
+
+	DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&input->touch_point_list));
+
+	if (!input->touch_focus) {
+		DBG("No touch focus found for touch motion event!\n");
+		return;
+	}
+
+	wl_list_for_each(tp, &input->touch_point_list, link) {
+		if (tp->id != id)
+			continue;
+
+		if (tp->widget->touch_motion_handler)
+			(*tp->widget->touch_motion_handler)(tp->widget, time, id, x_w, y_w, tp->widget->user_data);
+		return;
+	}
+}
+
+static void
+touch_handle_frame(void *data, struct wl_touch *wl_touch)
+{
+	struct input *input = data;
+	struct touch_point *tp, *tmp;
+
+	DBG("touch_handle_frame\n");
+
+	if (!input->touch_focus) {
+		DBG("No touch focus found for touch frame event!\n");
+		return;
+	}
+
+	wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
+		if (tp->widget->touch_frame_handler)
+			(*tp->widget->touch_frame_handler)(tp->widget, tp->widget->user_data);
+
+		wl_list_remove(&tp->link);
+		free(tp);
+	}
+}
+
+static void
+touch_handle_cancel(void *data, struct wl_touch *wl_touch)
+{
+	struct input *input = data;
+	struct touch_point *tp, *tmp;
+
+	DBG("touch_handle_cancel\n");
+
+	if (!input->touch_focus) {
+		DBG("No touch focus found for touch cancel event!\n");
+		return;
+	}
+
+	wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
+		if (tp->widget->touch_cancel_handler)
+			(*tp->widget->touch_cancel_handler)(tp->widget, tp->widget->user_data);
+
+		wl_list_remove(&tp->link);
+		free(tp);
+	}
+}
+
+static const struct wl_touch_listener touch_listener = {
+	touch_handle_down,
+	touch_handle_up,
+	touch_handle_motion,
+	touch_handle_frame,
+	touch_handle_cancel,
+};
+
+static void
 seat_handle_capabilities(void *data, struct wl_seat *seat,
 			 enum wl_seat_capability caps)
 {
@@ -3127,6 +3343,15 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
 		wl_keyboard_destroy(input->keyboard);
 		input->keyboard = NULL;
 	}
+
+	if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
+		input->touch = wl_seat_get_touch(seat);
+		wl_touch_set_user_data(input->touch, input);
+		wl_touch_add_listener(input->touch, &touch_listener, input);
+	} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
+		wl_touch_destroy(input->touch);
+		input->touch = NULL;
+	}
 }
 
 static const struct wl_seat_listener seat_listener = {
@@ -4690,6 +4915,7 @@ display_add_input(struct display *d, uint32_t id)
 	input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
 	input->pointer_focus = NULL;
 	input->keyboard_focus = NULL;
+	wl_list_init(&input->touch_point_list);
 	wl_list_insert(d->input_list.prev, &input->link);
 
 	wl_seat_add_listener(input->seat, &seat_listener, input);
diff --git a/clients/window.h b/clients/window.h
index a79b020..8bb05cd 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -220,6 +220,26 @@ typedef void (*widget_button_handler_t)(struct widget *widget,
 					uint32_t button,
 					enum wl_pointer_button_state state,
 					void *data);
+typedef void (*widget_touch_down_handler_t)(struct widget *widget,
+					    uint32_t serial,
+					    uint32_t time,
+					    int32_t id,
+					    wl_fixed_t x_w,
+					    wl_fixed_t y_w,
+					    void *data);
+typedef void (*widget_touch_up_handler_t)(struct widget *widget,
+					  uint32_t serial,
+					  uint32_t time,
+					  int32_t id,
+					  void *data);
+typedef void (*widget_touch_motion_handler_t)(struct widget *widget,
+					      uint32_t time,
+					      int32_t id,
+					      wl_fixed_t x_w,
+					      wl_fixed_t y_w,
+					      void *data);
+typedef void (*widget_touch_frame_handler_t)(struct widget *widget,void *data);
+typedef void (*widget_touch_cancel_handler_t)(struct widget *widget, void *data);
 typedef void (*widget_axis_handler_t)(struct widget *widget,
 				      struct input *input, uint32_t time,
 				      uint32_t axis,
@@ -436,9 +456,23 @@ void
 widget_set_button_handler(struct widget *widget,
 			  widget_button_handler_t handler);
 void
+widget_set_touch_down_handler(struct widget *widget,
+			      widget_touch_down_handler_t handler);
+void
+widget_set_touch_up_handler(struct widget *widget,
+			    widget_touch_up_handler_t handler);
+void
+widget_set_touch_motion_handler(struct widget *widget,
+				widget_touch_motion_handler_t handler);
+void
+widget_set_touch_frame_handler(struct widget *widget,
+			       widget_touch_frame_handler_t handler);
+void
+widget_set_touch_cancel_handler(struct widget *widget,
+				widget_touch_cancel_handler_t handler);
+void
 widget_set_axis_handler(struct widget *widget,
 			widget_axis_handler_t handler);
-
 void
 widget_schedule_redraw(struct widget *widget);
 
diff --git a/src/evdev.c b/src/evdev.c
index b3c99b3..2ec2b65 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -85,7 +85,7 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
 
 	case BTN_TOUCH:
 		if (e->value == 0 && !device->is_mt)
-			notify_touch(device->seat, time, device->mt.slot, 0, 0,
+			notify_touch(device->seat, time, 0, 0, 0,
 				     WL_TOUCH_UP);
 		break;
 	default:
diff --git a/src/input.c b/src/input.c
index 1887e7f..e8f3a01 100644
--- a/src/input.c
+++ b/src/input.c
@@ -27,6 +27,7 @@
 #include <assert.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <linux/input.h>
 
 #include "../shared/os-compatibility.h"
 #include "compositor.h"
@@ -1046,6 +1047,8 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
 		if (seat->num_tp == 1) {
 			es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
 			touch_set_focus(seat, es);
+			weston_compositor_run_button_binding(ec, seat, time, BTN_TOUCH,
+							     WL_POINTER_BUTTON_STATE_PRESSED);
 		} else if (touch->focus) {
 			es = (struct weston_surface *) touch->focus;
 			weston_surface_from_global_fixed(es, x, y, &sx, &sy);
@@ -1059,6 +1062,14 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
 		}
 
 		grab->interface->down(grab, time, touch_id, sx, sy);
+		if (seat->num_tp == 1) {
+			touch->grab_serial =
+				wl_display_get_serial(ec->wl_display);
+			touch->grab_time = time;
+			touch->grab_x = x;
+			touch->grab_y = y;
+		}
+
 		break;
 	case WL_TOUCH_MOTION:
 		es = (struct weston_surface *) touch->focus;
diff --git a/src/shell.c b/src/shell.c
index bcde789..265ab0d 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -3008,7 +3008,10 @@ click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t butt
 	struct weston_surface *focus;
 	struct weston_surface *main_surface;
 
-	focus = (struct weston_surface *) seat->pointer->focus;
+	if (button == BTN_LEFT)
+		focus = (struct weston_surface *) seat->pointer->focus;
+	else
+		focus = (struct weston_surface *) seat->touch->focus;
 	if (!focus)
 		return;
 
@@ -4373,6 +4376,9 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
 	weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
 					     click_to_activate_binding,
 					     shell);
+	weston_compositor_add_button_binding(ec, BTN_TOUCH, 0,
+					     click_to_activate_binding,
+					     shell);
 	weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
 				           MODIFIER_SUPER | MODIFIER_ALT,
 				           surface_opacity_binding, NULL);
-- 
1.8.3.1





More information about the wayland-devel mailing list