UI queue
- virtio: add virtio-multitouch device - sdl: various keyboard grab fixes - gtk: enable multi-touch events - misc fixes -----BEGIN PGP SIGNATURE----- iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmRzVQAcHG1hcmNhbmRy ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5a34D/9+1I9XnecCQk4rZhHI Fb1fUei4eLNOdxTZUK2zpOkArWf59VNsEa1LFqIiM+0IlWU3gQmrCLRFOuJrDxiA ugq9H23QLs3Z7HEab6/aq+VwUy+o1AXowLZBTrEGmw9SZQnrKeu4/prW0f5wbsTf u5ALDkJWo733vkbAplsfWPcOLzp3CoTvA89iw/I9eNVYsm6+vBJ+0cRBr0GCPmiJ 2xprhGkie491clNlbR3HmOX/RGFmcj/ClPraLXepaQq1gNCqurIrU7V3J/JcY5W0 YemXDEgpZ8iVt1OOKGKzTftGZzuhRpxAYvSPwjAp1XeEXB7eJEmjUWoFpyVt1tQZ 4y6pQGYdM2XW0sbAkt3w2TIgj/odv7L3IHG3UcsBRefl6Pm43G1FuGWjbulQ1ch0 YyFAr1xNPkWMYSW1MTb4vuTYFO9OEY08W4n+M6O187RUFiuf+W00OZUDqpp6zjqT LKjMktilpUOya1LvWU3D5et9LEXFgSrZj9rQlFsuMe3g24ZNPLypQh/jzSFs9ZsW At1nIGGrrZDr8YMFnANBudJbJc0Q1+ce5TB6090XSpNn/YXvu2H+n/ceA4/mA6sy MlQBrDmifb9iY6+62MbW8wJtiIy8Zi7A632pw8gbqB0ilkg4DNSBR5O42n1Fmhqp gLfxN48NN9Bx6H+zPJbwz2aDQQ== =3bPI -----END PGP SIGNATURE----- Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging UI queue - virtio: add virtio-multitouch device - sdl: various keyboard grab fixes - gtk: enable multi-touch events - misc fixes # -----BEGIN PGP SIGNATURE----- # # iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmRzVQAcHG1hcmNhbmRy # ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5a34D/9+1I9XnecCQk4rZhHI # Fb1fUei4eLNOdxTZUK2zpOkArWf59VNsEa1LFqIiM+0IlWU3gQmrCLRFOuJrDxiA # ugq9H23QLs3Z7HEab6/aq+VwUy+o1AXowLZBTrEGmw9SZQnrKeu4/prW0f5wbsTf # u5ALDkJWo733vkbAplsfWPcOLzp3CoTvA89iw/I9eNVYsm6+vBJ+0cRBr0GCPmiJ # 2xprhGkie491clNlbR3HmOX/RGFmcj/ClPraLXepaQq1gNCqurIrU7V3J/JcY5W0 # YemXDEgpZ8iVt1OOKGKzTftGZzuhRpxAYvSPwjAp1XeEXB7eJEmjUWoFpyVt1tQZ # 4y6pQGYdM2XW0sbAkt3w2TIgj/odv7L3IHG3UcsBRefl6Pm43G1FuGWjbulQ1ch0 # YyFAr1xNPkWMYSW1MTb4vuTYFO9OEY08W4n+M6O187RUFiuf+W00OZUDqpp6zjqT # LKjMktilpUOya1LvWU3D5et9LEXFgSrZj9rQlFsuMe3g24ZNPLypQh/jzSFs9ZsW # At1nIGGrrZDr8YMFnANBudJbJc0Q1+ce5TB6090XSpNn/YXvu2H+n/ceA4/mA6sy # MlQBrDmifb9iY6+62MbW8wJtiIy8Zi7A632pw8gbqB0ilkg4DNSBR5O42n1Fmhqp # gLfxN48NN9Bx6H+zPJbwz2aDQQ== # =3bPI # -----END PGP SIGNATURE----- # gpg: Signature made Sun 28 May 2023 06:20:00 AM PDT # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] * tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu: ui/gtk: enable backend to send multi-touch events ui: add helpers for virtio-multitouch events virtio-input-pci: add virtio-multitouch-pci virtio-input: add a virtio-mulitouch device ui: add the infrastructure to support MT events virtio-input: generalize virtio_input_key_config() ui/cursor: make width/height unsigned 16-bit integer ui/sdl2: disable SDL_HINT_GRAB_KEYBOARD on Windows ui/sdl2: Grab Alt+F4 also under Windows ui/sdl2: Grab Alt+Tab also in fullscreen mode ui/dbus: add a FIXME about texture/dmabuf scanout handling gtk: add gl-area support on win32 virtio-gpu: add a FIXME for virtio_gpu_load() win32: wrap socket close() with an exception handler ui/dbus: fix compilation when GBM && !OPENGL ui/sdl2: fix surface_gl_update_texture: Assertion 'gls' failed ui/gtk-egl: fix scaling for cursor position in scanout mode ui/gtk: use widget size for cursor motion event ui/gtk: fix passing y0_top parameter to scanout Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
57b93c0f8e
@ -1289,6 +1289,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
||||
/* load & apply scanout state */
|
||||
vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1);
|
||||
for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
|
||||
/* FIXME: should take scanout.r.{x,y} into account */
|
||||
scanout = &g->parent_obj.scanout[i];
|
||||
if (!scanout->resource_id) {
|
||||
continue;
|
||||
|
@ -16,9 +16,10 @@
|
||||
|
||||
#include "standard-headers/linux/input.h"
|
||||
|
||||
#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
|
||||
#define VIRTIO_ID_NAME_MOUSE "QEMU Virtio Mouse"
|
||||
#define VIRTIO_ID_NAME_TABLET "QEMU Virtio Tablet"
|
||||
#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
|
||||
#define VIRTIO_ID_NAME_MOUSE "QEMU Virtio Mouse"
|
||||
#define VIRTIO_ID_NAME_TABLET "QEMU Virtio Tablet"
|
||||
#define VIRTIO_ID_NAME_MULTITOUCH "QEMU Virtio MultiTouch"
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
@ -30,6 +31,7 @@ static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
|
||||
[INPUT_BUTTON_SIDE] = BTN_SIDE,
|
||||
[INPUT_BUTTON_EXTRA] = BTN_EXTRA,
|
||||
[INPUT_BUTTON_TOUCH] = BTN_TOUCH,
|
||||
};
|
||||
|
||||
static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
|
||||
@ -42,32 +44,38 @@ static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
|
||||
[INPUT_AXIS_Y] = ABS_Y,
|
||||
};
|
||||
|
||||
static const unsigned short axismap_tch[INPUT_AXIS__MAX] = {
|
||||
[INPUT_AXIS_X] = ABS_MT_POSITION_X,
|
||||
[INPUT_AXIS_Y] = ABS_MT_POSITION_Y,
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
static void virtio_input_key_config(VirtIOInput *vinput,
|
||||
const unsigned short *keymap,
|
||||
size_t mapsize)
|
||||
static void virtio_input_extend_config(VirtIOInput *vinput,
|
||||
const unsigned short *map,
|
||||
size_t mapsize,
|
||||
uint8_t select, uint8_t subsel)
|
||||
{
|
||||
virtio_input_config keys;
|
||||
virtio_input_config ext;
|
||||
int i, bit, byte, bmax = 0;
|
||||
|
||||
memset(&keys, 0, sizeof(keys));
|
||||
memset(&ext, 0, sizeof(ext));
|
||||
for (i = 0; i < mapsize; i++) {
|
||||
bit = keymap[i];
|
||||
bit = map[i];
|
||||
if (!bit) {
|
||||
continue;
|
||||
}
|
||||
byte = bit / 8;
|
||||
bit = bit % 8;
|
||||
keys.u.bitmap[byte] |= (1 << bit);
|
||||
ext.u.bitmap[byte] |= (1 << bit);
|
||||
if (bmax < byte+1) {
|
||||
bmax = byte+1;
|
||||
}
|
||||
}
|
||||
keys.select = VIRTIO_INPUT_CFG_EV_BITS;
|
||||
keys.subsel = EV_KEY;
|
||||
keys.size = bmax;
|
||||
virtio_input_add_config(vinput, &keys);
|
||||
ext.select = select;
|
||||
ext.subsel = subsel;
|
||||
ext.size = bmax;
|
||||
virtio_input_add_config(vinput, &ext);
|
||||
}
|
||||
|
||||
static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
@ -80,6 +88,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
InputKeyEvent *key;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
InputMultiTouchEvent *mtt;
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_KEY:
|
||||
@ -136,6 +145,24 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
event.value = cpu_to_le32(move->value);
|
||||
virtio_input_send(vinput, &event);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_MTT:
|
||||
mtt = evt->u.mtt.data;
|
||||
if (mtt->type == INPUT_MULTI_TOUCH_TYPE_DATA) {
|
||||
event.type = cpu_to_le16(EV_ABS);
|
||||
event.code = cpu_to_le16(axismap_tch[mtt->axis]);
|
||||
event.value = cpu_to_le32(mtt->value);
|
||||
virtio_input_send(vinput, &event);
|
||||
} else {
|
||||
event.type = cpu_to_le16(EV_ABS);
|
||||
event.code = cpu_to_le16(ABS_MT_SLOT);
|
||||
event.value = cpu_to_le32(mtt->slot);
|
||||
virtio_input_send(vinput, &event);
|
||||
event.type = cpu_to_le16(EV_ABS);
|
||||
event.code = cpu_to_le16(ABS_MT_TRACKING_ID);
|
||||
event.value = cpu_to_le32(mtt->tracking_id);
|
||||
virtio_input_send(vinput, &event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
@ -281,8 +308,9 @@ static void virtio_keyboard_init(Object *obj)
|
||||
|
||||
vhid->handler = &virtio_keyboard_handler;
|
||||
virtio_input_init_config(vinput, virtio_keyboard_config);
|
||||
virtio_input_key_config(vinput, qemu_input_map_qcode_to_linux,
|
||||
qemu_input_map_qcode_to_linux_len);
|
||||
virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux,
|
||||
qemu_input_map_qcode_to_linux_len,
|
||||
VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_keyboard_info = {
|
||||
@ -373,8 +401,9 @@ static void virtio_mouse_init(Object *obj)
|
||||
virtio_input_init_config(vinput, vhid->wheel_axis
|
||||
? virtio_mouse_config_v2
|
||||
: virtio_mouse_config_v1);
|
||||
virtio_input_key_config(vinput, keymap_button,
|
||||
ARRAY_SIZE(keymap_button));
|
||||
virtio_input_extend_config(vinput, keymap_button,
|
||||
ARRAY_SIZE(keymap_button),
|
||||
VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_mouse_info = {
|
||||
@ -497,8 +526,9 @@ static void virtio_tablet_init(Object *obj)
|
||||
virtio_input_init_config(vinput, vhid->wheel_axis
|
||||
? virtio_tablet_config_v2
|
||||
: virtio_tablet_config_v1);
|
||||
virtio_input_key_config(vinput, keymap_button,
|
||||
ARRAY_SIZE(keymap_button));
|
||||
virtio_input_extend_config(vinput, keymap_button,
|
||||
ARRAY_SIZE(keymap_button),
|
||||
VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_tablet_info = {
|
||||
@ -511,12 +541,98 @@ static const TypeInfo virtio_tablet_info = {
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
static QemuInputHandler virtio_multitouch_handler = {
|
||||
.name = VIRTIO_ID_NAME_MULTITOUCH,
|
||||
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT,
|
||||
.event = virtio_input_handle_event,
|
||||
.sync = virtio_input_handle_sync,
|
||||
};
|
||||
|
||||
static struct virtio_input_config virtio_multitouch_config[] = {
|
||||
{
|
||||
.select = VIRTIO_INPUT_CFG_ID_NAME,
|
||||
.size = sizeof(VIRTIO_ID_NAME_MULTITOUCH),
|
||||
.u.string = VIRTIO_ID_NAME_MULTITOUCH,
|
||||
},{
|
||||
.select = VIRTIO_INPUT_CFG_ID_DEVIDS,
|
||||
.size = sizeof(struct virtio_input_devids),
|
||||
.u.ids = {
|
||||
.bustype = const_le16(BUS_VIRTUAL),
|
||||
.vendor = const_le16(0x0627), /* same we use for usb hid devices */
|
||||
.product = const_le16(0x0003),
|
||||
.version = const_le16(0x0001),
|
||||
},
|
||||
},{
|
||||
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
||||
.subsel = ABS_MT_SLOT,
|
||||
.size = sizeof(virtio_input_absinfo),
|
||||
.u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
|
||||
.u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
|
||||
},{
|
||||
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
||||
.subsel = ABS_MT_TRACKING_ID,
|
||||
.size = sizeof(virtio_input_absinfo),
|
||||
.u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
|
||||
.u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
|
||||
},{
|
||||
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
||||
.subsel = ABS_MT_POSITION_X,
|
||||
.size = sizeof(virtio_input_absinfo),
|
||||
.u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
|
||||
.u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
|
||||
},{
|
||||
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
||||
.subsel = ABS_MT_POSITION_Y,
|
||||
.size = sizeof(virtio_input_absinfo),
|
||||
.u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
|
||||
.u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
|
||||
},
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
||||
static void virtio_multitouch_init(Object *obj)
|
||||
{
|
||||
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
|
||||
VirtIOInput *vinput = VIRTIO_INPUT(obj);
|
||||
unsigned short abs_props[] = {
|
||||
INPUT_PROP_DIRECT,
|
||||
};
|
||||
unsigned short abs_bits[] = {
|
||||
ABS_MT_SLOT,
|
||||
ABS_MT_TRACKING_ID,
|
||||
ABS_MT_POSITION_X,
|
||||
ABS_MT_POSITION_Y,
|
||||
};
|
||||
|
||||
vhid->handler = &virtio_multitouch_handler;
|
||||
virtio_input_init_config(vinput, virtio_multitouch_config);
|
||||
virtio_input_extend_config(vinput, keymap_button,
|
||||
ARRAY_SIZE(keymap_button),
|
||||
VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
|
||||
virtio_input_extend_config(vinput, abs_props,
|
||||
ARRAY_SIZE(abs_props),
|
||||
VIRTIO_INPUT_CFG_PROP_BITS, 0);
|
||||
virtio_input_extend_config(vinput, abs_bits,
|
||||
ARRAY_SIZE(abs_bits),
|
||||
VIRTIO_INPUT_CFG_EV_BITS, EV_ABS);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_multitouch_info = {
|
||||
.name = TYPE_VIRTIO_MULTITOUCH,
|
||||
.parent = TYPE_VIRTIO_INPUT_HID,
|
||||
.instance_size = sizeof(VirtIOInputHID),
|
||||
.instance_init = virtio_multitouch_init,
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
static void virtio_register_types(void)
|
||||
{
|
||||
type_register_static(&virtio_input_hid_info);
|
||||
type_register_static(&virtio_keyboard_info);
|
||||
type_register_static(&virtio_mouse_info);
|
||||
type_register_static(&virtio_tablet_info);
|
||||
type_register_static(&virtio_multitouch_info);
|
||||
}
|
||||
|
||||
type_init(virtio_register_types)
|
||||
|
@ -25,10 +25,11 @@ struct VirtIOInputPCI {
|
||||
VirtIOInput vdev;
|
||||
};
|
||||
|
||||
#define TYPE_VIRTIO_INPUT_HID_PCI "virtio-input-hid-pci"
|
||||
#define TYPE_VIRTIO_KEYBOARD_PCI "virtio-keyboard-pci"
|
||||
#define TYPE_VIRTIO_MOUSE_PCI "virtio-mouse-pci"
|
||||
#define TYPE_VIRTIO_TABLET_PCI "virtio-tablet-pci"
|
||||
#define TYPE_VIRTIO_INPUT_HID_PCI "virtio-input-hid-pci"
|
||||
#define TYPE_VIRTIO_KEYBOARD_PCI "virtio-keyboard-pci"
|
||||
#define TYPE_VIRTIO_MOUSE_PCI "virtio-mouse-pci"
|
||||
#define TYPE_VIRTIO_TABLET_PCI "virtio-tablet-pci"
|
||||
#define TYPE_VIRTIO_MULTITOUCH_PCI "virtio-multitouch-pci"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHIDPCI, VIRTIO_INPUT_HID_PCI)
|
||||
|
||||
struct VirtIOInputHIDPCI {
|
||||
@ -102,6 +103,14 @@ static void virtio_tablet_initfn(Object *obj)
|
||||
TYPE_VIRTIO_TABLET);
|
||||
}
|
||||
|
||||
static void virtio_multitouch_initfn(Object *obj)
|
||||
{
|
||||
VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_MULTITOUCH);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_input_pci_info = {
|
||||
.name = TYPE_VIRTIO_INPUT_PCI,
|
||||
.parent = TYPE_VIRTIO_PCI,
|
||||
@ -140,6 +149,13 @@ static const VirtioPCIDeviceTypeInfo virtio_tablet_pci_info = {
|
||||
.instance_init = virtio_tablet_initfn,
|
||||
};
|
||||
|
||||
static const VirtioPCIDeviceTypeInfo virtio_multitouch_pci_info = {
|
||||
.generic_name = TYPE_VIRTIO_MULTITOUCH_PCI,
|
||||
.parent = TYPE_VIRTIO_INPUT_HID_PCI,
|
||||
.instance_size = sizeof(VirtIOInputHIDPCI),
|
||||
.instance_init = virtio_multitouch_initfn,
|
||||
};
|
||||
|
||||
static void virtio_pci_input_register(void)
|
||||
{
|
||||
/* Base types: */
|
||||
@ -150,6 +166,7 @@ static void virtio_pci_input_register(void)
|
||||
virtio_pci_types_register(&virtio_keyboard_pci_info);
|
||||
virtio_pci_types_register(&virtio_mouse_pci_info);
|
||||
virtio_pci_types_register(&virtio_tablet_pci_info);
|
||||
virtio_pci_types_register(&virtio_multitouch_pci_info);
|
||||
}
|
||||
|
||||
type_init(virtio_pci_input_register)
|
||||
|
@ -24,10 +24,11 @@ OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass,
|
||||
#define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \
|
||||
OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT)
|
||||
|
||||
#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
|
||||
#define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device"
|
||||
#define TYPE_VIRTIO_MOUSE "virtio-mouse-device"
|
||||
#define TYPE_VIRTIO_TABLET "virtio-tablet-device"
|
||||
#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
|
||||
#define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device"
|
||||
#define TYPE_VIRTIO_MOUSE "virtio-mouse-device"
|
||||
#define TYPE_VIRTIO_TABLET "virtio-tablet-device"
|
||||
#define TYPE_VIRTIO_MULTITOUCH "virtio-multitouch-device"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHID, VIRTIO_INPUT_HID)
|
||||
#define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \
|
||||
|
@ -259,6 +259,10 @@ ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags);
|
||||
ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
EXCEPTION_DISPOSITION
|
||||
win32_close_exception_handler(struct _EXCEPTION_RECORD*, void*,
|
||||
struct _CONTEXT*, void*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -144,13 +144,13 @@ typedef struct QemuUIInfo {
|
||||
|
||||
/* cursor data format is 32bit RGBA */
|
||||
typedef struct QEMUCursor {
|
||||
int width, height;
|
||||
uint16_t width, height;
|
||||
int hot_x, hot_y;
|
||||
int refcount;
|
||||
uint32_t data[];
|
||||
} QEMUCursor;
|
||||
|
||||
QEMUCursor *cursor_alloc(int width, int height);
|
||||
QEMUCursor *cursor_alloc(uint16_t width, uint16_t height);
|
||||
QEMUCursor *cursor_ref(QEMUCursor *c);
|
||||
void cursor_unref(QEMUCursor *c);
|
||||
QEMUCursor *cursor_builtin_hidden(void);
|
||||
|
@ -8,9 +8,12 @@
|
||||
#define INPUT_EVENT_MASK_BTN (1<<INPUT_EVENT_KIND_BTN)
|
||||
#define INPUT_EVENT_MASK_REL (1<<INPUT_EVENT_KIND_REL)
|
||||
#define INPUT_EVENT_MASK_ABS (1<<INPUT_EVENT_KIND_ABS)
|
||||
#define INPUT_EVENT_MASK_MTT (1<<INPUT_EVENT_KIND_MTT)
|
||||
|
||||
#define INPUT_EVENT_ABS_MIN 0x0000
|
||||
#define INPUT_EVENT_ABS_MAX 0x7FFF
|
||||
#define INPUT_EVENT_SLOTS_MIN 0x0
|
||||
#define INPUT_EVENT_SLOTS_MAX 0xa
|
||||
|
||||
typedef struct QemuInputHandler QemuInputHandler;
|
||||
typedef struct QemuInputHandlerState QemuInputHandlerState;
|
||||
@ -61,6 +64,11 @@ int qemu_input_scale_axis(int value,
|
||||
void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value);
|
||||
void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
|
||||
int min_in, int max_in);
|
||||
void qemu_input_queue_mtt(QemuConsole *src, InputMultiTouchType type, int slot,
|
||||
int tracking_id);
|
||||
void qemu_input_queue_mtt_abs(QemuConsole *src, InputAxis axis, int value,
|
||||
int min_in, int max_in,
|
||||
int slot, int tracking_id);
|
||||
|
||||
void qemu_input_check_mode_change(void);
|
||||
void qemu_add_mouse_mode_change_notifier(Notifier *notify);
|
||||
|
68
qapi/ui.json
68
qapi/ui.json
@ -1055,11 +1055,13 @@
|
||||
#
|
||||
# @extra: rear side button of a 5-button mouse (since 2.9)
|
||||
#
|
||||
# @touch: screen contact on a multi-touch device (since 8.1)
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum' : 'InputButton',
|
||||
'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side',
|
||||
'extra', 'wheel-left', 'wheel-right' ] }
|
||||
'extra', 'wheel-left', 'wheel-right', 'touch' ] }
|
||||
|
||||
##
|
||||
# @InputAxis:
|
||||
@ -1071,6 +1073,17 @@
|
||||
{ 'enum' : 'InputAxis',
|
||||
'data' : [ 'x', 'y' ] }
|
||||
|
||||
##
|
||||
# @InputMultiTouchType:
|
||||
#
|
||||
# Type of a multi-touch event.
|
||||
#
|
||||
# Since: 8.1
|
||||
##
|
||||
{ 'enum' : 'InputMultiTouchType',
|
||||
'data' : [ 'begin', 'update', 'end', 'cancel', 'data' ] }
|
||||
|
||||
|
||||
##
|
||||
# @InputKeyEvent:
|
||||
#
|
||||
@ -1117,13 +1130,46 @@
|
||||
'data' : { 'axis' : 'InputAxis',
|
||||
'value' : 'int' } }
|
||||
|
||||
##
|
||||
# @InputMultiTouchEvent:
|
||||
#
|
||||
# MultiTouch input event.
|
||||
#
|
||||
# @slot: Which slot has generated the event.
|
||||
#
|
||||
# @tracking-id: ID to correlate this event with previously generated
|
||||
# events.
|
||||
#
|
||||
# @axis: Which axis is referenced by @value.
|
||||
#
|
||||
# @value: Contact position.
|
||||
#
|
||||
# Since: 8.1
|
||||
##
|
||||
{ 'struct' : 'InputMultiTouchEvent',
|
||||
'data' : { 'type' : 'InputMultiTouchType',
|
||||
'slot' : 'int',
|
||||
'tracking-id': 'int',
|
||||
'axis' : 'InputAxis',
|
||||
'value' : 'int' } }
|
||||
|
||||
##
|
||||
# @InputEventKind:
|
||||
#
|
||||
# @key: a keyboard input event
|
||||
#
|
||||
# @btn: a pointer button input event
|
||||
#
|
||||
# @rel: a relative pointer motion input event
|
||||
#
|
||||
# @abs: an absolute pointer motion input event
|
||||
#
|
||||
# @mtt: a multi-touch input event
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum': 'InputEventKind',
|
||||
'data': [ 'key', 'btn', 'rel', 'abs' ] }
|
||||
'data': [ 'key', 'btn', 'rel', 'abs', 'mtt' ] }
|
||||
|
||||
##
|
||||
# @InputKeyEventWrapper:
|
||||
@ -1149,17 +1195,20 @@
|
||||
{ 'struct': 'InputMoveEventWrapper',
|
||||
'data': { 'data': 'InputMoveEvent' } }
|
||||
|
||||
##
|
||||
# @InputMultiTouchEventWrapper:
|
||||
#
|
||||
# Since: 8.1
|
||||
##
|
||||
{ 'struct': 'InputMultiTouchEventWrapper',
|
||||
'data': { 'data': 'InputMultiTouchEvent' } }
|
||||
|
||||
##
|
||||
# @InputEvent:
|
||||
#
|
||||
# Input event union.
|
||||
#
|
||||
# @type: the input type, one of:
|
||||
#
|
||||
# - 'key': Input event of Keyboard
|
||||
# - 'btn': Input event of pointer buttons
|
||||
# - 'rel': Input event of relative pointer motion
|
||||
# - 'abs': Input event of absolute pointer motion
|
||||
# @type: the type of input event
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
@ -1169,7 +1218,8 @@
|
||||
'data' : { 'key' : 'InputKeyEventWrapper',
|
||||
'btn' : 'InputBtnEventWrapper',
|
||||
'rel' : 'InputMoveEventWrapper',
|
||||
'abs' : 'InputMoveEventWrapper' } }
|
||||
'abs' : 'InputMoveEventWrapper',
|
||||
'mtt' : 'InputMultiTouchEventWrapper' } }
|
||||
|
||||
##
|
||||
# @input-send-event:
|
||||
|
@ -22,6 +22,7 @@ void replay_save_input_event(InputEvent *evt)
|
||||
InputKeyEvent *key;
|
||||
InputBtnEvent *btn;
|
||||
InputMoveEvent *move;
|
||||
InputMultiTouchEvent *mtt;
|
||||
replay_put_dword(evt->type);
|
||||
|
||||
switch (evt->type) {
|
||||
@ -58,6 +59,14 @@ void replay_save_input_event(InputEvent *evt)
|
||||
replay_put_dword(move->axis);
|
||||
replay_put_qword(move->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_MTT:
|
||||
mtt = evt->u.mtt.data;
|
||||
replay_put_dword(mtt->type);
|
||||
replay_put_qword(mtt->slot);
|
||||
replay_put_qword(mtt->tracking_id);
|
||||
replay_put_dword(mtt->axis);
|
||||
replay_put_qword(mtt->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
@ -73,6 +82,7 @@ InputEvent *replay_read_input_event(void)
|
||||
InputBtnEvent btn;
|
||||
InputMoveEvent rel;
|
||||
InputMoveEvent abs;
|
||||
InputMultiTouchEvent mtt;
|
||||
|
||||
evt.type = replay_get_dword();
|
||||
switch (evt.type) {
|
||||
@ -109,6 +119,14 @@ InputEvent *replay_read_input_event(void)
|
||||
evt.u.abs.data->axis = (InputAxis)replay_get_dword();
|
||||
evt.u.abs.data->value = replay_get_qword();
|
||||
break;
|
||||
case INPUT_EVENT_KIND_MTT:
|
||||
evt.u.mtt.data = &mtt;
|
||||
evt.u.mtt.data->type = (InputMultiTouchType)replay_get_dword();
|
||||
evt.u.mtt.data->slot = replay_get_qword();
|
||||
evt.u.mtt.data->tracking_id = replay_get_qword();
|
||||
evt.u.mtt.data->axis = (InputAxis)replay_get_dword();
|
||||
evt.u.mtt.data->value = replay_get_qword();
|
||||
break;
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
|
@ -90,11 +90,12 @@ QEMUCursor *cursor_builtin_left_ptr(void)
|
||||
return cursor_parse_xpm(cursor_left_ptr_xpm);
|
||||
}
|
||||
|
||||
QEMUCursor *cursor_alloc(int width, int height)
|
||||
QEMUCursor *cursor_alloc(uint16_t width, uint16_t height)
|
||||
{
|
||||
QEMUCursor *c;
|
||||
size_t datasize = width * height * sizeof(uint32_t);
|
||||
|
||||
/* Modern physical hardware typically uses 512x512 sprites */
|
||||
if (width > 512 || height > 512) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ struct _DBusDisplayListener {
|
||||
|
||||
G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT)
|
||||
|
||||
#ifdef CONFIG_GBM
|
||||
#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
|
||||
static void dbus_update_gl_cb(GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
@ -102,6 +102,7 @@ static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: add missing x/y/w/h support */
|
||||
qemu_dbus_display1_listener_call_scanout_dmabuf(
|
||||
ddl->proxy,
|
||||
g_variant_new_handle(0),
|
||||
@ -129,6 +130,10 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
|
||||
.width = backing_width,
|
||||
.height = backing_height,
|
||||
.y0_top = backing_y_0_top,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.scanout_width = w,
|
||||
.scanout_height = h,
|
||||
};
|
||||
|
||||
assert(tex_id);
|
||||
@ -239,7 +244,7 @@ static void dbus_refresh(DisplayChangeListener *dcl)
|
||||
graphic_hw_update(dcl->con);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GBM
|
||||
#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
|
||||
static void dbus_gl_gfx_update(DisplayChangeListener *dcl,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
@ -302,7 +307,7 @@ static void dbus_gfx_update(DisplayChangeListener *dcl,
|
||||
DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GBM
|
||||
#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
|
||||
static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
|
||||
struct DisplaySurface *new_surface)
|
||||
{
|
||||
@ -369,7 +374,7 @@ static void dbus_cursor_define(DisplayChangeListener *dcl,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GBM
|
||||
#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
|
||||
const DisplayChangeListenerOps dbus_gl_dcl_ops = {
|
||||
.dpy_name = "dbus-gl",
|
||||
.dpy_gfx_update = dbus_gl_gfx_update,
|
||||
@ -417,7 +422,7 @@ dbus_display_listener_constructed(GObject *object)
|
||||
DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
|
||||
|
||||
ddl->dcl.ops = &dbus_dcl_ops;
|
||||
#ifdef CONFIG_GBM
|
||||
#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
|
||||
if (display_opengl) {
|
||||
ddl->dcl.ops = &dbus_gl_dcl_ops;
|
||||
}
|
||||
|
@ -88,8 +88,8 @@ void gd_egl_draw(VirtualConsole *vc)
|
||||
#endif
|
||||
gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
|
||||
|
||||
vc->gfx.scale_x = (double)ww / vc->gfx.w;
|
||||
vc->gfx.scale_y = (double)wh / vc->gfx.h;
|
||||
vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
|
||||
vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
|
||||
|
||||
glFlush();
|
||||
#ifdef CONFIG_GBM
|
||||
@ -256,7 +256,7 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
|
||||
}
|
||||
|
||||
gd_egl_scanout_texture(dcl, dmabuf->texture,
|
||||
false, dmabuf->width, dmabuf->height,
|
||||
dmabuf->y0_top, dmabuf->width, dmabuf->height,
|
||||
0, 0, dmabuf->width, dmabuf->height);
|
||||
|
||||
if (dmabuf->allow_fences) {
|
||||
|
@ -298,7 +298,7 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
|
||||
}
|
||||
|
||||
gd_gl_area_scanout_texture(dcl, dmabuf->texture,
|
||||
false, dmabuf->width, dmabuf->height,
|
||||
dmabuf->y0_top, dmabuf->width, dmabuf->height,
|
||||
0, 0, dmabuf->width, dmabuf->height);
|
||||
|
||||
if (dmabuf->allow_fences) {
|
||||
|
106
ui/gtk.c
106
ui/gtk.c
@ -130,6 +130,13 @@ typedef struct VCChardev VCChardev;
|
||||
DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV,
|
||||
TYPE_CHARDEV_VC)
|
||||
|
||||
struct touch_slot {
|
||||
int x;
|
||||
int y;
|
||||
int tracking_id;
|
||||
};
|
||||
static struct touch_slot touch_slots[INPUT_EVENT_SLOTS_MAX];
|
||||
|
||||
bool gtk_use_gl_area;
|
||||
|
||||
static void gd_grab_pointer(VirtualConsole *vc, const char *reason);
|
||||
@ -869,7 +876,6 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
|
||||
{
|
||||
VirtualConsole *vc = opaque;
|
||||
GtkDisplayState *s = vc->s;
|
||||
GdkWindow *window;
|
||||
int x, y;
|
||||
int mx, my;
|
||||
int fbh, fbw;
|
||||
@ -882,10 +888,9 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
|
||||
fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
|
||||
fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
|
||||
|
||||
window = gtk_widget_get_window(vc->gfx.drawing_area);
|
||||
ww = gdk_window_get_width(window);
|
||||
wh = gdk_window_get_height(window);
|
||||
ws = gdk_window_get_scale_factor(window);
|
||||
ww = gtk_widget_get_allocated_width(widget);
|
||||
wh = gtk_widget_get_allocated_height(widget);
|
||||
ws = gtk_widget_get_scale_factor(widget);
|
||||
|
||||
mx = my = 0;
|
||||
if (ww > fbw) {
|
||||
@ -1059,6 +1064,82 @@ static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll,
|
||||
}
|
||||
|
||||
|
||||
static gboolean gd_touch_event(GtkWidget *widget, GdkEventTouch *touch,
|
||||
void *opaque)
|
||||
{
|
||||
VirtualConsole *vc = opaque;
|
||||
struct touch_slot *slot;
|
||||
uint64_t num_slot = GPOINTER_TO_UINT(touch->sequence);
|
||||
bool needs_sync = false;
|
||||
int update;
|
||||
int type = -1;
|
||||
int i;
|
||||
|
||||
if (num_slot >= INPUT_EVENT_SLOTS_MAX) {
|
||||
warn_report("gtk: unexpected touch slot number: % " PRId64" >= %d\n",
|
||||
num_slot, INPUT_EVENT_SLOTS_MAX);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
slot = &touch_slots[num_slot];
|
||||
slot->x = touch->x;
|
||||
slot->y = touch->y;
|
||||
|
||||
switch (touch->type) {
|
||||
case GDK_TOUCH_BEGIN:
|
||||
type = INPUT_MULTI_TOUCH_TYPE_BEGIN;
|
||||
slot->tracking_id = num_slot;
|
||||
break;
|
||||
case GDK_TOUCH_UPDATE:
|
||||
type = INPUT_MULTI_TOUCH_TYPE_UPDATE;
|
||||
break;
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
type = INPUT_MULTI_TOUCH_TYPE_END;
|
||||
break;
|
||||
default:
|
||||
warn_report("gtk: unexpected touch event type\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < INPUT_EVENT_SLOTS_MAX; ++i) {
|
||||
if (i == num_slot) {
|
||||
update = type;
|
||||
} else {
|
||||
update = INPUT_MULTI_TOUCH_TYPE_UPDATE;
|
||||
}
|
||||
|
||||
slot = &touch_slots[i];
|
||||
|
||||
if (slot->tracking_id == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (update == INPUT_MULTI_TOUCH_TYPE_END) {
|
||||
slot->tracking_id = -1;
|
||||
qemu_input_queue_mtt(vc->gfx.dcl.con, update, i, slot->tracking_id);
|
||||
needs_sync = true;
|
||||
} else {
|
||||
qemu_input_queue_mtt(vc->gfx.dcl.con, update, i, slot->tracking_id);
|
||||
qemu_input_queue_btn(vc->gfx.dcl.con, INPUT_BUTTON_TOUCH, true);
|
||||
qemu_input_queue_mtt_abs(vc->gfx.dcl.con,
|
||||
INPUT_AXIS_X, (int) slot->x,
|
||||
0, surface_width(vc->gfx.ds),
|
||||
i, slot->tracking_id);
|
||||
qemu_input_queue_mtt_abs(vc->gfx.dcl.con,
|
||||
INPUT_AXIS_Y, (int) slot->y,
|
||||
0, surface_height(vc->gfx.ds),
|
||||
i, slot->tracking_id);
|
||||
needs_sync = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_sync) {
|
||||
qemu_input_event_sync();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const guint16 *gd_get_keymap(size_t *maplen)
|
||||
{
|
||||
GdkDisplay *dpy = gdk_display_get_default();
|
||||
@ -1980,6 +2061,8 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc)
|
||||
G_CALLBACK(gd_key_event), vc);
|
||||
g_signal_connect(vc->gfx.drawing_area, "key-release-event",
|
||||
G_CALLBACK(gd_key_event), vc);
|
||||
g_signal_connect(vc->gfx.drawing_area, "touch-event",
|
||||
G_CALLBACK(gd_touch_event), vc);
|
||||
|
||||
g_signal_connect(vc->gfx.drawing_area, "enter-notify-event",
|
||||
G_CALLBACK(gd_enter_event), vc);
|
||||
@ -2089,6 +2172,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
|
||||
GSList *group, GtkWidget *view_menu)
|
||||
{
|
||||
bool zoom_to_fit = false;
|
||||
int i;
|
||||
|
||||
vc->label = qemu_console_get_label(con);
|
||||
vc->s = s;
|
||||
@ -2136,6 +2220,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_BUTTON_MOTION_MASK |
|
||||
GDK_TOUCH_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_SCROLL_MASK |
|
||||
@ -2171,6 +2256,11 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
|
||||
s->free_scale = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < INPUT_EVENT_SLOTS_MAX; i++) {
|
||||
struct touch_slot *slot = &touch_slots[i];
|
||||
slot->tracking_id = -1;
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@ -2445,6 +2535,12 @@ static void early_gtk_display_init(DisplayOptions *opts)
|
||||
gtk_use_gl_area = true;
|
||||
gtk_gl_area_init();
|
||||
} else
|
||||
#endif
|
||||
#if defined(GDK_WINDOWING_WIN32)
|
||||
if (GDK_IS_WIN32_DISPLAY(gdk_display_get_default())) {
|
||||
gtk_use_gl_area = true;
|
||||
gtk_gl_area_init();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_X11
|
||||
|
42
ui/input.c
42
ui/input.c
@ -212,6 +212,7 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
|
||||
InputKeyEvent *key;
|
||||
InputBtnEvent *btn;
|
||||
InputMoveEvent *move;
|
||||
InputMultiTouchEvent *mtt;
|
||||
|
||||
if (src) {
|
||||
idx = qemu_console_get_index(src);
|
||||
@ -250,6 +251,11 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
|
||||
name = InputAxis_str(move->axis);
|
||||
trace_input_event_abs(idx, name, move->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_MTT:
|
||||
mtt = evt->u.mtt.data;
|
||||
name = InputAxis_str(mtt->axis);
|
||||
trace_input_event_mtt(idx, name, mtt->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
@ -541,6 +547,42 @@ void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
|
||||
qemu_input_event_send(src, &evt);
|
||||
}
|
||||
|
||||
void qemu_input_queue_mtt(QemuConsole *src, InputMultiTouchType type,
|
||||
int slot, int tracking_id)
|
||||
{
|
||||
InputMultiTouchEvent mtt = {
|
||||
.type = type,
|
||||
.slot = slot,
|
||||
.tracking_id = tracking_id,
|
||||
};
|
||||
InputEvent evt = {
|
||||
.type = INPUT_EVENT_KIND_MTT,
|
||||
.u.mtt.data = &mtt,
|
||||
};
|
||||
|
||||
qemu_input_event_send(src, &evt);
|
||||
}
|
||||
|
||||
void qemu_input_queue_mtt_abs(QemuConsole *src, InputAxis axis, int value,
|
||||
int min_in, int max_in, int slot, int tracking_id)
|
||||
{
|
||||
InputMultiTouchEvent mtt = {
|
||||
.type = INPUT_MULTI_TOUCH_TYPE_DATA,
|
||||
.slot = slot,
|
||||
.tracking_id = tracking_id,
|
||||
.axis = axis,
|
||||
.value = qemu_input_scale_axis(value, min_in, max_in,
|
||||
INPUT_EVENT_ABS_MIN,
|
||||
INPUT_EVENT_ABS_MAX),
|
||||
};
|
||||
InputEvent evt = {
|
||||
.type = INPUT_EVENT_KIND_MTT,
|
||||
.u.mtt.data = &mtt,
|
||||
};
|
||||
|
||||
qemu_input_event_send(src, &evt);
|
||||
}
|
||||
|
||||
void qemu_input_check_mode_change(void)
|
||||
{
|
||||
static int current_is_absolute;
|
||||
|
@ -67,6 +67,10 @@ void sdl2_gl_update(DisplayChangeListener *dcl,
|
||||
|
||||
assert(scon->opengl);
|
||||
|
||||
if (!scon->real_window) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
|
||||
surface_gl_update_texture(scon->gls, scon->surface, x, y, w, h);
|
||||
scon->updates++;
|
||||
|
@ -855,7 +855,14 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
|
||||
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* only available since SDL 2.0.8 */
|
||||
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
||||
#endif
|
||||
#ifndef CONFIG_WIN32
|
||||
/* QEMU uses its own low level keyboard hook procecure on Windows */
|
||||
SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
|
||||
#endif
|
||||
#ifdef SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED
|
||||
SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0");
|
||||
#endif
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
|
||||
memset(&info, 0, sizeof(info));
|
||||
SDL_VERSION(&info.version);
|
||||
|
||||
|
@ -90,6 +90,7 @@ input_event_key_qcode(int conidx, const char *qcode, bool down) "con %d, key qco
|
||||
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"
|
||||
input_event_abs(int conidx, const char *axis, int value) "con %d, axis %s, value 0x%x"
|
||||
input_event_mtt(int conidx, const char *axis, int value) "con %d, axis %s, value 0x%x"
|
||||
input_event_sync(void) ""
|
||||
input_mouse_mode(int absolute) "absolute %d"
|
||||
|
||||
|
@ -479,6 +479,13 @@ int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXCEPTION_DISPOSITION
|
||||
win32_close_exception_handler(struct _EXCEPTION_RECORD*,
|
||||
void*, struct _CONTEXT*, void*)
|
||||
{
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
#undef close
|
||||
int qemu_close_socket_osfhandle(int fd)
|
||||
{
|
||||
@ -504,12 +511,16 @@ int qemu_close_socket_osfhandle(int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* close() returns EBADF since we PROTECT_FROM_CLOSE the underlying handle,
|
||||
* but the FD is actually freed
|
||||
*/
|
||||
if (close(fd) < 0 && errno != EBADF) {
|
||||
return -1;
|
||||
__try1(win32_close_exception_handler) {
|
||||
/*
|
||||
* close() returns EBADF since we PROTECT_FROM_CLOSE the underlying
|
||||
* handle, but the FD is actually freed
|
||||
*/
|
||||
if (close(fd) < 0 && errno != EBADF) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
__except1 {
|
||||
}
|
||||
|
||||
if (!SetHandleInformation((HANDLE)s, flags, flags)) {
|
||||
|
Loading…
Reference in New Issue
Block a user