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 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).