Message ID | 1329695104-15174-4-git-send-email-aliguori@us.ibm.com |
---|---|
State | New |
Headers | show |
Am 20.02.2012 00:45, schrieb Anthony Liguori: > This enables VteTerminal to be used to render the text consoles. > VteTerminal is > the same widget used by gnome-terminal which means it's VT100 > emulation is as > good as they come. > > It's also screen reader accessible, supports copy/paste, proper > scrolling and > most of the other features you would expect from a terminal widget. > > Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> > --- > ui/gtk.c | 138 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 138 insertions(+), 0 deletions(-) > The new code uses VtePty and some functions which were added to VteTerminal in 2010, so this is a rather new interface: commit dd08c50c6a6dd4349d3cbce271ddf4b741db8861 Autor: Christian Persch <chpe@gnome.org> Do Jan 14 18:08:33 2010 Eintragender: Christian Persch <chpe@gnome.org> Mi Mär 17 18:22:15 2010 Add VtePty and adapt the VteTerminal APIs to it Add VtePty as a GObject holding the info about the PTY. Add new API to VteTerminal to set a VtePty, and deprecate the old API that takes a FD to the PTY. Also deprecate the whole of the undocumented _vte_pty_*() APIs. Add vte_terminal_fork_command_full() variant that allow providing a custom child setup function and that returns a GError on failure. => It does not work with Debian stable and other "old" distributions. configure detects GTK+ and VTE, but make fails. Regards, Stefan Weil
Am 20.02.2012 00:45, schrieb Anthony Liguori: > This enables VteTerminal to be used to render the text consoles. > VteTerminal is > the same widget used by gnome-terminal which means it's VT100 > emulation is as > good as they come. > > It's also screen reader accessible, supports copy/paste, proper > scrolling and > most of the other features you would expect from a terminal widget. > > Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> > --- > ui/gtk.c | 138 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 138 insertions(+), 0 deletions(-) > > diff --git a/ui/gtk.c b/ui/gtk.c > index 502705b..bf65a4f 100644 > --- a/ui/gtk.c > +++ b/ui/gtk.c [...] > +static int gd_vc_handler(QemuOpts *opts, CharDriverState **chrp) > +{ > + CharDriverState *chr; > + > + chr = g_malloc0(sizeof(*chr)); Some time ago, there was a decision to prefer g_new / g_new0: chr = g_new0(CharDriverState, 1); In function gtk_display_init there is also a g_malloc0 which should be replaced by g_new0. Regards, Stefan Weil
On 02/25/2012 10:21 AM, Stefan Weil wrote: > Am 20.02.2012 00:45, schrieb Anthony Liguori: >> This enables VteTerminal to be used to render the text consoles. VteTerminal is >> the same widget used by gnome-terminal which means it's VT100 emulation is as >> good as they come. >> >> It's also screen reader accessible, supports copy/paste, proper scrolling and >> most of the other features you would expect from a terminal widget. >> >> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> >> --- >> ui/gtk.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 138 insertions(+), 0 deletions(-) >> >> diff --git a/ui/gtk.c b/ui/gtk.c >> index 502705b..bf65a4f 100644 >> --- a/ui/gtk.c >> +++ b/ui/gtk.c > [...] >> +static int gd_vc_handler(QemuOpts *opts, CharDriverState **chrp) >> +{ >> + CharDriverState *chr; >> + >> + chr = g_malloc0(sizeof(*chr)); > > Some time ago, there was a decision to prefer g_new / g_new0: I'm not sure where the book of decisions is kept, but I certainly don't agree. a = malloc(sizeof(*a)) is an incredibly common pattern in QEMU. It would be silly to change this pattern without good cause. Regards, Anthony Liguori > > chr = g_new0(CharDriverState, 1); > > In function gtk_display_init there is also a g_malloc0 which > should be replaced by g_new0. > > Regards, > > Stefan Weil > >
Am 25.02.2012 20:49, schrieb Anthony Liguori: > On 02/25/2012 10:21 AM, Stefan Weil wrote: >> Am 20.02.2012 00:45, schrieb Anthony Liguori: >>> This enables VteTerminal to be used to render the text consoles. >>> VteTerminal is >>> the same widget used by gnome-terminal which means it's VT100 >>> emulation is as >>> good as they come. >>> >>> It's also screen reader accessible, supports copy/paste, proper >>> scrolling and >>> most of the other features you would expect from a terminal widget. >>> >>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> >>> --- >>> ui/gtk.c | 138 >>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >>> 1 files changed, 138 insertions(+), 0 deletions(-) >>> >>> diff --git a/ui/gtk.c b/ui/gtk.c >>> index 502705b..bf65a4f 100644 >>> --- a/ui/gtk.c >>> +++ b/ui/gtk.c >> [...] >>> +static int gd_vc_handler(QemuOpts *opts, CharDriverState **chrp) >>> +{ >>> + CharDriverState *chr; >>> + >>> + chr = g_malloc0(sizeof(*chr)); >> >> Some time ago, there was a decision to prefer g_new / g_new0: > > I'm not sure where the book of decisions is kept, but I certainly > don't agree. a = malloc(sizeof(*a)) is an incredibly common pattern in > QEMU. > > It would be silly to change this pattern without good cause. > > Regards, > > Anthony Liguori Hi Anthony, there is no book of decisions for QEMU, but there is best practice. As far as I remember this topic was first discussed in this qemu-devel thread: http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg01988.html a = malloc(sizeof(*a)) is no longer a valid pattern for QEMU since you introduced glib-2.0. Those calls were converted to a = g_malloc(sizeof(*a)) which was reasonable for a simple automated code conversion. I also used the g_malloc pattern in my patch, but was convinced that glib-2.0 offers a better alternative using g_new. Kind regards, Stefan Weil
On 02/25/2012 02:22 PM, Stefan Weil wrote: > Am 25.02.2012 20:49, schrieb Anthony Liguori: >> On 02/25/2012 10:21 AM, Stefan Weil wrote: >>> Am 20.02.2012 00:45, schrieb Anthony Liguori: >>>> This enables VteTerminal to be used to render the text consoles. VteTerminal is >>>> the same widget used by gnome-terminal which means it's VT100 emulation is as >>>> good as they come. >>>> >>>> It's also screen reader accessible, supports copy/paste, proper scrolling and >>>> most of the other features you would expect from a terminal widget. >>>> >>>> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> >>>> --- >>>> ui/gtk.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >>>> 1 files changed, 138 insertions(+), 0 deletions(-) >>>> >>>> diff --git a/ui/gtk.c b/ui/gtk.c >>>> index 502705b..bf65a4f 100644 >>>> --- a/ui/gtk.c >>>> +++ b/ui/gtk.c >>> [...] >>>> +static int gd_vc_handler(QemuOpts *opts, CharDriverState **chrp) >>>> +{ >>>> + CharDriverState *chr; >>>> + >>>> + chr = g_malloc0(sizeof(*chr)); >>> >>> Some time ago, there was a decision to prefer g_new / g_new0: >> >> I'm not sure where the book of decisions is kept, but I certainly don't agree. >> a = malloc(sizeof(*a)) is an incredibly common pattern in QEMU. >> >> It would be silly to change this pattern without good cause. >> >> Regards, >> >> Anthony Liguori > > Hi Anthony, > > there is no book of decisions for QEMU, but there is best practice. > As far as I remember this topic was first discussed in this > qemu-devel thread: > > http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg01988.html > > a = malloc(sizeof(*a)) is no longer a valid pattern for QEMU > since you introduced glib-2.0. Those calls were converted > to a = g_malloc(sizeof(*a)) which was reasonable for a simple > automated code conversion. > > I also used the g_malloc pattern in my patch, but was convinced > that glib-2.0 offers a better alternative using g_new. I meant g_malloc of course. If we want to have a "best practice", we should document it in CODING_STYLE. But I wouldn't agree with such a patch to coding style anyway. Regards, Anthony Liguori > > Kind regards, > > Stefan Weil > >
diff --git a/ui/gtk.c b/ui/gtk.c index 502705b..bf65a4f 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -35,6 +35,8 @@ #define dprintf(fmt, ...) do { } while (0) #endif +#define MAX_VCS 10 + typedef struct VirtualConsole { GtkWidget *menu_item; @@ -58,6 +60,9 @@ typedef struct GtkDisplayState GtkWidget *view_menu; GtkWidget *vga_item; + int nb_vcs; + VirtualConsole vc[MAX_VCS]; + GtkWidget *show_tabs_item; GtkWidget *vbox; @@ -379,6 +384,15 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque) if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vga_item))) { gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), 0); + } else { + int 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; + } + } } } @@ -405,8 +419,124 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2, gd_update_cursor(s, TRUE); } +/** Virtual Console Callbacks **/ + +static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len) +{ + VirtualConsole *vc = chr->opaque; + + return write(vc->fd, buf, len); +} + +static int nb_vcs; +static CharDriverState *vcs[MAX_VCS]; + +static int gd_vc_handler(QemuOpts *opts, CharDriverState **chrp) +{ + CharDriverState *chr; + + chr = g_malloc0(sizeof(*chr)); + chr->chr_write = gd_vc_chr_write; + + *chrp = chr; + + vcs[nb_vcs++] = chr; + + return 0; +} + void early_gtk_display_init(void) { + register_vc_handler(gd_vc_handler); +} + +static gboolean gd_vc_in(GIOChannel *chan, GIOCondition cond, void *opaque) +{ + VirtualConsole *vc = opaque; + uint8_t buffer[1024]; + ssize_t len; + + len = read(vc->fd, buffer, sizeof(buffer)); + if (len <= 0) { + return FALSE; + } + + qemu_chr_be_write(vc->chr, buffer, len); + + return TRUE; +} + +static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSList *group) +{ + const char *label; + char buffer[32]; + char path[32]; + VtePty *pty; + GIOChannel *chan; + GtkWidget *scrolled_window; + GtkAdjustment *adjustment; + int master_fd, slave_fd, ret; + struct termios tty; + + snprintf(buffer, sizeof(buffer), "vc%d", index); + snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index); + + vc->chr = vcs[index]; + + if (vc->chr->label) { + label = vc->chr->label; + } else { + label = buffer; + } + + 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, GDK_CONTROL_MASK | GDK_MOD1_MASK); + + vc->terminal = vte_terminal_new(); + + ret = openpty(&master_fd, &slave_fd, NULL, NULL, NULL); + g_assert(ret != -1); + + /* Set raw attributes on the pty. */ + tcgetattr(slave_fd, &tty); + cfmakeraw(&tty); + tcsetattr(slave_fd, TCSAFLUSH, &tty); + + pty = vte_pty_new_foreign(master_fd, NULL); + + vte_terminal_set_pty_object(VTE_TERMINAL(vc->terminal), pty); + + vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1); + + adjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal)); + + scrolled_window = gtk_scrolled_window_new(NULL, adjustment); + + gtk_container_add(GTK_CONTAINER(scrolled_window), vc->terminal); + + vc->fd = slave_fd; + 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)); + g_signal_connect(vc->menu_item, "activate", + G_CALLBACK(gd_menu_switch_vc), s); + + gtk_menu_append(GTK_MENU(s->view_menu), vc->menu_item); + + qemu_chr_generic_open(vc->chr); + if (vc->chr->init) { + vc->chr->init(vc->chr); + } + + chan = g_io_channel_unix_new(vc->fd); + g_io_add_watch(chan, G_IO_IN, gd_vc_in, vc); + + return group; } /** Window Creation **/ @@ -446,6 +576,7 @@ static void gd_create_menus(GtkDisplayState *s) GtkAccelGroup *accel_group; GSList *group = NULL; GtkWidget *separator; + int i; accel_group = gtk_accel_group_new(); s->file_menu = gtk_menu_new(); @@ -472,6 +603,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_append(GTK_MENU(s->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); + s->nb_vcs++; + } + separator = gtk_separator_menu_item_new(); gtk_menu_append(GTK_MENU(s->view_menu), separator);
This enables VteTerminal to be used to render the text consoles. VteTerminal is the same widget used by gnome-terminal which means it's VT100 emulation is as good as they come. It's also screen reader accessible, supports copy/paste, proper scrolling and most of the other features you would expect from a terminal widget. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> --- ui/gtk.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 138 insertions(+), 0 deletions(-)