summaryrefslogtreecommitdiffstats
path: root/src/ege-color-prof-tracker.cpp
diff options
context:
space:
mode:
authorJon A. Cruz <jon@joncruz.org>2007-11-17 08:56:33 +0000
committerjoncruz <joncruz@users.sourceforge.net>2007-11-17 08:56:33 +0000
commit648f6d0474dc2612d640a48a2bb1370916c87c7d (patch)
treef187379028b56c998edc3a1ebeee78f586acec26 /src/ege-color-prof-tracker.cpp
parent2geom tryout: new exceptions (diff)
downloadinkscape-648f6d0474dc2612d640a48a2bb1370916c87c7d.tar.gz
inkscape-648f6d0474dc2612d640a48a2bb1370916c87c7d.zip
Adding ICC Profiles in X support
(bzr r4095)
Diffstat (limited to 'src/ege-color-prof-tracker.cpp')
-rw-r--r--src/ege-color-prof-tracker.cpp619
1 files changed, 619 insertions, 0 deletions
diff --git a/src/ege-color-prof-tracker.cpp b/src/ege-color-prof-tracker.cpp
new file mode 100644
index 000000000..2496b8dd6
--- /dev/null
+++ b/src/ege-color-prof-tracker.cpp
@@ -0,0 +1,619 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is EGE Color Profile Tracker.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Note: this file should be kept compilable as both .cpp and .c */
+
+#include <string.h>
+
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkwindow.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <gdk/gdkx.h>
+#endif /* GDK_WINDOWING_X11 */
+
+#include "ege-color-prof-tracker.h"
+
+/*
+#define GDK_ROOT_WINDOW() (gdk_x11_get_default_root_xwindow ())
+#define GDK_DISPLAY() gdk_display
+#define GDK_WINDOW_XDISPLAY(win)
+#define GDK_WINDOW_XID(win)
+#define GDK_DISPLAY_XDISPLAY(display)
+#define GDK_SCREEN_XDISPLAY(screen)
+#define GDK_SCREEN_XNUMBER(screen)
+#define GDK_SCREEN_XSCREEN(screen)
+
+#define GDK_WINDOW_XWINDOW
+#define GDK_DRAWABLE_XID(win)
+
+GdkWindow* gdk_window_lookup (GdkNativeWindow anid);
+GdkWindow* gdk_window_lookup_for_display (GdkDisplay *display,
+ GdkNativeWindow anid);
+
+GdkDisplay* gdk_x11_lookup_xdisplay (Display *xdisplay);
+
+Display* gdk_x11_display_get_xdisplay (GdkDisplay *display);
+
+Window gdk_x11_get_default_root_xwindow (void);
+gint gdk_x11_get_default_screen (void);
+Display* gdk_x11_get_default_xdisplay (void);
+int gdk_x11_screen_get_screen_number (GdkScreen *screen);
+Screen* gdk_x11_screen_get_xscreen (GdkScreen *screen);
+
+const gchar* gdk_x11_get_xatom_name (Atom xatom);
+const gchar* gdk_x11_get_xatom_name_for_display (GdkDisplay *display,
+ Atom xatom);
+ */
+
+enum {
+ CHANGED = 0,
+ LAST_SIGNAL};
+
+
+static void ege_color_prof_tracker_class_init( EgeColorProfTrackerClass* klass );
+static void ege_color_prof_tracker_init( EgeColorProfTracker* tracker );
+static void ege_color_prof_tracker_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
+static void ege_color_prof_tracker_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
+
+typedef struct _ScreenTrack {
+ GdkScreen* screen;
+#ifdef GDK_WINDOWING_X11
+ gboolean zeroSeen;
+ gboolean otherSeen;
+#endif /* GDK_WINDOWING_X11 */
+ GSList* trackers;
+ GPtrArray* profiles;
+} ScreenTrack;
+
+#ifdef GDK_WINDOWING_X11
+GdkFilterReturn x11_win_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data);
+void handle_property_change(GdkScreen* screen, const gchar* name);
+void add_x11_tracking_for_screen(GdkScreen* screen, ScreenTrack* screenTrack);
+#endif /* GDK_WINDOWING_X11 */
+
+static GObjectClass* gParentClass = 0;
+static guint signals[LAST_SIGNAL] = {0};
+
+static GSList* tracked_screens = 0;
+
+
+struct _EgeColorProfTrackerPrivate
+{
+ GtkWidget* _target;
+ gint _monitor;
+};
+
+#define EGE_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_COLOR_PROF_TRACKER_TYPE, EgeColorProfTrackerPrivate ) )
+
+
+static void target_finalized( gpointer data, GObject* where_the_object_was );
+static void window_finalized( gpointer data, GObject* where_the_object_was );
+static void event_after_cb( GtkWidget* widget, GdkEvent* event, gpointer user_data );
+static void target_hierarchy_changed_cb(GtkWidget* widget, GtkWidget* prev_top, gpointer user_data);
+static void target_screen_changed_cb(GtkWidget* widget, GdkScreen* prev_screen, gpointer user_data);
+static void screen_size_changed_cb(GdkScreen* screen, gpointer user_data);
+static void fire(GdkScreen* screen, gint monitor);
+static void clear_profile( GdkScreen* screen, guint monitor );
+static void set_profile( GdkScreen* screen, guint monitor, const guint8* data, guint len );
+
+GType ege_color_prof_tracker_get_type( void )
+{
+ static GType myType = 0;
+ if ( !myType ) {
+ static const GTypeInfo myInfo = {
+ sizeof( EgeColorProfTrackerClass ),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc)ege_color_prof_tracker_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof( EgeColorProfTracker ),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc)ege_color_prof_tracker_init,
+ NULL
+ };
+
+ myType = g_type_register_static( G_TYPE_OBJECT, "EgeColorProfTracker", &myInfo, (GTypeFlags)0 );
+ }
+
+ return myType;
+}
+
+void ege_color_prof_tracker_class_init( EgeColorProfTrackerClass* klass )
+{
+ if ( klass ) {
+ gParentClass = G_OBJECT_CLASS( g_type_class_peek_parent( klass ) );
+ GObjectClass* objClass = G_OBJECT_CLASS( klass );
+
+ objClass->get_property = ege_color_prof_tracker_get_property;
+ objClass->set_property = ege_color_prof_tracker_set_property;
+
+ signals[CHANGED] = g_signal_new( "changed",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(EgeColorProfTrackerClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private( klass, sizeof(EgeColorProfTrackerClass) );
+ }
+}
+
+
+void ege_color_prof_tracker_init( EgeColorProfTracker* tracker )
+{
+ tracker->private_data = EGE_GET_PRIVATE( tracker );
+ tracker->private_data->_target = 0;
+ tracker->private_data->_monitor = 0;
+}
+
+EgeColorProfTracker* ege_color_prof_tracker_new( GtkWidget* target )
+{
+ GObject* obj = (GObject*)g_object_new( EGE_COLOR_PROF_TRACKER_TYPE,
+ NULL );
+
+ EgeColorProfTracker* tracker = EGE_COLOR_PROF_TRACKER( obj );
+ tracker->private_data->_target = target;
+
+ g_object_weak_ref( G_OBJECT(target), target_finalized, obj );
+ g_signal_connect( G_OBJECT(target), "hierarchy-changed", G_CALLBACK( target_hierarchy_changed_cb ), obj );
+ g_signal_connect( G_OBJECT(target), "screen-changed", G_CALLBACK( target_screen_changed_cb ), obj );
+
+ /* invoke the callbacks now to connect if the widget is already visible */
+ target_hierarchy_changed_cb( target, 0, obj );
+ target_screen_changed_cb( target, 0, obj );
+
+ return tracker;
+}
+
+void ege_color_prof_tracker_get_profile( EgeColorProfTracker const * tracker, gpointer* ptr, guint* len )
+{
+ gpointer dataPos = 0;
+ guint dataLen = 0;
+ if ( tracker && tracker->private_data->_target ) {
+ GdkScreen* screen = gtk_widget_get_screen(tracker->private_data->_target);
+ GSList* curr = tracked_screens;
+ while ( curr ) {
+ ScreenTrack* screenTrack = (ScreenTrack*)curr->data;
+ if ( screenTrack->screen == screen ) {
+ if ( tracker->private_data->_monitor >= 0 && tracker->private_data->_monitor < (gint)screenTrack->profiles->len ) {
+ GByteArray* gba = (GByteArray*)g_ptr_array_index( screenTrack->profiles, tracker->private_data->_monitor );
+ if ( gba ) {
+ dataPos = gba->data;
+ dataLen = gba->len;
+ }
+ } else {
+ g_warning("No profile data tracked for the specified item.");
+ }
+ break;
+ }
+ curr = g_slist_next(curr);
+ }
+
+ }
+ if ( ptr ) {
+ *ptr = dataPos;
+ }
+ if ( len ) {
+ *len = dataLen;
+ }
+}
+
+void ege_color_prof_tracker_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
+{
+ EgeColorProfTracker* tracker = EGE_COLOR_PROF_TRACKER( obj );
+ (void)tracker;
+ (void)value;
+
+ switch ( propId ) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
+ }
+}
+
+void ege_color_prof_tracker_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
+{
+ EgeColorProfTracker* tracker = EGE_COLOR_PROF_TRACKER( obj );
+ (void)tracker;
+ (void)value;
+ switch ( propId ) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
+ }
+}
+
+
+static void track_screen( GdkScreen* screen, EgeColorProfTracker* tracker )
+{
+ GSList* curr = tracked_screens;
+ /* First remove the tracker from different screens */
+ while ( curr ) {
+ ScreenTrack* screenTrack = (ScreenTrack*)curr->data;
+ if ( screenTrack->screen != screen ) {
+ screenTrack->trackers = g_slist_remove_all(screenTrack->trackers, tracker);
+ }
+ curr = g_slist_next(curr);
+ }
+
+ curr = tracked_screens;
+ while ( curr && ((ScreenTrack*)curr->data)->screen != screen ) {
+ curr = g_slist_next(curr);
+ }
+
+ if ( curr ) {
+ /* We found the screen already being tracked */
+ ScreenTrack* screenTrack = (ScreenTrack*)curr->data;
+ GSList* trackHook = g_slist_find( screenTrack->trackers, tracker );
+ if ( !trackHook ) {
+ screenTrack->trackers = g_slist_append( screenTrack->trackers, tracker );
+ }
+ } else {
+ ScreenTrack* newTrack = g_new(ScreenTrack, 1);
+ gint numMonitors = gdk_screen_get_n_monitors(screen);
+ int i = 0;
+ newTrack->screen = screen;
+#ifdef GDK_WINDOWING_X11
+ newTrack->zeroSeen = FALSE;
+ newTrack->otherSeen = FALSE;
+#endif /* GDK_WINDOWING_X11 */
+ newTrack->trackers = g_slist_append( 0, tracker );
+ newTrack->profiles = g_ptr_array_new();
+ for ( i = 0; i < numMonitors; i++ ) {
+ g_ptr_array_add( newTrack->profiles, 0 );
+ }
+ tracked_screens = g_slist_append( tracked_screens, newTrack );
+
+ g_signal_connect( G_OBJECT(screen), "size-changed", G_CALLBACK( screen_size_changed_cb ), tracker );
+
+#ifdef GDK_WINDOWING_X11
+ add_x11_tracking_for_screen(screen, newTrack);
+#endif // GDK_WINDOWING_X11
+ }
+}
+
+
+void target_finalized( gpointer data, GObject* where_the_object_was )
+{
+ (void)data;
+ GSList* curr = tracked_screens;
+ while ( curr ) {
+ ScreenTrack* track = (ScreenTrack*)curr->data;
+ GSList* trackHook = track->trackers;
+ while ( trackHook ) {
+ if ( (void*)(((EgeColorProfTracker*)(trackHook->data))->private_data->_target) == (void*)where_the_object_was ) {
+ /* The tracked widget is now gone, remove it */
+ ((EgeColorProfTracker*)trackHook->data)->private_data->_target = 0;
+ track->trackers = g_slist_remove( track->trackers, trackHook );
+ trackHook = 0;
+ } else {
+ trackHook = g_slist_next( trackHook );
+ }
+ }
+
+ curr = g_slist_next( curr );
+ }
+}
+
+void window_finalized( gpointer data, GObject* where_the_object_was )
+{
+ (void)data;
+ (void)where_the_object_was;
+/* g_message("Window at %p is now going away", where_the_object_was); */
+}
+
+void event_after_cb( GtkWidget* widget, GdkEvent* event, gpointer user_data )
+{
+ if ( event->type == GDK_CONFIGURE ) {
+ GdkScreen* screen = gtk_widget_get_screen(widget);
+ GdkWindow* window = widget->window;
+ EgeColorProfTracker* tracker = (EgeColorProfTracker*)user_data;
+ gint monitorNum = gdk_screen_get_monitor_at_window(screen, window);
+ if ( monitorNum != tracker->private_data->_monitor ) {
+ tracker->private_data->_monitor = monitorNum;
+ g_signal_emit( G_OBJECT(tracker), signals[CHANGED], 0 );
+ }
+ }
+}
+
+void target_hierarchy_changed_cb(GtkWidget* widget, GtkWidget* prev_top, gpointer user_data)
+{
+ if ( !prev_top && gtk_widget_get_toplevel(widget) ) {
+ GtkWidget* top = gtk_widget_get_toplevel(widget);
+ if ( GTK_WIDGET_TOPLEVEL(top) ) {
+ GtkWindow* win = GTK_WINDOW(top);
+ g_signal_connect( G_OBJECT(win), "event-after", G_CALLBACK( event_after_cb ), user_data );
+ g_object_weak_ref( G_OBJECT(win), window_finalized, user_data );
+ }
+ }
+}
+
+void target_screen_changed_cb(GtkWidget* widget, GdkScreen* prev_screen, gpointer user_data)
+{
+ GdkScreen* screen = gtk_widget_get_screen(widget);
+
+ if ( screen && (screen != prev_screen) ) {
+ track_screen( screen, EGE_COLOR_PROF_TRACKER(user_data) );
+ }
+}
+
+void screen_size_changed_cb(GdkScreen* screen, gpointer user_data)
+{
+ GSList* curr = tracked_screens;
+ (void)user_data;
+/* g_message("screen size changed to (%d, %d) with %d monitors for obj:%p", */
+/* gdk_screen_get_width(screen), gdk_screen_get_height(screen), */
+/* gdk_screen_get_n_monitors(screen), */
+/* user_data); */
+ while ( curr && ((ScreenTrack*)curr->data)->screen != screen ) {
+ curr = g_slist_next(curr);
+ }
+ if ( curr ) {
+ ScreenTrack* track = (ScreenTrack*)curr->data;
+ gint numMonitors = gdk_screen_get_n_monitors(screen);
+ if ( numMonitors > (gint)track->profiles->len ) {
+ guint i = 0;
+ for ( i = track->profiles->len; i < (guint)numMonitors; i++ ) {
+ g_ptr_array_add( track->profiles, 0 );
+#ifdef GDK_WINDOWING_X11
+ {
+ gchar* name = g_strdup_printf( "_ICC_PROFILE_%d", i );
+ handle_property_change( screen, name );
+ g_free(name);
+ }
+#endif /* GDK_WINDOWING_X11 */
+ }
+ } else if ( numMonitors < (gint)track->profiles->len ) {
+/* g_message("The count of monitors decreased, remove some"); */
+ }
+ }
+}
+
+void fire(GdkScreen* screen, gint monitor)
+{
+ GSList* curr = tracked_screens;
+ while ( curr ) {
+ ScreenTrack* track = (ScreenTrack*)curr->data;
+ if ( track->screen == screen) {
+ GSList* trackHook = track->trackers;
+ while ( trackHook ) {
+ EgeColorProfTracker* tracker = (EgeColorProfTracker*)(trackHook->data);
+ if ( (monitor == -1) || (tracker->private_data->_monitor == monitor) ) {
+ g_signal_emit( G_OBJECT(tracker), signals[CHANGED], 0 );
+ }
+ trackHook = g_slist_next(trackHook);
+ }
+ }
+ curr = g_slist_next(curr);
+ }
+}
+
+static void clear_profile( GdkScreen* screen, guint monitor )
+{
+ GSList* curr = tracked_screens;
+ while ( curr && ((ScreenTrack*)curr->data)->screen != screen ) {
+ curr = g_slist_next(curr);
+ }
+ if ( curr ) {
+ ScreenTrack* track = (ScreenTrack*)curr->data;
+ guint i = 0;
+ GByteArray* previous = 0;
+ for ( i = track->profiles->len; i <= monitor; i++ ) {
+ g_ptr_array_add( track->profiles, 0 );
+ }
+ previous = (GByteArray*)g_ptr_array_index( track->profiles, monitor );
+ if ( previous ) {
+ g_byte_array_free( previous, TRUE );
+ }
+
+ track->profiles->pdata[monitor] = 0;
+ }
+}
+
+static void set_profile( GdkScreen* screen, guint monitor, const guint8* data, guint len )
+{
+ GSList* curr = tracked_screens;
+ while ( curr && ((ScreenTrack*)curr->data)->screen != screen ) {
+ curr = g_slist_next(curr);
+ }
+ if ( curr ) {
+ ScreenTrack* track = (ScreenTrack*)curr->data;
+ guint i = 0;
+ GByteArray* previous = 0;
+ for ( i = track->profiles->len; i <= monitor; i++ ) {
+ g_ptr_array_add( track->profiles, 0 );
+ }
+ previous = (GByteArray*)g_ptr_array_index( track->profiles, monitor );
+ if ( previous ) {
+ g_byte_array_free( previous, TRUE );
+ }
+
+ if ( data && len ) {
+ GByteArray* newBytes = g_byte_array_sized_new( len );
+ newBytes = g_byte_array_append( newBytes, data, len );
+ track->profiles->pdata[monitor] = newBytes;
+ } else {
+ track->profiles->pdata[monitor] = 0;
+ }
+ }
+}
+
+#ifdef GDK_WINDOWING_X11
+GdkFilterReturn x11_win_filter(GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent* x11 = (XEvent*)xevent;
+ (void)event;
+ (void)data;
+
+ if ( x11->type == PropertyNotify ) {
+ XPropertyEvent* note = (XPropertyEvent*)x11;
+ /*GdkAtom gatom = gdk_x11_xatom_to_atom(note->atom);*/
+ const gchar* name = gdk_x11_get_xatom_name(note->atom);
+ if ( strncmp("_ICC_PROFILE", name, 12 ) == 0 ) {
+ XEvent* native = (XEvent*)xevent;
+ Status stat = Success;
+ XWindowAttributes tmp;
+ stat = XGetWindowAttributes( native->xproperty.display, native->xproperty.window, &tmp );
+ if ( stat ) {
+ GdkDisplay* display = gdk_x11_lookup_xdisplay(native->xproperty.display);
+ if ( display ) {
+ gint screenCount = gdk_display_get_n_screens(display);
+ GdkScreen* targetScreen = 0;
+ gint i = 0;
+ for ( i = 0; i < screenCount; i++ ) {
+ GdkScreen* sc = gdk_display_get_screen( display, i );
+ if ( tmp.screen == GDK_SCREEN_XSCREEN(sc) ) {
+ targetScreen = sc;
+ }
+ }
+
+ handle_property_change( targetScreen, name );
+ }
+ } else {
+/* g_message("%d failed XGetWindowAttributes with %d", GPOINTER_TO_INT(data), stat); */
+ }
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+void handle_property_change(GdkScreen* screen, const gchar* name)
+{
+ Display* xdisplay = GDK_SCREEN_XDISPLAY(screen);
+ gint monitor = 0;
+ Atom atom = XInternAtom(xdisplay, name, True);
+ if ( strncmp("_ICC_PROFILE_", name, 13 ) == 0 ) {
+ gint64 tmp = g_ascii_strtoll(name + 13, NULL, 10);
+ if ( tmp != 0 && tmp != G_MAXINT64 && tmp != G_MININT64 ) {
+ monitor = (gint)tmp;
+ }
+ }
+ if ( atom != None ) {
+ Atom actualType = None;
+ int actualFormat = 0;
+ unsigned long size = 128 * 1042;
+ unsigned long nitems = 0;
+ unsigned long bytesAfter = 0;
+ unsigned char* prop = 0;
+
+ clear_profile( screen, monitor );
+
+ if ( XGetWindowProperty( xdisplay, GDK_WINDOW_XID(gdk_screen_get_root_window(screen)),
+ atom, 0, size, False, AnyPropertyType,
+ &actualType, &actualFormat, &nitems, &bytesAfter, &prop ) == Success ) {
+ if ( (actualType != None) && (bytesAfter + nitems) ) {
+ size = nitems + bytesAfter;
+ bytesAfter = 0;
+ nitems = 0;
+ if ( XGetWindowProperty( xdisplay, GDK_WINDOW_XID(gdk_screen_get_root_window(screen)),
+ atom, 0, size, False, AnyPropertyType,
+ &actualType, &actualFormat, &nitems, &bytesAfter, &prop ) == Success ) {
+ gpointer profile = g_memdup( prop, nitems );
+ set_profile( screen, monitor, (const guint8*)profile, nitems );
+ XFree(prop);
+ } else {
+ g_warning("Problem reading profile from root window");
+ }
+ } else {
+ /* clear it */
+ set_profile( screen, monitor, 0, 0 );
+ }
+ } else {
+ g_message("error loading profile property");
+ }
+ }
+ fire(screen, monitor);
+}
+
+void add_x11_tracking_for_screen(GdkScreen* screen, ScreenTrack* screenTrack)
+{
+ Display* xdisplay = GDK_SCREEN_XDISPLAY(screen);
+ GdkWindow* root = gdk_screen_get_root_window(screen);
+ if ( root ) {
+ Window rootWin = GDK_WINDOW_XID(root);
+ Atom baseAtom = XInternAtom(xdisplay, "_ICC_PROFILE", True);
+ int numWinProps = 0;
+ Atom* propArray = XListProperties(xdisplay, rootWin, &numWinProps);
+ gint i;
+
+ gdk_window_set_events(root, (GdkEventMask)(gdk_window_get_events(root) | GDK_PROPERTY_CHANGE_MASK));
+ gdk_window_add_filter(root, x11_win_filter, GINT_TO_POINTER(1));
+
+ /* Look for any profiles attached to this root window */
+ if ( propArray ) {
+ int j = 0;
+ gint numMonitors = gdk_screen_get_n_monitors(screen);
+
+ if ( baseAtom != None ) {
+ for ( i = 0; i < numWinProps; i++ ) {
+ if ( baseAtom == propArray[i] ) {
+ screenTrack->zeroSeen = TRUE;
+ handle_property_change( screen, "_ICC_PROFILE" );
+ }
+ }
+ } else {
+/* g_message("Base atom not found"); */
+ }
+
+ for ( i = 1; i < numMonitors; i++ ) {
+ gchar* name = g_strdup_printf("_ICC_PROFILE_%d", i);
+ Atom atom = XInternAtom(xdisplay, name, True);
+ if ( atom != None ) {
+ for ( j = 0; j < numWinProps; j++ ) {
+ if ( atom == propArray[j] ) {
+ screenTrack->otherSeen = TRUE;
+ handle_property_change( screen, name );
+ }
+ }
+ }
+ g_free(name);
+ }
+ XFree(propArray);
+ propArray = 0;
+ }
+ }
+}
+#endif /* GDK_WINDOWING_X11 */