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