input-legacy.c (8133B)
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 25#include "qemu/osdep.h" 26#include "qapi/qapi-commands-ui.h" 27#include "ui/console.h" 28#include "keymaps.h" 29#include "ui/input.h" 30 31struct QEMUPutMouseEntry { 32 QEMUPutMouseEvent *qemu_put_mouse_event; 33 void *qemu_put_mouse_event_opaque; 34 int qemu_put_mouse_event_absolute; 35 36 /* new input core */ 37 QemuInputHandler h; 38 QemuInputHandlerState *s; 39 int axis[INPUT_AXIS__MAX]; 40 int buttons; 41}; 42 43struct QEMUPutKbdEntry { 44 QEMUPutKBDEvent *put_kbd; 45 void *opaque; 46 QemuInputHandlerState *s; 47}; 48 49struct QEMUPutLEDEntry { 50 QEMUPutLEDEvent *put_led; 51 void *opaque; 52 QTAILQ_ENTRY(QEMUPutLEDEntry) next; 53}; 54 55static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = 56 QTAILQ_HEAD_INITIALIZER(led_handlers); 57 58int index_from_key(const char *key, size_t key_length) 59{ 60 int i; 61 62 for (i = 0; i < Q_KEY_CODE__MAX; i++) { 63 if (!strncmp(key, QKeyCode_str(i), key_length) && 64 !QKeyCode_str(i)[key_length]) { 65 break; 66 } 67 } 68 69 /* Return Q_KEY_CODE__MAX if the key is invalid */ 70 return i; 71} 72 73static KeyValue *copy_key_value(KeyValue *src) 74{ 75 KeyValue *dst = g_new(KeyValue, 1); 76 memcpy(dst, src, sizeof(*src)); 77 if (dst->type == KEY_VALUE_KIND_NUMBER) { 78 QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number.data); 79 dst->type = KEY_VALUE_KIND_QCODE; 80 dst->u.qcode.data = code; 81 } 82 return dst; 83} 84 85void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, 86 Error **errp) 87{ 88 KeyValueList *p; 89 KeyValue **up = NULL; 90 int count = 0; 91 92 if (!has_hold_time) { 93 hold_time = 0; /* use default */ 94 } 95 96 for (p = keys; p != NULL; p = p->next) { 97 qemu_input_event_send_key(NULL, copy_key_value(p->value), true); 98 qemu_input_event_send_key_delay(hold_time); 99 up = g_realloc(up, sizeof(*up) * (count+1)); 100 up[count] = copy_key_value(p->value); 101 count++; 102 } 103 while (count) { 104 count--; 105 qemu_input_event_send_key(NULL, up[count], false); 106 qemu_input_event_send_key_delay(hold_time); 107 } 108 g_free(up); 109} 110 111static void legacy_kbd_event(DeviceState *dev, QemuConsole *src, 112 InputEvent *evt) 113{ 114 QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev; 115 int scancodes[3], i, count; 116 InputKeyEvent *key = evt->u.key.data; 117 118 if (!entry || !entry->put_kbd) { 119 return; 120 } 121 count = qemu_input_key_value_to_scancode(key->key, 122 key->down, 123 scancodes); 124 for (i = 0; i < count; i++) { 125 entry->put_kbd(entry->opaque, scancodes[i]); 126 } 127} 128 129static QemuInputHandler legacy_kbd_handler = { 130 .name = "legacy-kbd", 131 .mask = INPUT_EVENT_MASK_KEY, 132 .event = legacy_kbd_event, 133}; 134 135QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) 136{ 137 QEMUPutKbdEntry *entry; 138 139 entry = g_new0(QEMUPutKbdEntry, 1); 140 entry->put_kbd = func; 141 entry->opaque = opaque; 142 entry->s = qemu_input_handler_register((DeviceState *)entry, 143 &legacy_kbd_handler); 144 qemu_input_handler_activate(entry->s); 145 return entry; 146} 147 148static void legacy_mouse_event(DeviceState *dev, QemuConsole *src, 149 InputEvent *evt) 150{ 151 static const int bmap[INPUT_BUTTON__MAX] = { 152 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON, 153 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, 154 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON, 155 }; 156 QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev; 157 InputBtnEvent *btn; 158 InputMoveEvent *move; 159 160 switch (evt->type) { 161 case INPUT_EVENT_KIND_BTN: 162 btn = evt->u.btn.data; 163 if (btn->down) { 164 s->buttons |= bmap[btn->button]; 165 } else { 166 s->buttons &= ~bmap[btn->button]; 167 } 168 if (btn->down && btn->button == INPUT_BUTTON_WHEEL_UP) { 169 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, 170 s->axis[INPUT_AXIS_X], 171 s->axis[INPUT_AXIS_Y], 172 -1, 173 s->buttons); 174 } 175 if (btn->down && btn->button == INPUT_BUTTON_WHEEL_DOWN) { 176 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, 177 s->axis[INPUT_AXIS_X], 178 s->axis[INPUT_AXIS_Y], 179 1, 180 s->buttons); 181 } 182 break; 183 case INPUT_EVENT_KIND_ABS: 184 move = evt->u.abs.data; 185 s->axis[move->axis] = move->value; 186 break; 187 case INPUT_EVENT_KIND_REL: 188 move = evt->u.rel.data; 189 s->axis[move->axis] += move->value; 190 break; 191 default: 192 break; 193 } 194} 195 196static void legacy_mouse_sync(DeviceState *dev) 197{ 198 QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev; 199 200 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, 201 s->axis[INPUT_AXIS_X], 202 s->axis[INPUT_AXIS_Y], 203 0, 204 s->buttons); 205 206 if (!s->qemu_put_mouse_event_absolute) { 207 s->axis[INPUT_AXIS_X] = 0; 208 s->axis[INPUT_AXIS_Y] = 0; 209 } 210} 211 212QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, 213 void *opaque, int absolute, 214 const char *name) 215{ 216 QEMUPutMouseEntry *s; 217 218 s = g_new0(QEMUPutMouseEntry, 1); 219 220 s->qemu_put_mouse_event = func; 221 s->qemu_put_mouse_event_opaque = opaque; 222 s->qemu_put_mouse_event_absolute = absolute; 223 224 s->h.name = name; 225 s->h.mask = INPUT_EVENT_MASK_BTN | 226 (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL); 227 s->h.event = legacy_mouse_event; 228 s->h.sync = legacy_mouse_sync; 229 s->s = qemu_input_handler_register((DeviceState *)s, 230 &s->h); 231 232 return s; 233} 234 235void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry) 236{ 237 qemu_input_handler_activate(entry->s); 238} 239 240void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry) 241{ 242 qemu_input_handler_unregister(entry->s); 243 244 g_free(entry); 245} 246 247QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, 248 void *opaque) 249{ 250 QEMUPutLEDEntry *s; 251 252 s = g_new0(QEMUPutLEDEntry, 1); 253 254 s->put_led = func; 255 s->opaque = opaque; 256 QTAILQ_INSERT_TAIL(&led_handlers, s, next); 257 return s; 258} 259 260void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) 261{ 262 if (entry == NULL) 263 return; 264 QTAILQ_REMOVE(&led_handlers, entry, next); 265 g_free(entry); 266} 267 268void kbd_put_ledstate(int ledstate) 269{ 270 QEMUPutLEDEntry *cursor; 271 272 QTAILQ_FOREACH(cursor, &led_handlers, next) { 273 cursor->put_led(cursor->opaque, ledstate); 274 } 275}