Merge branch 'bilelmoussaoui/multi-sessions' into 'main'

session: Allow setting the unique name

See merge request GNOME/libmks!44
This commit is contained in:
Bilal Elmoussaoui 2023-10-25 21:24:29 +00:00
commit e295c48ccd
5 changed files with 230 additions and 51 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
subprojects/gtk subprojects/gtk
subprojects/libsass subprojects/libsass
subprojects/sassc subprojects/sassc
*.raw

View File

@ -22,7 +22,7 @@ tests:
- meson compile -C _build - meson compile -C _build
- meson test -C _build --suit "libmks" - meson test -C _build --suit "libmks"
- cd tests - cd tests
- BUILDDIR=_build xvfb-run ./functional.sh - BUILDDIR=_build dbus-run-session xvfb-run -ad ./functional.sh
- cd .. - cd ..
- rm -rf _build/subprojects - rm -rf _build/subprojects
- ninja coverage-html -C _build - ninja coverage-html -C _build

View File

@ -56,6 +56,8 @@
* with [method@Mks.Display.set_screen]. * with [method@Mks.Display.set_screen].
*/ */
#define QEMU_BUS_NAME "org.qemu"
static gboolean mks_session_initable_init (GInitable *initable, static gboolean mks_session_initable_init (GInitable *initable,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
@ -109,6 +111,7 @@ struct _MksSession
char *name; char *name;
char *uuid; char *uuid;
char *bus_name;
}; };
static void static void
@ -131,6 +134,7 @@ G_DEFINE_FINAL_TYPE_WITH_CODE (MksSession, mks_session, G_TYPE_OBJECT,
enum { enum {
PROP_0, PROP_0,
PROP_CONNECTION, PROP_CONNECTION,
PROP_BUS_NAME,
PROP_DEVICES, PROP_DEVICES,
PROP_NAME, PROP_NAME,
PROP_UUID, PROP_UUID,
@ -309,6 +313,7 @@ mks_session_dispose (GObject *object)
g_clear_object (&self->vm_object); g_clear_object (&self->vm_object);
g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->name, g_free);
g_clear_pointer (&self->uuid, g_free); g_clear_pointer (&self->uuid, g_free);
g_clear_pointer (&self->bus_name, g_free);
G_OBJECT_CLASS (mks_session_parent_class)->dispose (object); G_OBJECT_CLASS (mks_session_parent_class)->dispose (object);
} }
@ -339,6 +344,10 @@ mks_session_get_property (GObject *object,
g_value_set_object (value, mks_session_get_connection (self)); g_value_set_object (value, mks_session_get_connection (self));
break; break;
case PROP_BUS_NAME:
g_value_set_string (value, self->bus_name);
break;
case PROP_DEVICES: case PROP_DEVICES:
g_value_set_object (value, mks_session_get_devices (self)); g_value_set_object (value, mks_session_get_devices (self));
break; break;
@ -369,6 +378,9 @@ mks_session_set_property (GObject *object,
case PROP_CONNECTION: case PROP_CONNECTION:
mks_session_set_connection (self, g_value_get_object (value)); mks_session_set_connection (self, g_value_get_object (value));
break; break;
case PROP_BUS_NAME:
g_set_str (&self->bus_name, g_value_get_string (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -395,6 +407,16 @@ mks_session_class_init (MksSessionClass *klass)
G_TYPE_DBUS_CONNECTION, G_TYPE_DBUS_CONNECTION,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
/**
* MksSession:bus-name:
*
* The unique connection name to connect to or `org.qemu` as fallback.
*/
properties [PROP_BUS_NAME] =
g_param_spec_string ("bus-name", NULL, NULL,
QEMU_BUS_NAME,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
/** /**
* MksSession:devices: * MksSession:devices:
* *
@ -459,7 +481,7 @@ mks_session_initable_init (GInitable *initable,
object_manager = object_manager =
mks_qemu_object_manager_client_new_sync (self->connection, mks_qemu_object_manager_client_new_sync (self->connection,
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
"org.qemu", self->bus_name,
"/org/qemu/Display1", "/org/qemu/Display1",
cancellable, cancellable,
error); error);
@ -521,7 +543,7 @@ mks_session_async_initable_init_async (GAsyncInitable *async_initable,
else else
mks_qemu_object_manager_client_new (self->connection, mks_qemu_object_manager_client_new (self->connection,
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
"org.qemu", self->bus_name,
"/org/qemu/Display1", "/org/qemu/Display1",
cancellable, cancellable,
mks_session_async_initable_vm_cb, mks_session_async_initable_vm_cb,
@ -604,25 +626,12 @@ mks_session_new_for_connection (GDBusConnection *connection,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
g_autoptr(MksSession) self = NULL; mks_session_new_for_connection_with_name (connection,
g_autoptr(GTask) task = NULL; QEMU_BUS_NAME,
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
self = g_object_new (MKS_TYPE_SESSION,
"connection", connection,
NULL);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, mks_session_new_for_connection);
g_task_set_priority (task, io_priority);
g_async_initable_init_async (G_ASYNC_INITABLE (self),
io_priority, io_priority,
cancellable, cancellable,
mks_session_new_for_connection_cb, callback,
g_steal_pointer (&task)); user_data);
} }
/** /**
@ -663,12 +672,108 @@ mks_session_new_for_connection_sync (GDBusConnection *connection,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
g_autoptr(MksSession) self = NULL; return mks_session_new_for_connection_with_name_sync (connection,
QEMU_BUS_NAME,
cancellable,
error);
}
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); /**
* mks_session_new_for_connection_with_name:
* @connection: a #GDBusConnection
* @bus_name: The unique name to connect
* @io_priority: priority for IO operations
* @cancellable: (nullable): a #GCancellable or %NULL
* @callback: a callback to execute upon completion of the operation
* @user_data: closure data for @callback
*
* Creates a #MksSession which communicates using @connection.
*
* The constructor is similar to [func@Mks.Session.new_for_connection] but allows
* to set the bus name to something else than the default `org.qemu`.
*
* use [ctor@Mks.Session.new_for_connection_with_name_finish] to get the result of
* this operation.
*/
void
mks_session_new_for_connection_with_name (GDBusConnection *connection,
const char *bus_name,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(MksSession) self = NULL;
g_autoptr(GTask) task = NULL;
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
g_return_if_fail (bus_name != NULL);
self = g_object_new (MKS_TYPE_SESSION, self = g_object_new (MKS_TYPE_SESSION,
"connection", connection, "connection", connection,
"bus-name", bus_name,
NULL);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, mks_session_new_for_connection);
g_task_set_priority (task, io_priority);
g_async_initable_init_async (G_ASYNC_INITABLE (self),
io_priority,
cancellable,
mks_session_new_for_connection_cb,
g_steal_pointer (&task));
}
/**
* mks_session_new_for_connection_with_name_finish:
* @result: a #GAsyncResult provided to callback
* @error: (nullable): a location for a #GError or %NULL
*
* Completes a request to create a #MksSession for a [class@Gio.DBusConnection].
*
* Returns: (transfer full): a #MksSession if successful; otherwise %NULL
* and @error is set.
*/
MksSession *
mks_session_new_for_connection_with_name_finish (GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (G_IS_TASK (result), NULL);
return g_task_propagate_pointer (G_TASK (result), error);
}
/**
* mks_session_new_for_connection_with_name_sync:
* @bus_name: The unique name to connect
* @connection: a private #GDBusConnetion to a QEMU instance
* @cancellable: (nullable): a #GCancellable, or %NULL
* @error: (nullable): a location for a #GError, or %NULL
*
* Synchronously creates a new #MksSession instance.
*
* The constructor is similar to [func@Mks.Session.new_for_connection_sync] except
* it allows to set the bus name to something else than the default `org.qemu`.
*
* Returns: (transfer full): a #MksSession if successful; otherwise %NULL
* and @error is set.
*/
MksSession *
mks_session_new_for_connection_with_name_sync (GDBusConnection *connection,
const char *bus_name,
GCancellable *cancellable,
GError **error)
{
g_autoptr(MksSession) self = NULL;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
g_return_val_if_fail (bus_name != NULL, NULL);
self = g_object_new (MKS_TYPE_SESSION,
"connection", connection,
"bus-name", bus_name,
NULL); NULL);
if (g_initable_init (G_INITABLE (self), cancellable, error)) if (g_initable_init (G_INITABLE (self), cancellable, error))
@ -694,6 +799,22 @@ mks_session_get_connection (MksSession *self)
return self->connection; return self->connection;
} }
/**
* mks_session_get_bus_name:
* @self: a #MksSession
*
* Gets the DBus connection unique name or `org.qemu` as a fallback.
*
* Returns: A unique name the session is connected to
*/
const char *
mks_session_get_bus_name (MksSession *self)
{
g_return_val_if_fail (MKS_IS_SESSION (self), NULL);
return self->bus_name;
}
/** /**
* mks_session_get_uuid: * mks_session_get_uuid:
* @self: a #MksSession * @self: a #MksSession

View File

@ -43,13 +43,33 @@ void mks_session_new_for_connection (GDBusConnection *co
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
MKS_AVAILABLE_IN_ALL MKS_AVAILABLE_IN_ALL
MksSession *mks_session_new_for_connection_finish (GAsyncResult *result, MksSession *mks_session_new_for_connection_finish (GAsyncResult *result,
GError **error); GError **error);
MKS_AVAILABLE_IN_ALL
void mks_session_new_for_connection_with_name (GDBusConnection *connection,
const char *bus_name,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
MKS_AVAILABLE_IN_ALL
MksSession *mks_session_new_for_connection_with_name_finish (GAsyncResult *result,
GError **error);
MKS_AVAILABLE_IN_ALL MKS_AVAILABLE_IN_ALL
MksSession *mks_session_new_for_connection_sync (GDBusConnection *connection, MksSession *mks_session_new_for_connection_sync (GDBusConnection *connection,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
MKS_AVAILABLE_IN_ALL
MksSession *mks_session_new_for_connection_with_name_sync (GDBusConnection *connection,
const char *bus_name,
GCancellable *cancellable,
GError **error);
MKS_AVAILABLE_IN_ALL MKS_AVAILABLE_IN_ALL
GDBusConnection *mks_session_get_connection (MksSession *self); GDBusConnection *mks_session_get_connection (MksSession *self);
MKS_AVAILABLE_IN_ALL MKS_AVAILABLE_IN_ALL
@ -59,6 +79,8 @@ const char *mks_session_get_name (MksSession *se
MKS_AVAILABLE_IN_ALL MKS_AVAILABLE_IN_ALL
const char *mks_session_get_uuid (MksSession *self); const char *mks_session_get_uuid (MksSession *self);
MKS_AVAILABLE_IN_ALL MKS_AVAILABLE_IN_ALL
const char *mks_session_get_bus_name (MksSession *self);
MKS_AVAILABLE_IN_ALL
MksScreen *mks_session_ref_screen (MksSession *self); MksScreen *mks_session_ref_screen (MksSession *self);
G_END_DECLS G_END_DECLS

View File

@ -79,6 +79,10 @@ main (int argc,
g_autoptr(GDBusConnection) connection = NULL; g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(MksSession) session = NULL; g_autoptr(MksSession) session = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autoptr(GVariant) variant = NULL;
g_autoptr(GDBusProxy) proxy = NULL;
g_autofree const char **queued_owners = NULL;
gsize n_queued_owners;
GListModel *devices = NULL; GListModel *devices = NULL;
guint n_items; guint n_items;
@ -106,25 +110,56 @@ main (int argc,
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!(session = mks_session_new_for_connection_sync (connection, NULL, &error))) proxy = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
NULL,
&error);
if (proxy == NULL)
{
g_printerr ("Failed to connect to `org.freedesktop.DBus`: %s\n",
error->message);
return EXIT_FAILURE;
}
variant = g_dbus_proxy_call_sync (proxy, "ListQueuedOwners",
g_variant_new ("(s)", "org.qemu"), G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (error != NULL)
{
g_printerr ("Failed to ListQueuedOwners: %s\n",
error->message);
return EXIT_FAILURE;
}
queued_owners = g_variant_get_strv (g_variant_get_child_value (variant, 0),
&n_queued_owners);
for (guint i = 0; i < n_queued_owners; i++)
{
if (!(session = mks_session_new_for_connection_with_name_sync (connection, queued_owners[i], NULL, &error)))
{ {
g_printerr ("Failed to create MksSession: %s\n", g_printerr ("Failed to create MksSession: %s\n",
error->message); error->message);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
g_print ("Session(uuid=\"%s\", name=\"%s\")\n", g_print ("Session(uuid=\"%s\", name=\"%s\", bus-name=%s)\n",
mks_session_get_uuid (session), mks_session_get_uuid (session),
mks_session_get_name (session)); mks_session_get_name (session),
mks_session_get_bus_name (session));
devices = mks_session_get_devices (session); devices = mks_session_get_devices (session);
n_items = g_list_model_get_n_items (devices); n_items = g_list_model_get_n_items (devices);
for (guint i = 0; i < n_items; i++) for (guint j = 0; j < n_items; j++)
{ {
g_autoptr(MksDevice) device = g_list_model_get_item (devices, i); g_autoptr(MksDevice) device = g_list_model_get_item (devices, j);
print_device_info (device, 1); print_device_info (device, 1);
} }
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }