spice: add tablet support
[qemu/kraxel.git] / spice-input.c
blob5646ff90b68505ab58d5adb77e29fb8e6768ac61
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdbool.h>
4 #include <string.h>
6 #include <spice.h>
8 #include "qemu-common.h"
9 #include "qemu-spice.h"
10 #include "console.h"
12 /* keyboard bits */
14 typedef struct QemuSpiceKbd {
15 SpiceKbdInstance sin;
16 int ledstate;
17 } QemuSpiceKbd;
19 static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag);
20 static uint8_t kbd_get_leds(SpiceKbdInstance *sin);
21 static void kbd_leds(void *opaque, int l);
23 static const SpiceKbdInterface kbd_interface = {
24 .base.type = SPICE_INTERFACE_KEYBOARD,
25 .base.description = "qemu keyboard",
26 .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR,
27 .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
28 .push_scan_freg = kbd_push_key,
29 .get_leds = kbd_get_leds,
32 static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
34 kbd_put_keycode(frag);
37 static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
39 QemuSpiceKbd *kbd = container_of(sin, QemuSpiceKbd, sin);
40 return kbd->ledstate;
43 static void kbd_leds(void *opaque, int ledstate)
45 QemuSpiceKbd *kbd = opaque;
46 kbd->ledstate = ledstate;
47 spice_server_kbd_leds(&kbd->sin, ledstate);
50 /* mouse bits */
52 typedef struct QemuSpicePointer {
53 SpiceMouseInstance mouse;
54 SpiceTabletInstance tablet;
55 int width, height, x, y;
56 Notifier mouse_mode;
57 bool absolute;
58 } QemuSpicePointer;
60 static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
61 uint32_t buttons_state)
63 kbd_mouse_event(dx, dy, dz, buttons_state);
66 static void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state)
68 kbd_mouse_event(0, 0, 0, buttons_state);
71 static const SpiceMouseInterface mouse_interface = {
72 .base.type = SPICE_INTERFACE_MOUSE,
73 .base.description = "mouse",
74 .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR,
75 .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR,
76 .motion = mouse_motion,
77 .buttons = mouse_buttons,
80 static void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height)
82 QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
84 fprintf(stderr, "%s: %dx%d\n", __FUNCTION__, width, height);
85 if (height < 16)
86 height = 16;
87 if (width < 16)
88 width = 16;
89 pointer->width = width;
90 pointer->height = height;
93 static void tablet_position(SpiceTabletInstance* sin, int x, int y,
94 uint32_t buttons_state)
96 QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
98 pointer->x = x * 0x7FFF / (pointer->width - 1);
99 pointer->y = y * 0x7FFF / (pointer->height - 1);
100 kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
104 static void tablet_wheel(SpiceTabletInstance* sin, int wheel,
105 uint32_t buttons_state)
107 QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
109 kbd_mouse_event(pointer->x, pointer->y, wheel, buttons_state);
112 static void tablet_buttons(SpiceTabletInstance *sin,
113 uint32_t buttons_state)
115 QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
117 kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
120 static const SpiceTabletInterface tablet_interface = {
121 .base.type = SPICE_INTERFACE_TABLET,
122 .base.description = "tablet",
123 .base.major_version = SPICE_INTERFACE_TABLET_MAJOR,
124 .base.minor_version = SPICE_INTERFACE_TABLET_MINOR,
125 .set_logical_size = tablet_set_logical_size,
126 .position = tablet_position,
127 .wheel = tablet_wheel,
128 .buttons = tablet_buttons,
131 static void mouse_mode_notifier(Notifier *notifier)
133 QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode);
134 bool is_absolute = kbd_mouse_is_absolute();
135 bool has_absolute = kbd_mouse_has_absolute();
137 fprintf(stderr, "%s: absolute pointer: %s%s\n", __FUNCTION__,
138 has_absolute ? "present" : "not available",
139 is_absolute ? "+active" : "");
141 if (pointer->absolute == is_absolute)
142 return;
144 if (is_absolute) {
145 fprintf(stderr, "%s: using absolute pointer (client mode)\n", __FUNCTION__);
146 spice_server_add_interface(spice_server, &pointer->tablet.base);
147 } else {
148 fprintf(stderr, "%s: using relative pointer (server mode)\n", __FUNCTION__);
149 spice_server_remove_interface(&pointer->tablet.base);
151 pointer->absolute = is_absolute;
154 void qemu_spice_input_init(void)
156 QemuSpiceKbd *kbd;
157 QemuSpicePointer *pointer;
159 kbd = qemu_mallocz(sizeof(*kbd));
160 kbd->sin.base.sif = &kbd_interface.base;
161 spice_server_add_interface(spice_server, &kbd->sin.base);
162 qemu_add_led_event_handler(kbd_leds, kbd);
164 pointer = qemu_mallocz(sizeof(*pointer));
165 pointer->mouse.base.sif = &mouse_interface.base;
166 pointer->tablet.base.sif = &tablet_interface.base;
167 spice_server_add_interface(spice_server, &pointer->mouse.base);
169 pointer->absolute = false;
170 pointer->mouse_mode.notify = mouse_mode_notifier;
171 qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode);
172 mouse_mode_notifier(&pointer->mouse_mode);