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