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