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),
next prev parent 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.