Compare commits

..

24 Commits

Author SHA1 Message Date
Gerd Hoffmann
6fa2769751 gtk: workaround gtk2 vte resize issue
Hack isn't pretty, but gets the job done.
See source code comment for details.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
82fc18099a gtk: window sizing overhaul
Major 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 :(

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
0f61a61df3 gtk: zap unused global_state
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Bruce Rogers
3158a3482b gtk: Add handling for the xfree86 keycodes
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.

Signed-off-by: Bruce Rogers <brogers@suse.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
aa0a55d42d gtk: enable untabify for gfx
Now we have all grab fixes in place, so we can allow detaching
graphic display tabs too.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
0c77a37f11 gtk: detached window pointer grabs
Make ungrab hotkey work with detached windows.
Enable pointer grabs for detached windows.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:04 +02:00
Gerd Hoffmann
99623c90d1 gtk: update all windows on mouse mode changes
We might have multiple graphic displays now which all need a cursor update.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
2884cf5b93 gtk: fix grab checks
Make it handle multiple windows case correctly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
4eeaa3a885 gtk: update gd_update_caption
Adapt to recent changes, handle multiple windows.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
746b867030 gtk: skip keyboard grab when hover autograb is active
It's pointless.  With grab on hover enabled the keyboard grab
is already active when you press Ctrl-Alt-G ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
4c638e2e4b gtk: keep track of grab owner
Simplifies grab state tracking and makes ungrab more reliable.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
1c856da57b gtk: add gd_grab trace event
Input grab code is tricky, add some debug & trouble shooting aid.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
74444bc198 gtk: add tab to trace events
So you can see which of multiple displays (if present) was resized ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
cdeb7090ee gtk: allow moving tabs to windows and back.
"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.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
d3ef575080 gtk: simplify resize
Simply 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.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
6a24ced5ca gtk: use device type as label
IMO useful than showing VGA for any graphic device
even in case it is something completely different.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
ed1132e41a 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.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
e3500d1f5f gtk: move vga state into VirtualGfxConsole
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
271a25c0b6 gtk: VirtualConsole restruction
Move all vte-related items into VirtualVteConsole substruct.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
832189c9b1 gtk: remove page numbering assumtions from the code
Lookup page numbers using gtk_notebook_page_num() instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Cole Robinson
0fb20d1c39 gtk: Add a scrollbar for text consoles
Only show the scrollbar if the content doesn't fit on the visible space.

[ kraxel: fix box packing ]

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
ee5f31e48b gtk: cleanup CONFIG_VTE ifdef a bit.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
6fe83074d7 gtk: zap vte size requests
The 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.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:03 +02:00
Gerd Hoffmann
fd07d07ba9 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.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-26 08:41:02 +02:00
4 changed files with 855 additions and 496 deletions

View File

@@ -81,7 +81,6 @@ void do_mouse_set(Monitor *mon, const QDict *qdict);
#define QEMU_KEY_CTRL_PAGEUP 0xe406 #define QEMU_KEY_CTRL_PAGEUP 0xe406
#define QEMU_KEY_CTRL_PAGEDOWN 0xe407 #define QEMU_KEY_CTRL_PAGEDOWN 0xe407
void kbd_put_keysym_console(QemuConsole *s, int keysym);
void kbd_put_keysym(int keysym); void kbd_put_keysym(int keysym);
/* consoles */ /* consoles */

View File

@@ -1045,9 +1045,10 @@ displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
ppm_save(const char *filename, void *display_surface) "%s surface=%p" ppm_save(const char *filename, void *display_surface) "%s surface=%p"
# ui/gtk.c # ui/gtk.c
gd_switch(int width, int height) "width=%d, height=%d" gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d"
gd_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%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(int gdk_keycode, int qemu_keycode, const char *action) "translated GDK keycode %d to QEMU keycode %d (%s)" 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 # ui/input.c
input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%x, down %d" input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%x, down %d"

View File

@@ -143,6 +143,8 @@ struct QemuConsole {
TextCell *cells; TextCell *cells;
int text_x[2], text_y[2], cursor_invalidate; int text_x[2], text_y[2], cursor_invalidate;
int echo; int echo;
bool cursor_visible_phase;
QEMUTimer *cursor_timer;
int update_x0; int update_x0;
int update_y0; int update_y0;
@@ -175,14 +177,10 @@ static DisplayState *display_state;
static QemuConsole *active_console; static QemuConsole *active_console;
static QemuConsole *consoles[MAX_CONSOLES]; static QemuConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0; static int nb_consoles = 0;
static bool cursor_visible_phase;
static QEMUTimer *cursor_timer;
static void text_console_do_init(CharDriverState *chr, DisplayState *ds); static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
static void dpy_refresh(DisplayState *s); static void dpy_refresh(DisplayState *s);
static DisplayState *get_alloc_displaystate(void); static DisplayState *get_alloc_displaystate(void);
static void text_console_update_cursor_timer(void);
static void text_console_update_cursor(void *opaque);
static void gui_update(void *opaque) static void gui_update(void *opaque)
{ {
@@ -477,9 +475,6 @@ static inline void text_update_xy(QemuConsole *s, int x, int y)
static void invalidate_xy(QemuConsole *s, int x, int y) static void invalidate_xy(QemuConsole *s, int x, int y)
{ {
if (!qemu_console_is_visible(s)) {
return;
}
if (s->update_x0 > x * FONT_WIDTH) if (s->update_x0 > x * FONT_WIDTH)
s->update_x0 = x * FONT_WIDTH; s->update_x0 = x * FONT_WIDTH;
if (s->update_y0 > y * FONT_HEIGHT) if (s->update_y0 > y * FONT_HEIGHT)
@@ -495,20 +490,25 @@ static void update_xy(QemuConsole *s, int x, int y)
TextCell *c; TextCell *c;
int y1, y2; int y1, y2;
if (!qemu_console_is_visible(s)) {
return;
}
if (s->ds->have_text) { if (s->ds->have_text) {
text_update_xy(s, x, y); text_update_xy(s, x, y);
} }
y1 = (s->y_base + y) % s->total_height; if (s->ds->have_gfx) {
y2 = y1 - s->y_displayed; y1 = (s->y_base + y) % s->total_height;
if (y2 < 0) { y2 = y1 - s->y_displayed;
y2 += s->total_height; if (y2 < 0)
} y2 += s->total_height;
if (y2 < s->height) { if (y2 < s->height) {
c = &s->cells[y1 * s->width + x]; c = &s->cells[y1 * s->width + x];
vga_putcharxy(s, x, y2, c->ch, vga_putcharxy(s, x, y2, c->ch,
&(c->t_attrib)); &(c->t_attrib));
invalidate_xy(s, x, y2); invalidate_xy(s, x, y2);
}
} }
} }
@@ -518,28 +518,33 @@ static void console_show_cursor(QemuConsole *s, int show)
int y, y1; int y, y1;
int x = s->x; int x = s->x;
if (!qemu_console_is_visible(s)) {
return;
}
if (s->ds->have_text) { if (s->ds->have_text) {
s->cursor_invalidate = 1; s->cursor_invalidate = 1;
} }
if (x >= s->width) { if (s->ds->have_gfx) {
x = s->width - 1; if (x >= s->width) {
} x = s->width - 1;
y1 = (s->y_base + s->y) % s->total_height; }
y = y1 - s->y_displayed; y1 = (s->y_base + s->y) % s->total_height;
if (y < 0) { y = y1 - s->y_displayed;
y += s->total_height; if (y < 0)
} y += s->total_height;
if (y < s->height) { if (y < s->height) {
c = &s->cells[y1 * s->width + x]; c = &s->cells[y1 * s->width + x];
if (show && cursor_visible_phase) { if (show && s->cursor_visible_phase) {
TextAttributes t_attrib = s->t_attrib_default; TextAttributes t_attrib = s->t_attrib_default;
t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */ t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
vga_putcharxy(s, x, y, c->ch, &t_attrib); vga_putcharxy(s, x, y, c->ch, &t_attrib);
} else { } else {
vga_putcharxy(s, x, y, c->ch, &(c->t_attrib)); vga_putcharxy(s, x, y, c->ch, &(c->t_attrib));
}
invalidate_xy(s, x, y);
} }
invalidate_xy(s, x, y);
} }
} }
@@ -549,6 +554,10 @@ static void console_refresh(QemuConsole *s)
TextCell *c; TextCell *c;
int x, y, y1; int x, y, y1;
if (!qemu_console_is_visible(s)) {
return;
}
if (s->ds->have_text) { if (s->ds->have_text) {
s->text_x[0] = 0; s->text_x[0] = 0;
s->text_y[0] = 0; s->text_y[0] = 0;
@@ -557,23 +566,25 @@ static void console_refresh(QemuConsole *s)
s->cursor_invalidate = 1; s->cursor_invalidate = 1;
} }
vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface), if (s->ds->have_gfx) {
color_table_rgb[0][COLOR_BLACK]); vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface),
y1 = s->y_displayed; color_table_rgb[0][COLOR_BLACK]);
for (y = 0; y < s->height; y++) { y1 = s->y_displayed;
c = s->cells + y1 * s->width; for (y = 0; y < s->height; y++) {
for (x = 0; x < s->width; x++) { c = s->cells + y1 * s->width;
vga_putcharxy(s, x, y, c->ch, for (x = 0; x < s->width; x++) {
&(c->t_attrib)); vga_putcharxy(s, x, y, c->ch,
c++; &(c->t_attrib));
} c++;
if (++y1 == s->total_height) { }
y1 = 0; if (++y1 == s->total_height) {
y1 = 0;
}
} }
console_show_cursor(s, 1);
dpy_gfx_update(s, 0, 0,
surface_width(surface), surface_height(surface));
} }
console_show_cursor(s, 1);
dpy_gfx_update(s, 0, 0,
surface_width(surface), surface_height(surface));
} }
static void console_scroll(QemuConsole *s, int ydelta) static void console_scroll(QemuConsole *s, int ydelta)
@@ -629,7 +640,7 @@ static void console_put_lf(QemuConsole *s)
c->t_attrib = s->t_attrib_default; c->t_attrib = s->t_attrib_default;
c++; c++;
} }
if (s->y_displayed == s->y_base) { if (qemu_console_is_visible(s) && s->y_displayed == s->y_base) {
if (s->ds->have_text) { if (s->ds->have_text) {
s->text_x[0] = 0; s->text_x[0] = 0;
s->text_y[0] = 0; s->text_y[0] = 0;
@@ -637,16 +648,18 @@ static void console_put_lf(QemuConsole *s)
s->text_y[1] = s->height - 1; s->text_y[1] = s->height - 1;
} }
vga_bitblt(s, 0, FONT_HEIGHT, 0, 0, if (s->ds->have_gfx) {
s->width * FONT_WIDTH, vga_bitblt(s, 0, FONT_HEIGHT, 0, 0,
(s->height - 1) * FONT_HEIGHT); s->width * FONT_WIDTH,
vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT, (s->height - 1) * FONT_HEIGHT);
s->width * FONT_WIDTH, FONT_HEIGHT, vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT,
color_table_rgb[0][s->t_attrib_default.bgcol]); s->width * FONT_WIDTH, FONT_HEIGHT,
s->update_x0 = 0; color_table_rgb[0][s->t_attrib_default.bgcol]);
s->update_y0 = 0; s->update_x0 = 0;
s->update_x1 = s->width * FONT_WIDTH; s->update_y0 = 0;
s->update_y1 = s->height * FONT_HEIGHT; s->update_x1 = s->width * FONT_WIDTH;
s->update_y1 = s->height * FONT_HEIGHT;
}
} }
} }
} }
@@ -991,6 +1004,9 @@ void console_select(unsigned int index)
if (s) { if (s) {
DisplayState *ds = s->ds; DisplayState *ds = s->ds;
if (active_console && active_console->cursor_timer) {
timer_del(active_console->cursor_timer);
}
active_console = s; active_console = s;
if (ds->have_gfx) { if (ds->have_gfx) {
QLIST_FOREACH(dcl, &ds->listeners, next) { QLIST_FOREACH(dcl, &ds->listeners, next) {
@@ -1007,7 +1023,10 @@ void console_select(unsigned int index)
if (ds->have_text) { if (ds->have_text) {
dpy_text_resize(s, s->width, s->height); dpy_text_resize(s, s->width, s->height);
} }
text_console_update_cursor(NULL); if (s->cursor_timer) {
timer_mod(s->cursor_timer,
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + CONSOLE_CURSOR_PERIOD / 2);
}
} }
} }
@@ -1056,11 +1075,13 @@ static void kbd_send_chars(void *opaque)
} }
/* called when an ascii key is pressed */ /* called when an ascii key is pressed */
void kbd_put_keysym_console(QemuConsole *s, int keysym) void kbd_put_keysym(int keysym)
{ {
QemuConsole *s;
uint8_t buf[16], *q; uint8_t buf[16], *q;
int c; int c;
s = active_console;
if (!s || (s->console_type == GRAPHIC_CONSOLE)) if (!s || (s->console_type == GRAPHIC_CONSOLE))
return; return;
@@ -1109,11 +1130,6 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
} }
} }
void kbd_put_keysym(int keysym)
{
kbd_put_keysym_console(active_console, keysym);
}
static void text_console_invalidate(void *opaque) static void text_console_invalidate(void *opaque)
{ {
QemuConsole *s = (QemuConsole *) opaque; QemuConsole *s = (QemuConsole *) opaque;
@@ -1151,9 +1167,9 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
} }
} }
static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
uint32_t head)
{ {
Error *local_err = NULL;
Object *obj; Object *obj;
QemuConsole *s; QemuConsole *s;
int i; int i;
@@ -1163,14 +1179,13 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
obj = object_new(TYPE_QEMU_CONSOLE); obj = object_new(TYPE_QEMU_CONSOLE);
s = QEMU_CONSOLE(obj); s = QEMU_CONSOLE(obj);
s->head = head;
object_property_add_link(obj, "device", TYPE_DEVICE, object_property_add_link(obj, "device", TYPE_DEVICE,
(Object **)&s->device, (Object **)&s->device,
object_property_allow_set_link, object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE, OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort); &local_err);
object_property_add_uint32_ptr(obj, "head", object_property_add_uint32_ptr(obj, "head",
&s->head, &error_abort); &s->head, &local_err);
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
(console_type == GRAPHIC_CONSOLE))) { (console_type == GRAPHIC_CONSOLE))) {
@@ -1255,18 +1270,19 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
return surface; return surface;
} }
static DisplaySurface *qemu_create_message_surface(int w, int h, static DisplaySurface *qemu_create_dummy_surface(void)
const char *msg)
{ {
DisplaySurface *surface = qemu_create_displaysurface(w, h); static const char msg[] =
"This VM has no graphic display device.";
DisplaySurface *surface = qemu_create_displaysurface(640, 480);
pixman_color_t bg = color_table_rgb[0][COLOR_BLACK]; pixman_color_t bg = color_table_rgb[0][COLOR_BLACK];
pixman_color_t fg = color_table_rgb[0][COLOR_WHITE]; pixman_color_t fg = color_table_rgb[0][COLOR_WHITE];
pixman_image_t *glyph; pixman_image_t *glyph;
int len, x, y, i; int len, x, y, i;
len = strlen(msg); len = strlen(msg);
x = (w / FONT_WIDTH - len) / 2; x = (640/FONT_WIDTH - len) / 2;
y = (h / FONT_HEIGHT - 1) / 2; y = (480/FONT_HEIGHT - 1) / 2;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
glyph = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, msg[i]); glyph = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, msg[i]);
qemu_pixman_glyph_render(glyph, surface->image, &fg, &bg, qemu_pixman_glyph_render(glyph, surface->image, &fg, &bg,
@@ -1288,8 +1304,6 @@ void qemu_free_displaysurface(DisplaySurface *surface)
void register_displaychangelistener(DisplayChangeListener *dcl) void register_displaychangelistener(DisplayChangeListener *dcl)
{ {
static const char nodev[] =
"This VM has no graphic display device.";
static DisplaySurface *dummy; static DisplaySurface *dummy;
QemuConsole *con; QemuConsole *con;
@@ -1308,12 +1322,11 @@ void register_displaychangelistener(DisplayChangeListener *dcl)
dcl->ops->dpy_gfx_switch(dcl, con->surface); dcl->ops->dpy_gfx_switch(dcl, con->surface);
} else { } else {
if (!dummy) { if (!dummy) {
dummy = qemu_create_message_surface(640, 480, nodev); dummy = qemu_create_dummy_surface();
} }
dcl->ops->dpy_gfx_switch(dcl, dummy); dcl->ops->dpy_gfx_switch(dcl, dummy);
} }
} }
text_console_update_cursor(NULL);
} }
void update_displaychangelistener(DisplayChangeListener *dcl, void update_displaychangelistener(DisplayChangeListener *dcl,
@@ -1537,8 +1550,6 @@ static DisplayState *get_alloc_displaystate(void)
{ {
if (!display_state) { if (!display_state) {
display_state = g_new0(DisplayState, 1); display_state = g_new0(DisplayState, 1);
cursor_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
text_console_update_cursor, NULL);
} }
return display_state; return display_state;
} }
@@ -1549,6 +1560,7 @@ static DisplayState *get_alloc_displaystate(void)
*/ */
DisplayState *init_displaystate(void) DisplayState *init_displaystate(void)
{ {
Error *local_err = NULL;
gchar *name; gchar *name;
int i; int i;
@@ -1567,7 +1579,7 @@ DisplayState *init_displaystate(void)
* doesn't change any more */ * doesn't change any more */
name = g_strdup_printf("console[%d]", i); name = g_strdup_printf("console[%d]", i);
object_property_add_child(container_get(object_get_root(), "/backend"), object_property_add_child(container_get(object_get_root(), "/backend"),
name, OBJECT(consoles[i]), &error_abort); name, OBJECT(consoles[i]), &local_err);
g_free(name); g_free(name);
} }
@@ -1578,8 +1590,7 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
const GraphicHwOps *hw_ops, const GraphicHwOps *hw_ops,
void *opaque) void *opaque)
{ {
static const char noinit[] = Error *local_err = NULL;
"Guest has not initialized the display (yet).";
int width = 640; int width = 640;
int height = 480; int height = 480;
QemuConsole *s; QemuConsole *s;
@@ -1587,15 +1598,17 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
ds = get_alloc_displaystate(); ds = get_alloc_displaystate();
trace_console_gfx_new(); trace_console_gfx_new();
s = new_console(ds, GRAPHIC_CONSOLE, head); s = new_console(ds, GRAPHIC_CONSOLE);
s->hw_ops = hw_ops; s->hw_ops = hw_ops;
s->hw = opaque; s->hw = opaque;
if (dev) { if (dev) {
object_property_set_link(OBJECT(s), OBJECT(dev), "device", object_property_set_link(OBJECT(s), OBJECT(dev),
&error_abort); "device", &local_err);
object_property_set_int(OBJECT(s), head,
"head", &local_err);
} }
s->surface = qemu_create_message_surface(width, height, noinit); s->surface = qemu_create_displaysurface(width, height);
return s; return s;
} }
@@ -1609,6 +1622,7 @@ QemuConsole *qemu_console_lookup_by_index(unsigned int index)
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head) QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
{ {
Error *local_err = NULL;
Object *obj; Object *obj;
uint32_t h; uint32_t h;
int i; int i;
@@ -1618,12 +1632,12 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
continue; continue;
} }
obj = object_property_get_link(OBJECT(consoles[i]), obj = object_property_get_link(OBJECT(consoles[i]),
"device", &error_abort); "device", &local_err);
if (DEVICE(obj) != dev) { if (DEVICE(obj) != dev) {
continue; continue;
} }
h = object_property_get_int(OBJECT(consoles[i]), h = object_property_get_int(OBJECT(consoles[i]),
"head", &error_abort); "head", &local_err);
if (h != head) { if (h != head) {
continue; continue;
} }
@@ -1698,32 +1712,14 @@ static void text_console_set_echo(CharDriverState *chr, bool echo)
s->echo = echo; s->echo = echo;
} }
static void text_console_update_cursor_timer(void)
{
timer_mod(cursor_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
+ CONSOLE_CURSOR_PERIOD / 2);
}
static void text_console_update_cursor(void *opaque) static void text_console_update_cursor(void *opaque)
{ {
QemuConsole *s; QemuConsole *s = opaque;
int i, count = 0;
cursor_visible_phase = !cursor_visible_phase; s->cursor_visible_phase = !s->cursor_visible_phase;
graphic_hw_invalidate(s);
for (i = 0; i < nb_consoles; i++) { timer_mod(s->cursor_timer,
s = consoles[i]; qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + CONSOLE_CURSOR_PERIOD / 2);
if (qemu_console_is_graphic(s) ||
!qemu_console_is_visible(s)) {
continue;
}
count++;
graphic_hw_invalidate(s);
}
if (count) {
text_console_update_cursor_timer();
}
} }
static const GraphicHwOps text_console_ops = { static const GraphicHwOps text_console_ops = {
@@ -1759,6 +1755,9 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
s->surface = qemu_create_displaysurface(g_width, g_height); s->surface = qemu_create_displaysurface(g_width, g_height);
} }
s->cursor_timer =
timer_new_ms(QEMU_CLOCK_REALTIME, text_console_update_cursor, s);
s->hw_ops = &text_console_ops; s->hw_ops = &text_console_ops;
s->hw = s; s->hw = s;
@@ -1812,9 +1811,9 @@ static CharDriverState *text_console_init(ChardevVC *vc)
trace_console_txt_new(width, height); trace_console_txt_new(width, height);
if (width == 0 || height == 0) { if (width == 0 || height == 0) {
s = new_console(NULL, TEXT_CONSOLE, 0); s = new_console(NULL, TEXT_CONSOLE);
} else { } else {
s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE, 0); s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
s->surface = qemu_create_displaysurface(width, height); s->surface = qemu_create_displaysurface(width, height);
} }

1110
ui/gtk.c

File diff suppressed because it is too large Load Diff