input-legacy.c 7.8 KB

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