2 #include "sysemu/sysemu.h"
3 #include "qapi-types.h"
4 #include "qmp-commands.h"
7 #include "ui/console.h"
9 struct QemuInputHandlerState
{
11 QemuInputHandler
*handler
;
15 QTAILQ_ENTRY(QemuInputHandlerState
) node
;
17 static QTAILQ_HEAD(, QemuInputHandlerState
) handlers
=
18 QTAILQ_HEAD_INITIALIZER(handlers
);
19 static NotifierList mouse_mode_notifiers
=
20 NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers
);
22 QemuInputHandlerState
*qemu_input_handler_register(DeviceState
*dev
,
23 QemuInputHandler
*handler
)
25 QemuInputHandlerState
*s
= g_new0(QemuInputHandlerState
, 1);
31 QTAILQ_INSERT_TAIL(&handlers
, s
, node
);
33 qemu_input_check_mode_change();
37 void qemu_input_handler_activate(QemuInputHandlerState
*s
)
39 QTAILQ_REMOVE(&handlers
, s
, node
);
40 QTAILQ_INSERT_HEAD(&handlers
, s
, node
);
41 qemu_input_check_mode_change();
44 void qemu_input_handler_deactivate(QemuInputHandlerState
*s
)
46 QTAILQ_REMOVE(&handlers
, s
, node
);
47 QTAILQ_INSERT_TAIL(&handlers
, s
, node
);
48 qemu_input_check_mode_change();
51 void qemu_input_handler_unregister(QemuInputHandlerState
*s
)
53 QTAILQ_REMOVE(&handlers
, s
, node
);
55 qemu_input_check_mode_change();
58 void qemu_input_handler_bind(QemuInputHandlerState
*s
,
59 const char *device_id
, int head
,
65 dev
= qdev_find_recursive(sysbus_get_default(), device_id
);
67 error_set(errp
, QERR_DEVICE_NOT_FOUND
, device_id
);
71 con
= qemu_console_lookup_by_device(dev
, head
);
73 error_setg(errp
, "Device %s is not bound to a QemuConsole", device_id
);
80 static QemuInputHandlerState
*
81 qemu_input_find_handler(uint32_t mask
, QemuConsole
*con
)
83 QemuInputHandlerState
*s
;
85 QTAILQ_FOREACH(s
, &handlers
, node
) {
86 if (s
->con
== NULL
|| s
->con
!= con
) {
89 if (mask
& s
->handler
->mask
) {
94 QTAILQ_FOREACH(s
, &handlers
, node
) {
98 if (mask
& s
->handler
->mask
) {
105 static void qemu_input_transform_abs_rotate(InputEvent
*evt
)
107 switch (graphic_rotate
) {
109 if (evt
->abs
->axis
== INPUT_AXIS_X
) {
110 evt
->abs
->axis
= INPUT_AXIS_Y
;
111 } else if (evt
->abs
->axis
== INPUT_AXIS_Y
) {
112 evt
->abs
->axis
= INPUT_AXIS_X
;
113 evt
->abs
->value
= INPUT_EVENT_ABS_SIZE
- 1 - evt
->abs
->value
;
117 evt
->abs
->value
= INPUT_EVENT_ABS_SIZE
- 1 - evt
->abs
->value
;
120 if (evt
->abs
->axis
== INPUT_AXIS_X
) {
121 evt
->abs
->axis
= INPUT_AXIS_Y
;
122 evt
->abs
->value
= INPUT_EVENT_ABS_SIZE
- 1 - evt
->abs
->value
;
123 } else if (evt
->abs
->axis
== INPUT_AXIS_Y
) {
124 evt
->abs
->axis
= INPUT_AXIS_X
;
130 static void qemu_input_event_trace(QemuConsole
*src
, InputEvent
*evt
)
136 idx
= qemu_console_get_index(src
);
139 case INPUT_EVENT_KIND_KEY
:
140 switch (evt
->key
->key
->kind
) {
141 case KEY_VALUE_KIND_NUMBER
:
142 qcode
= qemu_input_key_number_to_qcode(evt
->key
->key
->number
);
143 name
= QKeyCode_lookup
[qcode
];
144 trace_input_event_key_number(idx
, evt
->key
->key
->number
,
145 name
, evt
->key
->down
);
147 case KEY_VALUE_KIND_QCODE
:
148 name
= QKeyCode_lookup
[evt
->key
->key
->qcode
];
149 trace_input_event_key_qcode(idx
, name
, evt
->key
->down
);
151 case KEY_VALUE_KIND_MAX
:
156 case INPUT_EVENT_KIND_BTN
:
157 name
= InputButton_lookup
[evt
->btn
->button
];
158 trace_input_event_btn(idx
, name
, evt
->btn
->down
);
160 case INPUT_EVENT_KIND_REL
:
161 name
= InputAxis_lookup
[evt
->rel
->axis
];
162 trace_input_event_rel(idx
, name
, evt
->rel
->value
);
164 case INPUT_EVENT_KIND_ABS
:
165 name
= InputAxis_lookup
[evt
->abs
->axis
];
166 trace_input_event_abs(idx
, name
, evt
->abs
->value
);
168 case INPUT_EVENT_KIND_MAX
:
174 void qemu_input_event_send(QemuConsole
*src
, InputEvent
*evt
)
176 QemuInputHandlerState
*s
;
178 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED
)) {
182 qemu_input_event_trace(src
, evt
);
185 if (graphic_rotate
&& (evt
->kind
== INPUT_EVENT_KIND_ABS
)) {
186 qemu_input_transform_abs_rotate(evt
);
190 s
= qemu_input_find_handler(1 << evt
->kind
, src
);
194 s
->handler
->event(s
->dev
, src
, evt
);
198 void qemu_input_event_sync(void)
200 QemuInputHandlerState
*s
;
202 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED
)) {
206 trace_input_event_sync();
208 QTAILQ_FOREACH(s
, &handlers
, node
) {
212 if (s
->handler
->sync
) {
213 s
->handler
->sync(s
->dev
);
219 InputEvent
*qemu_input_event_new_key(KeyValue
*key
, bool down
)
221 InputEvent
*evt
= g_new0(InputEvent
, 1);
222 evt
->key
= g_new0(InputKeyEvent
, 1);
223 evt
->kind
= INPUT_EVENT_KIND_KEY
;
225 evt
->key
->down
= down
;
229 void qemu_input_event_send_key(QemuConsole
*src
, KeyValue
*key
, bool down
)
232 evt
= qemu_input_event_new_key(key
, down
);
233 qemu_input_event_send(src
, evt
);
234 qemu_input_event_sync();
235 qapi_free_InputEvent(evt
);
238 void qemu_input_event_send_key_number(QemuConsole
*src
, int num
, bool down
)
240 KeyValue
*key
= g_new0(KeyValue
, 1);
241 key
->kind
= KEY_VALUE_KIND_NUMBER
;
243 qemu_input_event_send_key(src
, key
, down
);
246 void qemu_input_event_send_key_qcode(QemuConsole
*src
, QKeyCode q
, bool down
)
248 KeyValue
*key
= g_new0(KeyValue
, 1);
249 key
->kind
= KEY_VALUE_KIND_QCODE
;
251 qemu_input_event_send_key(src
, key
, down
);
254 InputEvent
*qemu_input_event_new_btn(InputButton btn
, bool down
)
256 InputEvent
*evt
= g_new0(InputEvent
, 1);
257 evt
->btn
= g_new0(InputBtnEvent
, 1);
258 evt
->kind
= INPUT_EVENT_KIND_BTN
;
259 evt
->btn
->button
= btn
;
260 evt
->btn
->down
= down
;
264 void qemu_input_queue_btn(QemuConsole
*src
, InputButton btn
, bool down
)
267 evt
= qemu_input_event_new_btn(btn
, down
);
268 qemu_input_event_send(src
, evt
);
269 qapi_free_InputEvent(evt
);
272 void qemu_input_update_buttons(QemuConsole
*src
, uint32_t *button_map
,
273 uint32_t button_old
, uint32_t button_new
)
278 for (btn
= 0; btn
< INPUT_BUTTON_MAX
; btn
++) {
279 mask
= button_map
[btn
];
280 if ((button_old
& mask
) == (button_new
& mask
)) {
283 qemu_input_queue_btn(src
, btn
, button_new
& mask
);
287 bool qemu_input_is_absolute(void)
289 QemuInputHandlerState
*s
;
291 s
= qemu_input_find_handler(INPUT_EVENT_MASK_REL
| INPUT_EVENT_MASK_ABS
,
293 return (s
!= NULL
) && (s
->handler
->mask
& INPUT_EVENT_MASK_ABS
);
296 int qemu_input_scale_axis(int value
, int size_in
, int size_out
)
301 return (int64_t)value
* (size_out
- 1) / (size_in
- 1);
304 InputEvent
*qemu_input_event_new_move(InputEventKind kind
,
305 InputAxis axis
, int value
)
307 InputEvent
*evt
= g_new0(InputEvent
, 1);
308 InputMoveEvent
*move
= g_new0(InputMoveEvent
, 1);
317 void qemu_input_queue_rel(QemuConsole
*src
, InputAxis axis
, int value
)
320 evt
= qemu_input_event_new_move(INPUT_EVENT_KIND_REL
, axis
, value
);
321 qemu_input_event_send(src
, evt
);
322 qapi_free_InputEvent(evt
);
325 void qemu_input_queue_abs(QemuConsole
*src
, InputAxis axis
, int value
, int size
)
328 int scaled
= qemu_input_scale_axis(value
, size
, INPUT_EVENT_ABS_SIZE
);
329 evt
= qemu_input_event_new_move(INPUT_EVENT_KIND_ABS
, axis
, scaled
);
330 qemu_input_event_send(src
, evt
);
331 qapi_free_InputEvent(evt
);
334 void qemu_input_check_mode_change(void)
336 static int current_is_absolute
;
339 is_absolute
= qemu_input_is_absolute();
341 if (is_absolute
!= current_is_absolute
) {
342 trace_input_mouse_mode(is_absolute
);
343 notifier_list_notify(&mouse_mode_notifiers
, NULL
);
346 current_is_absolute
= is_absolute
;
349 void qemu_add_mouse_mode_change_notifier(Notifier
*notify
)
351 notifier_list_add(&mouse_mode_notifiers
, notify
);
354 void qemu_remove_mouse_mode_change_notifier(Notifier
*notify
)
356 notifier_remove(notify
);
359 MouseInfoList
*qmp_query_mice(Error
**errp
)
361 MouseInfoList
*mice_list
= NULL
;
363 QemuInputHandlerState
*s
;
366 QTAILQ_FOREACH(s
, &handlers
, node
) {
367 if (!(s
->handler
->mask
&
368 (INPUT_EVENT_MASK_REL
| INPUT_EVENT_MASK_ABS
))) {
372 info
= g_new0(MouseInfoList
, 1);
373 info
->value
= g_new0(MouseInfo
, 1);
374 info
->value
->index
= s
->id
;
375 info
->value
->name
= g_strdup(s
->handler
->name
);
376 info
->value
->absolute
= s
->handler
->mask
& INPUT_EVENT_MASK_ABS
;
377 info
->value
->current
= current
;
380 info
->next
= mice_list
;
387 void do_mouse_set(Monitor
*mon
, const QDict
*qdict
)
389 QemuInputHandlerState
*s
;
390 int index
= qdict_get_int(qdict
, "index");
393 QTAILQ_FOREACH(s
, &handlers
, node
) {
394 if (s
->id
!= index
) {
397 if (!(s
->handler
->mask
& (INPUT_EVENT_MASK_REL
|
398 INPUT_EVENT_MASK_ABS
))) {
399 error_report("Input device '%s' is not a mouse", s
->handler
->name
);
403 qemu_input_handler_activate(s
);
408 error_report("Mouse at index '%d' not found", index
);
411 qemu_input_check_mode_change();