input: Make pointer grab motion callbacks take an event struct

Instead of only passing absolute pointer coordinates, effectively
loosing motion event data, pass a struct that can potentially contain
different types of motion events, currently being absolute and relative.

A helper function to get resulting absolute coordinates was added for
when previous callbacks simply used the (x, y) coordinates.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
diff --git a/src/input.c b/src/input.c
index 09d12de..53e84a0 100644
--- a/src/input.c
+++ b/src/input.c
@@ -167,17 +167,20 @@
 
 static void
 default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
-			    wl_fixed_t x, wl_fixed_t y)
+			    struct weston_pointer_motion_event *event)
 {
 	struct weston_pointer *pointer = grab->pointer;
 	struct wl_list *resource_list;
 	struct wl_resource *resource;
+	wl_fixed_t x, y;
 
-	if (pointer->focus)
+	if (pointer->focus) {
+		weston_pointer_motion_to_abs(pointer, event, &x, &y);
 		weston_view_from_global_fixed(pointer->focus, x, y,
 					      &pointer->sx, &pointer->sy);
+	}
 
-	weston_pointer_move(pointer, x, y);
+	weston_pointer_move(pointer, event);
 
 	resource_list = &pointer->focus_resource_list;
 	wl_resource_for_each(resource, resource_list) {
@@ -936,9 +939,9 @@
 		weston_pointer_clamp_for_output(pointer, prev, fx, fy);
 }
 
-/* Takes absolute values */
-WL_EXPORT void
-weston_pointer_move(struct weston_pointer *pointer, wl_fixed_t x, wl_fixed_t y)
+static void
+weston_pointer_move_to(struct weston_pointer *pointer,
+		       wl_fixed_t x, wl_fixed_t y)
 {
 	int32_t ix, iy;
 
@@ -961,6 +964,33 @@
 	wl_signal_emit(&pointer->motion_signal, pointer);
 }
 
+WL_EXPORT void
+weston_pointer_motion_to_abs(struct weston_pointer *pointer,
+			     struct weston_pointer_motion_event *event,
+			     wl_fixed_t *x, wl_fixed_t *y)
+{
+	if (event->mask & WESTON_POINTER_MOTION_ABS) {
+		*x = wl_fixed_from_double(event->x);
+		*y = wl_fixed_from_double(event->y);
+	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
+		*x = pointer->x + wl_fixed_from_double(event->dx);
+		*y = pointer->y + wl_fixed_from_double(event->dy);
+	} else {
+		assert(!"invalid motion event");
+		*x = *y = 0;
+	}
+}
+
+WL_EXPORT void
+weston_pointer_move(struct weston_pointer *pointer,
+		    struct weston_pointer_motion_event *event)
+{
+	wl_fixed_t x, y;
+
+	weston_pointer_motion_to_abs(pointer, event, &x, &y);
+	weston_pointer_move_to(pointer, x, y);
+}
+
 /** Verify if the pointer is in a valid position and move it if it isn't.
  */
 static void
@@ -1002,18 +1032,19 @@
 	fy = pointer->y;
 
 	weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
-	weston_pointer_move(pointer, fx, fy);
+	weston_pointer_move_to(pointer, fx, fy);
 }
 
 WL_EXPORT void
 notify_motion(struct weston_seat *seat,
-	      uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
+	      uint32_t time,
+	      struct weston_pointer_motion_event *event)
 {
 	struct weston_compositor *ec = seat->compositor;
 	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
 
 	weston_compositor_wake(ec);
-	pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
+	pointer->grab->interface->motion(pointer->grab, time, event);
 }
 
 static void
@@ -1058,9 +1089,17 @@
 {
 	struct weston_compositor *ec = seat->compositor;
 	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+	struct weston_pointer_motion_event event = { 0 };
 
 	weston_compositor_wake(ec);
-	pointer->grab->interface->motion(pointer->grab, time, x, y);
+
+	event = (struct weston_pointer_motion_event) {
+		.mask = WESTON_POINTER_MOTION_ABS,
+		.x = wl_fixed_to_double(x),
+		.y = wl_fixed_to_double(y),
+	};
+
+	pointer->grab->interface->motion(pointer->grab, time, &event);
 }
 
 WL_EXPORT void
@@ -1439,7 +1478,7 @@
 	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
 
 	if (output) {
-		weston_pointer_move(pointer, x, y);
+		weston_pointer_move_to(pointer, x, y);
 	} else {
 		/* FIXME: We should call weston_pointer_set_focus(seat,
 		 * NULL) here, but somehow that breaks re-entry... */