aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuha Riihimäki <juha.riihimaki@nokia.com>2012-07-04 11:18:33 +0000
committerPeter Maydell <peter.maydell@linaro.org>2012-07-25 13:31:41 +0100
commitc746737e13befb20b621ab1e820431a5ea3836de (patch)
tree2dbe7a6be55b170fb978669a1d5fcdbc42b1bf6f
parent155210f5c5f20871a04f28b1738404a68f8d9022 (diff)
Support multiple simultaneous keyboard event handlers
On some systems (such as n900), multiple physical devices can create keyboard events (gpio, lis302dl, twl4030, ..). Add hooks to make it possible to recieve keyboard input from multiple devices. merge our version with upstream multikb support multitouch, multi-keyboard and window close hook support TODO: make this look more like mouse version, ie return a handle which is passed to remove. Also who calls add_kbd_event_handler with a NULL function?? & if we send keycode to all kbd handlers this is ok for n900 but what about eg pc + usb kbd??
-rw-r--r--console.h8
-rw-r--r--hw/hid.c2
-rw-r--r--input.c33
3 files changed, 32 insertions, 11 deletions
diff --git a/console.h b/console.h
index 4334db5ca5..4b0d1e5419 100644
--- a/console.h
+++ b/console.h
@@ -37,6 +37,12 @@ typedef struct QEMUPutMouseEntry {
QTAILQ_ENTRY(QEMUPutMouseEntry) node;
} QEMUPutMouseEntry;
+typedef struct QEMUPutKBDEntry {
+ QEMUPutKBDEvent *put_kbd_event;
+ void *opaque;
+ QTAILQ_ENTRY(QEMUPutKBDEntry) next;
+} QEMUPutKBDEntry;
+
typedef struct QEMUPutLEDEntry {
QEMUPutLEDEvent *put_led;
void *opaque;
@@ -44,7 +50,7 @@ typedef struct QEMUPutLEDEntry {
} QEMUPutLEDEntry;
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
-void qemu_remove_kbd_event_handler(void);
+void qemu_remove_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
void *opaque, int absolute,
const char *name);
diff --git a/hw/hid.c b/hw/hid.c
index 03761ab8b8..e17776d783 100644
--- a/hw/hid.c
+++ b/hw/hid.c
@@ -383,7 +383,7 @@ void hid_free(HIDState *hs)
{
switch (hs->kind) {
case HID_KEYBOARD:
- qemu_remove_kbd_event_handler();
+ qemu_remove_kbd_event_handler(hid_keyboard_event, hs);
break;
case HID_MOUSE:
case HID_TABLET:
diff --git a/input.c b/input.c
index 6968b31781..f52cb59fd8 100644
--- a/input.c
+++ b/input.c
@@ -29,8 +29,8 @@
#include "error.h"
#include "qmp-commands.h"
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
+static QTAILQ_HEAD(, QEMUPutKBDEntry) kbd_handlers =
+ QTAILQ_HEAD_INITIALIZER(kbd_handlers);
static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
QTAILQ_HEAD_INITIALIZER(mouse_handlers);
@@ -39,14 +39,28 @@ static NotifierList mouse_mode_notifiers =
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{
- qemu_put_kbd_event_opaque = opaque;
- qemu_put_kbd_event = func;
+ QEMUPutKBDEntry *s;
+
+ if (func != NULL) {
+ s = g_malloc0(sizeof(QEMUPutKBDEntry));
+
+ s->put_kbd_event = func;
+ s->opaque = opaque;
+
+ QTAILQ_INSERT_TAIL(&kbd_handlers, s, next);
+ }
}
-void qemu_remove_kbd_event_handler(void)
+void qemu_remove_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{
- qemu_put_kbd_event_opaque = NULL;
- qemu_put_kbd_event = NULL;
+ QEMUPutKBDEntry *cursor, *cursor_next;
+ if (func != NULL) {
+ QTAILQ_FOREACH_SAFE(cursor, &kbd_handlers, next, cursor_next) {
+ if (cursor->put_kbd_event == func && cursor->opaque == opaque) {
+ QTAILQ_REMOVE(&kbd_handlers, cursor, next);
+ }
+ }
+ }
}
static void check_mode_change(void)
@@ -130,11 +144,12 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
void kbd_put_keycode(int keycode)
{
+ QEMUPutKBDEntry *cursor;
if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
return;
}
- if (qemu_put_kbd_event) {
- qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+ QTAILQ_FOREACH(cursor, &kbd_handlers, next) {
+ cursor->put_kbd_event(cursor->opaque, keycode);
}
}