Patchwork [RFC,7/8] ui/input: Introduce MouseOps::get_position()

login
register
mail settings
Submitter Andreas Färber
Date June 16, 2013, 3:40 a.m.
Message ID <1371354005-26873-8-git-send-email-afaerber@suse.de>
Download mbox | patch
Permalink /patch/251653/
State New
Headers show

Comments

Andreas Färber - June 16, 2013, 3:40 a.m.
Traditionally mice have used relative coordinates, so that a mouse event
at (0,0,0) would mean no change of position. However, with absolute
coordinates those coordinates signify the top left corner.

Since the VMState of mice is kept at device level, introduce a callback
to retrieve the current position in a migration-safe way.

For xenfb add state fields for (x,y) coordinates.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 hw/display/ads7846.c |  9 +++++++++
 hw/display/xenfb.c   | 34 ++++++++++++++++++++++++++++++----
 hw/input/hid.c       | 26 +++++++++++++++++++++++++-
 hw/input/tsc2005.c   |  9 +++++++++
 hw/input/tsc210x.c   |  9 +++++++++
 hw/input/vmmouse.c   | 14 ++++++++++++++
 hw/usb/dev-wacom.c   |  9 +++++++++
 include/ui/console.h |  3 +++
 8 files changed, 108 insertions(+), 5 deletions(-)

Patch

diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c
index d8d05e6..a7ee56f 100644
--- a/hw/display/ads7846.c
+++ b/hw/display/ads7846.c
@@ -88,6 +88,14 @@  static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value)
     return s->output;
 }
 
+static void ads7846_ts_get_position(void *opaque, int *x, int *y)
+{
+    ADS7846State *s = opaque;
+
+    *x = 0x7fff - (((s->input[1] - X_AXIS_MIN) << 15) / X_AXIS_DMAX);
+    *y = ((s->input[5] - Y_AXIS_MIN) << 15) / Y_AXIS_DMAX;
+}
+
 static void ads7846_ts_event(void *opaque,
                 int x, int y, int z, int buttons_state)
 {
@@ -143,6 +151,7 @@  static const VMStateDescription vmstate_ads7846 = {
 static const MouseOps ads7846_ts_ops = {
     .put_event = ads7846_ts_event,
     .get_buttons_state = ads7846_ts_get_buttons_state,
+    .get_position = ads7846_ts_get_position,
 };
 
 static int ads7846_init(SSISlave *dev)
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 0d27377..46a2881 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -57,10 +57,19 @@  struct common {
     QemuConsole       *con;
 };
 
+/**
+ * XenInput:
+ * @abs_pointer_wanted: Whether guest supports absolute pointer.
+ * @x: Last pointer X position in QEMU coordinates.
+ * @y: Last pointer Y position in QEMU coordinates.
+ * @button_state: Last seen pointer button state.
+ */
 struct XenInput {
     struct common c;
-    int abs_pointer_wanted; /* Whether guest supports absolute pointer */
-    int button_state;       /* Last seen pointer button state */
+    int abs_pointer_wanted;
+    int x;
+    int y;
+    int button_state;
     int extended;
     QEMUPutMouseEntry *qmouse;
 };
@@ -323,13 +332,16 @@  static void xenfb_mouse_event(void *opaque,
     int dh = surface_height(surface);
     int i;
 
-    if (xenfb->abs_pointer_wanted)
+    if (xenfb->abs_pointer_wanted) {
 	xenfb_send_position(xenfb,
 			    dx * (dw - 1) / 0x7fff,
 			    dy * (dh - 1) / 0x7fff,
 			    dz);
-    else
+        xenfb->x = dx;
+        xenfb->y = dy;
+    } else {
 	xenfb_send_motion(xenfb, dx, dy, dz);
+    }
 
     for (i = 0 ; i < 8 ; i++) {
 	int lastDown = xenfb->button_state & (1 << i);
@@ -350,6 +362,19 @@  static int xenfb_mouse_get_buttons_state(void *opaque)
     return in->button_state;
 }
 
+static void xenfb_mouse_get_position(void *opaque, int *x, int *y)
+{
+    XenInput *in = opaque;
+
+    if (in->abs_pointer_wanted) {
+        *x = in->x;
+        *y = in->y;
+    } else {
+        *x = 0;
+        *y = 0;
+    }
+}
+
 static int input_init(struct XenDevice *xendev)
 {
     xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
@@ -377,6 +402,7 @@  static int input_initialise(struct XenDevice *xendev)
 static const MouseOps xenfb_mouse_ops = {
     .put_event = xenfb_mouse_event,
     .get_buttons_state = xenfb_mouse_get_buttons_state,
+    .get_position = xenfb_mouse_get_position,
 };
 
 static void input_connected(struct XenDevice *xendev)
diff --git a/hw/input/hid.c b/hw/input/hid.c
index ebe6276..37239e5 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -264,6 +264,24 @@  void hid_pointer_activate(HIDState *hs)
     }
 }
 
+static void hid_pointer_get_position(void *opaque, int *x, int *y)
+{
+    HIDState *hs = opaque;
+    int index;
+    HIDPointerEvent *e;
+
+    index = (hs->n ? hs->head : hs->head - 1);
+    e = &hs->ptr.queue[index & QUEUE_MASK];
+
+    if (hs->kind == HID_MOUSE) {
+        *x = 0;
+        *y = 0;
+    } else {
+        *x = e->xdx;
+        *y = e->ydy;
+    }
+}
+
 int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
 {
     int dx, dy, dz, b, l;
@@ -442,6 +460,12 @@  static const MouseOps hid_mouse_ops = {
     .get_buttons_state = hid_pointer_get_buttons_state,
 };
 
+static const MouseOps hid_tablet_ops = {
+    .put_event = hid_pointer_event,
+    .get_buttons_state = hid_pointer_get_buttons_state,
+    .get_position = hid_pointer_get_position,
+};
+
 void hid_init(HIDState *hs, int kind, HIDEventFunc event)
 {
     hs->kind = kind;
@@ -454,7 +478,7 @@  void hid_init(HIDState *hs, int kind, HIDEventFunc event)
                                                         hs, false,
                                                         "QEMU HID Mouse");
     } else if (hs->kind == HID_TABLET) {
-        hs->ptr.eh_entry = qemu_add_mouse_event_handler(&hid_mouse_ops,
+        hs->ptr.eh_entry = qemu_add_mouse_event_handler(&hid_tablet_ops,
                                                         hs, true,
                                                         "QEMU HID Tablet");
     }
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
index ed9f405..c0dbc02 100644
--- a/hw/input/tsc2005.c
+++ b/hw/input/tsc2005.c
@@ -411,6 +411,14 @@  static void tsc2005_timer_tick(void *opaque)
     tsc2005_pin_update(s);
 }
 
+static void tsc2005_touchscreen_get_position(void *opaque, int *x, int *y)
+{
+    TSC2005State *s = opaque;
+
+    *x = s->x;
+    *y = s->y;
+}
+
 static void tsc2005_touchscreen_event(void *opaque,
                 int x, int y, int z, int buttons_state)
 {
@@ -529,6 +537,7 @@  static int tsc2005_load(QEMUFile *f, void *opaque, int version_id)
 static const MouseOps tsc2005_touchscreen_ops = {
     .put_event = tsc2005_touchscreen_event,
     .get_buttons_state = tsc2005_touchscreen_get_buttons_state,
+    .get_position = tsc2005_touchscreen_get_position,
 };
 
 void *tsc2005_init(qemu_irq pintdav)
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
index 593b90d..5faaaf6 100644
--- a/hw/input/tsc210x.c
+++ b/hw/input/tsc210x.c
@@ -967,6 +967,14 @@  static void tsc210x_timer_tick(void *opaque)
     qemu_irq_lower(s->davint);
 }
 
+static void tsc210x_touchscreen_get_position(void *opaque, int *x, int *y)
+{
+    TSC210xState *s = opaque;
+
+    *x = s->x;
+    *y = s->y;
+}
+
 static void tsc210x_touchscreen_event(void *opaque,
                 int x, int y, int z, int buttons_state)
 {
@@ -1110,6 +1118,7 @@  static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
 static const MouseOps tsc210x_touchscreen_ops = {
     .put_event = tsc210x_touchscreen_event,
     .get_buttons_state = tsc210x_touchscreen_get_buttons_state,
+    .get_position = tsc210x_touchscreen_get_position,
 };
 
 uWireSlave *tsc2102_init(qemu_irq pint)
diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c
index dd20f1d..461091a 100644
--- a/hw/input/vmmouse.c
+++ b/hw/input/vmmouse.c
@@ -73,6 +73,19 @@  static uint32_t vmmouse_get_status(VMMouseState *s)
     return (s->status << 16) | s->nb_queue;
 }
 
+static void vmmouse_get_position(void *opaque, int *x, int *y)
+{
+    VMMouseState *s = opaque;
+
+    if (s->absolute && s->nb_queue >= 4) {
+        *x = s->queue[s->nb_queue - 3] >> 1;
+        *y = s->queue[s->nb_queue - 2] >> 1;
+    } else {
+        *x = 0;
+        *y = 0;
+    }
+}
+
 static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_state)
 {
     VMMouseState *s = opaque;
@@ -127,6 +140,7 @@  static void vmmouse_remove_handler(VMMouseState *s)
 static const MouseOps vmmouse_mouse_ops = {
     .put_event = vmmouse_mouse_event,
     .get_buttons_state = vmmouse_get_buttons_state,
+    .get_position = vmmouse_get_position,
 };
 
 static void vmmouse_update_handler(VMMouseState *s, uint8_t absolute)
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 76f75bb..d4ebd9c 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -141,6 +141,14 @@  static void usb_mouse_event(void *opaque,
     usb_wakeup(s->intr, 0);
 }
 
+static void usb_wacom_get_position(void *opaque, int *x, int *y)
+{
+    USBWacomState *s = opaque;
+
+    *x = s->x * 0x7FFF / 5040;
+    *y = s->y * 0x7FFF / 3780;
+}
+
 static void usb_wacom_event(void *opaque,
                             int x, int y, int dz, int buttons_state)
 {
@@ -218,6 +226,7 @@  static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
 static const MouseOps usb_wacom_ops = {
     .put_event = usb_wacom_event,
     .get_buttons_state = usb_mouse_get_buttons_state,
+    .get_position = usb_wacom_get_position,
 };
 
 static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
diff --git a/include/ui/console.h b/include/ui/console.h
index 132591a..d41dd1d 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -30,15 +30,18 @@  typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz,
                                int buttons_state);
 typedef int QEMUGetMouseButtonsState(void *opaque);
+typedef void QEMUGetMousePosition(void *opaque, int *x, int *y);
 
 /**
  * MouseOps:
  * @put_event: Signals a mouse event to a backend.
  * @get_buttons_state: Retrieves mouse buttons state from a backend.
+ * @get_position: Retrieves mouse cursor position from a backend.
  */
 typedef struct MouseOps {
     QEMUPutMouseEvent *put_event;
     QEMUGetMouseButtonsState *get_buttons_state;
+    QEMUGetMousePosition *get_position;
 } MouseOps;
 
 typedef struct QEMUPutMouseEntry QEMUPutMouseEntry;