mirror of https://github.com/xemu-project/xemu.git
ui: qapi parser for -display cmd line.
gtk: multiple fixes. sdl: opts bugfix. vnc: magic cookie. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJa+qX7AAoJEEy22O7T6HE4XYAQALWBtR3E0zuS3UFpvMJMIiMY GyZ/3AQ0QH/W5+nHlDi6VrwCJAyT7GQENuiMH/yoXe8o3LrdWrsFgdg0oCUrT6Uz 28csuymGZprGw5YxZYMjdZgi2dcxXAR3KvBasY5/UlgT6wOSazV7JJDIuGRGcnvA UWtBl7fQ4O3lXxypFklCuHtNR0Jc7tLdF7HdG/ATSaFOnV44FRp+E1u2QRYi+gYs 7Qras/fXl4m7pMSifzACFGJCY4FJ/uopFu1MDItm/jm881KOjhZzIBYcTo5skw4n 5IKrl04O/c2iubs/cJi6Qye3Q2H8ijZUYO6ItRz71/upOodfIzXvotPBKh075s9V iOnlT+ajNvZ9ArEp/dGQfFrV0h/rJUjhmn4Lh21OJTqLpAvqKi4V48LS5cUQBFbx ZZ/yAzaTt06AIayHttTHrUYWdKLVwfEHtRzrAWVr8JmlwW8q1LvXytG21kXBjpT4 qjzPNhRGq2Q0GLUirskltEaLoJtcfCvqYNnPTDLLRov5MfLxnu8v0rOFC/JTAK3N w4PKBzXGB6mAY2Dq5QoOqK1JW+pGLiVa5dblaf69yEVjOzF9dVFlNXNc4G6Br0mH lyiBjqdaoMuT9/GpYNOO/Yj+XHNHU1M2EaNXvmc/NtdR2qSwsQ4Up1czn2Z7X4J0 8BSNswMiUrv4GOCSA/4l =R3f9 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180515-pull-request' into staging ui: qapi parser for -display cmd line. gtk: multiple fixes. sdl: opts bugfix. vnc: magic cookie. # gpg: Signature made Tue 15 May 2018 10:18:51 BST # gpg: using RSA key 4CB6D8EED3E87138 # 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>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/ui-20180515-pull-request: gtk: disable the F10 menubar key console: use linked list for QemuConsoles ui: document non-qapi parser cases. ui: switch gtk display to qapi parser ui: switch trivial displays to qapi parser ui: add qapi parser for -display vnc: add magic cookie to VncState ui/gtk: Only try to initialize EGL/X11 if GtkGlArea failed gtk: make it possible to hide the menu bar sdl2: move opts assignment into loop Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c13547feee
105
ui/console.c
105
ui/console.c
|
@ -165,6 +165,8 @@ struct QemuConsole {
|
|||
QEMUFIFO out_fifo;
|
||||
uint8_t out_fifo_buf[16];
|
||||
QEMUTimer *kbd_timer;
|
||||
|
||||
QTAILQ_ENTRY(QemuConsole) next;
|
||||
};
|
||||
|
||||
struct DisplayState {
|
||||
|
@ -180,8 +182,8 @@ struct DisplayState {
|
|||
|
||||
static DisplayState *display_state;
|
||||
static QemuConsole *active_console;
|
||||
static QemuConsole **consoles;
|
||||
static int nb_consoles = 0;
|
||||
static QTAILQ_HEAD(consoles_head, QemuConsole) consoles =
|
||||
QTAILQ_HEAD_INITIALIZER(consoles);
|
||||
static bool cursor_visible_phase;
|
||||
static QEMUTimer *cursor_timer;
|
||||
|
||||
|
@ -197,7 +199,7 @@ static void gui_update(void *opaque)
|
|||
uint64_t dcl_interval;
|
||||
DisplayState *ds = opaque;
|
||||
DisplayChangeListener *dcl;
|
||||
int i;
|
||||
QemuConsole *con;
|
||||
|
||||
ds->refreshing = true;
|
||||
dpy_refresh(ds);
|
||||
|
@ -212,9 +214,9 @@ static void gui_update(void *opaque)
|
|||
}
|
||||
if (ds->update_interval != interval) {
|
||||
ds->update_interval = interval;
|
||||
for (i = 0; i < nb_consoles; i++) {
|
||||
if (consoles[i]->hw_ops->update_interval) {
|
||||
consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval);
|
||||
QTAILQ_FOREACH(con, &consoles, next) {
|
||||
if (con->hw_ops->update_interval) {
|
||||
con->hw_ops->update_interval(con->hw, interval);
|
||||
}
|
||||
}
|
||||
trace_console_refresh(interval);
|
||||
|
@ -1292,10 +1294,13 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
|
|||
s->ds = ds;
|
||||
s->console_type = console_type;
|
||||
|
||||
consoles = g_realloc(consoles, sizeof(*consoles) * (nb_consoles+1));
|
||||
if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
|
||||
s->index = nb_consoles;
|
||||
consoles[nb_consoles++] = s;
|
||||
if (QTAILQ_EMPTY(&consoles)) {
|
||||
s->index = 0;
|
||||
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
||||
} else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
|
||||
QemuConsole *last = QTAILQ_LAST(&consoles, consoles_head);
|
||||
s->index = last->index + 1;
|
||||
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
||||
} else {
|
||||
/*
|
||||
* HACK: Put graphical consoles before text consoles.
|
||||
|
@ -1303,15 +1308,24 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
|
|||
* Only do that for coldplugged devices. After initial device
|
||||
* initialization we will not renumber the consoles any more.
|
||||
*/
|
||||
for (i = nb_consoles; i > 0; i--) {
|
||||
if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
|
||||
break;
|
||||
consoles[i] = consoles[i - 1];
|
||||
consoles[i]->index = i;
|
||||
QemuConsole *c = QTAILQ_FIRST(&consoles);
|
||||
|
||||
while (QTAILQ_NEXT(c, next) != NULL &&
|
||||
c->console_type == GRAPHIC_CONSOLE) {
|
||||
c = QTAILQ_NEXT(c, next);
|
||||
}
|
||||
if (c->console_type == GRAPHIC_CONSOLE) {
|
||||
/* have no text consoles */
|
||||
s->index = c->index + 1;
|
||||
QTAILQ_INSERT_AFTER(&consoles, c, s, next);
|
||||
} else {
|
||||
s->index = c->index;
|
||||
QTAILQ_INSERT_BEFORE(c, s, next);
|
||||
/* renumber text consoles */
|
||||
for (i = s->index + 1; c != NULL; c = QTAILQ_NEXT(c, next), i++) {
|
||||
c->index = i;
|
||||
}
|
||||
}
|
||||
s->index = i;
|
||||
consoles[i] = s;
|
||||
nb_consoles++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -1861,21 +1875,21 @@ static DisplayState *get_alloc_displaystate(void)
|
|||
DisplayState *init_displaystate(void)
|
||||
{
|
||||
gchar *name;
|
||||
int i;
|
||||
QemuConsole *con;
|
||||
|
||||
get_alloc_displaystate();
|
||||
for (i = 0; i < nb_consoles; i++) {
|
||||
if (consoles[i]->console_type != GRAPHIC_CONSOLE &&
|
||||
consoles[i]->ds == NULL) {
|
||||
text_console_do_init(consoles[i]->chr, display_state);
|
||||
QTAILQ_FOREACH(con, &consoles, next) {
|
||||
if (con->console_type != GRAPHIC_CONSOLE &&
|
||||
con->ds == NULL) {
|
||||
text_console_do_init(con->chr, display_state);
|
||||
}
|
||||
|
||||
/* Hook up into the qom tree here (not in new_console()), once
|
||||
* all QemuConsoles are created and the order / numbering
|
||||
* doesn't change any more */
|
||||
name = g_strdup_printf("console[%d]", i);
|
||||
name = g_strdup_printf("console[%d]", con->index);
|
||||
object_property_add_child(container_get(object_get_root(), "/backend"),
|
||||
name, OBJECT(consoles[i]), &error_abort);
|
||||
name, OBJECT(con), &error_abort);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
|
@ -1957,33 +1971,34 @@ void graphic_console_close(QemuConsole *con)
|
|||
|
||||
QemuConsole *qemu_console_lookup_by_index(unsigned int index)
|
||||
{
|
||||
if (index >= nb_consoles) {
|
||||
return NULL;
|
||||
QemuConsole *con;
|
||||
|
||||
QTAILQ_FOREACH(con, &consoles, next) {
|
||||
if (con->index == index) {
|
||||
return con;
|
||||
}
|
||||
}
|
||||
return consoles[index];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
|
||||
{
|
||||
QemuConsole *con;
|
||||
Object *obj;
|
||||
uint32_t h;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nb_consoles; i++) {
|
||||
if (!consoles[i]) {
|
||||
continue;
|
||||
}
|
||||
obj = object_property_get_link(OBJECT(consoles[i]),
|
||||
QTAILQ_FOREACH(con, &consoles, next) {
|
||||
obj = object_property_get_link(OBJECT(con),
|
||||
"device", &error_abort);
|
||||
if (DEVICE(obj) != dev) {
|
||||
continue;
|
||||
}
|
||||
h = object_property_get_uint(OBJECT(consoles[i]),
|
||||
h = object_property_get_uint(OBJECT(con),
|
||||
"head", &error_abort);
|
||||
if (h != head) {
|
||||
continue;
|
||||
}
|
||||
return consoles[i];
|
||||
return con;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2013,22 +2028,19 @@ QemuConsole *qemu_console_lookup_by_device_name(const char *device_id,
|
|||
|
||||
QemuConsole *qemu_console_lookup_unused(void)
|
||||
{
|
||||
QemuConsole *con;
|
||||
Object *obj;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nb_consoles; i++) {
|
||||
if (!consoles[i]) {
|
||||
QTAILQ_FOREACH(con, &consoles, next) {
|
||||
if (con->hw_ops != &unused_ops) {
|
||||
continue;
|
||||
}
|
||||
if (consoles[i]->hw_ops != &unused_ops) {
|
||||
continue;
|
||||
}
|
||||
obj = object_property_get_link(OBJECT(consoles[i]),
|
||||
obj = object_property_get_link(OBJECT(con),
|
||||
"device", &error_abort);
|
||||
if (obj != NULL) {
|
||||
continue;
|
||||
}
|
||||
return consoles[i];
|
||||
return con;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2130,12 +2142,11 @@ static void text_console_update_cursor_timer(void)
|
|||
static void text_console_update_cursor(void *opaque)
|
||||
{
|
||||
QemuConsole *s;
|
||||
int i, count = 0;
|
||||
int count = 0;
|
||||
|
||||
cursor_visible_phase = !cursor_visible_phase;
|
||||
|
||||
for (i = 0; i < nb_consoles; i++) {
|
||||
s = consoles[i];
|
||||
QTAILQ_FOREACH(s, &consoles, next) {
|
||||
if (qemu_console_is_graphic(s) ||
|
||||
!qemu_console_is_visible(s)) {
|
||||
continue;
|
||||
|
|
60
ui/gtk.c
60
ui/gtk.c
|
@ -145,6 +145,7 @@
|
|||
#define GDK_KEY_2 GDK_2
|
||||
#define GDK_KEY_f GDK_f
|
||||
#define GDK_KEY_g GDK_g
|
||||
#define GDK_KEY_m GDK_m
|
||||
#define GDK_KEY_q GDK_q
|
||||
#define GDK_KEY_plus GDK_plus
|
||||
#define GDK_KEY_equal GDK_equal
|
||||
|
@ -208,6 +209,7 @@ struct GtkDisplayState {
|
|||
|
||||
GtkWidget *show_tabs_item;
|
||||
GtkWidget *untabify_item;
|
||||
GtkWidget *show_menubar_item;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *notebook;
|
||||
|
@ -1387,6 +1389,30 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque)
|
||||
{
|
||||
GtkDisplayState *s = opaque;
|
||||
VirtualConsole *vc = gd_vc_find_current(s);
|
||||
|
||||
if (s->full_screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gtk_check_menu_item_get_active(
|
||||
GTK_CHECK_MENU_ITEM(s->show_menubar_item))) {
|
||||
gtk_widget_show(s->menu_bar);
|
||||
} else {
|
||||
gtk_widget_hide(s->menu_bar);
|
||||
}
|
||||
gd_update_windowsize(vc);
|
||||
}
|
||||
|
||||
static void gd_accel_show_menubar(void *opaque)
|
||||
{
|
||||
GtkDisplayState *s = opaque;
|
||||
gtk_menu_item_activate(GTK_MENU_ITEM(s->show_menubar_item));
|
||||
}
|
||||
|
||||
static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
|
||||
{
|
||||
GtkDisplayState *s = opaque;
|
||||
|
@ -1403,7 +1429,10 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
|
|||
} else {
|
||||
gtk_window_unfullscreen(GTK_WINDOW(s->window));
|
||||
gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s);
|
||||
gtk_widget_show(s->menu_bar);
|
||||
if (gtk_check_menu_item_get_active(
|
||||
GTK_CHECK_MENU_ITEM(s->show_menubar_item))) {
|
||||
gtk_widget_show(s->menu_bar);
|
||||
}
|
||||
s->full_screen = FALSE;
|
||||
if (vc->type == GD_VC_GFX) {
|
||||
vc->gfx.scale_x = 1.0;
|
||||
|
@ -2036,6 +2065,8 @@ static void gd_connect_signals(GtkDisplayState *s)
|
|||
G_CALLBACK(gd_menu_show_tabs), s);
|
||||
g_signal_connect(s->untabify_item, "activate",
|
||||
G_CALLBACK(gd_menu_untabify), s);
|
||||
g_signal_connect(s->show_menubar_item, "activate",
|
||||
G_CALLBACK(gd_menu_show_menubar), s);
|
||||
|
||||
g_signal_connect(s->window, "delete-event",
|
||||
G_CALLBACK(gd_window_close), s);
|
||||
|
@ -2272,11 +2303,26 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
|
|||
s->untabify_item = gtk_menu_item_new_with_mnemonic(_("Detach Tab"));
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->untabify_item);
|
||||
|
||||
s->show_menubar_item = gtk_check_menu_item_new_with_mnemonic(
|
||||
_("Show Menubar"));
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->show_menubar_item),
|
||||
TRUE);
|
||||
gtk_accel_group_connect(s->accel_group, GDK_KEY_m, HOTKEY_MODIFIERS, 0,
|
||||
g_cclosure_new_swap(G_CALLBACK(gd_accel_show_menubar), s, NULL));
|
||||
#if GTK_CHECK_VERSION(3, 8, 0)
|
||||
gtk_accel_label_set_accel(
|
||||
GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->show_menubar_item))),
|
||||
GDK_KEY_m, HOTKEY_MODIFIERS);
|
||||
#endif
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->show_menubar_item);
|
||||
|
||||
return view_menu;
|
||||
}
|
||||
|
||||
static void gd_create_menus(GtkDisplayState *s)
|
||||
{
|
||||
GtkSettings *settings;
|
||||
|
||||
s->accel_group = gtk_accel_group_new();
|
||||
s->machine_menu = gd_create_menu_machine(s);
|
||||
s->view_menu = gd_create_menu_view(s);
|
||||
|
@ -2292,6 +2338,10 @@ static void gd_create_menus(GtkDisplayState *s)
|
|||
|
||||
g_object_set_data(G_OBJECT(s->window), "accel_group", s->accel_group);
|
||||
gtk_window_add_accel_group(GTK_WINDOW(s->window), s->accel_group);
|
||||
|
||||
/* Disable the default "F10" menu shortcut. */
|
||||
settings = gtk_widget_get_settings(s->window);
|
||||
g_object_set(G_OBJECT(settings), "gtk-menu-bar-accel", "", NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2434,13 +2484,17 @@ static void early_gtk_display_init(DisplayOptions *opts)
|
|||
}
|
||||
|
||||
assert(opts->type == DISPLAY_TYPE_GTK);
|
||||
if (opts->has_gl && opts->gl) {
|
||||
if (opts->has_gl && opts->gl != DISPLAYGL_MODE_OFF) {
|
||||
if (opts->gl == DISPLAYGL_MODE_ES) {
|
||||
error_report("gtk: opengl es not supported");
|
||||
return;
|
||||
}
|
||||
#if defined(CONFIG_OPENGL)
|
||||
#if defined(CONFIG_GTK_GL) && defined(GDK_WINDOWING_WAYLAND)
|
||||
if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
||||
gtk_use_gl_area = true;
|
||||
gtk_gl_area_init();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
gtk_egl_init();
|
||||
|
|
|
@ -804,7 +804,6 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
|
|||
return;
|
||||
}
|
||||
sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
|
||||
sdl2_console->opts = o;
|
||||
for (i = 0; i < sdl2_num_outputs; i++) {
|
||||
QemuConsole *con = qemu_console_lookup_by_index(i);
|
||||
assert(con != NULL);
|
||||
|
@ -812,6 +811,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
|
|||
sdl2_console[i].hidden = true;
|
||||
}
|
||||
sdl2_console[i].idx = i;
|
||||
sdl2_console[i].opts = o;
|
||||
#ifdef CONFIG_OPENGL
|
||||
sdl2_console[i].opengl = display_opengl;
|
||||
sdl2_console[i].dcl.ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops;
|
||||
|
|
|
@ -82,6 +82,7 @@ VncJob *vnc_job_new(VncState *vs)
|
|||
{
|
||||
VncJob *job = g_new0(VncJob, 1);
|
||||
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
job->vs = vs;
|
||||
vnc_lock_queue(queue);
|
||||
QLIST_INIT(&job->rectangles);
|
||||
|
@ -214,6 +215,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
|
|||
/* Here job can only be NULL if queue->exit is true */
|
||||
job = QTAILQ_FIRST(&queue->jobs);
|
||||
vnc_unlock_queue(queue);
|
||||
assert(job->vs->magic == VNC_MAGIC);
|
||||
|
||||
if (queue->exit) {
|
||||
return -1;
|
||||
|
@ -236,6 +238,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
|
|||
|
||||
/* Make a local copy of vs and switch output buffers */
|
||||
vnc_async_encoding_start(job->vs, &vs);
|
||||
vs.magic = VNC_MAGIC;
|
||||
|
||||
/* Start sending rectangles */
|
||||
n_rectangles = 0;
|
||||
|
@ -289,6 +292,7 @@ disconnected:
|
|||
vnc_unlock_queue(queue);
|
||||
qemu_cond_broadcast(&queue->cond);
|
||||
g_free(job);
|
||||
vs.magic = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
10
ui/vnc.c
10
ui/vnc.c
|
@ -1138,6 +1138,7 @@ static void audio_capture_notify(void *opaque, audcnotification_e cmd)
|
|||
{
|
||||
VncState *vs = opaque;
|
||||
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
switch (cmd) {
|
||||
case AUD_CNOTIFY_DISABLE:
|
||||
vnc_lock_output(vs);
|
||||
|
@ -1167,6 +1168,7 @@ static void audio_capture(void *opaque, void *buf, int size)
|
|||
{
|
||||
VncState *vs = opaque;
|
||||
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
vnc_lock_output(vs);
|
||||
if (vs->output.offset < vs->throttle_output_offset) {
|
||||
vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
|
||||
|
@ -1275,6 +1277,7 @@ void vnc_disconnect_finish(VncState *vs)
|
|||
vs->ioc = NULL;
|
||||
object_unref(OBJECT(vs->sioc));
|
||||
vs->sioc = NULL;
|
||||
vs->magic = 0;
|
||||
g_free(vs);
|
||||
}
|
||||
|
||||
|
@ -1414,7 +1417,7 @@ static void vnc_client_write_locked(VncState *vs)
|
|||
|
||||
static void vnc_client_write(VncState *vs)
|
||||
{
|
||||
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
vnc_lock_output(vs);
|
||||
if (vs->output.offset) {
|
||||
vnc_client_write_locked(vs);
|
||||
|
@ -1487,6 +1490,7 @@ static void vnc_jobs_bh(void *opaque)
|
|||
{
|
||||
VncState *vs = opaque;
|
||||
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
vnc_jobs_consume_buffer(vs);
|
||||
}
|
||||
|
||||
|
@ -1537,6 +1541,8 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,
|
|||
GIOCondition condition, void *opaque)
|
||||
{
|
||||
VncState *vs = opaque;
|
||||
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
if (condition & G_IO_IN) {
|
||||
if (vnc_client_read(vs) < 0) {
|
||||
/* vs is free()ed here */
|
||||
|
@ -1568,6 +1574,7 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,
|
|||
|
||||
void vnc_write(VncState *vs, const void *data, size_t len)
|
||||
{
|
||||
assert(vs->magic == VNC_MAGIC);
|
||||
if (vs->disconnecting) {
|
||||
return;
|
||||
}
|
||||
|
@ -3064,6 +3071,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
|
|||
int i;
|
||||
|
||||
trace_vnc_client_connect(vs, sioc);
|
||||
vs->magic = VNC_MAGIC;
|
||||
vs->sioc = sioc;
|
||||
object_ref(OBJECT(vs->sioc));
|
||||
vs->ioc = QIO_CHANNEL(sioc);
|
||||
|
|
3
ui/vnc.h
3
ui/vnc.h
|
@ -255,8 +255,11 @@ typedef enum {
|
|||
VNC_STATE_UPDATE_FORCE,
|
||||
} VncStateUpdate;
|
||||
|
||||
#define VNC_MAGIC ((uint64_t)0x05b3f069b3d204bb)
|
||||
|
||||
struct VncState
|
||||
{
|
||||
uint64_t magic;
|
||||
QIOChannelSocket *sioc; /* The underlying socket */
|
||||
QIOChannel *ioc; /* The channel currently used for I/O */
|
||||
guint ioc_tag;
|
||||
|
|
76
vl.c
76
vl.c
|
@ -120,12 +120,14 @@ int main(int argc, char **argv)
|
|||
#include "ui/qemu-spice.h"
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/clone-visitor.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "crypto/init.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qapi/qapi-events-run-state.h"
|
||||
#include "qapi/qapi-visit-block-core.h"
|
||||
#include "qapi/qapi-visit-ui.h"
|
||||
#include "qapi/qapi-commands-block-core.h"
|
||||
#include "qapi/qapi-commands-misc.h"
|
||||
#include "qapi/qapi-commands-run-state.h"
|
||||
|
@ -2088,11 +2090,40 @@ static void select_vgahw(const char *p)
|
|||
}
|
||||
}
|
||||
|
||||
static void parse_display_qapi(const char *optarg)
|
||||
{
|
||||
Error *err = NULL;
|
||||
DisplayOptions *opts;
|
||||
Visitor *v;
|
||||
|
||||
v = qobject_input_visitor_new_str(optarg, "type", &err);
|
||||
if (!v) {
|
||||
error_report_err(err);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
visit_type_DisplayOptions(v, NULL, &opts, &error_fatal);
|
||||
QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts);
|
||||
|
||||
qapi_free_DisplayOptions(opts);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
static void parse_display(const char *p)
|
||||
{
|
||||
const char *opts;
|
||||
|
||||
if (strstart(p, "sdl", &opts)) {
|
||||
/*
|
||||
* sdl DisplayType needs hand-crafted parser instead of
|
||||
* parse_display_qapi() due to some options not in
|
||||
* DisplayOptions, specifically:
|
||||
* - frame
|
||||
* Already deprecated.
|
||||
* - ctrl_grab + alt_grab
|
||||
* Not clear yet what happens to them long-term. Should
|
||||
* replaced by something better or deprecated and dropped.
|
||||
*/
|
||||
dpy.type = DISPLAY_TYPE_SDL;
|
||||
while (*opts) {
|
||||
const char *nextopt;
|
||||
|
@ -2158,53 +2189,18 @@ static void parse_display(const char *p)
|
|||
opts = nextopt;
|
||||
}
|
||||
} else if (strstart(p, "vnc", &opts)) {
|
||||
/*
|
||||
* vnc isn't a (local) DisplayType but a protocol for remote
|
||||
* display access.
|
||||
*/
|
||||
if (*opts == '=') {
|
||||
vnc_parse(opts + 1, &error_fatal);
|
||||
} else {
|
||||
error_report("VNC requires a display argument vnc=<display>");
|
||||
exit(1);
|
||||
}
|
||||
} else if (strstart(p, "egl-headless", &opts)) {
|
||||
dpy.type = DISPLAY_TYPE_EGL_HEADLESS;
|
||||
} else if (strstart(p, "curses", &opts)) {
|
||||
dpy.type = DISPLAY_TYPE_CURSES;
|
||||
} else if (strstart(p, "gtk", &opts)) {
|
||||
dpy.type = DISPLAY_TYPE_GTK;
|
||||
while (*opts) {
|
||||
const char *nextopt;
|
||||
|
||||
if (strstart(opts, ",grab_on_hover=", &nextopt)) {
|
||||
opts = nextopt;
|
||||
dpy.u.gtk.has_grab_on_hover = true;
|
||||
if (strstart(opts, "on", &nextopt)) {
|
||||
dpy.u.gtk.grab_on_hover = true;
|
||||
} else if (strstart(opts, "off", &nextopt)) {
|
||||
dpy.u.gtk.grab_on_hover = false;
|
||||
} else {
|
||||
goto invalid_gtk_args;
|
||||
}
|
||||
} else if (strstart(opts, ",gl=", &nextopt)) {
|
||||
opts = nextopt;
|
||||
dpy.has_gl = true;
|
||||
if (strstart(opts, "on", &nextopt)) {
|
||||
dpy.gl = DISPLAYGL_MODE_ON;
|
||||
} else if (strstart(opts, "off", &nextopt)) {
|
||||
dpy.gl = DISPLAYGL_MODE_OFF;
|
||||
} else {
|
||||
goto invalid_gtk_args;
|
||||
}
|
||||
} else {
|
||||
invalid_gtk_args:
|
||||
error_report("invalid GTK option string");
|
||||
exit(1);
|
||||
}
|
||||
opts = nextopt;
|
||||
}
|
||||
} else if (strstart(p, "none", &opts)) {
|
||||
dpy.type = DISPLAY_TYPE_NONE;
|
||||
} else {
|
||||
error_report("unknown display type");
|
||||
exit(1);
|
||||
parse_display_qapi(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue