X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/67ef811ed1452efe9d60c4baa20c8ef6ea0cfe87..2212092e11db4c92416f989db9000737daaf9d37:/ui/console.c diff --git a/ui/console.c b/ui/console.c index 7db0fd27c9..b9575f2ee5 100644 --- a/ui/console.c +++ b/ui/console.c @@ -123,6 +123,8 @@ struct QemuConsole { DisplaySurface *surface; int dcls; DisplayChangeListener *gl; + bool gl_block; + int window_id; /* Graphic console state. */ Object *device; @@ -264,14 +266,24 @@ void graphic_hw_update(QemuConsole *con) void graphic_hw_gl_block(QemuConsole *con, bool block) { - if (!con) { - con = active_console; - } - if (con && con->hw_ops->gl_block) { + assert(con != NULL); + + con->gl_block = block; + if (con->hw_ops->gl_block) { con->hw_ops->gl_block(con->hw, block); } } +int qemu_console_get_window_id(QemuConsole *con) +{ + return con->window_id; +} + +void qemu_console_set_window_id(QemuConsole *con, int window_id) +{ + con->window_id = window_id; +} + void graphic_hw_invalidate(QemuConsole *con) { if (!con) { @@ -757,6 +769,31 @@ static void console_clear_xy(QemuConsole *s, int x, int y) update_xy(s, x, y); } +static void console_put_one(QemuConsole *s, int ch) +{ + TextCell *c; + int y1; + if (s->x >= s->width) { + /* line wrap */ + s->x = 0; + console_put_lf(s); + } + y1 = (s->y_base + s->y) % s->total_height; + c = &s->cells[y1 * s->width + s->x]; + c->ch = ch; + c->t_attrib = s->t_attrib; + update_xy(s, s->x, s->y); + s->x++; +} + +static void console_respond_str(QemuConsole *s, const char *buf) +{ + while (*buf) { + console_put_one(s, *buf); + buf++; + } +} + /* set cursor, checking bounds */ static void set_cursor(QemuConsole *s, int x, int y) { @@ -779,9 +816,9 @@ static void set_cursor(QemuConsole *s, int x, int y) static void console_putchar(QemuConsole *s, int ch) { - TextCell *c; - int y1, i; + int i; int x, y; + char response[40]; switch(s->state) { case TTY_STATE_NORM: @@ -817,17 +854,7 @@ static void console_putchar(QemuConsole *s, int ch) s->state = TTY_STATE_ESC; break; default: - if (s->x >= s->width) { - /* line wrap */ - s->x = 0; - console_put_lf(s); - } - y1 = (s->y_base + s->y) % s->total_height; - c = &s->cells[y1 * s->width + s->x]; - c->ch = ch; - c->t_attrib = s->t_attrib; - update_xy(s, s->x, s->y); - s->x++; + console_put_one(s, ch); break; } break; @@ -956,8 +983,19 @@ static void console_putchar(QemuConsole *s, int ch) console_handle_escape(s); break; case 'n': - /* report cursor position */ - /* TODO: send ESC[row;colR */ + switch (s->esc_params[0]) { + case 5: + /* report console status (always succeed)*/ + console_respond_str(s, "\033[0n"); + break; + case 6: + /* report cursor position */ + sprintf(response, "\033[%d;%dR", + (s->y_base + s->y) % s->total_height + 1, + s->x + 1); + console_respond_str(s, response); + break; + } break; case 's': /* save cursor position */ @@ -1056,6 +1094,7 @@ static void kbd_send_chars(void *opaque) void kbd_put_keysym_console(QemuConsole *s, int keysym) { uint8_t buf[16], *q; + CharBackend *be; int c; if (!s || (s->console_type == GRAPHIC_CONSOLE)) @@ -1098,7 +1137,8 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym) if (s->echo) { console_puts(s->chr, buf, q - buf); } - if (s->chr->chr_read) { + be = s->chr->be; + if (be && be->chr_read) { qemu_fifo_write(&s->out_fifo, buf, q - buf); kbd_send_chars(s); } @@ -1116,6 +1156,7 @@ static const int qcode_to_keysym[Q_KEY_CODE__MAX] = { [Q_KEY_CODE_PGUP] = QEMU_KEY_PAGEUP, [Q_KEY_CODE_PGDN] = QEMU_KEY_PAGEDOWN, [Q_KEY_CODE_DELETE] = QEMU_KEY_DELETE, + [Q_KEY_CODE_BACKSPACE] = QEMU_KEY_BACKSPACE, }; bool kbd_put_qcode_console(QemuConsole *s, int qcode) @@ -1266,6 +1307,17 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, return surface; } +DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image) +{ + DisplaySurface *surface = g_new0(DisplaySurface, 1); + + trace_displaysurface_create_pixman(surface); + surface->format = pixman_image_get_format(image); + surface->image = pixman_image_ref(image); + + return surface; +} + static void qemu_unmap_displaysurface_guestmem(pixman_image_t *image, void *unused) { @@ -1416,16 +1468,21 @@ bool dpy_ui_info_supported(QemuConsole *con) int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info) { assert(con != NULL); - con->ui_info = *info; + if (!dpy_ui_info_supported(con)) { return -1; } + if (memcmp(&con->ui_info, info, sizeof(con->ui_info)) == 0) { + /* nothing changed -- ignore */ + return 0; + } /* * Typically we get a flood of these as the user resizes the window. * Wait until the dust has settled (one second without updates), then * go notify the guest. */ + con->ui_info = *info; timer_mod(con->ui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); return 0; } @@ -1667,11 +1724,13 @@ QEMUGLContext dpy_gl_ctx_get_current(QemuConsole *con) void dpy_gl_scanout(QemuConsole *con, uint32_t backing_id, bool backing_y_0_top, + uint32_t backing_width, uint32_t backing_height, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { assert(con->gl); con->gl->ops->dpy_gl_scanout(con->gl, backing_id, backing_y_0_top, + backing_width, backing_height, x, y, width, height); } @@ -1790,6 +1849,29 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head) return NULL; } +QemuConsole *qemu_console_lookup_by_device_name(const char *device_id, + uint32_t head, Error **errp) +{ + DeviceState *dev; + QemuConsole *con; + + dev = qdev_find_recursive(sysbus_get_default(), device_id); + if (dev == NULL) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", device_id); + return NULL; + } + + con = qemu_console_lookup_by_device(dev, head); + if (con == NULL) { + error_setg(errp, "Device %s (head %d) is not bound to a QemuConsole", + device_id, head); + return NULL; + } + + return con; +} + bool qemu_console_is_visible(QemuConsole *con) { return (con == active_console) || (con->dcls > 0); @@ -1811,6 +1893,12 @@ bool qemu_console_is_fixedsize(QemuConsole *con) return con && (con->console_type != TEXT_CONSOLE); } +bool qemu_console_is_gl_blocked(QemuConsole *con) +{ + assert(con != NULL); + return con->gl_block; +} + char *qemu_console_get_label(QemuConsole *con) { if (con->console_type == GRAPHIC_CONSOLE) { @@ -1958,8 +2046,6 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) } qemu_chr_be_generic_open(chr); - if (chr->init) - chr->init(chr); } static CharDriverState *text_console_init(ChardevVC *vc, Error **errp) @@ -2004,10 +2090,6 @@ static CharDriverState *text_console_init(ChardevVC *vc, Error **errp) s->chr = chr; chr->opaque = s; chr->chr_set_echo = text_console_set_echo; - /* console/chardev init sometimes completes elsewhere in a 2nd - * stage, so defer OPENED events until they are fully initialized - */ - chr->explicit_be_open = true; if (display_state) { text_console_do_init(chr, display_state); @@ -2018,9 +2100,14 @@ static CharDriverState *text_console_init(ChardevVC *vc, Error **errp) static VcHandler *vc_handler = text_console_init; static CharDriverState *vc_init(const char *id, ChardevBackend *backend, - ChardevReturn *ret, Error **errp) + ChardevReturn *ret, bool *be_opened, + Error **errp) { - return vc_handler(backend->u.vc, errp); + /* console/chardev init sometimes completes elsewhere in a 2nd + * stage, so defer OPENED events until they are fully initialized + */ + *be_opened = false; + return vc_handler(backend->u.vc.data, errp); } void register_vc_handler(VcHandler *handler) @@ -2033,6 +2120,13 @@ void qemu_console_resize(QemuConsole *s, int width, int height) DisplaySurface *surface; assert(s->console_type == GRAPHIC_CONSOLE); + + if (s->surface && + pixman_image_get_width(s->surface->image) == width && + pixman_image_get_height(s->surface->image) == height) { + return; + } + surface = qemu_create_displaysurface(width, height); dpy_gfx_replace_surface(s, surface); } @@ -2062,7 +2156,7 @@ static void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, int val; ChardevVC *vc; - vc = backend->u.vc = g_new0(ChardevVC, 1); + vc = backend->u.vc.data = g_new0(ChardevVC, 1); qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc)); val = qemu_opt_get_number(opts, "width", 0);