Commit c13547fe authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180515-pull-request' into staging



ui: qapi parser for -display cmd line.
gtk: multiple fixes.
sdl: opts bugfix.
vnc: magic cookie.

# gpg: Signature made Tue 15 May 2018 10:18:51 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/ui-20180515-pull-request:
  gtk: disable the F10 menubar key
  console: use linked list for QemuConsoles
  ui: document non-qapi parser cases.
  ui: switch gtk display to qapi parser
  ui: switch trivial displays to qapi parser
  ui: add qapi parser for -display
  vnc: add magic cookie to VncState
  ui/gtk: Only try to initialize EGL/X11 if GtkGlArea failed
  gtk: make it possible to hide the menu bar
  sdl2: move opts assignment into loop

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 46cc2fc4 677b4905
Loading
Loading
Loading
Loading
+58 −47
Original line number Diff line number Diff line
@@ -165,6 +165,8 @@ struct QemuConsole {
    QEMUFIFO out_fifo;
    uint8_t out_fifo_buf[16];
    QEMUTimer *kbd_timer;

    QTAILQ_ENTRY(QemuConsole) next;
};

struct DisplayState {
@@ -180,8 +182,8 @@ struct DisplayState {

static DisplayState *display_state;
static QemuConsole *active_console;
static QemuConsole **consoles;
static int nb_consoles = 0;
static QTAILQ_HEAD(consoles_head, QemuConsole) consoles =
    QTAILQ_HEAD_INITIALIZER(consoles);
static bool cursor_visible_phase;
static QEMUTimer *cursor_timer;

@@ -197,7 +199,7 @@ static void gui_update(void *opaque)
    uint64_t dcl_interval;
    DisplayState *ds = opaque;
    DisplayChangeListener *dcl;
    int i;
    QemuConsole *con;

    ds->refreshing = true;
    dpy_refresh(ds);
@@ -212,9 +214,9 @@ static void gui_update(void *opaque)
    }
    if (ds->update_interval != interval) {
        ds->update_interval = interval;
        for (i = 0; i < nb_consoles; i++) {
            if (consoles[i]->hw_ops->update_interval) {
                consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval);
        QTAILQ_FOREACH(con, &consoles, next) {
            if (con->hw_ops->update_interval) {
                con->hw_ops->update_interval(con->hw, interval);
            }
        }
        trace_console_refresh(interval);
@@ -1292,10 +1294,13 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
    s->ds = ds;
    s->console_type = console_type;

    consoles = g_realloc(consoles, sizeof(*consoles) * (nb_consoles+1));
    if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
        s->index = nb_consoles;
        consoles[nb_consoles++] = s;
    if (QTAILQ_EMPTY(&consoles)) {
        s->index = 0;
        QTAILQ_INSERT_TAIL(&consoles, s, next);
    } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
        QemuConsole *last = QTAILQ_LAST(&consoles, consoles_head);
        s->index = last->index + 1;
        QTAILQ_INSERT_TAIL(&consoles, s, next);
    } else {
        /*
         * HACK: Put graphical consoles before text consoles.
@@ -1303,15 +1308,24 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
         * Only do that for coldplugged devices.  After initial device
         * initialization we will not renumber the consoles any more.
         */
        for (i = nb_consoles; i > 0; i--) {
            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
                break;
            consoles[i] = consoles[i - 1];
            consoles[i]->index = i;
        QemuConsole *c = QTAILQ_FIRST(&consoles);

        while (QTAILQ_NEXT(c, next) != NULL &&
               c->console_type == GRAPHIC_CONSOLE) {
            c = QTAILQ_NEXT(c, next);
        }
        if (c->console_type == GRAPHIC_CONSOLE) {
            /* have no text consoles */
            s->index = c->index + 1;
            QTAILQ_INSERT_AFTER(&consoles, c, s, next);
        } else {
            s->index = c->index;
            QTAILQ_INSERT_BEFORE(c, s, next);
            /* renumber text consoles */
            for (i = s->index + 1; c != NULL; c = QTAILQ_NEXT(c, next), i++) {
                c->index = i;
            }
        }
        s->index = i;
        consoles[i] = s;
        nb_consoles++;
    }
    return s;
}
@@ -1861,21 +1875,21 @@ static DisplayState *get_alloc_displaystate(void)
DisplayState *init_displaystate(void)
{
    gchar *name;
    int i;
    QemuConsole *con;

    get_alloc_displaystate();
    for (i = 0; i < nb_consoles; i++) {
        if (consoles[i]->console_type != GRAPHIC_CONSOLE &&
            consoles[i]->ds == NULL) {
            text_console_do_init(consoles[i]->chr, display_state);
    QTAILQ_FOREACH(con, &consoles, next) {
        if (con->console_type != GRAPHIC_CONSOLE &&
            con->ds == NULL) {
            text_console_do_init(con->chr, display_state);
        }

        /* Hook up into the qom tree here (not in new_console()), once
         * all QemuConsoles are created and the order / numbering
         * doesn't change any more */
        name = g_strdup_printf("console[%d]", i);
        name = g_strdup_printf("console[%d]", con->index);
        object_property_add_child(container_get(object_get_root(), "/backend"),
                                  name, OBJECT(consoles[i]), &error_abort);
                                  name, OBJECT(con), &error_abort);
        g_free(name);
    }

@@ -1957,33 +1971,34 @@ void graphic_console_close(QemuConsole *con)

QemuConsole *qemu_console_lookup_by_index(unsigned int index)
{
    if (index >= nb_consoles) {
        return NULL;
    QemuConsole *con;

    QTAILQ_FOREACH(con, &consoles, next) {
        if (con->index == index) {
            return con;
        }
    }
    return consoles[index];
    return NULL;
}

QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
{
    QemuConsole *con;
    Object *obj;
    uint32_t h;
    int i;

    for (i = 0; i < nb_consoles; i++) {
        if (!consoles[i]) {
            continue;
        }
        obj = object_property_get_link(OBJECT(consoles[i]),
    QTAILQ_FOREACH(con, &consoles, next) {
        obj = object_property_get_link(OBJECT(con),
                                       "device", &error_abort);
        if (DEVICE(obj) != dev) {
            continue;
        }
        h = object_property_get_uint(OBJECT(consoles[i]),
        h = object_property_get_uint(OBJECT(con),
                                     "head", &error_abort);
        if (h != head) {
            continue;
        }
        return consoles[i];
        return con;
    }
    return NULL;
}
@@ -2013,22 +2028,19 @@ QemuConsole *qemu_console_lookup_by_device_name(const char *device_id,

QemuConsole *qemu_console_lookup_unused(void)
{
    QemuConsole *con;
    Object *obj;
    int i;

    for (i = 0; i < nb_consoles; i++) {
        if (!consoles[i]) {
    QTAILQ_FOREACH(con, &consoles, next) {
        if (con->hw_ops != &unused_ops) {
            continue;
        }
        if (consoles[i]->hw_ops != &unused_ops) {
            continue;
        }
        obj = object_property_get_link(OBJECT(consoles[i]),
        obj = object_property_get_link(OBJECT(con),
                                       "device", &error_abort);
        if (obj != NULL) {
            continue;
        }
        return consoles[i];
        return con;
    }
    return NULL;
}
@@ -2130,12 +2142,11 @@ static void text_console_update_cursor_timer(void)
static void text_console_update_cursor(void *opaque)
{
    QemuConsole *s;
    int i, count = 0;
    int count = 0;

    cursor_visible_phase = !cursor_visible_phase;

    for (i = 0; i < nb_consoles; i++) {
        s = consoles[i];
    QTAILQ_FOREACH(s, &consoles, next) {
        if (qemu_console_is_graphic(s) ||
            !qemu_console_is_visible(s)) {
            continue;
+57 −3
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@
#define GDK_KEY_2 GDK_2
#define GDK_KEY_f GDK_f
#define GDK_KEY_g GDK_g
#define GDK_KEY_m GDK_m
#define GDK_KEY_q GDK_q
#define GDK_KEY_plus GDK_plus
#define GDK_KEY_equal GDK_equal
@@ -208,6 +209,7 @@ struct GtkDisplayState {

    GtkWidget *show_tabs_item;
    GtkWidget *untabify_item;
    GtkWidget *show_menubar_item;

    GtkWidget *vbox;
    GtkWidget *notebook;
@@ -1387,6 +1389,30 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
    }
}

static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque)
{
    GtkDisplayState *s = opaque;
    VirtualConsole *vc = gd_vc_find_current(s);

    if (s->full_screen) {
        return;
    }

    if (gtk_check_menu_item_get_active(
                GTK_CHECK_MENU_ITEM(s->show_menubar_item))) {
        gtk_widget_show(s->menu_bar);
    } else {
        gtk_widget_hide(s->menu_bar);
    }
    gd_update_windowsize(vc);
}

static void gd_accel_show_menubar(void *opaque)
{
    GtkDisplayState *s = opaque;
    gtk_menu_item_activate(GTK_MENU_ITEM(s->show_menubar_item));
}

static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
{
    GtkDisplayState *s = opaque;
@@ -1403,7 +1429,10 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
    } else {
        gtk_window_unfullscreen(GTK_WINDOW(s->window));
        gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s);
        if (gtk_check_menu_item_get_active(
                    GTK_CHECK_MENU_ITEM(s->show_menubar_item))) {
            gtk_widget_show(s->menu_bar);
        }
        s->full_screen = FALSE;
        if (vc->type == GD_VC_GFX) {
            vc->gfx.scale_x = 1.0;
@@ -2036,6 +2065,8 @@ static void gd_connect_signals(GtkDisplayState *s)
                     G_CALLBACK(gd_menu_show_tabs), s);
    g_signal_connect(s->untabify_item, "activate",
                     G_CALLBACK(gd_menu_untabify), s);
    g_signal_connect(s->show_menubar_item, "activate",
                     G_CALLBACK(gd_menu_show_menubar), s);

    g_signal_connect(s->window, "delete-event",
                     G_CALLBACK(gd_window_close), s);
@@ -2272,11 +2303,26 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
    s->untabify_item = gtk_menu_item_new_with_mnemonic(_("Detach Tab"));
    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->untabify_item);

    s->show_menubar_item = gtk_check_menu_item_new_with_mnemonic(
            _("Show Menubar"));
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->show_menubar_item),
                                   TRUE);
    gtk_accel_group_connect(s->accel_group, GDK_KEY_m, HOTKEY_MODIFIERS, 0,
            g_cclosure_new_swap(G_CALLBACK(gd_accel_show_menubar), s, NULL));
#if GTK_CHECK_VERSION(3, 8, 0)
    gtk_accel_label_set_accel(
            GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->show_menubar_item))),
            GDK_KEY_m, HOTKEY_MODIFIERS);
#endif
    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->show_menubar_item);

    return view_menu;
}

static void gd_create_menus(GtkDisplayState *s)
{
    GtkSettings *settings;

    s->accel_group = gtk_accel_group_new();
    s->machine_menu = gd_create_menu_machine(s);
    s->view_menu = gd_create_menu_view(s);
@@ -2292,6 +2338,10 @@ static void gd_create_menus(GtkDisplayState *s)

    g_object_set_data(G_OBJECT(s->window), "accel_group", s->accel_group);
    gtk_window_add_accel_group(GTK_WINDOW(s->window), s->accel_group);

    /* Disable the default "F10" menu shortcut. */
    settings = gtk_widget_get_settings(s->window);
    g_object_set(G_OBJECT(settings), "gtk-menu-bar-accel", "", NULL);
}


@@ -2434,13 +2484,17 @@ static void early_gtk_display_init(DisplayOptions *opts)
    }

    assert(opts->type == DISPLAY_TYPE_GTK);
    if (opts->has_gl && opts->gl) {
    if (opts->has_gl && opts->gl != DISPLAYGL_MODE_OFF) {
        if (opts->gl == DISPLAYGL_MODE_ES) {
            error_report("gtk: opengl es not supported");
            return;
        }
#if defined(CONFIG_OPENGL)
#if defined(CONFIG_GTK_GL) && defined(GDK_WINDOWING_WAYLAND)
        if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
            gtk_use_gl_area = true;
            gtk_gl_area_init();
        }
        } else
#endif
        {
            gtk_egl_init();
+1 −1
Original line number Diff line number Diff line
@@ -804,7 +804,6 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
        return;
    }
    sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
    sdl2_console->opts = o;
    for (i = 0; i < sdl2_num_outputs; i++) {
        QemuConsole *con = qemu_console_lookup_by_index(i);
        assert(con != NULL);
@@ -812,6 +811,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
            sdl2_console[i].hidden = true;
        }
        sdl2_console[i].idx = i;
        sdl2_console[i].opts = o;
#ifdef CONFIG_OPENGL
        sdl2_console[i].opengl = display_opengl;
        sdl2_console[i].dcl.ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops;
+4 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ VncJob *vnc_job_new(VncState *vs)
{
    VncJob *job = g_new0(VncJob, 1);

    assert(vs->magic == VNC_MAGIC);
    job->vs = vs;
    vnc_lock_queue(queue);
    QLIST_INIT(&job->rectangles);
@@ -214,6 +215,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
    /* Here job can only be NULL if queue->exit is true */
    job = QTAILQ_FIRST(&queue->jobs);
    vnc_unlock_queue(queue);
    assert(job->vs->magic == VNC_MAGIC);

    if (queue->exit) {
        return -1;
@@ -236,6 +238,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)

    /* Make a local copy of vs and switch output buffers */
    vnc_async_encoding_start(job->vs, &vs);
    vs.magic = VNC_MAGIC;

    /* Start sending rectangles */
    n_rectangles = 0;
@@ -289,6 +292,7 @@ disconnected:
    vnc_unlock_queue(queue);
    qemu_cond_broadcast(&queue->cond);
    g_free(job);
    vs.magic = 0;
    return 0;
}

+9 −1
Original line number Diff line number Diff line
@@ -1138,6 +1138,7 @@ static void audio_capture_notify(void *opaque, audcnotification_e cmd)
{
    VncState *vs = opaque;

    assert(vs->magic == VNC_MAGIC);
    switch (cmd) {
    case AUD_CNOTIFY_DISABLE:
        vnc_lock_output(vs);
@@ -1167,6 +1168,7 @@ static void audio_capture(void *opaque, void *buf, int size)
{
    VncState *vs = opaque;

    assert(vs->magic == VNC_MAGIC);
    vnc_lock_output(vs);
    if (vs->output.offset < vs->throttle_output_offset) {
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
@@ -1275,6 +1277,7 @@ void vnc_disconnect_finish(VncState *vs)
    vs->ioc = NULL;
    object_unref(OBJECT(vs->sioc));
    vs->sioc = NULL;
    vs->magic = 0;
    g_free(vs);
}

@@ -1414,7 +1417,7 @@ static void vnc_client_write_locked(VncState *vs)

static void vnc_client_write(VncState *vs)
{

    assert(vs->magic == VNC_MAGIC);
    vnc_lock_output(vs);
    if (vs->output.offset) {
        vnc_client_write_locked(vs);
@@ -1487,6 +1490,7 @@ static void vnc_jobs_bh(void *opaque)
{
    VncState *vs = opaque;

    assert(vs->magic == VNC_MAGIC);
    vnc_jobs_consume_buffer(vs);
}

@@ -1537,6 +1541,8 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,
                       GIOCondition condition, void *opaque)
{
    VncState *vs = opaque;

    assert(vs->magic == VNC_MAGIC);
    if (condition & G_IO_IN) {
        if (vnc_client_read(vs) < 0) {
            /* vs is free()ed here */
@@ -1568,6 +1574,7 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,

void vnc_write(VncState *vs, const void *data, size_t len)
{
    assert(vs->magic == VNC_MAGIC);
    if (vs->disconnecting) {
        return;
    }
@@ -3064,6 +3071,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
    int i;

    trace_vnc_client_connect(vs, sioc);
    vs->magic = VNC_MAGIC;
    vs->sioc = sioc;
    object_ref(OBJECT(vs->sioc));
    vs->ioc = QIO_CHANNEL(sioc);
Loading