Commit 3f9d69ba authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-20150427-1' into staging



gtk: support text consoles without vte, bugfixes.

# gpg: Signature made Mon Apr 27 14:34:15 2015 BST using RSA key ID D3E87138
# 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>"

* remotes/kraxel/tags/pull-gtk-20150427-1:
  gtk: Avoid accel key leakage into guest on console switch
  gtk: Fix VTE focus grabbing
  console/gtk: add qemu_console_get_label
  gtk: bind to text terminal consoles too
  gtk: handle switch_surface(NULL) properly

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 0d81cddd 1a01716a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head);
bool qemu_console_is_visible(QemuConsole *con);
bool qemu_console_is_graphic(QemuConsole *con);
bool qemu_console_is_fixedsize(QemuConsole *con);
char *qemu_console_get_label(QemuConsole *con);
int qemu_console_get_index(QemuConsole *con);
uint32_t qemu_console_get_head(QemuConsole *con);
QemuUIInfo *qemu_console_get_ui_info(QemuConsole *con);
+15 −0
Original line number Diff line number Diff line
@@ -1788,6 +1788,21 @@ bool qemu_console_is_fixedsize(QemuConsole *con)
    return con && (con->console_type != TEXT_CONSOLE);
}

char *qemu_console_get_label(QemuConsole *con)
{
    if (con->console_type == GRAPHIC_CONSOLE) {
        if (con->device) {
            return g_strdup(object_get_typename(con->device));
        }
        return g_strdup("VGA");
    } else {
        if (con->chr && con->chr->label) {
            return g_strdup(con->chr->label);
        }
        return g_strdup_printf("vc%d", con->index);
    }
}

int qemu_console_get_index(QemuConsole *con)
{
    if (con == NULL) {
+108 −52
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ typedef struct VirtualConsole {
    GtkWidget *window;
    GtkWidget *menu_item;
    GtkWidget *tab_item;
    GtkWidget *focus;
    VirtualConsoleType type;
    union {
        VirtualGfxConsole gfx;
@@ -230,6 +231,7 @@ struct GtkDisplayState {

    bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
    bool has_evdev;
    bool ignore_keys;
};

static void gd_grab_pointer(VirtualConsole *vc);
@@ -290,7 +292,8 @@ static void gd_update_cursor(VirtualConsole *vc)
    GtkDisplayState *s = vc->s;
    GdkWindow *window;

    if (vc->type != GD_VC_GFX) {
    if (vc->type != GD_VC_GFX ||
        !qemu_console_is_graphic(vc->gfx.dcl.con)) {
        return;
    }

@@ -363,6 +366,9 @@ static void gd_update_geometry_hints(VirtualConsole *vc)
    GtkWindow *geo_window;

    if (vc->type == GD_VC_GFX) {
        if (!vc->gfx.ds) {
            return;
        }
        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;
@@ -427,7 +433,8 @@ static void gtk_release_modifiers(GtkDisplayState *s)
    VirtualConsole *vc = gd_vc_find_current(s);
    int i, keycode;

    if (vc->type != GD_VC_GFX) {
    if (vc->type != GD_VC_GFX ||
        !qemu_console_is_graphic(vc->gfx.dcl.con)) {
        return;
    }
    for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
@@ -455,6 +462,7 @@ static void gd_update(DisplayChangeListener *dcl,
                      int x, int y, int w, int h)
{
    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
    GdkWindow *win;
    int x1, x2, y1, y2;
    int mx, my;
    int fbw, fbh;
@@ -481,8 +489,11 @@ static void gd_update(DisplayChangeListener *dcl,
    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(vc->gfx.drawing_area),
                          &ww, &wh);
    win = gtk_widget_get_window(vc->gfx.drawing_area);
    if (!win) {
        return;
    }
    gdk_drawable_get_size(win, &ww, &wh);

    mx = my = 0;
    if (ww > fbw) {
@@ -574,22 +585,28 @@ static void gd_switch(DisplayChangeListener *dcl,
    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
    bool resized = true;

    trace_gd_switch(vc->label, surface_width(surface), surface_height(surface));
    trace_gd_switch(vc->label,
                    surface ? surface_width(surface)  : 0,
                    surface ? surface_height(surface) : 0);

    if (vc->gfx.surface) {
        cairo_surface_destroy(vc->gfx.surface);
        vc->gfx.surface = NULL;
    }
    if (vc->gfx.convert) {
        pixman_image_unref(vc->gfx.convert);
        vc->gfx.convert = NULL;
    }

    if (vc->gfx.ds &&
    if (vc->gfx.ds && surface &&
        surface_width(vc->gfx.ds) == surface_width(surface) &&
        surface_height(vc->gfx.ds) == surface_height(surface)) {
        resized = false;
    }
    vc->gfx.ds = surface;

    if (vc->gfx.convert) {
        pixman_image_unref(vc->gfx.convert);
        vc->gfx.convert = NULL;
    if (!surface) {
        return;
    }

    if (surface->format == PIXMAN_x8r8g8b8) {
@@ -690,6 +707,9 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
    if (!gtk_widget_get_realized(widget)) {
        return FALSE;
    }
    if (!vc->gfx.ds) {
        return FALSE;
    }

    fbw = surface_width(vc->gfx.ds);
    fbh = surface_height(vc->gfx.ds);
@@ -771,6 +791,10 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
    int fbh, fbw;
    int ww, wh;

    if (!vc->gfx.ds) {
        return TRUE;
    }

    fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
    fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;

@@ -945,6 +969,23 @@ static int gd_map_keycode(GtkDisplayState *s, GdkDisplay *dpy, int gdk_keycode)
    return qemu_keycode;
}

static gboolean gd_text_key_down(GtkWidget *widget,
                                 GdkEventKey *key, void *opaque)
{
    VirtualConsole *vc = opaque;
    QemuConsole *con = vc->gfx.dcl.con;

    if (key->length) {
        kbd_put_string_console(con, key->string, key->length);
    } else {
        int num = gd_map_keycode(vc->s, gtk_widget_get_display(widget),
                                 key->hardware_keycode);
        int qcode = qemu_input_key_number_to_qcode(num);
        kbd_put_qcode_console(con, qcode);
    }
    return TRUE;
}

static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
{
    VirtualConsole *vc = opaque;
@@ -953,6 +994,11 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
    int qemu_keycode;
    int i;

    if (s->ignore_keys) {
        s->ignore_keys = (key->type == GDK_KEY_PRESS);
        return TRUE;
    }

    if (key->keyval == GDK_KEY_Pause) {
        qemu_input_event_send_key_qcode(vc->gfx.dcl.con, Q_KEY_CODE_PAUSE,
                                        key->type == GDK_KEY_PRESS);
@@ -1021,22 +1067,26 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
    GtkDisplayState *s = opaque;
    VirtualConsole *vc = gd_vc_find_by_menu(s);
    GtkNotebook *nb = GTK_NOTEBOOK(s->notebook);
    GtkWidget *child;
    gint page;

    gtk_release_modifiers(s);
    if (vc) {
        page = gtk_notebook_page_num(nb, vc->tab_item);
        gtk_notebook_set_current_page(nb, page);
        child = gtk_notebook_get_nth_page(nb, page);
        gtk_widget_grab_focus(child);
        gtk_widget_grab_focus(vc->focus);
    }
    s->ignore_keys = false;
}

static void gd_accel_switch_vc(void *opaque)
{
    VirtualConsole *vc = opaque;

    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item), TRUE);
#if !GTK_CHECK_VERSION(3, 0, 0)
    /* GTK2 sends the accel key to the target console - ignore this until */
    vc->s->ignore_keys = true;
#endif
}

static void gd_menu_show_tabs(GtkMenuItem *item, void *opaque)
@@ -1086,7 +1136,8 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
    GtkDisplayState *s = opaque;
    VirtualConsole *vc = gd_vc_find_current(s);

    if (vc->type == GD_VC_GFX) {
    if (vc->type == GD_VC_GFX &&
        qemu_console_is_graphic(vc->gfx.dcl.con)) {
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                       FALSE);
    }
@@ -1099,11 +1150,14 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
                         G_CALLBACK(gd_tab_window_close), vc);
        gtk_widget_show_all(vc->window);

        if (qemu_console_is_graphic(vc->gfx.dcl.con)) {
            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);
            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);
        }

        gd_update_geometry_hints(vc);
        gd_update_caption(s);
@@ -1120,8 +1174,10 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
        gtk_widget_hide(s->menu_bar);
        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);
            if (qemu_console_is_graphic(vc->gfx.dcl.con)) {
                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;
@@ -1370,7 +1426,8 @@ static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2,
#endif
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item),
                                   TRUE);
    on_vga = (vc->type == GD_VC_GFX);
    on_vga = (vc->type == GD_VC_GFX &&
              qemu_console_is_graphic(vc->gfx.dcl.con));
    if (!on_vga) {
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
                                       FALSE);
@@ -1542,6 +1599,7 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,

    vc->type = GD_VC_VTE;
    vc->tab_item = box;
    vc->focus = vc->vte.terminal;
    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item,
                             gtk_label_new(vc->label));

@@ -1577,6 +1635,7 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc)
    g_signal_connect(vc->gfx.drawing_area, "expose-event",
                     G_CALLBACK(gd_expose_event), vc);
#endif
    if (qemu_console_is_graphic(vc->gfx.dcl.con)) {
        g_signal_connect(vc->gfx.drawing_area, "event",
                         G_CALLBACK(gd_event), vc);
        g_signal_connect(vc->gfx.drawing_area, "button-press-event",
@@ -1596,6 +1655,10 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc)
                         G_CALLBACK(gd_leave_event), vc);
        g_signal_connect(vc->gfx.drawing_area, "focus-out-event",
                         G_CALLBACK(gd_focus_out_event), vc);
    } else {
        g_signal_connect(vc->gfx.drawing_area, "key-press-event",
                         G_CALLBACK(gd_text_key_down), vc);
    }
}

static void gd_connect_signals(GtkDisplayState *s)
@@ -1679,15 +1742,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
                              QemuConsole *con, int idx,
                              GSList *group, GtkWidget *view_menu)
{
    Object *obj;

    obj = object_property_get_link(OBJECT(con), "device", NULL);
    if (obj) {
        vc->label = g_strdup_printf("%s", object_get_typename(obj));
    } else {
        vc->label = g_strdup_printf("VGA");
    }

    vc->label = qemu_console_get_label(con);
    vc->s = s;
    vc->gfx.scale_x = 1.0;
    vc->gfx.scale_y = 1.0;
@@ -1706,16 +1761,17 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,

    vc->type = GD_VC_GFX;
    vc->tab_item = vc->gfx.drawing_area;
    vc->focus = vc->gfx.drawing_area;
    gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
                             vc->tab_item, gtk_label_new(vc->label));
    gd_connect_vc_gfx_signals(vc);

    group = gd_vc_menu_init(s, vc, idx, group, view_menu);

    vc->gfx.dcl.ops = &dcl_ops;
    vc->gfx.dcl.con = con;
    register_displaychangelistener(&vc->gfx.dcl);

    gd_connect_vc_gfx_signals(vc);
    group = gd_vc_menu_init(s, vc, idx, group, view_menu);

    return group;
}

@@ -1787,7 +1843,7 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
    /* gfx */
    for (vc = 0;; vc++) {
        con = qemu_console_lookup_by_index(vc);
        if (!con || !qemu_console_is_graphic(con)) {
        if (!con) {
            break;
        }
        group = gd_vc_gfx_init(s, &s->vc[vc], con,