color: Create color profile for assigned profile
We created device profiles, that we manage the lifetime of in colord, but color devices can be assigned profiles other than the ones it was created for. For example, this can include the standard sRGB profile provided by colord. To achieve this, keep track of the default profile of the CdDevice as the "assigned" color profile of the device. Given this profile (CdProfile), construct a MetaColorProfile that can then be interacted with as if it was generated by ourself. The assigned profile (default profile in colord terms) does nothing special so far, but will later be used to determine how to apply CRTC gamma ramps etc. The sRGB.icc file used in the tests was copied from colord. It was stated in the repository that it has no known copyright restrictions. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2164>
This commit is contained in:
parent
cc84a45b56
commit
0a0fb2fda9
9 changed files with 548 additions and 17 deletions
|
@ -62,6 +62,10 @@ struct _MetaColorDevice
|
|||
MetaColorProfile *device_profile;
|
||||
gulong device_profile_ready_handler_id;
|
||||
|
||||
MetaColorProfile *assigned_profile;
|
||||
gulong assigned_profile_ready_handler_id;
|
||||
GCancellable *assigned_profile_cancellable;
|
||||
|
||||
GCancellable *cancellable;
|
||||
|
||||
PendingState pending_state;
|
||||
|
@ -121,6 +125,77 @@ out:
|
|||
return g_string_free (device_id, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_default_profile_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaColorStore *color_store = META_COLOR_STORE (source_object);
|
||||
MetaColorDevice *color_device;
|
||||
g_autoptr (MetaColorProfile) color_profile = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
color_profile = meta_color_store_ensure_colord_profile_finish (color_store,
|
||||
res,
|
||||
&error);
|
||||
if (!color_profile)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
g_warning ("Failed to create color profile from colord profile: %s",
|
||||
error->message);
|
||||
}
|
||||
|
||||
color_device = META_COLOR_DEVICE (user_data);
|
||||
g_set_object (&color_device->assigned_profile, color_profile);
|
||||
}
|
||||
|
||||
static void
|
||||
update_assigned_profile (MetaColorDevice *color_device)
|
||||
{
|
||||
MetaColorManager *color_manager = color_device->color_manager;
|
||||
MetaColorStore *color_store =
|
||||
meta_color_manager_get_color_store (color_manager);
|
||||
CdProfile *default_profile;
|
||||
GCancellable *cancellable;
|
||||
|
||||
default_profile = cd_device_get_default_profile (color_device->cd_device);
|
||||
|
||||
if (color_device->assigned_profile &&
|
||||
meta_color_profile_get_cd_profile (color_device->assigned_profile) ==
|
||||
default_profile)
|
||||
return;
|
||||
|
||||
if (color_device->assigned_profile_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (color_device->assigned_profile_cancellable);
|
||||
g_clear_object (&color_device->assigned_profile_cancellable);
|
||||
}
|
||||
|
||||
if (!default_profile)
|
||||
{
|
||||
g_clear_object (&color_device->assigned_profile);
|
||||
return;
|
||||
}
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
color_device->assigned_profile_cancellable = cancellable;
|
||||
|
||||
meta_color_store_ensure_colord_profile (color_store,
|
||||
default_profile,
|
||||
cancellable,
|
||||
ensure_default_profile_cb,
|
||||
color_device);
|
||||
}
|
||||
|
||||
static void
|
||||
on_cd_device_changed (CdDevice *cd_device,
|
||||
MetaColorDevice *color_device)
|
||||
{
|
||||
update_assigned_profile (color_device);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMainLoop *loop;
|
||||
|
@ -180,11 +255,18 @@ meta_color_device_dispose (GObject *object)
|
|||
meta_topic (META_DEBUG_COLOR,
|
||||
"Removing color device '%s'", color_device->cd_device_id);
|
||||
|
||||
if (color_device->assigned_profile_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (color_device->assigned_profile_cancellable);
|
||||
g_clear_object (&color_device->assigned_profile_cancellable);
|
||||
}
|
||||
|
||||
g_cancellable_cancel (color_device->cancellable);
|
||||
g_clear_object (&color_device->cancellable);
|
||||
g_clear_signal_handler (&color_device->device_profile_ready_handler_id,
|
||||
color_device->device_profile);
|
||||
|
||||
g_clear_object (&color_device->assigned_profile);
|
||||
g_clear_object (&color_device->device_profile);
|
||||
|
||||
cd_device = color_device->cd_device;
|
||||
|
@ -284,6 +366,10 @@ on_cd_device_connected (GObject *source_object,
|
|||
|
||||
color_device->pending_state &= ~PENDING_CONNECTED;
|
||||
|
||||
g_signal_connect (cd_device, "changed",
|
||||
G_CALLBACK (on_cd_device_changed), color_device);
|
||||
update_assigned_profile (color_device);
|
||||
|
||||
maybe_finish_setup (color_device);
|
||||
}
|
||||
|
||||
|
@ -981,3 +1067,9 @@ meta_color_device_is_ready (MetaColorDevice *color_device)
|
|||
{
|
||||
return color_device->is_ready;
|
||||
}
|
||||
|
||||
MetaColorProfile *
|
||||
meta_color_device_get_assigned_profile (MetaColorDevice *color_device)
|
||||
{
|
||||
return color_device->assigned_profile;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ void meta_color_device_destroy (MetaColorDevice *color_device);
|
|||
void meta_color_device_update_monitor (MetaColorDevice *color_device,
|
||||
MetaMonitor *monitor);
|
||||
|
||||
META_EXPORT_TEST
|
||||
const char * meta_color_device_get_id (MetaColorDevice *color_device);
|
||||
|
||||
META_EXPORT_TEST
|
||||
|
@ -45,6 +46,9 @@ MetaMonitor * meta_color_device_get_monitor (MetaColorDevice *color_device);
|
|||
META_EXPORT_TEST
|
||||
MetaColorProfile * meta_color_device_get_device_profile (MetaColorDevice *color_device);
|
||||
|
||||
META_EXPORT_TEST
|
||||
MetaColorProfile * meta_color_device_get_assigned_profile (MetaColorDevice *color_device);
|
||||
|
||||
void meta_color_device_generate_profile (MetaColorDevice *color_device,
|
||||
const char *file_path,
|
||||
GCancellable *cancellable,
|
||||
|
|
|
@ -46,8 +46,10 @@ struct _MetaColorProfile
|
|||
GBytes *bytes;
|
||||
|
||||
char *cd_profile_id;
|
||||
gboolean is_owner;
|
||||
CdProfile *cd_profile;
|
||||
GCancellable *cancellable;
|
||||
guint notify_ready_id;
|
||||
|
||||
gboolean is_ready;
|
||||
};
|
||||
|
@ -109,30 +111,35 @@ meta_color_profile_finalize (GObject *object)
|
|||
MetaColorProfile *color_profile = META_COLOR_PROFILE (object);
|
||||
MetaColorManager *color_manager = color_profile->color_manager;
|
||||
CdClient *cd_client = meta_color_manager_get_cd_client (color_manager);
|
||||
CdProfile *cd_profile;
|
||||
|
||||
g_cancellable_cancel (color_profile->cancellable);
|
||||
g_clear_object (&color_profile->cancellable);
|
||||
g_clear_handle_id (&color_profile->notify_ready_id, g_source_remove);
|
||||
|
||||
cd_profile = color_profile->cd_profile;
|
||||
if (!cd_profile)
|
||||
if (color_profile->is_owner)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
CdProfile *cd_profile;
|
||||
|
||||
cd_profile = find_profile_sync (cd_client,
|
||||
color_profile->cd_profile_id,
|
||||
&error);
|
||||
if (!cd_profile &&
|
||||
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
cd_profile = color_profile->cd_profile;
|
||||
if (!cd_profile)
|
||||
{
|
||||
g_warning ("Failed to find colord profile %s: %s",
|
||||
color_profile->cd_profile_id,
|
||||
error->message);
|
||||
}
|
||||
}
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (cd_profile)
|
||||
cd_client_delete_profile (cd_client, cd_profile, NULL, NULL, NULL);
|
||||
cd_profile = find_profile_sync (cd_client,
|
||||
color_profile->cd_profile_id,
|
||||
&error);
|
||||
if (!cd_profile &&
|
||||
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_warning ("Failed to find colord profile %s: %s",
|
||||
color_profile->cd_profile_id,
|
||||
error->message);
|
||||
}
|
||||
}
|
||||
|
||||
if (cd_profile)
|
||||
cd_client_delete_profile (cd_client, cd_profile, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
g_clear_pointer (&color_profile->cd_profile_id, g_free);
|
||||
g_clear_object (&color_profile->cd_icc);
|
||||
|
@ -270,6 +277,7 @@ meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
|||
color_profile->cd_icc = cd_icc;
|
||||
color_profile->bytes = raw_bytes;
|
||||
color_profile->cancellable = g_cancellable_new ();
|
||||
color_profile->is_owner = TRUE;
|
||||
|
||||
color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum);
|
||||
|
||||
|
@ -278,6 +286,45 @@ meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
|||
return color_profile;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_ready_idle (gpointer user_data)
|
||||
{
|
||||
MetaColorProfile *color_profile = user_data;
|
||||
|
||||
color_profile->notify_ready_id = 0;
|
||||
color_profile->is_ready = TRUE;
|
||||
g_signal_emit (color_profile, signals[READY], 0);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
MetaColorProfile *
|
||||
meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
CdProfile *cd_profile,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes)
|
||||
{
|
||||
MetaColorProfile *color_profile;
|
||||
const char *checksum;
|
||||
|
||||
color_profile = g_object_new (META_TYPE_COLOR_PROFILE, NULL);
|
||||
color_profile->color_manager = color_manager;
|
||||
color_profile->cd_icc = cd_icc;
|
||||
color_profile->bytes = raw_bytes;
|
||||
color_profile->cancellable = g_cancellable_new ();
|
||||
color_profile->is_owner = FALSE;
|
||||
|
||||
checksum = cd_icc_get_metadata_item (cd_icc,
|
||||
CD_PROFILE_METADATA_FILE_CHECKSUM);
|
||||
color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum);
|
||||
color_profile->cd_profile = g_object_ref (cd_profile);
|
||||
|
||||
color_profile->notify_ready_id = g_idle_add (notify_ready_idle,
|
||||
color_profile);
|
||||
|
||||
return color_profile;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_color_profile_equals_bytes (MetaColorProfile *color_profile,
|
||||
GBytes *bytes)
|
||||
|
@ -303,8 +350,20 @@ meta_color_profile_get_cd_icc (MetaColorProfile *color_profile)
|
|||
return color_profile->cd_icc;
|
||||
}
|
||||
|
||||
CdProfile *
|
||||
meta_color_profile_get_cd_profile (MetaColorProfile *color_profile)
|
||||
{
|
||||
return color_profile->cd_profile;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_color_profile_is_ready (MetaColorProfile *color_profile)
|
||||
{
|
||||
return color_profile->is_ready;
|
||||
}
|
||||
|
||||
const char *
|
||||
meta_color_profile_get_id (MetaColorProfile *color_profile)
|
||||
{
|
||||
return color_profile->cd_profile_id;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,11 @@ MetaColorProfile * meta_color_profile_new_from_icc (MetaColorManager *color_mana
|
|||
CdIcc *icc,
|
||||
GBytes *raw_bytes);
|
||||
|
||||
MetaColorProfile * meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
CdProfile *cd_profile,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes);
|
||||
|
||||
gboolean meta_color_profile_equals_bytes (MetaColorProfile *color_profile,
|
||||
GBytes *bytes);
|
||||
|
||||
|
@ -44,6 +49,11 @@ size_t meta_color_profile_get_data_size (MetaColorProfile *color_profile);
|
|||
META_EXPORT_TEST
|
||||
CdIcc * meta_color_profile_get_cd_icc (MetaColorProfile *color_profile);
|
||||
|
||||
CdProfile * meta_color_profile_get_cd_profile (MetaColorProfile *color_profile);
|
||||
|
||||
gboolean meta_color_profile_is_ready (MetaColorProfile *color_profile);
|
||||
|
||||
META_EXPORT_TEST
|
||||
const char * meta_color_profile_get_id (MetaColorProfile *color_profile);
|
||||
|
||||
#endif /* META_COLOR_PROFILE_H */
|
||||
|
|
|
@ -54,6 +54,7 @@ meta_color_store_finalize (GObject *object)
|
|||
{
|
||||
MetaColorStore *color_store = META_COLOR_STORE (object);
|
||||
|
||||
g_clear_pointer (&color_store->profiles, g_hash_table_unref);
|
||||
g_clear_pointer (&color_store->device_profiles, g_hash_table_unref);
|
||||
g_clear_pointer (&color_store->pending_device_profiles, g_hash_table_unref);
|
||||
|
||||
|
@ -80,6 +81,8 @@ meta_color_store_new (MetaColorManager *color_manager)
|
|||
|
||||
color_store = g_object_new (META_TYPE_COLOR_STORE, NULL);
|
||||
color_store->color_manager = color_manager;
|
||||
color_store->profiles =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
color_store->device_profiles =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
color_store->pending_device_profiles =
|
||||
|
@ -205,5 +208,180 @@ meta_color_store_ensure_device_profile_finish (MetaColorStore *color_store,
|
|||
g_hash_table_insert (color_store->device_profiles,
|
||||
g_steal_pointer (&data->key),
|
||||
g_object_ref (color_profile));
|
||||
g_hash_table_insert (color_store->profiles,
|
||||
g_strdup (meta_color_profile_get_id (color_profile)),
|
||||
g_object_ref (color_profile));
|
||||
return color_profile;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaColorStore *color_store;
|
||||
CdProfile *cd_profile;
|
||||
|
||||
MetaColorProfile *created_profile;
|
||||
} EnsureColordProfileData;
|
||||
|
||||
static void
|
||||
ensure_colord_profile_data_free (EnsureColordProfileData *data)
|
||||
{
|
||||
g_clear_object (&data->cd_profile);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_cd_profile_contents_loaded (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GFile *file = G_FILE (source_object);
|
||||
g_autoptr (GTask) task = G_TASK (user_data);
|
||||
EnsureColordProfileData *data = g_task_get_task_data (task);
|
||||
MetaColorStore *color_store = data->color_store;
|
||||
MetaColorManager *color_manager = color_store->color_manager;
|
||||
CdProfile *cd_profile = data->cd_profile;
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autofree char *contents = NULL;
|
||||
size_t length;
|
||||
g_autoptr (CdIcc) cd_icc = NULL;
|
||||
g_autofree char *file_md5_checksum = NULL;
|
||||
GBytes *bytes;
|
||||
MetaColorProfile *color_profile;
|
||||
|
||||
if (!g_file_load_contents_finish (file, res,
|
||||
&contents,
|
||||
&length,
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
cd_icc = cd_icc_new ();
|
||||
if (!cd_icc_load_data (cd_icc,
|
||||
(uint8_t *) contents,
|
||||
length,
|
||||
CD_ICC_LOAD_FLAGS_METADATA,
|
||||
&error))
|
||||
{
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_PROPERTY_FILENAME,
|
||||
g_file_peek_path (file));
|
||||
|
||||
file_md5_checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5,
|
||||
(uint8_t *) contents,
|
||||
length);
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM,
|
||||
file_md5_checksum);
|
||||
|
||||
bytes = g_bytes_new_take (g_steal_pointer (&contents), length);
|
||||
color_profile =
|
||||
meta_color_profile_new_from_cd_profile (color_manager,
|
||||
cd_profile,
|
||||
g_steal_pointer (&cd_icc),
|
||||
bytes);
|
||||
|
||||
g_hash_table_insert (color_store->profiles,
|
||||
g_strdup (meta_color_profile_get_id (color_profile)),
|
||||
color_profile);
|
||||
|
||||
meta_topic (META_DEBUG_COLOR, "Created colord profile '%s' from '%s'",
|
||||
cd_profile_get_id (cd_profile),
|
||||
cd_profile_get_filename (cd_profile));
|
||||
|
||||
g_task_return_pointer (task, g_object_ref (color_profile), g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
on_cd_profile_connected (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CdProfile *cd_profile = CD_PROFILE (source_object);
|
||||
g_autoptr (GTask) task = G_TASK (user_data);
|
||||
EnsureColordProfileData *data = g_task_get_task_data (task);
|
||||
MetaColorStore *color_store = data->color_store;
|
||||
g_autoptr (GError) error = NULL;
|
||||
const char *file_path;
|
||||
g_autoptr (GFile) file = NULL;
|
||||
MetaColorProfile *color_profile;
|
||||
GCancellable *cancellable;
|
||||
|
||||
if (!cd_profile_connect_finish (cd_profile, res, &error))
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
color_profile = g_hash_table_lookup (color_store->profiles,
|
||||
cd_profile_get_id (cd_profile));
|
||||
if (color_profile)
|
||||
{
|
||||
meta_topic (META_DEBUG_COLOR, "Found existing colord profile '%s'",
|
||||
cd_profile_get_id (cd_profile));
|
||||
g_task_return_pointer (task,
|
||||
g_object_ref (color_profile),
|
||||
g_object_unref);
|
||||
return;
|
||||
}
|
||||
|
||||
file_path = cd_profile_get_filename (cd_profile);
|
||||
if (!file_path)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Tried to assign non-local profile");
|
||||
return;
|
||||
}
|
||||
|
||||
file = g_file_new_for_path (file_path);
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
g_file_load_contents_async (file,
|
||||
cancellable,
|
||||
on_cd_profile_contents_loaded,
|
||||
g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
void
|
||||
meta_color_store_ensure_colord_profile (MetaColorStore *color_store,
|
||||
CdProfile *cd_profile,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
EnsureColordProfileData *data;
|
||||
|
||||
task = g_task_new (G_OBJECT (color_store), cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, meta_color_store_ensure_colord_profile);
|
||||
|
||||
data = g_new0 (EnsureColordProfileData, 1);
|
||||
data->color_store = color_store;
|
||||
data->cd_profile = g_object_ref (cd_profile);
|
||||
g_task_set_task_data (task, data,
|
||||
(GDestroyNotify) ensure_colord_profile_data_free);
|
||||
|
||||
cd_profile_connect (cd_profile,
|
||||
cancellable,
|
||||
on_cd_profile_connected,
|
||||
task);
|
||||
}
|
||||
|
||||
MetaColorProfile *
|
||||
meta_color_store_ensure_colord_profile_finish (MetaColorStore *color_store,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task = G_TASK (res);
|
||||
|
||||
g_assert (g_task_get_source_tag (task) ==
|
||||
meta_color_store_ensure_colord_profile);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (res), error);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef META_COLOR_STORE_H
|
||||
#define META_COLOR_STORE_H
|
||||
|
||||
#include <colord.h>
|
||||
#include <gio/gio.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
|
@ -40,4 +41,14 @@ MetaColorProfile * meta_color_store_ensure_device_profile_finish (MetaColorStore
|
|||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
void meta_color_store_ensure_colord_profile (MetaColorStore *color_store,
|
||||
CdProfile *cd_profile,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
MetaColorProfile * meta_color_store_ensure_colord_profile_finish (MetaColorStore *color_store,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_COLOR_STORE_H */
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
static MetaContext *test_context;
|
||||
|
||||
/* Profile ID is 'icc-$(md5sum sRGB.icc)' */
|
||||
#define SRGB_ICC_PROFILE_ID "icc-112034c661b5e0c91c51f109684612a0";
|
||||
|
||||
#define PRIMARY_EPSILON 0.000015
|
||||
|
||||
static MonitorTestCaseSetup base_monitor_setup = {
|
||||
|
@ -101,6 +104,82 @@ static MonitorTestCaseSetup base_monitor_setup = {
|
|||
.white_y = 0.329102, \
|
||||
})
|
||||
|
||||
static GDBusProxy *
|
||||
get_colord_mock_proxy (void)
|
||||
{
|
||||
GDBusProxy *proxy;
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (GVariant) ret = NULL;
|
||||
|
||||
proxy =
|
||||
g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
||||
NULL,
|
||||
"org.freedesktop.ColorManager",
|
||||
"/org/freedesktop/ColorManager",
|
||||
"org.freedesktop.DBus.Mock",
|
||||
NULL, &error);
|
||||
if (!proxy)
|
||||
{
|
||||
g_error ("Failed to find mocked color manager system service, %s",
|
||||
error->message);
|
||||
}
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
static void
|
||||
set_colord_device_profiles (const char *cd_device_id,
|
||||
const char **cd_profile_ids,
|
||||
int n_cd_profile_ids)
|
||||
{
|
||||
GDBusProxy *proxy;
|
||||
g_autoptr (GError) error = NULL;
|
||||
GVariantBuilder params_builder;
|
||||
GVariantBuilder profiles_builder;
|
||||
int i;
|
||||
|
||||
proxy = get_colord_mock_proxy ();
|
||||
|
||||
g_variant_builder_init (¶ms_builder, G_VARIANT_TYPE ("(sas)"));
|
||||
g_variant_builder_add (¶ms_builder, "s", cd_device_id);
|
||||
|
||||
g_variant_builder_init (&profiles_builder, G_VARIANT_TYPE ("as"));
|
||||
for (i = 0; i < n_cd_profile_ids; i++)
|
||||
g_variant_builder_add (&profiles_builder, "s", cd_profile_ids[i]);
|
||||
g_variant_builder_add (¶ms_builder, "as", &profiles_builder);
|
||||
|
||||
if (!g_dbus_proxy_call_sync (proxy,
|
||||
"SetDeviceProfiles",
|
||||
g_variant_builder_end (¶ms_builder),
|
||||
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL,
|
||||
&error))
|
||||
g_error ("Failed to set device profile: %s", error->message);
|
||||
}
|
||||
|
||||
static void
|
||||
add_colord_system_profile (const char *cd_profile_id,
|
||||
const char *file_path)
|
||||
{
|
||||
GDBusProxy *proxy;
|
||||
g_autoptr (GError) error = NULL;
|
||||
GVariantBuilder params_builder;
|
||||
|
||||
proxy = get_colord_mock_proxy ();
|
||||
|
||||
g_variant_builder_init (¶ms_builder, G_VARIANT_TYPE ("(ss)"));
|
||||
g_variant_builder_add (¶ms_builder, "s", cd_profile_id);
|
||||
g_variant_builder_add (¶ms_builder, "s", file_path);
|
||||
|
||||
if (!g_dbus_proxy_call_sync (proxy,
|
||||
"AddSystemProfile",
|
||||
g_variant_builder_end (¶ms_builder),
|
||||
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL,
|
||||
&error))
|
||||
g_error ("Failed to add system profile: %s", error->message);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_color_management_device_basic (void)
|
||||
{
|
||||
|
@ -269,6 +348,63 @@ meta_test_color_management_profile_device (void)
|
|||
g_assert_cmpfloat_with_epsilon (white->Z, 1.10479736, PRIMARY_EPSILON);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_color_management_profile_system (void)
|
||||
{
|
||||
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaMonitorManagerTest *monitor_manager_test =
|
||||
META_MONITOR_MANAGER_TEST (monitor_manager);
|
||||
MetaColorManager *color_manager =
|
||||
meta_backend_get_color_manager (backend);
|
||||
MetaEdidInfo edid_info;
|
||||
MonitorTestCaseSetup test_case_setup = base_monitor_setup;
|
||||
MetaMonitorTestSetup *test_setup;
|
||||
MetaMonitor *monitor;
|
||||
MetaColorDevice *color_device;
|
||||
const char *path;
|
||||
const char *color_profiles[1];
|
||||
MetaColorProfile *color_profile;
|
||||
const char *srgb_profile_id = SRGB_ICC_PROFILE_ID;
|
||||
|
||||
edid_info = CALTECH_MONITOR_EDID;
|
||||
test_case_setup.outputs[0].edid_info = edid_info;
|
||||
test_case_setup.outputs[0].has_edid_info = TRUE;
|
||||
test_setup = meta_create_monitor_test_setup (backend, &test_case_setup,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup);
|
||||
|
||||
monitor = meta_monitor_manager_get_monitors (monitor_manager)->data;
|
||||
color_device = meta_color_manager_get_color_device (color_manager, monitor);
|
||||
g_assert_nonnull (color_device);
|
||||
|
||||
while (!meta_color_device_is_ready (color_device))
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
g_assert_null (meta_color_device_get_assigned_profile (color_device));
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "tests", "icc-profiles", "sRGB.icc",
|
||||
NULL);
|
||||
add_colord_system_profile (srgb_profile_id, path);
|
||||
color_profiles[0] = srgb_profile_id;
|
||||
set_colord_device_profiles (meta_color_device_get_id (color_device),
|
||||
color_profiles, G_N_ELEMENTS (color_profiles));
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
color_profile = meta_color_device_get_assigned_profile (color_device);
|
||||
if (color_profile)
|
||||
break;
|
||||
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
}
|
||||
|
||||
g_assert_cmpstr (meta_color_profile_get_id (color_profile),
|
||||
==,
|
||||
srgb_profile_id);
|
||||
}
|
||||
|
||||
static MetaMonitorTestSetup *
|
||||
create_stage_view_test_setup (MetaBackend *backend)
|
||||
{
|
||||
|
@ -296,18 +432,28 @@ init_tests (void)
|
|||
meta_test_color_management_device_basic);
|
||||
g_test_add_func ("/color-management/profile/device",
|
||||
meta_test_color_management_profile_device);
|
||||
g_test_add_func ("/color-management/profile/system",
|
||||
meta_test_color_management_profile_system);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_autoptr (MetaContext) context = NULL;
|
||||
char *path;
|
||||
|
||||
context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED,
|
||||
META_CONTEXT_TEST_FLAG_NONE);
|
||||
|
||||
g_assert (meta_context_configure (context, &argc, &argv, NULL));
|
||||
|
||||
path = g_test_build_filename (G_TEST_BUILT,
|
||||
"tests",
|
||||
"share",
|
||||
NULL);
|
||||
g_setenv ("XDG_DATA_HOME", path, TRUE);
|
||||
g_free (path);
|
||||
|
||||
test_context = context;
|
||||
|
||||
init_tests ();
|
||||
|
|
|
@ -13,7 +13,7 @@ __copyright__ = '(c) 2021 Red Hat Inc.'
|
|||
import dbus
|
||||
import os
|
||||
import pwd
|
||||
from dbusmock import MOCK_IFACE
|
||||
from dbusmock import MOCK_IFACE, mockobject
|
||||
|
||||
|
||||
BUS_PREFIX = 'org.freedesktop.ColorManager'
|
||||
|
@ -65,7 +65,9 @@ def CreateDevice(self, device_id, scope, props):
|
|||
DEVICE_IFACE,
|
||||
{
|
||||
'DeviceId': device_id,
|
||||
'Profiles': dbus.types.Array(signature='o'),
|
||||
'Enabled': True,
|
||||
'ProfilingInhibitors': dbus.types.Array(signature='s'),
|
||||
},
|
||||
[])
|
||||
self.EmitSignal(MAIN_IFACE, 'DeviceAdded', 'o', [device_path])
|
||||
|
@ -119,3 +121,32 @@ def Reset(self):
|
|||
for profile_path in self.profiles.values():
|
||||
self.RemoveObject(profile_path)
|
||||
self.profiles = {}
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='ss')
|
||||
def AddSystemProfile(self, profile_id, file_path):
|
||||
uid = os.getuid()
|
||||
username = get_username(uid)
|
||||
profile_path = PATH_PREFIX + '/profiles/' + \
|
||||
escape_unit_name(profile_id) + \
|
||||
'_' + username + '_' + str(uid)
|
||||
self.profiles[profile_id] = profile_path
|
||||
self.AddObject(profile_path,
|
||||
PROFILE_IFACE,
|
||||
{
|
||||
'ProfileId': profile_id,
|
||||
'Filename': file_path,
|
||||
'Enabled': True,
|
||||
},
|
||||
[])
|
||||
self.EmitSignal(MAIN_IFACE, 'ProfileAdded', 'o', [profile_path])
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='sas')
|
||||
def SetDeviceProfiles(self, device_id, profile_ids):
|
||||
device_path = self.devices[device_id]
|
||||
device = mockobject.objects[device_path]
|
||||
profile_paths = [
|
||||
dbus.types.ObjectPath(self.profiles[profile_id])
|
||||
for profile_id in profile_ids
|
||||
]
|
||||
device.UpdateProperties(DEVICE_IFACE, {'Profiles': dbus.types.Array(profile_paths)})
|
||||
device.EmitSignal(DEVICE_IFACE, 'Changed', '', [])
|
||||
|
|
BIN
src/tests/icc-profiles/sRGB.icc
Normal file
BIN
src/tests/icc-profiles/sRGB.icc
Normal file
Binary file not shown.
Loading…
Reference in a new issue