All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support.
@ 2014-05-26  8:13 Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 01/24] gtk: zap scrolled_window Gerd Hoffmann
                   ` (23 more replies)
  0 siblings, 24 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:13 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

This series adds multiwindow support to the gtk ui.
Also brings some cleanups and bugfixes.

cheers,
  Gerd

The following changes since commit 178ac111bca16c08a79b2609ebdc75197bea976a:

  Merge remote-tracking branch 'remotes/qmp-unstable/queue/qmp' into staging (2014-05-22 19:04:49 +0100)

are available in the git repository at:


  git://git.kraxel.org/qemu tags/pull-gtk-7

for you to fetch changes up to 6fa27697514bb45e80fcb57f38054a8833f87ff9:

  gtk: workaround gtk2 vte resize issue (2014-05-26 08:41:04 +0200)

----------------------------------------------------------------
gtk: ui overhaul, multiwindow support.

----------------------------------------------------------------
Bruce Rogers (1):
      gtk: Add handling for the xfree86 keycodes

Cole Robinson (1):
      gtk: Add a scrollbar for text consoles

Gerd Hoffmann (22):
      gtk: zap scrolled_window
      gtk: zap vte size requests
      gtk: cleanup CONFIG_VTE ifdef a bit.
      gtk: remove page numbering assumtions from the code
      gtk: VirtualConsole restruction
      gtk: move vga state into VirtualGfxConsole
      gtk: support multiple gfx displays
      gtk: use device type as label
      gtk: simplify resize
      gtk: allow moving tabs to windows and back.
      gtk: add tab to trace events
      gtk: add gd_grab trace event
      gtk: keep track of grab owner
      gtk: skip keyboard grab when hover autograb is active
      gtk: update gd_update_caption
      gtk: fix grab checks
      gtk: update all windows on mouse mode changes
      gtk: detached window pointer grabs
      gtk: enable untabify for gfx
      gtk: zap unused global_state
      gtk: window sizing overhaul
      gtk: workaround gtk2 vte resize issue

 trace-events |    7 +-
 ui/gtk.c     | 1108 ++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 738 insertions(+), 377 deletions(-)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 01/24] gtk: zap scrolled_window
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
@ 2014-05-26  8:13 ` Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 02/24] gtk: zap vte size requests Gerd Hoffmann
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:13 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

The vte widget implements the scrollable interface, placing it into
a scrolled window is pointless and creates a bunch of strange effects.
Zap it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 9f5061a..f6f3677 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -110,7 +110,6 @@ typedef struct VirtualConsole
     GtkWidget *menu_item;
     GtkWidget *terminal;
 #if defined(CONFIG_VTE)
-    GtkWidget *scrolled_window;
     CharDriverState *chr;
 #endif
 } VirtualConsole;
@@ -1189,8 +1188,6 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     const char *label;
     char buffer[32];
     char path[32];
-    GtkWidget *scrolled_window;
-    GtkAdjustment *vadjustment;
 
     snprintf(buffer, sizeof(buffer), "vc%d", index);
     snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
@@ -1213,24 +1210,12 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
 
     vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1);
 
-#if VTE_CHECK_VERSION(0, 28, 0) && GTK_CHECK_VERSION(3, 0, 0)
-    vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vc->terminal));
-#else
-    vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal));
-#endif
-
-    scrolled_window = gtk_scrolled_window_new(NULL, vadjustment);
-    gtk_container_add(GTK_CONTAINER(scrolled_window), vc->terminal);
-
     vte_terminal_set_size(VTE_TERMINAL(vc->terminal), 80, 25);
 
     vc->chr->opaque = vc;
-    vc->scrolled_window = scrolled_window;
-
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vc->scrolled_window),
-                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
-    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), scrolled_window, gtk_label_new(label));
+    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->terminal,
+                             gtk_label_new(label));
     g_signal_connect(vc->menu_item, "activate",
                      G_CALLBACK(gd_menu_switch_vc), s);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 02/24] gtk: zap vte size requests
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 01/24] gtk: zap scrolled_window Gerd Hoffmann
@ 2014-05-26  8:13 ` Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 03/24] gtk: cleanup CONFIG_VTE ifdef a bit Gerd Hoffmann
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:13 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

The vte tabs simply get the size of the vga tab then, with whatever
cols and lines are fitting in.  I find this bahavior more useful than
resizing the qemu window all day long.

YMMV.  Comments are welcome.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index f6f3677..776e72d 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1058,19 +1058,12 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
                            gpointer data)
 {
     GtkDisplayState *s = data;
-    guint last_page;
     gboolean on_vga;
 
     if (!gtk_widget_get_realized(s->notebook)) {
         return;
     }
 
-    last_page = gtk_notebook_get_current_page(nb);
-
-    if (last_page) {
-        gtk_widget_set_size_request(s->vc[last_page - 1].terminal, -1, -1);
-    }
-
     on_vga = arg2 == 0;
 
     if (!on_vga) {
@@ -1086,14 +1079,7 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
     } else {
 #if defined(CONFIG_VTE)
         VirtualConsole *vc = &s->vc[arg2 - 1];
-        VteTerminal *term = VTE_TERMINAL(vc->terminal);
-        int width, height;
-
-        width = 80 * vte_terminal_get_char_width(term);
-        height = 25 * vte_terminal_get_char_height(term);
-
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item), TRUE);
-        gtk_widget_set_size_request(vc->terminal, width, height);
 #else
         g_assert_not_reached();
 #endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 03/24] gtk: cleanup CONFIG_VTE ifdef a bit.
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 01/24] gtk: zap scrolled_window Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 02/24] gtk: zap vte size requests Gerd Hoffmann
@ 2014-05-26  8:13 ` Gerd Hoffmann
  2014-05-26  8:13 ` [Qemu-devel] [PULL 04/24] gtk: Add a scrollbar for text consoles Gerd Hoffmann
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:13 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 45 ++++++++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 19 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 776e72d..068a39b 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -108,8 +108,8 @@ static const int modifier_keycode[] = {
 typedef struct VirtualConsole
 {
     GtkWidget *menu_item;
-    GtkWidget *terminal;
 #if defined(CONFIG_VTE)
+    GtkWidget *terminal;
     CharDriverState *chr;
 #endif
 } VirtualConsole;
@@ -1124,13 +1124,12 @@ static gboolean gd_focus_out_event(GtkWidget *widget,
 
 /** Virtual Console Callbacks **/
 
+#if defined(CONFIG_VTE)
 static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
-#if defined(CONFIG_VTE)
     VirtualConsole *vc = chr->opaque;
 
     vte_terminal_feed(VTE_TERMINAL(vc->terminal), (const char *)buf, len);
-#endif
     return len;
 }
 
@@ -1151,12 +1150,6 @@ static CharDriverState *gd_vc_handler(ChardevVC *unused)
     return chr;
 }
 
-void early_gtk_display_init(void)
-{
-    register_vc_handler(gd_vc_handler);
-}
-
-#if defined(CONFIG_VTE)
 static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size,
                          gpointer user_data)
 {
@@ -1165,12 +1158,10 @@ static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size,
     qemu_chr_be_write(vc->chr, (uint8_t  *)text, (unsigned int)size);
     return TRUE;
 }
-#endif
 
 static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSList *group,
                           GtkWidget *view_menu)
 {
-#if defined(CONFIG_VTE)
     const char *label;
     char buffer[32];
     char path[32];
@@ -1212,10 +1203,23 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
         vc->chr->init(vc->chr);
     }
 
-#endif /* CONFIG_VTE */
     return group;
 }
 
+static void gd_vcs_init(GtkDisplayState *s, GSList *group,
+                        GtkWidget *view_menu)
+{
+    int i;
+
+    for (i = 0; i < nb_vcs; i++) {
+        VirtualConsole *vc = &s->vc[i];
+
+        group = gd_vc_init(s, vc, i, group, view_menu);
+        s->nb_vcs++;
+    }
+}
+#endif /* CONFIG_VTE */
+
 /** Window Creation **/
 
 static void gd_connect_signals(GtkDisplayState *s)
@@ -1316,7 +1320,6 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
     GSList *group = NULL;
     GtkWidget *view_menu;
     GtkWidget *separator;
-    int i;
 
     view_menu = gtk_menu_new();
     gtk_menu_set_accel_group(GTK_MENU(view_menu), accel_group);
@@ -1378,12 +1381,9 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
     gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, HOTKEY_MODIFIERS);
     gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->vga_item);
 
-    for (i = 0; i < nb_vcs; i++) {
-        VirtualConsole *vc = &s->vc[i];
-
-        group = gd_vc_init(s, vc, i, group, view_menu);
-        s->nb_vcs++;
-    }
+#if defined(CONFIG_VTE)
+    gd_vcs_init(s, group, view_menu);
+#endif
 
     separator = gtk_separator_menu_item_new();
     gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
@@ -1512,3 +1512,10 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
 
     global_state = s;
 }
+
+void early_gtk_display_init(void)
+{
+#if defined(CONFIG_VTE)
+    register_vc_handler(gd_vc_handler);
+#endif
+}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 04/24] gtk: Add a scrollbar for text consoles
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2014-05-26  8:13 ` [Qemu-devel] [PULL 03/24] gtk: cleanup CONFIG_VTE ifdef a bit Gerd Hoffmann
@ 2014-05-26  8:13 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 05/24] gtk: remove page numbering assumtions from the code Gerd Hoffmann
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:13 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori, Cole Robinson

From: Cole Robinson <crobinso@redhat.com>

Only show the scrollbar if the content doesn't fit on the visible space.

[ kraxel: fix box packing ]

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 068a39b..6a3fe00 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -109,6 +109,8 @@ typedef struct VirtualConsole
 {
     GtkWidget *menu_item;
 #if defined(CONFIG_VTE)
+    GtkWidget *box;
+    GtkWidget *scrollbar;
     GtkWidget *terminal;
     CharDriverState *chr;
 #endif
@@ -1125,6 +1127,18 @@ static gboolean gd_focus_out_event(GtkWidget *widget,
 /** Virtual Console Callbacks **/
 
 #if defined(CONFIG_VTE)
+static void gd_vc_adjustment_changed(GtkAdjustment *adjustment, void *opaque)
+{
+    VirtualConsole *vc = opaque;
+
+    if (gtk_adjustment_get_upper(adjustment) >
+        gtk_adjustment_get_page_size(adjustment)) {
+        gtk_widget_show(vc->scrollbar);
+    } else {
+        gtk_widget_hide(vc->scrollbar);
+    }
+}
+
 static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     VirtualConsole *vc = chr->opaque;
@@ -1165,6 +1179,9 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     const char *label;
     char buffer[32];
     char path[32];
+    GtkWidget *box;
+    GtkWidget *scrollbar;
+    GtkAdjustment *vadjustment;
 
     snprintf(buffer, sizeof(buffer), "vc%d", index);
     snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
@@ -1186,12 +1203,33 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     g_signal_connect(vc->terminal, "commit", G_CALLBACK(gd_vc_in), vc);
 
     vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1);
-
     vte_terminal_set_size(VTE_TERMINAL(vc->terminal), 80, 25);
 
+#if VTE_CHECK_VERSION(0, 28, 0) && GTK_CHECK_VERSION(3, 0, 0)
+    vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vc->terminal));
+#else
+    vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal));
+#endif
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+    box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
+    scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, vadjustment);
+#else
+    box = gtk_hbox_new(false, 2);
+    scrollbar = gtk_vscrollbar_new(vadjustment);
+#endif
+
+    gtk_box_pack_start(GTK_BOX(box), vc->terminal, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(box), scrollbar, FALSE, FALSE, 0);
+
     vc->chr->opaque = vc;
+    vc->box = box;
+    vc->scrollbar = scrollbar;
+
+    g_signal_connect(vadjustment, "changed",
+                     G_CALLBACK(gd_vc_adjustment_changed), vc);
 
-    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->terminal,
+    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), box,
                              gtk_label_new(label));
     g_signal_connect(vc->menu_item, "activate",
                      G_CALLBACK(gd_menu_switch_vc), s);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 05/24] gtk: remove page numbering assumtions from the code
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2014-05-26  8:13 ` [Qemu-devel] [PULL 04/24] gtk: Add a scrollbar for text consoles Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 06/24] gtk: VirtualConsole restruction Gerd Hoffmann
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Lookup page numbers using gtk_notebook_page_num() instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 40 ++++++++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 6a3fe00..49753ef 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -190,7 +190,11 @@ static bool gd_grab_on_hover(GtkDisplayState *s)
 
 static bool gd_on_vga(GtkDisplayState *s)
 {
-    return gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook)) == 0;
+    gint p1, p2;
+
+    p1 = gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook));
+    p2 = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), s->drawing_area);
+    return p1 == p2;
 }
 
 static void gd_update_cursor(GtkDisplayState *s, gboolean override)
@@ -805,19 +809,25 @@ static void gd_menu_quit(GtkMenuItem *item, void *opaque)
 static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    gint page;
 
     if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vga_item))) {
-        gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), 0);
+        page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
+                                     s->drawing_area);
+        gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
     } else {
-        int i;
-
         gtk_release_modifiers(s);
+#if defined(CONFIG_VTE)
+        gint i;
         for (i = 0; i < s->nb_vcs; i++) {
             if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vc[i].menu_item))) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), i + 1);
-                break;
+                page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
+                                             s->vc[i].box);
+                gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
+                return;
             }
         }
+#endif
     }
 }
 
@@ -1061,12 +1071,14 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
 {
     GtkDisplayState *s = data;
     gboolean on_vga;
+    gint page;
 
     if (!gtk_widget_get_realized(s->notebook)) {
         return;
     }
 
-    on_vga = arg2 == 0;
+    page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), s->drawing_area);
+    on_vga = arg2 == page;
 
     if (!on_vga) {
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
@@ -1076,12 +1088,20 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
                                        TRUE);
     }
 
-    if (arg2 == 0) {
+    if (on_vga) {
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->vga_item), TRUE);
     } else {
 #if defined(CONFIG_VTE)
-        VirtualConsole *vc = &s->vc[arg2 - 1];
-        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item), TRUE);
+        VirtualConsole *vc;
+        gint page, i;
+        for (i = 0; i < s->nb_vcs; i++) {
+            vc = &s->vc[i];
+            page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), vc->box);
+            if (page == arg2) {
+                gtk_check_menu_item_set_active
+                    (GTK_CHECK_MENU_ITEM(vc->menu_item), TRUE);
+            }
+        }
 #else
         g_assert_not_reached();
 #endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 06/24] gtk: VirtualConsole restruction
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 05/24] gtk: remove page numbering assumtions from the code Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 07/24] gtk: move vga state into VirtualGfxConsole Gerd Hoffmann
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Move all vte-related items into VirtualVteConsole substruct.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 119 +++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 73 insertions(+), 46 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 49753ef..78f6ccc 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -105,15 +105,23 @@ static const int modifier_keycode[] = {
     0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd,
 };
 
-typedef struct VirtualConsole
-{
-    GtkWidget *menu_item;
 #if defined(CONFIG_VTE)
+typedef struct VirtualVteConsole {
     GtkWidget *box;
     GtkWidget *scrollbar;
     GtkWidget *terminal;
     CharDriverState *chr;
+} VirtualVteConsole;
+#endif
+
+typedef struct VirtualConsole {
+    GtkWidget *menu_item;
+    GtkWidget *tab_item;
+    union {
+#if defined(CONFIG_VTE)
+        VirtualVteConsole vte;
 #endif
+    };
 } VirtualConsole;
 
 typedef struct GtkDisplayState
@@ -178,6 +186,36 @@ static GtkDisplayState *global_state;
 
 /** Utility Functions **/
 
+static VirtualConsole *gd_vc_find_by_menu(GtkDisplayState *s)
+{
+    VirtualConsole *vc;
+    gint i;
+
+    for (i = 0; i < s->nb_vcs; i++) {
+        vc = &s->vc[i];
+        if (gtk_check_menu_item_get_active
+            (GTK_CHECK_MENU_ITEM(vc->menu_item))) {
+            return vc;
+        }
+    }
+    return NULL;
+}
+
+static VirtualConsole *gd_vc_find_by_page(GtkDisplayState *s, gint page)
+{
+    VirtualConsole *vc;
+    gint i, p;
+
+    for (i = 0; i < s->nb_vcs; i++) {
+        vc = &s->vc[i];
+        p = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), vc->tab_item);
+        if (p == page) {
+            return vc;
+        }
+    }
+    return NULL;
+}
+
 static bool gd_is_grab_active(GtkDisplayState *s)
 {
     return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->grab_item));
@@ -817,17 +855,12 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
         gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
     } else {
         gtk_release_modifiers(s);
-#if defined(CONFIG_VTE)
-        gint i;
-        for (i = 0; i < s->nb_vcs; i++) {
-            if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vc[i].menu_item))) {
-                page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
-                                             s->vc[i].box);
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
-                return;
-            }
+        VirtualConsole *vc = gd_vc_find_by_menu(s);
+        if (vc) {
+            page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
+                                         vc->tab_item);
+            gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
         }
-#endif
     }
 }
 
@@ -1091,20 +1124,12 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
     if (on_vga) {
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->vga_item), TRUE);
     } else {
-#if defined(CONFIG_VTE)
         VirtualConsole *vc;
-        gint page, i;
-        for (i = 0; i < s->nb_vcs; i++) {
-            vc = &s->vc[i];
-            page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), vc->box);
-            if (page == arg2) {
-                gtk_check_menu_item_set_active
-                    (GTK_CHECK_MENU_ITEM(vc->menu_item), TRUE);
-            }
+        vc = gd_vc_find_by_page(s, arg2);
+        if (vc) {
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item),
+                                           TRUE);
         }
-#else
-        g_assert_not_reached();
-#endif
     }
 
     gtk_widget_set_sensitive(s->grab_item, on_vga);
@@ -1153,9 +1178,9 @@ static void gd_vc_adjustment_changed(GtkAdjustment *adjustment, void *opaque)
 
     if (gtk_adjustment_get_upper(adjustment) >
         gtk_adjustment_get_page_size(adjustment)) {
-        gtk_widget_show(vc->scrollbar);
+        gtk_widget_show(vc->vte.scrollbar);
     } else {
-        gtk_widget_hide(vc->scrollbar);
+        gtk_widget_hide(vc->vte.scrollbar);
     }
 }
 
@@ -1163,7 +1188,7 @@ static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     VirtualConsole *vc = chr->opaque;
 
-    vte_terminal_feed(VTE_TERMINAL(vc->terminal), (const char *)buf, len);
+    vte_terminal_feed(VTE_TERMINAL(vc->vte.terminal), (const char *)buf, len);
     return len;
 }
 
@@ -1189,7 +1214,7 @@ static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size,
 {
     VirtualConsole *vc = user_data;
 
-    qemu_chr_be_write(vc->chr, (uint8_t  *)text, (unsigned int)size);
+    qemu_chr_be_write(vc->vte.chr, (uint8_t  *)text, (unsigned int)size);
     return TRUE;
 }
 
@@ -1206,10 +1231,10 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     snprintf(buffer, sizeof(buffer), "vc%d", index);
     snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
 
-    vc->chr = vcs[index];
+    vc->vte.chr = vcs[index];
 
-    if (vc->chr->label) {
-        label = vc->chr->label;
+    if (vc->vte.chr->label) {
+        label = vc->vte.chr->label;
     } else {
         label = buffer;
     }
@@ -1219,16 +1244,17 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item), path);
     gtk_accel_map_add_entry(path, GDK_KEY_2 + index, HOTKEY_MODIFIERS);
 
-    vc->terminal = vte_terminal_new();
-    g_signal_connect(vc->terminal, "commit", G_CALLBACK(gd_vc_in), vc);
+    vc->vte.terminal = vte_terminal_new();
+    g_signal_connect(vc->vte.terminal, "commit", G_CALLBACK(gd_vc_in), vc);
 
-    vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1);
-    vte_terminal_set_size(VTE_TERMINAL(vc->terminal), 80, 25);
+    vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->vte.terminal), -1);
+    vte_terminal_set_size(VTE_TERMINAL(vc->vte.terminal), 80, 25);
 
 #if VTE_CHECK_VERSION(0, 28, 0) && GTK_CHECK_VERSION(3, 0, 0)
-    vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vc->terminal));
+    vadjustment = gtk_scrollable_get_vadjustment
+        (GTK_SCROLLABLE(vc->vte.terminal));
 #else
-    vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal));
+    vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->vte.terminal));
 #endif
 
 #if GTK_CHECK_VERSION(3, 0, 0)
@@ -1239,26 +1265,27 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     scrollbar = gtk_vscrollbar_new(vadjustment);
 #endif
 
-    gtk_box_pack_start(GTK_BOX(box), vc->terminal, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(box), vc->vte.terminal, TRUE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(box), scrollbar, FALSE, FALSE, 0);
 
-    vc->chr->opaque = vc;
-    vc->box = box;
-    vc->scrollbar = scrollbar;
+    vc->vte.chr->opaque = vc;
+    vc->vte.box = box;
+    vc->vte.scrollbar = scrollbar;
 
     g_signal_connect(vadjustment, "changed",
                      G_CALLBACK(gd_vc_adjustment_changed), vc);
 
-    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), box,
+    vc->tab_item = box;
+    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item,
                              gtk_label_new(label));
     g_signal_connect(vc->menu_item, "activate",
                      G_CALLBACK(gd_menu_switch_vc), s);
 
     gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item);
 
-    qemu_chr_be_generic_open(vc->chr);
-    if (vc->chr->init) {
-        vc->chr->init(vc->chr);
+    qemu_chr_be_generic_open(vc->vte.chr);
+    if (vc->vte.chr->init) {
+        vc->vte.chr->init(vc->vte.chr);
     }
 
     return group;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 07/24] gtk: move vga state into VirtualGfxConsole
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 06/24] gtk: VirtualConsole restruction Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 08/24] gtk: support multiple gfx displays Gerd Hoffmann
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 615 ++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 337 insertions(+), 278 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 78f6ccc..bc42f68 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -105,6 +105,18 @@ static const int modifier_keycode[] = {
     0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd,
 };
 
+typedef struct GtkDisplayState GtkDisplayState;
+
+typedef struct VirtualGfxConsole {
+    GtkWidget *drawing_area;
+    DisplayChangeListener dcl;
+    DisplaySurface *ds;
+    pixman_image_t *convert;
+    cairo_surface_t *surface;
+    double scale_x;
+    double scale_y;
+} VirtualGfxConsole;
+
 #if defined(CONFIG_VTE)
 typedef struct VirtualVteConsole {
     GtkWidget *box;
@@ -114,18 +126,25 @@ typedef struct VirtualVteConsole {
 } VirtualVteConsole;
 #endif
 
+typedef enum VirtualConsoleType {
+    GD_VC_GFX,
+    GD_VC_VTE,
+} VirtualConsoleType;
+
 typedef struct VirtualConsole {
+    GtkDisplayState *s;
     GtkWidget *menu_item;
     GtkWidget *tab_item;
+    VirtualConsoleType type;
     union {
+        VirtualGfxConsole gfx;
 #if defined(CONFIG_VTE)
         VirtualVteConsole vte;
 #endif
     };
 } VirtualConsole;
 
-typedef struct GtkDisplayState
-{
+struct GtkDisplayState {
     GtkWidget *window;
 
     GtkWidget *menu_bar;
@@ -148,7 +167,6 @@ typedef struct GtkDisplayState
     GtkWidget *zoom_fit_item;
     GtkWidget *grab_item;
     GtkWidget *grab_on_hover_item;
-    GtkWidget *vga_item;
 
     int nb_vcs;
     VirtualConsole vc[MAX_VCS];
@@ -157,11 +175,6 @@ typedef struct GtkDisplayState
 
     GtkWidget *vbox;
     GtkWidget *notebook;
-    GtkWidget *drawing_area;
-    cairo_surface_t *surface;
-    pixman_image_t *convert;
-    DisplayChangeListener dcl;
-    DisplaySurface *ds;
     int button_mask;
     gboolean last_set;
     int last_x;
@@ -169,8 +182,6 @@ typedef struct GtkDisplayState
     int grab_x_root;
     int grab_y_root;
 
-    double scale_x;
-    double scale_y;
     gboolean full_screen;
 
     GdkCursor *null_cursor;
@@ -180,7 +191,7 @@ typedef struct GtkDisplayState
     bool external_pause_update;
 
     bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
-} GtkDisplayState;
+};
 
 static GtkDisplayState *global_state;
 
@@ -216,6 +227,14 @@ static VirtualConsole *gd_vc_find_by_page(GtkDisplayState *s, gint page)
     return NULL;
 }
 
+static VirtualConsole *gd_vc_find_current(GtkDisplayState *s)
+{
+    gint page;
+
+    page = gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook));
+    return gd_vc_find_by_page(s, page);
+}
+
 static bool gd_is_grab_active(GtkDisplayState *s)
 {
     return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->grab_item));
@@ -226,26 +245,17 @@ static bool gd_grab_on_hover(GtkDisplayState *s)
     return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->grab_on_hover_item));
 }
 
-static bool gd_on_vga(GtkDisplayState *s)
-{
-    gint p1, p2;
-
-    p1 = gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook));
-    p2 = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), s->drawing_area);
-    return p1 == p2;
-}
-
-static void gd_update_cursor(GtkDisplayState *s, gboolean override)
+static void gd_update_cursor(VirtualConsole *vc)
 {
+    GtkDisplayState *s = vc->s;
     GdkWindow *window;
-    bool on_vga;
-
-    window = gtk_widget_get_window(GTK_WIDGET(s->drawing_area));
 
-    on_vga = gd_on_vga(s);
+    if (vc->type != GD_VC_GFX) {
+        return;
+    }
 
-    if ((override || on_vga) &&
-        (s->full_screen || qemu_input_is_absolute() || gd_is_grab_active(s))) {
+    window = gtk_widget_get_window(GTK_WIDGET(vc->gfx.drawing_area));
+    if (s->full_screen || qemu_input_is_absolute() || gd_is_grab_active(s)) {
         gdk_window_set_cursor(window, s->null_cursor);
     } else {
         gdk_window_set_cursor(window, NULL);
@@ -282,26 +292,29 @@ static void gd_update_caption(GtkDisplayState *s)
     g_free(title);
 }
 
-static void gd_update_windowsize(GtkDisplayState *s)
+static void gd_update_windowsize(VirtualConsole *vc)
 {
+    GtkDisplayState *s = vc->s;
+
     if (!s->full_screen) {
         GtkRequisition req;
         double sx, sy;
 
         if (s->free_scale) {
-            sx = s->scale_x;
-            sy = s->scale_y;
+            sx = vc->gfx.scale_x;
+            sy = vc->gfx.scale_y;
 
-            s->scale_y = 1.0;
-            s->scale_x = 1.0;
+            vc->gfx.scale_y = 1.0;
+            vc->gfx.scale_x = 1.0;
         } else {
             sx = 1.0;
             sy = 1.0;
         }
 
-        gtk_widget_set_size_request(s->drawing_area,
-                                    surface_width(s->ds) * s->scale_x,
-                                    surface_height(s->ds) * s->scale_y);
+        gtk_widget_set_size_request
+            (vc->gfx.drawing_area,
+             surface_width(vc->gfx.ds) * vc->gfx.scale_x,
+             surface_height(vc->gfx.ds) * vc->gfx.scale_y);
 #if GTK_CHECK_VERSION(3, 0, 0)
         gtk_widget_get_preferred_size(s->vbox, NULL, &req);
 #else
@@ -313,18 +326,20 @@ static void gd_update_windowsize(GtkDisplayState *s)
     }
 }
 
-static void gd_update_full_redraw(GtkDisplayState *s)
+static void gd_update_full_redraw(VirtualConsole *vc)
 {
+    GtkWidget *area = vc->gfx.drawing_area;
     int ww, wh;
-    gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
-    gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
+    gdk_drawable_get_size(gtk_widget_get_window(area), &ww, &wh);
+    gtk_widget_queue_draw_area(area, 0, 0, ww, wh);
 }
 
 static void gtk_release_modifiers(GtkDisplayState *s)
 {
+    VirtualConsole *vc = gd_vc_find_current(s);
     int i, keycode;
 
-    if (!gd_on_vga(s)) {
+    if (vc->type != GD_VC_GFX) {
         return;
     }
     for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
@@ -332,7 +347,7 @@ static void gtk_release_modifiers(GtkDisplayState *s)
         if (!s->modifier_pressed[i]) {
             continue;
         }
-        qemu_input_event_send_key_number(s->dcl.con, keycode, false);
+        qemu_input_event_send_key_number(vc->gfx.dcl.con, keycode, false);
         s->modifier_pressed[i] = false;
     }
 }
@@ -342,7 +357,7 @@ static void gtk_release_modifiers(GtkDisplayState *s)
 static void gd_update(DisplayChangeListener *dcl,
                       int x, int y, int w, int h)
 {
-    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
     int x1, x2, y1, y2;
     int mx, my;
     int fbw, fbh;
@@ -350,21 +365,23 @@ static void gd_update(DisplayChangeListener *dcl,
 
     trace_gd_update(x, y, w, h);
 
-    if (s->convert) {
-        pixman_image_composite(PIXMAN_OP_SRC, s->ds->image, NULL, s->convert,
+    if (vc->gfx.convert) {
+        pixman_image_composite(PIXMAN_OP_SRC, vc->gfx.ds->image,
+                               NULL, vc->gfx.convert,
                                x, y, 0, 0, x, y, w, h);
     }
 
-    x1 = floor(x * s->scale_x);
-    y1 = floor(y * s->scale_y);
+    x1 = floor(x * vc->gfx.scale_x);
+    y1 = floor(y * vc->gfx.scale_y);
 
-    x2 = ceil(x * s->scale_x + w * s->scale_x);
-    y2 = ceil(y * s->scale_y + h * s->scale_y);
+    x2 = ceil(x * vc->gfx.scale_x + w * vc->gfx.scale_x);
+    y2 = ceil(y * vc->gfx.scale_y + h * vc->gfx.scale_y);
 
-    fbw = surface_width(s->ds) * s->scale_x;
-    fbh = surface_height(s->ds) * s->scale_y;
+    fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
+    fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
 
-    gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
+    gdk_drawable_get_size(gtk_widget_get_window(vc->gfx.drawing_area),
+                          &ww, &wh);
 
     mx = my = 0;
     if (ww > fbw) {
@@ -374,7 +391,8 @@ static void gd_update(DisplayChangeListener *dcl,
         my = (wh - fbh) / 2;
     }
 
-    gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1));
+    gtk_widget_queue_draw_area(vc->gfx.drawing_area,
+                               mx + x1, my + y1, (x2 - x1), (y2 - y1));
 }
 
 static void gd_refresh(DisplayChangeListener *dcl)
@@ -386,7 +404,7 @@ static void gd_refresh(DisplayChangeListener *dcl)
 static void gd_mouse_set(DisplayChangeListener *dcl,
                          int x, int y, int visible)
 {
-    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
     GdkDisplay *dpy;
     GdkDeviceManager *mgr;
     gint x_root, y_root;
@@ -395,29 +413,29 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
         return;
     }
 
-    dpy = gtk_widget_get_display(s->drawing_area);
+    dpy = gtk_widget_get_display(vc->gfx.drawing_area);
     mgr = gdk_display_get_device_manager(dpy);
-    gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
+    gdk_window_get_root_coords(gtk_widget_get_window(vc->gfx.drawing_area),
                                x, y, &x_root, &y_root);
     gdk_device_warp(gdk_device_manager_get_client_pointer(mgr),
-                    gtk_widget_get_screen(s->drawing_area),
+                    gtk_widget_get_screen(vc->gfx.drawing_area),
                     x_root, y_root);
 }
 #else
 static void gd_mouse_set(DisplayChangeListener *dcl,
                          int x, int y, int visible)
 {
-    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
     gint x_root, y_root;
 
     if (qemu_input_is_absolute()) {
         return;
     }
 
-    gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
+    gdk_window_get_root_coords(gtk_widget_get_window(vc->gfx.drawing_area),
                                x, y, &x_root, &y_root);
-    gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area),
-                             gtk_widget_get_screen(s->drawing_area),
+    gdk_display_warp_pointer(gtk_widget_get_display(vc->gfx.drawing_area),
+                             gtk_widget_get_screen(vc->gfx.drawing_area),
                              x_root, y_root);
 }
 #endif
@@ -425,7 +443,7 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
 static void gd_cursor_define(DisplayChangeListener *dcl,
                              QEMUCursor *c)
 {
-    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
     GdkPixbuf *pixbuf;
     GdkCursor *cursor;
 
@@ -433,9 +451,10 @@ static void gd_cursor_define(DisplayChangeListener *dcl,
                                       GDK_COLORSPACE_RGB, true, 8,
                                       c->width, c->height, c->width * 4,
                                       NULL, NULL);
-    cursor = gdk_cursor_new_from_pixbuf(gtk_widget_get_display(s->drawing_area),
-                                        pixbuf, c->hot_x, c->hot_y);
-    gdk_window_set_cursor(gtk_widget_get_window(s->drawing_area), cursor);
+    cursor = gdk_cursor_new_from_pixbuf
+        (gtk_widget_get_display(vc->gfx.drawing_area),
+         pixbuf, c->hot_x, c->hot_y);
+    gdk_window_set_cursor(gtk_widget_get_window(vc->gfx.drawing_area), cursor);
     g_object_unref(pixbuf);
 #if !GTK_CHECK_VERSION(3, 0, 0)
     gdk_cursor_unref(cursor);
@@ -447,25 +466,25 @@ static void gd_cursor_define(DisplayChangeListener *dcl,
 static void gd_switch(DisplayChangeListener *dcl,
                       DisplaySurface *surface)
 {
-    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
     bool resized = true;
 
     trace_gd_switch(surface_width(surface), surface_height(surface));
 
-    if (s->surface) {
-        cairo_surface_destroy(s->surface);
+    if (vc->gfx.surface) {
+        cairo_surface_destroy(vc->gfx.surface);
     }
 
-    if (s->ds &&
-        surface_width(s->ds) == surface_width(surface) &&
-        surface_height(s->ds) == surface_height(surface)) {
+    if (vc->gfx.ds &&
+        surface_width(vc->gfx.ds) == surface_width(surface) &&
+        surface_height(vc->gfx.ds) == surface_height(surface)) {
         resized = false;
     }
-    s->ds = surface;
+    vc->gfx.ds = surface;
 
-    if (s->convert) {
-        pixman_image_unref(s->convert);
-        s->convert = NULL;
+    if (vc->gfx.convert) {
+        pixman_image_unref(vc->gfx.convert);
+        vc->gfx.convert = NULL;
     }
 
     if (surface->format == PIXMAN_x8r8g8b8) {
@@ -475,7 +494,7 @@ static void gd_switch(DisplayChangeListener *dcl,
          * No need to convert, use surface directly.  Should be the
          * common case as this is qemu_default_pixelformat(32) too.
          */
-        s->surface = cairo_image_surface_create_for_data
+        vc->gfx.surface = cairo_image_surface_create_for_data
             (surface_data(surface),
              CAIRO_FORMAT_RGB24,
              surface_width(surface),
@@ -483,26 +502,27 @@ static void gd_switch(DisplayChangeListener *dcl,
              surface_stride(surface));
     } else {
         /* Must convert surface, use pixman to do it. */
-        s->convert = pixman_image_create_bits(PIXMAN_x8r8g8b8,
-                                              surface_width(surface),
-                                              surface_height(surface),
-                                              NULL, 0);
-        s->surface = cairo_image_surface_create_for_data
-            ((void *)pixman_image_get_data(s->convert),
+        vc->gfx.convert = pixman_image_create_bits(PIXMAN_x8r8g8b8,
+                                                   surface_width(surface),
+                                                   surface_height(surface),
+                                                   NULL, 0);
+        vc->gfx.surface = cairo_image_surface_create_for_data
+            ((void *)pixman_image_get_data(vc->gfx.convert),
              CAIRO_FORMAT_RGB24,
-             pixman_image_get_width(s->convert),
-             pixman_image_get_height(s->convert),
-             pixman_image_get_stride(s->convert));
-        pixman_image_composite(PIXMAN_OP_SRC, s->ds->image, NULL, s->convert,
+             pixman_image_get_width(vc->gfx.convert),
+             pixman_image_get_height(vc->gfx.convert),
+             pixman_image_get_stride(vc->gfx.convert));
+        pixman_image_composite(PIXMAN_OP_SRC, vc->gfx.ds->image,
+                               NULL, vc->gfx.convert,
                                0, 0, 0, 0, 0, 0,
-                               pixman_image_get_width(s->convert),
-                               pixman_image_get_height(s->convert));
+                               pixman_image_get_width(vc->gfx.convert),
+                               pixman_image_get_height(vc->gfx.convert));
     }
 
     if (resized) {
-        gd_update_windowsize(s);
+        gd_update_windowsize(vc);
     } else {
-        gd_update_full_redraw(s);
+        gd_update_full_redraw(vc);
     }
 }
 
@@ -525,7 +545,7 @@ static void gd_mouse_mode_change(Notifier *notify, void *data)
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                        FALSE);
     }
-    gd_update_cursor(s, FALSE);
+    gd_update_cursor(gd_vc_find_current(s));
 }
 
 /** GTK Events **/
@@ -534,9 +554,15 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
                                 void *opaque)
 {
     GtkDisplayState *s = opaque;
+    int i;
 
     if (!no_quit) {
-        unregister_displaychangelistener(&s->dcl);
+        for (i = 0; i < s->nb_vcs; i++) {
+            if (s->vc[i].type != GD_VC_GFX) {
+                continue;
+            }
+            unregister_displaychangelistener(&s->vc[i].gfx.dcl);
+        }
         qmp_quit(NULL);
         return FALSE;
     }
@@ -546,7 +572,8 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
 
 static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
 {
-    GtkDisplayState *s = opaque;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
     int mx, my;
     int ww, wh;
     int fbw, fbh;
@@ -555,25 +582,25 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
         return FALSE;
     }
 
-    fbw = surface_width(s->ds);
-    fbh = surface_height(s->ds);
+    fbw = surface_width(vc->gfx.ds);
+    fbh = surface_height(vc->gfx.ds);
 
     gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh);
 
     if (s->full_screen) {
-        s->scale_x = (double)ww / fbw;
-        s->scale_y = (double)wh / fbh;
+        vc->gfx.scale_x = (double)ww / fbw;
+        vc->gfx.scale_y = (double)wh / fbh;
     } else if (s->free_scale) {
         double sx, sy;
 
         sx = (double)ww / fbw;
         sy = (double)wh / fbh;
 
-        s->scale_x = s->scale_y = MIN(sx, sy);
+        vc->gfx.scale_x = vc->gfx.scale_y = MIN(sx, sy);
     }
 
-    fbw *= s->scale_x;
-    fbh *= s->scale_y;
+    fbw *= vc->gfx.scale_x;
+    fbh *= vc->gfx.scale_y;
 
     mx = my = 0;
     if (ww > fbw) {
@@ -594,8 +621,9 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
                     -1 * fbw, fbh);
     cairo_fill(cr);
 
-    cairo_scale(cr, s->scale_x, s->scale_y);
-    cairo_set_source_surface(cr, s->surface, mx / s->scale_x, my / s->scale_y);
+    cairo_scale(cr, vc->gfx.scale_x, vc->gfx.scale_y);
+    cairo_set_source_surface(cr, vc->gfx.surface,
+                             mx / vc->gfx.scale_x, my / vc->gfx.scale_y);
     cairo_paint(cr);
 
     return TRUE;
@@ -627,16 +655,18 @@ static gboolean gd_expose_event(GtkWidget *widget, GdkEventExpose *expose,
 static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
                                 void *opaque)
 {
-    GtkDisplayState *s = opaque;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
     int x, y;
     int mx, my;
     int fbh, fbw;
     int ww, wh;
 
-    fbw = surface_width(s->ds) * s->scale_x;
-    fbh = surface_height(s->ds) * s->scale_y;
+    fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
+    fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
 
-    gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
+    gdk_drawable_get_size(gtk_widget_get_window(vc->gfx.drawing_area),
+                          &ww, &wh);
 
     mx = my = 0;
     if (ww > fbw) {
@@ -646,23 +676,23 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
         my = (wh - fbh) / 2;
     }
 
-    x = (motion->x - mx) / s->scale_x;
-    y = (motion->y - my) / s->scale_y;
+    x = (motion->x - mx) / vc->gfx.scale_x;
+    y = (motion->y - my) / vc->gfx.scale_y;
 
     if (qemu_input_is_absolute()) {
         if (x < 0 || y < 0 ||
-            x >= surface_width(s->ds) ||
-            y >= surface_height(s->ds)) {
+            x >= surface_width(vc->gfx.ds) ||
+            y >= surface_height(vc->gfx.ds)) {
             return TRUE;
         }
-        qemu_input_queue_abs(s->dcl.con, INPUT_AXIS_X, x,
-                             surface_width(s->ds));
-        qemu_input_queue_abs(s->dcl.con, INPUT_AXIS_Y, y,
-                             surface_height(s->ds));
+        qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_X, x,
+                             surface_width(vc->gfx.ds));
+        qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_Y, y,
+                             surface_height(vc->gfx.ds));
         qemu_input_event_sync();
     } else if (s->last_set && gd_is_grab_active(s)) {
-        qemu_input_queue_rel(s->dcl.con, INPUT_AXIS_X, x - s->last_x);
-        qemu_input_queue_rel(s->dcl.con, INPUT_AXIS_Y, y - s->last_y);
+        qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, x - s->last_x);
+        qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_Y, y - s->last_y);
         qemu_input_event_sync();
     }
     s->last_x = x;
@@ -670,7 +700,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
     s->last_set = TRUE;
 
     if (!qemu_input_is_absolute() && gd_is_grab_active(s)) {
-        GdkScreen *screen = gtk_widget_get_screen(s->drawing_area);
+        GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area);
         int x = (int)motion->x_root;
         int y = (int)motion->y_root;
 
@@ -712,7 +742,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
 static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
                                 void *opaque)
 {
-    GtkDisplayState *s = opaque;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
     InputButton btn;
 
     /* implicitly grab the input at the first click in the relative mode */
@@ -733,7 +764,8 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
         return TRUE;
     }
 
-    qemu_input_queue_btn(s->dcl.con, btn, button->type == GDK_BUTTON_PRESS);
+    qemu_input_queue_btn(vc->gfx.dcl.con, btn,
+                         button->type == GDK_BUTTON_PRESS);
     qemu_input_event_sync();
     return TRUE;
 }
@@ -741,7 +773,7 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
 static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll,
                                 void *opaque)
 {
-    GtkDisplayState *s = opaque;
+    VirtualConsole *vc = opaque;
     InputButton btn;
 
     if (scroll->direction == GDK_SCROLL_UP) {
@@ -752,16 +784,17 @@ static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll,
         return TRUE;
     }
 
-    qemu_input_queue_btn(s->dcl.con, btn, true);
+    qemu_input_queue_btn(vc->gfx.dcl.con, btn, true);
     qemu_input_event_sync();
-    qemu_input_queue_btn(s->dcl.con, btn, false);
+    qemu_input_queue_btn(vc->gfx.dcl.con, btn, false);
     qemu_input_event_sync();
     return TRUE;
 }
 
 static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
 {
-    GtkDisplayState *s = opaque;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
     int gdk_keycode = key->hardware_keycode;
     int i;
 
@@ -799,7 +832,7 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
         }
     }
 
-    qemu_input_event_send_key_number(s->dcl.con, qemu_keycode,
+    qemu_input_event_send_key_number(vc->gfx.dcl.con, qemu_keycode,
                                      key->type == GDK_KEY_PRESS);
 
     return TRUE;
@@ -847,20 +880,14 @@ static void gd_menu_quit(GtkMenuItem *item, void *opaque)
 static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_by_menu(s);
     gint page;
 
-    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vga_item))) {
+    gtk_release_modifiers(s);
+    if (vc) {
         page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
-                                     s->drawing_area);
+                                     vc->tab_item);
         gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
-    } else {
-        gtk_release_modifiers(s);
-        VirtualConsole *vc = gd_vc_find_by_menu(s);
-        if (vc) {
-            page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
-                                         vc->tab_item);
-            gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
-        }
     }
 }
 
@@ -878,91 +905,100 @@ static void gd_menu_show_tabs(GtkMenuItem *item, void *opaque)
 static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
 
     if (!s->full_screen) {
         gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE);
         gtk_widget_set_size_request(s->menu_bar, 0, 0);
-        gtk_widget_set_size_request(s->drawing_area, -1, -1);
-        gtk_window_fullscreen(GTK_WINDOW(s->window));
-        if (gd_on_vga(s)) {
-            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), TRUE);
+        if (vc->type == GD_VC_GFX) {
+            gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1);
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
+                                           TRUE);
         }
+        gtk_window_fullscreen(GTK_WINDOW(s->window));
         s->full_screen = TRUE;
     } else {
         gtk_window_unfullscreen(GTK_WINDOW(s->window));
         gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s);
         gtk_widget_set_size_request(s->menu_bar, -1, -1);
-        gtk_widget_set_size_request(s->drawing_area,
-                                    surface_width(s->ds),
-                                    surface_height(s->ds));
-        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE);
         s->full_screen = FALSE;
-        s->scale_x = 1.0;
-        s->scale_y = 1.0;
+        if (vc->type == GD_VC_GFX) {
+            vc->gfx.scale_x = 1.0;
+            vc->gfx.scale_y = 1.0;
+            gtk_widget_set_size_request(vc->gfx.drawing_area,
+                                        surface_width(vc->gfx.ds),
+                                        surface_height(vc->gfx.ds));
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
+                                           FALSE);
+        }
     }
 
-    gd_update_cursor(s, FALSE);
+    gd_update_cursor(vc);
 }
 
 static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
 
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item),
                                    FALSE);
 
-    s->scale_x += .25;
-    s->scale_y += .25;
+    vc->gfx.scale_x += .25;
+    vc->gfx.scale_y += .25;
 
-    gd_update_windowsize(s);
+    gd_update_windowsize(vc);
 }
 
 static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
 
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item),
                                    FALSE);
 
-    s->scale_x -= .25;
-    s->scale_y -= .25;
+    vc->gfx.scale_x -= .25;
+    vc->gfx.scale_y -= .25;
 
-    s->scale_x = MAX(s->scale_x, .25);
-    s->scale_y = MAX(s->scale_y, .25);
+    vc->gfx.scale_x = MAX(vc->gfx.scale_x, .25);
+    vc->gfx.scale_y = MAX(vc->gfx.scale_y, .25);
 
-    gd_update_windowsize(s);
+    gd_update_windowsize(vc);
 }
 
 static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
 
-    s->scale_x = 1.0;
-    s->scale_y = 1.0;
+    vc->gfx.scale_x = 1.0;
+    vc->gfx.scale_y = 1.0;
 
-    gd_update_windowsize(s);
+    gd_update_windowsize(vc);
 }
 
 static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
 
     if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) {
         s->free_scale = TRUE;
     } else {
         s->free_scale = FALSE;
-        s->scale_x = 1.0;
-        s->scale_y = 1.0;
-        gd_update_windowsize(s);
+        vc->gfx.scale_x = 1.0;
+        vc->gfx.scale_y = 1.0;
+        gd_update_windowsize(vc);
     }
 
-    gd_update_full_redraw(s);
+    gd_update_full_redraw(vc);
 }
 
-static void gd_grab_keyboard(GtkDisplayState *s)
+static void gd_grab_keyboard(VirtualConsole *vc)
 {
 #if GTK_CHECK_VERSION(3, 0, 0)
-    GdkDisplay *display = gtk_widget_get_display(s->drawing_area);
+    GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
     GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
     GList *devices = gdk_device_manager_list_devices(mgr,
                                                      GDK_DEVICE_TYPE_MASTER);
@@ -971,7 +1007,7 @@ static void gd_grab_keyboard(GtkDisplayState *s)
         GdkDevice *dev = tmp->data;
         if (gdk_device_get_source(dev) == GDK_SOURCE_KEYBOARD) {
             gdk_device_grab(dev,
-                            gtk_widget_get_window(s->drawing_area),
+                            gtk_widget_get_window(vc->gfx.drawing_area),
                             GDK_OWNERSHIP_NONE,
                             FALSE,
                             GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
@@ -982,16 +1018,16 @@ static void gd_grab_keyboard(GtkDisplayState *s)
     }
     g_list_free(devices);
 #else
-    gdk_keyboard_grab(gtk_widget_get_window(s->drawing_area),
+    gdk_keyboard_grab(gtk_widget_get_window(vc->gfx.drawing_area),
                       FALSE,
                       GDK_CURRENT_TIME);
 #endif
 }
 
-static void gd_ungrab_keyboard(GtkDisplayState *s)
+static void gd_ungrab_keyboard(VirtualConsole *vc)
 {
 #if GTK_CHECK_VERSION(3, 0, 0)
-    GdkDisplay *display = gtk_widget_get_display(s->drawing_area);
+    GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
     GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
     GList *devices = gdk_device_manager_list_devices(mgr,
                                                      GDK_DEVICE_TYPE_MASTER);
@@ -1010,9 +1046,9 @@ static void gd_ungrab_keyboard(GtkDisplayState *s)
 #endif
 }
 
-static void gd_grab_pointer(GtkDisplayState *s)
+static void gd_grab_pointer(VirtualConsole *vc)
 {
-    GdkDisplay *display = gtk_widget_get_display(s->drawing_area);
+    GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
 #if GTK_CHECK_VERSION(3, 0, 0)
     GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
     GList *devices = gdk_device_manager_list_devices(mgr,
@@ -1022,7 +1058,7 @@ static void gd_grab_pointer(GtkDisplayState *s)
         GdkDevice *dev = tmp->data;
         if (gdk_device_get_source(dev) == GDK_SOURCE_MOUSE) {
             gdk_device_grab(dev,
-                            gtk_widget_get_window(s->drawing_area),
+                            gtk_widget_get_window(vc->gfx.drawing_area),
                             GDK_OWNERSHIP_NONE,
                             FALSE, /* All events to come to our
                                       window directly */
@@ -1031,16 +1067,16 @@ static void gd_grab_pointer(GtkDisplayState *s)
                             GDK_BUTTON_RELEASE_MASK |
                             GDK_BUTTON_MOTION_MASK |
                             GDK_SCROLL_MASK,
-                            s->null_cursor,
+                            vc->s->null_cursor,
                             GDK_CURRENT_TIME);
         }
         tmp = tmp->next;
     }
     g_list_free(devices);
     gdk_device_get_position(gdk_device_manager_get_client_pointer(mgr),
-                            NULL, &s->grab_x_root, &s->grab_y_root);
+                            NULL, &vc->s->grab_x_root, &vc->s->grab_y_root);
 #else
-    gdk_pointer_grab(gtk_widget_get_window(s->drawing_area),
+    gdk_pointer_grab(gtk_widget_get_window(vc->gfx.drawing_area),
                      FALSE, /* All events to come to our window directly */
                      GDK_POINTER_MOTION_MASK |
                      GDK_BUTTON_PRESS_MASK |
@@ -1048,16 +1084,16 @@ static void gd_grab_pointer(GtkDisplayState *s)
                      GDK_BUTTON_MOTION_MASK |
                      GDK_SCROLL_MASK,
                      NULL, /* Allow cursor to move over entire desktop */
-                     s->null_cursor,
+                     vc->s->null_cursor,
                      GDK_CURRENT_TIME);
     gdk_display_get_pointer(display, NULL,
-                            &s->grab_x_root, &s->grab_y_root, NULL);
+                            &vc->s->grab_x_root, &vc->s->grab_y_root, NULL);
 #endif
 }
 
-static void gd_ungrab_pointer(GtkDisplayState *s)
+static void gd_ungrab_pointer(VirtualConsole *vc)
 {
-    GdkDisplay *display = gtk_widget_get_display(s->drawing_area);
+    GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
 #if GTK_CHECK_VERSION(3, 0, 0)
     GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
     GList *devices = gdk_device_manager_list_devices(mgr,
@@ -1073,46 +1109,52 @@ static void gd_ungrab_pointer(GtkDisplayState *s)
     }
     g_list_free(devices);
     gdk_device_warp(gdk_device_manager_get_client_pointer(mgr),
-                    gtk_widget_get_screen(s->drawing_area),
-                    s->grab_x_root, s->grab_y_root);
+                    gtk_widget_get_screen(vc->gfx.drawing_area),
+                    vc->s->grab_x_root, vc->s->grab_y_root);
 #else
     gdk_pointer_ungrab(GDK_CURRENT_TIME);
     gdk_display_warp_pointer(display,
-                             gtk_widget_get_screen(s->drawing_area),
-                             s->grab_x_root, s->grab_y_root);
+                             gtk_widget_get_screen(vc->gfx.drawing_area),
+                             vc->s->grab_x_root, vc->s->grab_y_root);
 #endif
 }
 
 static void gd_menu_grab_input(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
 
     if (gd_is_grab_active(s)) {
-        gd_grab_keyboard(s);
-        gd_grab_pointer(s);
+        gd_grab_keyboard(vc);
+        gd_grab_pointer(vc);
     } else {
-        gd_ungrab_keyboard(s);
-        gd_ungrab_pointer(s);
+        gd_ungrab_keyboard(vc);
+        gd_ungrab_pointer(vc);
     }
 
     gd_update_caption(s);
-    gd_update_cursor(s, FALSE);
+    gd_update_cursor(vc);
 }
 
 static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
                            gpointer data)
 {
     GtkDisplayState *s = data;
+    VirtualConsole *vc;
     gboolean on_vga;
-    gint page;
 
     if (!gtk_widget_get_realized(s->notebook)) {
         return;
     }
 
-    page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), s->drawing_area);
-    on_vga = arg2 == page;
+    vc = gd_vc_find_by_page(s, arg2);
+    if (!vc) {
+        return;
+    }
+    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item),
+                                   TRUE);
 
+    on_vga = (vc->type == GD_VC_GFX);
     if (!on_vga) {
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                        FALSE);
@@ -1120,49 +1162,42 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                        TRUE);
     }
-
-    if (on_vga) {
-        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->vga_item), TRUE);
-    } else {
-        VirtualConsole *vc;
-        vc = gd_vc_find_by_page(s, arg2);
-        if (vc) {
-            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item),
-                                           TRUE);
-        }
-    }
-
     gtk_widget_set_sensitive(s->grab_item, on_vga);
 
-    gd_update_cursor(s, TRUE);
+    gd_update_cursor(vc);
 }
 
-static gboolean gd_enter_event(GtkWidget *widget, GdkEventCrossing *crossing, gpointer data)
+static gboolean gd_enter_event(GtkWidget *widget, GdkEventCrossing *crossing,
+                               gpointer opaque)
 {
-    GtkDisplayState *s = data;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
 
     if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
-        gd_grab_keyboard(s);
+        gd_grab_keyboard(vc);
     }
 
     return TRUE;
 }
 
-static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing, gpointer data)
+static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing,
+                               gpointer opaque)
 {
-    GtkDisplayState *s = data;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
 
     if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
-        gd_ungrab_keyboard(s);
+        gd_ungrab_keyboard(vc);
     }
 
     return TRUE;
 }
 
 static gboolean gd_focus_out_event(GtkWidget *widget,
-                                   GdkEventCrossing *crossing, gpointer data)
+                                   GdkEventCrossing *crossing, gpointer opaque)
 {
-    GtkDisplayState *s = data;
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
 
     gtk_release_modifiers(s);
 
@@ -1218,8 +1253,8 @@ static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size,
     return TRUE;
 }
 
-static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSList *group,
-                          GtkWidget *view_menu)
+static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc, int index,
+                              GSList *group, GtkWidget *view_menu)
 {
     const char *label;
     char buffer[32];
@@ -1231,6 +1266,7 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     snprintf(buffer, sizeof(buffer), "vc%d", index);
     snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
 
+    vc->s = s;
     vc->vte.chr = vcs[index];
 
     if (vc->vte.chr->label) {
@@ -1275,6 +1311,7 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     g_signal_connect(vadjustment, "changed",
                      G_CALLBACK(gd_vc_adjustment_changed), vc);
 
+    vc->type = GD_VC_VTE;
     vc->tab_item = box;
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item,
                              gtk_label_new(label));
@@ -1291,15 +1328,15 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     return group;
 }
 
-static void gd_vcs_init(GtkDisplayState *s, GSList *group,
+static void gd_vcs_init(GtkDisplayState *s, int offset, GSList *group,
                         GtkWidget *view_menu)
 {
     int i;
 
     for (i = 0; i < nb_vcs; i++) {
-        VirtualConsole *vc = &s->vc[i];
+        VirtualConsole *vc = &s->vc[offset+i];
 
-        group = gd_vc_init(s, vc, i, group, view_menu);
+        group = gd_vc_vte_init(s, vc, i, group, view_menu);
         s->nb_vcs++;
     }
 }
@@ -1307,6 +1344,36 @@ static void gd_vcs_init(GtkDisplayState *s, GSList *group,
 
 /** Window Creation **/
 
+static void gd_connect_vc_gfx_signals(VirtualConsole *vc)
+{
+#if GTK_CHECK_VERSION(3, 0, 0)
+    g_signal_connect(vc->gfx.drawing_area, "draw",
+                     G_CALLBACK(gd_draw_event), vc);
+#else
+    g_signal_connect(vc->gfx.drawing_area, "expose-event",
+                     G_CALLBACK(gd_expose_event), vc);
+#endif
+    g_signal_connect(vc->gfx.drawing_area, "event",
+                     G_CALLBACK(gd_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "button-press-event",
+                     G_CALLBACK(gd_button_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "button-release-event",
+                     G_CALLBACK(gd_button_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "scroll-event",
+                     G_CALLBACK(gd_scroll_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "key-press-event",
+                     G_CALLBACK(gd_key_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "key-release-event",
+                     G_CALLBACK(gd_key_event), vc);
+
+    g_signal_connect(vc->gfx.drawing_area, "enter-notify-event",
+                     G_CALLBACK(gd_enter_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "leave-notify-event",
+                     G_CALLBACK(gd_leave_event), vc);
+    g_signal_connect(vc->gfx.drawing_area, "focus-out-event",
+                     G_CALLBACK(gd_focus_out_event), vc);
+}
+
 static void gd_connect_signals(GtkDisplayState *s)
 {
     g_signal_connect(s->show_tabs_item, "activate",
@@ -1315,26 +1382,6 @@ static void gd_connect_signals(GtkDisplayState *s)
     g_signal_connect(s->window, "delete-event",
                      G_CALLBACK(gd_window_close), s);
 
-#if GTK_CHECK_VERSION(3, 0, 0)
-    g_signal_connect(s->drawing_area, "draw",
-                     G_CALLBACK(gd_draw_event), s);
-#else
-    g_signal_connect(s->drawing_area, "expose-event",
-                     G_CALLBACK(gd_expose_event), s);
-#endif
-    g_signal_connect(s->drawing_area, "event",
-                     G_CALLBACK(gd_event), s);
-    g_signal_connect(s->drawing_area, "button-press-event",
-                     G_CALLBACK(gd_button_event), s);
-    g_signal_connect(s->drawing_area, "button-release-event",
-                     G_CALLBACK(gd_button_event), s);
-    g_signal_connect(s->drawing_area, "scroll-event",
-                     G_CALLBACK(gd_scroll_event), s);
-    g_signal_connect(s->drawing_area, "key-press-event",
-                     G_CALLBACK(gd_key_event), s);
-    g_signal_connect(s->drawing_area, "key-release-event",
-                     G_CALLBACK(gd_key_event), s);
-
     g_signal_connect(s->pause_item, "activate",
                      G_CALLBACK(gd_menu_pause), s);
     g_signal_connect(s->reset_item, "activate",
@@ -1353,18 +1400,10 @@ static void gd_connect_signals(GtkDisplayState *s)
                      G_CALLBACK(gd_menu_zoom_fixed), s);
     g_signal_connect(s->zoom_fit_item, "activate",
                      G_CALLBACK(gd_menu_zoom_fit), 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);
-    g_signal_connect(s->drawing_area, "enter-notify-event",
-                     G_CALLBACK(gd_enter_event), s);
-    g_signal_connect(s->drawing_area, "leave-notify-event",
-                     G_CALLBACK(gd_leave_event), s);
-    g_signal_connect(s->drawing_area, "focus-out-event",
-                     G_CALLBACK(gd_focus_out_event), s);
 }
 
 static GtkWidget *gd_create_menu_machine(GtkDisplayState *s, GtkAccelGroup *accel_group)
@@ -1400,6 +1439,59 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s, GtkAccelGroup *acce
     return machine_menu;
 }
 
+static const DisplayChangeListenerOps dcl_ops = {
+    .dpy_name          = "gtk",
+    .dpy_gfx_update    = gd_update,
+    .dpy_gfx_switch    = gd_switch,
+    .dpy_refresh       = gd_refresh,
+    .dpy_mouse_set     = gd_mouse_set,
+    .dpy_cursor_define = gd_cursor_define,
+};
+
+static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
+                              QemuConsole *con, int index,
+                              GSList *group, GtkWidget *view_menu)
+{
+    vc->s = s;
+    vc->gfx.scale_x = 1.0;
+    vc->gfx.scale_y = 1.0;
+
+    vc->gfx.drawing_area = gtk_drawing_area_new();
+    gtk_widget_add_events(vc->gfx.drawing_area,
+                          GDK_POINTER_MOTION_MASK |
+                          GDK_BUTTON_PRESS_MASK |
+                          GDK_BUTTON_RELEASE_MASK |
+                          GDK_BUTTON_MOTION_MASK |
+                          GDK_ENTER_NOTIFY_MASK |
+                          GDK_LEAVE_NOTIFY_MASK |
+                          GDK_SCROLL_MASK |
+                          GDK_KEY_PRESS_MASK);
+    gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE);
+    gtk_widget_set_can_focus(vc->gfx.drawing_area, TRUE);
+
+    vc->type = GD_VC_GFX;
+    vc->tab_item = vc->gfx.drawing_area;
+    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
+                             vc->tab_item, gtk_label_new("VGA"));
+    gd_connect_vc_gfx_signals(vc);
+
+    vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, "_VGA");
+    group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item));
+    gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item),
+                                 "<QEMU>/View/VGA");
+    gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, HOTKEY_MODIFIERS);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item);
+
+    g_signal_connect(vc->menu_item, "activate",
+                     G_CALLBACK(gd_menu_switch_vc), s);
+
+    vc->gfx.dcl.ops = &dcl_ops;
+    vc->gfx.dcl.con = con;
+    register_displaychangelistener(&vc->gfx.dcl);
+
+    return group;
+}
+
 static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_group)
 {
     GSList *group = NULL;
@@ -1459,15 +1551,13 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
     separator = gtk_separator_menu_item_new();
     gtk_menu_shell_append(GTK_MENU_SHELL(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),
-                                 "<QEMU>/View/VGA");
-    gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, HOTKEY_MODIFIERS);
-    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->vga_item);
+    /* gfx */
+    group = gd_vc_gfx_init(s, &s->vc[0], qemu_console_lookup_by_index(0), 0,
+                           group, view_menu);
 
 #if defined(CONFIG_VTE)
-    gd_vcs_init(s, group, view_menu);
+    /* vte */
+    gd_vcs_init(s, 1, group, view_menu);
 #endif
 
     separator = gtk_separator_menu_item_new();
@@ -1501,15 +1591,6 @@ static void gd_create_menus(GtkDisplayState *s)
     s->accel_group = accel_group;
 }
 
-static const DisplayChangeListenerOps dcl_ops = {
-    .dpy_name          = "gtk",
-    .dpy_gfx_update    = gd_update,
-    .dpy_gfx_switch    = gd_switch,
-    .dpy_refresh       = gd_refresh,
-    .dpy_mouse_set     = gd_mouse_set,
-    .dpy_cursor_define = gd_cursor_define,
-};
-
 void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
@@ -1517,9 +1598,6 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
 
     gtk_init(NULL, NULL);
 
-    s->dcl.ops = &dcl_ops;
-    s->dcl.con = qemu_console_lookup_by_index(0);
-
     s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 #if GTK_CHECK_VERSION(3, 2, 0)
     s->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
@@ -1527,11 +1605,8 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
     s->vbox = gtk_vbox_new(FALSE, 0);
 #endif
     s->notebook = gtk_notebook_new();
-    s->drawing_area = gtk_drawing_area_new();
     s->menu_bar = gtk_menu_bar_new();
 
-    s->scale_x = 1.0;
-    s->scale_y = 1.0;
     s->free_scale = FALSE;
 
     setlocale(LC_ALL, "");
@@ -1544,8 +1619,6 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
     qemu_add_mouse_mode_change_notifier(&s->mouse_mode_notifier);
     qemu_add_vm_change_state_handler(gd_change_runstate, s);
 
-    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
-
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu_logo_no_text.svg");
     if (filename) {
         GError *error = NULL;
@@ -1562,18 +1635,6 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
 
     gd_connect_signals(s);
 
-    gtk_widget_add_events(s->drawing_area,
-                          GDK_POINTER_MOTION_MASK |
-                          GDK_BUTTON_PRESS_MASK |
-                          GDK_BUTTON_RELEASE_MASK |
-                          GDK_BUTTON_MOTION_MASK |
-                          GDK_ENTER_NOTIFY_MASK |
-                          GDK_LEAVE_NOTIFY_MASK |
-                          GDK_SCROLL_MASK |
-                          GDK_KEY_PRESS_MASK);
-    gtk_widget_set_double_buffered(s->drawing_area, FALSE);
-    gtk_widget_set_can_focus(s->drawing_area, TRUE);
-
     gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE);
     gtk_notebook_set_show_border(GTK_NOTEBOOK(s->notebook), FALSE);
 
@@ -1593,8 +1654,6 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
         gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_on_hover_item));
     }
 
-    register_displaychangelistener(&s->dcl);
-
     global_state = s;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 08/24] gtk: support multiple gfx displays
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 07/24] gtk: move vga state into VirtualGfxConsole Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 09/24] gtk: use device type as label Gerd Hoffmann
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Each display gets its own tab.  Tab switching continues to work like it
did, just the hotkeys of the vte consoles changes in case a secondary
display is present as it will get ctrl-alt-2 assigned and the vtes are
shifted by one.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 80 ++++++++++++++++++++++++++++++++++------------------------------
 1 file changed, 43 insertions(+), 37 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index bc42f68..0756432 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1206,6 +1206,26 @@ static gboolean gd_focus_out_event(GtkWidget *widget,
 
 /** Virtual Console Callbacks **/
 
+static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc,
+                               const char *label, int idx,
+                               GSList *group, GtkWidget *view_menu)
+{
+    char path[32];
+
+    snprintf(path, sizeof(path), "<QEMU>/View/VC%d", idx);
+
+    vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, label);
+    group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item));
+    gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item), path);
+    gtk_accel_map_add_entry(path, GDK_KEY_1 + idx, HOTKEY_MODIFIERS);
+
+    g_signal_connect(vc->menu_item, "activate",
+                     G_CALLBACK(gd_menu_switch_vc), s);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item);
+
+    return group;
+}
+
 #if defined(CONFIG_VTE)
 static void gd_vc_adjustment_changed(GtkAdjustment *adjustment, void *opaque)
 {
@@ -1253,32 +1273,22 @@ static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size,
     return TRUE;
 }
 
-static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc, int index,
+static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
+                              CharDriverState *chr, int idx,
                               GSList *group, GtkWidget *view_menu)
 {
     const char *label;
     char buffer[32];
-    char path[32];
     GtkWidget *box;
     GtkWidget *scrollbar;
     GtkAdjustment *vadjustment;
 
-    snprintf(buffer, sizeof(buffer), "vc%d", index);
-    snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
-
     vc->s = s;
-    vc->vte.chr = vcs[index];
-
-    if (vc->vte.chr->label) {
-        label = vc->vte.chr->label;
-    } else {
-        label = buffer;
-    }
+    vc->vte.chr = chr;
 
-    vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, label);
-    group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item));
-    gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item), path);
-    gtk_accel_map_add_entry(path, GDK_KEY_2 + index, HOTKEY_MODIFIERS);
+    snprintf(buffer, sizeof(buffer), "vc%d", idx);
+    label = vc->vte.chr->label ? vc->vte.chr->label : buffer;
+    group = gd_vc_menu_init(s, vc, vc->vte.chr->label, idx, group, view_menu);
 
     vc->vte.terminal = vte_terminal_new();
     g_signal_connect(vc->vte.terminal, "commit", G_CALLBACK(gd_vc_in), vc);
@@ -1315,10 +1325,6 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc, int index,
     vc->tab_item = box;
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item,
                              gtk_label_new(label));
-    g_signal_connect(vc->menu_item, "activate",
-                     G_CALLBACK(gd_menu_switch_vc), s);
-
-    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item);
 
     qemu_chr_be_generic_open(vc->vte.chr);
     if (vc->vte.chr->init) {
@@ -1328,15 +1334,14 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc, int index,
     return group;
 }
 
-static void gd_vcs_init(GtkDisplayState *s, int offset, GSList *group,
+static void gd_vcs_init(GtkDisplayState *s, GSList *group,
                         GtkWidget *view_menu)
 {
     int i;
 
     for (i = 0; i < nb_vcs; i++) {
-        VirtualConsole *vc = &s->vc[offset+i];
-
-        group = gd_vc_vte_init(s, vc, i, group, view_menu);
+        VirtualConsole *vc = &s->vc[s->nb_vcs];
+        group = gd_vc_vte_init(s, vc, vcs[i], s->nb_vcs, group, view_menu);
         s->nb_vcs++;
     }
 }
@@ -1449,7 +1454,7 @@ static const DisplayChangeListenerOps dcl_ops = {
 };
 
 static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
-                              QemuConsole *con, int index,
+                              QemuConsole *con, int idx,
                               GSList *group, GtkWidget *view_menu)
 {
     vc->s = s;
@@ -1475,15 +1480,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
                              vc->tab_item, gtk_label_new("VGA"));
     gd_connect_vc_gfx_signals(vc);
 
-    vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, "_VGA");
-    group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item));
-    gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item),
-                                 "<QEMU>/View/VGA");
-    gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, HOTKEY_MODIFIERS);
-    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item);
-
-    g_signal_connect(vc->menu_item, "activate",
-                     G_CALLBACK(gd_menu_switch_vc), s);
+    group = gd_vc_menu_init(s, vc, "VGA", idx, group, view_menu);
 
     vc->gfx.dcl.ops = &dcl_ops;
     vc->gfx.dcl.con = con;
@@ -1497,6 +1494,8 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
     GSList *group = NULL;
     GtkWidget *view_menu;
     GtkWidget *separator;
+    QemuConsole *con;
+    int vc;
 
     view_menu = gtk_menu_new();
     gtk_menu_set_accel_group(GTK_MENU(view_menu), accel_group);
@@ -1552,12 +1551,19 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
     gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
 
     /* gfx */
-    group = gd_vc_gfx_init(s, &s->vc[0], qemu_console_lookup_by_index(0), 0,
-                           group, view_menu);
+    for (vc = 0;; vc++) {
+        con = qemu_console_lookup_by_index(vc);
+        if (!con || !qemu_console_is_graphic(con)) {
+            break;
+        }
+        group = gd_vc_gfx_init(s, &s->vc[vc], con,
+                               vc, group, view_menu);
+        s->nb_vcs++;
+    }
 
 #if defined(CONFIG_VTE)
     /* vte */
-    gd_vcs_init(s, 1, group, view_menu);
+    gd_vcs_init(s, group, view_menu);
 #endif
 
     separator = gtk_separator_menu_item_new();
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 09/24] gtk: use device type as label
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 08/24] gtk: support multiple gfx displays Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 10/24] gtk: simplify resize Gerd Hoffmann
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

IMO useful than showing VGA for any graphic device
even in case it is something completely different.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 0756432..a8393dd 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -67,6 +67,7 @@
 #include "x_keymap.h"
 #include "keymaps.h"
 #include "sysemu/char.h"
+#include "qom/object.h"
 
 #define MAX_VCS 10
 
@@ -1457,6 +1458,15 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
                               QemuConsole *con, int idx,
                               GSList *group, GtkWidget *view_menu)
 {
+    const char *label = "VGA";
+    Error *local_err = NULL;
+    Object *obj;
+
+    obj = object_property_get_link(OBJECT(con), "device", &local_err);
+    if (obj) {
+        label = object_get_typename(obj);
+    }
+
     vc->s = s;
     vc->gfx.scale_x = 1.0;
     vc->gfx.scale_y = 1.0;
@@ -1477,10 +1487,10 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
     vc->type = GD_VC_GFX;
     vc->tab_item = vc->gfx.drawing_area;
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
-                             vc->tab_item, gtk_label_new("VGA"));
+                             vc->tab_item, gtk_label_new(label));
     gd_connect_vc_gfx_signals(vc);
 
-    group = gd_vc_menu_init(s, vc, "VGA", idx, group, view_menu);
+    group = gd_vc_menu_init(s, vc, label, idx, group, view_menu);
 
     vc->gfx.dcl.ops = &dcl_ops;
     vc->gfx.dcl.con = con;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 10/24] gtk: simplify resize
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 09/24] gtk: use device type as label Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 11/24] gtk: allow moving tabs to windows and back Gerd Hoffmann
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Simply ask for a small window size.  When the widgets don't fit in gtk
will automatically make the window large enougth to make things fit, no
need to try (and fail) duplicate that logic in qemu.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 40 ++++++++++++++--------------------------
 1 file changed, 14 insertions(+), 26 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index a8393dd..6790cf8 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -296,35 +296,23 @@ static void gd_update_caption(GtkDisplayState *s)
 static void gd_update_windowsize(VirtualConsole *vc)
 {
     GtkDisplayState *s = vc->s;
+    double sx, sy;
 
-    if (!s->full_screen) {
-        GtkRequisition req;
-        double sx, sy;
-
-        if (s->free_scale) {
-            sx = vc->gfx.scale_x;
-            sy = vc->gfx.scale_y;
-
-            vc->gfx.scale_y = 1.0;
-            vc->gfx.scale_x = 1.0;
-        } else {
-            sx = 1.0;
-            sy = 1.0;
-        }
-
-        gtk_widget_set_size_request
-            (vc->gfx.drawing_area,
-             surface_width(vc->gfx.ds) * vc->gfx.scale_x,
-             surface_height(vc->gfx.ds) * vc->gfx.scale_y);
-#if GTK_CHECK_VERSION(3, 0, 0)
-        gtk_widget_get_preferred_size(s->vbox, NULL, &req);
-#else
-        gtk_widget_size_request(s->vbox, &req);
-#endif
+    if (vc->type != GD_VC_GFX || s->full_screen) {
+        return;
+    }
 
-        gtk_window_resize(GTK_WINDOW(s->window),
-                          req.width * sx, req.height * sy);
+    if (s->free_scale) {
+        sx = 1.0;
+        sy = 1.0;
+    } else {
+        sx = vc->gfx.scale_x;
+        sy = vc->gfx.scale_y;
     }
+    gtk_widget_set_size_request(vc->gfx.drawing_area,
+                                surface_width(vc->gfx.ds) * sx,
+                                surface_height(vc->gfx.ds) * sy);
+    gtk_window_resize(GTK_WINDOW(s->window), 320, 240);
 }
 
 static void gd_update_full_redraw(VirtualConsole *vc)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 11/24] gtk: allow moving tabs to windows and back.
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 10/24] gtk: simplify resize Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 12/24] gtk: add tab to trace events Gerd Hoffmann
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

"View->Detach tab" will move to tab to a new window.
Simply closing the window will move it back into a notebook tab.
The label will be permamently stored in VirtualConsole->label,
so it can easily be reused to (re-)label tabs and windows.

Works for vte tabs only for now. pointer/kbd grab code needs
adaptions before we can enable it for gfx tabs too.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 63 insertions(+), 11 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 6790cf8..07883a1 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -134,6 +134,8 @@ typedef enum VirtualConsoleType {
 
 typedef struct VirtualConsole {
     GtkDisplayState *s;
+    char *label;
+    GtkWidget *window;
     GtkWidget *menu_item;
     GtkWidget *tab_item;
     VirtualConsoleType type;
@@ -173,6 +175,7 @@ struct GtkDisplayState {
     VirtualConsole vc[MAX_VCS];
 
     GtkWidget *show_tabs_item;
+    GtkWidget *untabify_item;
 
     GtkWidget *vbox;
     GtkWidget *notebook;
@@ -891,6 +894,50 @@ static void gd_menu_show_tabs(GtkMenuItem *item, void *opaque)
     }
 }
 
+static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event,
+                                    void *opaque)
+{
+    VirtualConsole *vc = opaque;
+    GtkDisplayState *s = vc->s;
+
+    gtk_widget_set_sensitive(vc->menu_item, true);
+    gtk_widget_reparent(vc->tab_item, s->notebook);
+    gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(s->notebook),
+                                    vc->tab_item, vc->label);
+    gtk_widget_destroy(vc->window);
+    vc->window = NULL;
+    return TRUE;
+}
+
+static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
+{
+    GtkDisplayState *s = opaque;
+    VirtualConsole *vc = gd_vc_find_current(s);
+    char *title;
+
+    if (vc->type == GD_VC_GFX) {
+        /* temporary: needs more work to get grabs etc correct */
+        return;
+    }
+    if (!vc->window) {
+        gtk_widget_set_sensitive(vc->menu_item, false);
+        vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+        gtk_widget_reparent(vc->tab_item, vc->window);
+
+        if (qemu_name) {
+            title = g_strdup_printf("QEMU (%s): %s", qemu_name, vc->label);
+        } else {
+            title = g_strdup_printf("QEMU: %s", vc->label);
+        }
+        gtk_window_set_title(GTK_WINDOW(vc->window), title);
+        g_free(title);
+
+        g_signal_connect(vc->window, "delete-event",
+                         G_CALLBACK(gd_tab_window_close), vc);
+        gtk_widget_show_all(vc->window);
+    }
+}
+
 static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
@@ -1196,14 +1243,13 @@ static gboolean gd_focus_out_event(GtkWidget *widget,
 /** Virtual Console Callbacks **/
 
 static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc,
-                               const char *label, int idx,
-                               GSList *group, GtkWidget *view_menu)
+                               int idx, GSList *group, GtkWidget *view_menu)
 {
     char path[32];
 
     snprintf(path, sizeof(path), "<QEMU>/View/VC%d", idx);
 
-    vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, label);
+    vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, vc->label);
     group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item));
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item), path);
     gtk_accel_map_add_entry(path, GDK_KEY_1 + idx, HOTKEY_MODIFIERS);
@@ -1266,7 +1312,6 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
                               CharDriverState *chr, int idx,
                               GSList *group, GtkWidget *view_menu)
 {
-    const char *label;
     char buffer[32];
     GtkWidget *box;
     GtkWidget *scrollbar;
@@ -1276,8 +1321,9 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
     vc->vte.chr = chr;
 
     snprintf(buffer, sizeof(buffer), "vc%d", idx);
-    label = vc->vte.chr->label ? vc->vte.chr->label : buffer;
-    group = gd_vc_menu_init(s, vc, vc->vte.chr->label, idx, group, view_menu);
+    vc->label = g_strdup_printf("%s", vc->vte.chr->label
+                                ? vc->vte.chr->label : buffer);
+    group = gd_vc_menu_init(s, vc, idx, group, view_menu);
 
     vc->vte.terminal = vte_terminal_new();
     g_signal_connect(vc->vte.terminal, "commit", G_CALLBACK(gd_vc_in), vc);
@@ -1313,7 +1359,7 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
     vc->type = GD_VC_VTE;
     vc->tab_item = box;
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item,
-                             gtk_label_new(label));
+                             gtk_label_new(vc->label));
 
     qemu_chr_be_generic_open(vc->vte.chr);
     if (vc->vte.chr->init) {
@@ -1372,6 +1418,8 @@ static void gd_connect_signals(GtkDisplayState *s)
 {
     g_signal_connect(s->show_tabs_item, "activate",
                      G_CALLBACK(gd_menu_show_tabs), s);
+    g_signal_connect(s->untabify_item, "activate",
+                     G_CALLBACK(gd_menu_untabify), s);
 
     g_signal_connect(s->window, "delete-event",
                      G_CALLBACK(gd_window_close), s);
@@ -1446,13 +1494,14 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
                               QemuConsole *con, int idx,
                               GSList *group, GtkWidget *view_menu)
 {
-    const char *label = "VGA";
     Error *local_err = NULL;
     Object *obj;
 
     obj = object_property_get_link(OBJECT(con), "device", &local_err);
     if (obj) {
-        label = object_get_typename(obj);
+        vc->label = g_strdup_printf("%s", object_get_typename(obj));
+    } else {
+        vc->label = g_strdup_printf("VGA");
     }
 
     vc->s = s;
@@ -1475,10 +1524,10 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
     vc->type = GD_VC_GFX;
     vc->tab_item = vc->gfx.drawing_area;
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
-                             vc->tab_item, gtk_label_new(label));
+                             vc->tab_item, gtk_label_new(vc->label));
     gd_connect_vc_gfx_signals(vc);
 
-    group = gd_vc_menu_init(s, vc, label, idx, group, view_menu);
+    group = gd_vc_menu_init(s, vc, idx, group, view_menu);
 
     vc->gfx.dcl.ops = &dcl_ops;
     vc->gfx.dcl.con = con;
@@ -1570,6 +1619,9 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
     s->show_tabs_item = gtk_check_menu_item_new_with_mnemonic(_("Show _Tabs"));
     gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->show_tabs_item);
 
+    s->untabify_item = gtk_menu_item_new_with_mnemonic(_("Detach Tab"));
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->untabify_item);
+
     return view_menu;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 12/24] gtk: add tab to trace events
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 11/24] gtk: allow moving tabs to windows and back Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 13/24] gtk: add gd_grab trace event Gerd Hoffmann
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

So you can see which of multiple displays (if present) was resized ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 trace-events | 6 +++---
 ui/gtk.c     | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/trace-events b/trace-events
index b6d289d..3a41abf 100644
--- a/trace-events
+++ b/trace-events
@@ -1045,9 +1045,9 @@ displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
 ppm_save(const char *filename, void *display_surface) "%s surface=%p"
 
 # ui/gtk.c
-gd_switch(int width, int height) "width=%d, height=%d"
-gd_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d"
-gd_key_event(int gdk_keycode, int qemu_keycode, const char *action) "translated GDK keycode %d to QEMU keycode %d (%s)"
+gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d"
+gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d, h=%d"
+gd_key_event(const char *tab, int gdk_keycode, int qemu_keycode, const char *action) "tab=%s, translated GDK keycode %d to QEMU keycode %d (%s)"
 
 # ui/input.c
 input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%x, down %d"
diff --git a/ui/gtk.c b/ui/gtk.c
index 07883a1..3ee9465 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -355,7 +355,7 @@ static void gd_update(DisplayChangeListener *dcl,
     int fbw, fbh;
     int ww, wh;
 
-    trace_gd_update(x, y, w, h);
+    trace_gd_update(vc->label, x, y, w, h);
 
     if (vc->gfx.convert) {
         pixman_image_composite(PIXMAN_OP_SRC, vc->gfx.ds->image,
@@ -461,7 +461,7 @@ static void gd_switch(DisplayChangeListener *dcl,
     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
     bool resized = true;
 
-    trace_gd_switch(surface_width(surface), surface_height(surface));
+    trace_gd_switch(vc->label, surface_width(surface), surface_height(surface));
 
     if (vc->gfx.surface) {
         cairo_surface_destroy(vc->gfx.surface);
@@ -815,7 +815,7 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
     }
 #endif
 
-    trace_gd_key_event(gdk_keycode, qemu_keycode,
+    trace_gd_key_event(vc->label, gdk_keycode, qemu_keycode,
                        (key->type == GDK_KEY_PRESS) ? "down" : "up");
 
     for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 13/24] gtk: add gd_grab trace event
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 12/24] gtk: add tab to trace events Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 14/24] gtk: keep track of grab owner Gerd Hoffmann
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Input grab code is tricky, add some debug & trouble shooting aid.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 trace-events | 1 +
 ui/gtk.c     | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/trace-events b/trace-events
index 3a41abf..aaaae42 100644
--- a/trace-events
+++ b/trace-events
@@ -1048,6 +1048,7 @@ ppm_save(const char *filename, void *display_surface) "%s surface=%p"
 gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d"
 gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d, h=%d"
 gd_key_event(const char *tab, int gdk_keycode, int qemu_keycode, const char *action) "tab=%s, translated GDK keycode %d to QEMU keycode %d (%s)"
+gd_grab(const char *tab, const char *device, bool on) "tab=%s, %s %d"
 
 # ui/input.c
 input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%x, down %d"
diff --git a/ui/gtk.c b/ui/gtk.c
index 3ee9465..0e35abf 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1058,6 +1058,7 @@ static void gd_grab_keyboard(VirtualConsole *vc)
                       FALSE,
                       GDK_CURRENT_TIME);
 #endif
+    trace_gd_grab(vc->label, "kbd", true);
 }
 
 static void gd_ungrab_keyboard(VirtualConsole *vc)
@@ -1080,6 +1081,7 @@ static void gd_ungrab_keyboard(VirtualConsole *vc)
 #else
     gdk_keyboard_ungrab(GDK_CURRENT_TIME);
 #endif
+    trace_gd_grab(vc->label, "kbd", false);
 }
 
 static void gd_grab_pointer(VirtualConsole *vc)
@@ -1125,6 +1127,7 @@ static void gd_grab_pointer(VirtualConsole *vc)
     gdk_display_get_pointer(display, NULL,
                             &vc->s->grab_x_root, &vc->s->grab_y_root, NULL);
 #endif
+    trace_gd_grab(vc->label, "ptr", true);
 }
 
 static void gd_ungrab_pointer(VirtualConsole *vc)
@@ -1153,6 +1156,7 @@ static void gd_ungrab_pointer(VirtualConsole *vc)
                              gtk_widget_get_screen(vc->gfx.drawing_area),
                              vc->s->grab_x_root, vc->s->grab_y_root);
 #endif
+    trace_gd_grab(vc->label, "ptr", false);
 }
 
 static void gd_menu_grab_input(GtkMenuItem *item, void *opaque)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 14/24] gtk: keep track of grab owner
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 13/24] gtk: add gd_grab trace event Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 15/24] gtk: skip keyboard grab when hover autograb is active Gerd Hoffmann
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Simplifies grab state tracking and makes ungrab more reliable.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 0e35abf..d87bd1b 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -185,6 +185,8 @@ struct GtkDisplayState {
     int last_y;
     int grab_x_root;
     int grab_y_root;
+    VirtualConsole *kbd_owner;
+    VirtualConsole *ptr_owner;
 
     gboolean full_screen;
 
@@ -1058,11 +1060,19 @@ static void gd_grab_keyboard(VirtualConsole *vc)
                       FALSE,
                       GDK_CURRENT_TIME);
 #endif
+    vc->s->kbd_owner = vc;
     trace_gd_grab(vc->label, "kbd", true);
 }
 
-static void gd_ungrab_keyboard(VirtualConsole *vc)
+static void gd_ungrab_keyboard(GtkDisplayState *s)
 {
+    VirtualConsole *vc = s->kbd_owner;
+
+    if (vc == NULL) {
+        return;
+    }
+    s->kbd_owner = NULL;
+
 #if GTK_CHECK_VERSION(3, 0, 0)
     GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
     GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
@@ -1127,11 +1137,19 @@ static void gd_grab_pointer(VirtualConsole *vc)
     gdk_display_get_pointer(display, NULL,
                             &vc->s->grab_x_root, &vc->s->grab_y_root, NULL);
 #endif
+    vc->s->ptr_owner = vc;
     trace_gd_grab(vc->label, "ptr", true);
 }
 
-static void gd_ungrab_pointer(VirtualConsole *vc)
+static void gd_ungrab_pointer(GtkDisplayState *s)
 {
+    VirtualConsole *vc = s->ptr_owner;
+
+    if (vc == NULL) {
+        return;
+    }
+    s->ptr_owner = NULL;
+
     GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
 #if GTK_CHECK_VERSION(3, 0, 0)
     GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
@@ -1168,8 +1186,8 @@ static void gd_menu_grab_input(GtkMenuItem *item, void *opaque)
         gd_grab_keyboard(vc);
         gd_grab_pointer(vc);
     } else {
-        gd_ungrab_keyboard(vc);
-        gd_ungrab_pointer(vc);
+        gd_ungrab_keyboard(s);
+        gd_ungrab_pointer(s);
     }
 
     gd_update_caption(s);
@@ -1227,7 +1245,7 @@ static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing,
     GtkDisplayState *s = vc->s;
 
     if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
-        gd_ungrab_keyboard(vc);
+        gd_ungrab_keyboard(s);
     }
 
     return TRUE;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 15/24] gtk: skip keyboard grab when hover autograb is active
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 14/24] gtk: keep track of grab owner Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 16/24] gtk: update gd_update_caption Gerd Hoffmann
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

It's pointless.  With grab on hover enabled the keyboard grab
is already active when you press Ctrl-Alt-G ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index d87bd1b..f804813 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1183,7 +1183,9 @@ static void gd_menu_grab_input(GtkMenuItem *item, void *opaque)
     VirtualConsole *vc = gd_vc_find_current(s);
 
     if (gd_is_grab_active(s)) {
-        gd_grab_keyboard(vc);
+        if (!gd_grab_on_hover(s)) {
+            gd_grab_keyboard(vc);
+        }
         gd_grab_pointer(vc);
     } else {
         gd_ungrab_keyboard(s);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 16/24] gtk: update gd_update_caption
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (14 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 15/24] gtk: skip keyboard grab when hover autograb is active Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 17/24] gtk: fix grab checks Gerd Hoffmann
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Adapt to recent changes, handle multiple windows.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 45 ++++++++++++++++++++++++++++-----------------
 1 file changed, 28 insertions(+), 17 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index f804813..7d6a20d 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -271,11 +271,20 @@ static void gd_update_cursor(VirtualConsole *vc)
 static void gd_update_caption(GtkDisplayState *s)
 {
     const char *status = "";
+    gchar *prefix;
     gchar *title;
     const char *grab = "";
     bool is_paused = !runstate_is_running();
+    int i;
 
-    if (gd_is_grab_active(s)) {
+    if (qemu_name) {
+        prefix = g_strdup_printf("QEMU (%s)", qemu_name);
+    } else {
+        prefix = g_strdup_printf("QEMU");
+    }
+
+    if (s->ptr_owner != NULL &&
+        s->ptr_owner->window == NULL) {
         grab = _(" - Press Ctrl+Alt+G to release grab");
     }
 
@@ -287,15 +296,24 @@ static void gd_update_caption(GtkDisplayState *s)
                                    is_paused);
     s->external_pause_update = false;
 
-    if (qemu_name) {
-        title = g_strdup_printf("QEMU (%s)%s%s", qemu_name, status, grab);
-    } else {
-        title = g_strdup_printf("QEMU%s%s", status, grab);
-    }
-
+    title = g_strdup_printf("%s%s%s", prefix, status, grab);
     gtk_window_set_title(GTK_WINDOW(s->window), title);
-
     g_free(title);
+
+    for (i = 0; i < s->nb_vcs; i++) {
+        VirtualConsole *vc = &s->vc[i];
+
+        if (!vc->window) {
+            continue;
+        }
+        title = g_strdup_printf("%s: %s%s%s", prefix, vc->label,
+                                vc == s->kbd_owner ? " +kbd" : "",
+                                vc == s->ptr_owner ? " +ptr" : "");
+        gtk_window_set_title(GTK_WINDOW(vc->window), title);
+        g_free(title);
+    }
+
+    g_free(prefix);
 }
 
 static void gd_update_windowsize(VirtualConsole *vc)
@@ -915,7 +933,6 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
     VirtualConsole *vc = gd_vc_find_current(s);
-    char *title;
 
     if (vc->type == GD_VC_GFX) {
         /* temporary: needs more work to get grabs etc correct */
@@ -926,17 +943,11 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
         vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
         gtk_widget_reparent(vc->tab_item, vc->window);
 
-        if (qemu_name) {
-            title = g_strdup_printf("QEMU (%s): %s", qemu_name, vc->label);
-        } else {
-            title = g_strdup_printf("QEMU: %s", vc->label);
-        }
-        gtk_window_set_title(GTK_WINDOW(vc->window), title);
-        g_free(title);
-
         g_signal_connect(vc->window, "delete-event",
                          G_CALLBACK(gd_tab_window_close), vc);
         gtk_widget_show_all(vc->window);
+
+        gd_update_caption(s);
     }
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 17/24] gtk: fix grab checks
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 16/24] gtk: update gd_update_caption Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 18/24] gtk: update all windows on mouse mode changes Gerd Hoffmann
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Make it handle multiple windows case correctly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 35 +++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 7d6a20d..91b6824 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -201,6 +201,9 @@ struct GtkDisplayState {
 
 static GtkDisplayState *global_state;
 
+static void gd_grab_pointer(VirtualConsole *vc);
+static void gd_ungrab_pointer(GtkDisplayState *s);
+
 /** Utility Functions **/
 
 static VirtualConsole *gd_vc_find_by_menu(GtkDisplayState *s)
@@ -261,7 +264,7 @@ static void gd_update_cursor(VirtualConsole *vc)
     }
 
     window = gtk_widget_get_window(GTK_WIDGET(vc->gfx.drawing_area));
-    if (s->full_screen || qemu_input_is_absolute() || gd_is_grab_active(s)) {
+    if (s->full_screen || qemu_input_is_absolute() || s->ptr_owner == vc) {
         gdk_window_set_cursor(window, s->null_cursor);
     } else {
         gdk_window_set_cursor(window, NULL);
@@ -702,7 +705,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
         qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_Y, y,
                              surface_height(vc->gfx.ds));
         qemu_input_event_sync();
-    } else if (s->last_set && gd_is_grab_active(s)) {
+    } else if (s->last_set && s->ptr_owner == vc) {
         qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, x - s->last_x);
         qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_Y, y - s->last_y);
         qemu_input_event_sync();
@@ -711,7 +714,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
     s->last_y = y;
     s->last_set = TRUE;
 
-    if (!qemu_input_is_absolute() && gd_is_grab_active(s)) {
+    if (!qemu_input_is_absolute() && s->ptr_owner == vc) {
         GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area);
         int x = (int)motion->x_root;
         int y = (int)motion->y_root;
@@ -760,9 +763,18 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
 
     /* implicitly grab the input at the first click in the relative mode */
     if (button->button == 1 && button->type == GDK_BUTTON_PRESS &&
-        !qemu_input_is_absolute() && !gd_is_grab_active(s)) {
-        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
-                                       TRUE);
+        !qemu_input_is_absolute() && s->ptr_owner != vc) {
+        gd_ungrab_pointer(s);
+        if (!vc->window) {
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
+                                           TRUE);
+        } else {
+#if 0
+            /* FIXME: no way (yet) to ungrab */
+            gd_grab_pointer(vc);
+#endif
+            gd_update_caption(s);
+        }
         return TRUE;
     }
 
@@ -1224,7 +1236,6 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
     }
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item),
                                    TRUE);
-
     on_vga = (vc->type == GD_VC_GFX);
     if (!on_vga) {
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
@@ -1244,10 +1255,11 @@ static gboolean gd_enter_event(GtkWidget *widget, GdkEventCrossing *crossing,
     VirtualConsole *vc = opaque;
     GtkDisplayState *s = vc->s;
 
-    if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
+    if (gd_grab_on_hover(s)) {
+        gd_ungrab_keyboard(s);
         gd_grab_keyboard(vc);
+        gd_update_caption(s);
     }
-
     return TRUE;
 }
 
@@ -1257,10 +1269,10 @@ static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing,
     VirtualConsole *vc = opaque;
     GtkDisplayState *s = vc->s;
 
-    if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
+    if (gd_grab_on_hover(s)) {
         gd_ungrab_keyboard(s);
+        gd_update_caption(s);
     }
-
     return TRUE;
 }
 
@@ -1271,7 +1283,6 @@ static gboolean gd_focus_out_event(GtkWidget *widget,
     GtkDisplayState *s = vc->s;
 
     gtk_release_modifiers(s);
-
     return TRUE;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 18/24] gtk: update all windows on mouse mode changes
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (16 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 17/24] gtk: fix grab checks Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 19/24] gtk: detached window pointer grabs Gerd Hoffmann
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

We might have multiple graphic displays now which all need a cursor update.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 91b6824..8215841 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -553,6 +553,7 @@ static void gd_change_runstate(void *opaque, int running, RunState state)
 static void gd_mouse_mode_change(Notifier *notify, void *data)
 {
     GtkDisplayState *s;
+    int i;
 
     s = container_of(notify, GtkDisplayState, mouse_mode_notifier);
     /* release the grab at switching to absolute mode */
@@ -560,7 +561,10 @@ static void gd_mouse_mode_change(Notifier *notify, void *data)
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                        FALSE);
     }
-    gd_update_cursor(gd_vc_find_current(s));
+    for (i = 0; i < s->nb_vcs; i++) {
+        VirtualConsole *vc = &s->vc[i];
+        gd_update_cursor(vc);
+    }
 }
 
 /** GTK Events **/
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 19/24] gtk: detached window pointer grabs
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 18/24] gtk: update all windows on mouse mode changes Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 20/24] gtk: enable untabify for gfx Gerd Hoffmann
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Make ungrab hotkey work with detached windows.
Enable pointer grabs for detached windows.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 8215841..298419b 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -773,10 +773,7 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                            TRUE);
         } else {
-#if 0
-            /* FIXME: no way (yet) to ungrab */
             gd_grab_pointer(vc);
-#endif
             gd_update_caption(s);
         }
         return TRUE;
@@ -945,6 +942,20 @@ static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event,
     return TRUE;
 }
 
+static gboolean gd_win_grab(void *opaque)
+{
+    VirtualConsole *vc = opaque;
+
+    fprintf(stderr, "%s: %s\n", __func__, vc->label);
+    if (vc->s->ptr_owner) {
+        gd_ungrab_pointer(vc->s);
+    } else {
+        gd_grab_pointer(vc);
+    }
+    gd_update_caption(vc->s);
+    return TRUE;
+}
+
 static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
@@ -963,6 +974,13 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
                          G_CALLBACK(gd_tab_window_close), vc);
         gtk_widget_show_all(vc->window);
 
+        GtkAccelGroup *ag = gtk_accel_group_new();
+        gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag);
+
+        GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), vc, NULL);
+        gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb);
+
+        fprintf(stderr, "%s: %p\n", __func__, vc);
         gd_update_caption(s);
     }
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 20/24] gtk: enable untabify for gfx
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 19/24] gtk: detached window pointer grabs Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 21/24] gtk: Add handling for the xfree86 keycodes Gerd Hoffmann
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Now we have all grab fixes in place, so we can allow detaching
graphic display tabs too.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 298419b..79dc8db 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -338,7 +338,11 @@ static void gd_update_windowsize(VirtualConsole *vc)
     gtk_widget_set_size_request(vc->gfx.drawing_area,
                                 surface_width(vc->gfx.ds) * sx,
                                 surface_height(vc->gfx.ds) * sy);
-    gtk_window_resize(GTK_WINDOW(s->window), 320, 240);
+    if (vc->window) {
+        gtk_window_resize(GTK_WINDOW(vc->window), 320, 240);
+    } else {
+        gtk_window_resize(GTK_WINDOW(s->window), 320, 240);
+    }
 }
 
 static void gd_update_full_redraw(VirtualConsole *vc)
@@ -962,8 +966,8 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
     VirtualConsole *vc = gd_vc_find_current(s);
 
     if (vc->type == GD_VC_GFX) {
-        /* temporary: needs more work to get grabs etc correct */
-        return;
+        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
+                                       FALSE);
     }
     if (!vc->window) {
         gtk_widget_set_sensitive(vc->menu_item, false);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 21/24] gtk: Add handling for the xfree86 keycodes
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 20/24] gtk: enable untabify for gfx Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 22/24] gtk: zap unused global_state Gerd Hoffmann
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori, Bruce Rogers

From: Bruce Rogers <brogers@suse.com>

Currently only evdev keycodes are handled by the gtk-ui. SDL has
code to handle both. This patch adds similar processing so that
both keycode types will be handled via the gtk-ui.

Signed-off-by: Bruce Rogers <brogers@suse.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 79dc8db..a55ceb4 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -68,6 +68,10 @@
 #include "keymaps.h"
 #include "sysemu/char.h"
 #include "qom/object.h"
+#ifndef _WIN32
+#include <gdk/gdkx.h>
+#include <X11/XKBlib.h>
+#endif
 
 #define MAX_VCS 10
 
@@ -197,6 +201,7 @@ struct GtkDisplayState {
     bool external_pause_update;
 
     bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
+    bool has_evdev;
 };
 
 static GtkDisplayState *global_state;
@@ -842,7 +847,11 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
     } else if (gdk_keycode < 97) {
         qemu_keycode = gdk_keycode - 8;
     } else if (gdk_keycode < 158) {
-        qemu_keycode = translate_evdev_keycode(gdk_keycode - 97);
+        if (s->has_evdev) {
+            qemu_keycode = translate_evdev_keycode(gdk_keycode - 97);
+        } else {
+            qemu_keycode = translate_xfree86_keycode(gdk_keycode - 97);
+        }
     } else if (gdk_keycode == 208) { /* Hiragana_Katakana */
         qemu_keycode = 0x70;
     } else if (gdk_keycode == 211) { /* backslash */
@@ -1719,6 +1728,29 @@ static void gd_create_menus(GtkDisplayState *s)
     s->accel_group = accel_group;
 }
 
+static void gd_set_keycode_type(GtkDisplayState *s)
+{
+#ifndef _WIN32
+    char *keycodes = NULL;
+    GdkDisplay *display = gtk_widget_get_display(s->window);
+    Display *x11_display = gdk_x11_display_get_xdisplay(display);
+    XkbDescPtr desc = XkbGetKeyboard(x11_display, XkbGBN_AllComponentsMask,
+                                     XkbUseCoreKbd);
+
+    if (desc && desc->names) {
+        keycodes = XGetAtomName(x11_display, desc->names->keycodes);
+    }
+    if (keycodes == NULL) {
+        fprintf(stderr, "could not lookup keycode name\n");
+    } else if (strstart(keycodes, "evdev", NULL)) {
+        s->has_evdev = true;
+    } else if (!strstart(keycodes, "xfree86", NULL)) {
+        fprintf(stderr, "unknown keycodes `%s', please report to "
+                "qemu-devel@nongnu.org\n", keycodes);
+    }
+#endif
+}
+
 void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
@@ -1782,6 +1814,8 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
         gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_on_hover_item));
     }
 
+    gd_set_keycode_type(s);
+
     global_state = s;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 22/24] gtk: zap unused global_state
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 21/24] gtk: Add handling for the xfree86 keycodes Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 23/24] gtk: window sizing overhaul Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 24/24] gtk: workaround gtk2 vte resize issue Gerd Hoffmann
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index a55ceb4..0d86025 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -204,8 +204,6 @@ struct GtkDisplayState {
     bool has_evdev;
 };
 
-static GtkDisplayState *global_state;
-
 static void gd_grab_pointer(VirtualConsole *vc);
 static void gd_ungrab_pointer(GtkDisplayState *s);
 
@@ -1815,8 +1813,6 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
     }
 
     gd_set_keycode_type(s);
-
-    global_state = s;
 }
 
 void early_gtk_display_init(void)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 23/24] gtk: window sizing overhaul
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (21 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 22/24] gtk: zap unused global_state Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  2014-05-26  8:14 ` [Qemu-devel] [PULL 24/24] gtk: workaround gtk2 vte resize issue Gerd Hoffmann
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Major overhaul for window size handling.  This basically switches qemu
over to use geometry hints for the window manager instead of trying to
get the job done with widget resize requests.  This allows to specify
better what we need and also avoids window resizes.

FIXME: on gtk2 someone overwrites the geometry hints :(

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 100 ++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 70 insertions(+), 30 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 0d86025..ac5dbe0 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -74,6 +74,12 @@
 #endif
 
 #define MAX_VCS 10
+#define VC_WINDOW_X_MIN  320
+#define VC_WINDOW_Y_MIN  240
+#define VC_TERM_X_MIN     80
+#define VC_TERM_Y_MIN     25
+#define VC_SCALE_MIN    0.25
+#define VC_SCALE_STEP   0.25
 
 #if !defined(CONFIG_VTE)
 # define VTE_CHECK_VERSION(a, b, c) 0
@@ -322,29 +328,63 @@ static void gd_update_caption(GtkDisplayState *s)
     g_free(prefix);
 }
 
-static void gd_update_windowsize(VirtualConsole *vc)
+static void gd_update_geometry_hints(VirtualConsole *vc)
 {
     GtkDisplayState *s = vc->s;
-    double sx, sy;
+    GdkWindowHints mask = 0;
+    GdkGeometry geo = {};
+    GtkWidget *geo_widget = NULL;
+    GtkWindow *geo_window;
 
-    if (vc->type != GD_VC_GFX || s->full_screen) {
-        return;
+    if (vc->type == GD_VC_GFX) {
+        if (s->free_scale) {
+            geo.min_width  = surface_width(vc->gfx.ds) * VC_SCALE_MIN;
+            geo.min_height = surface_height(vc->gfx.ds) * VC_SCALE_MIN;
+            mask |= GDK_HINT_MIN_SIZE;
+        } else {
+            geo.min_width  = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
+            geo.min_height = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
+            mask |= GDK_HINT_MIN_SIZE;
+        }
+        geo_widget = vc->gfx.drawing_area;
+        gtk_widget_set_size_request(geo_widget, geo.min_width, geo.min_height);
+
+#if defined(CONFIG_VTE)
+    } else if (vc->type == GD_VC_VTE) {
+        VteTerminal *term = VTE_TERMINAL(vc->vte.terminal);
+        GtkBorder *ib;
+
+        geo.width_inc  = vte_terminal_get_char_width(term);
+        geo.height_inc = vte_terminal_get_char_height(term);
+        mask |= GDK_HINT_RESIZE_INC;
+        geo.base_width  = geo.width_inc;
+        geo.base_height = geo.height_inc;
+        mask |= GDK_HINT_BASE_SIZE;
+        geo.min_width  = geo.width_inc * VC_TERM_X_MIN;
+        geo.min_height = geo.height_inc * VC_TERM_Y_MIN;
+        mask |= GDK_HINT_MIN_SIZE;
+        gtk_widget_style_get(vc->vte.terminal, "inner-border", &ib, NULL);
+        geo.base_width  += ib->left + ib->right;
+        geo.base_height += ib->top + ib->bottom;
+        geo.min_width   += ib->left + ib->right;
+        geo.min_height  += ib->top + ib->bottom;
+        geo_widget = vc->vte.terminal;
+#endif
     }
 
-    if (s->free_scale) {
-        sx = 1.0;
-        sy = 1.0;
-    } else {
-        sx = vc->gfx.scale_x;
-        sy = vc->gfx.scale_y;
-    }
-    gtk_widget_set_size_request(vc->gfx.drawing_area,
-                                surface_width(vc->gfx.ds) * sx,
-                                surface_height(vc->gfx.ds) * sy);
-    if (vc->window) {
-        gtk_window_resize(GTK_WINDOW(vc->window), 320, 240);
-    } else {
-        gtk_window_resize(GTK_WINDOW(s->window), 320, 240);
+    geo_window = GTK_WINDOW(vc->window ? vc->window : s->window);
+    gtk_window_set_geometry_hints(geo_window, geo_widget, &geo, mask);
+}
+
+static void gd_update_windowsize(VirtualConsole *vc)
+{
+    GtkDisplayState *s = vc->s;
+
+    gd_update_geometry_hints(vc);
+
+    if (vc->type == GD_VC_GFX && !s->full_screen && !s->free_scale) {
+        gtk_window_resize(GTK_WINDOW(vc->window ? vc->window : s->window),
+                          VC_WINDOW_X_MIN, VC_WINDOW_Y_MIN);
     }
 }
 
@@ -991,7 +1031,7 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
         GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), vc, NULL);
         gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb);
 
-        fprintf(stderr, "%s: %p\n", __func__, vc);
+        gd_update_geometry_hints(vc);
         gd_update_caption(s);
     }
 }
@@ -1019,9 +1059,7 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
         if (vc->type == GD_VC_GFX) {
             vc->gfx.scale_x = 1.0;
             vc->gfx.scale_y = 1.0;
-            gtk_widget_set_size_request(vc->gfx.drawing_area,
-                                        surface_width(vc->gfx.ds),
-                                        surface_height(vc->gfx.ds));
+            gd_update_windowsize(vc);
             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                            FALSE);
         }
@@ -1038,8 +1076,8 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item),
                                    FALSE);
 
-    vc->gfx.scale_x += .25;
-    vc->gfx.scale_y += .25;
+    vc->gfx.scale_x += VC_SCALE_STEP;
+    vc->gfx.scale_y += VC_SCALE_STEP;
 
     gd_update_windowsize(vc);
 }
@@ -1052,11 +1090,11 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item),
                                    FALSE);
 
-    vc->gfx.scale_x -= .25;
-    vc->gfx.scale_y -= .25;
+    vc->gfx.scale_x -= VC_SCALE_STEP;
+    vc->gfx.scale_y -= VC_SCALE_STEP;
 
-    vc->gfx.scale_x = MAX(vc->gfx.scale_x, .25);
-    vc->gfx.scale_y = MAX(vc->gfx.scale_y, .25);
+    vc->gfx.scale_x = MAX(vc->gfx.scale_x, VC_SCALE_MIN);
+    vc->gfx.scale_y = MAX(vc->gfx.scale_y, VC_SCALE_MIN);
 
     gd_update_windowsize(vc);
 }
@@ -1083,9 +1121,9 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
         s->free_scale = FALSE;
         vc->gfx.scale_x = 1.0;
         vc->gfx.scale_y = 1.0;
-        gd_update_windowsize(vc);
     }
 
+    gd_update_windowsize(vc);
     gd_update_full_redraw(vc);
 }
 
@@ -1279,6 +1317,7 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
     }
     gtk_widget_set_sensitive(s->grab_item, on_vga);
 
+    gd_update_windowsize(vc);
     gd_update_cursor(vc);
 }
 
@@ -1408,7 +1447,8 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
     g_signal_connect(vc->vte.terminal, "commit", G_CALLBACK(gd_vc_in), vc);
 
     vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->vte.terminal), -1);
-    vte_terminal_set_size(VTE_TERMINAL(vc->vte.terminal), 80, 25);
+    vte_terminal_set_size(VTE_TERMINAL(vc->vte.terminal),
+                          VC_TERM_X_MIN, VC_TERM_Y_MIN);
 
 #if VTE_CHECK_VERSION(0, 28, 0) && GTK_CHECK_VERSION(3, 0, 0)
     vadjustment = gtk_scrollable_get_vadjustment
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PULL 24/24] gtk: workaround gtk2 vte resize issue
  2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
                   ` (22 preceding siblings ...)
  2014-05-26  8:14 ` [Qemu-devel] [PULL 23/24] gtk: window sizing overhaul Gerd Hoffmann
@ 2014-05-26  8:14 ` Gerd Hoffmann
  23 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2014-05-26  8:14 UTC (permalink / raw
  To: qemu-devel; +Cc: Gerd Hoffmann, Anthony Liguori

Hack isn't pretty, but gets the job done.
See source code comment for details.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index ac5dbe0..b908936 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -85,6 +85,20 @@
 # define VTE_CHECK_VERSION(a, b, c) 0
 #endif
 
+#if defined(CONFIG_VTE) && !GTK_CHECK_VERSION(3, 0, 0)
+/*
+ * The gtk2 vte terminal widget seriously messes up the window resize
+ * for some reason.  You basically can't make the qemu window smaller
+ * any more because the toplevel window geoemtry hints are overridden.
+ *
+ * Workaround that by hiding all vte widgets, except the one in the
+ * current tab.
+ *
+ * Luckily everything works smooth in gtk3.
+ */
+# define VTE_RESIZE_HACK 1
+#endif
+
 /* Compatibility define to let us build on both Gtk2 and Gtk3 */
 #if GTK_CHECK_VERSION(3, 0, 0)
 static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh)
@@ -1301,10 +1315,21 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
         return;
     }
 
+#ifdef VTE_RESIZE_HACK
+    vc = gd_vc_find_current(s);
+    if (vc && vc->type == GD_VC_VTE) {
+        gtk_widget_hide(vc->vte.terminal);
+    }
+#endif
     vc = gd_vc_find_by_page(s, arg2);
     if (!vc) {
         return;
     }
+#ifdef VTE_RESIZE_HACK
+    if (vc->type == GD_VC_VTE) {
+        gtk_widget_show(vc->vte.terminal);
+    }
+#endif
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item),
                                    TRUE);
     on_vga = (vc->type == GD_VC_GFX);
@@ -1845,6 +1870,21 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
 
     gtk_widget_show_all(s->window);
 
+#ifdef VTE_RESIZE_HACK
+    {
+        VirtualConsole *cur = gd_vc_find_current(s);
+        int i;
+
+        for (i = 0; i < s->nb_vcs; i++) {
+            VirtualConsole *vc = &s->vc[i];
+            if (vc && vc->type == GD_VC_VTE && vc != cur) {
+                gtk_widget_hide(vc->vte.terminal);
+            }
+        }
+        gd_update_windowsize(cur);
+    }
+#endif
+
     if (full_screen) {
         gtk_menu_item_activate(GTK_MENU_ITEM(s->full_screen_item));
     }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2014-05-26  8:14 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-26  8:13 [Qemu-devel] [PULL 00/24] gtk: ui overhaul, multiwindow support Gerd Hoffmann
2014-05-26  8:13 ` [Qemu-devel] [PULL 01/24] gtk: zap scrolled_window Gerd Hoffmann
2014-05-26  8:13 ` [Qemu-devel] [PULL 02/24] gtk: zap vte size requests Gerd Hoffmann
2014-05-26  8:13 ` [Qemu-devel] [PULL 03/24] gtk: cleanup CONFIG_VTE ifdef a bit Gerd Hoffmann
2014-05-26  8:13 ` [Qemu-devel] [PULL 04/24] gtk: Add a scrollbar for text consoles Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 05/24] gtk: remove page numbering assumtions from the code Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 06/24] gtk: VirtualConsole restruction Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 07/24] gtk: move vga state into VirtualGfxConsole Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 08/24] gtk: support multiple gfx displays Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 09/24] gtk: use device type as label Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 10/24] gtk: simplify resize Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 11/24] gtk: allow moving tabs to windows and back Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 12/24] gtk: add tab to trace events Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 13/24] gtk: add gd_grab trace event Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 14/24] gtk: keep track of grab owner Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 15/24] gtk: skip keyboard grab when hover autograb is active Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 16/24] gtk: update gd_update_caption Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 17/24] gtk: fix grab checks Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 18/24] gtk: update all windows on mouse mode changes Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 19/24] gtk: detached window pointer grabs Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 20/24] gtk: enable untabify for gfx Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 21/24] gtk: Add handling for the xfree86 keycodes Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 22/24] gtk: zap unused global_state Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 23/24] gtk: window sizing overhaul Gerd Hoffmann
2014-05-26  8:14 ` [Qemu-devel] [PULL 24/24] gtk: workaround gtk2 vte resize issue Gerd Hoffmann

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.