qemu/ui/input-legacy.c

267 lines
7.6 KiB
C
Raw Normal View History

/*
* QEMU System Emulator
*
* Copyright (c) 2003-2008 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "sysemu/sysemu.h"
#include "ui/console.h"
#include "qapi/error.h"
#include "qmp-commands.h"
#include "qapi-types.h"
#include "ui/keymaps.h"
#include "ui/input.h"
struct QEMUPutMouseEntry {
QEMUPutMouseEvent *qemu_put_mouse_event;
void *qemu_put_mouse_event_opaque;
int qemu_put_mouse_event_absolute;
/* new input core */
QemuInputHandler h;
QemuInputHandlerState *s;
int axis[INPUT_AXIS__MAX];
int buttons;
};
struct QEMUPutKbdEntry {
QEMUPutKBDEvent *put_kbd;
void *opaque;
QemuInputHandlerState *s;
};
struct QEMUPutLEDEntry {
QEMUPutLEDEvent *put_led;
void *opaque;
QTAILQ_ENTRY(QEMUPutLEDEntry) next;
};
static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
QTAILQ_HEAD_INITIALIZER(led_handlers);
int index_from_key(const char *key)
{
int i;
for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
if (!strcmp(key, QKeyCode_lookup[i])) {
break;
}
}
/* Return Q_KEY_CODE__MAX if the key is invalid */
return i;
}
static KeyValue *copy_key_value(KeyValue *src)
{
KeyValue *dst = g_new(KeyValue, 1);
memcpy(dst, src, sizeof(*src));
return dst;
}
void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
Error **errp)
{
KeyValueList *p;
KeyValue **up = NULL;
int count = 0;
if (!has_hold_time) {
hold_time = 0; /* use default */
}
for (p = keys; p != NULL; p = p->next) {
qemu_input_event_send_key(NULL, copy_key_value(p->value), true);
qemu_input_event_send_key_delay(hold_time);
up = g_realloc(up, sizeof(*up) * (count+1));
up[count] = copy_key_value(p->value);
count++;
}
while (count) {
count--;
qemu_input_event_send_key(NULL, up[count], false);
qemu_input_event_send_key_delay(hold_time);
}
g_free(up);
}
static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt)
{
QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
int scancodes[3], i, count;
if (!entry || !entry->put_kbd) {
return;
}
count = qemu_input_key_value_to_scancode(evt->u.key->key,
evt->u.key->down,
scancodes);
for (i = 0; i < count; i++) {
entry->put_kbd(entry->opaque, scancodes[i]);
}
}
static QemuInputHandler legacy_kbd_handler = {
.name = "legacy-kbd",
.mask = INPUT_EVENT_MASK_KEY,
.event = legacy_kbd_event,
};
QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{
QEMUPutKbdEntry *entry;
entry = g_new0(QEMUPutKbdEntry, 1);
entry->put_kbd = func;
entry->opaque = opaque;
entry->s = qemu_input_handler_register((DeviceState *)entry,
&legacy_kbd_handler);
qemu_input_handler_activate(entry->s);
return entry;
}
static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt)
{
static const int bmap[INPUT_BUTTON__MAX] = {
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
};
QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
switch (evt->type) {
case INPUT_EVENT_KIND_BTN:
if (evt->u.btn->down) {
s->buttons |= bmap[evt->u.btn->button];
} else {
s->buttons &= ~bmap[evt->u.btn->button];
}
qapi: Change munging of CamelCase enum values When munging enum values, the fact that we were passing the entire prefix + value through camel_to_upper() meant that enum values spelled with CamelCase could be turned into CAMEL_CASE. However, this provides a potential collision (both OneTwo and One-Two would munge into ONE_TWO) for enum types, when the same two names are valid side-by-side as QAPI member names. By changing the generation of enum constants to always be prefix + '_' + c_name(value, False).upper(), and ensuring that there are no case collisions (in the next patches), we no longer have to worry about names that would be distinct as QAPI members but collide as variant tag names, without having to think about what munging the heuristics in camel_to_upper() will actually perform on an enum value. Making the change will affect enums that did not follow coding conventions, using 'CamelCase' rather than desired 'lower-case'. Thankfully, there are only two culprits: InputButton and ErrorClass. We already tweaked ErrorClass to make it an alias of QapiErrorClass, where only the alias needs changing rather than the whole tree. So the bulk of this change is modifying INPUT_BUTTON_WHEEL_UP to the new INPUT_BUTTON_WHEELUP (and likewise for WHEELDOWN). That part of this commit may later need reverting if we rename the enum constants from 'WheelUp' to 'wheel-up' as part of moving x-input-send-event to a stable interface; but at least we have documentation bread crumbs in place to remind us (commit 513e7cd), and it matches the fact that SDL constants are also spelled SDL_BUTTON_WHEELUP. Suggested by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1447836791-369-27-git-send-email-eblake@redhat.com> [Commit message tweaked] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 16:53:01 +08:00
if (evt->u.btn->down && evt->u.btn->button == INPUT_BUTTON_WHEELUP) {
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
s->axis[INPUT_AXIS_X],
s->axis[INPUT_AXIS_Y],
-1,
s->buttons);
}
if (evt->u.btn->down &&
qapi: Change munging of CamelCase enum values When munging enum values, the fact that we were passing the entire prefix + value through camel_to_upper() meant that enum values spelled with CamelCase could be turned into CAMEL_CASE. However, this provides a potential collision (both OneTwo and One-Two would munge into ONE_TWO) for enum types, when the same two names are valid side-by-side as QAPI member names. By changing the generation of enum constants to always be prefix + '_' + c_name(value, False).upper(), and ensuring that there are no case collisions (in the next patches), we no longer have to worry about names that would be distinct as QAPI members but collide as variant tag names, without having to think about what munging the heuristics in camel_to_upper() will actually perform on an enum value. Making the change will affect enums that did not follow coding conventions, using 'CamelCase' rather than desired 'lower-case'. Thankfully, there are only two culprits: InputButton and ErrorClass. We already tweaked ErrorClass to make it an alias of QapiErrorClass, where only the alias needs changing rather than the whole tree. So the bulk of this change is modifying INPUT_BUTTON_WHEEL_UP to the new INPUT_BUTTON_WHEELUP (and likewise for WHEELDOWN). That part of this commit may later need reverting if we rename the enum constants from 'WheelUp' to 'wheel-up' as part of moving x-input-send-event to a stable interface; but at least we have documentation bread crumbs in place to remind us (commit 513e7cd), and it matches the fact that SDL constants are also spelled SDL_BUTTON_WHEELUP. Suggested by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1447836791-369-27-git-send-email-eblake@redhat.com> [Commit message tweaked] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 16:53:01 +08:00
evt->u.btn->button == INPUT_BUTTON_WHEELDOWN) {
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
s->axis[INPUT_AXIS_X],
s->axis[INPUT_AXIS_Y],
1,
s->buttons);
}
break;
case INPUT_EVENT_KIND_ABS:
s->axis[evt->u.abs->axis] = evt->u.abs->value;
break;
case INPUT_EVENT_KIND_REL:
s->axis[evt->u.rel->axis] += evt->u.rel->value;
break;
default:
break;
}
}
static void legacy_mouse_sync(DeviceState *dev)
{
QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
s->axis[INPUT_AXIS_X],
s->axis[INPUT_AXIS_Y],
0,
s->buttons);
if (!s->qemu_put_mouse_event_absolute) {
s->axis[INPUT_AXIS_X] = 0;
s->axis[INPUT_AXIS_Y] = 0;
}
}
QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
void *opaque, int absolute,
const char *name)
{
QEMUPutMouseEntry *s;
s = g_new0(QEMUPutMouseEntry, 1);
s->qemu_put_mouse_event = func;
s->qemu_put_mouse_event_opaque = opaque;
s->qemu_put_mouse_event_absolute = absolute;
s->h.name = name;
s->h.mask = INPUT_EVENT_MASK_BTN |
(absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
s->h.event = legacy_mouse_event;
s->h.sync = legacy_mouse_sync;
s->s = qemu_input_handler_register((DeviceState *)s,
&s->h);
return s;
}
void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
{
qemu_input_handler_activate(entry->s);
}
void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
{
qemu_input_handler_unregister(entry->s);
g_free(entry);
}
QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
void *opaque)
{
QEMUPutLEDEntry *s;
s = g_new0(QEMUPutLEDEntry, 1);
s->put_led = func;
s->opaque = opaque;
QTAILQ_INSERT_TAIL(&led_handlers, s, next);
return s;
}
void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
{
if (entry == NULL)
return;
QTAILQ_REMOVE(&led_handlers, entry, next);
g_free(entry);
}
void kbd_put_ledstate(int ledstate)
{
QEMUPutLEDEntry *cursor;
QTAILQ_FOREACH(cursor, &led_handlers, next) {
cursor->put_led(cursor->opaque, ledstate);
}
}