Message ID | 1363772625-9182-23-git-send-email-kraxel@redhat.com |
---|---|
State | New |
Headers | show |
Gerd Hoffmann <kraxel@redhat.com> writes: > Multihead support: For each graphical console we'll create a gtk > window, so with multiple graphics cards installed you get a gtk window > for each. vte tabs are attached to the console #0 window. This is neat but I'm not sure if the user experience is right. Each window would have independent grab. Each window would have independent full screen. I'm not sure there's an obviously right solution but it's worth discussing. I do like the idea of having two windows but perhaps we should make the second window have a no menu bar with a title that indicates that it's a secondary display? Regards, Anthony Liguori > --- > ui/gtk.c | 40 +++++++++++++++++++++++++++------------- > 1 file changed, 27 insertions(+), 13 deletions(-) > > diff --git a/ui/gtk.c b/ui/gtk.c > index 512e974..1c86054 100644 > --- a/ui/gtk.c > +++ b/ui/gtk.c > @@ -159,8 +159,6 @@ typedef struct GtkDisplayState > bool external_pause_update; > } GtkDisplayState; > > -static GtkDisplayState *global_state; > - > /** Utility Functions **/ > > static bool gd_is_grab_active(GtkDisplayState *s) > @@ -1210,7 +1208,7 @@ static void gd_connect_signals(GtkDisplayState *s) > G_CALLBACK(gd_leave_event), s); > } > > -static void gd_create_menus(GtkDisplayState *s) > +static void gd_create_menus(GtkDisplayState *s, bool vtetabs) > { > GtkStockItem item; > GtkAccelGroup *accel_group; > @@ -1302,11 +1300,13 @@ static void gd_create_menus(GtkDisplayState *s) > gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, GDK_CONTROL_MASK | GDK_MOD1_MASK); > gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->vga_item); > > - for (i = 0; i < nb_vcs; i++) { > - VirtualConsole *vc = &s->vc[i]; > + if (vtetabs) { > + for (i = 0; i < nb_vcs; i++) { > + VirtualConsole *vc = &s->vc[i]; > > - group = gd_vc_init(s, vc, i, group); > - s->nb_vcs++; > + group = gd_vc_init(s, vc, i, group); > + s->nb_vcs++; > + } > } > > separator = gtk_separator_menu_item_new(); > @@ -1336,14 +1336,13 @@ static const DisplayChangeListenerOps dcl_ops = { > .dpy_cursor_define = gd_cursor_define, > }; > > -void gtk_display_init(DisplayState *ds) > +static void gtk_display_init_one(DisplayState *ds, QemuConsole *con, > + bool vtetabs) > { > GtkDisplayState *s = g_malloc0(sizeof(*s)); > > - gtk_init(NULL, NULL); > - > s->dcl.ops = &dcl_ops; > - s->dcl.con = qemu_console_lookup_by_index(0); > + s->dcl.con = con; > > s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); > #if GTK_CHECK_VERSION(3, 2, 0) > @@ -1371,7 +1370,7 @@ void gtk_display_init(DisplayState *ds) > > gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA")); > > - gd_create_menus(s); > + gd_create_menus(s, vtetabs); > > gd_connect_signals(s); > > @@ -1400,6 +1399,21 @@ void gtk_display_init(DisplayState *ds) > gtk_widget_show_all(s->window); > > register_displaychangelistener(ds, &s->dcl); > +} > > - global_state = s; > +void gtk_display_init(DisplayState *ds) > +{ > + QemuConsole *con; > + int i = 0; > + > + gtk_init(NULL, NULL); > + > + con = qemu_console_lookup_by_index(i++); > + gtk_display_init_one(ds, con, true); > + while ((con = qemu_console_lookup_by_index(i++)) != NULL) { > + if (!qemu_console_is_graphic(con)) { > + break; > + } > + gtk_display_init_one(ds, con, false); > + } > } > -- > 1.7.9.7
On 03/20/13 14:04, Anthony Liguori wrote: > Gerd Hoffmann <kraxel@redhat.com> writes: > >> Multihead support: For each graphical console we'll create a gtk >> window, so with multiple graphics cards installed you get a gtk window >> for each. vte tabs are attached to the console #0 window. > > This is neat but I'm not sure if the user experience is right. > > Each window would have independent grab. Each window would have > independent full screen. > > I'm not sure there's an obviously right solution but it's worth > discussing. I do like the idea of having two windows but perhaps we > should make the second window have a no menu bar with a title that > indicates that it's a secondary display? Sure there is plenty of room for improvements, but I think those can go in incrementally ... /me went for another window because placing the secondary display into a tab doesn't make that much sense, and this is the minimal patch doing just that. It's also not really usable (yet) anyway as we don't have input routing, atm there is absolutely no way for the guest to figure which display (absolute) mouse events where coming from. cheers, Gerd
On 03/20/2013 01:43 PM, Gerd Hoffmann wrote: > >> Multihead support: For each graphical console we'll create a gtk >> window, so with multiple graphics cards installed you get a gtk window >> for each. vte tabs are attached to the console #0 window. >> --- >> ui/gtk.c | 40 +++++++++++++++++++++++++++---**---------- >> 1 file changed, 27 insertions(+), 13 deletions(-) >> >> > This patch doesn't seem to apply to current master.
On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote: > Multihead support: For each graphical console we'll create a gtk > window, so with multiple graphics cards installed you get a gtk window > for each. vte tabs are attached to the console #0 window. So is this going to mean arm's vexpress-a9 gets a pointless new second window? [there are two display devices in it]. If so, we're going to need to model what the hardware actually does, which is that there's a single connection on the back of the box for a monitor, and it's guest software controllable which of the two display devices is routed to the connection... -- PMM
On 03/20/13 21:06, Peter Maydell wrote: > On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote: >> Multihead support: For each graphical console we'll create a gtk >> window, so with multiple graphics cards installed you get a gtk window >> for each. vte tabs are attached to the console #0 window. > > So is this going to mean arm's vexpress-a9 gets a pointless > new second window? [there are two display devices in it]. I don't think so, given that multiple graphical consoles are not really supported by qemu today. Basically you get one window per graphical_console_init(). > If so, we're going to need to model what the hardware actually > does, which is that there's a single connection on the back > of the box for a monitor, and it's guest software controllable > which of the two display devices is routed to the connection... How does this work in 1.4? cheers, Gerd
On 03/21/13 08:52, Gerd Hoffmann wrote: > On 03/20/13 21:06, Peter Maydell wrote: >> On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote: >>> Multihead support: For each graphical console we'll create a gtk >>> window, so with multiple graphics cards installed you get a gtk window >>> for each. vte tabs are attached to the console #0 window. >> >> So is this going to mean arm's vexpress-a9 gets a pointless >> new second window? [there are two display devices in it]. > > I don't think so, given that multiple graphical consoles are not really > supported by qemu today. > > Basically you get one window per graphical_console_init(). Ahem, well, there is a second window now. >> If so, we're going to need to model what the hardware actually >> does, which is that there's a single connection on the back >> of the box for a monitor, and it's guest software controllable >> which of the two display devices is routed to the connection... > > How does this work in 1.4? I guess the second display device was never ever shown anywhere? cheers, Gerd
On 21 March 2013 08:51, Gerd Hoffmann <kraxel@redhat.com> wrote: > On 03/21/13 08:52, Gerd Hoffmann wrote: >> On 03/20/13 21:06, Peter Maydell wrote: >>> On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote: >>>> Multihead support: For each graphical console we'll create a gtk >>>> window, so with multiple graphics cards installed you get a gtk window >>>> for each. vte tabs are attached to the console #0 window. >>> >>> So is this going to mean arm's vexpress-a9 gets a pointless >>> new second window? [there are two display devices in it]. >> >> I don't think so, given that multiple graphical consoles are not really >> supported by qemu today. >> >> Basically you get one window per graphical_console_init(). > > Ahem, well, there is a second window now. Thought there might be :-) >>> If so, we're going to need to model what the hardware actually >>> does, which is that there's a single connection on the back >>> of the box for a monitor, and it's guest software controllable >>> which of the two display devices is routed to the connection... >> >> How does this work in 1.4? > > I guess the second display device was never ever shown anywhere? Correct. We rely on "last display device wins" plus the fact this happens to match up with the device Linux chooses for display. This is obviously not great but up til now QEMU hasn't actually supported multiple display devices so I haven't worried about it. -- PMM
Hi, >>>> If so, we're going to need to model what the hardware actually >>>> does, which is that there's a single connection on the back >>>> of the box for a monitor, and it's guest software controllable >>>> which of the two display devices is routed to the connection... >>> >>> How does this work in 1.4? >> >> I guess the second display device was never ever shown anywhere? > > Correct. We rely on "last display device wins" plus the fact this > happens to match up with the device Linux chooses for display. > This is obviously not great but up til now QEMU hasn't actually > supported multiple display devices so I haven't worried about it. Ok. I think the most sensible way to handle this is to implement the output routing device, make it own the (single) QemuConsole, and depending on the router state the one or the other display device is allowed to render to the QemuConsole. Alternative would be to give a QemuConsole to each display device (like it is today), then add graphics_hw_{activate,deactivate} ops and have UIs react on it. I suspect that would quickly become a bit messy though with all the different UIs we have. Also with gtk you could end up with the vte tabs being attached to a window with an inactive display device ... Comments? cheers, Gerd
Gerd Hoffmann <kraxel@redhat.com> writes: > Hi, > >>>>> If so, we're going to need to model what the hardware actually >>>>> does, which is that there's a single connection on the back >>>>> of the box for a monitor, and it's guest software controllable >>>>> which of the two display devices is routed to the connection... >>>> >>>> How does this work in 1.4? >>> >>> I guess the second display device was never ever shown anywhere? >> >> Correct. We rely on "last display device wins" plus the fact this >> happens to match up with the device Linux chooses for display. >> This is obviously not great but up til now QEMU hasn't actually >> supported multiple display devices so I haven't worried about it. > > Ok. > > I think the most sensible way to handle this is to implement the output > routing device, make it own the (single) QemuConsole, and depending on > the router state the one or the other display device is allowed to > render to the QemuConsole. Where does the switching happen in hardware? Is this two devices with a DVI port with a switch on it to have a single output port or it is something more sophisticated where there are two memory regions and a register is used to select which one is written out? Regards, Anthony Liguori
On 21 March 2013 18:25, Anthony Liguori <aliguori@us.ibm.com> wrote: > Gerd Hoffmann <kraxel@redhat.com> writes: >> I think the most sensible way to handle this is to implement the output >> routing device, make it own the (single) QemuConsole, and depending on >> the router state the one or the other display device is allowed to >> render to the QemuConsole. > > Where does the switching happen in hardware? Is this two devices with a > DVI port with a switch on it to have a single output port or it is > something more sophisticated where there are two memory regions and a > register is used to select which one is written out? The motherboard has a DVI multiplexer, which selects between the two video+audio output streams (actually it selects between three sources but we don't model the second daughterboard at all). I think these streams are not actually DVI but they are certainly video with pixel clock and S/PDIF audio already. There's a config register in the motherboard which selects which source should go out to the DVI connector. Conceptually I think it should look like this: /-----\ [ PL111 ] ===(video)====> | | | MUX | ===(video)===> [display] [ PL111 ] ===(video)====> | | \-----/ ^ [arm_sysregs]---(qemu_irq)---/ (where [] means a device and () a kind of connection.) If we supported routing of audio output we could in theory run the audio through the mux in the same way. -- PMM
diff --git a/ui/gtk.c b/ui/gtk.c index 512e974..1c86054 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -159,8 +159,6 @@ typedef struct GtkDisplayState bool external_pause_update; } GtkDisplayState; -static GtkDisplayState *global_state; - /** Utility Functions **/ static bool gd_is_grab_active(GtkDisplayState *s) @@ -1210,7 +1208,7 @@ static void gd_connect_signals(GtkDisplayState *s) G_CALLBACK(gd_leave_event), s); } -static void gd_create_menus(GtkDisplayState *s) +static void gd_create_menus(GtkDisplayState *s, bool vtetabs) { GtkStockItem item; GtkAccelGroup *accel_group; @@ -1302,11 +1300,13 @@ static void gd_create_menus(GtkDisplayState *s) gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, GDK_CONTROL_MASK | GDK_MOD1_MASK); gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->vga_item); - for (i = 0; i < nb_vcs; i++) { - VirtualConsole *vc = &s->vc[i]; + if (vtetabs) { + for (i = 0; i < nb_vcs; i++) { + VirtualConsole *vc = &s->vc[i]; - group = gd_vc_init(s, vc, i, group); - s->nb_vcs++; + group = gd_vc_init(s, vc, i, group); + s->nb_vcs++; + } } separator = gtk_separator_menu_item_new(); @@ -1336,14 +1336,13 @@ static const DisplayChangeListenerOps dcl_ops = { .dpy_cursor_define = gd_cursor_define, }; -void gtk_display_init(DisplayState *ds) +static void gtk_display_init_one(DisplayState *ds, QemuConsole *con, + bool vtetabs) { GtkDisplayState *s = g_malloc0(sizeof(*s)); - gtk_init(NULL, NULL); - s->dcl.ops = &dcl_ops; - s->dcl.con = qemu_console_lookup_by_index(0); + s->dcl.con = con; s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); #if GTK_CHECK_VERSION(3, 2, 0) @@ -1371,7 +1370,7 @@ void gtk_display_init(DisplayState *ds) gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA")); - gd_create_menus(s); + gd_create_menus(s, vtetabs); gd_connect_signals(s); @@ -1400,6 +1399,21 @@ void gtk_display_init(DisplayState *ds) gtk_widget_show_all(s->window); register_displaychangelistener(ds, &s->dcl); +} - global_state = s; +void gtk_display_init(DisplayState *ds) +{ + QemuConsole *con; + int i = 0; + + gtk_init(NULL, NULL); + + con = qemu_console_lookup_by_index(i++); + gtk_display_init_one(ds, con, true); + while ((con = qemu_console_lookup_by_index(i++)) != NULL) { + if (!qemu_console_is_graphic(con)) { + break; + } + gtk_display_init_one(ds, con, false); + } }