From 4d110d579178f71c5bba821c069d7e197ef30427 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 9 Feb 2023 02:23:18 -0800 Subject: [PATCH] lib: make MksDevice classes internal We want to use the vfunc of the class to implement devices coming from a Qemu object on D-Bus, but we don't want to expose that in public API. Instead, we can keep the object instance and class internal but still expose the subclasses as public API. We have to do old-style class definitions to do that, but worth the ability to keep public API limited so that we can make changes later. --- lib/mks-device-private.h | 22 ++++++++++++-- lib/mks-device.c | 58 ++++++++++++++++++++++++----------- lib/mks-device.h | 23 +++++++------- lib/mks-keyboard.c | 6 ++++ lib/mks-keyboard.h | 21 +++++++++++-- lib/mks-mouse.c | 6 ++++ lib/mks-mouse.h | 21 +++++++++++-- lib/mks-screen-private.h | 5 --- lib/mks-screen.c | 66 ++++++++++++++++++++++------------------ lib/mks-screen.h | 18 ++++++++--- lib/mks-session.c | 5 ++- 11 files changed, 174 insertions(+), 77 deletions(-) diff --git a/lib/mks-device-private.h b/lib/mks-device-private.h index 5017945..4099f13 100644 --- a/lib/mks-device-private.h +++ b/lib/mks-device-private.h @@ -22,10 +22,28 @@ #pragma once #include "mks-device.h" +#include "mks-qemu.h" G_BEGIN_DECLS -void _mks_device_set_name (MksDevice *self, - const char *name); +struct _MksDevice +{ + GObject parent_instance; + MksQemuObject *object; + char *name; +}; + +struct _MksDeviceClass +{ + GObjectClass parent_class; + + gboolean (*setup) (MksDevice *self, + MksQemuObject *object); +}; + +gpointer _mks_device_new (GType device_type, + MksQemuObject *object); +void _mks_device_set_name (MksDevice *self, + const char *name); G_END_DECLS diff --git a/lib/mks-device.c b/lib/mks-device.c index f286a6e..79946cc 100644 --- a/lib/mks-device.c +++ b/lib/mks-device.c @@ -23,12 +23,7 @@ #include "mks-device-private.h" -typedef struct -{ - char *name; -} MksDevicePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MksDevice, mks_device, G_TYPE_OBJECT) +G_DEFINE_TYPE (MksDevice, mks_device, G_TYPE_OBJECT) enum { PROP_0, @@ -38,15 +33,25 @@ enum { static GParamSpec *properties [N_PROPS]; +static gboolean +mks_device_real_setup (MksDevice *device, + MksQemuObject *object) +{ + g_assert (MKS_IS_DEVICE (device)); + g_assert (MKS_QEMU_IS_OBJECT (object)); + + return TRUE; +} + static void -mks_device_finalize (GObject *object) +mks_device_dispose (GObject *object) { MksDevice *self = (MksDevice *)object; - MksDevicePrivate *priv = mks_device_get_instance_private (self); - g_clear_pointer (&priv->name, g_free); + g_clear_pointer (&self->name, g_free); + g_clear_object (&self->object); - G_OBJECT_CLASS (mks_device_parent_class)->finalize (object); + G_OBJECT_CLASS (mks_device_parent_class)->dispose (object); } static void @@ -73,9 +78,11 @@ mks_device_class_init (MksDeviceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = mks_device_finalize; + object_class->dispose = mks_device_dispose; object_class->get_property = mks_device_get_property; + klass->setup = mks_device_real_setup; + properties [PROP_NAME] = g_param_spec_string ("name", NULL, NULL, NULL, @@ -92,21 +99,38 @@ mks_device_init (MksDevice *self) const char * mks_device_get_name (MksDevice *self) { - MksDevicePrivate *priv = mks_device_get_instance_private (self); - g_return_val_if_fail (MKS_IS_DEVICE (self), NULL); - return priv->name; + return self->name; } void _mks_device_set_name (MksDevice *self, const char *name) { - MksDevicePrivate *priv = mks_device_get_instance_private (self); - g_return_if_fail (MKS_IS_DEVICE (self)); - if (g_set_str (&priv->name, name)) + if (g_set_str (&self->name, name)) g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_NAME]); } + +gpointer +_mks_device_new (GType device_type, + MksQemuObject *object) +{ + g_autoptr(MksDevice) self = NULL; + + g_return_val_if_fail (g_type_is_a (device_type, MKS_TYPE_DEVICE), NULL); + g_return_val_if_fail (device_type != MKS_TYPE_DEVICE, NULL); + g_return_val_if_fail (MKS_QEMU_IS_OBJECT (object), NULL); + + if (!(self = g_object_new (device_type, NULL))) + return NULL; + + self->object = g_object_ref (object); + + if (!MKS_DEVICE_GET_CLASS (self)->setup (self, object)) + return NULL; + + return g_steal_pointer (&self); +} diff --git a/lib/mks-device.h b/lib/mks-device.h index c25c368..4a4ea59 100644 --- a/lib/mks-device.h +++ b/lib/mks-device.h @@ -32,20 +32,21 @@ G_BEGIN_DECLS -#define MKS_TYPE_DEVICE (mks_device_get_type()) +#define MKS_TYPE_DEVICE (mks_device_get_type ()) +#define MKS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_DEVICE, MksDevice)) +#define MKS_DEVICE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_DEVICE, MksDevice const)) +#define MKS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MKS_TYPE_DEVICE, MksDeviceClass)) +#define MKS_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MKS_TYPE_DEVICE)) +#define MKS_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MKS_TYPE_DEVICE)) +#define MKS_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MKS_TYPE_DEVICE, MksDeviceClass)) + +typedef struct _MksDeviceClass MksDeviceClass; MKS_AVAILABLE_IN_ALL -G_DECLARE_DERIVABLE_TYPE (MksDevice, mks_device, MKS, DEVICE, GObject) - -struct _MksDeviceClass -{ - GObjectClass parent_class; - - /*< private >*/ - gpointer _reserved[15]; -}; - +GType mks_device_get_type (void) G_GNUC_CONST; MKS_AVAILABLE_IN_ALL const char *mks_device_get_name (MksDevice *self); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MksDevice, g_object_unref) + G_END_DECLS diff --git a/lib/mks-keyboard.c b/lib/mks-keyboard.c index 9439429..727704b 100644 --- a/lib/mks-keyboard.c +++ b/lib/mks-keyboard.c @@ -21,6 +21,7 @@ #include "config.h" +#include "mks-device-private.h" #include "mks-keyboard.h" struct _MksKeyboard @@ -28,6 +29,11 @@ struct _MksKeyboard MksDevice parent_instance; }; +struct _MksKeyboardClass +{ + MksDeviceClass parent_instance; +}; + G_DEFINE_FINAL_TYPE (MksKeyboard, mks_keyboard, MKS_TYPE_DEVICE) enum { diff --git a/lib/mks-keyboard.h b/lib/mks-keyboard.h index fd7997d..fecce92 100644 --- a/lib/mks-keyboard.h +++ b/lib/mks-keyboard.h @@ -21,13 +21,28 @@ #pragma once -#include "mks-device.h" +#if !defined(MKS_INSIDE) && !defined(MKS_COMPILATION) +# error "Only can be included directly." +#endif + +#include + +#include "mks-types.h" +#include "mks-version-macros.h" G_BEGIN_DECLS -#define MKS_TYPE_KEYBOARD (mks_keyboard_get_type()) +#define MKS_TYPE_KEYBOARD (mks_keyboard_get_type ()) +#define MKS_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_KEYBOARD, MksKeyboard)) +#define MKS_KEYBOARD_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_KEYBOARD, MksKeyboard const)) +#define MKS_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MKS_TYPE_KEYBOARD, MksKeyboardClass)) +#define MKS_IS_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MKS_TYPE_KEYBOARD)) +#define MKS_IS_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MKS_TYPE_KEYBOARD)) +#define MKS_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MKS_TYPE_KEYBOARD, MksKeyboardClass)) + +typedef struct _MksKeyboardClass MksKeyboardClass; MKS_AVAILABLE_IN_ALL -G_DECLARE_FINAL_TYPE (MksKeyboard, mks_keyboard, MKS, KEYBOARD, MksDevice) +GType mks_keyboard_get_type (void) G_GNUC_CONST; G_END_DECLS diff --git a/lib/mks-mouse.c b/lib/mks-mouse.c index 3c1d336..b163a27 100644 --- a/lib/mks-mouse.c +++ b/lib/mks-mouse.c @@ -21,6 +21,7 @@ #include "config.h" +#include "mks-device-private.h" #include "mks-mouse.h" struct _MksMouse @@ -28,6 +29,11 @@ struct _MksMouse MksDevice parent_instance; }; +struct _MksMouseClass +{ + MksDeviceClass parent_class; +}; + G_DEFINE_FINAL_TYPE (MksMouse, mks_mouse, MKS_TYPE_DEVICE) enum { diff --git a/lib/mks-mouse.h b/lib/mks-mouse.h index f5239d4..b4c2375 100644 --- a/lib/mks-mouse.h +++ b/lib/mks-mouse.h @@ -21,13 +21,28 @@ #pragma once -#include "mks-device.h" +#if !defined(MKS_INSIDE) && !defined(MKS_COMPILATION) +# error "Only can be included directly." +#endif + +#include + +#include "mks-types.h" +#include "mks-version-macros.h" G_BEGIN_DECLS -#define MKS_TYPE_MOUSE (mks_mouse_get_type()) +#define MKS_TYPE_MOUSE (mks_mouse_get_type ()) +#define MKS_MOUSE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_MOUSE, MksMouse)) +#define MKS_MOUSE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_MOUSE, MksMouse const)) +#define MKS_MOUSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MKS_TYPE_MOUSE, MksMouseClass)) +#define MKS_IS_MOUSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MKS_TYPE_MOUSE)) +#define MKS_IS_MOUSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MKS_TYPE_MOUSE)) +#define MKS_MOUSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MKS_TYPE_MOUSE, MksMouseClass)) + +typedef struct _MksMouseClass MksMouseClass; MKS_AVAILABLE_IN_ALL -G_DECLARE_FINAL_TYPE (MksMouse, mks_mouse, MKS, MOUSE, MksDevice) +GType mks_mouse_get_type (void) G_GNUC_CONST; G_END_DECLS diff --git a/lib/mks-screen-private.h b/lib/mks-screen-private.h index 065a1ef..ddd0ac3 100644 --- a/lib/mks-screen-private.h +++ b/lib/mks-screen-private.h @@ -21,13 +21,8 @@ #pragma once -#include - -#include "mks-qemu.h" #include "mks-screen.h" G_BEGIN_DECLS -MksDevice *_mks_screen_new (MksQemuObject *object); - G_END_DECLS diff --git a/lib/mks-screen.c b/lib/mks-screen.c index 36401df..38df78f 100644 --- a/lib/mks-screen.c +++ b/lib/mks-screen.c @@ -28,11 +28,15 @@ #include "mks-mouse-private.h" #include "mks-screen-private.h" +struct _MksScreenClass +{ + MksDeviceClass parent_class; +}; + struct _MksScreen { MksDevice parent_instance; - MksQemuObject *console_object; MksQemuConsole *console; gulong console_notify_handler; @@ -154,6 +158,35 @@ mks_screen_set_console (MksScreen *self, } } +static gboolean +mks_screen_setup (MksDevice *device, + MksQemuObject *object) +{ + MksScreen *self = (MksScreen *)device; + g_autolist(GDBusInterface) interfaces = NULL; + + g_assert (MKS_IS_SCREEN (self)); + g_assert (MKS_QEMU_IS_OBJECT (object)); + + interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object)); + + for (const GList *iter = interfaces; iter; iter = iter->next) + { + GDBusInterface *iface = iter->data; + + if (MKS_QEMU_IS_CONSOLE (iface)) + mks_screen_set_console (self, MKS_QEMU_CONSOLE (iface)); + else if (MKS_QEMU_IS_KEYBOARD (iface)) + self->keyboard = _mks_device_new (MKS_TYPE_KEYBOARD, object); + else if (MKS_QEMU_IS_MOUSE (iface)) + self->mouse = _mks_device_new (MKS_TYPE_MOUSE, object); + } + + return self->console != NULL && + self->keyboard != NULL && + self->mouse != NULL; +} + static void mks_screen_dispose (GObject *object) { @@ -165,7 +198,6 @@ mks_screen_dispose (GObject *object) g_clear_object (&self->console); } - g_clear_object (&self->console_object); g_clear_object (&self->keyboard); g_clear_object (&self->mouse); @@ -215,10 +247,13 @@ static void mks_screen_class_init (MksScreenClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + MksDeviceClass *device_class = MKS_DEVICE_CLASS (klass); object_class->dispose = mks_screen_dispose; object_class->get_property = mks_screen_get_property; + device_class->setup = mks_screen_setup; + properties [PROP_KEYBOARD] = g_param_spec_object ("keyboard", NULL, NULL, MKS_TYPE_KEYBOARD, @@ -258,33 +293,6 @@ mks_screen_init (MksScreen *self) { } -MksDevice * -_mks_screen_new (MksQemuObject *object) -{ - g_autoptr(MksScreen) self = NULL; - g_autolist(GDBusInterface) interfaces = NULL; - - g_return_val_if_fail (MKS_QEMU_IS_OBJECT (object), NULL); - - self = g_object_new (MKS_TYPE_SCREEN, NULL); - self->console_object = g_object_ref (object); - - interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object)); - - for (const GList *iter = interfaces; iter; iter = iter->next) - { - GDBusInterface *iface = iter->data; - - if (MKS_QEMU_IS_CONSOLE (iface)) - mks_screen_set_console (self, MKS_QEMU_CONSOLE (iface)); - } - - if (self->console == NULL) - return NULL; - - return MKS_DEVICE (g_steal_pointer (&self)); -} - /** * mks_screen_get_keyboard: * @self: a #MksScreen diff --git a/lib/mks-screen.h b/lib/mks-screen.h index 4f41343..09e49d5 100644 --- a/lib/mks-screen.h +++ b/lib/mks-screen.h @@ -27,11 +27,20 @@ #include -#include "mks-device.h" +#include "mks-types.h" +#include "mks-version-macros.h" G_BEGIN_DECLS -#define MKS_TYPE_SCREEN (mks_screen_get_type()) +#define MKS_TYPE_SCREEN (mks_screen_get_type ()) +#define MKS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_SCREEN, MksScreen)) +#define MKS_SCREEN_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKS_TYPE_SCREEN, MksScreen const)) +#define MKS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MKS_TYPE_SCREEN, MksScreenClass)) +#define MKS_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MKS_TYPE_SCREEN)) +#define MKS_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MKS_TYPE_SCREEN)) +#define MKS_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MKS_TYPE_SCREEN, MksScreenClass)) + +typedef struct _MksScreenClass MksScreenClass; typedef enum _MksScreenKind { @@ -40,8 +49,7 @@ typedef enum _MksScreenKind } MksScreenKind; MKS_AVAILABLE_IN_ALL -G_DECLARE_FINAL_TYPE (MksScreen, mks_screen, MKS, SCREEN, MksDevice) - +GType mks_screen_get_type (void) G_GNUC_CONST; MKS_AVAILABLE_IN_ALL MksScreenKind mks_screen_get_kind (MksScreen *self); MKS_AVAILABLE_IN_ALL @@ -55,4 +63,6 @@ guint mks_screen_get_height (MksScreen *self); MKS_AVAILABLE_IN_ALL guint mks_screen_get_number (MksScreen *self); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MksScreen, g_object_unref) + G_END_DECLS diff --git a/lib/mks-session.c b/lib/mks-session.c index 63b7df8..acf5758 100644 --- a/lib/mks-session.c +++ b/lib/mks-session.c @@ -21,7 +21,7 @@ #include "config.h" -#include "mks-device.h" +#include "mks-device-private.h" #include "mks-read-only-list-model-private.h" #include "mks-qemu.h" #include "mks-screen-private.h" @@ -225,7 +225,7 @@ mks_session_object_manager_object_added_cb (MksSession *self, if (MKS_QEMU_IS_VM (iface)) mks_session_set_vm (self, object, MKS_QEMU_VM (iface)); else if (MKS_QEMU_IS_CONSOLE (iface)) - mks_session_add_device (self, _mks_screen_new (object)); + mks_session_add_device (self, _mks_device_new (MKS_TYPE_SCREEN, object)); } } @@ -423,7 +423,6 @@ mks_session_initable_init (GInitable *initable, { MksSession *self = (MksSession *)initable; g_autoptr(GDBusObjectManager) object_manager = NULL; - g_autolist(GDBusObjectProxy) objects = NULL; g_assert (MKS_IS_SESSION (self)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));