device: 0.987 mistranslation: 0.975 graphic: 0.949 performance: 0.910 user-level: 0.840 VMM: 0.740 semantic: 0.720 vnc: 0.667 risc-v: 0.629 KVM: 0.626 hypervisor: 0.623 architecture: 0.619 network: 0.613 boot: 0.587 socket: 0.585 PID: 0.578 kernel: 0.572 permissions: 0.546 virtual: 0.514 ppc: 0.440 x86: 0.386 arm: 0.385 i386: 0.354 debug: 0.328 peripherals: 0.280 assembly: 0.265 TCG: 0.252 files: 0.230 register: 0.145 gtk UI interprets double/triple click as button release 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: 1. Start a VM using the GTK interface. 2. Open a tool to examine guest mouse input events, such as `xev` or `yutani-test` 3. Click twice with any button, without releasing on the second click. 4. Observe erroneous 'up' event in guest. 5. Move the mouse while keeping the button pressed. 6. 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 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(); ```