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