diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2012-02-07 14:36:14 +0100 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2012-02-13 17:12:37 +0100 |
commit | fdbd5c1b5eb8596b574ad651afb74a7c59a14484 (patch) | |
tree | 785e9576b4c3506d9dd3dc17138b370dc15f5331 | |
parent | 8fe6547b6181fb7acbabedcd6ed95caf263dd8cc (diff) |
widget: fix mouse wrapping failing when the window is outside
Use a anchor mouse position after every move, similar to spicec to
avoid reaching transparent border on the screen.
We try to move to the center of the screen, but
gdk_display_warp_pointer () will move the cursor within the grabbed
window (so it still receives mouse events even on Windows)
Tested with Linux and Windows clients.
Fixes bug: https://bugs.freedesktop.org/show_bug.cgi?id=45595
-rw-r--r-- | gtk/spice-widget.c | 47 |
1 files changed, 14 insertions, 33 deletions
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c index c5c5d33..c502732 100644 --- a/gtk/spice-widget.c +++ b/gtk/spice-widget.c @@ -619,7 +619,7 @@ static GdkGrabStatus do_pointer_grab(SpiceDisplay *display) int threshold; GdkWindow *w = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display))); Display *x_display = GDK_WINDOW_XDISPLAY(w); - + XGetPointerControl(x_display, &accel_numerator, &accel_denominator, &threshold); XChangePointerControl(x_display, False, False, accel_numerator, @@ -682,35 +682,19 @@ static void try_mouse_grab(SpiceDisplay *display) d->mouse_last_y = -1; } -static void mouse_check_edges(GtkWidget *widget, GdkEventMotion *motion) +static void mouse_wrap(SpiceDisplay *display, GdkEventMotion *motion) { - SpiceDisplay *display = SPICE_DISPLAY(widget); SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); - GdkScreen *screen = gtk_widget_get_screen(widget); - gint ww, wh; + GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(display)); - gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh); - int x = (int)motion->x; - int y = (int)motion->y; - int xr = (int)motion->x_root; - int yr = (int)motion->y_root; - - /* from gtk-vnc: In relative mode check to see if client pointer - * hit the window edges, and if so move it back by 100px. 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) xr += 100; - if (y <= 0) yr += 100; - if (x >= (ww - 1)) xr -= 100; - if (y >= (wh - 1)) yr -= 100; - - if (xr != (int)motion->x_root || yr != (int)motion->y_root) { + gint xr = gdk_screen_get_width(screen) / 2; + gint yr = gdk_screen_get_height(screen) / 2; + + if (xr != (gint)motion->x_root || yr != (gint)motion->y_root) { /* FIXME: we try our best to ignore that next pointer move event.. */ gdk_display_sync(gdk_screen_get_display(screen)); - gdk_display_warp_pointer(gtk_widget_get_display(widget), + gdk_display_warp_pointer(gtk_widget_get_display(GTK_WIDGET(display)), screen, xr, yr); d->mouse_last_x = -1; d->mouse_last_y = -1; @@ -736,7 +720,7 @@ static void try_mouse_ungrab(SpiceDisplay *display) int threshold; GdkWindow *w = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display))); Display *x_display = GDK_WINDOW_XDISPLAY(w); - + XGetPointerControl(x_display, &accel_numerator, &accel_denominator, &threshold); XChangePointerControl(x_display, True, True, accel_numerator, @@ -1181,18 +1165,15 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion) break; case SPICE_MOUSE_MODE_SERVER: if (d->mouse_grab_active) { - if (d->mouse_last_x != -1 && - d->mouse_last_y != -1) { - gint dx = motion->x - d->mouse_last_x; - gint dy = motion->y - d->mouse_last_y; + gint dx = d->mouse_last_x != -1 ? motion->x - d->mouse_last_x : 0; + gint dy = d->mouse_last_y != -1 ? motion->y - d->mouse_last_y : 0; - spice_inputs_motion(d->inputs, dx, dy, - button_mask_gdk_to_spice(motion->state)); - } + spice_inputs_motion(d->inputs, dx, dy, + button_mask_gdk_to_spice(motion->state)); d->mouse_last_x = motion->x; d->mouse_last_y = motion->y; - mouse_check_edges(widget, motion); + mouse_wrap(display, motion); } break; default: |