mirror of https://gitee.com/openkylin/qemu.git
ui/gtk: Fix relative mouse with multiple monitors
To handle relative mouse input the event handler needs to move the mouse away from the screen edges. Failing to do so results in the mouse getting stuck at invisible walls. However the current implementation for this is broken on hosts with multiple monitors. With multiple monitors the mouse can be located outside of the current monitor which is not handled by the current code. Also the monitor itself might be located at coordinates different from (0, 0). Signed-off-by: Dennis Wölfing <denniswoelfing@gmx.de> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20210720143940.291413-1-denniswoelfing@gmx.de> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
a2376507f6
commit
cd6c768f6a
26
ui/gtk.c
26
ui/gtk.c
|
@ -865,37 +865,25 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
|
||||||
GdkWindow *win = gtk_widget_get_window(widget);
|
GdkWindow *win = gtk_widget_get_window(widget);
|
||||||
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
|
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
|
||||||
GdkRectangle geometry;
|
GdkRectangle geometry;
|
||||||
int screen_width, screen_height;
|
|
||||||
|
|
||||||
int x = (int)motion->x_root;
|
int x = (int)motion->x_root;
|
||||||
int y = (int)motion->y_root;
|
int y = (int)motion->y_root;
|
||||||
|
|
||||||
gdk_monitor_get_geometry(monitor, &geometry);
|
gdk_monitor_get_geometry(monitor, &geometry);
|
||||||
screen_width = geometry.width;
|
|
||||||
screen_height = geometry.height;
|
|
||||||
|
|
||||||
/* In relative mode check to see if client pointer hit
|
/* In relative mode check to see if client pointer hit
|
||||||
* one of the screen edges, and if so move it back by
|
* one of the monitor edges, and if so move it back to the
|
||||||
* 200 pixels. This is important because the pointer
|
* center of the monitor. This is important because the pointer
|
||||||
* in the server doesn't correspond 1-for-1, and so
|
* in the server doesn't correspond 1-for-1, and so
|
||||||
* may still be only half way across the screen. Without
|
* may still be only half way across the screen. Without
|
||||||
* this warp, the server pointer would thus appear to hit
|
* this warp, the server pointer would thus appear to hit
|
||||||
* an invisible wall */
|
* an invisible wall */
|
||||||
if (x == 0) {
|
if (x <= geometry.x || x - geometry.x >= geometry.width - 1 ||
|
||||||
x += 200;
|
y <= geometry.y || y - geometry.y >= geometry.height - 1) {
|
||||||
}
|
|
||||||
if (y == 0) {
|
|
||||||
y += 200;
|
|
||||||
}
|
|
||||||
if (x == (screen_width - 1)) {
|
|
||||||
x -= 200;
|
|
||||||
}
|
|
||||||
if (y == (screen_height - 1)) {
|
|
||||||
y -= 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x != (int)motion->x_root || y != (int)motion->y_root) {
|
|
||||||
GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion);
|
GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion);
|
||||||
|
x = geometry.x + geometry.width / 2;
|
||||||
|
y = geometry.y + geometry.height / 2;
|
||||||
|
|
||||||
gdk_device_warp(dev, screen, x, y);
|
gdk_device_warp(dev, screen, x, y);
|
||||||
s->last_set = FALSE;
|
s->last_set = FALSE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
Loading…
Reference in New Issue