UI-related for 10.0

-----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmfH8VIcHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5fpaD/41MyK8mvNINCBh/zNs
 BttToR+P2OKDdJcg+fiq8nSaBOqk8TnxWNdfKhd8bdPY3yD56zGzgYhZVLm+d0a6
 a54jkSYLxpM7LL9nKFjLSXDqhmrreU94YGIADzG5WPhndBBHg7ZtHoS5fhlCt4dq
 0YiPMdQqYf75lSk0w/q+KG+MNX/kA/2Yq2vmxMSRT+DniW7PfcO5MixYfaAs5zJz
 JazcCZTDgbv/DrIsNeaEyMraE3GBnY1fU2obbwoQ2D+eFGA4SpUwjHKZnVkKuD0I
 jYV53BQ+dQMGpN0kmQEyQOj25HvUR5WWlsvSYqHaWupUmg3P+Ne+RaGBUmymgwAU
 FI8SVo9njl/4N8uaSDN76Ed6hpQh+LnnuR0pSDdxLLTef7JwC07009a1tYNeo3gq
 xzTT0NlD8g8oTA/p/2HVAE2nKQME9qK3v3gqfVwZGlPnOBnL2S8+9qO5qK3xHUd0
 g3YwbaKl5aRDs2t2gzrUVEk6VO9TdpllzkskF26YuDmGgPHIU8y0P2TafPgtJ1cI
 emlT06PiNwbJrpOLlLf8SaFXKWgDigt4mTUHg5ZNEDVOfs59qxcTPS1HdSKmA1nP
 x5Zhq4AUFGAxJxziUznFvCYuqwiPqVkiqvrZF2PIAgkBCb0P8JtDbk+6DtTrrP+m
 y2ODr8nH3Oo3hgDk7SOh577NKQ==
 =KDTR
 -----END PGP SIGNATURE-----

Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging

UI-related for 10.0

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmfH8VIcHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5fpaD/41MyK8mvNINCBh/zNs
# BttToR+P2OKDdJcg+fiq8nSaBOqk8TnxWNdfKhd8bdPY3yD56zGzgYhZVLm+d0a6
# a54jkSYLxpM7LL9nKFjLSXDqhmrreU94YGIADzG5WPhndBBHg7ZtHoS5fhlCt4dq
# 0YiPMdQqYf75lSk0w/q+KG+MNX/kA/2Yq2vmxMSRT+DniW7PfcO5MixYfaAs5zJz
# JazcCZTDgbv/DrIsNeaEyMraE3GBnY1fU2obbwoQ2D+eFGA4SpUwjHKZnVkKuD0I
# jYV53BQ+dQMGpN0kmQEyQOj25HvUR5WWlsvSYqHaWupUmg3P+Ne+RaGBUmymgwAU
# FI8SVo9njl/4N8uaSDN76Ed6hpQh+LnnuR0pSDdxLLTef7JwC07009a1tYNeo3gq
# xzTT0NlD8g8oTA/p/2HVAE2nKQME9qK3v3gqfVwZGlPnOBnL2S8+9qO5qK3xHUd0
# g3YwbaKl5aRDs2t2gzrUVEk6VO9TdpllzkskF26YuDmGgPHIU8y0P2TafPgtJ1cI
# emlT06PiNwbJrpOLlLf8SaFXKWgDigt4mTUHg5ZNEDVOfs59qxcTPS1HdSKmA1nP
# x5Zhq4AUFGAxJxziUznFvCYuqwiPqVkiqvrZF2PIAgkBCb0P8JtDbk+6DtTrrP+m
# y2ODr8nH3Oo3hgDk7SOh577NKQ==
# =KDTR
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 05 Mar 2025 14:38:10 HKT
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu:
  chardev: use remoteAddr if the chardev is client
  ui/console-vc: implement DCH (delete) and ICH (insert) commands
  ui/console-vc: add support for cursor DECSC and DECRC commands
  ui/console-vc: report cursor position in the screen not in the scroll buffer
  ui/console-vc: report to the application instead of screen rendering
  ui/console-vc: introduce parsing of the 'ESC ( <ch>' sequence

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-03-05 21:58:23 +08:00
commit e8a0110293
2 changed files with 149 additions and 15 deletions

View File

@ -571,9 +571,13 @@ static char *qemu_chr_compute_filename(SocketChardev *s)
switch (ss->ss_family) { switch (ss->ss_family) {
case AF_UNIX: case AF_UNIX:
return g_strdup_printf("unix:%s%s", if (s->is_listen) {
((struct sockaddr_un *)(ss))->sun_path, return g_strdup_printf("unix:%s,server=on",
s->is_listen ? ",server=on" : ""); ((struct sockaddr_un *)(ss))->sun_path);
} else {
return g_strdup_printf("unix:%s",
((struct sockaddr_un *)(ps))->sun_path);
}
case AF_INET6: case AF_INET6:
left = "["; left = "[";
right = "]"; right = "]";

View File

@ -42,6 +42,8 @@ enum TTYState {
TTY_STATE_NORM, TTY_STATE_NORM,
TTY_STATE_ESC, TTY_STATE_ESC,
TTY_STATE_CSI, TTY_STATE_CSI,
TTY_STATE_G0,
TTY_STATE_G1,
}; };
typedef struct QemuTextConsole { typedef struct QemuTextConsole {
@ -88,6 +90,7 @@ struct VCChardev {
int esc_params[MAX_ESC_PARAMS]; int esc_params[MAX_ESC_PARAMS];
int nb_esc_params; int nb_esc_params;
TextAttributes t_attrib; /* currently active text attributes */ TextAttributes t_attrib; /* currently active text attributes */
TextAttributes t_attrib_saved;
int x_saved, y_saved; int x_saved, y_saved;
}; };
typedef struct VCChardev VCChardev; typedef struct VCChardev VCChardev;
@ -615,10 +618,9 @@ static void vc_put_one(VCChardev *vc, int ch)
static void vc_respond_str(VCChardev *vc, const char *buf) static void vc_respond_str(VCChardev *vc, const char *buf)
{ {
while (*buf) { QemuTextConsole *s = vc->console;
vc_put_one(vc, *buf);
buf++; qemu_chr_be_write(s->chr, (const uint8_t *)buf, strlen(buf));
}
} }
/* set cursor, checking bounds */ /* set cursor, checking bounds */
@ -643,6 +645,113 @@ static void vc_set_cursor(VCChardev *vc, int x, int y)
s->y = y; s->y = y;
} }
/**
* vc_csi_P() - (DCH) deletes one or more characters from the cursor
* position to the right. As characters are deleted, the remaining
* characters between the cursor and right margin move to the
* left. Character attributes move with the characters.
*/
static void vc_csi_P(struct VCChardev *vc, unsigned int nr)
{
QemuTextConsole *s = vc->console;
TextCell *c1, *c2;
unsigned int x1, x2, y;
unsigned int end, len;
if (!nr) {
nr = 1;
}
if (nr > s->width - s->x) {
nr = s->width - s->x;
if (!nr) {
return;
}
}
x1 = s->x;
x2 = s->x + nr;
len = s->width - x2;
if (len) {
y = (s->y_base + s->y) % s->total_height;
c1 = &s->cells[y * s->width + x1];
c2 = &s->cells[y * s->width + x2];
memmove(c1, c2, len * sizeof(*c1));
for (end = x1 + len; x1 < end; x1++) {
vc_update_xy(vc, x1, s->y);
}
}
/* Clear the rest */
for (; x1 < s->width; x1++) {
vc_clear_xy(vc, x1, s->y);
}
}
/**
* vc_csi_at() - (ICH) inserts `nr` blank characters with the default
* character attribute. The cursor remains at the beginning of the
* blank characters. Text between the cursor and right margin moves to
* the right. Characters scrolled past the right margin are lost.
*/
static void vc_csi_at(struct VCChardev *vc, unsigned int nr)
{
QemuTextConsole *s = vc->console;
TextCell *c1, *c2;
unsigned int x1, x2, y;
unsigned int end, len;
if (!nr) {
nr = 1;
}
if (nr > s->width - s->x) {
nr = s->width - s->x;
if (!nr) {
return;
}
}
x1 = s->x + nr;
x2 = s->x;
len = s->width - x1;
if (len) {
y = (s->y_base + s->y) % s->total_height;
c1 = &s->cells[y * s->width + x1];
c2 = &s->cells[y * s->width + x2];
memmove(c1, c2, len * sizeof(*c1));
for (end = x1 + len; x1 < end; x1++) {
vc_update_xy(vc, x1, s->y);
}
}
/* Insert blanks */
for (x1 = s->x; x1 < s->x + nr; x1++) {
vc_clear_xy(vc, x1, s->y);
}
}
/**
* vc_save_cursor() - saves cursor position and character attributes.
*/
static void vc_save_cursor(VCChardev *vc)
{
QemuTextConsole *s = vc->console;
vc->x_saved = s->x;
vc->y_saved = s->y;
vc->t_attrib_saved = vc->t_attrib;
}
/**
* vc_restore_cursor() - restores cursor position and character
* attributes from saved state.
*/
static void vc_restore_cursor(VCChardev *vc)
{
QemuTextConsole *s = vc->console;
s->x = vc->x_saved;
s->y = vc->y_saved;
vc->t_attrib = vc->t_attrib_saved;
}
static void vc_putchar(VCChardev *vc, int ch) static void vc_putchar(VCChardev *vc, int ch)
{ {
QemuTextConsole *s = vc->console; QemuTextConsole *s = vc->console;
@ -694,6 +803,16 @@ static void vc_putchar(VCChardev *vc, int ch)
vc->esc_params[i] = 0; vc->esc_params[i] = 0;
vc->nb_esc_params = 0; vc->nb_esc_params = 0;
vc->state = TTY_STATE_CSI; vc->state = TTY_STATE_CSI;
} else if (ch == '(') {
vc->state = TTY_STATE_G0;
} else if (ch == ')') {
vc->state = TTY_STATE_G1;
} else if (ch == '7') {
vc_save_cursor(vc);
vc->state = TTY_STATE_NORM;
} else if (ch == '8') {
vc_restore_cursor(vc);
vc->state = TTY_STATE_NORM;
} else { } else {
vc->state = TTY_STATE_NORM; vc->state = TTY_STATE_NORM;
} }
@ -810,6 +929,9 @@ static void vc_putchar(VCChardev *vc, int ch)
break; break;
} }
break; break;
case 'P':
vc_csi_P(vc, vc->esc_params[0]);
break;
case 'm': case 'm':
vc_handle_escape(vc); vc_handle_escape(vc);
break; break;
@ -822,21 +944,19 @@ static void vc_putchar(VCChardev *vc, int ch)
case 6: case 6:
/* report cursor position */ /* report cursor position */
response = g_strdup_printf("\033[%d;%dR", response = g_strdup_printf("\033[%d;%dR",
(s->y_base + s->y) % s->total_height + 1, s->y + 1, s->x + 1);
s->x + 1);
vc_respond_str(vc, response); vc_respond_str(vc, response);
break; break;
} }
break; break;
case 's': case 's':
/* save cursor position */ vc_save_cursor(vc);
vc->x_saved = s->x;
vc->y_saved = s->y;
break; break;
case 'u': case 'u':
/* restore cursor position */ vc_restore_cursor(vc);
s->x = vc->x_saved; break;
s->y = vc->y_saved; case '@':
vc_csi_at(vc, vc->esc_params[0]);
break; break;
default: default:
trace_console_putchar_unhandled(ch); trace_console_putchar_unhandled(ch);
@ -844,6 +964,16 @@ static void vc_putchar(VCChardev *vc, int ch)
} }
break; break;
} }
break;
case TTY_STATE_G0: /* set character sets */
case TTY_STATE_G1: /* set character sets */
switch (ch) {
case 'B':
/* Latin-1 map */
break;
}
vc->state = TTY_STATE_NORM;
break;
} }
} }