1 #include "sysemu/sysemu.h" 2 #include "qapi-types.h" 3 #include "qmp-commands.h" 4 #include "trace.h" 5 #include "ui/input.h" 6 #include "ui/console.h" 7 8 struct QemuInputHandlerState { 9 DeviceState *dev; 10 QemuInputHandler *handler; 11 int id; 12 int events; 13 QTAILQ_ENTRY(QemuInputHandlerState) node; 14 }; 15 static QTAILQ_HEAD(, QemuInputHandlerState) handlers = 16 QTAILQ_HEAD_INITIALIZER(handlers); 17 static NotifierList mouse_mode_notifiers = 18 NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers); 19 20 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev, 21 QemuInputHandler *handler) 22 { 23 QemuInputHandlerState *s = g_new0(QemuInputHandlerState, 1); 24 static int id = 1; 25 26 s->dev = dev; 27 s->handler = handler; 28 s->id = id++; 29 QTAILQ_INSERT_TAIL(&handlers, s, node); 30 31 qemu_input_check_mode_change(); 32 return s; 33 } 34 35 void qemu_input_handler_activate(QemuInputHandlerState *s) 36 { 37 QTAILQ_REMOVE(&handlers, s, node); 38 QTAILQ_INSERT_HEAD(&handlers, s, node); 39 qemu_input_check_mode_change(); 40 } 41 42 void qemu_input_handler_deactivate(QemuInputHandlerState *s) 43 { 44 QTAILQ_REMOVE(&handlers, s, node); 45 QTAILQ_INSERT_TAIL(&handlers, s, node); 46 qemu_input_check_mode_change(); 47 } 48 49 void qemu_input_handler_unregister(QemuInputHandlerState *s) 50 { 51 QTAILQ_REMOVE(&handlers, s, node); 52 g_free(s); 53 qemu_input_check_mode_change(); 54 } 55 56 static QemuInputHandlerState* 57 qemu_input_find_handler(uint32_t mask) 58 { 59 QemuInputHandlerState *s; 60 61 QTAILQ_FOREACH(s, &handlers, node) { 62 if (mask & s->handler->mask) { 63 return s; 64 } 65 } 66 return NULL; 67 } 68 69 static void qemu_input_transform_abs_rotate(InputEvent *evt) 70 { 71 switch (graphic_rotate) { 72 case 90: 73 if (evt->abs->axis == INPUT_AXIS_X) { 74 evt->abs->axis = INPUT_AXIS_Y; 75 } else if (evt->abs->axis == INPUT_AXIS_Y) { 76 evt->abs->axis = INPUT_AXIS_X; 77 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value; 78 } 79 break; 80 case 180: 81 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value; 82 break; 83 case 270: 84 if (evt->abs->axis == INPUT_AXIS_X) { 85 evt->abs->axis = INPUT_AXIS_Y; 86 evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value; 87 } else if (evt->abs->axis == INPUT_AXIS_Y) { 88 evt->abs->axis = INPUT_AXIS_X; 89 } 90 break; 91 } 92 } 93 94 static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt) 95 { 96 const char *name; 97 int idx = -1; 98 99 if (src) { 100 idx = qemu_console_get_index(src); 101 } 102 switch (evt->kind) { 103 case INPUT_EVENT_KIND_KEY: 104 switch (evt->key->key->kind) { 105 case KEY_VALUE_KIND_NUMBER: 106 trace_input_event_key_number(idx, evt->key->key->number, 107 evt->key->down); 108 break; 109 case KEY_VALUE_KIND_QCODE: 110 name = QKeyCode_lookup[evt->key->key->qcode]; 111 trace_input_event_key_qcode(idx, name, evt->key->down); 112 break; 113 case KEY_VALUE_KIND_MAX: 114 /* keep gcc happy */ 115 break; 116 } 117 break; 118 case INPUT_EVENT_KIND_BTN: 119 name = InputButton_lookup[evt->btn->button]; 120 trace_input_event_btn(idx, name, evt->btn->down); 121 break; 122 case INPUT_EVENT_KIND_REL: 123 name = InputAxis_lookup[evt->rel->axis]; 124 trace_input_event_rel(idx, name, evt->rel->value); 125 break; 126 case INPUT_EVENT_KIND_ABS: 127 name = InputAxis_lookup[evt->abs->axis]; 128 trace_input_event_abs(idx, name, evt->abs->value); 129 break; 130 case INPUT_EVENT_KIND_MAX: 131 /* keep gcc happy */ 132 break; 133 } 134 } 135 136 void qemu_input_event_send(QemuConsole *src, InputEvent *evt) 137 { 138 QemuInputHandlerState *s; 139 140 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { 141 return; 142 } 143 144 qemu_input_event_trace(src, evt); 145 146 /* pre processing */ 147 if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) { 148 qemu_input_transform_abs_rotate(evt); 149 } 150 151 /* send event */ 152 s = qemu_input_find_handler(1 << evt->kind); 153 if (!s) { 154 return; 155 } 156 s->handler->event(s->dev, src, evt); 157 s->events++; 158 } 159 160 void qemu_input_event_sync(void) 161 { 162 QemuInputHandlerState *s; 163 164 if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { 165 return; 166 } 167 168 trace_input_event_sync(); 169 170 QTAILQ_FOREACH(s, &handlers, node) { 171 if (!s->events) { 172 continue; 173 } 174 if (s->handler->sync) { 175 s->handler->sync(s->dev); 176 } 177 s->events = 0; 178 } 179 } 180 181 InputEvent *qemu_input_event_new_key(KeyValue *key, bool down) 182 { 183 InputEvent *evt = g_new0(InputEvent, 1); 184 evt->key = g_new0(InputKeyEvent, 1); 185 evt->kind = INPUT_EVENT_KIND_KEY; 186 evt->key->key = key; 187 evt->key->down = down; 188 return evt; 189 } 190 191 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down) 192 { 193 InputEvent *evt; 194 evt = qemu_input_event_new_key(key, down); 195 qemu_input_event_send(src, evt); 196 qemu_input_event_sync(); 197 qapi_free_InputEvent(evt); 198 } 199 200 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down) 201 { 202 KeyValue *key = g_new0(KeyValue, 1); 203 key->kind = KEY_VALUE_KIND_NUMBER; 204 key->number = num; 205 qemu_input_event_send_key(src, key, down); 206 } 207 208 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down) 209 { 210 KeyValue *key = g_new0(KeyValue, 1); 211 key->kind = KEY_VALUE_KIND_QCODE; 212 key->qcode = q; 213 qemu_input_event_send_key(src, key, down); 214 } 215 216 InputEvent *qemu_input_event_new_btn(InputButton btn, bool down) 217 { 218 InputEvent *evt = g_new0(InputEvent, 1); 219 evt->btn = g_new0(InputBtnEvent, 1); 220 evt->kind = INPUT_EVENT_KIND_BTN; 221 evt->btn->button = btn; 222 evt->btn->down = down; 223 return evt; 224 } 225 226 void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down) 227 { 228 InputEvent *evt; 229 evt = qemu_input_event_new_btn(btn, down); 230 qemu_input_event_send(src, evt); 231 qapi_free_InputEvent(evt); 232 } 233 234 void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map, 235 uint32_t button_old, uint32_t button_new) 236 { 237 InputButton btn; 238 uint32_t mask; 239 240 for (btn = 0; btn < INPUT_BUTTON_MAX; btn++) { 241 mask = button_map[btn]; 242 if ((button_old & mask) == (button_new & mask)) { 243 continue; 244 } 245 qemu_input_queue_btn(src, btn, button_new & mask); 246 } 247 } 248 249 bool qemu_input_is_absolute(void) 250 { 251 QemuInputHandlerState *s; 252 253 s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS); 254 return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS); 255 } 256 257 int qemu_input_scale_axis(int value, int size_in, int size_out) 258 { 259 if (size_in < 2) { 260 return size_out / 2; 261 } 262 return (int64_t)value * (size_out - 1) / (size_in - 1); 263 } 264 265 InputEvent *qemu_input_event_new_move(InputEventKind kind, 266 InputAxis axis, int value) 267 { 268 InputEvent *evt = g_new0(InputEvent, 1); 269 InputMoveEvent *move = g_new0(InputMoveEvent, 1); 270 271 evt->kind = kind; 272 evt->data = move; 273 move->axis = axis; 274 move->value = value; 275 return evt; 276 } 277 278 void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value) 279 { 280 InputEvent *evt; 281 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value); 282 qemu_input_event_send(src, evt); 283 qapi_free_InputEvent(evt); 284 } 285 286 void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size) 287 { 288 InputEvent *evt; 289 int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE); 290 evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled); 291 qemu_input_event_send(src, evt); 292 qapi_free_InputEvent(evt); 293 } 294 295 void qemu_input_check_mode_change(void) 296 { 297 static int current_is_absolute; 298 int is_absolute; 299 300 is_absolute = qemu_input_is_absolute(); 301 302 if (is_absolute != current_is_absolute) { 303 trace_input_mouse_mode(is_absolute); 304 notifier_list_notify(&mouse_mode_notifiers, NULL); 305 } 306 307 current_is_absolute = is_absolute; 308 } 309 310 void qemu_add_mouse_mode_change_notifier(Notifier *notify) 311 { 312 notifier_list_add(&mouse_mode_notifiers, notify); 313 } 314 315 void qemu_remove_mouse_mode_change_notifier(Notifier *notify) 316 { 317 notifier_remove(notify); 318 } 319 320 MouseInfoList *qmp_query_mice(Error **errp) 321 { 322 MouseInfoList *mice_list = NULL; 323 MouseInfoList *info; 324 QemuInputHandlerState *s; 325 bool current = true; 326 327 QTAILQ_FOREACH(s, &handlers, node) { 328 if (!(s->handler->mask & 329 (INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS))) { 330 continue; 331 } 332 333 info = g_new0(MouseInfoList, 1); 334 info->value = g_new0(MouseInfo, 1); 335 info->value->index = s->id; 336 info->value->name = g_strdup(s->handler->name); 337 info->value->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS; 338 info->value->current = current; 339 340 current = false; 341 info->next = mice_list; 342 mice_list = info; 343 } 344 345 return mice_list; 346 } 347 348 void do_mouse_set(Monitor *mon, const QDict *qdict) 349 { 350 QemuInputHandlerState *s; 351 int index = qdict_get_int(qdict, "index"); 352 int found = 0; 353 354 QTAILQ_FOREACH(s, &handlers, node) { 355 if (s->id != index) { 356 continue; 357 } 358 if (!(s->handler->mask & (INPUT_EVENT_MASK_REL | 359 INPUT_EVENT_MASK_ABS))) { 360 error_report("Input device '%s' is not a mouse", s->handler->name); 361 return; 362 } 363 found = 1; 364 qemu_input_handler_activate(s); 365 break; 366 } 367 368 if (!found) { 369 error_report("Mouse at index '%d' not found", index); 370 } 371 372 qemu_input_check_mode_change(); 373 } 374