- 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:
Richard Henderson 2023-05-29 13:15:10 -07:00
commit 57b93c0f8e
19 changed files with 442 additions and 60 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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) \

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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
View File

@ -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

View File

@ -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;

View File

@ -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++;

View File

@ -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);

View File

@ -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"

View File

@ -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)) {