From 3a67f1fa10df7aab7c1389aa781224613de401aa Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 24 Mar 2010 08:43:12 -0300 Subject: [PATCH 01/14] spice: add tablet RH-Author: Gerd Hoffmann Message-id: <1269420192-16481-1-git-send-email-kraxel@redhat.com> Patchwork-id: 8082 O-Subject: [RHEL-6 kvm PATCH v3] spice: add tablet Bugzilla: 574211 RH-Acked-by: Yonit Halperin RH-Acked-by: Alexander Larsson RH-Acked-by: Juan Quintela Open tablet channel. Absolute positioning (aka client mouse mode) works now. As soon as the guest activates the usb tablet the switchover happens automatically. [ update: Register spice tablet interface only in case we see the guest using a absolute pointing device (aka usb tablet) instead of doing it unconditionally. ] [ v2: make have_tablet bool ] [ v3: more have_tablet bool fixes ] bugzilla: #574211 -- spice: add tablet support Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 1 + qemu-spice.h | 1 + spice-display.c | 1 + spice-input.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 0 deletions(-) Signed-off-by: Eduardo Habkost --- hw/qxl.c | 1 + qemu-spice.h | 1 + spice-display.c | 1 + spice-input.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 0 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 732c546..233fb66 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -816,6 +816,7 @@ static void qxl_display_resize(struct DisplayState *ds) pthread_mutex_unlock(&dirty_lock); } } + qemu_spice_tablet_size(ds_get_width(ds), ds_get_height(ds)); } static void qxl_display_refresh(struct DisplayState *ds) diff --git a/qemu-spice.h b/qemu-spice.h index 3071160..4d3e837 100644 --- a/qemu-spice.h +++ b/qemu-spice.h @@ -13,6 +13,7 @@ extern int using_spice; void qemu_spice_init(void); void qemu_spice_input_init(SpiceServer *s); +void qemu_spice_tablet_size(int width, int height); void qemu_spice_display_init(DisplayState *ds); void qxl_display_init(DisplayState *ds); diff --git a/spice-display.c b/spice-display.c index 54c7663..a3441ab 100644 --- a/spice-display.c +++ b/spice-display.c @@ -139,6 +139,7 @@ static void spice_display_resize(struct DisplayState *ds) sdpy.is_attached = 1; sdpy.worker->attach(sdpy.worker); } + qemu_spice_tablet_size(ds_get_width(ds), ds_get_height(ds)); } static void spice_display_refresh(struct DisplayState *ds) diff --git a/spice-input.c b/spice-input.c index 56a1c8c..f8454fc 100644 --- a/spice-input.c +++ b/spice-input.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -11,7 +12,11 @@ /* keyboard bits */ static int ledstate; +static bool have_tablet; +static SpiceServer *spice_state; +static int abs_x, abs_y, abs_width, abs_height; +static void qemu_spice_tablet_mode(bool enabled); static void kbd_push_scan_freg(KeyboardInterface *keyboard, uint8_t frag); static uint8_t kbd_get_leds(KeyboardInterface *keyboard); static void kbd_leds(void *opaque, int l); @@ -48,6 +53,14 @@ static void kbd_leds(void *opaque, int l) static void mouse_motion(MouseInterface* mouse, int dx, int dy, int dz, uint32_t buttons_state) { + if (kbd_mouse_is_absolute()) { + /* + * We'll arrive here when the guest activates some input + * device with absolute positioning, i.e. usb tablet. + */ + qemu_spice_tablet_mode(true); + return; + } kbd_mouse_event(dx, dy, dz, buttons_state); } @@ -66,9 +79,77 @@ static MouseInterface mouse_interface = { .buttons = mouse_buttons, }; +/* tablet bits */ + +static void tablet_set_logical_size(TabletInterface* interface, int width, int height) +{ + abs_width = width; + abs_height = height; +} + +static void tablet_position(TabletInterface *interface, int x, int y, + uint32_t buttons_state) +{ + if (!kbd_mouse_is_absolute()) { + qemu_spice_tablet_mode(false); + return; + } + abs_x = x * 0x7FFF / (abs_width - 1); + abs_y = y * 0x7FFF / (abs_height - 1); + kbd_mouse_event(abs_x, abs_y, 0, buttons_state); +} + + +static void tablet_wheel(TabletInterface *interface, int wheel, + uint32_t buttons_state) +{ + kbd_mouse_event(abs_x, abs_y, wheel, buttons_state); +} + +static void tablet_buttons(TabletInterface *interface, + uint32_t buttons_state) +{ + kbd_mouse_event(abs_x, abs_y, 0, buttons_state); +} + +static TabletInterface tablet_interface = { + .base.base_version = VM_INTERFACE_VERSION, + .base.type = VD_INTERFACE_TABLET, + .base.description = "tablet", + .base.major_version = VD_INTERFACE_TABLET_MAJOR, + .base.minor_version = VD_INTERFACE_TABLET_MINOR, + .set_logical_size = tablet_set_logical_size, + .position = tablet_position, + .wheel = tablet_wheel, + .buttons = tablet_buttons, +}; + void qemu_spice_input_init(SpiceServer *s) { + spice_state = s; qemu_add_led_event_handler(kbd_leds, s); qemu_spice_add_interface(&kbd_interface.base); qemu_spice_add_interface(&mouse_interface.base); } + +static void qemu_spice_tablet_mode(bool enabled) +{ + if (enabled) { + if (!have_tablet) { + qemu_spice_add_interface(&tablet_interface.base); + have_tablet = true; + } + spice_server_set_mouse_absolute(spice_state, 1); + } else { + if (have_tablet) { + qemu_spice_remove_interface(&tablet_interface.base); + have_tablet = false; + } + spice_server_set_mouse_absolute(spice_state, 0); + } +} + +void qemu_spice_tablet_size(int width, int height) +{ + tablet_set_logical_size(&tablet_interface, width, height); +} -- 1.6.3.rc4.29.g8146