blob: fd2293b39903d63d483e008b492b59fcf011bd9c [file] [log] [blame]
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +01001#include "sysemu/sysemu.h"
2#include "qapi-types.h"
3#include "ui/input.h"
4
5struct QemuInputHandlerState {
6 DeviceState *dev;
7 QemuInputHandler *handler;
8 int id;
9 int events;
10 QTAILQ_ENTRY(QemuInputHandlerState) node;
11};
12static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
13 QTAILQ_HEAD_INITIALIZER(handlers);
14
15QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
16 QemuInputHandler *handler)
17{
18 QemuInputHandlerState *s = g_new0(QemuInputHandlerState, 1);
19 static int id = 1;
20
21 s->dev = dev;
22 s->handler = handler;
23 s->id = id++;
24 QTAILQ_INSERT_TAIL(&handlers, s, node);
25 return s;
26}
27
28void qemu_input_handler_activate(QemuInputHandlerState *s)
29{
30 QTAILQ_REMOVE(&handlers, s, node);
31 QTAILQ_INSERT_HEAD(&handlers, s, node);
32}
33
34void qemu_input_handler_unregister(QemuInputHandlerState *s)
35{
36 QTAILQ_REMOVE(&handlers, s, node);
37 g_free(s);
38}
39
40static QemuInputHandlerState*
41qemu_input_find_handler(uint32_t mask)
42{
43 QemuInputHandlerState *s;
44
45 QTAILQ_FOREACH(s, &handlers, node) {
46 if (mask & s->handler->mask) {
47 return s;
48 }
49 }
50 return NULL;
51}
52
Gerd Hoffmannd3535432013-11-28 11:29:33 +010053static void qemu_input_transform_abs_rotate(InputEvent *evt)
54{
55 switch (graphic_rotate) {
56 case 90:
57 if (evt->abs->axis == INPUT_AXIS_X) {
58 evt->abs->axis = INPUT_AXIS_Y;
59 } else if (evt->abs->axis == INPUT_AXIS_Y) {
60 evt->abs->axis = INPUT_AXIS_X;
61 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value;
62 }
63 break;
64 case 180:
65 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value;
66 break;
67 case 270:
68 if (evt->abs->axis == INPUT_AXIS_X) {
69 evt->abs->axis = INPUT_AXIS_Y;
70 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value;
71 } else if (evt->abs->axis == INPUT_AXIS_Y) {
72 evt->abs->axis = INPUT_AXIS_X;
73 }
74 break;
75 }
76}
77
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010078void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
79{
80 QemuInputHandlerState *s;
81
82 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
83 return;
84 }
85
Gerd Hoffmannd3535432013-11-28 11:29:33 +010086 /* pre processing */
87 if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) {
88 qemu_input_transform_abs_rotate(evt);
89 }
90
91 /* send event */
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010092 s = qemu_input_find_handler(1 << evt->kind);
93 s->handler->event(s->dev, src, evt);
94 s->events++;
95}
96
97void qemu_input_event_sync(void)
98{
99 QemuInputHandlerState *s;
100
101 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
102 return;
103 }
104
105 QTAILQ_FOREACH(s, &handlers, node) {
106 if (!s->events) {
107 continue;
108 }
109 if (s->handler->sync) {
110 s->handler->sync(s->dev);
111 }
112 s->events = 0;
113 }
114}
Gerd Hoffmann65671472013-11-27 11:38:47 +0100115
116InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
117{
118 InputEvent *evt = g_new0(InputEvent, 1);
119 evt->key = g_new0(InputKeyEvent, 1);
120 evt->kind = INPUT_EVENT_KIND_KEY;
121 evt->key->key = key;
122 evt->key->down = down;
123 return evt;
124}
125
126void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
127{
128 InputEvent *evt;
129 evt = qemu_input_event_new_key(key, down);
130 qemu_input_event_send(src, evt);
131 qemu_input_event_sync();
132 qapi_free_InputEvent(evt);
133}
134
135void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
136{
137 KeyValue *key = g_new0(KeyValue, 1);
138 key->kind = KEY_VALUE_KIND_NUMBER;
139 key->number = num;
140 qemu_input_event_send_key(src, key, down);
141}
142
143void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
144{
145 KeyValue *key = g_new0(KeyValue, 1);
146 key->kind = KEY_VALUE_KIND_QCODE;
147 key->qcode = q;
148 qemu_input_event_send_key(src, key, down);
149}
Gerd Hoffmann43579402013-11-27 18:24:29 +0100150
151InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
152{
153 InputEvent *evt = g_new0(InputEvent, 1);
154 evt->btn = g_new0(InputBtnEvent, 1);
155 evt->kind = INPUT_EVENT_KIND_BTN;
156 evt->btn->button = btn;
157 evt->btn->down = down;
158 return evt;
159}
160
161void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
162{
163 InputEvent *evt;
164 evt = qemu_input_event_new_btn(btn, down);
165 qemu_input_event_send(src, evt);
166 qapi_free_InputEvent(evt);
167}
168
169void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
170 uint32_t button_old, uint32_t button_new)
171{
172 InputButton btn;
173 uint32_t mask;
174
175 for (btn = 0; btn < INPUT_BUTTON_MAX; btn++) {
176 mask = button_map[btn];
177 if ((button_old & mask) == (button_new & mask)) {
178 continue;
179 }
180 qemu_input_queue_btn(src, btn, button_new & mask);
181 }
182}
183
184int qemu_input_scale_axis(int value, int size_in, int size_out)
185{
186 if (size_in < 2) {
187 return size_out / 2;
188 }
189 return (int64_t)value * (size_out - 1) / (size_in - 1);
190}
191
192InputEvent *qemu_input_event_new_move(InputEventKind kind,
193 InputAxis axis, int value)
194{
195 InputEvent *evt = g_new0(InputEvent, 1);
196 InputMoveEvent *move = g_new0(InputMoveEvent, 1);
197
198 evt->kind = kind;
199 evt->data = move;
200 move->axis = axis;
201 move->value = value;
202 return evt;
203}
204
205void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
206{
207 InputEvent *evt;
208 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value);
209 qemu_input_event_send(src, evt);
210 qapi_free_InputEvent(evt);
211}
212
213void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size)
214{
215 InputEvent *evt;
216 int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE);
217 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled);
218 qemu_input_event_send(src, evt);
219 qapi_free_InputEvent(evt);
220}