[gnome-settings-daemon] color: Add a D-Bus interface to the color panel
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] color: Add a D-Bus interface to the color panel
- Date: Mon, 30 Jan 2017 14:27:28 +0000 (UTC)
commit 20daa3a21aa3b819a28a7148fa43918eae730c65
Author: Richard Hughes <richard hughsie com>
Date: Wed Jan 25 14:44:29 2017 +0000
color: Add a D-Bus interface to the color panel
This allow us to set the display temperature whilst still applying a color
profile. Future patches will set this automatically much like Red Shift.
Resolves: https://bugzilla.gnome.org/show_bug.cgi?id=742149
plugins/color/gsd-color-manager.c | 178 +++++++++++++++++++++++++++++++++++++
plugins/color/gsd-color-state.c | 81 ++++++++++++++---
plugins/color/gsd-color-state.h | 7 ++
3 files changed, 253 insertions(+), 13 deletions(-)
---
diff --git a/plugins/color/gsd-color-manager.c b/plugins/color/gsd-color-manager.c
index 2cf72d2..6a1c745 100644
--- a/plugins/color/gsd-color-manager.c
+++ b/plugins/color/gsd-color-manager.c
@@ -22,6 +22,7 @@
#include <glib/gi18n.h>
#include <gdk/gdk.h>
+#include <gtk/gtk.h>
#include "gnome-settings-profile.h"
#include "gsd-color-calibrate.h"
@@ -29,10 +30,31 @@
#include "gsd-color-profiles.h"
#include "gsd-color-state.h"
+#define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
+#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
+#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon"
+
+#define GSD_COLOR_DBUS_NAME GSD_DBUS_NAME ".Color"
+#define GSD_COLOR_DBUS_PATH GSD_DBUS_PATH "/Color"
+#define GSD_COLOR_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Color"
+
+static const gchar introspection_xml[] =
+"<node>"
+" <interface name='org.gnome.SettingsDaemon.Color'>"
+" <property name='Temperature' type='u' access='readwrite'/>"
+" </interface>"
+"</node>";
+
#define GSD_COLOR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_COLOR_MANAGER,
GsdColorManagerPrivate))
struct GsdColorManagerPrivate
{
+ /* D-Bus */
+ guint name_id;
+ GDBusNodeInfo *introspection_data;
+ GDBusConnection *connection;
+ GCancellable *bus_cancellable;
+
GsdColorCalibrate *calibrate;
GsdColorProfiles *profiles;
GsdColorState *state;
@@ -124,6 +146,19 @@ gsd_color_manager_finalize (GObject *object)
gsd_color_manager_stop (manager);
+ if (manager->priv->bus_cancellable != NULL) {
+ g_cancellable_cancel (manager->priv->bus_cancellable);
+ g_clear_object (&manager->priv->bus_cancellable);
+ }
+
+ g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref);
+ g_clear_object (&manager->priv->connection);
+
+ if (manager->priv->name_id != 0) {
+ g_bus_unown_name (manager->priv->name_id);
+ manager->priv->name_id = 0;
+ }
+
g_clear_object (&manager->priv->calibrate);
g_clear_object (&manager->priv->profiles);
g_clear_object (&manager->priv->state);
@@ -131,6 +166,148 @@ gsd_color_manager_finalize (GObject *object)
G_OBJECT_CLASS (gsd_color_manager_parent_class)->finalize (object);
}
+static GVariant *
+handle_get_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error, gpointer user_data)
+{
+ GVariant *retval = NULL;
+ GsdColorManager *manager = GSD_COLOR_MANAGER (user_data);
+ GsdColorManagerPrivate *priv = manager->priv;
+
+ if (g_strcmp0 (interface_name, GSD_COLOR_DBUS_INTERFACE) != 0) {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "No such interface: %s", interface_name);
+ return NULL;
+ }
+
+ if (g_strcmp0 (property_name, "Temperature") == 0) {
+ guint temperature;
+ temperature = gsd_color_state_get_temperature (priv->state);
+ retval = g_variant_new_uint32 (temperature);
+ }
+
+ if (retval == NULL) {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Failed to get property: %s", property_name);
+ }
+
+ return retval;
+}
+
+static gboolean
+handle_set_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *value,
+ GError **error, gpointer user_data)
+{
+ GsdColorManager *manager = GSD_COLOR_MANAGER (user_data);
+ GsdColorManagerPrivate *priv = manager->priv;
+
+ if (g_strcmp0 (interface_name, GSD_COLOR_DBUS_INTERFACE) != 0) {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "No such interface: %s", interface_name);
+ return FALSE;
+ }
+
+ if (g_strcmp0 (property_name, "Temperature") == 0) {
+ guint32 temperature;
+ g_variant_get (value, "u", &temperature);
+ if (temperature < GSD_COLOR_TEMPERATURE_MIN) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "%" G_GUINT32_FORMAT "K is < min %" G_GUINT32_FORMAT "K",
+ temperature, GSD_COLOR_TEMPERATURE_MIN);
+ return FALSE;
+ }
+ if (temperature > GSD_COLOR_TEMPERATURE_MAX) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "%" G_GUINT32_FORMAT "K is > max %" G_GUINT32_FORMAT "K",
+ temperature, GSD_COLOR_TEMPERATURE_MAX);
+ return FALSE;
+ }
+ gsd_color_state_set_temperature (priv->state, temperature);
+ return TRUE;
+ }
+
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "No such property: %s", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ NULL,
+ handle_get_property,
+ handle_set_property
+};
+
+static void
+name_lost_handler_cb (GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+ g_debug ("lost name, so exiting");
+ gtk_main_quit ();
+}
+
+static void
+on_bus_gotten (GObject *source_object,
+ GAsyncResult *res,
+ GsdColorManager *manager)
+{
+ GsdColorManagerPrivate *priv = manager->priv;
+ GDBusConnection *connection;
+ GError *error = NULL;
+
+ connection = g_bus_get_finish (res, &error);
+ if (connection == NULL) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not get session bus: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ priv->connection = connection;
+
+ g_dbus_connection_register_object (connection,
+ GSD_COLOR_DBUS_PATH,
+ priv->introspection_data->interfaces[0],
+ &interface_vtable,
+ manager,
+ NULL,
+ NULL);
+
+ priv->name_id = g_bus_own_name_on_connection (connection,
+ GSD_COLOR_DBUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL,
+ name_lost_handler_cb,
+ manager,
+ NULL);
+}
+
+static void
+register_manager_dbus (GsdColorManager *manager)
+{
+ GsdColorManagerPrivate *priv = manager->priv;
+
+ priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+ g_assert (priv->introspection_data != NULL);
+
+ g_bus_get (G_BUS_TYPE_SESSION,
+ priv->bus_cancellable,
+ (GAsyncReadyCallback) on_bus_gotten,
+ manager);
+}
+
GsdColorManager *
gsd_color_manager_new (void)
{
@@ -140,6 +317,7 @@ gsd_color_manager_new (void)
manager_object = g_object_new (GSD_TYPE_COLOR_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
+ register_manager_dbus (manager_object);
}
return GSD_COLOR_MANAGER (manager_object);
diff --git a/plugins/color/gsd-color-state.c b/plugins/color/gsd-color-state.c
index 8778a44..a580633 100644
--- a/plugins/color/gsd-color-state.c
+++ b/plugins/color/gsd-color-state.c
@@ -46,6 +46,8 @@
#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon"
+static void gcm_session_set_gamma_for_all_devices (GsdColorState *state);
+
struct GsdColorStatePrivate
{
GCancellable *cancellable;
@@ -56,6 +58,7 @@ struct GsdColorStatePrivate
GdkWindow *gdk_window;
gboolean session_is_active;
GHashTable *device_assign_hash;
+ guint color_temperature;
};
static void gsd_color_state_class_init (GsdColorStateClass *klass);
@@ -169,6 +172,23 @@ gcm_session_screen_set_icc_profile (GsdColorState *state,
return TRUE;
}
+void
+gsd_color_state_set_temperature (GsdColorState *state, guint temperature)
+{
+ GsdColorStatePrivate *priv = state->priv;
+ g_return_if_fail (GSD_IS_COLOR_STATE (state));
+ priv->color_temperature = temperature;
+ gcm_session_set_gamma_for_all_devices (state);
+}
+
+guint
+gsd_color_state_get_temperature (GsdColorState *state)
+{
+ GsdColorStatePrivate *priv = state->priv;
+ g_return_val_if_fail (GSD_IS_COLOR_STATE (state), 0);
+ return priv->color_temperature;
+}
+
static gchar *
gcm_session_get_output_id (GsdColorState *state, GnomeRROutput *output)
{
@@ -360,7 +380,7 @@ out:
}
static GPtrArray *
-gcm_session_generate_vcgt (CdProfile *profile, guint size)
+gcm_session_generate_vcgt (CdProfile *profile, guint color_temperature, guint size)
{
GnomeRROutputClutItem *tmp;
GPtrArray *array = NULL;
@@ -369,6 +389,7 @@ gcm_session_generate_vcgt (CdProfile *profile, guint size)
guint i;
cmsHPROFILE lcms_profile;
CdIcc *icc = NULL;
+ CdColorRGB temp;
/* invalid size */
if (size == 0)
@@ -387,14 +408,23 @@ gcm_session_generate_vcgt (CdProfile *profile, guint size)
goto out;
}
+ /* get the color temperature */
+ if (!cd_color_get_blackbody_rgb (color_temperature, &temp)) {
+ g_warning ("failed to get blackbody for %uK", color_temperature);
+ cd_color_rgb_set (&temp, 1.0, 1.0, 1.0);
+ } else {
+ g_debug ("using VCGT gamma of %uK = %.1f,%.1f,%.1f",
+ color_temperature, temp.R, temp.G, temp.B);
+ }
+
/* create array */
array = g_ptr_array_new_with_free_func (g_free);
for (i = 0; i < size; i++) {
in = (gdouble) i / (gdouble) (size - 1);
tmp = g_new0 (GnomeRROutputClutItem, 1);
- tmp->red = cmsEvalToneCurveFloat(vcgt[0], in) * (gdouble) 0xffff;
- tmp->green = cmsEvalToneCurveFloat(vcgt[1], in) * (gdouble) 0xffff;
- tmp->blue = cmsEvalToneCurveFloat(vcgt[2], in) * (gdouble) 0xffff;
+ tmp->red = cmsEvalToneCurveFloat(vcgt[0], in) * temp.R * (gdouble) 0xffff;
+ tmp->green = cmsEvalToneCurveFloat(vcgt[1], in) * temp.G * (gdouble) 0xffff;
+ tmp->blue = cmsEvalToneCurveFloat(vcgt[2], in) * temp.B * (gdouble) 0xffff;
g_ptr_array_add (array, tmp);
}
out:
@@ -475,6 +505,7 @@ out:
static gboolean
gcm_session_device_set_gamma (GnomeRROutput *output,
CdProfile *profile,
+ guint color_temperature,
GError **error)
{
gboolean ret = FALSE;
@@ -487,7 +518,7 @@ gcm_session_device_set_gamma (GnomeRROutput *output,
ret = TRUE;
goto out;
}
- clut = gcm_session_generate_vcgt (profile, size);
+ clut = gcm_session_generate_vcgt (profile, color_temperature, size);
if (clut == NULL) {
g_set_error_literal (error,
GSD_COLOR_MANAGER_ERROR,
@@ -508,6 +539,7 @@ out:
static gboolean
gcm_session_device_reset_gamma (GnomeRROutput *output,
+ guint color_temperature,
GError **error)
{
gboolean ret;
@@ -516,6 +548,7 @@ gcm_session_device_reset_gamma (GnomeRROutput *output,
guint32 value;
GPtrArray *clut;
GnomeRROutputClutItem *data;
+ CdColorRGB temp;
/* create a linear ramp */
g_debug ("falling back to dummy ramp");
@@ -525,12 +558,22 @@ gcm_session_device_reset_gamma (GnomeRROutput *output,
ret = TRUE;
goto out;
}
+
+ /* get the color temperature */
+ if (!cd_color_get_blackbody_rgb (color_temperature, &temp)) {
+ g_warning ("failed to get blackbody for %uK", color_temperature);
+ cd_color_rgb_set (&temp, 1.0, 1.0, 1.0);
+ } else {
+ g_debug ("using reset gamma of %uK = %.1f,%.1f,%.1f",
+ color_temperature, temp.R, temp.G, temp.B);
+ }
+
for (i = 0; i < size; i++) {
value = (i * 0xffff) / (size - 1);
data = g_new0 (GnomeRROutputClutItem, 1);
- data->red = value;
- data->green = value;
- data->blue = value;
+ data->red = value * temp.R;
+ data->green = value * temp.G;
+ data->blue = value * temp.B;
g_ptr_array_add (clut, data);
}
@@ -669,6 +712,7 @@ gcm_session_device_assign_profile_connect_cb (GObject *object,
guint brightness_percentage;
GcmSessionAsyncHelper *helper = (GcmSessionAsyncHelper *) user_data;
GsdColorState *state = GSD_COLOR_STATE (helper->state);
+ GsdColorStatePrivate *priv = state->priv;
/* get properties */
ret = cd_profile_connect_finish (profile, res, &error);
@@ -720,6 +764,7 @@ gcm_session_device_assign_profile_connect_cb (GObject *object,
if (ret) {
ret = gcm_session_device_set_gamma (output,
profile,
+ priv->color_temperature,
&error);
if (!ret) {
g_warning ("failed to set %s gamma tables: %s",
@@ -730,6 +775,7 @@ gcm_session_device_assign_profile_connect_cb (GObject *object,
}
} else {
ret = gcm_session_device_reset_gamma (output,
+ priv->color_temperature,
&error);
if (!ret) {
g_warning ("failed to reset %s gamma tables: %s",
@@ -874,6 +920,7 @@ gcm_session_device_assign_connect_cb (GObject *object,
/* reset, as we want linear profiles for profiling */
ret = gcm_session_device_reset_gamma (output,
+ priv->color_temperature,
&error);
if (!ret) {
g_warning ("failed to reset %s gamma tables: %s",
@@ -1201,12 +1248,8 @@ gcm_session_profile_gamma_find_device_cb (GObject *object,
g_object_unref (device);
}
-/* We have to reset the gamma tables each time as if the primary output
- * has changed then different crtcs are going to be used.
- * See https://bugzilla.gnome.org/show_bug.cgi?id=660164 for an example */
static void
-gnome_rr_screen_output_changed_cb (GnomeRRScreen *screen,
- GsdColorState *state)
+gcm_session_set_gamma_for_all_devices (GsdColorState *state)
{
GnomeRROutput **outputs;
GsdColorStatePrivate *priv = state->priv;
@@ -1227,7 +1270,16 @@ gnome_rr_screen_output_changed_cb (GnomeRRScreen *screen,
gcm_session_profile_gamma_find_device_cb,
state);
}
+}
+/* We have to reset the gamma tables each time as if the primary output
+ * has changed then different crtcs are going to be used.
+ * See https://bugzilla.gnome.org/show_bug.cgi?id=660164 for an example */
+static void
+gnome_rr_screen_output_changed_cb (GnomeRRScreen *screen,
+ GsdColorState *state)
+{
+ gcm_session_set_gamma_for_all_devices (state);
}
static gboolean
@@ -1448,6 +1500,9 @@ gsd_color_state_init (GsdColorState *state)
g_free,
NULL);
+ /* default color temperature */
+ priv->color_temperature = GSD_COLOR_TEMPERATURE_DEFAULT;
+
priv->client = cd_client_new ();
}
diff --git a/plugins/color/gsd-color-state.h b/plugins/color/gsd-color-state.h
index ebe5850..8adb9c5 100644
--- a/plugins/color/gsd-color-state.h
+++ b/plugins/color/gsd-color-state.h
@@ -29,6 +29,10 @@ G_BEGIN_DECLS
#define GSD_COLOR_STATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_COLOR_STATE, GsdColorState))
#define GSD_IS_COLOR_STATE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_COLOR_STATE))
+#define GSD_COLOR_TEMPERATURE_MIN 1000 /* Kelvin */
+#define GSD_COLOR_TEMPERATURE_DEFAULT 6500 /* Kelvin, is RGB [1.0,1.0,1.0] */
+#define GSD_COLOR_TEMPERATURE_MAX 10000 /* Kelvin */
+
typedef struct GsdColorStatePrivate GsdColorStatePrivate;
typedef struct
@@ -48,6 +52,9 @@ GQuark gsd_color_state_error_quark (void);
GsdColorState * gsd_color_state_new (void);
void gsd_color_state_start (GsdColorState *state);
void gsd_color_state_stop (GsdColorState *state);
+void gsd_color_state_set_temperature (GsdColorState *state,
+ guint temperature);
+guint gsd_color_state_get_temperature (GsdColorState *state);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]