qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: Anthony Liguori <aliguori@us.ibm.com>
Cc: qemu-devel@nongnu.org, Alex Graf <agraf@suse.de>
Subject: Re: [Qemu-devel] [PATCH 4/6] gtk: add support for input grabbing
Date: Sun, 19 Feb 2012 18:09:17 -0600	[thread overview]
Message-ID: <4F418F2D.1090304@codemonkey.ws> (raw)
In-Reply-To: <1329695104-15174-5-git-send-email-aliguori@us.ibm.com>

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<aliguori@us.ibm.com>
> ---
>   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),
> +                                 "<QEMU>/View/Grab Input");
> +    gtk_accel_map_add_entry("<QEMU>/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),

  reply	other threads:[~2012-02-20  0:09 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-19 23:44 [Qemu-devel] [PATCH 0/6] Add GTK UI to enable basic accessibility Anthony Liguori
2012-02-19 23:44 ` [Qemu-devel] [PATCH 1/6] console: allow VCs to be overridden by UI Anthony Liguori
2012-02-20  9:17   ` Gerd Hoffmann
2012-02-20 13:45     ` Anthony Liguori
2012-02-20 13:59       ` Gerd Hoffmann
2012-02-20 14:11         ` Anthony Liguori
2012-02-20 14:27           ` Gerd Hoffmann
2012-02-20 15:10             ` Anthony Liguori
2012-02-19 23:45 ` [Qemu-devel] [PATCH 2/6] ui: add basic GTK gui Anthony Liguori
2012-02-20 20:45   ` Stefan Weil
2012-02-21  0:20     ` Anthony Liguori
2012-02-19 23:45 ` [Qemu-devel] [PATCH 3/6] gtk: add virtual console support Anthony Liguori
2012-02-20 21:13   ` Stefan Weil
2012-02-25 16:21   ` Stefan Weil
2012-02-25 19:49     ` Anthony Liguori
2012-02-25 20:22       ` Stefan Weil
2012-02-25 21:18         ` Anthony Liguori
2012-02-19 23:45 ` [Qemu-devel] [PATCH 4/6] gtk: add support for input grabbing Anthony Liguori
2012-02-20  0:09   ` Anthony Liguori [this message]
2012-02-19 23:45 ` [Qemu-devel] [PATCH 5/6] gtk: add support for screen scaling and full screen Anthony Liguori
2012-02-20  7:41   ` Paolo Bonzini
2012-02-20 13:45     ` Anthony Liguori
2012-02-25 15:49   ` Stefan Weil
2012-02-19 23:45 ` [Qemu-devel] [PATCH 6/6] gtk: make default UI Anthony Liguori
2012-02-20  0:15   ` Roy Tam
2012-02-20  1:10     ` Anthony Liguori
2012-02-20  1:50       ` Roy Tam
2012-02-20  2:22         ` Anthony Liguori
2012-02-20  2:24       ` Brad Smith
2012-02-20  2:44         ` Anthony Liguori
2012-02-20  2:50           ` Roy Tam
2012-02-20  2:52           ` Brad Smith
2012-02-20  3:04             ` Anthony Liguori
2012-02-20 14:06               ` Stefano Stabellini
2012-02-20 14:07                 ` Anthony Liguori
2012-02-20 14:44                   ` Stefano Stabellini
2012-02-20 14:46                     ` Roy Tam
2012-02-19 23:59 ` [Qemu-devel] [PATCH 0/6] Add GTK UI to enable basic accessibility Anthony Liguori
2012-02-20 12:17 ` Kevin Wolf
2012-02-20 12:47   ` Kevin Wolf
2012-02-20 14:08     ` Anthony Liguori
2012-02-20 14:04   ` Anthony Liguori
2012-02-20 14:33     ` Kevin Wolf
2012-02-25 17:02 ` Stefan Weil
2012-02-25 20:11   ` Anthony Liguori
2012-02-25 21:15     ` Stefan Weil
2012-02-25 21:47       ` [Qemu-devel] Very small VGA window sizes (was: Re: [PATCH 0/6] Add GTK UI to enable basic accessibility) Stefan Weil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F418F2D.1090304@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=agraf@suse.de \
    --cc=aliguori@us.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).