Statistics
| Branch: | Revision:

root / ui / input.c @ 9c17d615

History | View | Annotate | Download (13.3 kB)

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 "monitor/monitor.h"
27
#include "ui/console.h"
28
#include "qapi/error.h"
29
#include "qmp-commands.h"
30
#include "qapi-types.h"
31

    
32
static QEMUPutKBDEvent *qemu_put_kbd_event;
33
static void *qemu_put_kbd_event_opaque;
34
static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
35
static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
36
    QTAILQ_HEAD_INITIALIZER(mouse_handlers);
37
static NotifierList mouse_mode_notifiers = 
38
    NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
39

    
40
static const int key_defs[] = {
41
    [Q_KEY_CODE_SHIFT] = 0x2a,
42
    [Q_KEY_CODE_SHIFT_R] = 0x36,
43

    
44
    [Q_KEY_CODE_ALT] = 0x38,
45
    [Q_KEY_CODE_ALT_R] = 0xb8,
46
    [Q_KEY_CODE_ALTGR] = 0x64,
47
    [Q_KEY_CODE_ALTGR_R] = 0xe4,
48
    [Q_KEY_CODE_CTRL] = 0x1d,
49
    [Q_KEY_CODE_CTRL_R] = 0x9d,
50

    
51
    [Q_KEY_CODE_MENU] = 0xdd,
52

    
53
    [Q_KEY_CODE_ESC] = 0x01,
54

    
55
    [Q_KEY_CODE_1] = 0x02,
56
    [Q_KEY_CODE_2] = 0x03,
57
    [Q_KEY_CODE_3] = 0x04,
58
    [Q_KEY_CODE_4] = 0x05,
59
    [Q_KEY_CODE_5] = 0x06,
60
    [Q_KEY_CODE_6] = 0x07,
61
    [Q_KEY_CODE_7] = 0x08,
62
    [Q_KEY_CODE_8] = 0x09,
63
    [Q_KEY_CODE_9] = 0x0a,
64
    [Q_KEY_CODE_0] = 0x0b,
65
    [Q_KEY_CODE_MINUS] = 0x0c,
66
    [Q_KEY_CODE_EQUAL] = 0x0d,
67
    [Q_KEY_CODE_BACKSPACE] = 0x0e,
68

    
69
    [Q_KEY_CODE_TAB] = 0x0f,
70
    [Q_KEY_CODE_Q] = 0x10,
71
    [Q_KEY_CODE_W] = 0x11,
72
    [Q_KEY_CODE_E] = 0x12,
73
    [Q_KEY_CODE_R] = 0x13,
74
    [Q_KEY_CODE_T] = 0x14,
75
    [Q_KEY_CODE_Y] = 0x15,
76
    [Q_KEY_CODE_U] = 0x16,
77
    [Q_KEY_CODE_I] = 0x17,
78
    [Q_KEY_CODE_O] = 0x18,
79
    [Q_KEY_CODE_P] = 0x19,
80
    [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
81
    [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
82
    [Q_KEY_CODE_RET] = 0x1c,
83

    
84
    [Q_KEY_CODE_A] = 0x1e,
85
    [Q_KEY_CODE_S] = 0x1f,
86
    [Q_KEY_CODE_D] = 0x20,
87
    [Q_KEY_CODE_F] = 0x21,
88
    [Q_KEY_CODE_G] = 0x22,
89
    [Q_KEY_CODE_H] = 0x23,
90
    [Q_KEY_CODE_J] = 0x24,
91
    [Q_KEY_CODE_K] = 0x25,
92
    [Q_KEY_CODE_L] = 0x26,
93
    [Q_KEY_CODE_SEMICOLON] = 0x27,
94
    [Q_KEY_CODE_APOSTROPHE] = 0x28,
95
    [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
96

    
97
    [Q_KEY_CODE_BACKSLASH] = 0x2b,
98
    [Q_KEY_CODE_Z] = 0x2c,
99
    [Q_KEY_CODE_X] = 0x2d,
100
    [Q_KEY_CODE_C] = 0x2e,
101
    [Q_KEY_CODE_V] = 0x2f,
102
    [Q_KEY_CODE_B] = 0x30,
103
    [Q_KEY_CODE_N] = 0x31,
104
    [Q_KEY_CODE_M] = 0x32,
105
    [Q_KEY_CODE_COMMA] = 0x33,
106
    [Q_KEY_CODE_DOT] = 0x34,
107
    [Q_KEY_CODE_SLASH] = 0x35,
108

    
109
    [Q_KEY_CODE_ASTERISK] = 0x37,
110

    
111
    [Q_KEY_CODE_SPC] = 0x39,
112
    [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
113
    [Q_KEY_CODE_F1] = 0x3b,
114
    [Q_KEY_CODE_F2] = 0x3c,
115
    [Q_KEY_CODE_F3] = 0x3d,
116
    [Q_KEY_CODE_F4] = 0x3e,
117
    [Q_KEY_CODE_F5] = 0x3f,
118
    [Q_KEY_CODE_F6] = 0x40,
119
    [Q_KEY_CODE_F7] = 0x41,
120
    [Q_KEY_CODE_F8] = 0x42,
121
    [Q_KEY_CODE_F9] = 0x43,
122
    [Q_KEY_CODE_F10] = 0x44,
123
    [Q_KEY_CODE_NUM_LOCK] = 0x45,
124
    [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
125

    
126
    [Q_KEY_CODE_KP_DIVIDE] = 0xb5,
127
    [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
128
    [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
129
    [Q_KEY_CODE_KP_ADD] = 0x4e,
130
    [Q_KEY_CODE_KP_ENTER] = 0x9c,
131
    [Q_KEY_CODE_KP_DECIMAL] = 0x53,
132
    [Q_KEY_CODE_SYSRQ] = 0x54,
133

    
134
    [Q_KEY_CODE_KP_0] = 0x52,
135
    [Q_KEY_CODE_KP_1] = 0x4f,
136
    [Q_KEY_CODE_KP_2] = 0x50,
137
    [Q_KEY_CODE_KP_3] = 0x51,
138
    [Q_KEY_CODE_KP_4] = 0x4b,
139
    [Q_KEY_CODE_KP_5] = 0x4c,
140
    [Q_KEY_CODE_KP_6] = 0x4d,
141
    [Q_KEY_CODE_KP_7] = 0x47,
142
    [Q_KEY_CODE_KP_8] = 0x48,
143
    [Q_KEY_CODE_KP_9] = 0x49,
144

    
145
    [Q_KEY_CODE_LESS] = 0x56,
146

    
147
    [Q_KEY_CODE_F11] = 0x57,
148
    [Q_KEY_CODE_F12] = 0x58,
149

    
150
    [Q_KEY_CODE_PRINT] = 0xb7,
151

    
152
    [Q_KEY_CODE_HOME] = 0xc7,
153
    [Q_KEY_CODE_PGUP] = 0xc9,
154
    [Q_KEY_CODE_PGDN] = 0xd1,
155
    [Q_KEY_CODE_END] = 0xcf,
156

    
157
    [Q_KEY_CODE_LEFT] = 0xcb,
158
    [Q_KEY_CODE_UP] = 0xc8,
159
    [Q_KEY_CODE_DOWN] = 0xd0,
160
    [Q_KEY_CODE_RIGHT] = 0xcd,
161

    
162
    [Q_KEY_CODE_INSERT] = 0xd2,
163
    [Q_KEY_CODE_DELETE] = 0xd3,
164
#ifdef NEED_CPU_H
165
#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
166
    [Q_KEY_CODE_STOP] = 0xf0,
167
    [Q_KEY_CODE_AGAIN] = 0xf1,
168
    [Q_KEY_CODE_PROPS] = 0xf2,
169
    [Q_KEY_CODE_UNDO] = 0xf3,
170
    [Q_KEY_CODE_FRONT] = 0xf4,
171
    [Q_KEY_CODE_COPY] = 0xf5,
172
    [Q_KEY_CODE_OPEN] = 0xf6,
173
    [Q_KEY_CODE_PASTE] = 0xf7,
174
    [Q_KEY_CODE_FIND] = 0xf8,
175
    [Q_KEY_CODE_CUT] = 0xf9,
176
    [Q_KEY_CODE_LF] = 0xfa,
177
    [Q_KEY_CODE_HELP] = 0xfb,
178
    [Q_KEY_CODE_META_L] = 0xfc,
179
    [Q_KEY_CODE_META_R] = 0xfd,
180
    [Q_KEY_CODE_COMPOSE] = 0xfe,
181
#endif
182
#endif
183
    [Q_KEY_CODE_MAX] = 0,
184
};
185

    
186
int index_from_key(const char *key)
187
{
188
    int i;
189

    
190
    for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
191
        if (!strcmp(key, QKeyCode_lookup[i])) {
192
            break;
193
        }
194
    }
195

    
196
    /* Return Q_KEY_CODE_MAX if the key is invalid */
197
    return i;
198
}
199

    
200
int index_from_keycode(int code)
201
{
202
    int i;
203

    
204
    for (i = 0; i < Q_KEY_CODE_MAX; i++) {
205
        if (key_defs[i] == code) {
206
            break;
207
        }
208
    }
209

    
210
    /* Return Q_KEY_CODE_MAX if the code is invalid */
211
    return i;
212
}
213

    
214
static int *keycodes;
215
static int keycodes_size;
216
static QEMUTimer *key_timer;
217

    
218
static int keycode_from_keyvalue(const KeyValue *value)
219
{
220
    if (value->kind == KEY_VALUE_KIND_QCODE) {
221
        return key_defs[value->qcode];
222
    } else {
223
        assert(value->kind == KEY_VALUE_KIND_NUMBER);
224
        return value->number;
225
    }
226
}
227

    
228
static void free_keycodes(void)
229
{
230
    g_free(keycodes);
231
    keycodes = NULL;
232
    keycodes_size = 0;
233
}
234

    
235
static void release_keys(void *opaque)
236
{
237
    int i;
238

    
239
    for (i = 0; i < keycodes_size; i++) {
240
        if (keycodes[i] & 0x80) {
241
            kbd_put_keycode(0xe0);
242
        }
243
        kbd_put_keycode(keycodes[i]| 0x80);
244
    }
245

    
246
    free_keycodes();
247
}
248

    
249
void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
250
                  Error **errp)
251
{
252
    int keycode;
253
    KeyValueList *p;
254

    
255
    if (!key_timer) {
256
        key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
257
    }
258

    
259
    if (keycodes != NULL) {
260
        qemu_del_timer(key_timer);
261
        release_keys(NULL);
262
    }
263

    
264
    if (!has_hold_time) {
265
        hold_time = 100;
266
    }
267

    
268
    for (p = keys; p != NULL; p = p->next) {
269
        /* key down events */
270
        keycode = keycode_from_keyvalue(p->value);
271
        if (keycode < 0x01 || keycode > 0xff) {
272
            error_setg(errp, "invalid hex keycode 0x%x\n", keycode);
273
            free_keycodes();
274
            return;
275
        }
276

    
277
        if (keycode & 0x80) {
278
            kbd_put_keycode(0xe0);
279
        }
280
        kbd_put_keycode(keycode & 0x7f);
281

    
282
        keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
283
        keycodes[keycodes_size++] = keycode;
284
    }
285

    
286
    /* delayed key up events */
287
    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
288
                   muldiv64(get_ticks_per_sec(), hold_time, 1000));
289
}
290

    
291
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
292
{
293
    qemu_put_kbd_event_opaque = opaque;
294
    qemu_put_kbd_event = func;
295
}
296

    
297
void qemu_remove_kbd_event_handler(void)
298
{
299
    qemu_put_kbd_event_opaque = NULL;
300
    qemu_put_kbd_event = NULL;
301
}
302

    
303
static void check_mode_change(void)
304
{
305
    static int current_is_absolute, current_has_absolute;
306
    int is_absolute;
307
    int has_absolute;
308

    
309
    is_absolute = kbd_mouse_is_absolute();
310
    has_absolute = kbd_mouse_has_absolute();
311

    
312
    if (is_absolute != current_is_absolute ||
313
        has_absolute != current_has_absolute) {
314
        notifier_list_notify(&mouse_mode_notifiers, NULL);
315
    }
316

    
317
    current_is_absolute = is_absolute;
318
    current_has_absolute = has_absolute;
319
}
320

    
321
QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
322
                                                void *opaque, int absolute,
323
                                                const char *name)
324
{
325
    QEMUPutMouseEntry *s;
326
    static int mouse_index = 0;
327

    
328
    s = g_malloc0(sizeof(QEMUPutMouseEntry));
329

    
330
    s->qemu_put_mouse_event = func;
331
    s->qemu_put_mouse_event_opaque = opaque;
332
    s->qemu_put_mouse_event_absolute = absolute;
333
    s->qemu_put_mouse_event_name = g_strdup(name);
334
    s->index = mouse_index++;
335

    
336
    QTAILQ_INSERT_TAIL(&mouse_handlers, s, node);
337

    
338
    check_mode_change();
339

    
340
    return s;
341
}
342

    
343
void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
344
{
345
    QTAILQ_REMOVE(&mouse_handlers, entry, node);
346
    QTAILQ_INSERT_HEAD(&mouse_handlers, entry, node);
347

    
348
    check_mode_change();
349
}
350

    
351
void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
352
{
353
    QTAILQ_REMOVE(&mouse_handlers, entry, node);
354

    
355
    g_free(entry->qemu_put_mouse_event_name);
356
    g_free(entry);
357

    
358
    check_mode_change();
359
}
360

    
361
QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
362
                                            void *opaque)
363
{
364
    QEMUPutLEDEntry *s;
365

    
366
    s = g_malloc0(sizeof(QEMUPutLEDEntry));
367

    
368
    s->put_led = func;
369
    s->opaque = opaque;
370
    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
371
    return s;
372
}
373

    
374
void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
375
{
376
    if (entry == NULL)
377
        return;
378
    QTAILQ_REMOVE(&led_handlers, entry, next);
379
    g_free(entry);
380
}
381

    
382
void kbd_put_keycode(int keycode)
383
{
384
    if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
385
        return;
386
    }
387
    if (qemu_put_kbd_event) {
388
        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
389
    }
390
}
391

    
392
void kbd_put_ledstate(int ledstate)
393
{
394
    QEMUPutLEDEntry *cursor;
395

    
396
    QTAILQ_FOREACH(cursor, &led_handlers, next) {
397
        cursor->put_led(cursor->opaque, ledstate);
398
    }
399
}
400

    
401
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
402
{
403
    QEMUPutMouseEntry *entry;
404
    QEMUPutMouseEvent *mouse_event;
405
    void *mouse_event_opaque;
406
    int width, height;
407

    
408
    if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
409
        return;
410
    }
411
    if (QTAILQ_EMPTY(&mouse_handlers)) {
412
        return;
413
    }
414

    
415
    entry = QTAILQ_FIRST(&mouse_handlers);
416

    
417
    mouse_event = entry->qemu_put_mouse_event;
418
    mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
419

    
420
    if (mouse_event) {
421
        if (entry->qemu_put_mouse_event_absolute) {
422
            width = 0x7fff;
423
            height = 0x7fff;
424
        } else {
425
            width = graphic_width - 1;
426
            height = graphic_height - 1;
427
        }
428

    
429
        switch (graphic_rotate) {
430
        case 0:
431
            mouse_event(mouse_event_opaque,
432
                        dx, dy, dz, buttons_state);
433
            break;
434
        case 90:
435
            mouse_event(mouse_event_opaque,
436
                        width - dy, dx, dz, buttons_state);
437
            break;
438
        case 180:
439
            mouse_event(mouse_event_opaque,
440
                        width - dx, height - dy, dz, buttons_state);
441
            break;
442
        case 270:
443
            mouse_event(mouse_event_opaque,
444
                        dy, height - dx, dz, buttons_state);
445
            break;
446
        }
447
    }
448
}
449

    
450
int kbd_mouse_is_absolute(void)
451
{
452
    if (QTAILQ_EMPTY(&mouse_handlers)) {
453
        return 0;
454
    }
455

    
456
    return QTAILQ_FIRST(&mouse_handlers)->qemu_put_mouse_event_absolute;
457
}
458

    
459
int kbd_mouse_has_absolute(void)
460
{
461
    QEMUPutMouseEntry *entry;
462

    
463
    QTAILQ_FOREACH(entry, &mouse_handlers, node) {
464
        if (entry->qemu_put_mouse_event_absolute) {
465
            return 1;
466
        }
467
    }
468

    
469
    return 0;
470
}
471

    
472
MouseInfoList *qmp_query_mice(Error **errp)
473
{
474
    MouseInfoList *mice_list = NULL;
475
    QEMUPutMouseEntry *cursor;
476
    bool current = true;
477

    
478
    QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
479
        MouseInfoList *info = g_malloc0(sizeof(*info));
480
        info->value = g_malloc0(sizeof(*info->value));
481
        info->value->name = g_strdup(cursor->qemu_put_mouse_event_name);
482
        info->value->index = cursor->index;
483
        info->value->absolute = !!cursor->qemu_put_mouse_event_absolute;
484
        info->value->current = current;
485

    
486
        current = false;
487

    
488
        info->next = mice_list;
489
        mice_list = info;
490
    }
491

    
492
    return mice_list;
493
}
494

    
495
void do_mouse_set(Monitor *mon, const QDict *qdict)
496
{
497
    QEMUPutMouseEntry *cursor;
498
    int index = qdict_get_int(qdict, "index");
499
    int found = 0;
500

    
501
    if (QTAILQ_EMPTY(&mouse_handlers)) {
502
        monitor_printf(mon, "No mouse devices connected\n");
503
        return;
504
    }
505

    
506
    QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
507
        if (cursor->index == index) {
508
            found = 1;
509
            qemu_activate_mouse_event_handler(cursor);
510
            break;
511
        }
512
    }
513

    
514
    if (!found) {
515
        monitor_printf(mon, "Mouse at given index not found\n");
516
    }
517

    
518
    check_mode_change();
519
}
520

    
521
void qemu_add_mouse_mode_change_notifier(Notifier *notify)
522
{
523
    notifier_list_add(&mouse_mode_notifiers, notify);
524
}
525

    
526
void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
527
{
528
    notifier_remove(notify);
529
}