xref: /qemu/ui/input-legacy.c (revision 134b443512825bed401b6e141447b8cdc22d2efe)
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