Compare commits

..

24 Commits

Author SHA1 Message Date
Gerd Hoffmann
6fa2769751 gtk: workaround gtk2 vte resize issue
Hack isn't pretty, but gets the job done.
See source code comment for details.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
82fc18099a gtk: window sizing overhaul
Major overhaul for window size handling.  This basically switches qemu
over to use geometry hints for the window manager instead of trying to
get the job done with widget resize requests.  This allows to specify
better what we need and also avoids window resizes.

FIXME: on gtk2 someone overwrites the geometry hints :(

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
0f61a61df3 gtk: zap unused global_state
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Bruce Rogers
3158a3482b gtk: Add handling for the xfree86 keycodes
Currently only evdev keycodes are handled by the gtk-ui. SDL has
code to handle both. This patch adds similar processing so that
both keycode types will be handled via the gtk-ui.

Signed-off-by: Bruce Rogers <brogers@suse.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
aa0a55d42d gtk: enable untabify for gfx
Now we have all grab fixes in place, so we can allow detaching
graphic display tabs too.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
0c77a37f11 gtk: detached window pointer grabs
Make ungrab hotkey work with detached windows.
Enable pointer grabs for detached windows.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
99623c90d1 gtk: update all windows on mouse mode changes
We might have multiple graphic displays now which all need a cursor update.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
2884cf5b93 gtk: fix grab checks
Make it handle multiple windows case correctly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
4eeaa3a885 gtk: update gd_update_caption
Adapt to recent changes, handle multiple windows.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
746b867030 gtk: skip keyboard grab when hover autograb is active
It's pointless.  With grab on hover enabled the keyboard grab
is already active when you press Ctrl-Alt-G ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
4c638e2e4b gtk: keep track of grab owner
Simplifies grab state tracking and makes ungrab more reliable.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
1c856da57b gtk: add gd_grab trace event
Input grab code is tricky, add some debug & trouble shooting aid.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
74444bc198 gtk: add tab to trace events
So you can see which of multiple displays (if present) was resized ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
cdeb7090ee gtk: allow moving tabs to windows and back.
"View->Detach tab" will move to tab to a new window.
Simply closing the window will move it back into a notebook tab.
The label will be permamently stored in VirtualConsole->label,
so it can easily be reused to (re-)label tabs and windows.

Works for vte tabs only for now. pointer/kbd grab code needs
adaptions before we can enable it for gfx tabs too.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
d3ef575080 gtk: simplify resize
Simply ask for a small window size.  When the widgets don't fit in gtk
will automatically make the window large enougth to make things fit, no
need to try (and fail) duplicate that logic in qemu.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
6a24ced5ca gtk: use device type as label
IMO useful than showing VGA for any graphic device
even in case it is something completely different.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
ed1132e41a gtk: support multiple gfx displays
Each display gets its own tab.  Tab switching continues to work like it
did, just the hotkeys of the vte consoles changes in case a secondary
display is present as it will get ctrl-alt-2 assigned and the vtes are
shifted by one.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
e3500d1f5f gtk: move vga state into VirtualGfxConsole
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
271a25c0b6 gtk: VirtualConsole restruction
Move all vte-related items into VirtualVteConsole substruct.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
832189c9b1 gtk: remove page numbering assumtions from the code
Lookup page numbers using gtk_notebook_page_num() instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Cole Robinson
0fb20d1c39 gtk: Add a scrollbar for text consoles
Only show the scrollbar if the content doesn't fit on the visible space.

[ kraxel: fix box packing ]

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
ee5f31e48b gtk: cleanup CONFIG_VTE ifdef a bit.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
6fe83074d7 gtk: zap vte size requests
The vte tabs simply get the size of the vga tab then, with whatever
cols and lines are fitting in.  I find this bahavior more useful than
resizing the qemu window all day long.

YMMV.  Comments are welcome.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
fd07d07ba9 gtk: zap scrolled_window
The vte widget implements the scrollable interface, placing it into
a scrolled window is pointless and creates a bunch of strange effects.
Zap it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:02 +02:00
11 changed files with 840 additions and 689 deletions

View File

@@ -1,76 +0,0 @@
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,135 +105,70 @@ void hid_set_next_idle(HIDState *hs)
}
}
static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt)
static void hid_pointer_event_clear(HIDPointerEvent *e, int 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;
}
e->xdx = e->ydy = e->dz = 0;
e->buttons_state = buttons;
}
static void hid_pointer_sync(DeviceState *dev)
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;
}
}
e->dz += z1;
}
static void hid_pointer_event(void *opaque,
int x1, int y1, int z1, int buttons_state)
{
HIDState *hs = (HIDState *)dev;
HIDPointerEvent *prev, *curr, *next;
bool event_compression = false;
HIDState *hs = opaque;
unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
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;
}
}
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 */
/* 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);
hs->n++;
hs->event(hs);
hid_pointer_event_clear(&hs->ptr.queue[use_slot], buttons_state);
}
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,
InputEvent *evt)
static void hid_keyboard_event(void *opaque, int keycode)
{
HIDState *hs = (HIDState *)dev;
int scancodes[3], i, count;
HIDState *hs = opaque;
int slot;
count = qemu_input_key_value_to_scancode(evt->key->key,
evt->key->down,
scancodes);
if (hs->n + count > QUEUE_LENGTH) {
if (hs->n == QUEUE_LENGTH) {
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
return;
}
for (i = 0; i < count; i++) {
slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
hs->kbd.keycodes[slot] = scancodes[i];
}
hs->kbd.keycodes[slot] = keycode;
hs->event(hs);
}
@@ -312,14 +247,14 @@ static inline int int_clamp(int val, int vmin, int vmax)
void hid_pointer_activate(HIDState *hs)
{
if (!hs->ptr.mouse_grabbed) {
qemu_input_handler_activate(hs->s);
qemu_activate_mouse_event_handler(hs->ptr.eh_entry);
hs->ptr.mouse_grabbed = 1;
}
}
int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
{
int dx, dy, dz, l;
int dx, dy, dz, b, l;
int index;
HIDPointerEvent *e;
@@ -344,6 +279,17 @@ 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))) {
@@ -358,7 +304,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
switch (hs->kind) {
case HID_MOUSE:
if (len > l) {
buf[l++] = e->buttons_state;
buf[l++] = b;
}
if (len > l) {
buf[l++] = dx;
@@ -373,7 +319,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
case HID_TABLET:
if (len > l) {
buf[l++] = e->buttons_state;
buf[l++] = b;
}
if (len > l) {
buf[l++] = dx & 0xff;
@@ -467,45 +413,31 @@ void hid_reset(HIDState *hs)
void hid_free(HIDState *hs)
{
qemu_input_handler_unregister(hs->s);
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;
}
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->s = qemu_input_handler_register((DeviceState *)hs,
&hid_keyboard_handler);
qemu_input_handler_activate(hs->s);
hs->kbd.eh_entry = qemu_add_kbd_event_handler(hid_keyboard_event, hs);
} else if (hs->kind == HID_MOUSE) {
hs->s = qemu_input_handler_register((DeviceState *)hs,
&hid_mouse_handler);
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
0, "QEMU HID Mouse");
} else if (hs->kind == HID_TABLET) {
hs->s = qemu_input_handler_register((DeviceState *)hs,
&hid_tablet_handler);
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
1, "QEMU HID Tablet");
}
}

View File

@@ -47,8 +47,6 @@ typedef struct USBHIDState {
USBEndpoint *intr;
HIDState hid;
uint32_t usb_version;
char *display;
uint32_t head;
} USBHIDState;
enum {
@@ -576,9 +574,6 @@ 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;
}
@@ -658,8 +653,6 @@ 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(),
};
@@ -703,11 +696,6 @@ 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);
@@ -718,7 +706,6 @@ 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,7 +2,6 @@
#define QEMU_HID_H
#include "migration/vmstate.h"
#include "ui/input.h"
#define HID_MOUSE 1
#define HID_TABLET 2
@@ -23,6 +22,7 @@ typedef void (*HIDEventFunc)(HIDState *s);
typedef struct HIDMouseState {
HIDPointerEvent queue[QUEUE_LENGTH];
int mouse_grabbed;
QEMUPutMouseEntry *eh_entry;
} HIDMouseState;
typedef struct HIDKeyboardState {
@@ -31,6 +31,7 @@ typedef struct HIDKeyboardState {
uint8_t leds;
uint8_t key[16];
int32_t keys;
QEMUPutKbdEntry *eh_entry;
} HIDKeyboardState;
struct HIDState {
@@ -46,7 +47,6 @@ struct HIDState {
bool idle_pending;
QEMUTimer *idle_timer;
HIDEventFunc event;
QemuInputHandlerState *s;
};
void hid_init(HIDState *hs, int kind, HIDEventFunc event);

View File

@@ -29,9 +29,6 @@ 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);
@@ -39,7 +36,6 @@ 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

@@ -1045,12 +1045,13 @@ displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
ppm_save(const char *filename, void *display_surface) "%s surface=%p"
# ui/gtk.c
gd_switch(int width, int height) "width=%d, height=%d"
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)"
gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d"
gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d, h=%d"
gd_key_event(const char *tab, int gdk_keycode, int qemu_keycode, const char *action) "tab=%s, translated GDK keycode %d to QEMU keycode %d (%s)"
gd_grab(const char *tab, const char *device, bool on) "tab=%s, %s %d"
# ui/input.c
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_number(int conidx, int number, bool down) "con %d, key number 0x%x, 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 & KEY_MASK, true);
qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, false);
qemu_input_event_send_key_number(NULL, keycode, true);
qemu_input_event_send_key_number(NULL, keycode, false);
if (keycode & ALTGR) {
qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, false);

1096
ui/gtk.c

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,6 @@ 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,
@@ -131,7 +129,7 @@ static const int qcode_to_number[] = {
[Q_KEY_CODE_MAX] = 0,
};
static int number_to_qcode[0x100];
static int number_to_qcode[0xff];
int qemu_input_key_value_to_number(const KeyValue *value)
{
@@ -143,7 +141,7 @@ int qemu_input_key_value_to_number(const KeyValue *value)
}
}
int qemu_input_key_number_to_qcode(uint8_t nr)
int qemu_input_key_value_to_qcode(const KeyValue *value)
{
static int first = true;
@@ -157,16 +155,11 @@ int qemu_input_key_number_to_qcode(uint8_t nr)
}
}
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 qemu_input_key_number_to_qcode(value->number);
return number_to_qcode[value->number];
}
}

View File

@@ -1,4 +1,3 @@
#include "hw/qdev.h"
#include "sysemu/sysemu.h"
#include "qapi-types.h"
#include "qmp-commands.h"
@@ -11,7 +10,6 @@ struct QemuInputHandlerState {
QemuInputHandler *handler;
int id;
int events;
QemuConsole *con;
QTAILQ_ENTRY(QemuInputHandlerState) node;
};
static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
@@ -55,46 +53,12 @@ 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, QemuConsole *con)
qemu_input_find_handler(uint32_t mask)
{
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;
}
@@ -130,7 +94,7 @@ static void qemu_input_transform_abs_rotate(InputEvent *evt)
static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
{
const char *name;
int qcode, idx = -1;
int idx = -1;
if (src) {
idx = qemu_console_get_index(src);
@@ -139,10 +103,8 @@ 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,
name, evt->key->down);
evt->key->down);
break;
case KEY_VALUE_KIND_QCODE:
name = QKeyCode_lookup[evt->key->key->qcode];
@@ -187,7 +149,7 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
}
/* send event */
s = qemu_input_find_handler(1 << evt->kind, src);
s = qemu_input_find_handler(1 << evt->kind);
if (!s) {
return;
}
@@ -288,8 +250,7 @@ bool qemu_input_is_absolute(void)
{
QemuInputHandlerState *s;
s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
NULL);
s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS);
return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
}

View File

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