* [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.