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