18f0056b7SPaolo Bonzini /*
28f0056b7SPaolo Bonzini * QEMU System Emulator
38f0056b7SPaolo Bonzini *
48f0056b7SPaolo Bonzini * Copyright (c) 2003-2008 Fabrice Bellard
58f0056b7SPaolo Bonzini *
68f0056b7SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
78f0056b7SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
88f0056b7SPaolo Bonzini * in the Software without restriction, including without limitation the rights
98f0056b7SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108f0056b7SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
118f0056b7SPaolo Bonzini * furnished to do so, subject to the following conditions:
128f0056b7SPaolo Bonzini *
138f0056b7SPaolo Bonzini * The above copyright notice and this permission notice shall be included in
148f0056b7SPaolo Bonzini * all copies or substantial portions of the Software.
158f0056b7SPaolo Bonzini *
168f0056b7SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178f0056b7SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188f0056b7SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198f0056b7SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208f0056b7SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218f0056b7SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228f0056b7SPaolo Bonzini * THE SOFTWARE.
238f0056b7SPaolo Bonzini */
248f0056b7SPaolo Bonzini
25e16f4c87SPeter Maydell #include "qemu/osdep.h"
26*17f6315eSDmitry Petrov #include "qemu/log.h"
279af23989SMarkus Armbruster #include "qapi/qapi-commands-ui.h"
2828ecbaeeSPaolo Bonzini #include "ui/console.h"
290041e9a0SMichael S. Tsirkin #include "keymaps.h"
309784e579SGerd Hoffmann #include "ui/input.h"
318f0056b7SPaolo Bonzini
3272711efbSGerd Hoffmann struct QEMUPutMouseEntry {
3372711efbSGerd Hoffmann QEMUPutMouseEvent *qemu_put_mouse_event;
3472711efbSGerd Hoffmann void *qemu_put_mouse_event_opaque;
3572711efbSGerd Hoffmann int qemu_put_mouse_event_absolute;
36edd85a3dSGerd Hoffmann
37edd85a3dSGerd Hoffmann /* new input core */
38edd85a3dSGerd Hoffmann QemuInputHandler h;
39edd85a3dSGerd Hoffmann QemuInputHandlerState *s;
407fb1cf16SEric Blake int axis[INPUT_AXIS__MAX];
41edd85a3dSGerd Hoffmann int buttons;
4272711efbSGerd Hoffmann };
4372711efbSGerd Hoffmann
445a37532dSGerd Hoffmann struct QEMUPutKbdEntry {
455a37532dSGerd Hoffmann QEMUPutKBDEvent *put_kbd;
465a37532dSGerd Hoffmann void *opaque;
479784e579SGerd Hoffmann QemuInputHandlerState *s;
485a37532dSGerd Hoffmann };
495a37532dSGerd Hoffmann
5072711efbSGerd Hoffmann struct QEMUPutLEDEntry {
5172711efbSGerd Hoffmann QEMUPutLEDEvent *put_led;
5272711efbSGerd Hoffmann void *opaque;
5372711efbSGerd Hoffmann QTAILQ_ENTRY(QEMUPutLEDEntry) next;
5472711efbSGerd Hoffmann };
5572711efbSGerd Hoffmann
565a37532dSGerd Hoffmann static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
575a37532dSGerd Hoffmann QTAILQ_HEAD_INITIALIZER(led_handlers);
588f0056b7SPaolo Bonzini
index_from_key(const char * key,size_t key_length)5964ffbe04SWolfgang Bumiller int index_from_key(const char *key, size_t key_length)
601048c88fSAmos Kong {
619d537c90SLuiz Capitulino int i;
621048c88fSAmos Kong
631c236ba5SMarkus Armbruster for (i = 0; i < Q_KEY_CODE__MAX; i++) {
64977c736fSMarkus Armbruster if (!strncmp(key, QKeyCode_str(i), key_length) &&
65977c736fSMarkus Armbruster !QKeyCode_str(i)[key_length]) {
661048c88fSAmos Kong break;
671048c88fSAmos Kong }
681048c88fSAmos Kong }
691048c88fSAmos Kong
707fb1cf16SEric Blake /* Return Q_KEY_CODE__MAX if the key is invalid */
711048c88fSAmos Kong return i;
721048c88fSAmos Kong }
731048c88fSAmos Kong
copy_key_value(KeyValue * src)74ce53f2f9SGerd Hoffmann static KeyValue *copy_key_value(KeyValue *src)
75ce53f2f9SGerd Hoffmann {
76ce53f2f9SGerd Hoffmann KeyValue *dst = g_new(KeyValue, 1);
77ce53f2f9SGerd Hoffmann memcpy(dst, src, sizeof(*src));
781d5b8d77SDaniel P. Berrange if (dst->type == KEY_VALUE_KIND_NUMBER) {
791d5b8d77SDaniel P. Berrange QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number.data);
801d5b8d77SDaniel P. Berrange dst->type = KEY_VALUE_KIND_QCODE;
811d5b8d77SDaniel P. Berrange dst->u.qcode.data = code;
821d5b8d77SDaniel P. Berrange }
83ce53f2f9SGerd Hoffmann return dst;
84e4c8f004SAmos Kong }
85e4c8f004SAmos Kong
qmp_send_key(KeyValueList * keys,bool has_hold_time,int64_t hold_time,Error ** errp)869f328977SLuiz Capitulino void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
87e4c8f004SAmos Kong Error **errp)
88e4c8f004SAmos Kong {
899f328977SLuiz Capitulino KeyValueList *p;
90e37f2024SGerd Hoffmann KeyValue **up = NULL;
91e37f2024SGerd Hoffmann int count = 0;
92e4c8f004SAmos Kong
93e4c8f004SAmos Kong if (!has_hold_time) {
942e377f17SGerd Hoffmann hold_time = 0; /* use default */
95e4c8f004SAmos Kong }
96e4c8f004SAmos Kong
97e4c8f004SAmos Kong for (p = keys; p != NULL; p = p->next) {
98ce53f2f9SGerd Hoffmann qemu_input_event_send_key(NULL, copy_key_value(p->value), true);
992e377f17SGerd Hoffmann qemu_input_event_send_key_delay(hold_time);
100e37f2024SGerd Hoffmann up = g_realloc(up, sizeof(*up) * (count+1));
101e37f2024SGerd Hoffmann up[count] = copy_key_value(p->value);
102e37f2024SGerd Hoffmann count++;
103e4c8f004SAmos Kong }
104e37f2024SGerd Hoffmann while (count) {
105e37f2024SGerd Hoffmann count--;
106e37f2024SGerd Hoffmann qemu_input_event_send_key(NULL, up[count], false);
1072e377f17SGerd Hoffmann qemu_input_event_send_key_delay(hold_time);
1082e377f17SGerd Hoffmann }
109e37f2024SGerd Hoffmann g_free(up);
110e4c8f004SAmos Kong }
111e4c8f004SAmos Kong
legacy_mouse_event(DeviceState * dev,QemuConsole * src,InputEvent * evt)112edd85a3dSGerd Hoffmann static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
113edd85a3dSGerd Hoffmann InputEvent *evt)
114edd85a3dSGerd Hoffmann {
1157fb1cf16SEric Blake static const int bmap[INPUT_BUTTON__MAX] = {
116edd85a3dSGerd Hoffmann [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
117edd85a3dSGerd Hoffmann [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
118edd85a3dSGerd Hoffmann [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
119edd85a3dSGerd Hoffmann };
120edd85a3dSGerd Hoffmann QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
121b5a1b443SEric Blake InputBtnEvent *btn;
122b5a1b443SEric Blake InputMoveEvent *move;
123edd85a3dSGerd Hoffmann
124568c73a4SEric Blake switch (evt->type) {
125edd85a3dSGerd Hoffmann case INPUT_EVENT_KIND_BTN:
12632bafa8fSEric Blake btn = evt->u.btn.data;
127b5a1b443SEric Blake if (btn->down) {
128b5a1b443SEric Blake s->buttons |= bmap[btn->button];
129edd85a3dSGerd Hoffmann } else {
130b5a1b443SEric Blake s->buttons &= ~bmap[btn->button];
131edd85a3dSGerd Hoffmann }
132b5a1b443SEric Blake if (btn->down && btn->button == INPUT_BUTTON_WHEEL_UP) {
133dbb2a132SGerd Hoffmann s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
134dbb2a132SGerd Hoffmann s->axis[INPUT_AXIS_X],
135dbb2a132SGerd Hoffmann s->axis[INPUT_AXIS_Y],
136dbb2a132SGerd Hoffmann -1,
137dbb2a132SGerd Hoffmann s->buttons);
138dbb2a132SGerd Hoffmann }
139b5a1b443SEric Blake if (btn->down && btn->button == INPUT_BUTTON_WHEEL_DOWN) {
140dbb2a132SGerd Hoffmann s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
141dbb2a132SGerd Hoffmann s->axis[INPUT_AXIS_X],
142dbb2a132SGerd Hoffmann s->axis[INPUT_AXIS_Y],
143dbb2a132SGerd Hoffmann 1,
144dbb2a132SGerd Hoffmann s->buttons);
145dbb2a132SGerd Hoffmann }
146*17f6315eSDmitry Petrov if (btn->down && btn->button == INPUT_BUTTON_WHEEL_RIGHT) {
147*17f6315eSDmitry Petrov s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
148*17f6315eSDmitry Petrov s->axis[INPUT_AXIS_X],
149*17f6315eSDmitry Petrov s->axis[INPUT_AXIS_Y],
150*17f6315eSDmitry Petrov -2,
151*17f6315eSDmitry Petrov s->buttons);
152*17f6315eSDmitry Petrov }
153*17f6315eSDmitry Petrov if (btn->down && btn->button == INPUT_BUTTON_WHEEL_LEFT) {
154*17f6315eSDmitry Petrov s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
155*17f6315eSDmitry Petrov s->axis[INPUT_AXIS_X],
156*17f6315eSDmitry Petrov s->axis[INPUT_AXIS_Y],
157*17f6315eSDmitry Petrov 2,
158*17f6315eSDmitry Petrov s->buttons);
159*17f6315eSDmitry Petrov }
160edd85a3dSGerd Hoffmann break;
161edd85a3dSGerd Hoffmann case INPUT_EVENT_KIND_ABS:
16232bafa8fSEric Blake move = evt->u.abs.data;
163b5a1b443SEric Blake s->axis[move->axis] = move->value;
164edd85a3dSGerd Hoffmann break;
165edd85a3dSGerd Hoffmann case INPUT_EVENT_KIND_REL:
16632bafa8fSEric Blake move = evt->u.rel.data;
167b5a1b443SEric Blake s->axis[move->axis] += move->value;
168edd85a3dSGerd Hoffmann break;
169edd85a3dSGerd Hoffmann default:
170edd85a3dSGerd Hoffmann break;
171edd85a3dSGerd Hoffmann }
172edd85a3dSGerd Hoffmann }
173edd85a3dSGerd Hoffmann
legacy_mouse_sync(DeviceState * dev)174edd85a3dSGerd Hoffmann static void legacy_mouse_sync(DeviceState *dev)
175edd85a3dSGerd Hoffmann {
176edd85a3dSGerd Hoffmann QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
177edd85a3dSGerd Hoffmann
178edd85a3dSGerd Hoffmann s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
179edd85a3dSGerd Hoffmann s->axis[INPUT_AXIS_X],
180edd85a3dSGerd Hoffmann s->axis[INPUT_AXIS_Y],
181edd85a3dSGerd Hoffmann 0,
182edd85a3dSGerd Hoffmann s->buttons);
183edd85a3dSGerd Hoffmann
184edd85a3dSGerd Hoffmann if (!s->qemu_put_mouse_event_absolute) {
185edd85a3dSGerd Hoffmann s->axis[INPUT_AXIS_X] = 0;
186edd85a3dSGerd Hoffmann s->axis[INPUT_AXIS_Y] = 0;
187edd85a3dSGerd Hoffmann }
188edd85a3dSGerd Hoffmann }
189edd85a3dSGerd Hoffmann
qemu_add_mouse_event_handler(QEMUPutMouseEvent * func,void * opaque,int absolute,const char * name)1908f0056b7SPaolo Bonzini QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
1918f0056b7SPaolo Bonzini void *opaque, int absolute,
1928f0056b7SPaolo Bonzini const char *name)
1938f0056b7SPaolo Bonzini {
1946fef28eeSAnthony Liguori QEMUPutMouseEntry *s;
1958f0056b7SPaolo Bonzini
196fedf0d35SMarkus Armbruster s = g_new0(QEMUPutMouseEntry, 1);
1978f0056b7SPaolo Bonzini
1988f0056b7SPaolo Bonzini s->qemu_put_mouse_event = func;
1998f0056b7SPaolo Bonzini s->qemu_put_mouse_event_opaque = opaque;
2008f0056b7SPaolo Bonzini s->qemu_put_mouse_event_absolute = absolute;
2016fef28eeSAnthony Liguori
202edd85a3dSGerd Hoffmann s->h.name = name;
203edd85a3dSGerd Hoffmann s->h.mask = INPUT_EVENT_MASK_BTN |
204edd85a3dSGerd Hoffmann (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
205edd85a3dSGerd Hoffmann s->h.event = legacy_mouse_event;
206edd85a3dSGerd Hoffmann s->h.sync = legacy_mouse_sync;
207edd85a3dSGerd Hoffmann s->s = qemu_input_handler_register((DeviceState *)s,
208edd85a3dSGerd Hoffmann &s->h);
209edd85a3dSGerd Hoffmann
2108f0056b7SPaolo Bonzini return s;
2118f0056b7SPaolo Bonzini }
2128f0056b7SPaolo Bonzini
qemu_activate_mouse_event_handler(QEMUPutMouseEntry * entry)2136fef28eeSAnthony Liguori void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
2146fef28eeSAnthony Liguori {
215edd85a3dSGerd Hoffmann qemu_input_handler_activate(entry->s);
2168f0056b7SPaolo Bonzini }
2178f0056b7SPaolo Bonzini
qemu_remove_mouse_event_handler(QEMUPutMouseEntry * entry)2188f0056b7SPaolo Bonzini void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
2198f0056b7SPaolo Bonzini {
220edd85a3dSGerd Hoffmann qemu_input_handler_unregister(entry->s);
221edd85a3dSGerd Hoffmann
2227267c094SAnthony Liguori g_free(entry);
2238f0056b7SPaolo Bonzini }
2248f0056b7SPaolo Bonzini
qemu_add_led_event_handler(QEMUPutLEDEvent * func,void * opaque)22503a23a85SGerd Hoffmann QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
22603a23a85SGerd Hoffmann void *opaque)
22703a23a85SGerd Hoffmann {
22803a23a85SGerd Hoffmann QEMUPutLEDEntry *s;
22903a23a85SGerd Hoffmann
230fedf0d35SMarkus Armbruster s = g_new0(QEMUPutLEDEntry, 1);
23103a23a85SGerd Hoffmann
23203a23a85SGerd Hoffmann s->put_led = func;
23303a23a85SGerd Hoffmann s->opaque = opaque;
23403a23a85SGerd Hoffmann QTAILQ_INSERT_TAIL(&led_handlers, s, next);
23503a23a85SGerd Hoffmann return s;
23603a23a85SGerd Hoffmann }
23703a23a85SGerd Hoffmann
qemu_remove_led_event_handler(QEMUPutLEDEntry * entry)23803a23a85SGerd Hoffmann void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
23903a23a85SGerd Hoffmann {
24003a23a85SGerd Hoffmann if (entry == NULL)
24103a23a85SGerd Hoffmann return;
24203a23a85SGerd Hoffmann QTAILQ_REMOVE(&led_handlers, entry, next);
2437267c094SAnthony Liguori g_free(entry);
24403a23a85SGerd Hoffmann }
24503a23a85SGerd Hoffmann
kbd_put_ledstate(int ledstate)24603a23a85SGerd Hoffmann void kbd_put_ledstate(int ledstate)
24703a23a85SGerd Hoffmann {
24803a23a85SGerd Hoffmann QEMUPutLEDEntry *cursor;
24903a23a85SGerd Hoffmann
25003a23a85SGerd Hoffmann QTAILQ_FOREACH(cursor, &led_handlers, next) {
25103a23a85SGerd Hoffmann cursor->put_led(cursor->opaque, ledstate);
25203a23a85SGerd Hoffmann }
25303a23a85SGerd Hoffmann }
254