Compare commits

...

10 Commits

Author SHA1 Message Date
Gerd Hoffmann
8977bd111f docs: add multiseat.txt
Howto on setting up multiseat for guests.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
f85d28316a usb: add input routing support for tablet and keyboard
Add display property to the keyboard.
Add display and head properties to the tablet.

If properties are set bind device to the display specified to
setup input routing.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
ee8c0b622c sdl: pass key event source to input layer
So the input layer knows where the input is coming from
and input routing works correctly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
6f5943cf45 input: bind devices and input routing
Add function to bind input devices to display devices.  Implementing
input routing on top of this:  Events coming from the display device in
question are routed to the input device bound to it (if there is one).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
8b84286f4c input: switch hid mouse and tablet to the new input layer api.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
1ff5eedd1d input: switch hid keyboard to new input layer api.
Minimal patch to get the switchover done.  We continue processing ps/2
scancodes for now as they are part of the live migration stream.  Fixing
that, then mapping directly from QKeyValue to HID keycodes is left as
excercise for another day.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
86846bfe64 input: keymap: add meta keys
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:43 +02:00
Gerd Hoffmann
2386a90730 input: add name to input_event_key_number
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:42 +02:00
Gerd Hoffmann
11c7fa7fa6 input: add qemu_input_key_number_to_qcode
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:42 +02:00
Andrew Oates
f5c0ab1312 input (curses): mask keycodes to remove modifier bits
Without the mask, control bits are passed on in the keycode, generating
incorrect PS/2 sequences when SHIFT, ALT, etc are held down.

Cc: qemu-stable@nongnu.org
Signed-off-by: Andrew Oates <andrew@aoates.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:42:42 +02:00
10 changed files with 309 additions and 99 deletions

76
docs/multiseat.txt Normal file
View File

@@ -0,0 +1,76 @@
multiseat howto (with some multihead coverage)
==============================================
host side
---------
First you must compile qemu with a user interface supporting
multihead/multiseat and input event routing. Right now this list is
pretty short: sdl2.
./configure --enable-sdl --with-sdlabi=2.0
Next put together the qemu command line:
qemu -enable-kvm -usb $memory $disk $whatever \
-display sdl \
-vga std \
-device usb-tablet
That is it for the first head, which will use the standard vga, the
standard ps/2 keyboard (implicitly there) and the usb-tablet. Now the
additional switches for the second head:
-device pci-bridge,addr=12.0,chassis_nr=2,id=head.2 \
-device secondary-vga,bus=head.2,addr=02.0,id=video.2 \
-device nec-usb-xhci,bus=head.2,addr=0f.0,id=usb.2 \
-device usb-kbd,bus=usb.2.0,port=1,display=video.2 \
-device usb-tablet,bus=usb.2.0,port=2,display=video.2
This places a pci bridge in slot 12, connects a display adapter and
xhci (usb) controller to the bridge. Then it adds a usb keyboard and
usb mouse, both connected to the xhci and linked to the display.
The "display=video2" sets up the input routing. Any input coming from
the window which belongs to the video.2 display adapter will be routed
to these input devices.
guest side
----------
You need a pretty recent linux guest. systemd with loginctl. kernel
3.14+ with CONFIG_DRM_BOCHS enabled. Fedora 20 will do. Must be
fully updated for the new kernel though, i.e. the live iso doesn't cut
it.
Now we'll have to configure the guest. Boot and login. By default
all devices belong to seat0. You can use "loginctl seat-status seat0"
to list them all (and to get the sysfs paths for cut+paste). Now
we'll go assign all pci devices connected the pci bridge in slot 12 to
a new head:
loginctl attach seat-qemu \
/sys/devices/pci0000:00/0000:00:12.0/0000:01:02.0/drm/card1
loginctl attach seat-qemu \
/sys/devices/pci0000:00/0000:00:12.0/0000:01:02.0/graphics/fb1
loginctl attach seat-qemu \
/sys/devices/pci0000:00/0000:00:12.0/0000:01:0f.0/usb2
Use "loginctl seat-status seat-qemu" to check the result. It isn't
needed to assign the usb devices to the head individually, assigning a
usb (root) hub will automatically assign all usb devices connected to
it too.
BTW: loginctl writes udev rules to /etc/udev/rules.d to make these
device assignments permanent, so you need to do this only once.
Now simply restart gdm (rebooting will do too), and a login screen
should show up on the second head.
Enjoy!
--
Gerd Hoffmann <kraxel@redhat.com>

View File

@@ -105,70 +105,135 @@ void hid_set_next_idle(HIDState *hs)
}
}
static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons)
static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt)
{
e->xdx = e->ydy = e->dz = 0;
e->buttons_state = buttons;
static const int bmap[INPUT_BUTTON_MAX] = {
[INPUT_BUTTON_LEFT] = 0x01,
[INPUT_BUTTON_RIGHT] = 0x02,
[INPUT_BUTTON_MIDDLE] = 0x04,
};
HIDState *hs = (HIDState *)dev;
HIDPointerEvent *e;
assert(hs->n < QUEUE_LENGTH);
e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
switch (evt->kind) {
case INPUT_EVENT_KIND_REL:
if (evt->rel->axis == INPUT_AXIS_X) {
e->xdx += evt->rel->value;
} else if (evt->rel->axis == INPUT_AXIS_Y) {
e->ydy -= evt->rel->value;
}
break;
case INPUT_EVENT_KIND_ABS:
if (evt->rel->axis == INPUT_AXIS_X) {
e->xdx = evt->rel->value;
} else if (evt->rel->axis == INPUT_AXIS_Y) {
e->ydy = evt->rel->value;
}
break;
case INPUT_EVENT_KIND_BTN:
if (evt->btn->down) {
e->buttons_state |= bmap[evt->btn->button];
if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) {
e->dz--;
} else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) {
e->dz++;
}
} else {
e->buttons_state &= ~bmap[evt->btn->button];
}
break;
default:
/* keep gcc happy */
break;
}
}
static void hid_pointer_event_combine(HIDPointerEvent *e, int xyrel,
int x1, int y1, int z1) {
if (xyrel) {
e->xdx += x1;
e->ydy += y1;
} else {
e->xdx = x1;
e->ydy = y1;
/* Windows drivers do not like the 0/0 position and ignore such
* events. */
if (!(x1 | y1)) {
e->xdx = 1;
static void hid_pointer_sync(DeviceState *dev)
{
HIDState *hs = (HIDState *)dev;
HIDPointerEvent *prev, *curr, *next;
bool event_compression = false;
if (hs->n == QUEUE_LENGTH-1) {
/*
* Queue full. We are loosing information, but we at least
* keep track of most recent button state.
*/
return;
}
prev = &hs->ptr.queue[(hs->head + hs->n - 1) & QUEUE_MASK];
curr = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
next = &hs->ptr.queue[(hs->head + hs->n + 1) & QUEUE_MASK];
if (hs->n > 0) {
/*
* No button state change between previous and current event
* (and previous wasn't seen by the guest yet), so there is
* motion information only and we can combine the two event
* into one.
*/
if (curr->buttons_state == prev->buttons_state) {
event_compression = true;
}
}
e->dz += z1;
}
static void hid_pointer_event(void *opaque,
int x1, int y1, int z1, int buttons_state)
{
HIDState *hs = opaque;
unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
/* We combine events where feasible to keep the queue small. We shouldn't
* combine anything with the first event of a particular button state, as
* that would change the location of the button state change. When the
* queue is empty, a second event is needed because we don't know if
* the first event changed the button state. */
if (hs->n == QUEUE_LENGTH) {
/* Queue full. Discard old button state, combine motion normally. */
hs->ptr.queue[use_slot].buttons_state = buttons_state;
} else if (hs->n < 2 ||
hs->ptr.queue[use_slot].buttons_state != buttons_state ||
hs->ptr.queue[previous_slot].buttons_state !=
hs->ptr.queue[use_slot].buttons_state) {
/* Cannot or should not combine, so add an empty item to the queue. */
QUEUE_INCR(use_slot);
if (event_compression) {
/* add current motion to previous, clear current */
if (hs->kind == HID_MOUSE) {
prev->xdx += curr->xdx;
curr->xdx = 0;
prev->ydy -= curr->ydy;
curr->ydy = 0;
} else {
prev->xdx = curr->xdx;
prev->ydy = curr->ydy;
}
prev->dz += curr->dz;
curr->dz = 0;
} else {
/* prepate next (clear rel, copy abs + btns) */
if (hs->kind == HID_MOUSE) {
next->xdx = 0;
next->ydy = 0;
} else {
next->xdx = curr->xdx;
next->ydy = curr->ydy;
}
next->dz = 0;
next->buttons_state = curr->buttons_state;
/* make current guest visible, notify guest */
hs->n++;
hid_pointer_event_clear(&hs->ptr.queue[use_slot], buttons_state);
hs->event(hs);
}
hid_pointer_event_combine(&hs->ptr.queue[use_slot],
hs->kind == HID_MOUSE,
x1, y1, z1);
hs->event(hs);
}
static void hid_keyboard_event(void *opaque, int keycode)
static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt)
{
HIDState *hs = opaque;
HIDState *hs = (HIDState *)dev;
int scancodes[3], i, count;
int slot;
if (hs->n == QUEUE_LENGTH) {
count = qemu_input_key_value_to_scancode(evt->key->key,
evt->key->down,
scancodes);
if (hs->n + count > QUEUE_LENGTH) {
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
return;
}
slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
hs->kbd.keycodes[slot] = keycode;
for (i = 0; i < count; i++) {
slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
hs->kbd.keycodes[slot] = scancodes[i];
}
hs->event(hs);
}
@@ -247,14 +312,14 @@ static inline int int_clamp(int val, int vmin, int vmax)
void hid_pointer_activate(HIDState *hs)
{
if (!hs->ptr.mouse_grabbed) {
qemu_activate_mouse_event_handler(hs->ptr.eh_entry);
qemu_input_handler_activate(hs->s);
hs->ptr.mouse_grabbed = 1;
}
}
int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
{
int dx, dy, dz, b, l;
int dx, dy, dz, l;
int index;
HIDPointerEvent *e;
@@ -279,17 +344,6 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
dz = int_clamp(e->dz, -127, 127);
e->dz -= dz;
b = 0;
if (e->buttons_state & MOUSE_EVENT_LBUTTON) {
b |= 0x01;
}
if (e->buttons_state & MOUSE_EVENT_RBUTTON) {
b |= 0x02;
}
if (e->buttons_state & MOUSE_EVENT_MBUTTON) {
b |= 0x04;
}
if (hs->n &&
!e->dz &&
(hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) {
@@ -304,7 +358,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
switch (hs->kind) {
case HID_MOUSE:
if (len > l) {
buf[l++] = b;
buf[l++] = e->buttons_state;
}
if (len > l) {
buf[l++] = dx;
@@ -319,7 +373,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
case HID_TABLET:
if (len > l) {
buf[l++] = b;
buf[l++] = e->buttons_state;
}
if (len > l) {
buf[l++] = dx & 0xff;
@@ -413,31 +467,45 @@ void hid_reset(HIDState *hs)
void hid_free(HIDState *hs)
{
switch (hs->kind) {
case HID_KEYBOARD:
qemu_remove_kbd_event_handler(hs->kbd.eh_entry);
break;
case HID_MOUSE:
case HID_TABLET:
qemu_remove_mouse_event_handler(hs->ptr.eh_entry);
break;
}
qemu_input_handler_unregister(hs->s);
hid_del_idle_timer(hs);
}
static QemuInputHandler hid_keyboard_handler = {
.name = "QEMU HID Keyboard",
.mask = INPUT_EVENT_MASK_KEY,
.event = hid_keyboard_event,
};
static QemuInputHandler hid_mouse_handler = {
.name = "QEMU HID Mouse",
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
.event = hid_pointer_event,
.sync = hid_pointer_sync,
};
static QemuInputHandler hid_tablet_handler = {
.name = "QEMU HID Tablet",
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
.event = hid_pointer_event,
.sync = hid_pointer_sync,
};
void hid_init(HIDState *hs, int kind, HIDEventFunc event)
{
hs->kind = kind;
hs->event = event;
if (hs->kind == HID_KEYBOARD) {
hs->kbd.eh_entry = qemu_add_kbd_event_handler(hid_keyboard_event, hs);
hs->s = qemu_input_handler_register((DeviceState *)hs,
&hid_keyboard_handler);
qemu_input_handler_activate(hs->s);
} else if (hs->kind == HID_MOUSE) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
0, "QEMU HID Mouse");
hs->s = qemu_input_handler_register((DeviceState *)hs,
&hid_mouse_handler);
} else if (hs->kind == HID_TABLET) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
1, "QEMU HID Tablet");
hs->s = qemu_input_handler_register((DeviceState *)hs,
&hid_tablet_handler);
}
}

View File

@@ -47,6 +47,8 @@ typedef struct USBHIDState {
USBEndpoint *intr;
HIDState hid;
uint32_t usb_version;
char *display;
uint32_t head;
} USBHIDState;
enum {
@@ -574,6 +576,9 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
usb_desc_init(dev);
us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
hid_init(&us->hid, kind, usb_hid_changed);
if (us->display && us->hid.s) {
qemu_input_handler_bind(us->hid.s, us->display, us->head, NULL);
}
return 0;
}
@@ -653,6 +658,8 @@ static void usb_hid_class_initfn(ObjectClass *klass, void *data)
static Property usb_tablet_properties[] = {
DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
DEFINE_PROP_STRING("display", USBHIDState, display),
DEFINE_PROP_UINT32("head", USBHIDState, head, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -696,6 +703,11 @@ static const TypeInfo usb_mouse_info = {
.class_init = usb_mouse_class_initfn,
};
static Property usb_keyboard_properties[] = {
DEFINE_PROP_STRING("display", USBHIDState, display),
DEFINE_PROP_END_OF_LIST(),
};
static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -706,6 +718,7 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
uc->product_desc = "QEMU USB Keyboard";
uc->usb_desc = &desc_keyboard;
dc->vmsd = &vmstate_usb_kbd;
dc->props = usb_keyboard_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}

View File

@@ -2,6 +2,7 @@
#define QEMU_HID_H
#include "migration/vmstate.h"
#include "ui/input.h"
#define HID_MOUSE 1
#define HID_TABLET 2
@@ -22,7 +23,6 @@ typedef void (*HIDEventFunc)(HIDState *s);
typedef struct HIDMouseState {
HIDPointerEvent queue[QUEUE_LENGTH];
int mouse_grabbed;
QEMUPutMouseEntry *eh_entry;
} HIDMouseState;
typedef struct HIDKeyboardState {
@@ -31,7 +31,6 @@ typedef struct HIDKeyboardState {
uint8_t leds;
uint8_t key[16];
int32_t keys;
QEMUPutKbdEntry *eh_entry;
} HIDKeyboardState;
struct HIDState {
@@ -47,6 +46,7 @@ struct HIDState {
bool idle_pending;
QEMUTimer *idle_timer;
HIDEventFunc event;
QemuInputHandlerState *s;
};
void hid_init(HIDState *hs, int kind, HIDEventFunc event);

View File

@@ -29,6 +29,9 @@ QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
void qemu_input_handler_activate(QemuInputHandlerState *s);
void qemu_input_handler_deactivate(QemuInputHandlerState *s);
void qemu_input_handler_unregister(QemuInputHandlerState *s);
void qemu_input_handler_bind(QemuInputHandlerState *s,
const char *device_id, int head,
Error **errp);
void qemu_input_event_send(QemuConsole *src, InputEvent *evt);
void qemu_input_event_sync(void);
@@ -36,6 +39,7 @@ InputEvent *qemu_input_event_new_key(KeyValue *key, bool down);
void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down);
void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down);
void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down);
int qemu_input_key_number_to_qcode(uint8_t nr);
int qemu_input_key_value_to_number(const KeyValue *value);
int qemu_input_key_value_to_qcode(const KeyValue *value);
int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,

View File

@@ -1050,7 +1050,7 @@ gd_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d"
gd_key_event(int gdk_keycode, int qemu_keycode, const char *action) "translated GDK keycode %d to QEMU keycode %d (%s)"
# ui/input.c
input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%x, down %d"
input_event_key_number(int conidx, int number, const char *qcode, bool down) "con %d, key number 0x%x [%s], down %d"
input_event_key_qcode(int conidx, const char *qcode, bool down) "con %d, key qcode %s, down %d"
input_event_btn(int conidx, const char *btn, bool down) "con %d, button %s, down %d"
input_event_rel(int conidx, const char *axis, int value) "con %d, axis %s, value %d"

View File

@@ -288,8 +288,8 @@ static void curses_refresh(DisplayChangeListener *dcl)
qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, true);
}
qemu_input_event_send_key_number(NULL, keycode, true);
qemu_input_event_send_key_number(NULL, keycode, false);
qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, true);
qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, false);
if (keycode & ALTGR) {
qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, false);

View File

@@ -13,6 +13,8 @@ static const int qcode_to_number[] = {
[Q_KEY_CODE_CTRL] = 0x1d,
[Q_KEY_CODE_CTRL_R] = 0x9d,
[Q_KEY_CODE_META_L] = 0xdb,
[Q_KEY_CODE_META_R] = 0xdc,
[Q_KEY_CODE_MENU] = 0xdd,
[Q_KEY_CODE_ESC] = 0x01,
@@ -129,7 +131,7 @@ static const int qcode_to_number[] = {
[Q_KEY_CODE_MAX] = 0,
};
static int number_to_qcode[0xff];
static int number_to_qcode[0x100];
int qemu_input_key_value_to_number(const KeyValue *value)
{
@@ -141,7 +143,7 @@ int qemu_input_key_value_to_number(const KeyValue *value)
}
}
int qemu_input_key_value_to_qcode(const KeyValue *value)
int qemu_input_key_number_to_qcode(uint8_t nr)
{
static int first = true;
@@ -155,11 +157,16 @@ int qemu_input_key_value_to_qcode(const KeyValue *value)
}
}
return number_to_qcode[nr];
}
int qemu_input_key_value_to_qcode(const KeyValue *value)
{
if (value->kind == KEY_VALUE_KIND_QCODE) {
return value->qcode;
} else {
assert(value->kind == KEY_VALUE_KIND_NUMBER);
return number_to_qcode[value->number];
return qemu_input_key_number_to_qcode(value->number);
}
}

View File

@@ -1,3 +1,4 @@
#include "hw/qdev.h"
#include "sysemu/sysemu.h"
#include "qapi-types.h"
#include "qmp-commands.h"
@@ -10,6 +11,7 @@ struct QemuInputHandlerState {
QemuInputHandler *handler;
int id;
int events;
QemuConsole *con;
QTAILQ_ENTRY(QemuInputHandlerState) node;
};
static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
@@ -53,12 +55,46 @@ void qemu_input_handler_unregister(QemuInputHandlerState *s)
qemu_input_check_mode_change();
}
void qemu_input_handler_bind(QemuInputHandlerState *s,
const char *device_id, int head,
Error **errp)
{
DeviceState *dev;
QemuConsole *con;
dev = qdev_find_recursive(sysbus_get_default(), device_id);
if (dev == NULL) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device_id);
return;
}
con = qemu_console_lookup_by_device(dev, head);
if (con == NULL) {
error_setg(errp, "Device %s is not bound to a QemuConsole", device_id);
return;
}
s->con = con;
}
static QemuInputHandlerState*
qemu_input_find_handler(uint32_t mask)
qemu_input_find_handler(uint32_t mask, QemuConsole *con)
{
QemuInputHandlerState *s;
QTAILQ_FOREACH(s, &handlers, node) {
if (s->con == NULL || s->con != con) {
continue;
}
if (mask & s->handler->mask) {
return s;
}
}
QTAILQ_FOREACH(s, &handlers, node) {
if (s->con != NULL) {
continue;
}
if (mask & s->handler->mask) {
return s;
}
@@ -94,7 +130,7 @@ static void qemu_input_transform_abs_rotate(InputEvent *evt)
static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
{
const char *name;
int idx = -1;
int qcode, idx = -1;
if (src) {
idx = qemu_console_get_index(src);
@@ -103,8 +139,10 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
case INPUT_EVENT_KIND_KEY:
switch (evt->key->key->kind) {
case KEY_VALUE_KIND_NUMBER:
qcode = qemu_input_key_number_to_qcode(evt->key->key->number);
name = QKeyCode_lookup[qcode];
trace_input_event_key_number(idx, evt->key->key->number,
evt->key->down);
name, evt->key->down);
break;
case KEY_VALUE_KIND_QCODE:
name = QKeyCode_lookup[evt->key->key->qcode];
@@ -149,7 +187,7 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
}
/* send event */
s = qemu_input_find_handler(1 << evt->kind);
s = qemu_input_find_handler(1 << evt->kind, src);
if (!s) {
return;
}
@@ -250,7 +288,8 @@ bool qemu_input_is_absolute(void)
{
QemuInputHandlerState *s;
s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS);
s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
NULL);
return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
}

View File

@@ -190,30 +190,33 @@ static void sdl_switch(DisplayChangeListener *dcl,
}
}
static void reset_keys(void)
static void reset_keys(struct sdl2_state *scon)
{
QemuConsole *con = scon ? scon->dcl.con : NULL;
int i;
for (i = 0; i < 256; i++) {
if (modifiers_state[i]) {
int qcode = sdl2_scancode_to_qcode[i];
qemu_input_event_send_key_qcode(NULL, qcode, false);
qemu_input_event_send_key_qcode(con, qcode, false);
modifiers_state[i] = 0;
}
}
}
static void sdl_process_key(SDL_KeyboardEvent *ev)
static void sdl_process_key(struct sdl2_state *scon,
SDL_KeyboardEvent *ev)
{
int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode];
QemuConsole *con = scon ? scon->dcl.con : NULL;
switch (ev->keysym.scancode) {
#if 0
case SDL_SCANCODE_NUMLOCKCLEAR:
case SDL_SCANCODE_CAPSLOCK:
/* SDL does not send the key up event, so we generate it */
qemu_input_event_send_key_qcode(NULL, qcode, true);
qemu_input_event_send_key_qcode(NULL, qcode, false);
qemu_input_event_send_key_qcode(con, qcode, true);
qemu_input_event_send_key_qcode(con, qcode, false);
return;
#endif
case SDL_SCANCODE_LCTRL:
@@ -231,7 +234,7 @@ static void sdl_process_key(SDL_KeyboardEvent *ev)
}
/* fall though */
default:
qemu_input_event_send_key_qcode(NULL, qcode,
qemu_input_event_send_key_qcode(con, qcode,
ev->type == SDL_KEYDOWN);
}
}
@@ -506,7 +509,7 @@ static void handle_keydown(SDL_Event *ev)
}
}
if (!gui_keysym) {
sdl_process_key(&ev->key);
sdl_process_key(scon, &ev->key);
}
}
@@ -531,13 +534,13 @@ static void handle_keyup(SDL_Event *ev)
}
/* SDL does not send back all the modifiers key, so we must
* correct it. */
reset_keys();
reset_keys(scon);
return;
}
gui_keysym = 0;
}
if (!gui_keysym) {
sdl_process_key(&ev->key);
sdl_process_key(scon, &ev->key);
}
}