mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
ui/dbus: handle console hotplug/unplug events
Subscribe to QemuConsoleEvent notifications to dynamically add and remove D-Bus display consoles. This mirrors the GTK backend's handling added in the previous commits. Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260623-b4-ui-v4-33-4656aec3398d@redhat.com>
This commit is contained in:
@@ -533,6 +533,11 @@ int dbus_display_console_get_index(DBusDisplayConsole *ddc)
|
||||
return qemu_console_get_index(ddc->dcl.con);
|
||||
}
|
||||
|
||||
QemuConsole *dbus_display_console_get_qemu_console(DBusDisplayConsole *ddc)
|
||||
{
|
||||
return ddc->dcl.con;
|
||||
}
|
||||
|
||||
DBusDisplayConsole *
|
||||
dbus_display_console_new(DBusDisplay *display, QemuConsole *con)
|
||||
{
|
||||
|
||||
95
ui/dbus.c
95
ui/dbus.c
@@ -142,6 +142,9 @@ dbus_display_finalize(Object *o)
|
||||
{
|
||||
DBusDisplay *dd = DBUS_DISPLAY(o);
|
||||
|
||||
if (dd->console_notifier.notify) {
|
||||
qemu_console_remove_notifier(&dd->console_notifier);
|
||||
}
|
||||
if (dd->notifier.notify) {
|
||||
dbus_display_notifier_remove(&dd->notifier);
|
||||
}
|
||||
@@ -164,14 +167,35 @@ dbus_display_finalize(Object *o)
|
||||
dbus_display = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
dbus_display_add_console(DBusDisplay *dd, int idx, Error **errp)
|
||||
static void
|
||||
dbus_update_console_ids(DBusDisplay *dd)
|
||||
{
|
||||
g_autoptr(GArray) arr = g_array_new(FALSE, FALSE, sizeof(guint32));
|
||||
|
||||
for (guint i = 0; i < dd->consoles->len; i++) {
|
||||
DBusDisplayConsole *ddc = g_ptr_array_index(dd->consoles, i);
|
||||
guint32 idx = dbus_display_console_get_index(ddc);
|
||||
g_array_append_val(arr, idx);
|
||||
}
|
||||
|
||||
g_object_set(dd->iface, "console-ids",
|
||||
g_variant_new_fixed_array(G_VARIANT_TYPE("u"),
|
||||
arr->data, arr->len,
|
||||
sizeof(guint32)),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
dbus_display_add_console(DBusDisplay *dd, QemuConsole *con, Error **errp)
|
||||
{
|
||||
QemuConsole *con;
|
||||
DBusDisplayConsole *dbus_console;
|
||||
|
||||
con = qemu_console_lookup_by_index(idx);
|
||||
assert(con);
|
||||
for (guint i = 0; i < dd->consoles->len; i++) {
|
||||
DBusDisplayConsole *ddc = g_ptr_array_index(dd->consoles, i);
|
||||
if (dbus_display_console_get_qemu_console(ddc) == con) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (qemu_console_is_graphic(con) &&
|
||||
dd->gl_mode != DISPLAY_GL_MODE_OFF) {
|
||||
@@ -179,20 +203,58 @@ dbus_display_add_console(DBusDisplay *dd, int idx, Error **errp)
|
||||
}
|
||||
|
||||
dbus_console = dbus_display_console_new(dd, con);
|
||||
g_ptr_array_insert(dd->consoles, idx, dbus_console);
|
||||
g_ptr_array_add(dd->consoles, dbus_console);
|
||||
g_dbus_object_manager_server_export(dd->server,
|
||||
G_DBUS_OBJECT_SKELETON(dbus_console));
|
||||
dbus_update_console_ids(dd);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_display_remove_console(DBusDisplay *dd, QemuConsole *con)
|
||||
{
|
||||
for (guint i = 0; i < dd->consoles->len; i++) {
|
||||
DBusDisplayConsole *ddc = g_ptr_array_index(dd->consoles, i);
|
||||
if (dbus_display_console_get_qemu_console(ddc) == con) {
|
||||
if (display_opengl) {
|
||||
qemu_console_set_display_gl_ctx(con, NULL);
|
||||
}
|
||||
g_dbus_object_manager_server_unexport(
|
||||
dd->server,
|
||||
g_dbus_object_get_object_path(G_DBUS_OBJECT(ddc)));
|
||||
g_ptr_array_remove_index(dd->consoles, i);
|
||||
dbus_update_console_ids(dd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_console_notify(Notifier *n, void *data)
|
||||
{
|
||||
DBusDisplay *dd = container_of(n, DBusDisplay, console_notifier);
|
||||
QemuConsoleEvent *event = data;
|
||||
|
||||
switch (event->type) {
|
||||
case QEMU_CONSOLE_ADDED: {
|
||||
Error *err = NULL;
|
||||
if (!dbus_display_add_console(dd, event->con, &err)) {
|
||||
error_report_err(err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEMU_CONSOLE_REMOVED:
|
||||
dbus_display_remove_console(dd, event->con);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_display_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
DBusDisplay *dd = DBUS_DISPLAY(uc);
|
||||
g_autoptr(GError) err = NULL;
|
||||
g_autofree char *uuid = qemu_uuid_unparse_strdup(&qemu_uuid);
|
||||
g_autoptr(GArray) consoles = NULL;
|
||||
GVariant *console_ids;
|
||||
int idx;
|
||||
|
||||
if (!object_resolve_path_type("", TYPE_DBUS_DISPLAY, NULL)) {
|
||||
@@ -233,27 +295,24 @@ dbus_display_complete(UserCreatable *uc, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
consoles = g_array_new(FALSE, FALSE, sizeof(guint32));
|
||||
for (idx = 0;; idx++) {
|
||||
if (!qemu_console_lookup_by_index(idx)) {
|
||||
QemuConsole *con = qemu_console_lookup_by_index(idx);
|
||||
if (!con) {
|
||||
break;
|
||||
}
|
||||
if (!dbus_display_add_console(dd, idx, errp)) {
|
||||
if (!dbus_display_add_console(dd, con, errp)) {
|
||||
return;
|
||||
}
|
||||
g_array_append_val(consoles, idx);
|
||||
}
|
||||
|
||||
console_ids = g_variant_new_from_data(
|
||||
G_VARIANT_TYPE("au"),
|
||||
consoles->data, consoles->len * sizeof(guint32), TRUE,
|
||||
(GDestroyNotify)g_array_unref, consoles);
|
||||
g_steal_pointer(&consoles);
|
||||
g_object_set(dd->iface,
|
||||
"name", qemu_name ?: "QEMU " QEMU_VERSION,
|
||||
"uuid", uuid,
|
||||
"console-ids", console_ids,
|
||||
NULL);
|
||||
dbus_update_console_ids(dd);
|
||||
|
||||
dd->console_notifier.notify = dbus_console_notify;
|
||||
qemu_console_add_notifier(&dd->console_notifier);
|
||||
|
||||
if (dd->bus) {
|
||||
g_dbus_object_manager_server_set_connection(dd->server, dd->bus);
|
||||
|
||||
@@ -60,6 +60,7 @@ struct DBusDisplay {
|
||||
DBusClipboardRequest clipboard_request[QEMU_CLIPBOARD_SELECTION__COUNT];
|
||||
|
||||
Notifier notifier;
|
||||
Notifier console_notifier;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -86,6 +87,8 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con);
|
||||
int
|
||||
dbus_display_console_get_index(DBusDisplayConsole *ddc);
|
||||
|
||||
QemuConsole *
|
||||
dbus_display_console_get_qemu_console(DBusDisplayConsole *ddc);
|
||||
|
||||
extern const DisplayChangeListenerOps dbus_console_dcl_ops;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user