Hi Dennis

On Tue, Jun 29, 2021 at 5:26 PM Dennis Wölfing <denniswoelf...@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 <denniswoelf...@gmx.de>
>

Looks reasonable to me. In spice-gtk we have slightly different code, we
wrap at the middle of the monitor instead (
https://gitlab.freedesktop.org/spice/spice-gtk/-/blob/master/src/spice-widget.c#L1214),
what do you think?

And also, spice-gtk has special cases for w32 and wayland, which behave
differently.

Gtk4 is also different, as device_warp() is gone (it will have to handle it
specifically again for the different platforms:
https://gitlab.gnome.org/malureau/rdw/-/blob/master/rdw/src/display.rs#L812)



---
>  ui/gtk.c | 21 +++++++++------------
>  1 file changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 98046f577b..5258532b19 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -865,33 +865,30 @@ 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
> +         * one of the monitor edges, and if so move it back by
>           * 200 pixels. 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 (x <= geometry.x) {
> +            x = geometry.x + 200;
>          }
> -        if (y == 0) {
> -            y += 200;
> +        if (y <= geometry.y) {
> +            y = geometry.y + 200;
>          }
> -        if (x == (screen_width - 1)) {
> -            x -= 200;
> +        if (x - geometry.x >= (geometry.width - 1)) {
> +            x = geometry.x + (geometry.width - 1) - 200;
>          }
> -        if (y == (screen_height - 1)) {
> -            y -= 200;
> +        if (y - geometry.y >= (geometry.height - 1)) {
> +            y = geometry.y + (geometry.height - 1) - 200;
>          }
>
>          if (x != (int)motion->x_root || y != (int)motion->y_root) {
> --
> 2.32.0
>
>
>

-- 
Marc-André Lureau

Reply via email to