color: Handle profiles not initializing succesfully

We might fail with some part of the color profile construction and
initialization. For example there might be a system wide profile with
the same ID as one we attempt to add from a local ICC directory. When
this happens, we should drop these profiles, and use the ones from the
system instead.

Profiles may fail to initialize for other reasons too, e.g.
unpredictable colord errors, or other I/O issues.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2429
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2622>
This commit is contained in:
Jonas Ådahl 2022-09-13 18:25:25 +02:00 committed by Marge Bot
parent 20a98e6849
commit 94e1f8702d
3 changed files with 43 additions and 12 deletions

View File

@ -396,8 +396,17 @@ on_cd_device_connected (GObject *source_object,
static void static void
on_profile_ready (MetaColorProfile *color_profile, on_profile_ready (MetaColorProfile *color_profile,
gboolean success,
MetaColorDevice *color_device) MetaColorDevice *color_device)
{ {
if (!success)
{
g_clear_object (&color_device->device_profile);
g_cancellable_cancel (color_device->cancellable);
meta_color_device_notify_ready (color_device, FALSE);
return;
}
color_device->pending_state &= ~PENDING_PROFILE_READY; color_device->pending_state &= ~PENDING_PROFILE_READY;
maybe_finish_setup (color_device); maybe_finish_setup (color_device);
} }

View File

@ -165,7 +165,8 @@ meta_color_profile_class_init (MetaColorProfileClass *klass)
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
G_TYPE_NONE, 0); G_TYPE_NONE, 1,
G_TYPE_BOOLEAN);
} }
static void static void
@ -190,18 +191,20 @@ on_cd_profile_connected (GObject *source_object,
g_warning ("Failed to connect to colord profile %s: %s", g_warning ("Failed to connect to colord profile %s: %s",
color_profile->cd_profile_id, color_profile->cd_profile_id,
error->message); error->message);
color_profile->is_ready = TRUE;
g_signal_emit (color_profile, signals[READY], 0, FALSE);
return;
} }
else
{
g_warn_if_fail (g_strcmp0 (cd_profile_get_id (cd_profile), g_warn_if_fail (g_strcmp0 (cd_profile_get_id (cd_profile),
color_profile->cd_profile_id) == 0); color_profile->cd_profile_id) == 0);
meta_topic (META_DEBUG_COLOR, "Color profile '%s' connected", meta_topic (META_DEBUG_COLOR, "Color profile '%s' connected",
color_profile->cd_profile_id); color_profile->cd_profile_id);
}
color_profile->is_ready = TRUE; color_profile->is_ready = TRUE;
g_signal_emit (color_profile, signals[READY], 0); g_signal_emit (color_profile, signals[READY], 0, TRUE);
} }
static void static void
@ -220,10 +223,21 @@ on_cd_profile_created (GObject *source_object,
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
g_warning ("Failed to create colord color profile: %s", error->message); if (g_error_matches (error,
CD_CLIENT_ERROR, CD_CLIENT_ERROR_ALREADY_EXISTS))
{
meta_topic (META_DEBUG_COLOR, "Tried to create duplicate profile %s",
color_profile->cd_profile_id);
}
else
{
g_warning ("Failed to create colord color profile %s: %s",
color_profile->cd_profile_id,
error->message);
}
color_profile->is_ready = TRUE; color_profile->is_ready = TRUE;
g_signal_emit (color_profile, signals[READY], 0); g_signal_emit (color_profile, signals[READY], 0, FALSE);
return; return;
} }
@ -299,7 +313,7 @@ notify_ready_idle (gpointer user_data)
color_profile->notify_ready_id = 0; color_profile->notify_ready_id = 0;
color_profile->is_ready = TRUE; color_profile->is_ready = TRUE;
g_signal_emit (color_profile, signals[READY], 0); g_signal_emit (color_profile, signals[READY], 0, TRUE);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }

View File

@ -87,8 +87,16 @@ meta_color_store_init (MetaColorStore *color_store)
static void static void
on_directory_profile_ready (MetaColorProfile *color_profile, on_directory_profile_ready (MetaColorProfile *color_profile,
gboolean success,
MetaColorStore *color_store) MetaColorStore *color_store)
{ {
if (!success)
{
g_hash_table_remove (color_store->pending_local_profiles,
meta_color_profile_get_file_path (color_profile));
return;
}
g_object_ref (color_profile); g_object_ref (color_profile);
if (!g_hash_table_steal (color_store->pending_local_profiles, if (!g_hash_table_steal (color_store->pending_local_profiles,