* [PATCH RFC v4 0/1] the org.qemu.Display1.UIInfo interface design
@ 2026-08-30 5:46 Chengyang Zhu
2026-08-30 5:46 ` [PATCH RFC v4 1/1] ui/dbus: add org.qemu.Display1.UIInfo interface Chengyang Zhu
0 siblings, 1 reply; 4+ messages in thread
From: Chengyang Zhu @ 2026-08-30 5:46 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, Chengyang Zhu
Currently, the `SetUIInfo` method cannot set a refresh rate.
Simply adding a refresh_rate argument would break the method signature.
This patch adds the UIInfo interface containing
* property `Supported` indicating whether console UI info is supported.
* the method `Apply` taking a dictionary as input.
* the method `Get` returning the current UI info as a dictionary.
Changes since v3:
* switched back to the dictionary approach.
This patch needs further discussion on:
* Updated/Changed signal as mentioned before in the v3 email thread.
* necessary test suite to prevent dictionary schema deviating from QemuUIInfo.
Test results:
* qemu:qtest-x86_64/dbus-display-test passed
* qemu:qtest-x86_64/dbus-vmstate-test passed
* qemu:qtest-x86_64/dbus-vnc-test SKIP
* manually created a virtual machine
and successfully set its refresh rate and resolution via `Apply`
Chengyang Zhu (1):
ui/dbus: add org.qemu.Display1.UIInfo interface
ui/dbus-console.c | 106 +++++++++++++++++++++++++++++++++++++++++++
ui/dbus-display1.xml | 50 ++++++++++++++++++++
2 files changed, 156 insertions(+)
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH RFC v4 1/1] ui/dbus: add org.qemu.Display1.UIInfo interface 2026-08-30 5:46 [PATCH RFC v4 0/1] the org.qemu.Display1.UIInfo interface design Chengyang Zhu @ 2026-08-30 5:46 ` Chengyang Zhu 2026-08-30 11:48 ` Marc-André Lureau 0 siblings, 1 reply; 4+ messages in thread From: Chengyang Zhu @ 2026-08-30 5:46 UTC (permalink / raw) To: qemu-devel; +Cc: marcandre.lureau, Chengyang Zhu Currently, the SetUIInfo method cannot set a refresh rate. Simply adding a refresh_rate argument would break the method signature. This patch adds the UIInfo interface containing * property `Supported` indicating whether console UI info is supported. * the method `Apply` taking a dictionary as input. * the method `Get` returning the current UI info as a dictionary. Signed-off-by: Chengyang Zhu <colazcyg@gmail.com> --- ui/dbus-console.c | 106 +++++++++++++++++++++++++++++++++++++++++++ ui/dbus-display1.xml | 50 ++++++++++++++++++++ 2 files changed, 156 insertions(+) diff --git a/ui/dbus-console.c b/ui/dbus-console.c index e1ac06814b..947c3b3a54 100644 --- a/ui/dbus-console.c +++ b/ui/dbus-console.c @@ -55,6 +55,8 @@ struct _DBusDisplayConsole { guint last_x; guint last_y; Notifier mouse_mode_notifier; + + QemuDBusDisplay1UIInfo *iface_ui_info; }; G_DEFINE_TYPE(DBusDisplayConsole, @@ -155,6 +157,7 @@ dbus_display_console_dispose(GObject *object) qemu_input_led_notifier_remove(&ddc->led_notifier); qemu_console_unregister_listener(&ddc->dcl); qemu_remove_mouse_mode_change_notifier(&ddc->mouse_mode_notifier); + g_clear_object(&ddc->iface_ui_info); g_clear_object(&ddc->iface_touch); g_clear_object(&ddc->iface_mouse); g_clear_object(&ddc->iface_kbd); @@ -528,6 +531,98 @@ dbus_mouse_mode_change(Notifier *notify, void *data) dbus_mouse_update_is_absolute(ddc); } +static gboolean +dbus_ui_info_get(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation) +{ + QemuUIInfo ui_info; + GVariantDict dict; + + if (!qemu_console_ui_info_supported(ddc->dcl.con)) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_UNSUPPORTED, + "UIInfo is not supported"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + ui_info = *qemu_console_get_ui_info(ddc->dcl.con); + g_variant_dict_init(&dict, NULL); + + g_variant_dict_insert(&dict, "width_mm", "q", ui_info.width_mm); + g_variant_dict_insert(&dict, "height_mm", "q", ui_info.height_mm); + g_variant_dict_insert(&dict, "xoff", "i", ui_info.xoff); + g_variant_dict_insert(&dict, "yoff", "i", ui_info.yoff); + g_variant_dict_insert(&dict, "width", "u", ui_info.width); + g_variant_dict_insert(&dict, "height", "u", ui_info.height); + g_variant_dict_insert(&dict, "refresh_rate", "u", ui_info.refresh_rate); + + qemu_dbus_display1_uiinfo_complete_get(ddc->iface_ui_info, invocation, + g_variant_dict_end(&dict)); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static bool +dbus_ui_info_apply_lookup(GDBusMethodInvocation *invocation, + GVariantDict *dict, + const gchar *key, + const gchar *fmt_str, + void *res) +{ + if (g_variant_dict_contains(dict, key) && + !g_variant_dict_lookup(dict, key, fmt_str, res)) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_INVALID, + "%s must have D-Bus signature %s", + key, fmt_str); + return false; + } + return true; +} + +static gboolean +dbus_ui_info_apply(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + GVariant *arg_ui_info) +{ + QemuUIInfo ui_info; + g_auto(GVariantDict) dict = G_VARIANT_DICT_INIT(arg_ui_info); + + if (!qemu_console_ui_info_supported(ddc->dcl.con)) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_UNSUPPORTED, + "UIInfo is not supported"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + ui_info = *qemu_console_get_ui_info(ddc->dcl.con); + + if (!dbus_ui_info_apply_lookup(invocation, &dict, "width_mm", "q", + &ui_info.width_mm) || + !dbus_ui_info_apply_lookup(invocation, &dict, "height_mm", "q", + &ui_info.height_mm) || + !dbus_ui_info_apply_lookup(invocation, &dict, "xoff", "i", + &ui_info.xoff) || + !dbus_ui_info_apply_lookup(invocation, &dict, "yoff", "i", + &ui_info.yoff) || + !dbus_ui_info_apply_lookup(invocation, &dict, "width", "u", + &ui_info.width) || + !dbus_ui_info_apply_lookup(invocation, &dict, "height", "u", + &ui_info.height) || + !dbus_ui_info_apply_lookup(invocation, &dict, "refresh_rate", "u", + &ui_info.refresh_rate)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } + + qemu_console_set_ui_info(ddc->dcl.con, &ui_info, false); + qemu_dbus_display1_uiinfo_complete_apply(ddc->iface_ui_info, invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + int dbus_display_console_get_index(DBusDisplayConsole *ddc) { return qemu_console_get_index(ddc->dcl.con); @@ -550,6 +645,7 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con) "org.qemu.Display1.Keyboard", "org.qemu.Display1.Mouse", "org.qemu.Display1.MultiTouch", + "org.qemu.Display1.UIInfo", NULL }; @@ -626,5 +722,15 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con) qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier); dbus_mouse_update_is_absolute(ddc); + ddc->iface_ui_info = qemu_dbus_display1_uiinfo_skeleton_new(); + qemu_dbus_display1_uiinfo_set_supported(ddc->iface_ui_info, + qemu_console_ui_info_supported(ddc->dcl.con)); + g_object_connect(ddc->iface_ui_info, + "swapped-signal::handle-get", dbus_ui_info_get, ddc, + "swapped-signal::handle-apply", dbus_ui_info_apply, ddc, + NULL); + g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(ddc), + G_DBUS_INTERFACE_SKELETON(ddc->iface_ui_info)); + return ddc; } diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml index d96bae2ed6..26483edc37 100644 --- a/ui/dbus-display1.xml +++ b/ui/dbus-display1.xml @@ -1159,4 +1159,54 @@ --> <property name="Encoding" type="s" access="read"/> </interface> + + <!-- + org.qemu.Display1.UIInfo: + + This interface is implemented on + ``/org/qemu/Display1/Console_$id`` (see + :dbus:iface:`~org.qemu.Display1.Console`). + --> + <interface name="org.qemu.Display1.UIInfo"> + <!-- + Supported: + + Whether console UI info is supported. + --> + <property name="Supported" type="b" access="read"/> + + <!-- + Get: + @ui_info: a dictionary of current UI info properties. + + Return the properties of the current console display. + + - ``width_mm`` (q): the physical display width in millimeters. + - ``height_mm`` (q): the physical display height in millimeters. + - ``xoff`` (i): the horizontal offset in pixels. + - ``yoff`` (i): the vertical offset in pixels. + - ``width`` (u): the console width in pixels. + - ``height`` (u): the console height in pixels. + - ``refresh_rate`` (u): the display refresh rate in millihertz. + --> + <method name="Get"> + <arg name="ui_info" type="a{sv}" direction="out"/> + </method> + + <!-- + Apply: + @ui_info: a dictionary of new UI info properties. + + Apply the properties to the console display. + The dictionary schema of ``Apply`` is a subset of that of ``Get``. + + The properties will be merged with existing values. + Extra keys will be ignored. + The invocation will fail if any key has the wrong type, + leaving the UI info unchanged. + --> + <method name="Apply"> + <arg name="ui_info" type="a{sv}" direction="in"/> + </method> + </interface> </node> -- 2.55.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH RFC v4 1/1] ui/dbus: add org.qemu.Display1.UIInfo interface 2026-08-30 5:46 ` [PATCH RFC v4 1/1] ui/dbus: add org.qemu.Display1.UIInfo interface Chengyang Zhu @ 2026-08-30 11:48 ` Marc-André Lureau 2026-08-31 3:33 ` colazcy 0 siblings, 1 reply; 4+ messages in thread From: Marc-André Lureau @ 2026-08-30 11:48 UTC (permalink / raw) To: Chengyang Zhu; +Cc: qemu-devel Hi On Sun, Aug 30, 2026 at 9:47 AM Chengyang Zhu <colazcyg@gmail.com> wrote: > > Currently, the SetUIInfo method cannot set a refresh rate. > Simply adding a refresh_rate argument would break the method signature. > > This patch adds the UIInfo interface containing > * property `Supported` indicating whether console UI info is supported. > * the method `Apply` taking a dictionary as input. > * the method `Get` returning the current UI info as a dictionary. > > Signed-off-by: Chengyang Zhu <colazcyg@gmail.com> > --- > ui/dbus-console.c | 106 +++++++++++++++++++++++++++++++++++++++++++ > ui/dbus-display1.xml | 50 ++++++++++++++++++++ > 2 files changed, 156 insertions(+) > > diff --git a/ui/dbus-console.c b/ui/dbus-console.c > index e1ac06814b..947c3b3a54 100644 > --- a/ui/dbus-console.c > +++ b/ui/dbus-console.c > @@ -55,6 +55,8 @@ struct _DBusDisplayConsole { > guint last_x; > guint last_y; > Notifier mouse_mode_notifier; > + > + QemuDBusDisplay1UIInfo *iface_ui_info; > }; > > G_DEFINE_TYPE(DBusDisplayConsole, > @@ -155,6 +157,7 @@ dbus_display_console_dispose(GObject *object) > qemu_input_led_notifier_remove(&ddc->led_notifier); > qemu_console_unregister_listener(&ddc->dcl); > qemu_remove_mouse_mode_change_notifier(&ddc->mouse_mode_notifier); > + g_clear_object(&ddc->iface_ui_info); > g_clear_object(&ddc->iface_touch); > g_clear_object(&ddc->iface_mouse); > g_clear_object(&ddc->iface_kbd); > @@ -528,6 +531,98 @@ dbus_mouse_mode_change(Notifier *notify, void *data) > dbus_mouse_update_is_absolute(ddc); > } > > +static gboolean > +dbus_ui_info_get(DBusDisplayConsole *ddc, > + GDBusMethodInvocation *invocation) > +{ > + QemuUIInfo ui_info; > + GVariantDict dict; > + > + if (!qemu_console_ui_info_supported(ddc->dcl.con)) { > + g_dbus_method_invocation_return_error(invocation, > + DBUS_DISPLAY_ERROR, > + DBUS_DISPLAY_ERROR_UNSUPPORTED, > + "UIInfo is not supported"); > + return DBUS_METHOD_INVOCATION_HANDLED; > + } > + > + ui_info = *qemu_console_get_ui_info(ddc->dcl.con); > + g_variant_dict_init(&dict, NULL); > + > + g_variant_dict_insert(&dict, "width_mm", "q", ui_info.width_mm); > + g_variant_dict_insert(&dict, "height_mm", "q", ui_info.height_mm); > + g_variant_dict_insert(&dict, "xoff", "i", ui_info.xoff); > + g_variant_dict_insert(&dict, "yoff", "i", ui_info.yoff); > + g_variant_dict_insert(&dict, "width", "u", ui_info.width); > + g_variant_dict_insert(&dict, "height", "u", ui_info.height); > + g_variant_dict_insert(&dict, "refresh_rate", "u", ui_info.refresh_rate); > + > + qemu_dbus_display1_uiinfo_complete_get(ddc->iface_ui_info, invocation, > + g_variant_dict_end(&dict)); > + > + return DBUS_METHOD_INVOCATION_HANDLED; > +} > + > +static bool > +dbus_ui_info_apply_lookup(GDBusMethodInvocation *invocation, > + GVariantDict *dict, > + const gchar *key, > + const gchar *fmt_str, > + void *res) > +{ > + if (g_variant_dict_contains(dict, key) && > + !g_variant_dict_lookup(dict, key, fmt_str, res)) { > + g_dbus_method_invocation_return_error(invocation, > + DBUS_DISPLAY_ERROR, > + DBUS_DISPLAY_ERROR_INVALID, > + "%s must have D-Bus signature %s", > + key, fmt_str); > + return false; > + } > + return true; A bit surprising that the function returns true for unknown/invalid keys, but ok > +} > + > +static gboolean > +dbus_ui_info_apply(DBusDisplayConsole *ddc, > + GDBusMethodInvocation *invocation, > + GVariant *arg_ui_info) > +{ > + QemuUIInfo ui_info; > + g_auto(GVariantDict) dict = G_VARIANT_DICT_INIT(arg_ui_info); > + > + if (!qemu_console_ui_info_supported(ddc->dcl.con)) { > + g_dbus_method_invocation_return_error(invocation, > + DBUS_DISPLAY_ERROR, > + DBUS_DISPLAY_ERROR_UNSUPPORTED, > + "UIInfo is not supported"); > + return DBUS_METHOD_INVOCATION_HANDLED; > + } > + > + ui_info = *qemu_console_get_ui_info(ddc->dcl.con); > + > + if (!dbus_ui_info_apply_lookup(invocation, &dict, "width_mm", "q", > + &ui_info.width_mm) || > + !dbus_ui_info_apply_lookup(invocation, &dict, "height_mm", "q", > + &ui_info.height_mm) || > + !dbus_ui_info_apply_lookup(invocation, &dict, "xoff", "i", > + &ui_info.xoff) || > + !dbus_ui_info_apply_lookup(invocation, &dict, "yoff", "i", > + &ui_info.yoff) || > + !dbus_ui_info_apply_lookup(invocation, &dict, "width", "u", > + &ui_info.width) || > + !dbus_ui_info_apply_lookup(invocation, &dict, "height", "u", > + &ui_info.height) || > + !dbus_ui_info_apply_lookup(invocation, &dict, "refresh_rate", "u", > + &ui_info.refresh_rate)) { > + return DBUS_METHOD_INVOCATION_HANDLED; > + } > + > + qemu_console_set_ui_info(ddc->dcl.con, &ui_info, false); > + qemu_dbus_display1_uiinfo_complete_apply(ddc->iface_ui_info, invocation); > + > + return DBUS_METHOD_INVOCATION_HANDLED; > +} > + > int dbus_display_console_get_index(DBusDisplayConsole *ddc) > { > return qemu_console_get_index(ddc->dcl.con); > @@ -550,6 +645,7 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con) > "org.qemu.Display1.Keyboard", > "org.qemu.Display1.Mouse", > "org.qemu.Display1.MultiTouch", > + "org.qemu.Display1.UIInfo", > NULL > }; > > @@ -626,5 +722,15 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con) > qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier); > dbus_mouse_update_is_absolute(ddc); > > + ddc->iface_ui_info = qemu_dbus_display1_uiinfo_skeleton_new(); > + qemu_dbus_display1_uiinfo_set_supported(ddc->iface_ui_info, > + qemu_console_ui_info_supported(ddc->dcl.con)); > + g_object_connect(ddc->iface_ui_info, > + "swapped-signal::handle-get", dbus_ui_info_get, ddc, > + "swapped-signal::handle-apply", dbus_ui_info_apply, ddc, > + NULL); > + g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(ddc), > + G_DBUS_INTERFACE_SKELETON(ddc->iface_ui_info)); > + > return ddc; > } > diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml > index d96bae2ed6..26483edc37 100644 > --- a/ui/dbus-display1.xml > +++ b/ui/dbus-display1.xml > @@ -1159,4 +1159,54 @@ > --> > <property name="Encoding" type="s" access="read"/> > </interface> > + > + <!-- > + org.qemu.Display1.UIInfo: > + > + This interface is implemented on > + ``/org/qemu/Display1/Console_$id`` (see > + :dbus:iface:`~org.qemu.Display1.Console`). > + --> > + <interface name="org.qemu.Display1.UIInfo"> > + <!-- > + Supported: > + > + Whether console UI info is supported. > + --> > + <property name="Supported" type="b" access="read"/> > + > + <!-- > + Get: > + @ui_info: a dictionary of current UI info properties. > + > + Return the properties of the current console display. > + > + - ``width_mm`` (q): the physical display width in millimeters. > + - ``height_mm`` (q): the physical display height in millimeters. > + - ``xoff`` (i): the horizontal offset in pixels. > + - ``yoff`` (i): the vertical offset in pixels. > + - ``width`` (u): the console width in pixels. > + - ``height`` (u): the console height in pixels. > + - ``refresh_rate`` (u): the display refresh rate in millihertz. > + --> > + <method name="Get"> > + <arg name="ui_info" type="a{sv}" direction="out"/> > + </method> > + > + <!-- > + Apply: > + @ui_info: a dictionary of new UI info properties. > + > + Apply the properties to the console display. > + The dictionary schema of ``Apply`` is a subset of that of ``Get``. > + > + The properties will be merged with existing values. > + Extra keys will be ignored. > + The invocation will fail if any key has the wrong type, > + leaving the UI info unchanged. > + --> > + <method name="Apply"> > + <arg name="ui_info" type="a{sv}" direction="in"/> > + </method> > + </interface> > </node> > -- > 2.55.0 > > lgtm, I can pick this patch unless you want to send a non-rfc version before ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH RFC v4 1/1] ui/dbus: add org.qemu.Display1.UIInfo interface 2026-08-30 11:48 ` Marc-André Lureau @ 2026-08-31 3:33 ` colazcy 0 siblings, 0 replies; 4+ messages in thread From: colazcy @ 2026-08-31 3:33 UTC (permalink / raw) To: Marc-André Lureau; +Cc: qemu-devel Hi On 8/30/26 7:48 PM, Marc-André Lureau wrote: >> +static bool >> +dbus_ui_info_apply_lookup(GDBusMethodInvocation *invocation, >> + GVariantDict *dict, >> + const gchar *key, >> + const gchar *fmt_str, >> + void *res) >> +{ >> + if (g_variant_dict_contains(dict, key) && >> + !g_variant_dict_lookup(dict, key, fmt_str, res)) { >> + g_dbus_method_invocation_return_error(invocation, >> + DBUS_DISPLAY_ERROR, >> + DBUS_DISPLAY_ERROR_INVALID, >> + "%s must have D-Bus signature %s", >> + key, fmt_str); >> + return false; >> + } >> + return true; > A bit surprising that the function returns true for unknown/invalid keys, but ok The function will: * return false for invalid key-value pairs (values have the wrong type signature). * return true otherwise. So `dbus_ui_info_apply` will ignore extra keys, report errors for invalid key-value pairs and accept a dictionary whose keys are a subset of the schema keys. This behavior is expected. > lgtm, I can pick this patch unless you want to send a non-rfc version before Okay. This patch is my final version and you can pick it. Thanks for your guidance. ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-31 3:34 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-30 5:46 [PATCH RFC v4 0/1] the org.qemu.Display1.UIInfo interface design Chengyang Zhu 2026-08-30 5:46 ` [PATCH RFC v4 1/1] ui/dbus: add org.qemu.Display1.UIInfo interface Chengyang Zhu 2026-08-30 11:48 ` Marc-André Lureau 2026-08-31 3:33 ` colazcy
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.