summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2012-02-07 14:36:14 +0100
committerMarc-André Lureau <marcandre.lureau@redhat.com>2012-02-13 17:12:37 +0100
commitfdbd5c1b5eb8596b574ad651afb74a7c59a14484 (patch)
tree785e9576b4c3506d9dd3dc17138b370dc15f5331
parent8fe6547b6181fb7acbabedcd6ed95caf263dd8cc (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.c47
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: