blob: ab22c8423fb7833e9b35a2a39362d405afda495e [file] [log] [blame]
Peter Maydelle16f4c82016-01-29 17:49:51 +00001#include "qemu/osdep.h"
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +01002#include "sysemu/sysemu.h"
Markus Armbrusterd49b6832015-03-17 18:29:20 +01003#include "qemu/error-report.h"
Gerd Hoffmanne842c682013-12-10 17:09:36 +01004#include "qmp-commands.h"
Gerd Hoffmannc43ce552013-12-04 15:20:05 +01005#include "trace.h"
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +01006#include "ui/input.h"
Gerd Hoffmannc43ce552013-12-04 15:20:05 +01007#include "ui/console.h"
Pavel Dovgalyukee312992015-09-17 19:25:24 +03008#include "sysemu/replay.h"
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +01009
10struct QemuInputHandlerState {
11 DeviceState *dev;
12 QemuInputHandler *handler;
13 int id;
14 int events;
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +020015 QemuConsole *con;
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010016 QTAILQ_ENTRY(QemuInputHandlerState) node;
17};
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +020018
19typedef struct QemuInputEventQueue QemuInputEventQueue;
20struct QemuInputEventQueue {
21 enum {
22 QEMU_INPUT_QUEUE_DELAY = 1,
23 QEMU_INPUT_QUEUE_EVENT,
24 QEMU_INPUT_QUEUE_SYNC,
25 } type;
26 QEMUTimer *timer;
27 uint32_t delay_ms;
28 QemuConsole *src;
29 InputEvent *evt;
30 QTAILQ_ENTRY(QemuInputEventQueue) node;
31};
32
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010033static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
34 QTAILQ_HEAD_INITIALIZER(handlers);
Gerd Hoffmann4a33f452013-12-05 11:23:42 +010035static NotifierList mouse_mode_notifiers =
36 NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010037
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +020038static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
39 QTAILQ_HEAD_INITIALIZER(kbd_queue);
40static QEMUTimer *kbd_timer;
41static uint32_t kbd_default_delay_ms = 10;
Gerd Hoffmannfa18f362017-04-28 10:42:37 +020042static uint32_t queue_count;
43static uint32_t queue_limit = 1024;
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +020044
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010045QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
46 QemuInputHandler *handler)
47{
48 QemuInputHandlerState *s = g_new0(QemuInputHandlerState, 1);
49 static int id = 1;
50
51 s->dev = dev;
52 s->handler = handler;
53 s->id = id++;
54 QTAILQ_INSERT_TAIL(&handlers, s, node);
Gerd Hoffmann4a33f452013-12-05 11:23:42 +010055
56 qemu_input_check_mode_change();
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010057 return s;
58}
59
60void qemu_input_handler_activate(QemuInputHandlerState *s)
61{
62 QTAILQ_REMOVE(&handlers, s, node);
63 QTAILQ_INSERT_HEAD(&handlers, s, node);
Gerd Hoffmann4a33f452013-12-05 11:23:42 +010064 qemu_input_check_mode_change();
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010065}
66
Gerd Hoffmann528728f2014-03-16 00:38:45 +010067void qemu_input_handler_deactivate(QemuInputHandlerState *s)
68{
69 QTAILQ_REMOVE(&handlers, s, node);
70 QTAILQ_INSERT_TAIL(&handlers, s, node);
71 qemu_input_check_mode_change();
72}
73
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010074void qemu_input_handler_unregister(QemuInputHandlerState *s)
75{
76 QTAILQ_REMOVE(&handlers, s, node);
77 g_free(s);
Gerd Hoffmann4a33f452013-12-05 11:23:42 +010078 qemu_input_check_mode_change();
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010079}
80
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +020081void qemu_input_handler_bind(QemuInputHandlerState *s,
82 const char *device_id, int head,
83 Error **errp)
84{
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +020085 QemuConsole *con;
Gerd Hoffmannf2c1d542016-01-12 11:45:43 +010086 Error *err = NULL;
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +020087
Gerd Hoffmannf2c1d542016-01-12 11:45:43 +010088 con = qemu_console_lookup_by_device_name(device_id, head, &err);
89 if (err) {
90 error_propagate(errp, err);
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +020091 return;
92 }
93
94 s->con = con;
95}
96
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010097static QemuInputHandlerState*
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +020098qemu_input_find_handler(uint32_t mask, QemuConsole *con)
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +010099{
100 QemuInputHandlerState *s;
101
102 QTAILQ_FOREACH(s, &handlers, node) {
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +0200103 if (s->con == NULL || s->con != con) {
104 continue;
105 }
106 if (mask & s->handler->mask) {
107 return s;
108 }
109 }
110
111 QTAILQ_FOREACH(s, &handlers, node) {
112 if (s->con != NULL) {
113 continue;
114 }
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +0100115 if (mask & s->handler->mask) {
116 return s;
117 }
118 }
119 return NULL;
120}
121
Gerd Hoffmann6575ccd2016-01-12 12:39:33 +0100122void qmp_input_send_event(bool has_device, const char *device,
123 bool has_head, int64_t head,
124 InputEventList *events, Error **errp)
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300125{
126 InputEventList *e;
127 QemuConsole *con;
Gerd Hoffmannb98d26e2016-01-12 12:11:14 +0100128 Error *err = NULL;
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300129
Amos Kong51fc4472014-11-07 12:41:25 +0800130 con = NULL;
Gerd Hoffmannb98d26e2016-01-12 12:11:14 +0100131 if (has_device) {
132 if (!has_head) {
133 head = 0;
134 }
135 con = qemu_console_lookup_by_device_name(device, head, &err);
136 if (err) {
137 error_propagate(errp, err);
Amos Kong51fc4472014-11-07 12:41:25 +0800138 return;
139 }
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300140 }
141
142 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
143 error_setg(errp, "VM not running");
144 return;
145 }
146
147 for (e = events; e != NULL; e = e->next) {
148 InputEvent *event = e->value;
149
Eric Blake568c73a2015-10-26 16:34:58 -0600150 if (!qemu_input_find_handler(1 << event->type, con)) {
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300151 error_setg(errp, "Input handler not found for "
152 "event type %s",
Markus Armbruster977c7362017-08-24 10:46:08 +0200153 InputEventKind_str(event->type));
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300154 return;
155 }
156 }
157
158 for (e = events; e != NULL; e = e->next) {
Daniel P. Berrangeaf07e5f2017-09-29 11:12:00 +0100159 InputEvent *evt = e->value;
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300160
Daniel P. Berrangeaf07e5f2017-09-29 11:12:00 +0100161 if (evt->type == INPUT_EVENT_KIND_KEY &&
162 evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {
163 KeyValue *key = evt->u.key.data->key;
Daniel P. Berrange237925b2017-10-19 15:28:42 +0100164 QKeyCode code = qemu_input_key_number_to_qcode(key->u.number.data);
Daniel P. Berrangeaf07e5f2017-09-29 11:12:00 +0100165 qemu_input_event_send_key_qcode(con, code, evt->u.key.data->down);
166 } else {
167 qemu_input_event_send(con, evt);
168 }
Marcelo Tosatti50c66172014-09-30 18:10:17 -0300169 }
170
171 qemu_input_event_sync();
172}
173
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200174static int qemu_input_transform_invert_abs_value(int value)
175{
176 return (int64_t)INPUT_EVENT_ABS_MAX - value + INPUT_EVENT_ABS_MIN;
177}
178
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100179static void qemu_input_transform_abs_rotate(InputEvent *evt)
180{
Eric Blake32bafa82016-03-17 16:48:37 -0600181 InputMoveEvent *move = evt->u.abs.data;
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100182 switch (graphic_rotate) {
183 case 90:
Eric Blakeb5a1b442016-03-03 09:16:49 -0700184 if (move->axis == INPUT_AXIS_X) {
185 move->axis = INPUT_AXIS_Y;
186 } else if (move->axis == INPUT_AXIS_Y) {
187 move->axis = INPUT_AXIS_X;
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200188 move->value = qemu_input_transform_invert_abs_value(move->value);
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100189 }
190 break;
191 case 180:
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200192 move->value = qemu_input_transform_invert_abs_value(move->value);
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100193 break;
194 case 270:
Eric Blakeb5a1b442016-03-03 09:16:49 -0700195 if (move->axis == INPUT_AXIS_X) {
196 move->axis = INPUT_AXIS_Y;
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200197 move->value = qemu_input_transform_invert_abs_value(move->value);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700198 } else if (move->axis == INPUT_AXIS_Y) {
199 move->axis = INPUT_AXIS_X;
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100200 }
201 break;
202 }
203}
204
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100205static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
206{
207 const char *name;
Gerd Hoffmann2386a902014-05-21 13:49:59 +0200208 int qcode, idx = -1;
Eric Blakeb5a1b442016-03-03 09:16:49 -0700209 InputKeyEvent *key;
210 InputBtnEvent *btn;
211 InputMoveEvent *move;
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100212
213 if (src) {
214 idx = qemu_console_get_index(src);
215 }
Eric Blake568c73a2015-10-26 16:34:58 -0600216 switch (evt->type) {
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100217 case INPUT_EVENT_KIND_KEY:
Eric Blake32bafa82016-03-17 16:48:37 -0600218 key = evt->u.key.data;
Eric Blakeb5a1b442016-03-03 09:16:49 -0700219 switch (key->key->type) {
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100220 case KEY_VALUE_KIND_NUMBER:
Eric Blake32bafa82016-03-17 16:48:37 -0600221 qcode = qemu_input_key_number_to_qcode(key->key->u.number.data);
Markus Armbruster977c7362017-08-24 10:46:08 +0200222 name = QKeyCode_str(qcode);
Eric Blake32bafa82016-03-17 16:48:37 -0600223 trace_input_event_key_number(idx, key->key->u.number.data,
Eric Blakeb5a1b442016-03-03 09:16:49 -0700224 name, key->down);
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100225 break;
226 case KEY_VALUE_KIND_QCODE:
Markus Armbruster977c7362017-08-24 10:46:08 +0200227 name = QKeyCode_str(key->key->u.qcode.data);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700228 trace_input_event_key_qcode(idx, name, key->down);
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100229 break;
Eric Blake7fb1cf12015-11-18 01:52:57 -0700230 case KEY_VALUE_KIND__MAX:
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100231 /* keep gcc happy */
232 break;
233 }
234 break;
235 case INPUT_EVENT_KIND_BTN:
Eric Blake32bafa82016-03-17 16:48:37 -0600236 btn = evt->u.btn.data;
Markus Armbruster977c7362017-08-24 10:46:08 +0200237 name = InputButton_str(btn->button);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700238 trace_input_event_btn(idx, name, btn->down);
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100239 break;
240 case INPUT_EVENT_KIND_REL:
Eric Blake32bafa82016-03-17 16:48:37 -0600241 move = evt->u.rel.data;
Markus Armbruster977c7362017-08-24 10:46:08 +0200242 name = InputAxis_str(move->axis);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700243 trace_input_event_rel(idx, name, move->value);
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100244 break;
245 case INPUT_EVENT_KIND_ABS:
Eric Blake32bafa82016-03-17 16:48:37 -0600246 move = evt->u.abs.data;
Markus Armbruster977c7362017-08-24 10:46:08 +0200247 name = InputAxis_str(move->axis);
Eric Blakeb5a1b442016-03-03 09:16:49 -0700248 trace_input_event_abs(idx, name, move->value);
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100249 break;
Eric Blake7fb1cf12015-11-18 01:52:57 -0700250 case INPUT_EVENT_KIND__MAX:
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100251 /* keep gcc happy */
252 break;
253 }
254}
255
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200256static void qemu_input_queue_process(void *opaque)
257{
258 struct QemuInputEventQueueHead *queue = opaque;
259 QemuInputEventQueue *item;
260
261 g_assert(!QTAILQ_EMPTY(queue));
262 item = QTAILQ_FIRST(queue);
263 g_assert(item->type == QEMU_INPUT_QUEUE_DELAY);
264 QTAILQ_REMOVE(queue, item, node);
Alexander Graf77b03592017-06-22 09:41:58 +0200265 queue_count--;
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200266 g_free(item);
267
268 while (!QTAILQ_EMPTY(queue)) {
269 item = QTAILQ_FIRST(queue);
270 switch (item->type) {
271 case QEMU_INPUT_QUEUE_DELAY:
272 timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
273 + item->delay_ms);
274 return;
275 case QEMU_INPUT_QUEUE_EVENT:
276 qemu_input_event_send(item->src, item->evt);
277 qapi_free_InputEvent(item->evt);
278 break;
279 case QEMU_INPUT_QUEUE_SYNC:
280 qemu_input_event_sync();
281 break;
282 }
283 QTAILQ_REMOVE(queue, item, node);
Gerd Hoffmannfa18f362017-04-28 10:42:37 +0200284 queue_count--;
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200285 g_free(item);
286 }
287}
288
289static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
290 QEMUTimer *timer, uint32_t delay_ms)
291{
292 QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
293 bool start_timer = QTAILQ_EMPTY(queue);
294
295 item->type = QEMU_INPUT_QUEUE_DELAY;
296 item->delay_ms = delay_ms;
297 item->timer = timer;
298 QTAILQ_INSERT_TAIL(queue, item, node);
Gerd Hoffmannfa18f362017-04-28 10:42:37 +0200299 queue_count++;
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200300
301 if (start_timer) {
302 timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
303 + item->delay_ms);
304 }
305}
306
307static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
308 QemuConsole *src, InputEvent *evt)
309{
310 QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
311
312 item->type = QEMU_INPUT_QUEUE_EVENT;
313 item->src = src;
314 item->evt = evt;
315 QTAILQ_INSERT_TAIL(queue, item, node);
Gerd Hoffmannfa18f362017-04-28 10:42:37 +0200316 queue_count++;
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200317}
318
319static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
320{
321 QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
322
323 item->type = QEMU_INPUT_QUEUE_SYNC;
324 QTAILQ_INSERT_TAIL(queue, item, node);
Gerd Hoffmannfa18f362017-04-28 10:42:37 +0200325 queue_count++;
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200326}
327
Pavel Dovgalyukee312992015-09-17 19:25:24 +0300328void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +0100329{
330 QemuInputHandlerState *s;
331
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100332 qemu_input_event_trace(src, evt);
333
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100334 /* pre processing */
Eric Blake568c73a2015-10-26 16:34:58 -0600335 if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) {
Gerd Hoffmannd3535432013-11-28 11:29:33 +0100336 qemu_input_transform_abs_rotate(evt);
337 }
338
339 /* send event */
Eric Blake568c73a2015-10-26 16:34:58 -0600340 s = qemu_input_find_handler(1 << evt->type, src);
Gerd Hoffmannbdcc3a22014-03-31 16:07:30 +0200341 if (!s) {
342 return;
343 }
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +0100344 s->handler->event(s->dev, src, evt);
345 s->events++;
346}
347
Pavel Dovgalyukee312992015-09-17 19:25:24 +0300348void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +0100349{
Daniel P. Berrangeaf07e5f2017-09-29 11:12:00 +0100350 /* Expect all parts of QEMU to send events with QCodes exclusively.
351 * Key numbers are only supported as end-user input via QMP */
352 assert(!(evt->type == INPUT_EVENT_KIND_KEY &&
353 evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));
354
Daniel P. Berrange80b857f2017-10-19 15:28:47 +0100355
356 /*
357 * 'sysrq' was mistakenly added to hack around the fact that
358 * the ps2 driver was not generating correct scancodes sequences
359 * when 'alt+print' was pressed. This flaw is now fixed and the
360 * 'sysrq' key serves no further purpose. We normalize it to
361 * 'print', so that downstream receivers of the event don't
362 * neeed to deal with this mistake
363 */
364 if (evt->type == INPUT_EVENT_KIND_KEY &&
365 evt->u.key.data->key->u.qcode.data == Q_KEY_CODE_SYSRQ) {
366 evt->u.key.data->key->u.qcode.data = Q_KEY_CODE_PRINT;
367 }
368
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +0100369 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
370 return;
371 }
372
Pavel Dovgalyukee312992015-09-17 19:25:24 +0300373 replay_input_event(src, evt);
374}
375
376void qemu_input_event_sync_impl(void)
377{
378 QemuInputHandlerState *s;
379
Gerd Hoffmannc43ce552013-12-04 15:20:05 +0100380 trace_input_event_sync();
381
Gerd Hoffmannc8b405b2013-11-27 10:35:26 +0100382 QTAILQ_FOREACH(s, &handlers, node) {
383 if (!s->events) {
384 continue;
385 }
386 if (s->handler->sync) {
387 s->handler->sync(s->dev);
388 }
389 s->events = 0;
390 }
391}
Gerd Hoffmann65671472013-11-27 11:38:47 +0100392
Pavel Dovgalyukee312992015-09-17 19:25:24 +0300393void qemu_input_event_sync(void)
394{
395 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
396 return;
397 }
398
399 replay_input_sync_event();
400}
401
Daniel P. Berrange3ad35e72017-09-29 11:12:01 +0100402static InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
Gerd Hoffmann65671472013-11-27 11:38:47 +0100403{
404 InputEvent *evt = g_new0(InputEvent, 1);
Eric Blake32bafa82016-03-17 16:48:37 -0600405 evt->u.key.data = g_new0(InputKeyEvent, 1);
Eric Blake568c73a2015-10-26 16:34:58 -0600406 evt->type = INPUT_EVENT_KIND_KEY;
Eric Blake32bafa82016-03-17 16:48:37 -0600407 evt->u.key.data->key = key;
408 evt->u.key.data->down = down;
Gerd Hoffmann65671472013-11-27 11:38:47 +0100409 return evt;
410}
411
412void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
413{
414 InputEvent *evt;
415 evt = qemu_input_event_new_key(key, down);
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200416 if (QTAILQ_EMPTY(&kbd_queue)) {
417 qemu_input_event_send(src, evt);
418 qemu_input_event_sync();
419 qapi_free_InputEvent(evt);
Gerd Hoffmannfa18f362017-04-28 10:42:37 +0200420 } else if (queue_count < queue_limit) {
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200421 qemu_input_queue_event(&kbd_queue, src, evt);
422 qemu_input_queue_sync(&kbd_queue);
linzhechengfca47742017-12-25 10:37:30 +0800423 } else {
424 qapi_free_InputEvent(evt);
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200425 }
Gerd Hoffmann65671472013-11-27 11:38:47 +0100426}
427
428void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
429{
Daniel P. Berrangeaf07e5f2017-09-29 11:12:00 +0100430 QKeyCode code = qemu_input_key_number_to_qcode(num);
431 qemu_input_event_send_key_qcode(src, code, down);
Gerd Hoffmann65671472013-11-27 11:38:47 +0100432}
433
434void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
435{
436 KeyValue *key = g_new0(KeyValue, 1);
Eric Blake568c73a2015-10-26 16:34:58 -0600437 key->type = KEY_VALUE_KIND_QCODE;
Eric Blake32bafa82016-03-17 16:48:37 -0600438 key->u.qcode.data = q;
Gerd Hoffmann65671472013-11-27 11:38:47 +0100439 qemu_input_event_send_key(src, key, down);
440}
Gerd Hoffmann43579402013-11-27 18:24:29 +0100441
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200442void qemu_input_event_send_key_delay(uint32_t delay_ms)
443{
Marc-André Lureau05c66382017-04-25 17:05:20 +0400444 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
445 return;
446 }
447
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200448 if (!kbd_timer) {
449 kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
450 &kbd_queue);
451 }
Gerd Hoffmannfa18f362017-04-28 10:42:37 +0200452 if (queue_count < queue_limit) {
453 qemu_input_queue_delay(&kbd_queue, kbd_timer,
454 delay_ms ? delay_ms : kbd_default_delay_ms);
455 }
Gerd Hoffmannbe1a7172014-05-28 13:02:40 +0200456}
457
Gerd Hoffmann43579402013-11-27 18:24:29 +0100458InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
459{
460 InputEvent *evt = g_new0(InputEvent, 1);
Eric Blake32bafa82016-03-17 16:48:37 -0600461 evt->u.btn.data = g_new0(InputBtnEvent, 1);
Eric Blake568c73a2015-10-26 16:34:58 -0600462 evt->type = INPUT_EVENT_KIND_BTN;
Eric Blake32bafa82016-03-17 16:48:37 -0600463 evt->u.btn.data->button = btn;
464 evt->u.btn.data->down = down;
Gerd Hoffmann43579402013-11-27 18:24:29 +0100465 return evt;
466}
467
468void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
469{
470 InputEvent *evt;
471 evt = qemu_input_event_new_btn(btn, down);
472 qemu_input_event_send(src, evt);
473 qapi_free_InputEvent(evt);
474}
475
476void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
477 uint32_t button_old, uint32_t button_new)
478{
479 InputButton btn;
480 uint32_t mask;
481
Eric Blake7fb1cf12015-11-18 01:52:57 -0700482 for (btn = 0; btn < INPUT_BUTTON__MAX; btn++) {
Gerd Hoffmann43579402013-11-27 18:24:29 +0100483 mask = button_map[btn];
484 if ((button_old & mask) == (button_new & mask)) {
485 continue;
486 }
487 qemu_input_queue_btn(src, btn, button_new & mask);
488 }
489}
490
Gerd Hoffmann502c8db2013-11-28 11:31:09 +0100491bool qemu_input_is_absolute(void)
492{
493 QemuInputHandlerState *s;
494
Gerd Hoffmann6f5943c2014-05-19 15:18:37 +0200495 s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
496 NULL);
Gerd Hoffmann502c8db2013-11-28 11:31:09 +0100497 return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
498}
499
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200500int qemu_input_scale_axis(int value,
501 int min_in, int max_in,
502 int min_out, int max_out)
Gerd Hoffmann43579402013-11-27 18:24:29 +0100503{
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200504 int64_t range_in = (int64_t)max_in - min_in;
505 int64_t range_out = (int64_t)max_out - min_out;
506
507 if (range_in < 1) {
508 return min_out + range_out / 2;
Gerd Hoffmann43579402013-11-27 18:24:29 +0100509 }
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200510 return ((int64_t)value - min_in) * range_out / range_in + min_out;
Gerd Hoffmann43579402013-11-27 18:24:29 +0100511}
512
513InputEvent *qemu_input_event_new_move(InputEventKind kind,
514 InputAxis axis, int value)
515{
516 InputEvent *evt = g_new0(InputEvent, 1);
517 InputMoveEvent *move = g_new0(InputMoveEvent, 1);
518
Eric Blake568c73a2015-10-26 16:34:58 -0600519 evt->type = kind;
Eric Blake32bafa82016-03-17 16:48:37 -0600520 evt->u.rel.data = move; /* evt->u.rel is the same as evt->u.abs */
Gerd Hoffmann43579402013-11-27 18:24:29 +0100521 move->axis = axis;
522 move->value = value;
523 return evt;
524}
525
526void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
527{
528 InputEvent *evt;
529 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value);
530 qemu_input_event_send(src, evt);
531 qapi_free_InputEvent(evt);
532}
533
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200534void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
535 int min_in, int max_in)
Gerd Hoffmann43579402013-11-27 18:24:29 +0100536{
537 InputEvent *evt;
Philippe Voinov9cfa7ab2017-05-05 15:39:52 +0200538 int scaled = qemu_input_scale_axis(value, min_in, max_in,
539 INPUT_EVENT_ABS_MIN,
540 INPUT_EVENT_ABS_MAX);
Gerd Hoffmann43579402013-11-27 18:24:29 +0100541 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled);
542 qemu_input_event_send(src, evt);
543 qapi_free_InputEvent(evt);
544}
Gerd Hoffmann4a33f452013-12-05 11:23:42 +0100545
546void qemu_input_check_mode_change(void)
547{
548 static int current_is_absolute;
549 int is_absolute;
550
551 is_absolute = qemu_input_is_absolute();
552
553 if (is_absolute != current_is_absolute) {
Gerd Hoffmanna8dfb1c2013-12-05 11:24:14 +0100554 trace_input_mouse_mode(is_absolute);
Gerd Hoffmann4a33f452013-12-05 11:23:42 +0100555 notifier_list_notify(&mouse_mode_notifiers, NULL);
556 }
557
558 current_is_absolute = is_absolute;
559}
560
561void qemu_add_mouse_mode_change_notifier(Notifier *notify)
562{
563 notifier_list_add(&mouse_mode_notifiers, notify);
564}
565
566void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
567{
568 notifier_remove(notify);
569}
Gerd Hoffmanne842c682013-12-10 17:09:36 +0100570
571MouseInfoList *qmp_query_mice(Error **errp)
572{
573 MouseInfoList *mice_list = NULL;
574 MouseInfoList *info;
575 QemuInputHandlerState *s;
576 bool current = true;
577
578 QTAILQ_FOREACH(s, &handlers, node) {
579 if (!(s->handler->mask &
580 (INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS))) {
581 continue;
582 }
583
584 info = g_new0(MouseInfoList, 1);
585 info->value = g_new0(MouseInfo, 1);
586 info->value->index = s->id;
587 info->value->name = g_strdup(s->handler->name);
588 info->value->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
589 info->value->current = current;
590
591 current = false;
592 info->next = mice_list;
593 mice_list = info;
594 }
595
596 return mice_list;
597}
Gerd Hoffmann70b52f62013-12-10 17:16:03 +0100598
Markus Armbruster3e5a50d2015-02-06 13:55:43 +0100599void hmp_mouse_set(Monitor *mon, const QDict *qdict)
Gerd Hoffmann70b52f62013-12-10 17:16:03 +0100600{
601 QemuInputHandlerState *s;
602 int index = qdict_get_int(qdict, "index");
603 int found = 0;
604
605 QTAILQ_FOREACH(s, &handlers, node) {
Hani Benhabiles0419f782014-03-31 23:09:06 +0100606 if (s->id != index) {
607 continue;
Gerd Hoffmann70b52f62013-12-10 17:16:03 +0100608 }
Hani Benhabiles0419f782014-03-31 23:09:06 +0100609 if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
610 INPUT_EVENT_MASK_ABS))) {
611 error_report("Input device '%s' is not a mouse", s->handler->name);
612 return;
613 }
614 found = 1;
615 qemu_input_handler_activate(s);
616 break;
Gerd Hoffmann70b52f62013-12-10 17:16:03 +0100617 }
618
619 if (!found) {
Hani Benhabiles0419f782014-03-31 23:09:06 +0100620 error_report("Mouse at index '%d' not found", index);
Gerd Hoffmann70b52f62013-12-10 17:16:03 +0100621 }
622
623 qemu_input_check_mode_change();
624}