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.
This commit is contained in:
Christian Hergert 2023-02-09 02:23:18 -08:00
parent ec09aaaa07
commit 4d110d5791
11 changed files with 174 additions and 77 deletions

View File

@ -22,9 +22,27 @@
#pragma once
#include "mks-device.h"
#include "mks-qemu.h"
G_BEGIN_DECLS
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);

View File

@ -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);
}

View File

@ -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

View File

@ -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 {

View File

@ -21,13 +21,28 @@
#pragma once
#include "mks-device.h"
#if !defined(MKS_INSIDE) && !defined(MKS_COMPILATION)
# error "Only <libmks.h> can be included directly."
#endif
#include <glib-object.h>
#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

View File

@ -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 {

View File

@ -21,13 +21,28 @@
#pragma once
#include "mks-device.h"
#if !defined(MKS_INSIDE) && !defined(MKS_COMPILATION)
# error "Only <libmks.h> can be included directly."
#endif
#include <glib-object.h>
#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

View File

@ -21,13 +21,8 @@
#pragma once
#include <gio/gio.h>
#include "mks-qemu.h"
#include "mks-screen.h"
G_BEGIN_DECLS
MksDevice *_mks_screen_new (MksQemuObject *object);
G_END_DECLS

View File

@ -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

View File

@ -27,11 +27,20 @@
#include <glib-object.h>
#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

View File

@ -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));