]> git.proxmox.com Git - mirror_qemu.git/blame - ui/input-legacy.c
input: add qemu_input_handler_deactivate
[mirror_qemu.git] / ui / input-legacy.c
CommitLineData
8f0056b7
PB
1/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
9c17d615 25#include "sysemu/sysemu.h"
83c9089e 26#include "monitor/monitor.h"
28ecbaee 27#include "ui/console.h"
7b1b5d19 28#include "qapi/error.h"
e235cec3 29#include "qmp-commands.h"
e4c8f004 30#include "qapi-types.h"
b2d1674b 31#include "ui/keymaps.h"
9784e579 32#include "ui/input.h"
8f0056b7 33
72711efb
GH
34struct QEMUPutMouseEntry {
35 QEMUPutMouseEvent *qemu_put_mouse_event;
36 void *qemu_put_mouse_event_opaque;
37 int qemu_put_mouse_event_absolute;
edd85a3d
GH
38
39 /* new input core */
40 QemuInputHandler h;
41 QemuInputHandlerState *s;
42 int axis[INPUT_AXIS_MAX];
43 int buttons;
72711efb
GH
44};
45
5a37532d
GH
46struct QEMUPutKbdEntry {
47 QEMUPutKBDEvent *put_kbd;
48 void *opaque;
9784e579 49 QemuInputHandlerState *s;
5a37532d
GH
50};
51
72711efb
GH
52struct QEMUPutLEDEntry {
53 QEMUPutLEDEvent *put_led;
54 void *opaque;
55 QTAILQ_ENTRY(QEMUPutLEDEntry) next;
56};
57
5a37532d
GH
58static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
59 QTAILQ_HEAD_INITIALIZER(led_handlers);
6fef28ee
AL
60static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
61 QTAILQ_HEAD_INITIALIZER(mouse_handlers);
8f0056b7 62
1048c88f
AK
63int index_from_key(const char *key)
64{
9d537c90 65 int i;
1048c88f
AK
66
67 for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
68 if (!strcmp(key, QKeyCode_lookup[i])) {
69 break;
70 }
71 }
72
1048c88f
AK
73 /* Return Q_KEY_CODE_MAX if the key is invalid */
74 return i;
75}
76
05a3543d
LC
77static int *keycodes;
78static int keycodes_size;
e4c8f004
AK
79static QEMUTimer *key_timer;
80
9f328977
LC
81static void free_keycodes(void)
82{
83 g_free(keycodes);
84 keycodes = NULL;
85 keycodes_size = 0;
86}
87
e4c8f004
AK
88static void release_keys(void *opaque)
89{
153d02e3 90 while (keycodes_size > 0) {
d2a92603
GH
91 qemu_input_event_send_key_number(NULL, keycodes[--keycodes_size],
92 false);
e4c8f004 93 }
05a3543d 94
9f328977 95 free_keycodes();
e4c8f004
AK
96}
97
9f328977 98void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
e4c8f004
AK
99 Error **errp)
100{
101 int keycode;
9f328977 102 KeyValueList *p;
e4c8f004
AK
103
104 if (!key_timer) {
bc72ad67 105 key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL);
e4c8f004
AK
106 }
107
108 if (keycodes != NULL) {
bc72ad67 109 timer_del(key_timer);
e4c8f004
AK
110 release_keys(NULL);
111 }
05a3543d 112
e4c8f004
AK
113 if (!has_hold_time) {
114 hold_time = 100;
115 }
116
117 for (p = keys; p != NULL; p = p->next) {
e4c8f004 118 /* key down events */
02aa76c2 119 keycode = qemu_input_key_value_to_number(p->value);
9f328977 120 if (keycode < 0x01 || keycode > 0xff) {
312fd5f2 121 error_setg(errp, "invalid hex keycode 0x%x", keycode);
9f328977
LC
122 free_keycodes();
123 return;
124 }
125
d2a92603 126 qemu_input_event_send_key_number(NULL, keycode, true);
05a3543d
LC
127
128 keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
129 keycodes[keycodes_size++] = keycode;
e4c8f004 130 }
e4c8f004
AK
131
132 /* delayed key up events */
bc72ad67 133 timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
e4c8f004
AK
134 muldiv64(get_ticks_per_sec(), hold_time, 1000));
135}
136
9784e579
GH
137static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
138 InputEvent *evt)
139{
140 QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
02aa76c2 141 int scancodes[3], i, count;
9784e579
GH
142
143 if (!entry || !entry->put_kbd) {
144 return;
145 }
02aa76c2
GH
146 count = qemu_input_key_value_to_scancode(evt->key->key,
147 evt->key->down,
148 scancodes);
149 for (i = 0; i < count; i++) {
150 entry->put_kbd(entry->opaque, scancodes[i]);
9784e579 151 }
9784e579
GH
152}
153
154static QemuInputHandler legacy_kbd_handler = {
155 .name = "legacy-kbd",
156 .mask = INPUT_EVENT_MASK_KEY,
157 .event = legacy_kbd_event,
158};
159
5a37532d 160QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
8f0056b7 161{
5a37532d
GH
162 QEMUPutKbdEntry *entry;
163
9784e579 164 entry = g_new0(QEMUPutKbdEntry, 1);
5a37532d
GH
165 entry->put_kbd = func;
166 entry->opaque = opaque;
9784e579
GH
167 entry->s = qemu_input_handler_register((DeviceState *)entry,
168 &legacy_kbd_handler);
7f5e07d9 169 qemu_input_handler_activate(entry->s);
5a37532d 170 return entry;
8f0056b7
PB
171}
172
5a37532d 173void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
46aaebff 174{
9784e579
GH
175 qemu_input_handler_unregister(entry->s);
176 g_free(entry);
46aaebff
JS
177}
178
edd85a3d
GH
179static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
180 InputEvent *evt)
181{
182 static const int bmap[INPUT_BUTTON_MAX] = {
183 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
184 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
185 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
186 };
187 QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
188
189 switch (evt->kind) {
190 case INPUT_EVENT_KIND_BTN:
191 if (evt->btn->down) {
192 s->buttons |= bmap[evt->btn->button];
193 } else {
194 s->buttons &= ~bmap[evt->btn->button];
195 }
dbb2a132
GH
196 if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_UP) {
197 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
198 s->axis[INPUT_AXIS_X],
199 s->axis[INPUT_AXIS_Y],
200 -1,
201 s->buttons);
202 }
203 if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) {
204 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
205 s->axis[INPUT_AXIS_X],
206 s->axis[INPUT_AXIS_Y],
207 1,
208 s->buttons);
209 }
edd85a3d
GH
210 break;
211 case INPUT_EVENT_KIND_ABS:
212 s->axis[evt->abs->axis] = evt->abs->value;
213 break;
214 case INPUT_EVENT_KIND_REL:
215 s->axis[evt->rel->axis] += evt->rel->value;
216 break;
217 default:
218 break;
219 }
220}
221
222static void legacy_mouse_sync(DeviceState *dev)
223{
224 QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
225
226 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
227 s->axis[INPUT_AXIS_X],
228 s->axis[INPUT_AXIS_Y],
229 0,
230 s->buttons);
231
232 if (!s->qemu_put_mouse_event_absolute) {
233 s->axis[INPUT_AXIS_X] = 0;
234 s->axis[INPUT_AXIS_Y] = 0;
235 }
236}
237
8f0056b7
PB
238QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
239 void *opaque, int absolute,
240 const char *name)
241{
6fef28ee 242 QEMUPutMouseEntry *s;
8f0056b7 243
7267c094 244 s = g_malloc0(sizeof(QEMUPutMouseEntry));
8f0056b7
PB
245
246 s->qemu_put_mouse_event = func;
247 s->qemu_put_mouse_event_opaque = opaque;
248 s->qemu_put_mouse_event_absolute = absolute;
8f0056b7 249
edd85a3d
GH
250 s->h.name = name;
251 s->h.mask = INPUT_EVENT_MASK_BTN |
252 (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
253 s->h.event = legacy_mouse_event;
254 s->h.sync = legacy_mouse_sync;
255 s->s = qemu_input_handler_register((DeviceState *)s,
256 &s->h);
257
8f0056b7
PB
258 return s;
259}
260
6fef28ee 261void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
8f0056b7 262{
edd85a3d 263 qemu_input_handler_activate(entry->s);
6fef28ee 264}
8f0056b7 265
6fef28ee
AL
266void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
267{
edd85a3d
GH
268 qemu_input_handler_unregister(entry->s);
269
7267c094 270 g_free(entry);
8f0056b7
PB
271}
272
03a23a85
GH
273QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
274 void *opaque)
275{
276 QEMUPutLEDEntry *s;
277
7267c094 278 s = g_malloc0(sizeof(QEMUPutLEDEntry));
03a23a85
GH
279
280 s->put_led = func;
281 s->opaque = opaque;
282 QTAILQ_INSERT_TAIL(&led_handlers, s, next);
283 return s;
284}
285
286void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
287{
288 if (entry == NULL)
289 return;
290 QTAILQ_REMOVE(&led_handlers, entry, next);
7267c094 291 g_free(entry);
03a23a85
GH
292}
293
03a23a85
GH
294void kbd_put_ledstate(int ledstate)
295{
296 QEMUPutLEDEntry *cursor;
297
298 QTAILQ_FOREACH(cursor, &led_handlers, next) {
299 cursor->put_led(cursor->opaque, ledstate);
300 }
301}