qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH for 6.1 v2] ui/gtk: Fix relative mouse with multiple monitors
@ 2021-07-20 14:39 Dennis Wölfing
  2021-07-20 18:41 ` Marc-André Lureau
  2021-07-23 12:18 ` Gerd Hoffmann
  0 siblings, 2 replies; 3+ messages in thread
From: Dennis Wölfing @ 2021-07-20 14:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dennis Wölfing, Marc-André Lureau, Gerd Hoffmann

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>
---
Changes in v2:
Warp the mouse to the center of the monitor.

 ui/gtk.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 376b4d528d..18542c7633 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -865,37 +865,25 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
         GdkWindow *win = gtk_widget_get_window(widget);
         GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
         GdkRectangle geometry;
-        int screen_width, screen_height;

         int x = (int)motion->x_root;
         int y = (int)motion->y_root;

         gdk_monitor_get_geometry(monitor, &geometry);
-        screen_width = geometry.width;
-        screen_height = geometry.height;

         /* In relative mode check to see if client pointer hit
-         * one of the screen edges, and if so move it back by
-         * 200 pixels. This is important because the pointer
+         * one of the monitor edges, and if so move it back to the
+         * center of the monitor. This is important because the pointer
          * in the server doesn't correspond 1-for-1, and so
          * may still be only half way across the screen. Without
          * this warp, the server pointer would thus appear to hit
          * an invisible wall */
-        if (x == 0) {
-            x += 200;
-        }
-        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) {
+        if (x <= geometry.x || x - geometry.x >= geometry.width - 1 ||
+            y <= geometry.y || y - geometry.y >= geometry.height - 1) {
             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);
             s->last_set = FALSE;
             return FALSE;
--
2.32.0



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH for 6.1 v2] ui/gtk: Fix relative mouse with multiple monitors
  2021-07-20 14:39 [PATCH for 6.1 v2] ui/gtk: Fix relative mouse with multiple monitors Dennis Wölfing
@ 2021-07-20 18:41 ` Marc-André Lureau
  2021-07-23 12:18 ` Gerd Hoffmann
  1 sibling, 0 replies; 3+ messages in thread
From: Marc-André Lureau @ 2021-07-20 18:41 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: QEMU, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 3009 bytes --]

On Tue, Jul 20, 2021 at 6:43 PM Dennis Wölfing <denniswoelfing@gmx.de>
wrote:

> 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>

---
> Changes in v2:
> Warp the mouse to the center of the monitor.
>
>  ui/gtk.c | 26 +++++++-------------------
>  1 file changed, 7 insertions(+), 19 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 376b4d528d..18542c7633 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -865,37 +865,25 @@ static gboolean gd_motion_event(GtkWidget *widget,
> GdkEventMotion *motion,
>          GdkWindow *win = gtk_widget_get_window(widget);
>          GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
>          GdkRectangle geometry;
> -        int screen_width, screen_height;
>
>          int x = (int)motion->x_root;
>          int y = (int)motion->y_root;
>
>          gdk_monitor_get_geometry(monitor, &geometry);
> -        screen_width = geometry.width;
> -        screen_height = geometry.height;
>
>          /* In relative mode check to see if client pointer hit
> -         * one of the screen edges, and if so move it back by
> -         * 200 pixels. This is important because the pointer
> +         * one of the monitor edges, and if so move it back to the
> +         * center of the monitor. This is important because the pointer
>           * in the server doesn't correspond 1-for-1, and so
>           * may still be only half way across the screen. Without
>           * this warp, the server pointer would thus appear to hit
>           * an invisible wall */
> -        if (x == 0) {
> -            x += 200;
> -        }
> -        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) {
> +        if (x <= geometry.x || x - geometry.x >= geometry.width - 1 ||
> +            y <= geometry.y || y - geometry.y >= geometry.height - 1) {
>              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);
>              s->last_set = FALSE;
>              return FALSE;
> --
> 2.32.0
>
>

-- 
Marc-André Lureau

[-- Attachment #2: Type: text/html, Size: 4044 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH for 6.1 v2] ui/gtk: Fix relative mouse with multiple monitors
  2021-07-20 14:39 [PATCH for 6.1 v2] ui/gtk: Fix relative mouse with multiple monitors Dennis Wölfing
  2021-07-20 18:41 ` Marc-André Lureau
@ 2021-07-23 12:18 ` Gerd Hoffmann
  1 sibling, 0 replies; 3+ messages in thread
From: Gerd Hoffmann @ 2021-07-23 12:18 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: Marc-André Lureau, qemu-devel

On Tue, Jul 20, 2021 at 04:39:41PM +0200, Dennis Wölfing wrote:
> 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>
> ---
> Changes in v2:
> Warp the mouse to the center of the monitor.

Added to my 6.1-fixes queue.

thanks,
  Gerd



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-23 12:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-20 14:39 [PATCH for 6.1 v2] ui/gtk: Fix relative mouse with multiple monitors Dennis Wölfing
2021-07-20 18:41 ` Marc-André Lureau
2021-07-23 12:18 ` Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).