input: switch hid mouse and tablet to the new input layer api.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
1ff5eedd1d
commit
8b84286f4c
195
hw/input/hid.c
195
hw/input/hid.c
@ -105,57 +105,115 @@ 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;
|
static const int bmap[INPUT_BUTTON_MAX] = {
|
||||||
e->buttons_state = buttons;
|
[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,
|
static void hid_pointer_sync(DeviceState *dev)
|
||||||
int x1, int y1, int z1) {
|
{
|
||||||
if (xyrel) {
|
HIDState *hs = (HIDState *)dev;
|
||||||
e->xdx += x1;
|
HIDPointerEvent *prev, *curr, *next;
|
||||||
e->ydy += y1;
|
bool event_compression = false;
|
||||||
} else {
|
|
||||||
e->xdx = x1;
|
if (hs->n == QUEUE_LENGTH-1) {
|
||||||
e->ydy = y1;
|
/*
|
||||||
/* Windows drivers do not like the 0/0 position and ignore such
|
* Queue full. We are loosing information, but we at least
|
||||||
* events. */
|
* keep track of most recent button state.
|
||||||
if (!(x1 | y1)) {
|
*/
|
||||||
e->xdx = 1;
|
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,
|
if (event_compression) {
|
||||||
int x1, int y1, int z1, int buttons_state)
|
/* add current motion to previous, clear current */
|
||||||
{
|
if (hs->kind == HID_MOUSE) {
|
||||||
HIDState *hs = opaque;
|
prev->xdx += curr->xdx;
|
||||||
unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
|
curr->xdx = 0;
|
||||||
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
|
prev->ydy -= curr->ydy;
|
||||||
|
curr->ydy = 0;
|
||||||
/* We combine events where feasible to keep the queue small. We shouldn't
|
} else {
|
||||||
* combine anything with the first event of a particular button state, as
|
prev->xdx = curr->xdx;
|
||||||
* that would change the location of the button state change. When the
|
prev->ydy = curr->ydy;
|
||||||
* queue is empty, a second event is needed because we don't know if
|
}
|
||||||
* the first event changed the button state. */
|
prev->dz += curr->dz;
|
||||||
if (hs->n == QUEUE_LENGTH) {
|
curr->dz = 0;
|
||||||
/* Queue full. Discard old button state, combine motion normally. */
|
} else {
|
||||||
hs->ptr.queue[use_slot].buttons_state = buttons_state;
|
/* prepate next (clear rel, copy abs + btns) */
|
||||||
} else if (hs->n < 2 ||
|
if (hs->kind == HID_MOUSE) {
|
||||||
hs->ptr.queue[use_slot].buttons_state != buttons_state ||
|
next->xdx = 0;
|
||||||
hs->ptr.queue[previous_slot].buttons_state !=
|
next->ydy = 0;
|
||||||
hs->ptr.queue[use_slot].buttons_state) {
|
} else {
|
||||||
/* Cannot or should not combine, so add an empty item to the queue. */
|
next->xdx = curr->xdx;
|
||||||
QUEUE_INCR(use_slot);
|
next->ydy = curr->ydy;
|
||||||
|
}
|
||||||
|
next->dz = 0;
|
||||||
|
next->buttons_state = curr->buttons_state;
|
||||||
|
/* make current guest visible, notify guest */
|
||||||
hs->n++;
|
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(DeviceState *dev, QemuConsole *src,
|
static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||||
@ -254,14 +312,14 @@ static inline int int_clamp(int val, int vmin, int vmax)
|
|||||||
void hid_pointer_activate(HIDState *hs)
|
void hid_pointer_activate(HIDState *hs)
|
||||||
{
|
{
|
||||||
if (!hs->ptr.mouse_grabbed) {
|
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;
|
hs->ptr.mouse_grabbed = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int dx, dy, dz, b, l;
|
int dx, dy, dz, l;
|
||||||
int index;
|
int index;
|
||||||
HIDPointerEvent *e;
|
HIDPointerEvent *e;
|
||||||
|
|
||||||
@ -286,17 +344,6 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
|||||||
dz = int_clamp(e->dz, -127, 127);
|
dz = int_clamp(e->dz, -127, 127);
|
||||||
e->dz -= dz;
|
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 &&
|
if (hs->n &&
|
||||||
!e->dz &&
|
!e->dz &&
|
||||||
(hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) {
|
(hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) {
|
||||||
@ -311,7 +358,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
|||||||
switch (hs->kind) {
|
switch (hs->kind) {
|
||||||
case HID_MOUSE:
|
case HID_MOUSE:
|
||||||
if (len > l) {
|
if (len > l) {
|
||||||
buf[l++] = b;
|
buf[l++] = e->buttons_state;
|
||||||
}
|
}
|
||||||
if (len > l) {
|
if (len > l) {
|
||||||
buf[l++] = dx;
|
buf[l++] = dx;
|
||||||
@ -326,7 +373,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
|||||||
|
|
||||||
case HID_TABLET:
|
case HID_TABLET:
|
||||||
if (len > l) {
|
if (len > l) {
|
||||||
buf[l++] = b;
|
buf[l++] = e->buttons_state;
|
||||||
}
|
}
|
||||||
if (len > l) {
|
if (len > l) {
|
||||||
buf[l++] = dx & 0xff;
|
buf[l++] = dx & 0xff;
|
||||||
@ -420,15 +467,7 @@ void hid_reset(HIDState *hs)
|
|||||||
|
|
||||||
void hid_free(HIDState *hs)
|
void hid_free(HIDState *hs)
|
||||||
{
|
{
|
||||||
switch (hs->kind) {
|
qemu_input_handler_unregister(hs->s);
|
||||||
case HID_KEYBOARD:
|
|
||||||
qemu_input_handler_unregister(hs->s);
|
|
||||||
break;
|
|
||||||
case HID_MOUSE:
|
|
||||||
case HID_TABLET:
|
|
||||||
qemu_remove_mouse_event_handler(hs->ptr.eh_entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hid_del_idle_timer(hs);
|
hid_del_idle_timer(hs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,6 +477,20 @@ static QemuInputHandler hid_keyboard_handler = {
|
|||||||
.event = hid_keyboard_event,
|
.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)
|
void hid_init(HIDState *hs, int kind, HIDEventFunc event)
|
||||||
{
|
{
|
||||||
hs->kind = kind;
|
hs->kind = kind;
|
||||||
@ -448,11 +501,11 @@ void hid_init(HIDState *hs, int kind, HIDEventFunc event)
|
|||||||
&hid_keyboard_handler);
|
&hid_keyboard_handler);
|
||||||
qemu_input_handler_activate(hs->s);
|
qemu_input_handler_activate(hs->s);
|
||||||
} else if (hs->kind == HID_MOUSE) {
|
} else if (hs->kind == HID_MOUSE) {
|
||||||
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
|
hs->s = qemu_input_handler_register((DeviceState *)hs,
|
||||||
0, "QEMU HID Mouse");
|
&hid_mouse_handler);
|
||||||
} else if (hs->kind == HID_TABLET) {
|
} else if (hs->kind == HID_TABLET) {
|
||||||
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
|
hs->s = qemu_input_handler_register((DeviceState *)hs,
|
||||||
1, "QEMU HID Tablet");
|
&hid_tablet_handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ typedef void (*HIDEventFunc)(HIDState *s);
|
|||||||
typedef struct HIDMouseState {
|
typedef struct HIDMouseState {
|
||||||
HIDPointerEvent queue[QUEUE_LENGTH];
|
HIDPointerEvent queue[QUEUE_LENGTH];
|
||||||
int mouse_grabbed;
|
int mouse_grabbed;
|
||||||
QEMUPutMouseEntry *eh_entry;
|
|
||||||
} HIDMouseState;
|
} HIDMouseState;
|
||||||
|
|
||||||
typedef struct HIDKeyboardState {
|
typedef struct HIDKeyboardState {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user