On Wed, Oct 31, 2012 at 04:51:05PM +0100, Marc-André Lureau wrote: > Windows grab do not exist like on X11, so we need to clip the cursor > to our client window, while making sure it doesn't overlap with > windows statusbar. When wrapping the cursor, we need to make sure we > also stay within the clip region, or else the clip is inverted > (pointer can't enter the clip region anymore), and we also lose the > keyboard hook/grab. > > The end result works better than spicec, which didn't exclude the > Windows statusbar, and was subject to losing pointer when wrapping > mouse over it. > > Another approach I have been playing with is to clip the cursor, and > process raw input messages, this will have the advantage to work even > when the client is completely out of the working area (under the > statusbar for example), but the complexity involved is too high for > very poor benefit (interacting with a non-visible client), we could > even argue that the behaviour implemented by this patch is more > correct (it refuses to grab the cursor if the client isn't visible in > the working area). > > This solves the following bugs: > https://bugzilla.redhat.com/show_bug.cgi?id=857430 > https://bugzilla.redhat.com/show_bug.cgi?id=857389 > --- > gtk/spice-widget.c | 69 ++++++++++++++++++++++++++++++++++++++++-------------- > 1 file changed, 51 insertions(+), 18 deletions(-) > > diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c > index 023ec5e..63f8425 100644 > --- a/gtk/spice-widget.c > +++ b/gtk/spice-widget.c > @@ -599,17 +599,57 @@ static void update_keyboard_grab(SpiceDisplay *display) > try_keyboard_ungrab(display); > } > > +#ifdef WIN32 > +static gboolean win32_clip_cursor(void) > +{ > + RECT window, workarea, rect; > + > + g_return_val_if_fail(win32_window != NULL, FALSE); > + > + if (!GetWindowRect(win32_window, &window)) > + goto error; > + > + if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea, 0)) > + goto error; > + > + if (!IntersectRect(&rect, &window, &workarea)) > + return false; > + > + SPICE_DEBUG("clip rect %ld %ld %ld %ld\n", > + rect.left, rect.right, rect.top, rect.bottom); > + > + if (!ClipCursor(&rect)) > + goto error; > + > + return true; > + > +error: > + { > + DWORD errval = GetLastError(); > + gchar *errstr = g_win32_error_message(errval); > + g_warning("failed to clip cursor (%ld) %s", errval, errstr); > + } > + > + return false; > +} > +#endif > + > static GdkGrabStatus do_pointer_grab(SpiceDisplay *display) > { > SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); > GdkWindow *window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display))); > - GdkGrabStatus status; > + GdkGrabStatus status = GDK_GRAB_BROKEN; > GdkCursor *blank = get_blank_cursor(); > > if (!gtk_widget_get_realized(GTK_WIDGET(display))) > - return GDK_GRAB_BROKEN; > - try_keyboard_grab(display); > + goto end; > + > +#ifdef WIN32 > + if (!win32_clip_cursor()) > + goto end; > +#endif > > + try_keyboard_grab(display); > /* > * from gtk-vnc: > * For relative mouse to work correctly when grabbed we need to > @@ -635,18 +675,6 @@ static GdkGrabStatus do_pointer_grab(SpiceDisplay *display) > d->mouse_grab_active = true; > g_signal_emit(display, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, true); > } > -#ifdef WIN32 > - { > - RECT client_rect; > - POINT origin; > - > - origin.x = origin.y = 0; > - ClientToScreen(focus_window, &origin); > - GetClientRect(focus_window, &client_rect); > - OffsetRect(&client_rect, origin.x, origin.y); > - ClipCursor(&client_rect); > - } > -#endif > > #ifdef GDK_WINDOWING_X11 > if (status == GDK_GRAB_SUCCESS) { > @@ -663,6 +691,7 @@ static GdkGrabStatus do_pointer_grab(SpiceDisplay *display) > } > #endif > > +end: > gdk_cursor_unref(blank); > return status; > } > @@ -722,10 +751,14 @@ static void mouse_wrap(SpiceDisplay *display, GdkEventMotion *motion) > { > SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); > GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(display)); > + gint xr, yr; > > - gint xr = gdk_screen_get_width(screen) / 2; > - gint yr = gdk_screen_get_height(screen) / 2; > - > +#ifdef WIN32 > + RECT clip; > + g_return_if_fail(GetClipCursor(&clip)); > + xr = clip.left + (clip.right - clip.left) / 2; > + yr = clip.top + (clip.bottom - clip.top) / 2; > +#endif > if (xr != (gint)motion->x_root || yr != (gint)motion->y_root) { xr and yr are no longer initialized at this point on !WIN32 Patch looks good otherwise. Christophe > /* FIXME: we try our best to ignore that next pointer move event.. */ > gdk_display_sync(gdk_screen_get_display(screen)); > -- > 1.7.11.7 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpCjkJnQ_AQY.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel