]>
Commit | Line | Data |
---|---|---|
c8b405b6 GH |
1 | #include "sysemu/sysemu.h" |
2 | #include "qapi-types.h" | |
3 | #include "ui/input.h" | |
4 | ||
5 | struct QemuInputHandlerState { | |
6 | DeviceState *dev; | |
7 | QemuInputHandler *handler; | |
8 | int id; | |
9 | int events; | |
10 | QTAILQ_ENTRY(QemuInputHandlerState) node; | |
11 | }; | |
12 | static QTAILQ_HEAD(, QemuInputHandlerState) handlers = | |
13 | QTAILQ_HEAD_INITIALIZER(handlers); | |
14 | ||
15 | QemuInputHandlerState *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 | ||
28 | void qemu_input_handler_activate(QemuInputHandlerState *s) | |
29 | { | |
30 | QTAILQ_REMOVE(&handlers, s, node); | |
31 | QTAILQ_INSERT_HEAD(&handlers, s, node); | |
32 | } | |
33 | ||
34 | void qemu_input_handler_unregister(QemuInputHandlerState *s) | |
35 | { | |
36 | QTAILQ_REMOVE(&handlers, s, node); | |
37 | g_free(s); | |
38 | } | |
39 | ||
40 | static QemuInputHandlerState* | |
41 | qemu_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 | ||
d3535431 GH |
53 | static 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 | ||
c8b405b6 GH |
78 | void 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 | ||
d3535431 GH |
86 | /* pre processing */ |
87 | if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) { | |
88 | qemu_input_transform_abs_rotate(evt); | |
89 | } | |
90 | ||
91 | /* send event */ | |
c8b405b6 GH |
92 | s = qemu_input_find_handler(1 << evt->kind); |
93 | s->handler->event(s->dev, src, evt); | |
94 | s->events++; | |
95 | } | |
96 | ||
97 | void 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 | } | |
65671475 GH |
115 | |
116 | InputEvent *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 | ||
126 | void 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 | ||
135 | void 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 | ||
143 | void 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 | } | |
43579403 GH |
150 | |
151 | InputEvent *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 | ||
161 | void 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 | ||
169 | void 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 | ||
502c8db5 GH |
184 | bool qemu_input_is_absolute(void) |
185 | { | |
186 | QemuInputHandlerState *s; | |
187 | ||
188 | s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS); | |
189 | return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS); | |
190 | } | |
191 | ||
43579403 GH |
192 | int qemu_input_scale_axis(int value, int size_in, int size_out) |
193 | { | |
194 | if (size_in < 2) { | |
195 | return size_out / 2; | |
196 | } | |
197 | return (int64_t)value * (size_out - 1) / (size_in - 1); | |
198 | } | |
199 | ||
200 | InputEvent *qemu_input_event_new_move(InputEventKind kind, | |
201 | InputAxis axis, int value) | |
202 | { | |
203 | InputEvent *evt = g_new0(InputEvent, 1); | |
204 | InputMoveEvent *move = g_new0(InputMoveEvent, 1); | |
205 | ||
206 | evt->kind = kind; | |
207 | evt->data = move; | |
208 | move->axis = axis; | |
209 | move->value = value; | |
210 | return evt; | |
211 | } | |
212 | ||
213 | void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value) | |
214 | { | |
215 | InputEvent *evt; | |
216 | evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value); | |
217 | qemu_input_event_send(src, evt); | |
218 | qapi_free_InputEvent(evt); | |
219 | } | |
220 | ||
221 | void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size) | |
222 | { | |
223 | InputEvent *evt; | |
224 | int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE); | |
225 | evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled); | |
226 | qemu_input_event_send(src, evt); | |
227 | qapi_free_InputEvent(evt); | |
228 | } |