Looks good, On Wed, Nov 14, 2012 at 03:21:36PM +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). > > v2: > - choose the nearest monitor for clipping > - the ClipRegion is in Windows coordinate, we can't use gdk warp > - fix https://bugzilla.redhat.com/show_bug.cgi?id=872640 Minor nit, this should not be in the commit log, but below the --- so that it's there for the reviewer, but does not end in git history. But thanks for adding such a log :) ACK Christophe > > 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 | 90 ++++++++++++++++++++++++++++++++++++++++++------------ > 1 file changed, 71 insertions(+), 19 deletions(-) > > diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c > index 1858499..fd4d9e6 100644 > --- a/gtk/spice-widget.c > +++ b/gtk/spice-widget.c > @@ -725,17 +725,66 @@ static void set_mouse_accel(SpiceDisplay *display, gboolean enabled) > #endif > } > > +#ifdef WIN32 > +static gboolean win32_clip_cursor(void) > +{ > + RECT window, workarea, rect; > + HMONITOR monitor; > + MONITORINFO mi = { 0, }; > + > + g_return_val_if_fail(win32_window != NULL, FALSE); > + > + if (!GetWindowRect(win32_window, &window)) > + goto error; > + > + monitor = MonitorFromRect(&window, MONITOR_DEFAULTTONEAREST); > + g_return_val_if_fail(monitor != NULL, false); > + > + mi.cbSize = sizeof(mi); > + if (!GetMonitorInfo(monitor, &mi)) > + goto error; > + workarea = mi.rcWork; > + > + if (!IntersectRect(&rect, &window, &workarea)) { > + g_critical("error clipping cursor"); > + 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 > @@ -761,22 +810,11 @@ 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 > > if (status == GDK_GRAB_SUCCESS) > set_mouse_accel(display, FALSE); > > +end: > gdk_cursor_unref(blank); > return status; > } > @@ -835,10 +873,21 @@ static void try_mouse_grab(SpiceDisplay *display) > 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; > + /* the clip rectangle has no offset, so we can't use gdk_wrap_pointer */ > + SetCursorPos(xr, yr); > + d->mouse_last_x = -1; > + d->mouse_last_y = -1; > +#else > + GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(display)); > + xr = gdk_screen_get_width(screen) / 2; > + 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.. */ > @@ -849,6 +898,8 @@ static void mouse_wrap(SpiceDisplay *display, GdkEventMotion *motion) > d->mouse_last_x = -1; > d->mouse_last_y = -1; > } > +#endif > + > } > > static void try_mouse_ungrab(SpiceDisplay *display) > @@ -1409,7 +1460,8 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion) > > d->mouse_last_x = x; > d->mouse_last_y = y; > - mouse_wrap(display, motion); > + if (dx != 0 || dy != 0) > + mouse_wrap(display, motion); > } > break; > default: > -- > 1.7.11.7 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpO1mPTICpyV.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel