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:
commit
e8a0110293
@ -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 = "]";
|
||||||
|
154
ui/console-vc.c
154
ui/console-vc.c
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user