Hook up axis events.
diff --git a/clients/simple-touch.c b/clients/simple-touch.c
index d93aaaa..b85a841 100644
--- a/clients/simple-touch.c
+++ b/clients/simple-touch.c
@@ -112,6 +112,12 @@
 }
 
 static void
+input_device_handle_axis(void *data, struct wl_input_device *input_device,
+			uint32_t time, uint32_t axis, int32_t value)
+{
+}
+
+static void
 input_device_handle_key(void *data, struct wl_input_device *input_device,
 			uint32_t time, uint32_t key, uint32_t state)
 {
@@ -227,6 +233,7 @@
 static const struct wl_input_device_listener input_device_listener = {
 	input_device_handle_motion,
 	input_device_handle_button,
+	input_device_handle_axis,
 	input_device_handle_key,
 	input_device_handle_pointer_enter,
 	input_device_handle_pointer_leave,
diff --git a/clients/window.c b/clients/window.c
index 5d33a3c..49b0188 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -1521,6 +1521,13 @@
 }
 
 static void
+input_handle_axis(void *data,
+		    struct wl_input_device *input_device,
+		    uint32_t time, uint32_t axis, int32_t value)
+{
+}
+
+static void
 input_handle_key(void *data, struct wl_input_device *input_device,
 		 uint32_t time, uint32_t key, uint32_t state)
 {
@@ -1690,6 +1697,7 @@
 static const struct wl_input_device_listener input_device_listener = {
 	input_handle_motion,
 	input_handle_button,
+	input_handle_axis,
 	input_handle_key,
 	input_handle_pointer_enter,
 	input_handle_pointer_leave,
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 1baf55e..0f4d4ad 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -520,6 +520,16 @@
 }
 
 static void
+input_handle_axis(void *data, struct wl_input_device *input_device,
+			uint32_t time, uint32_t axis, int32_t value)
+{
+	struct wayland_input *input = data;
+	struct wayland_compositor *c = input->compositor;
+
+	notify_axis(c->base.input_device, time, axis, value);
+}
+
+static void
 input_handle_key(void *data, struct wl_input_device *input_device,
 		  uint32_t time, uint32_t key, uint32_t state)
 {
@@ -586,6 +596,7 @@
 static const struct wl_input_device_listener input_device_listener = {
 	input_handle_motion,
 	input_handle_button,
+	input_handle_axis,
 	input_handle_key,
 	input_handle_pointer_enter,
 	input_handle_pointer_leave,
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 0b7da9b..119c456 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -485,14 +485,28 @@
 		button = BTN_RIGHT;
 		break;
 	case 4:
+		if (state)
+			notify_axis(c->base.input_device,
+				      weston_compositor_get_time(),
+				      WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, 1);
+		return;
 	case 5:
+		if (state)
+			notify_axis(c->base.input_device,
+				      weston_compositor_get_time(),
+				      WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, -1);
+		return;
 	case 6:
+		if (state)
+			notify_axis(c->base.input_device,
+				      weston_compositor_get_time(),
+				      WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, 1);
+		return;
 	case 7:
-		/* X11 sends wheel events as buttons events.  But
-		 * linux input treats as REL_WHEEL, therefore not
-		 * button type at all. When we update the input
-		 * protocol and get the 'axis' event, we'll send
-		 * scroll events as axis events. */
+		if (state)
+			notify_axis(c->base.input_device,
+				      weston_compositor_get_time(),
+				      WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, -1);
 		return;
 	}
 
diff --git a/src/compositor.c b/src/compositor.c
index c8ac59c..72e5277 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1549,6 +1549,20 @@
 
 }
 
+WL_EXPORT void
+notify_axis(struct wl_input_device *device,
+	      uint32_t time, uint32_t axis, int32_t value)
+{
+	struct weston_input_device *wd = (struct weston_input_device *) device;
+	struct weston_compositor *compositor = wd->compositor;
+
+	weston_compositor_activity(compositor);
+
+	if (device->pointer_focus_resource)
+		wl_resource_post_event(device->pointer_focus_resource,
+				WL_INPUT_DEVICE_AXIS, time, axis, value);
+}
+
 static void
 update_modifier_state(struct weston_input_device *device,
 		      uint32_t key, uint32_t state)
diff --git a/src/compositor.h b/src/compositor.h
index ae680ed..1141c2f 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -370,6 +370,9 @@
 notify_button(struct wl_input_device *device,
 	      uint32_t time, int32_t button, int32_t state);
 void
+notify_axis(struct wl_input_device *device,
+	      uint32_t time, uint32_t axis, int32_t value);
+void
 notify_key(struct wl_input_device *device,
 	   uint32_t time, uint32_t key, uint32_t state);
 
diff --git a/src/evdev.c b/src/evdev.c
index e0a5966..8642f51 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -227,8 +227,8 @@
 }
 
 static inline void
-evdev_process_relative_motion(struct evdev_input_device *device,
-			      struct input_event *e)
+evdev_process_relative(struct evdev_input_device *device,
+			      struct input_event *e, uint32_t time)
 {
 	switch (e->code) {
 	case REL_X:
@@ -239,6 +239,16 @@
 		device->rel.dy += e->value;
 		device->type |= EVDEV_RELATIVE_MOTION;
 		break;
+	case REL_WHEEL:
+		notify_axis(&device->master->base.input_device,
+			      time,
+			      WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, e->value);
+		break;
+	case REL_HWHEEL:
+		notify_axis(&device->master->base.input_device,
+			      time,
+			      WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, e->value);
+		break;
 	}
 }
 
@@ -344,7 +354,7 @@
 			evdev_flush_motion(device, time);
 		switch (e->type) {
 		case EV_REL:
-			evdev_process_relative_motion(device, e);
+			evdev_process_relative(device, e, time);
 			break;
 		case EV_ABS:
 			evdev_process_absolute(device, e);