From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:52956) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzGoj-0002Ke-HU for qemu-devel@nongnu.org; Sun, 19 Feb 2012 19:09:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RzGoi-0004jM-73 for qemu-devel@nongnu.org; Sun, 19 Feb 2012 19:09:21 -0500 Received: from mail-tul01m020-f173.google.com ([209.85.214.173]:56406) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzGoi-0004jE-0W for qemu-devel@nongnu.org; Sun, 19 Feb 2012 19:09:20 -0500 Received: by obbup16 with SMTP id up16so7421467obb.4 for ; Sun, 19 Feb 2012 16:09:19 -0800 (PST) Message-ID: <4F418F2D.1090304@codemonkey.ws> Date: Sun, 19 Feb 2012 18:09:17 -0600 From: Anthony Liguori MIME-Version: 1.0 References: <1329695104-15174-1-git-send-email-aliguori@us.ibm.com> <1329695104-15174-5-git-send-email-aliguori@us.ibm.com> In-Reply-To: <1329695104-15174-5-git-send-email-aliguori@us.ibm.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 4/6] gtk: add support for input grabbing List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori Cc: qemu-devel@nongnu.org, Alex Graf On 02/19/2012 05:45 PM, Anthony Liguori wrote: > There is a small deviation from SDL's behavior here. Instead of Ctrl+Alt > triggering grab, we now use Ctrl-Alt-g to trigger grab. > > GTK will not accept Ctrl+Alt as an accelerator since it just consists of > modifiers. Having grab as a proper accelerator is important as it allows a user > to override the accelerator for accessibility purposes. > > We also are not automatically grabbing on left-click. Besides the inability to > tie mouse clicks to an accelerator, I think this behavior is hard to discover > and since it only happens depending on the guest state, it can lead to confusing > behavior. > > This can be changed in the future if there's a strong resistence to dropping > left-click-to-grab, but I think we're better off dropping it. > > Signed-off-by: Anthony Liguori > --- > ui/gtk.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 98 insertions(+), 4 deletions(-) > > diff --git a/ui/gtk.c b/ui/gtk.c > index bf65a4f..73051db 100644 > --- a/ui/gtk.c > +++ b/ui/gtk.c > @@ -58,6 +58,7 @@ typedef struct GtkDisplayState > > GtkWidget *view_menu_item; > GtkWidget *view_menu; > + GtkWidget *grab_item; > GtkWidget *vga_item; > > int nb_vcs; > @@ -86,6 +87,11 @@ static GtkDisplayState *global_state; > > /** Utility Functions **/ > > +static bool gd_is_grab_active(GtkDisplayState *s) > +{ > + return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->grab_item)); > +} > + > static void gd_update_cursor(GtkDisplayState *s, gboolean override) > { > GdkWindow *window; > @@ -95,7 +101,8 @@ static void gd_update_cursor(GtkDisplayState *s, gboolean override) > > on_vga = (gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook)) == 0); > > - if ((override || on_vga)&& kbd_mouse_is_absolute()) { > + if ((override || on_vga)&& > + (kbd_mouse_is_absolute() || gd_is_grab_active(s))) { > gdk_window_set_cursor(window, s->null_cursor); > } else { > gdk_window_set_cursor(window, NULL); > @@ -106,15 +113,20 @@ static void gd_update_caption(GtkDisplayState *s) > { > const char *status = ""; > gchar *title; > + const char *grab = ""; > + > + if (gd_is_grab_active(s)) { > + grab = " - Press Ctrl+Alt+G to release grab"; > + } > > if (!runstate_is_running()) { > status = " [Stopped]"; > } > > if (qemu_name) { > - title = g_strdup_printf("QEMU (%s)%s", qemu_name, status); > + title = g_strdup_printf("QEMU (%s)%s%s", qemu_name, status, grab); > } else { > - title = g_strdup_printf("QEMU%s", status); > + title = g_strdup_printf("QEMU%s%s", status, grab); > } > > gtk_window_set_title(GTK_WINDOW(s->window), title); > @@ -288,10 +300,44 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, > s->last_x = x; > s->last_y = y; > > - if (kbd_mouse_is_absolute()) { > + if (kbd_mouse_is_absolute() || gd_is_grab_active(s)) { > kbd_mouse_event(dx, dy, 0, s->button_mask); > } > > + if (!kbd_mouse_is_absolute()&& gd_is_grab_active(s)) { > + GdkDrawable *drawable = GDK_DRAWABLE(gtk_widget_get_window(s->drawing_area)); > + GdkDisplay *display = gdk_drawable_get_display(drawable); > + GdkScreen *screen = gdk_drawable_get_screen(drawable); > + int x = (int)motion->x_root; > + int y = (int)motion->y_root; > + > + /* In relative mode check to see if client pointer hit > + * one of the screen 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 (y == 0) { > + y += 200; > + } > + if (x == (gdk_screen_get_width(screen) - 1)) { > + x -= 200; > + } > + if (y == (gdk_screen_get_height(screen) - 1)) { > + y -= 200; > + } > + > + if (x != (int)motion->x_root || y != (int)motion->y_root) { > + gdk_display_warp_pointer(display, screen, x, y); > + s->last_x = -1; > + s->last_y = -1; > + return FALSE; > + } This clause is almost verbatim from gtk-vnc. The long helpful comment indicates that it probably wasn't written by me :-) I'll throw in the gtk-vnc copyright statement in the next round. Regards, Anthony Liguori > + } > return TRUE; > } > > @@ -407,15 +453,52 @@ static void gd_menu_show_tabs(GtkMenuItem *item, void *opaque) > } > } > > +static void gd_menu_grab_input(GtkMenuItem *item, void *opaque) > +{ > + GtkDisplayState *s = opaque; > + > + if (gd_is_grab_active(s)) { > + gdk_keyboard_grab(gtk_widget_get_window(GTK_WIDGET(s->drawing_area)), > + FALSE, > + GDK_CURRENT_TIME); > + gdk_pointer_grab(gtk_widget_get_window(GTK_WIDGET(s->drawing_area)), > + FALSE, /* All events to come to our window directly */ > + GDK_POINTER_MOTION_MASK | > + GDK_BUTTON_PRESS_MASK | > + GDK_BUTTON_RELEASE_MASK | > + GDK_BUTTON_MOTION_MASK | > + GDK_SCROLL_MASK, > + NULL, /* Allow cursor to move over entire desktop */ > + s->null_cursor, > + GDK_CURRENT_TIME); > + } else { > + gdk_keyboard_ungrab(GDK_CURRENT_TIME); > + gdk_pointer_ungrab(GDK_CURRENT_TIME); > + } > + > + gd_update_caption(s); > + gd_update_cursor(s, FALSE); > +} > + > static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2, > gpointer data) > { > GtkDisplayState *s = data; > + gboolean on_vga; > > if (!gtk_widget_get_realized(s->notebook)) { > return; > } > > + on_vga = arg2 == 0; > + > + if (!on_vga) { > + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), > + FALSE); > + } > + > + gtk_widget_set_sensitive(s->grab_item, on_vga); > + > gd_update_cursor(s, TRUE); > } > > @@ -566,6 +649,8 @@ static void gd_connect_signals(GtkDisplayState *s) > G_CALLBACK(gd_menu_quit), s); > g_signal_connect(s->vga_item, "activate", > G_CALLBACK(gd_menu_switch_vc), s); > + g_signal_connect(s->grab_item, "activate", > + G_CALLBACK(gd_menu_grab_input), s); > g_signal_connect(s->notebook, "switch-page", > G_CALLBACK(gd_change_page), s); > } > @@ -596,6 +681,15 @@ static void gd_create_menus(GtkDisplayState *s) > separator = gtk_separator_menu_item_new(); > gtk_menu_append(GTK_MENU(s->view_menu), separator); > > + s->grab_item = gtk_check_menu_item_new_with_mnemonic("_Grab Input"); > + gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->grab_item), > + "/View/Grab Input"); > + gtk_accel_map_add_entry("/View/Grab Input", GDK_KEY_g, GDK_CONTROL_MASK | GDK_MOD1_MASK); > + gtk_menu_append(GTK_MENU(s->view_menu), s->grab_item); > + > + separator = gtk_separator_menu_item_new(); > + gtk_menu_append(GTK_MENU(s->view_menu), separator); > + > s->vga_item = gtk_radio_menu_item_new_with_mnemonic(group, "_VGA"); > group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(s->vga_item)); > gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->vga_item),