Mouse cursor invisible in virt-manager on Wayland
Once clicking into the spice-gtk widget in virt-manager, the mouse cursor becomes invisible on the whole window (not just the VM itself) - this includes the virt-manager main window if it's open. Clicking on something that triggers a new cursor shape like the window bar for dragging restores the cursor.
Reproducible:
- Wayland GNOME session (Fedora 29)
- create a new VM with just PXE boot
- click into the guest once it is started
- mouse cursor is now gone and doesn't reappear until something else sets the cursor shape
Note: it doesn't matter that the VM doesn't get past the initial boot screen
This only happens on Wayland, not Xorg.
Symptoms
Just a list of the more confusing behaviours so they're all summed up:
- the cursor isn't visible on any of the window decoration, menu bar or even in the virt-manager main window
- the cursor isn't captured by the window
- after clicking into the window, "Press Control_L ..." shows up in the title bar. the pointer works outside the window, on the icon bar and the menu bar, but not on the window decoration to move the window (window close button works)
- the "Press Control_L ..." never disappears, even if I click outside the window and do other stuff
- Ctrl_L+Alt removes the titlebar label but does not make the cursor reappear. The cursor now works on the window decoration to move the window too.
Analysis:
The issue is the GDK seat grab spice-gtk uses.
do_pointer_grab()
issues a gdk_seat_grab()
with the blank cursor. This immediately triggers a grab_broken
call that is ignored, see commit 951c21d0. It also triggers a leave_event
with GDK_CROSSING_GRAB
which is effectively ignored because mouse_grab_active
is true by then.
Up to here it seems mostly ok, although I think the grab-broken check should check for implicit
being set.
When leaving the VM window leave_event()
has crossing->window == the grab window
. The crossing->mode
is GDK_MODE_NORMAL
and mouse_grab_active
is still true. And nothing happens, we're still grabbed.
I don't see a single gdk_seat_ungrab()
anywhere (which would restore the cursor handling).
The Ctrl+Alt combination calls try_mouse_ungrab()
which removes the GTK grab but not the GDK seat grab.
A quick check shows that adding a gdk_seat_ungrab()
in the leave event makes it work as expected, at the cost of the grab.
Problem sources:
- the expectation seems to be that a grab cannot interact with anything else. Under X, nothing reacts once the grab is there. Under Wayland it still highlights the buttons, allows for the menus.
- under X,
try_mouse_ungrab()
is sufficient to remove the grab correctly, Wayland requires the additionalgdk_seat_ungrab()
.
cc @carlosg, because this could very well be in GTK territoriy.