]> git.proxmox.com Git - mirror_qemu.git/blame - ui/input.c
input: move mouse mode notifier to new core
[mirror_qemu.git] / ui / input.c
CommitLineData
c8b405b6
GH
1#include "sysemu/sysemu.h"
2#include "qapi-types.h"
c43ce551 3#include "trace.h"
c8b405b6 4#include "ui/input.h"
c43ce551 5#include "ui/console.h"
c8b405b6
GH
6
7struct QemuInputHandlerState {
8 DeviceState *dev;
9 QemuInputHandler *handler;
10 int id;
11 int events;
12 QTAILQ_ENTRY(QemuInputHandlerState) node;
13};
14static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
15 QTAILQ_HEAD_INITIALIZER(handlers);
4a33f45e
GH
16static NotifierList mouse_mode_notifiers =
17 NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
c8b405b6
GH
18
19QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
20 QemuInputHandler *handler)
21{
22 QemuInputHandlerState *s = g_new0(QemuInputHandlerState, 1);
23 static int id = 1;
24
25 s->dev = dev;
26 s->handler = handler;
27 s->id = id++;
28 QTAILQ_INSERT_TAIL(&handlers, s, node);
4a33f45e
GH
29
30 qemu_input_check_mode_change();
c8b405b6
GH
31 return s;
32}
33
34void qemu_input_handler_activate(QemuInputHandlerState *s)
35{
36 QTAILQ_REMOVE(&handlers, s, node);
37 QTAILQ_INSERT_HEAD(&handlers, s, node);
4a33f45e 38 qemu_input_check_mode_change();
c8b405b6
GH
39}
40
41void qemu_input_handler_unregister(QemuInputHandlerState *s)
42{
43 QTAILQ_REMOVE(&handlers, s, node);
44 g_free(s);
4a33f45e 45 qemu_input_check_mode_change();
c8b405b6
GH
46}
47
48static QemuInputHandlerState*
49qemu_input_find_handler(uint32_t mask)
50{
51 QemuInputHandlerState *s;
52
53 QTAILQ_FOREACH(s, &handlers, node) {
54 if (mask & s->handler->mask) {
55 return s;
56 }
57 }
58 return NULL;
59}
60
d3535431
GH
61static void qemu_input_transform_abs_rotate(InputEvent *evt)
62{
63 switch (graphic_rotate) {
64 case 90:
65 if (evt->abs->axis == INPUT_AXIS_X) {
66 evt->abs->axis = INPUT_AXIS_Y;
67 } else if (evt->abs->axis == INPUT_AXIS_Y) {
68 evt->abs->axis = INPUT_AXIS_X;
69 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value;
70 }
71 break;
72 case 180:
73 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value;
74 break;
75 case 270:
76 if (evt->abs->axis == INPUT_AXIS_X) {
77 evt->abs->axis = INPUT_AXIS_Y;
78 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value;
79 } else if (evt->abs->axis == INPUT_AXIS_Y) {
80 evt->abs->axis = INPUT_AXIS_X;
81 }
82 break;
83 }
84}
85
c43ce551
GH
86static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
87{
88 const char *name;
89 int idx = -1;
90
91 if (src) {
92 idx = qemu_console_get_index(src);
93 }
94 switch (evt->kind) {
95 case INPUT_EVENT_KIND_KEY:
96 switch (evt->key->key->kind) {
97 case KEY_VALUE_KIND_NUMBER:
98 trace_input_event_key_number(idx, evt->key->key->number,
99 evt->key->down);
100 break;
101 case KEY_VALUE_KIND_QCODE:
102 name = QKeyCode_lookup[evt->key->key->qcode];
103 trace_input_event_key_qcode(idx, name, evt->key->down);
104 break;
105 case KEY_VALUE_KIND_MAX:
106 /* keep gcc happy */
107 break;
108 }
109 break;
110 case INPUT_EVENT_KIND_BTN:
111 name = InputButton_lookup[evt->btn->button];
112 trace_input_event_btn(idx, name, evt->btn->down);
113 break;
114 case INPUT_EVENT_KIND_REL:
115 name = InputAxis_lookup[evt->rel->axis];
116 trace_input_event_rel(idx, name, evt->rel->value);
117 break;
118 case INPUT_EVENT_KIND_ABS:
119 name = InputAxis_lookup[evt->abs->axis];
120 trace_input_event_abs(idx, name, evt->abs->value);
121 break;
122 case INPUT_EVENT_KIND_MAX:
123 /* keep gcc happy */
124 break;
125 }
126}
127
c8b405b6
GH
128void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
129{
130 QemuInputHandlerState *s;
131
132 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
133 return;
134 }
135
c43ce551
GH
136 qemu_input_event_trace(src, evt);
137
d3535431
GH
138 /* pre processing */
139 if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) {
140 qemu_input_transform_abs_rotate(evt);
141 }
142
143 /* send event */
c8b405b6
GH
144 s = qemu_input_find_handler(1 << evt->kind);
145 s->handler->event(s->dev, src, evt);
146 s->events++;
147}
148
149void qemu_input_event_sync(void)
150{
151 QemuInputHandlerState *s;
152
153 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
154 return;
155 }
156
c43ce551
GH
157 trace_input_event_sync();
158
c8b405b6
GH
159 QTAILQ_FOREACH(s, &handlers, node) {
160 if (!s->events) {
161 continue;
162 }
163 if (s->handler->sync) {
164 s->handler->sync(s->dev);
165 }
166 s->events = 0;
167 }
168}
65671475
GH
169
170InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
171{
172 InputEvent *evt = g_new0(InputEvent, 1);
173 evt->key = g_new0(InputKeyEvent, 1);
174 evt->kind = INPUT_EVENT_KIND_KEY;
175 evt->key->key = key;
176 evt->key->down = down;
177 return evt;
178}
179
180void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
181{
182 InputEvent *evt;
183 evt = qemu_input_event_new_key(key, down);
184 qemu_input_event_send(src, evt);
185 qemu_input_event_sync();
186 qapi_free_InputEvent(evt);
187}
188
189void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
190{
191 KeyValue *key = g_new0(KeyValue, 1);
192 key->kind = KEY_VALUE_KIND_NUMBER;
193 key->number = num;
194 qemu_input_event_send_key(src, key, down);
195}
196
197void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
198{
199 KeyValue *key = g_new0(KeyValue, 1);
200 key->kind = KEY_VALUE_KIND_QCODE;
201 key->qcode = q;
202 qemu_input_event_send_key(src, key, down);
203}
43579403
GH
204
205InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
206{
207 InputEvent *evt = g_new0(InputEvent, 1);
208 evt->btn = g_new0(InputBtnEvent, 1);
209 evt->kind = INPUT_EVENT_KIND_BTN;
210 evt->btn->button = btn;
211 evt->btn->down = down;
212 return evt;
213}
214
215void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
216{
217 InputEvent *evt;
218 evt = qemu_input_event_new_btn(btn, down);
219 qemu_input_event_send(src, evt);
220 qapi_free_InputEvent(evt);
221}
222
223void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
224 uint32_t button_old, uint32_t button_new)
225{
226 InputButton btn;
227 uint32_t mask;
228
229 for (btn = 0; btn < INPUT_BUTTON_MAX; btn++) {
230 mask = button_map[btn];
231 if ((button_old & mask) == (button_new & mask)) {
232 continue;
233 }
234 qemu_input_queue_btn(src, btn, button_new & mask);
235 }
236}
237
502c8db5
GH
238bool qemu_input_is_absolute(void)
239{
240 QemuInputHandlerState *s;
241
242 s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS);
243 return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
244}
245
43579403
GH
246int qemu_input_scale_axis(int value, int size_in, int size_out)
247{
248 if (size_in < 2) {
249 return size_out / 2;
250 }
251 return (int64_t)value * (size_out - 1) / (size_in - 1);
252}
253
254InputEvent *qemu_input_event_new_move(InputEventKind kind,
255 InputAxis axis, int value)
256{
257 InputEvent *evt = g_new0(InputEvent, 1);
258 InputMoveEvent *move = g_new0(InputMoveEvent, 1);
259
260 evt->kind = kind;
261 evt->data = move;
262 move->axis = axis;
263 move->value = value;
264 return evt;
265}
266
267void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
268{
269 InputEvent *evt;
270 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value);
271 qemu_input_event_send(src, evt);
272 qapi_free_InputEvent(evt);
273}
274
275void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size)
276{
277 InputEvent *evt;
278 int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE);
279 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled);
280 qemu_input_event_send(src, evt);
281 qapi_free_InputEvent(evt);
282}
4a33f45e
GH
283
284void qemu_input_check_mode_change(void)
285{
286 static int current_is_absolute;
287 int is_absolute;
288
289 is_absolute = qemu_input_is_absolute();
290
291 if (is_absolute != current_is_absolute) {
292 notifier_list_notify(&mouse_mode_notifiers, NULL);
293 }
294
295 current_is_absolute = is_absolute;
296}
297
298void qemu_add_mouse_mode_change_notifier(Notifier *notify)
299{
300 notifier_list_add(&mouse_mode_notifiers, notify);
301}
302
303void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
304{
305 notifier_remove(notify);
306}