qemu gtk ui overhaul
cover qemu gtk ui overhaul
Hi,
I'm trying to put the qemu gtk ui into shape. Fixing a bunch of issues we have, and also make it ready for multihead support.
Git tree is here:
git://git.kraxel.org/qemu rebase/ui-gtk-next
please review,
Gerd
Bruce Rogers (1):
gtk: Add handling for the xfree86 keycodes
Cole Robinson (1):
gtk: Add a scrollbar for text consoles
Gerd Hoffmann (23):
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
gtk: factor out gtk3 grab into the new gd_grab_devices function
trace-events | 7 +- ui/gtk.c | 1198 +++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 769 insertions(+), 436 deletions(-)
Signature · 1 line
1.8.3.1
PATCH 1/25 gtk: zap scrolled_window
The vte widget implements the scrollable interface, placing it into a scrolled window is pointless and creates a bunch of strange effects. Zap it.
--- ui/gtk.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-)
ui/gtk.c +2 -17
@@ -110,7 +110,6 @@ typedef struct VirtualConsoleGtkWidget *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, GSLconst 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, GSLvte_terminal_set_scrollback_lines (VTE_TERMINAL (vc->terminal),-1 ); -#if VTE_CHECK_VERSION (0 ,28 ,0 ) &>K_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);
Signature · 1 line
1.8.3.1
PATCH 2/25 gtk: zap vte size requests
In reply to Gerd HoffmannThe 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.
--- ui/gtk.c | 14 -------------- 1 file changed, 14 deletions(-)
ui/gtk.c +0 -14
@@ -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
Signature · 1 line
1.8.3.1
PATCH 3/25 gtk: cleanup CONFIG_VTE ifdef a bit.
In reply to Gerd Hoffmann--- ui/gtk.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-)
ui/gtk.c +26 -19
@@ -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_gGSList *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_ggtk_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 +}
Signature · 1 line
1.8.3.1
PATCH 4/25 gtk: Add a scrollbar for text consoles
In reply to Gerd HoffmannFrom: Cole Robinson <[email protected]>
Only show the scrollbar if the content doesn't fit on the visible space.
[ kraxel: fix box packing ]
--- ui/gtk.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-)
ui/gtk.c +40 -2
@@ -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, GSLconst 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, GSLg_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 ) &>K_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);
Signature · 1 line
1.8.3.1
PATCH 5/25 gtk: remove page numbering assumtions from the code
In reply to Gerd HoffmannLookup page numbers using gtk_notebook_page_num() instead.
--- ui/gtk.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-)
ui/gtk.c +30 -10
@@ -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
Signature · 1 line
1.8.3.1
PATCH 6/25 gtk: VirtualConsole restruction
In reply to Gerd HoffmannMove all vte-related items into VirtualVteConsole substruct.
--- ui/gtk.c | 119 +++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 46 deletions(-)
ui/gtk.c +73 -46
@@ -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, GSLsnprintf (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, GSLgtk_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 ) &>K_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;
Signature · 1 line
1.8.3.1
PATCH 7/25 gtk: move vga state into VirtualGfxConsole
In reply to Gerd Hoffmann--- ui/gtk.c | 615 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 337 insertions(+), 278 deletions(-)
ui/gtk.c +337 -278
@@ -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 GtkDisplayStateGtkWidget *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 GtkDisplayStateGtkWidget *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 GtkDisplayStateint 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 GtkDisplayStatebool 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 ourwindow 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, GSLsnprintf (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, GSLg_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, GSLreturn 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 *accereturn 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; }
Signature · 1 line
1.8.3.1
PATCH 8/25 gtk: support multiple gfx displays
In reply to Gerd HoffmannEach 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.
--- ui/gtk.c | 80 ++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 37 deletions(-)
ui/gtk.c +43 -37
@@ -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_gGSList *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_ggtk_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 ();
Signature · 1 line
1.8.3.1
PATCH 9/25 gtk: use device type as label
In reply to Gerd HoffmannIMO useful than showing VGA for any graphic device even in case it is something completely different.
--- ui/gtk.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
ui/gtk.c +12 -2
@@ -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;
Signature · 1 line
1.8.3.1
PATCH 10/25 gtk: simplify resize
In reply to Gerd HoffmannSimply 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.
--- ui/gtk.c | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-)
ui/gtk.c +14 -26
@@ -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)
Signature · 1 line
1.8.3.1
PATCH 11/25 gtk: allow moving tabs to windows and back.
In reply to Gerd Hoffmann"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.
--- ui/gtk.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 11 deletions(-)
ui/gtk.c +63 -11
@@ -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; }
Signature · 1 line
1.8.3.1
PATCH 12/25 gtk: add tab to trace events
In reply to Gerd HoffmannSo you can see which of multiple displays (if present) was resized ;)
--- trace-events | 6 +++--- ui/gtk.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-)
trace-events +3 -3
@@ -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"
ui/gtk.c +3 -3
@@ -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++) {
Signature · 1 line
1.8.3.1
PATCH 13/25 gtk: add gd_grab trace event
In reply to Gerd HoffmannInput grab code is tricky, add some debug & trouble shooting aid.
--- trace-events | 1 + ui/gtk.c | 4 ++++ 2 files changed, 5 insertions(+)
trace-events +1 -0
@@ -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"
ui/gtk.c +4 -0
@@ -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)
Signature · 1 line
1.8.3.1
PATCH 14/25 gtk: keep track of grab owner
In reply to Gerd HoffmannSimplifies grab state tracking and makes ungrab more reliable.
--- ui/gtk.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-)
ui/gtk.c +23 -5
@@ -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;
Signature · 1 line
1.8.3.1
PATCH 15/25 gtk: skip keyboard grab when hover autograb is active
In reply to Gerd HoffmannIt's pointless. With grab on hover enabled the keyboard grab is already active when you press Ctrl-Alt-G ;)
--- ui/gtk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
ui/gtk.c +3 -1
@@ -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);
Signature · 1 line
1.8.3.1
PATCH 16/25 gtk: update gd_update_caption
In reply to Gerd HoffmannAdapt to recent changes, handle multiple windows.
--- ui/gtk.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-)
ui/gtk.c +28 -17
@@ -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); } }
Signature · 1 line
1.8.3.1
PATCH 17/25 gtk: fix grab checks
In reply to Gerd HoffmannMake it handle multiple windows case correctly.
--- ui/gtk.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-)
ui/gtk.c +23 -12
@@ -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; }
Signature · 1 line
1.8.3.1
PATCH 18/25 gtk: update all windows on mouse mode changes
In reply to Gerd HoffmannWe might have multiple graphic displays now which all need a cursor update.
--- ui/gtk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
ui/gtk.c +5 -1
@@ -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 **/
Signature · 1 line
1.8.3.1
PATCH 19/25 gtk: detached window pointer grabs
In reply to Gerd HoffmannMake ungrab hotkey work with detached windows.
Enable pointer grabs for detached windows.
--- ui/gtk.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
ui/gtk.c +21 -3
@@ -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); } }
Signature · 1 line
1.8.3.1
PATCH 20/25 gtk: enable untabify for gfx
In reply to Gerd HoffmannNow we have all grab fixes in place, so we can allow detaching graphic display tabs too.
--- ui/gtk.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
ui/gtk.c +7 -3
@@ -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);
Signature · 1 line
1.8.3.1
PATCH 21/25 gtk: Add handling for the xfree86 keycodes
In reply to Gerd HoffmannFrom: Bruce Rogers <[email protected]>
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.
--- ui/gtk.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
ui/gtk.c +35 -1
@@ -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 " +"[email protected]\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; }
Signature · 1 line
1.8.3.1
PATCH 22/25 gtk: zap unused global_state
In reply to Gerd Hoffmann--- ui/gtk.c | 4 ---- 1 file changed, 4 deletions(-)
ui/gtk.c +0 -4
@@ -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 )
Signature · 1 line
1.8.3.1
PATCH 23/25 gtk: window sizing overhaul
In reply to Gerd HoffmannMajor 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 :(
--- ui/gtk.c | 100 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 30 deletions(-)
ui/gtk.c +70 -30
@@ -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 ) &>K_CHECK_VERSION (3 ,0 ,0 ) vadjustment = gtk_scrollable_get_vadjustment
Signature · 1 line
1.8.3.1
PATCH 24/25 gtk: workaround gtk2 vte resize issue
In reply to Gerd HoffmannHack isn't pretty, but gets the job done.
See source code comment for details.
--- ui/gtk.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
ui/gtk.c +40 -0
@@ -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)); }
Signature · 1 line
1.8.3.1
PATCH 25/25 gtk: factor out gtk3 grab into the new gd_grab_devices function
In reply to Gerd Hoffmann--- ui/gtk.c | 100 +++++++++++++++++++++++---------------------------------------- 1 file changed, 36 insertions(+), 64 deletions(-)
ui/gtk.c +36 -64
@@ -1141,28 +1141,39 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)gd_update_full_redraw (vc); } -static void gd_grab_keyboard (VirtualConsole *vc) -{#if GTK_CHECK_VERSION (3 ,0 ,0 ) +static void gd_grab_devices (VirtualConsole *vc,bool grab, +GdkInputSource source,GdkEventMask mask, +GdkCursor *cursor) +{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 ); -GList *tmp = devices; -while (tmp) { +GList *devs =gdk_device_manager_list_devices (mgr,GDK_DEVICE_TYPE_MASTER ); +GList *tmp = devs; + +for (tmp = devs; tmp; tmp = tmp->next) {GdkDevice *dev = tmp->data; -if (gdk_device_get_source (dev) ==GDK_SOURCE_KEYBOARD ) { -gdk_device_grab (dev, -gtk_widget_get_window (vc->gfx.drawing_area), -GDK_OWNERSHIP_NONE , - FALSE, -GDK_KEY_PRESS_MASK |GDK_KEY_RELEASE_MASK , -NULL , -GDK_CURRENT_TIME ); +if (gdk_device_get_source (dev) != source) { +continue ; + } +if (grab) { +GdkWindow *win =gtk_widget_get_window (vc->gfx.drawing_area); +gdk_device_grab (dev, win,GDK_OWNERSHIP_NONE , FALSE, + mask, cursor,GDK_CURRENT_TIME ); + }else { +gdk_device_ungrab (dev,GDK_CURRENT_TIME ); } - tmp = tmp->next; } -g_list_free (devices); +g_list_free (devs); +} +#endif + +static void gd_grab_keyboard (VirtualConsole *vc) +{ +#if GTK_CHECK_VERSION (3 ,0 ,0 ) +gd_grab_devices (vc, true,GDK_SOURCE_KEYBOARD , +GDK_KEY_PRESS_MASK |GDK_KEY_RELEASE_MASK , +NULL );#else gdk_keyboard_grab(gtk_widget_get_window(vc->gfx.drawing_area), FALSE,
@@ -1182,20 +1193,7 @@ static void gd_ungrab_keyboard(GtkDisplayState *s) 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); -GList *devices =gdk_device_manager_list_devices (mgr, -GDK_DEVICE_TYPE_MASTER ); -GList *tmp = devices; -while (tmp) { -GdkDevice *dev = tmp->data; -if (gdk_device_get_source (dev) ==GDK_SOURCE_KEYBOARD ) { -gdk_device_ungrab (dev, -GDK_CURRENT_TIME ); - } - tmp = tmp->next; - } -g_list_free (devices); +gd_grab_devices (vc, false,GDK_SOURCE_KEYBOARD ,0 ,NULL );#else gdk_keyboard_ungrab (GDK_CURRENT_TIME );#endif
@@ -1207,28 +1205,13 @@ static void gd_grab_pointer(VirtualConsole *vc)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, -GDK_DEVICE_TYPE_MASTER ); -GList *tmp = devices; -while (tmp) { -GdkDevice *dev = tmp->data; -if (gdk_device_get_source (dev) ==GDK_SOURCE_MOUSE ) { -gdk_device_grab (dev, -gtk_widget_get_window (vc->gfx.drawing_area), -GDK_OWNERSHIP_NONE , - FALSE,/* All events to come to our -window directly */ -GDK_POINTER_MOTION_MASK | -GDK_BUTTON_PRESS_MASK | -GDK_BUTTON_RELEASE_MASK | -GDK_BUTTON_MOTION_MASK | -GDK_SCROLL_MASK , - vc->s->null_cursor, -GDK_CURRENT_TIME ); - } - tmp = tmp->next; - } -g_list_free (devices); +gd_grab_devices (vc, true,GDK_SOURCE_MOUSE , +GDK_POINTER_MOTION_MASK | +GDK_BUTTON_PRESS_MASK | +GDK_BUTTON_RELEASE_MASK | +GDK_BUTTON_MOTION_MASK | +GDK_SCROLL_MASK , + vc->s->null_cursor);gdk_device_get_position (gdk_device_manager_get_client_pointer (mgr),NULL , &vc->s->grab_x_root, &vc->s->grab_y_root);#else
@@ -1261,18 +1244,7 @@ static void gd_ungrab_pointer(GtkDisplayState *s)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, -GDK_DEVICE_TYPE_MASTER ); -GList *tmp = devices; -while (tmp) { -GdkDevice *dev = tmp->data; -if (gdk_device_get_source (dev) ==GDK_SOURCE_MOUSE ) { -gdk_device_ungrab (dev, -GDK_CURRENT_TIME ); - } - tmp = tmp->next; - } -g_list_free (devices); +gd_grab_devices (vc, false,GDK_SOURCE_MOUSE ,0 ,NULL );gdk_device_warp (gdk_device_manager_get_client_pointer (mgr),gtk_widget_get_screen (vc->gfx.drawing_area), vc->s->grab_x_root, vc->s->grab_y_root);
Signature · 1 line
1.8.3.1
Am 21.05.2014 10:43, schrieb Gerd Hoffmann:
Quoted 11 lines
Hi,
I'm trying to put the qemu gtk ui into shape. Fixing a bunch of issues we have, and also make it ready for multihead support.
Git tree is here:
git://git.kraxel.org/qemurebase/ui-gtk-nextplease review,
Gerd
Hi Gerd,
I did some tests with Linux und Windows versions of QEMU based on your code. Both compile and work. The "Detach Tab" feature is something which I have missed since a long time (also for SDL), great to see it implemented now. Here are some first results from a short test.
I noticed that some issues with the old code still exist: when "Show tabs" is enabled and disabled again, QEMU adds some black scan lines at the top of the VGA screen. This can be easily reproduced. Another small problem is "Zoom To Fit" which sometimes changes the display even if it was optimal before (more difficult to reproduce).
"Fullscreen" shows some new issues with your code (tested on a 1024x600 Linux netbook). With Alt+Ctrl+F in non detached compatmonitor0 I get a display which continuously switches from fullscreen to non fullscreen. In detached mode, a fullscreen VGA display shows some white scan lines at the top. It would be nice to have scroll bars when necessary. On my small display it is no longer possible to see the whole compatmonitor0 contents (it's larger than my display, zooming or resizing the window does not work and there are no scroll bars).
Regards
Stefan
Hi,
Quoted 3 lines
I noticed that some issues with the old code still exist: when "Show tabs" is enabled and disabled again, QEMU adds some black scan lines at the top of the VGA screen. This can be easily reproduced.
Easily fixed, was just a missing "gd_update_windowsize" call.
Quoted 3 lines
Another small
problem is "Zoom To Fit" which sometimes changes the display even if it was optimal before (more difficult to reproduce).
Changes in what way?
Quoted 3 lines
"Fullscreen" shows some new issues with your code (tested on a 1024x600 Linux netbook). With Alt+Ctrl+F in non detached compatmonitor0 I get a display which continuously switches from fullscreen to non fullscreen.
Hmm, doesn't reproduce here.
Quoted 2 lines
In detached mode, a fullscreen VGA display shows some white scan lines at the top.
I suspect this is the menu bar. Current code tries to hide it by forcing the widget size to 0x0. In gtk2 this results in a small white line at the top of the screen, probably because the minimum widget size in gtk is 1x1. In gtk3 this doesn't work at all and the menu bar remains visible. This isn't a new issue btw.
I've tried to fix that with a simple gtk_widget_hide(menu_bar) call. Which has the side effect to also turn off all menu accelerators. Which is a non-starter, especially for Ctrl-Alt-F not working any more.
If someone has an idea how to tackle this, I'm all ears.
Quoted 4 lines
It would be nice to have scroll bars when necessary. On my small display it is no longer possible to see the whole compatmonitor0 contents (it's larger than my display, zooming or resizing the window does not work and there are no scroll bars).
Try setting the VC_TERM_{X,Y}_MIN defines at the top of gtk.c to something smaller. Then you should be able to make the vte tabs small enough that they fit onto the screen.
Making the terminal font configurable is probably a good idea too.
cheers,
Gerd
Il 22/05/2014 08:24, Gerd Hoffmann ha scritto:
Quoted 9 lines
I suspect this is the menu bar. Current code tries to hide it by forcing the widget size to
0x0. In gtk2 this results in a small white line at the top of the screen, probably because the minimum widget size in gtk is 1x1. In gtk3 this doesn't work at all and the menu bar remains visible. This isn't a new issue btw.I've tried to fix that with a simple
gtk_widget_hide(menu_bar)call. Which has the side effect to also turn off all menu accelerators. Which is a non-starter, especially for Ctrl-Alt-F not working any more.
Subclass the menu bar and override the draw and size_allocate methods when the widget is "hidden"?
Paolo
[Qemu-devel] Mousegrab broken with vfio in 2.1.0 (was: [PATCH 00/25] qemu gtk ui overhaul)
In reply to Gerd HoffmannI think one of those gtk patches broke mouse/keyboard grab for my Windows 8 vfio/vga-passthrough setup in 2.1.0 and I was instructed on IRC to report that here.
With 2.0.0 I got a black qemu window with "This VM has no graphic display device", which I could click on to get a mouse grab. With 2.1.0 I just get the qemu monitor window.
If I press Ctrl-Alt-g or use the corresponding menu entry, the gtk window grabs the input devices and the titlebar changes to "press Ctrl-Alt-g to release grab", but none of the input reaches the vm.
I tried all of {gtk3, sdl} x {usb-mouse, usb-tablet}:
With gtk3, none worked.
With sdl usb-tablet worked, but I haven't figured out how to do an actual mouse grab. (maybe related to me passing "-vga none"?)
If I drop the "-vga none" I can get a mouse-grab, but the passed-through gpu won't work, so this is no option for me.
If needed I can produce some logs with both 2.0 and 2.1, but I don't know what options I should pass to qemu to make those useful.
Here is how I start qemu:
qemu-system-x86_64
-enable-kvm -M q35 -cpu host,hv-time,kvm=off -vga none
-m 8192 -smp 2,sockets=1,cores=2,threads=1
-bios /usr/share/qemu/bios.bin
-device ioh3420,bus=pcie.0,addr=1c.0,multifunction=on,port=1,chassis=1,id=root.1
-device vfio-pci,host=01:00.0,bus=root.1,addr=00.0,multifunction=on,x-vga=on
-device vfio-pci,host=01:00.1,bus=root.1,addr=00.1
-drive file=/mnt/images/Win8.raw,id=disk,format=raw,if=virtio
-device ich9-intel-hda,bus=pcie.0,addr=1b.0,id=sound0
-device hda-micro,id=sound0-codec0,bus=sound0.0,cad=0
-net bridge -net nic,model=virtio
-rtc base=localtime
-usb
-usbdevice mouse
-usbdevice keyboardGreetings,
Benedikt
Re: [Qemu-devel] Mousegrab broken with vfio in 2.1.0 (was: [PATCH 00/25] qemu gtk ui overhaul)
Quoted 24 lines · Benedikt Morbach
I think one of those gtk patches broke mouse/keyboard grab for my Windows 8 vfio/vga-passthrough setup in 2.1.0 and I was instructed on IRC to report that here.
With 2.0.0 I got a black qemu window with "This VM has no graphic display device", which I could click on to get a mouse grab. With 2.1.0 I just get the qemu monitor window.
If I press Ctrl-Alt-g or use the corresponding menu entry, the gtk window grabs the input devices and the titlebar changes to "press Ctrl-Alt-g to release grab", but none of the input reaches the vm.I tried all of {gtk3, sdl} x {usb-mouse, usb-tablet}:
With gtk3, none worked.
With sdl usb-tablet worked, but I haven't figured out how to do an actual mouse grab. (maybe related to me passing "-vga none"?)If I drop the "-vga none" I can get a mouse-grab, but the passed-through gpu won't work, so this is no option for me.
If needed I can produce some logs with both 2.0 and 2.1, but I don't know what options I should pass to qemu to make those useful.
Here is how I start qemu:
qemu-system-x86_64
Quoted 14 lines
-enable-kvm -M q35 -cpu host,hv-time,kvm=off -vga none
-m 8192 -smp 2,sockets=1,cores=2,threads=1
-bios /usr/share/qemu/bios.bin
-device ioh3420,bus=pcie.0,addr=1c.0,multifunction=on,port=1,chassis=1,id=root.1
-device vfio-pci,host=01:00.0,bus=root.1,addr=00.0,multifunction=on,x-vga=on
-device vfio-pci,host=01:00.1,bus=root.1,addr=00.1
-drive file=/mnt/images/Win8.raw,id=disk,format=raw,if=virtio
-device ich9-intel-hda,bus=pcie.0,addr=1b.0,id=sound0
-device hda-micro,id=sound0-codec0,bus=sound0.0,cad=0
-net bridge -net nic,model=virtio
-rtc base=localtime
-usb
-usbdevice mouse
-usbdevice keyboardI have now bisected this down to:
commit ed1132e41a31ded554adc542ddf043714f05b9d0
gtk: support multiple gfx displays
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.
PATCH 1/1 fix gtk interface for vfio + vga=none (was: Mousegrab broken with vfio in 2.1.0)
after the recent ui rework it didn't show a gfx window if no emulated graphics card was attached. This prevented input grab from working for the vfio gpu passthrough use case.
Hack around this by always creating at least one gfx tab.
---
I'm not quite sure how much of a hack this is, but it at least matches the old behaviour of creating at least one gfx console and works for me. So if anyone wants to give this a shot until someone comes up with a proper fix, here it is.
ui/gtk.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
ui/gtk.c +6 -4
@@ -1639,9 +1639,11 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,Error *local_err =NULL ;Object *obj; - obj =object_property_get_link (OBJECT (con),"device" , &local_err); -if (obj) { - vc->label =g_strdup_printf ("%s" ,object_get_typename (obj)); +if (con) { + obj =object_property_get_link (OBJECT (con),"device" , &local_err); +if (obj) { + vc->label =g_strdup_printf ("%s" ,object_get_typename (obj)); + } }else { vc->label =g_strdup_printf ("VGA" ); }
@@ -1742,7 +1744,7 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g/* gfx */ for (vc =0 ;; vc++) { con =qemu_console_lookup_by_index (vc); -if (!con || !qemu_console_is_graphic (con)) { +if (vc >0 && (!con || !qemu_console_is_graphic (con))) {break ; } group = gd_vc_gfx_init(s, &s->vc[vc], con,
Signature · 1 line
2.0.4
Re: [Qemu-devel] Mousegrab broken with vfio in 2.1.0 (was: [PATCH 00/25] qemu gtk ui overhaul)
In reply to Benedikt MorbachQuoted 6 lines · Benedikt Morbach
I think one of those gtk patches broke mouse/keyboard grab for my Windows 8 vfio/vga-passthrough setup in 2.1.0 and I was instructed on IRC to report that here.
With 2.0.0 I got a black qemu window with "This VM has no graphic display device", which I could click on to get a mouse grab.
Yes, this is (intentionally) gone in 2.1.
No vga -> no graphic display.
Quoted 3 lines
If I press Ctrl-Alt-g or use the corresponding menu entry, the gtk window grabs the input devices and the titlebar changes to "press Ctrl-Alt-g to release grab", but none of the input reaches the vm.
It shouldn't allow the grab in the first place.
But, yes, any input (grab being active or not) is only routed to the guest in case a graphic display tab is the active one. You don't want the guest see the stuff you are typing into the qemu monitor.
Quoted 2 lines
If I drop the "-vga none" I can get a mouse-grab, but the passed-through gpu won't work, so this is no option for me.
Worth trying: '-vga none -device secondary-vga'.
How does your setup look like? Two gfx cards, one for the host, one for the guest? Then have qemu running on the host display, let qemu grab the input and feed mouse (kbd too?) input to the guest that way?
It's a bit strange, but I think we don't have a better way to do it (without additional physical devices). In case you have a spare usb mouse you can simply plug it in and use usb-host to assign it to the guest, which is probably more comfortable than grabbing/ungrabbing when switching between host and guest.
cheers,
Gerd