Introduce qemu_console_register_listener() which combines setting
dcl->con, dcl->ops and calling register_displaychangelistener() into a
single call. This removes repetitive boilerplate across all display
backends and makes it harder to forget setting one of the fields.
Also move the early-return check in unregister_displaychangelistener()
before the trace call, so that unregistering a never-registered listener
(e.g. on error paths) does not dereference a NULL ops pointer.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/ui/console.h | 6 ++++--
hw/display/qxl.c | 4 +---
ui/console.c | 11 ++++++++---
ui/curses.c | 9 +++------
ui/dbus-console.c | 6 ++----
ui/dbus-listener.c | 27 ++++++++-------------------
ui/egl-headless.c | 4 +---
ui/gtk.c | 10 ++++------
ui/sdl2.c | 8 +++-----
ui/spice-display.c | 8 +++-----
ui/vnc.c | 11 ++++-------
ui/cocoa.m | 13 ++++---------
12 files changed, 45 insertions(+), 72 deletions(-)
diff --git a/include/ui/console.h b/include/ui/console.h
index 3189788fb5f..c695b433fe3 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -305,10 +305,12 @@ struct DisplayGLCtx {
DisplayState *init_displaystate(void);
-void register_displaychangelistener(DisplayChangeListener *dcl);
+void qemu_console_register_listener(QemuConsole *con,
+ DisplayChangeListener *dcl,
+ const DisplayChangeListenerOps *ops);
void update_displaychangelistener(DisplayChangeListener *dcl,
uint64_t interval);
-void unregister_displaychangelistener(DisplayChangeListener *dcl);
+void qemu_console_unregister_listener(DisplayChangeListener *dcl);
bool dpy_ui_info_supported(const QemuConsole *con);
const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con);
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 3d4b5635568..02e8c1435be 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2252,9 +2252,7 @@ static void qxl_realize_primary(PCIDevice *dev, Error **errp)
return;
}
- qxl->ssd.dcl.ops = &display_listener_ops;
- qxl->ssd.dcl.con = vga->con;
- register_displaychangelistener(&qxl->ssd.dcl);
+ qemu_console_register_listener(vga->con, &qxl->ssd.dcl, &display_listener_ops);
}
static void qxl_realize_secondary(PCIDevice *dev, Error **errp)
diff --git a/ui/console.c b/ui/console.c
index baffdeb22b1..3ab987add34 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -642,10 +642,15 @@ dcl_set_graphic_cursor(DisplayChangeListener *dcl, QemuGraphicConsole *con)
}
}
-void register_displaychangelistener(DisplayChangeListener *dcl)
+void qemu_console_register_listener(QemuConsole *con,
+ DisplayChangeListener *dcl,
+ const DisplayChangeListenerOps *ops)
{
assert(!dcl->ds);
+ dcl->con = con;
+ dcl->ops = ops;
+
trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
dcl->ds = get_alloc_displaystate();
QLIST_INSERT_HEAD(&dcl->ds->listeners, dcl, next);
@@ -670,10 +675,10 @@ void update_displaychangelistener(DisplayChangeListener *dcl,
}
}
-void unregister_displaychangelistener(DisplayChangeListener *dcl)
+void qemu_console_unregister_listener(DisplayChangeListener *dcl)
{
DisplayState *ds = dcl->ds;
- trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name);
+ trace_displaychangelistener_unregister(dcl, dcl->ops ? dcl->ops->dpy_name : NULL);
if (!ds) {
return;
}
diff --git a/ui/curses.c b/ui/curses.c
index 78f21d940e3..4e2a0b25955 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -324,9 +324,8 @@ static void curses_refresh(DisplayChangeListener *dcl)
if (con) {
erase();
wnoutrefresh(stdscr);
- unregister_displaychangelistener(dcl);
- dcl->con = con;
- register_displaychangelistener(dcl);
+ qemu_console_unregister_listener(dcl);
+ qemu_console_register_listener(con, dcl, dcl->ops);
invalidate = 1;
}
@@ -805,9 +804,7 @@ static void curses_display_init(DisplayState *ds, DisplayOptions *opts)
curses_winch_init();
dcl = g_new0(DisplayChangeListener, 1);
- dcl->con = qemu_console_lookup_default();
- dcl->ops = &dcl_ops;
- register_displaychangelistener(dcl);
+ qemu_console_register_listener(qemu_console_lookup_default(), dcl, &dcl_ops);
invalidate = 1;
}
diff --git a/ui/dbus-console.c b/ui/dbus-console.c
index 85e215ef233..249760d82aa 100644
--- a/ui/dbus-console.c
+++ b/ui/dbus-console.c
@@ -143,7 +143,6 @@ dbus_display_console_init(DBusDisplayConsole *object)
DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object);
ddc->listeners = g_ptr_array_new_with_free_func(g_object_unref);
- ddc->dcl.ops = &dbus_console_dcl_ops;
}
static void
@@ -151,7 +150,7 @@ dbus_display_console_dispose(GObject *object)
{
DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object);
- unregister_displaychangelistener(&ddc->dcl);
+ qemu_console_unregister_listener(&ddc->dcl);
g_clear_object(&ddc->iface_touch);
g_clear_object(&ddc->iface_mouse);
g_clear_object(&ddc->iface_kbd);
@@ -553,7 +552,6 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con)
"g-object-path", path,
NULL);
ddc->display = display;
- ddc->dcl.con = con;
/* handle errors, and skip non graphics? */
qemu_console_fill_device_address(
con, device_addr, sizeof(device_addr), NULL);
@@ -611,7 +609,7 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con)
slot->tracking_id = -1;
}
- register_displaychangelistener(&ddc->dcl);
+ qemu_console_register_listener(con, &ddc->dcl, &dbus_console_dcl_ops);
ddc->mouse_mode_notifier.notify = dbus_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier);
dbus_mouse_update_is_absolute(ddc);
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 3e2b4adf41f..45b8cc74a6b 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -956,7 +956,7 @@ dbus_display_listener_dispose(GObject *object)
{
DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
- unregister_displaychangelistener(&ddl->dcl);
+ qemu_console_unregister_listener(&ddl->dcl);
g_clear_object(&ddl->conn);
g_clear_pointer(&ddl->bus_name, g_free);
g_clear_object(&ddl->proxy);
@@ -977,28 +977,12 @@ dbus_display_listener_dispose(GObject *object)
G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object);
}
-static void
-dbus_display_listener_constructed(GObject *object)
-{
- DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
-
- ddl->dcl.ops = &dbus_dcl_ops;
-#ifdef CONFIG_OPENGL
- if (display_opengl) {
- ddl->dcl.ops = &dbus_gl_dcl_ops;
- }
-#endif
-
- G_OBJECT_CLASS(dbus_display_listener_parent_class)->constructed(object);
-}
-
static void
dbus_display_listener_class_init(DBusDisplayListenerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->dispose = dbus_display_listener_dispose;
- object_class->constructed = dbus_display_listener_constructed;
}
static void
@@ -1241,6 +1225,7 @@ dbus_display_listener_new(const char *bus_name,
GDBusConnection *conn,
DBusDisplayConsole *console)
{
+ const DisplayChangeListenerOps *ops = &dbus_dcl_ops;
DBusDisplayListener *ddl;
QemuConsole *con;
g_autoptr(GError) err = NULL;
@@ -1272,8 +1257,12 @@ dbus_display_listener_new(const char *bus_name,
con = qemu_console_lookup_by_index(dbus_display_console_get_index(console));
assert(con);
- ddl->dcl.con = con;
- register_displaychangelistener(&ddl->dcl);
+#ifdef CONFIG_OPENGL
+ if (display_opengl) {
+ ops = &dbus_gl_dcl_ops;
+ }
+#endif
+ qemu_console_register_listener(con, &ddl->dcl, ops);
return ddl;
}
diff --git a/ui/egl-headless.c b/ui/egl-headless.c
index 352b30b43fb..4f046c975a9 100644
--- a/ui/egl-headless.c
+++ b/ui/egl-headless.c
@@ -229,13 +229,11 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts)
}
edpy = g_new0(egl_dpy, 1);
- edpy->dcl.con = con;
- edpy->dcl.ops = &egl_ops;
edpy->gls = qemu_gl_init_shader();
ctx = g_new0(DisplayGLCtx, 1);
ctx->ops = &eglctx_ops;
qemu_console_set_display_gl_ctx(con, ctx);
- register_displaychangelistener(&edpy->dcl);
+ qemu_console_register_listener(con, &edpy->dcl, &egl_ops);
}
}
diff --git a/ui/gtk.c b/ui/gtk.c
index 9ebe7e8df0d..3aaa44ff3e2 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -2251,6 +2251,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
QemuConsole *con, int idx,
GSList *group, GtkWidget *view_menu)
{
+ const DisplayChangeListenerOps *ops = &dcl_ops;
bool zoom_to_fit = false;
int i;
@@ -2275,7 +2276,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
vc->gfx.drawing_area = gtk_gl_area_new();
g_signal_connect(vc->gfx.drawing_area, "realize",
G_CALLBACK(gl_area_realize), vc);
- vc->gfx.dcl.ops = &dcl_gl_area_ops;
+ ops = &dcl_gl_area_ops;
vc->gfx.dgc.ops = &gl_area_ctx_ops;
} else {
#ifdef CONFIG_X11
@@ -2290,7 +2291,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE);
#pragma GCC diagnostic pop
- vc->gfx.dcl.ops = &dcl_egl_ops;
+ ops = &dcl_egl_ops;
vc->gfx.dgc.ops = &egl_ctx_ops;
vc->gfx.has_dmabuf = qemu_egl_has_dmabuf();
#else
@@ -2301,7 +2302,6 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
#endif
{
vc->gfx.drawing_area = gtk_drawing_area_new();
- vc->gfx.dcl.ops = &dcl_ops;
}
@@ -2325,12 +2325,10 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
vc->tab_item, gtk_label_new(vc->label));
vc->gfx.kbd = qkbd_state_init(con);
- vc->gfx.dcl.con = con;
-
if (display_opengl) {
qemu_console_set_display_gl_ctx(con, &vc->gfx.dgc);
}
- register_displaychangelistener(&vc->gfx.dcl);
+ qemu_console_register_listener(con, &vc->gfx.dcl, ops);
gd_connect_vc_gfx_signals(vc);
group = gd_vc_menu_init(s, vc, idx, group, view_menu);
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 3ffb8acaff8..105e1ee9399 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -934,6 +934,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
for (i = 0; i < sdl2_num_outputs; i++) {
QemuConsole *con = qemu_console_lookup_by_index(i);
+ const DisplayChangeListenerOps *ops = &dcl_2d_ops;
assert(con != NULL);
if (!qemu_console_is_graphic(con) &&
qemu_console_get_index(con) != 0) {
@@ -943,13 +944,11 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
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;
sdl2_console[i].dgc.ops = display_opengl ? &gl_ctx_ops : NULL;
+ ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops;
#else
sdl2_console[i].opengl = 0;
- sdl2_console[i].dcl.ops = &dcl_2d_ops;
#endif
- sdl2_console[i].dcl.con = con;
sdl2_console[i].kbd = qkbd_state_init(con);
#ifdef CONFIG_OPENGL
if (display_opengl) {
@@ -957,8 +956,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
sdl2_gl_console_init(&sdl2_console[i]);
}
#endif
- register_displaychangelistener(&sdl2_console[i].dcl);
-
+ qemu_console_register_listener(con, &sdl2_console[i].dcl, ops);
#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_X11)
if (SDL_GetWindowWMInfo(sdl2_console[i].real_window, &info)) {
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 5052f371f44..44e8637ea4f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -1380,13 +1380,13 @@ static void qemu_spice_display_init_one(QemuConsole *con)
SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1);
Error *err = NULL;
char device_address[256] = "";
+ const DisplayChangeListenerOps *ops = &display_listener_ops;
qemu_spice_display_init_common(ssd);
- ssd->dcl.ops = &display_listener_ops;
#ifdef HAVE_SPICE_GL
if (spice_opengl) {
- ssd->dcl.ops = &display_listener_gl_ops;
+ ops = &display_listener_gl_ops;
ssd->dgc.ops = &gl_ctx_ops;
ssd->gl_unblock_bh = qemu_bh_new(qemu_spice_gl_unblock_bh, ssd);
ssd->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
@@ -1396,8 +1396,6 @@ static void qemu_spice_display_init_one(QemuConsole *con)
ssd->have_scanout = false;
}
#endif
- ssd->dcl.con = con;
-
ssd->qxl.base.sif = &dpy_interface.base;
qemu_spice_add_display_interface(&ssd->qxl, con);
@@ -1415,7 +1413,7 @@ static void qemu_spice_display_init_one(QemuConsole *con)
if (spice_opengl) {
qemu_console_set_display_gl_ctx(con, &ssd->dgc);
}
- register_displaychangelistener(&ssd->dcl);
+ qemu_console_register_listener(con, &ssd->dcl, ops);
}
void qemu_spice_display_init(void)
diff --git a/ui/vnc.c b/ui/vnc.c
index fe2659a39ca..9daf295a763 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1858,10 +1858,9 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALT)) {
QemuConsole *con = qemu_console_lookup_by_index(qcode - Q_KEY_CODE_1);
if (con) {
- unregister_displaychangelistener(&vs->vd->dcl);
+ qemu_console_unregister_listener(&vs->vd->dcl);
qkbd_state_switch_console(vs->vd->kbd, con);
- vs->vd->dcl.con = con;
- register_displaychangelistener(&vs->vd->dcl);
+ qemu_console_register_listener(con, &vs->vd->dcl, vs->vd->dcl.ops);
}
return;
}
@@ -3435,7 +3434,6 @@ VncDisplay *vnc_display_new(const char *id, Error **errp)
qemu_mutex_init(&vd->mutex);
vd->id = g_strdup(id);
- vd->dcl.ops = &dcl_ops;
QTAILQ_INIT(&vd->clients);
vd->expires = TIME_MAX;
@@ -3518,7 +3516,7 @@ void vnc_display_free(VncDisplay *vd)
return;
}
vnc_display_close(vd);
- unregister_displaychangelistener(&vd->dcl);
+ qemu_console_unregister_listener(&vd->dcl);
qkbd_state_free(vd->kbd);
qemu_del_vm_change_state_handler(vd->vmstate_handler_entry);
kbd_layout_free(vd->kbd_layout);
@@ -4261,8 +4259,7 @@ static bool vnc_display_open(VncDisplay *vd, Error **errp)
con = qemu_console_lookup_default();
}
- vd->dcl.con = con;
- register_displaychangelistener(&vd->dcl);
+ qemu_console_register_listener(con, &vd->dcl, &dcl_ops);
vd->kbd = qkbd_state_init(vd->dcl.con);
qkbd_state_set_delay(vd->kbd, key_delay_ms);
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 9093d1e408f..aaf82421589 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -93,9 +93,7 @@ static void cocoa_switch(DisplayChangeListener *dcl,
.dpy_mouse_set = cocoa_mouse_set,
.dpy_cursor_define = cocoa_cursor_define,
};
-static DisplayChangeListener dcl = {
- .ops = &dcl_ops,
-};
+static DisplayChangeListener dcl;
static QKbdState *kbd;
static int cursor_hide = 1;
static int left_command_key_enabled = 1;
@@ -425,8 +423,7 @@ - (void) selectConsoleLocked:(unsigned int)index
unregister_displaychangelistener(&dcl);
qkbd_state_switch_console(kbd, con);
- dcl.con = con;
- register_displaychangelistener(&dcl);
+ qemu_console_register_listener(con, &dcl, &dcl_ops);
[self notifyMouseModeChange];
[self updateUIInfo];
}
@@ -2145,11 +2142,9 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
add_console_menu_entries();
addRemovableDevicesMenuItems();
- dcl.con = qemu_console_lookup_default();
+ qemu_console_register_listener(qemu_console_lookup_default(),
+ &dcl, &dcl_ops);
kbd = qkbd_state_init(dcl.con);
-
- // register vga output callbacks
- register_displaychangelistener(&dcl);
qemu_add_mouse_mode_change_notifier(&mouse_mode_change_notifier);
[cocoaView notifyMouseModeChange];
[cocoaView updateUIInfo];
--
2.53.0