gtk UI interprets double/triple click as button release
Host environment
- Operating system: Ubuntu 20.04
- OS/kernel version: Linux luka 5.4.0-80-generic #90-Ubuntu SMP Fri Jul 9 22:49:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- Architecture: x86-64
- QEMU flavor: qemu-system-x86_64
- QEMU version: 6.0.94 (v6.0.0-3214-gecf2706e-dirty)
- QEMU command line:
qemu-system-x86_64 -display gtk
Emulated/Virtualized environment
- Operating system: ToaruOS 2.0
- OS/kernel version: toaru livecd 1.99.4-a34dadba-dirty misaka Aug 20 2021 17:14:04 x86_64 ToaruOS
- Architecture: x86-64
Description of problem
When using the GTK interface clicking rapidly in a down-up-down pattern, the final "down" event is erroneously followed by an immediate "up" event and the mouse device in the guest reports the pressed button as no longer being held.
Steps to reproduce
- Start a VM using the GTK interface.
- Open a tool to examine guest mouse input events, such as
xev
oryutani-test
- Click twice with any button, without releasing on the second click.
- Observe erroneous 'up' event in guest.
- Move the mouse while keeping the button pressed.
- Observe the guest reports the button is not held.
Additional information
GTK 3 sends an additional GDK_2BUTTON_PRESS
event after the initial GDK_BUTTON_PRESS
event, which QEMU is misinterpreting as a release event. I confirmed this with the addition of some logging of button->type
in gd_button_event
:
button = 1, type = 4
button = 1, type = 7
button = 1, type = 4
button = 1, type = 7
button = 1, type = 4 # = PRESS
button = 1, type = 5 # = 2BUTTON_PRESS
button = 1, type = 7
button = 1, type = 4
button = 1, type = 7
button = 1, type = 4
button = 1, type = 5
button = 1, type = 7
button = 1, type = 4
button = 1, type = 7
button = 1, type = 4
button = 1, type = 7
button = 1, type = 4
button = 1, type = 7
button = 1, type = 4
button = 1, type = 5
button = 1, type = 7
diff --git a/ui/gtk.c b/ui/gtk.c
index cfb0728d1f..b9979f0e11 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -925,6 +925,13 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
return TRUE;
}
+ /* ignore additional events for double- and triple- press, as they are
+ * sent to us after a regular press event; otherwise we will misinterpret
+ * these as release events and eat the button! */
+ if (button->type == GDK_2BUTTON_PRESS || button->type == GDK_3BUTTON_PRESS) {
+ return TRUE;
+ }
+
qemu_input_queue_btn(vc->gfx.dcl.con, btn,
button->type == GDK_BUTTON_PRESS);
qemu_input_event_sync();
Edited by K. Lange