1 #include "qemu/osdep.h"
3 #include "sysemu/sysemu.h"
4 #include "qapi-types.h"
5 #include "qemu/error-report.h"
6 #include "qmp-commands.h"
9 #include "ui/console.h"
10 #include "sysemu/replay.h"
12 struct QemuInputHandlerState
{
14 QemuInputHandler
*handler
;
18 QTAILQ_ENTRY(QemuInputHandlerState
) node
;
21 typedef struct QemuInputEventQueue QemuInputEventQueue
;
22 struct QemuInputEventQueue
{
24 QEMU_INPUT_QUEUE_DELAY
= 1,
25 QEMU_INPUT_QUEUE_EVENT
,
26 QEMU_INPUT_QUEUE_SYNC
,
32 QTAILQ_ENTRY(QemuInputEventQueue
) node
;
35 static QTAILQ_HEAD(, QemuInputHandlerState
) handlers
=
36 QTAILQ_HEAD_INITIALIZER(handlers
);
37 static NotifierList mouse_mode_notifiers
=
38 NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers
);
40 static QTAILQ_HEAD(QemuInputEventQueueHead
, QemuInputEventQueue
) kbd_queue
=
41 QTAILQ_HEAD_INITIALIZER(kbd_queue
);
42 static QEMUTimer
*kbd_timer
;
43 static uint32_t kbd_default_delay_ms
= 10;
45 QemuInputHandlerState
*qemu_input_handler_register(DeviceState
*dev
,
46 QemuInputHandler
*handler
)
48 QemuInputHandlerState
*s
= g_new0(QemuInputHandlerState
, 1);
54 QTAILQ_INSERT_TAIL(&handlers
, s
, node
);
56 qemu_input_check_mode_change();
60 void qemu_input_handler_activate(QemuInputHandlerState
*s
)
62 QTAILQ_REMOVE(&handlers
, s
, node
);
63 QTAILQ_INSERT_HEAD(&handlers
, s
, node
);
64 qemu_input_check_mode_change();
67 void qemu_input_handler_deactivate(QemuInputHandlerState
*s
)
69 QTAILQ_REMOVE(&handlers
, s
, node
);
70 QTAILQ_INSERT_TAIL(&handlers
, s
, node
);
71 qemu_input_check_mode_change();
74 void qemu_input_handler_unregister(QemuInputHandlerState
*s
)
76 QTAILQ_REMOVE(&handlers
, s
, node
);
78 qemu_input_check_mode_change();
81 void qemu_input_handler_bind(QemuInputHandlerState
*s
,
82 const char *device_id
, int head
,
88 con
= qemu_console_lookup_by_device_name(device_id
, head
, &err
);
90 error_propagate(errp
, err
);
97 static QemuInputHandlerState
*
98 qemu_input_find_handler(uint32_t mask
, QemuConsole
*con
)
100 QemuInputHandlerState
*s
;
102 QTAILQ_FOREACH(s
, &handlers
, node
) {
103 if (s
->con
== NULL
|| s
->con
!= con
) {
106 if (mask
& s
->handler
->mask
) {
111 QTAILQ_FOREACH(s
, &handlers
, node
) {
112 if (s
->con
!= NULL
) {
115 if (mask
& s
->handler
->mask
) {
122 void qmp_input_send_event(bool has_device
, const char *device
,
123 bool has_head
, int64_t head
,
124 InputEventList
*events
, Error
**errp
)
135 con
= qemu_console_lookup_by_device_name(device
, head
, &err
);
137 error_propagate(errp
, err
);
142 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED
)) {
143 error_setg(errp
, "VM not running");
147 for (e
= events
; e
!= NULL
; e
= e
->next
) {
148 InputEvent
*event
= e
->value
;
150 if (!qemu_input_find_handler(1 << event
->type
, con
)) {
151 error_setg(errp
, "Input handler not found for "
153 InputEventKind_lookup
[event
->type
]);
158 for (e
= events
; e
!= NULL
; e
= e
->next
) {
159 InputEvent
*event
= e
->value
;
161 qemu_input_event_send(con
, event
);
164 qemu_input_event_sync();
167 static void qemu_input_transform_abs_rotate(InputEvent
*evt
)
169 InputMoveEvent
*move
= evt
->u
.abs
.data
;
170 switch (graphic_rotate
) {
172 if (move
->axis
== INPUT_AXIS_X
) {
173 move
->axis
= INPUT_AXIS_Y
;
174 } else if (move
->axis
== INPUT_AXIS_Y
) {
175 move
->axis
= INPUT_AXIS_X
;
176 move
->value
= INPUT_EVENT_ABS_SIZE
- 1 - move
->value
;
180 move
->value
= INPUT_EVENT_ABS_SIZE
- 1 - move
->value
;
183 if (move
->axis
== INPUT_AXIS_X
) {
184 move
->axis
= INPUT_AXIS_Y
;
185 move
->value
= INPUT_EVENT_ABS_SIZE
- 1 - move
->value
;
186 } else if (move
->axis
== INPUT_AXIS_Y
) {
187 move
->axis
= INPUT_AXIS_X
;
193 static void qemu_input_event_trace(QemuConsole
*src
, InputEvent
*evt
)
199 InputMoveEvent
*move
;
202 idx
= qemu_console_get_index(src
);
205 case INPUT_EVENT_KIND_KEY
:
206 key
= evt
->u
.key
.data
;
207 switch (key
->key
->type
) {
208 case KEY_VALUE_KIND_NUMBER
:
209 qcode
= qemu_input_key_number_to_qcode(key
->key
->u
.number
.data
);
210 name
= QKeyCode_lookup
[qcode
];
211 trace_input_event_key_number(idx
, key
->key
->u
.number
.data
,
214 case KEY_VALUE_KIND_QCODE
:
215 name
= QKeyCode_lookup
[key
->key
->u
.qcode
.data
];
216 trace_input_event_key_qcode(idx
, name
, key
->down
);
218 case KEY_VALUE_KIND__MAX
:
223 case INPUT_EVENT_KIND_BTN
:
224 btn
= evt
->u
.btn
.data
;
225 name
= InputButton_lookup
[btn
->button
];
226 trace_input_event_btn(idx
, name
, btn
->down
);
228 case INPUT_EVENT_KIND_REL
:
229 move
= evt
->u
.rel
.data
;
230 name
= InputAxis_lookup
[move
->axis
];
231 trace_input_event_rel(idx
, name
, move
->value
);
233 case INPUT_EVENT_KIND_ABS
:
234 move
= evt
->u
.abs
.data
;
235 name
= InputAxis_lookup
[move
->axis
];
236 trace_input_event_abs(idx
, name
, move
->value
);
238 case INPUT_EVENT_KIND__MAX
:
244 static void qemu_input_queue_process(void *opaque
)
246 struct QemuInputEventQueueHead
*queue
= opaque
;
247 QemuInputEventQueue
*item
;
249 g_assert(!QTAILQ_EMPTY(queue
));
250 item
= QTAILQ_FIRST(queue
);
251 g_assert(item
->type
== QEMU_INPUT_QUEUE_DELAY
);
252 QTAILQ_REMOVE(queue
, item
, node
);
255 while (!QTAILQ_EMPTY(queue
)) {
256 item
= QTAILQ_FIRST(queue
);
257 switch (item
->type
) {
258 case QEMU_INPUT_QUEUE_DELAY
:
259 timer_mod(item
->timer
, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL
)
262 case QEMU_INPUT_QUEUE_EVENT
:
263 qemu_input_event_send(item
->src
, item
->evt
);
264 qapi_free_InputEvent(item
->evt
);
266 case QEMU_INPUT_QUEUE_SYNC
:
267 qemu_input_event_sync();
270 QTAILQ_REMOVE(queue
, item
, node
);
275 static void qemu_input_queue_delay(struct QemuInputEventQueueHead
*queue
,
276 QEMUTimer
*timer
, uint32_t delay_ms
)
278 QemuInputEventQueue
*item
= g_new0(QemuInputEventQueue
, 1);
279 bool start_timer
= QTAILQ_EMPTY(queue
);
281 item
->type
= QEMU_INPUT_QUEUE_DELAY
;
282 item
->delay_ms
= delay_ms
;
284 QTAILQ_INSERT_TAIL(queue
, item
, node
);
287 timer_mod(item
->timer
, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL
)
292 static void qemu_input_queue_event(struct QemuInputEventQueueHead
*queue
,
293 QemuConsole
*src
, InputEvent
*evt
)
295 QemuInputEventQueue
*item
= g_new0(QemuInputEventQueue
, 1);
297 item
->type
= QEMU_INPUT_QUEUE_EVENT
;
300 QTAILQ_INSERT_TAIL(queue
, item
, node
);
303 static void qemu_input_queue_sync(struct QemuInputEventQueueHead
*queue
)
305 QemuInputEventQueue
*item
= g_new0(QemuInputEventQueue
, 1);
307 item
->type
= QEMU_INPUT_QUEUE_SYNC
;
308 QTAILQ_INSERT_TAIL(queue
, item
, node
);
311 void qemu_input_event_send_impl(QemuConsole
*src
, InputEvent
*evt
)
313 QemuInputHandlerState
*s
;
315 qemu_input_event_trace(src
, evt
);
318 if (graphic_rotate
&& (evt
->type
== INPUT_EVENT_KIND_ABS
)) {
319 qemu_input_transform_abs_rotate(evt
);
323 s
= qemu_input_find_handler(1 << evt
->type
, src
);
327 s
->handler
->event(s
->dev
, src
, evt
);
331 void qemu_input_event_send(QemuConsole
*src
, InputEvent
*evt
)
333 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED
)) {
337 replay_input_event(src
, evt
);
340 void qemu_input_event_sync_impl(void)
342 QemuInputHandlerState
*s
;
344 trace_input_event_sync();
346 QTAILQ_FOREACH(s
, &handlers
, node
) {
350 if (s
->handler
->sync
) {
351 s
->handler
->sync(s
->dev
);
357 void qemu_input_event_sync(void)
359 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED
)) {
363 replay_input_sync_event();
366 InputEvent
*qemu_input_event_new_key(KeyValue
*key
, bool down
)
368 InputEvent
*evt
= g_new0(InputEvent
, 1);
369 evt
->u
.key
.data
= g_new0(InputKeyEvent
, 1);
370 evt
->type
= INPUT_EVENT_KIND_KEY
;
371 evt
->u
.key
.data
->key
= key
;
372 evt
->u
.key
.data
->down
= down
;
376 void qemu_input_event_send_key(QemuConsole
*src
, KeyValue
*key
, bool down
)
379 evt
= qemu_input_event_new_key(key
, down
);
380 if (QTAILQ_EMPTY(&kbd_queue
)) {
381 qemu_input_event_send(src
, evt
);
382 qemu_input_event_sync();
383 qapi_free_InputEvent(evt
);
385 qemu_input_queue_event(&kbd_queue
, src
, evt
);
386 qemu_input_queue_sync(&kbd_queue
);
390 void qemu_input_event_send_key_number(QemuConsole
*src
, int num
, bool down
)
392 KeyValue
*key
= g_new0(KeyValue
, 1);
393 key
->type
= KEY_VALUE_KIND_NUMBER
;
394 key
->u
.number
.data
= num
;
395 qemu_input_event_send_key(src
, key
, down
);
398 void qemu_input_event_send_key_qcode(QemuConsole
*src
, QKeyCode q
, bool down
)
400 KeyValue
*key
= g_new0(KeyValue
, 1);
401 key
->type
= KEY_VALUE_KIND_QCODE
;
402 key
->u
.qcode
.data
= q
;
403 qemu_input_event_send_key(src
, key
, down
);
406 void qemu_input_event_send_key_delay(uint32_t delay_ms
)
409 kbd_timer
= timer_new_ms(QEMU_CLOCK_VIRTUAL
, qemu_input_queue_process
,
412 qemu_input_queue_delay(&kbd_queue
, kbd_timer
,
413 delay_ms
? delay_ms
: kbd_default_delay_ms
);
416 InputEvent
*qemu_input_event_new_btn(InputButton btn
, bool down
)
418 InputEvent
*evt
= g_new0(InputEvent
, 1);
419 evt
->u
.btn
.data
= g_new0(InputBtnEvent
, 1);
420 evt
->type
= INPUT_EVENT_KIND_BTN
;
421 evt
->u
.btn
.data
->button
= btn
;
422 evt
->u
.btn
.data
->down
= down
;
426 void qemu_input_queue_btn(QemuConsole
*src
, InputButton btn
, bool down
)
429 evt
= qemu_input_event_new_btn(btn
, down
);
430 qemu_input_event_send(src
, evt
);
431 qapi_free_InputEvent(evt
);
434 void qemu_input_update_buttons(QemuConsole
*src
, uint32_t *button_map
,
435 uint32_t button_old
, uint32_t button_new
)
440 for (btn
= 0; btn
< INPUT_BUTTON__MAX
; btn
++) {
441 mask
= button_map
[btn
];
442 if ((button_old
& mask
) == (button_new
& mask
)) {
445 qemu_input_queue_btn(src
, btn
, button_new
& mask
);
449 bool qemu_input_is_absolute(void)
451 QemuInputHandlerState
*s
;
453 s
= qemu_input_find_handler(INPUT_EVENT_MASK_REL
| INPUT_EVENT_MASK_ABS
,
455 return (s
!= NULL
) && (s
->handler
->mask
& INPUT_EVENT_MASK_ABS
);
458 int qemu_input_scale_axis(int value
, int size_in
, int size_out
)
463 return (int64_t)value
* (size_out
- 1) / (size_in
- 1);
466 InputEvent
*qemu_input_event_new_move(InputEventKind kind
,
467 InputAxis axis
, int value
)
469 InputEvent
*evt
= g_new0(InputEvent
, 1);
470 InputMoveEvent
*move
= g_new0(InputMoveEvent
, 1);
473 evt
->u
.rel
.data
= move
; /* evt->u.rel is the same as evt->u.abs */
479 void qemu_input_queue_rel(QemuConsole
*src
, InputAxis axis
, int value
)
482 evt
= qemu_input_event_new_move(INPUT_EVENT_KIND_REL
, axis
, value
);
483 qemu_input_event_send(src
, evt
);
484 qapi_free_InputEvent(evt
);
487 void qemu_input_queue_abs(QemuConsole
*src
, InputAxis axis
, int value
, int size
)
490 int scaled
= qemu_input_scale_axis(value
, size
, INPUT_EVENT_ABS_SIZE
);
491 evt
= qemu_input_event_new_move(INPUT_EVENT_KIND_ABS
, axis
, scaled
);
492 qemu_input_event_send(src
, evt
);
493 qapi_free_InputEvent(evt
);
496 void qemu_input_check_mode_change(void)
498 static int current_is_absolute
;
501 is_absolute
= qemu_input_is_absolute();
503 if (is_absolute
!= current_is_absolute
) {
504 trace_input_mouse_mode(is_absolute
);
505 notifier_list_notify(&mouse_mode_notifiers
, NULL
);
508 current_is_absolute
= is_absolute
;
511 void qemu_add_mouse_mode_change_notifier(Notifier
*notify
)
513 notifier_list_add(&mouse_mode_notifiers
, notify
);
516 void qemu_remove_mouse_mode_change_notifier(Notifier
*notify
)
518 notifier_remove(notify
);
521 MouseInfoList
*qmp_query_mice(Error
**errp
)
523 MouseInfoList
*mice_list
= NULL
;
525 QemuInputHandlerState
*s
;
528 QTAILQ_FOREACH(s
, &handlers
, node
) {
529 if (!(s
->handler
->mask
&
530 (INPUT_EVENT_MASK_REL
| INPUT_EVENT_MASK_ABS
))) {
534 info
= g_new0(MouseInfoList
, 1);
535 info
->value
= g_new0(MouseInfo
, 1);
536 info
->value
->index
= s
->id
;
537 info
->value
->name
= g_strdup(s
->handler
->name
);
538 info
->value
->absolute
= s
->handler
->mask
& INPUT_EVENT_MASK_ABS
;
539 info
->value
->current
= current
;
542 info
->next
= mice_list
;
549 void hmp_mouse_set(Monitor
*mon
, const QDict
*qdict
)
551 QemuInputHandlerState
*s
;
552 int index
= qdict_get_int(qdict
, "index");
555 QTAILQ_FOREACH(s
, &handlers
, node
) {
556 if (s
->id
!= index
) {
559 if (!(s
->handler
->mask
& (INPUT_EVENT_MASK_REL
|
560 INPUT_EVENT_MASK_ABS
))) {
561 error_report("Input device '%s' is not a mouse", s
->handler
->name
);
565 qemu_input_handler_activate(s
);
570 error_report("Mouse at index '%d' not found", index
);
573 qemu_input_check_mode_change();