Hello,
There's a long standing bug with -display sdl that host side mouse pointer
does not follow guest or jumps around or otherwise behaves erratically.
There are several tickets about this as well but gitlab does not make it
easy to find them so these are just a few I think might be related, there
might be more:
https://gitlab.com/qemu-project/qemu/-/work_items/1550
https://gitlab.com/qemu-project/qemu/-/work_items/2960
https://gitlab.com/qemu-project/qemu/-/work_items/2948
I can also reproduce it with
qemu-system-ppc -M pegasos2 -display sdl -device ati-vga -kernel boot.img -cdrom morphos.iso
(boot.img is from the root dir of the morphos iso). Mouse pointer mostly
works as long as don't move it too fast or you don't switch to full screen
with Ctrl+Alt+F then it does not work even if you switch back to window.
This can be avoided using disabling host side cursor with -device
ati-vga,guest_hwcursor=on.
After not finding any cause in ati-vga I've added some diagnostics to sdl
backend:
diff --git a/ui/sdl2.c b/ui/sdl2.c
index aaaede56e0..4f625365ab 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -333,6 +333,7 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y,
y, 0, surface_height(scon->surface));
} else {
+fprintf(stderr,"%s(%d,%d,%d,%d,%d), %d %d,%d,",__func__,dx,dy,x,y,state,guest_cursor,guest_x,guest_y);
if (guest_cursor) {
x -= guest_x;
y -= guest_y;
@@ -341,6 +342,7 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
dx = x;
dy = y;
}
+fprintf(stderr," -> %d,%d %d,%d\n",dx,dy,guest_x,guest_y);
qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_X, dx);
qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_Y, dy);
}
@@ -525,6 +527,7 @@ static void handle_mousemotion(SDL_Event *ev)
dx = (int64_t)ev->motion.xrel * surf_w / scr_w;
dy = (int64_t)ev->motion.yrel * surf_h / scr_h;
if (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
+fprintf(stderr, "%s(%d,%d,%d,%d, %d,%d,%d,%d)\n",__func__,surf_w,surf_h,scr_w,scr_h,x,y,dx,dy);
sdl_send_mouse_event(scon, dx, dy, x, y, ev->motion.state);
}
}
@@ -750,6 +753,7 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl,
} else if (gui_grab) {
sdl_hide_cursor(scon);
}
+fprintf(stderr,"%s(%d,%d,%d)\n",__func__,x,y,on);
guest_cursor = on;
guest_x = x, guest_y = y;
}
and got this output just booting the iso without clicking in the window or
moving the mouse. First this is the guest moving the cursor by writing the
HW cursor register for position to place the pointer in the middle:
sdl_mouse_warp(1024,576,1)
sdl_mouse_warp(1024,576,1)
sdl_mouse_warp(1024,576,1)
sdl_mouse_warp(1024,576,1)
then just switching to full screen with Crtl+Alt+F without moving the
mouse in the guest I get these:
handle_mousemotion(2048,1152,2560,1440, 655,368,0,0)
sdl_send_mouse_event(0,0,655,368,0), 1 1024,576, -> -369,-208 655,368
sdl_mouse_warp(286,160,1)
handle_mousemotion(2048,1152,2560,1440, 182,102,0,0)
sdl_send_mouse_event(0,0,182,102,0), 1 286,160, -> -104,-58 182,102
sdl_mouse_warp(78,44,1)
handle_mousemotion(2048,1152,2560,1440, 49,28,0,0)
sdl_send_mouse_event(0,0,49,28,0), 1 78,44, -> -29,-16 49,28
sdl_mouse_warp(20,12,1)
handle_mousemotion(2048,1152,2560,1440, 12,7,0,0)
sdl_send_mouse_event(0,0,12,7,0), 1 20,12, -> -8,-5 12,7
sdl_mouse_warp(4,2,1)
handle_mousemotion(2048,1152,2560,1440, 2,0,0,0)
sdl_send_mouse_event(0,0,2,0,0), 1 4,2, -> -2,-2 2,0
sdl_mouse_warp(2,0,1)
handle_mousemotion(2048,1152,2560,1440, 0,0,0,0)
sdl_send_mouse_event(0,0,0,0,0), 1 2,0, -> -2,0 0,0
sdl_mouse_warp(0,0,1)
handle_mousemotion(2048,1152,2560,1440, 0,0,0,0)
sdl_send_mouse_event(0,0,0,0,0), 1 0,0, -> 0,0 0,0
sdl_mouse_warp(0,0,1)
handle_mousemotion(2048,1152,2560,1440, 0,0,0,0)
sdl_send_mouse_event(0,0,0,0,0), 1 0,0, -> 0,0 0,0
sdl_mouse_warp(0,0,1)
The pointer is moved to the top left without any input from the user and
cannot leave it any more (less severe cases could cause laggy mouse
pointer or other issues). Trying to move the mouse afterwards can only
move vertically.
On the ati-vga side writing CUR_HORZ_VERT_POSN register that the guest
does to move the HW cursor calls
dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
s->regs.cur_hv_pos & 0xffff, true);
which ends up in sdl_mouse_warp that sets guest_x,guest_y but then other
parts of sdl.c also try to also set it differently. That's what I could
find out but I don't understand how it should work and why it doesn't. It
looks like there is some confusion about what guest_x and guest_y should
be. Could somebody give some clue how this could be fixed? Or even better
fix it as I'm quite lost on this.
Thank you,
BALATON Zoltan
© 2016 - 2026 Red Hat, Inc.