[gnome-color-manager] Set _ICC_PROFILE on each Xrandr output, as well as on the root window
- From: Richard Hughes <rhughes src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-color-manager] Set _ICC_PROFILE on each Xrandr output, as well as on the root window
- Date: Wed, 4 Nov 2009 13:09:59 +0000 (UTC)
commit 062f0b088018dc4876b9860cf25ad35e8523401a
Author: Richard Hughes <richard hughsie com>
Date: Wed Nov 4 13:08:51 2009 +0000
Set _ICC_PROFILE on each Xrandr output, as well as on the root window
src/gcm-inspect.c | 103 +++++++++++++++++++++++-------
src/gcm-utils.c | 10 +++-
src/gcm-xserver.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gcm-xserver.h | 4 +-
4 files changed, 275 insertions(+), 25 deletions(-)
---
diff --git a/src/gcm-inspect.c b/src/gcm-inspect.c
index 33d2432..65dff45 100644
--- a/src/gcm-inspect.c
+++ b/src/gcm-inspect.c
@@ -29,6 +29,49 @@
#include "gcm-xserver.h"
/**
+ * gcm_inspect_print_data_info:
+ **/
+static gboolean
+gcm_inspect_print_data_info (const gchar *title, const guint8 *data, gsize length)
+{
+ gchar *description = NULL;
+ gchar *copyright = NULL;
+ GcmProfile *profile = NULL;
+ GError *error = NULL;
+ gboolean ret;
+
+ /* parse the data */
+ profile = gcm_profile_new ();
+ ret = gcm_profile_parse_data (profile, (const gchar *) data, length, &error);
+ if (!ret) {
+ egg_warning ("failed to parse data: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* print some interesting facts about the profile */
+ g_object_get (profile,
+ "description", &description,
+ "copyright", ©right,
+ NULL);
+
+ /* print title */
+ g_print ("%s\n", title);
+
+ /* TRANSLATORS: this is the ICC profile description stored in an atom in the XServer */
+ g_print (" - %s %s\n", _("Description:"), description);
+
+ /* TRANSLATORS: this is the ICC profile copyright */
+ g_print (" - %s %s\n", _("Copyright:"), copyright);
+out:
+ g_free (copyright);
+ g_free (description);
+ if (profile != NULL)
+ g_object_unref (profile);
+ return ret;
+}
+
+/**
* main:
**/
int
@@ -40,11 +83,14 @@ main (int argc, char **argv)
GError *error = NULL;
GOptionContext *context;
guint8 *data = NULL;
+ guint8 *data_tmp;
gsize length;
- GcmProfile *profile = NULL;
GcmXserver *xserver = NULL;
- gchar *description = NULL;
- gchar *copyright = NULL;
+ GnomeRROutput **outputs;
+ guint i;
+ GnomeRRScreen *rr_screen = NULL;
+ const gchar *output_name;
+ gchar *title;
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
@@ -72,32 +118,45 @@ main (int argc, char **argv)
goto out;
}
- /* parse the data */
- profile = gcm_profile_new ();
- ret = gcm_profile_parse_data (profile, (const gchar *) data, length, &error);
- if (!ret) {
- egg_warning ("failed to parse data: %s", error->message);
- g_error_free (error);
+ /* TRANSLATORS: the root window of all the screens */
+ gcm_inspect_print_data_info (_("Root window profile (deprecated):"), data, length);
+
+ /* get screen */
+ rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), NULL, NULL, &error);
+ if (rr_screen == NULL) {
+ egg_warning ("failed to get rr screen: %s", error->message);
goto out;
}
- /* print some interesting facts about the profile */
- g_object_get (profile,
- "description", &description,
- "copyright", ©right,
- NULL);
+ /* coldplug devices */
+ outputs = gnome_rr_screen_list_outputs (rr_screen);
+ for (i=0; outputs[i] != NULL; i++) {
- /* TRANSLATORS: this is the ICC profile description stored in an atom in the XServer */
- g_print ("%s %s\n", _("Profile description:"), description);
+ /* get output name */
+ output_name = gnome_rr_output_get_name (outputs[i]);
+ title = g_strdup_printf (_("Output profile '%s':"), output_name);
+
+ /* get profile from XServer */
+ ret = gcm_xserver_get_output_profile_data (xserver, output_name, &data_tmp, &length, &error);
+ if (!ret) {
+ egg_warning ("failed to get output profile data: %s", error->message);
+ /* TRANSLATORS: this is when the profile has not been set */
+ g_print ("%s %s\n", title, _("not set"));
+ g_error_free (error);
+ /* non-fatal */
+ error = NULL;
+ } else {
+ /* TRANSLATORS: the output, i.e. the flat panel */
+ gcm_inspect_print_data_info (title, data_tmp, length);
+ g_free (data_tmp);
+ }
+ g_free (title);
+ }
- /* TRANSLATORS: this is the ICC profile copyright */
- g_print ("%s %s\n", _("Profile copyright:"), copyright);
out:
g_free (data);
- g_free (copyright);
- g_free (description);
- if (profile != NULL)
- g_object_unref (profile);
+ if (rr_screen != NULL)
+ gnome_rr_screen_destroy (rr_screen);
if (xserver != NULL)
g_object_unref (xserver);
return retval;
diff --git a/src/gcm-utils.c b/src/gcm-utils.c
index 4819851..f439b41 100644
--- a/src/gcm-utils.c
+++ b/src/gcm-utils.c
@@ -273,6 +273,7 @@ gcm_utils_set_output_gamma (GnomeRROutput *output, GError **error)
GnomeRRCrtc *crtc;
gint x, y;
gchar *filename;
+ const gchar *output_name;
/* get CLUT */
clut = gcm_utils_get_clut_for_output (output, error);
@@ -292,11 +293,16 @@ gcm_utils_set_output_gamma (GnomeRROutput *output, GError **error)
if (!ret)
goto out;
+ /* set the per-output profile atoms */
+ xserver = gcm_xserver_new ();
+ output_name = gnome_rr_output_get_name (output);
+ ret = gcm_xserver_set_output_profile (xserver, output_name, filename, error);
+ if (!ret)
+ goto out;
+
/* is the monitor our primary monitor */
gnome_rr_output_get_position (output, &x, &y);
if (x == 0 && y == 0 && filename != NULL) {
- egg_debug ("setting main ICC profile atom from %s", filename);
- xserver = gcm_xserver_new ();
ret = gcm_xserver_set_root_window_profile (xserver, filename, error);
if (!ret)
goto out;
diff --git a/src/gcm-xserver.c b/src/gcm-xserver.c
index b7e4d90..54f3508 100644
--- a/src/gcm-xserver.c
+++ b/src/gcm-xserver.c
@@ -36,6 +36,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
#include "gcm-xserver.h"
@@ -70,6 +71,7 @@ G_DEFINE_TYPE (GcmXserver, gcm_xserver, G_TYPE_OBJECT)
/**
* gcm_xserver_get_root_window_profile_data:
*
+ * @xserver: a valid %GcmXserver instance
* @data: the data that is returned from the XServer. Free with g_free()
* @length: the size of the returned data, or %NULL if you don't care
* @error: a %GError that is set in the result of an error, or %NULL
@@ -136,6 +138,7 @@ out:
/**
* gcm_xserver_set_root_window_profile:
+ * @xserver: a valid %GcmXserver instance
* @filename: the filename of the ICC profile
* @error: a %GError that is set in the result of an error, or %NULL
* Return value: %TRUE for success.
@@ -152,6 +155,8 @@ gcm_xserver_set_root_window_profile (GcmXserver *xserver, const gchar *filename,
g_return_val_if_fail (GCM_IS_XSERVER (xserver), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
+ egg_debug ("setting root window ICC profile atom from %s", filename);
+
/* get contents of file */
ret = g_file_get_contents (filename, &data, &length, error);
if (!ret)
@@ -168,6 +173,7 @@ out:
/**
* gcm_xserver_set_root_window_profile_data:
+ * @xserver: a valid %GcmXserver instance
* @data: the data that is to be set to the XServer
* @length: the size of the data
* @error: a %GError that is set in the result of an error, or %NULL
@@ -215,6 +221,183 @@ out:
}
/**
+ * gcm_xserver_get_output_profile_data:
+ *
+ * @xserver: a valid %GcmXserver instance
+ * @output_name: the output name, e.g. "LVDS1"
+ * @data: the data that is returned from the XServer. Free with g_free()
+ * @length: the size of the returned data, or %NULL if you don't care
+ * @error: a %GError that is set in the result of an error, or %NULL
+ * Return value: %TRUE for success.
+ *
+ * Gets the ICC profile data from the specified output.
+ **/
+gboolean
+gcm_xserver_get_output_profile_data (GcmXserver *xserver, const gchar *output_name, guint8 **data, gsize *length, GError **error)
+{
+ gboolean ret = FALSE;
+ const gchar *atom_name;
+ gchar *data_tmp = NULL;
+ gint format;
+ gint rc = Success;
+ gulong bytes_after;
+ gulong nitems;
+ Atom atom = None;
+ Atom type;
+ gint i;
+ XRROutputInfo *output;
+ XRRScreenResources *resources = NULL;
+ GcmXserverPrivate *priv = xserver->priv;
+
+ g_return_val_if_fail (GCM_IS_XSERVER (xserver), FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ /* get the atom name */
+ atom_name = "_ICC_PROFILE";
+
+ /* get the value */
+ gdk_error_trap_push ();
+ atom = gdk_x11_get_xatom_by_name_for_display (priv->display_gdk, atom_name);
+ resources = XRRGetScreenResources (priv->display, priv->window);
+ for (i = 0; i < resources->noutput; ++i) {
+ output = XRRGetOutputInfo (priv->display, resources, resources->outputs[i]);
+ if (g_strcmp0 (output->name, output_name) == 0) {
+ rc = XRRGetOutputProperty (priv->display, resources->outputs[i],
+ atom, 0, ~0, False, False, AnyPropertyType, &type, &format, &nitems, &bytes_after, (unsigned char **) &data_tmp);
+ egg_debug ("found %s, got %i bytes", output_name, (guint) nitems);
+ }
+ XRRFreeOutputInfo (output);
+ }
+ gdk_error_trap_pop ();
+
+ /* did the call fail */
+ if (rc != Success) {
+ if (error != NULL)
+ *error = g_error_new (1, 0, "failed to get %s atom with rc %i", atom_name, rc);
+ goto out;
+ }
+
+ /* was nothing found */
+ if (nitems == 0) {
+ if (error != NULL)
+ *error = g_error_new (1, 0, "%s atom has not been set", atom_name);
+ goto out;
+ }
+
+ /* allocate the data using Glib, rather than asking the user to use XFree */
+ *data = g_new0 (guint8, nitems);
+ memcpy (*data, data_tmp, nitems);
+
+ /* copy the length */
+ if (length != NULL)
+ *length = nitems;
+
+ /* success */
+ ret = TRUE;
+out:
+ if (resources != NULL)
+ XRRFreeScreenResources (resources);
+ if (data_tmp != NULL)
+ XFree (data_tmp);
+ return ret;
+}
+
+/**
+ * gcm_xserver_set_output_profile:
+ * @xserver: a valid %GcmXserver instance
+ * @output_name: the output name, e.g. "LVDS1"
+ * @filename: the filename of the ICC profile
+ * @error: a %GError that is set in the result of an error, or %NULL
+ * Return value: %TRUE for success.
+ *
+ * Sets the ICC profile data to the specified output.
+ **/
+gboolean
+gcm_xserver_set_output_profile (GcmXserver *xserver, const gchar *output_name, const gchar *filename, GError **error)
+{
+ gboolean ret;
+ gchar *data = NULL;
+ gsize length;
+
+ g_return_val_if_fail (GCM_IS_XSERVER (xserver), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ egg_debug ("setting output '%s' ICC profile atom from %s", output_name, filename);
+
+ /* get contents of file */
+ ret = g_file_get_contents (filename, &data, &length, error);
+ if (!ret)
+ goto out;
+
+ /* send to the XServer */
+ ret = gcm_xserver_set_output_profile_data (xserver, output_name, (const guint8 *) data, length, error);
+ if (!ret)
+ goto out;
+out:
+ g_free (data);
+ return ret;
+}
+
+/**
+ * gcm_xserver_set_output_profile_data:
+ * @xserver: a valid %GcmXserver instance
+ * @output_name: the output name, e.g. "LVDS1"
+ * @data: the data that is to be set to the XServer
+ * @length: the size of the data
+ * @error: a %GError that is set in the result of an error, or %NULL
+ * Return value: %TRUE for success.
+ *
+ * Sets the ICC profile data to the specified output.
+ **/
+gboolean
+gcm_xserver_set_output_profile_data (GcmXserver *xserver, const gchar *output_name, const guint8 *data, gsize length, GError **error)
+{
+ gboolean ret = FALSE;
+ const gchar *atom_name;
+ gint rc;
+ gint i;
+ Atom atom = None;
+ XRROutputInfo *output;
+ XRRScreenResources *resources = NULL;
+ GcmXserverPrivate *priv = xserver->priv;
+
+ g_return_val_if_fail (GCM_IS_XSERVER (xserver), FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (length != 0, FALSE);
+
+ /* get the atom name */
+ atom_name = "_ICC_PROFILE";
+
+ /* get the value */
+ gdk_error_trap_push ();
+ atom = gdk_x11_get_xatom_by_name_for_display (priv->display_gdk, atom_name);
+ resources = XRRGetScreenResources (priv->display, priv->window);
+ for (i = 0; i < resources->noutput; ++i) {
+ output = XRRGetOutputInfo (priv->display, resources, resources->outputs[i]);
+ if (g_strcmp0 (output->name, output_name) == 0) {
+ egg_debug ("found %s, setting %i bytes", output_name, length);
+ XRRChangeOutputProperty (priv->display, resources->outputs[i], atom, XA_CARDINAL, 8, PropModeReplace, (unsigned char*) data, (gint)length);
+ }
+ XRRFreeOutputInfo (output);
+ }
+ rc = gdk_error_trap_pop ();
+
+ /* did the call fail */
+ if (rc != Success) {
+ if (error != NULL)
+ *error = g_error_new (1, 0, "failed to set output %s atom with rc %i", atom_name, rc);
+ goto out;
+ }
+
+ /* success */
+ ret = TRUE;
+out:
+ if (resources != NULL)
+ XRRFreeScreenResources (resources);
+ return ret;
+}
+
+/**
* gcm_xserver_get_property:
**/
static void
diff --git a/src/gcm-xserver.h b/src/gcm-xserver.h
index 9f97472..807e2d5 100644
--- a/src/gcm-xserver.h
+++ b/src/gcm-xserver.h
@@ -56,6 +56,8 @@ struct _GcmXserverClass
GType gcm_xserver_get_type (void);
GcmXserver *gcm_xserver_new (void);
+
+/* per screen */
gboolean gcm_xserver_get_root_window_profile_data (GcmXserver *xserver,
guint8 **data,
gsize *length,
@@ -68,7 +70,7 @@ gboolean gcm_xserver_set_root_window_profile (GcmXserver *xserver,
const gchar *filename,
GError **error);
-/* TODO: implement */
+/* per output */
gboolean gcm_xserver_get_output_profile_data (GcmXserver *xserver,
const gchar *output_name,
guint8 **data,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]