gnome-desktop r5115 - in branches/randr-12: . desktop-docs gnome-about libgnome-desktop libgnome-desktop/libgnomeui po



Author: ssp
Date: Mon Jun 16 20:16:33 2008
New Revision: 5115
URL: http://svn.gnome.org/viewvc/gnome-desktop?rev=5115&view=rev

Log:
Merge from trunk

Modified:
   branches/randr-12/ChangeLog
   branches/randr-12/NEWS
   branches/randr-12/README
   branches/randr-12/configure.in
   branches/randr-12/desktop-docs/ChangeLog
   branches/randr-12/gnome-about/ChangeLog
   branches/randr-12/libgnome-desktop/ChangeLog
   branches/randr-12/libgnome-desktop/Makefile.am
   branches/randr-12/libgnome-desktop/display-name.c
   branches/randr-12/libgnome-desktop/edid-parse.c
   branches/randr-12/libgnome-desktop/edid.h
   branches/randr-12/libgnome-desktop/gnome-bg.c
   branches/randr-12/libgnome-desktop/gnome-rr-config.c
   branches/randr-12/libgnome-desktop/gnome-rr.c
   branches/randr-12/libgnome-desktop/libgnomeui/Makefile.am
   branches/randr-12/libgnome-desktop/libgnomeui/gnome-bg.h
   branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr-config.h
   branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr.h
   branches/randr-12/po/ChangeLog
   branches/randr-12/po/ar.po
   branches/randr-12/po/gu.po

Modified: branches/randr-12/NEWS
==============================================================================
--- branches/randr-12/NEWS	(original)
+++ branches/randr-12/NEWS	Mon Jun 16 20:16:33 2008
@@ -1,4 +1,29 @@
 ==============
+Version 2.23.3
+==============
+
+  libgnome-desktop
+
+	* GnomeBG: Fix some logic errors wrt to caching of slideshows that may
+	  cause nautilus crashes (Matthias Clasen)
+	* GnomeBG: Support multi-resolution backgrounds (Matthias Clasen)
+	* GnomeBG: Falls back to the default image if the user's background
+	  doesn't exist (Ray Strode)
+	* GnomeBG: Prevent loops caused by setting URI (SÃren Sandmann)
+	* GnomeBG: Fix leak (Kjartan Maraas)
+	* GnomeBG: Get rid of URIs and only use paths (SÃren Sandmann)
+	* GnomeBG: Make sure tiles are at least 24 pixels wide (SÃren Sandmann)
+	* GnomeBG: Some tweaks to the tile scaling heuristic (SÃren Sandmann)
+	* GnomeBG: Small fixes (SÃren Sandmann)
+	* GnomeBG: Add getters for the various properties (SÃren Sandmann)
+	* GnomeBG: Monitor the image file (SÃren Sandmann)
+
+  Translators
+
+	* Khaled Hosny (ar)
+	* Sweta Kothari (gu)
+
+==============
 Version 2.23.2
 ==============
 

Modified: branches/randr-12/README
==============================================================================
--- branches/randr-12/README	(original)
+++ branches/randr-12/README	Mon Jun 16 20:16:33 2008
@@ -1,4 +1,4 @@
-gnome-desktop 2.23.2
+gnome-desktop 2.23.3
 ====================
 
 	This package is free software and is part of the

Modified: branches/randr-12/configure.in
==============================================================================
--- branches/randr-12/configure.in	(original)
+++ branches/randr-12/configure.in	Mon Jun 16 20:16:33 2008
@@ -1,4 +1,4 @@
-AC_INIT([gnome-desktop], [2.23.3],
+AC_INIT([gnome-desktop], [2.23.4],
         [http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-desktop])
 AC_CONFIG_SRCDIR([libgnome-desktop])
 
@@ -19,7 +19,7 @@
 #   change to C+1:0:0
 # - If the interface is the same as the previous version, change to C:R+1:A
 
-LT_VERSION=6:8:4
+LT_VERSION=7:0:0
 AC_SUBST(LT_VERSION)
 
 AM_MAINTAINER_MODE
@@ -35,7 +35,7 @@
 
 GNOME_PLATFORM=2
 GNOME_MINOR=23
-GNOME_MICRO=2
+GNOME_MICRO=3
 GNOME_DISTRIBUTOR="GNOME.Org"
 GNOME_DATE=`date +"%Y-%m-%d"`
 

Modified: branches/randr-12/libgnome-desktop/Makefile.am
==============================================================================
--- branches/randr-12/libgnome-desktop/Makefile.am	(original)
+++ branches/randr-12/libgnome-desktop/Makefile.am	Mon Jun 16 20:16:33 2008
@@ -20,12 +20,7 @@
 	gnome-desktop-item.c	\
 	gnome-ditem-edit.c	\
 	gnome-hint.c		\
-	gnome-bg.c		\
-	display-name.c		\
-	gnome-rr.c		\
-	gnome-rr-config.c	\
-	edid-parse.c		\
-	edid.h
+	gnome-bg.c
 
 libgnome_desktop_2_la_LIBADD =	\
 	$(XLIB_LIBS)		\

Modified: branches/randr-12/libgnome-desktop/display-name.c
==============================================================================
--- branches/randr-12/libgnome-desktop/display-name.c	(original)
+++ branches/randr-12/libgnome-desktop/display-name.c	Mon Jun 16 20:16:33 2008
@@ -1,252 +0,0 @@
-/*
- * Copyright 2007 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* Author: Soren Sandmann <sandmann redhat com> */
-
-#include <stdlib.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-#include "edid.h"
-
-typedef struct Vendor Vendor;
-struct Vendor
-{
-    const char vendor_id[4];
-    const char vendor_name[28];
-};
-
-/* This list of vendor codes derived from lshw
- * 
- * http://ezix.org/project/wiki/HardwareLiSter
- */
-static const struct Vendor vendors[] = 
-{
-    { "AIC", "AG Neovo" },
-    { "ACR", "Acer" },
-    { "DEL", "DELL" },
-    { "SAM", "SAMSUNG" },
-    { "SNY", "SONY" },
-    { "SEC", "Epson" },
-    { "WAC", "Wacom" },
-    { "NEC", "NEC" },
-    { "CMO", "CMO" },	/* Chi Mei */
-    { "BNQ", "BenQ" },
-
-    { "ABP", "Advansys" },
-    { "ACC", "Accton" },
-    { "ACE", "Accton" },
-    { "ADP", "Adaptec" },
-    { "ADV", "AMD" },
-    { "AIR", "AIR" },
-    { "AMI", "AMI" },
-    { "ASU", "ASUS" },
-    { "ATI", "ATI" },
-    { "ATK", "Allied Telesyn" },
-    { "AZT", "Aztech" },
-    { "BAN", "Banya" },
-    { "BRI", "Boca Research" },
-    { "BUS", "Buslogic" },
-    { "CCI", "Cache Computers Inc." },
-    { "CHA", "Chase" },
-    { "CMD", "CMD Technology, Inc." },
-    { "COG", "Cogent" },
-    { "CPQ", "Compaq" },
-    { "CRS", "Crescendo" },
-    { "CSC", "Crystal" },
-    { "CSI", "CSI" },
-    { "CTL", "Creative Labs" },
-    { "DBI", "Digi" },
-    { "DEC", "Digital Equipment" },
-    { "DBK", "Databook" },
-    { "EGL", "Eagle Technology" },
-    { "ELS", "ELSA" },
-    { "ESS", "ESS" },
-    { "FAR", "Farallon" },
-    { "FDC", "Future Domain" },
-    { "HWP", "Hewlett-Packard" },
-    { "IBM", "IBM" },
-    { "INT", "Intel" },
-    { "ISA", "Iomega" },
-    { "MDG", "Madge" },
-    { "MDY", "Microdyne" },
-    { "MET", "Metheus" },
-    { "MIC", "Micronics" },
-    { "MLX", "Mylex" },
-    { "NVL", "Novell" },
-    { "OLC", "Olicom" },
-    { "PRO", "Proteon" },
-    { "RII", "Racal" },
-    { "RTL", "Realtek" },
-    { "SCM", "SCM" },
-    { "SKD", "SysKonnect" },
-    { "SGI", "SGI" },
-    { "SMC", "SMC" },
-    { "SNI", "Siemens Nixdorf" },
-    { "STL", "Stallion Technologies" },
-    { "SUN", "Sun" },
-    { "SUP", "SupraExpress" },
-    { "SVE", "SVEC" },
-    { "TCC", "Thomas-Conrad" },
-    { "TCI", "Tulip" },
-    { "TCM", "3Com" },
-    { "TCO", "Thomas-Conrad" },
-    { "TEC", "Tecmar" },
-    { "TRU", "Truevision" },
-    { "TOS", "Toshiba" },
-    { "TYN", "Tyan" },
-    { "UBI", "Ungermann-Bass" },
-    { "USC", "UltraStor" },
-    { "VDM", "Vadem" },
-    { "VMI", "Vermont" },
-    { "WDC", "Western Digital" },
-    { "ZDS", "Zeos" },
-
-    /* From http://faydoc.tripod.com/structures/01/0136.htm */
-    { "ACT", "Targa" },
-    { "ADI", "ADI" },
-    { "AOC", "AOC Intl" },
-    { "API", "Acer America" },
-    { "APP", "Apple Computer" },
-    { "ART", "ArtMedia" },
-    { "AST", "AST Research" },
-    { "CPL", "Compal" },
-    { "CTX", "Chuntex Electronic Co." },
-    { "DPC", "Delta Electronics" },
-    { "DWE", "Daewoo" },
-    { "ECS", "ELITEGROUP" },
-    { "EIZ", "EIZO" },
-    { "FCM", "Funai" },
-    { "GSM", "LG Electronics" },
-    { "GWY", "Gateway 2000" },
-    { "HEI", "Hyundai" },
-    { "HIT", "Hitachi" },
-    { "HSL", "Hansol" },
-    { "HTC", "Hitachi" },
-    { "ICL", "Fujitsu ICL" },
-    { "IVM", "Idek Iiyama" },
-    { "KFC", "KFC Computek" },
-    { "LKM", "ADLAS" },
-    { "LNK", "LINK Tech" },
-    { "LTN", "Lite-On" },
-    { "MAG", "MAG InnoVision" },
-    { "MAX", "Maxdata" },
-    { "MEI", "Panasonic" },
-    { "MEL", "Mitsubishi" },
-    { "MIR", "miro" },
-    { "MTC", "MITAC" },
-    { "NAN", "NANAO" },
-    { "NEC", "NEC Tech" },
-    { "NOK", "Nokia" },
-    { "OQI", "OPTIQUEST" },
-    { "PBN", "Packard Bell" },
-    { "PGS", "Princeton" },
-    { "PHL", "Philips" },
-    { "REL", "Relisys" },
-    { "SDI", "Samtron" },
-    { "SMI", "Smile" },
-    { "SPT", "Sceptre" },
-    { "SRC", "Shamrock Technology" },
-    { "STP", "Sceptre" },
-    { "TAT", "Tatung" },
-    { "TRL", "Royal Information Company" },
-    { "TSB", "Toshiba, Inc." },
-    { "UNM", "Unisys" },
-    { "VSC", "ViewSonic" },
-    { "WTC", "Wen Tech" },
-    { "ZCM", "Zenith Data Systems" },
-
-    { "???", "Unknown" },
-};
-
-static const char *
-find_vendor (const char *code)
-{
-    int i;
-
-    for (i = 0; i < sizeof (vendors) / sizeof (vendors[0]); ++i)
-    {
-	const Vendor *v = &(vendors[i]);
-	
-	if (strcmp (v->vendor_id, code) == 0)
-	    return v->vendor_name;
-    }
-
-    return code;
-};
-
-char *
-make_display_name (const char *output_name,
-		   const MonitorInfo *info)
-{
-    const char *vendor;
-    int width_mm, height_mm, inches;
-
-    if (output_name &&
-	(strstr ("lvds", output_name)	||
-	 strstr ("LVDS", output_name)	||
-	 strstr ("Lvds", output_name)))
-    {
-	vendor = "Laptop";
-    }
-    else if (info)
-    {
-	vendor = find_vendor (info->manufacturer_code);
-    }
-    else
-    {
-	vendor = "Unknown";
-    }
-
-    if (info && info->width_mm != -1 && info->height_mm)
-    {
-	width_mm = info->width_mm;
-	height_mm = info->height_mm;
-    }
-    else if (info && info->n_detailed_timings)
-    {
-	width_mm = info->detailed_timings[0].width_mm;
-	height_mm = info->detailed_timings[0].height_mm;
-    }
-    else
-    {
-	width_mm = -1;
-	height_mm = -1;
-    }
-    
-    if (width_mm != -1 && height_mm != -1)
-    {
-	double d = sqrt (width_mm * width_mm + height_mm * height_mm);
-
-	inches = (int)(d / 25.4 + 0.5);
-    }
-    else
-    {
-	inches = -1;
-    }
-
-    if (inches > 0)
-	return g_strdup_printf ("%s %d\"", vendor, inches);
-    else
-	return g_strdup_printf ("%s\n", vendor);
-}

Modified: branches/randr-12/libgnome-desktop/edid-parse.c
==============================================================================
--- branches/randr-12/libgnome-desktop/edid-parse.c	(original)
+++ branches/randr-12/libgnome-desktop/edid-parse.c	Mon Jun 16 20:16:33 2008
@@ -1,551 +0,0 @@
-/*
- * Copyright 2007 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* Author: Soren Sandmann <sandmann redhat com> */
-
-#include "edid.h"
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#define TRUE 1
-#define FALSE 0
-
-static int
-get_bit (int in, int bit)
-{
-    return (in & (1 << bit)) >> bit;
-}
-
-static int
-get_bits (int in, int begin, int end)
-{
-    int mask = (1 << (end - begin + 1)) - 1;
-    
-    return (in >> begin) & mask;
-}
-
-static int
-decode_header (const uchar *edid)
-{
-    if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
-	return TRUE;
-    return FALSE;
-}
-
-static int
-decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
-{
-    int is_model_year;
-    
-    /* Manufacturer Code */
-    info->manufacturer_code[0]  = get_bits (edid[0x08], 2, 6);
-    info->manufacturer_code[1]  = get_bits (edid[0x08], 0, 1) << 3;
-    info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
-    info->manufacturer_code[2]  = get_bits (edid[0x09], 0, 4);
-    info->manufacturer_code[3]  = '\0';
-    
-    info->manufacturer_code[0] += 'A' - 1;
-    info->manufacturer_code[1] += 'A' - 1;
-    info->manufacturer_code[2] += 'A' - 1;
-
-    /* Product Code */
-    info->product_code = edid[0x0b] << 8 | edid[0x0a];
-
-    /* Serial Number */
-    info->serial_number =
-	edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
-
-    /* Week and Year */
-    is_model_year = FALSE;
-    switch (edid[0x10])
-    {
-    case 0x00:
-	info->production_week = -1;
-	break;
-
-    case 0xff:
-	info->production_week = -1;
-	is_model_year = TRUE;
-	break;
-
-    default:
-	info->production_week = edid[0x10];
-	break;
-    }
-
-    if (is_model_year)
-    {
-	info->production_year = -1;
-	info->model_year = 1990 + edid[0x11];
-    }
-    else
-    {
-	info->production_year = 1990 + edid[0x11];
-	info->model_year = -1;
-    }
-
-    return TRUE;
-}
-
-static int
-decode_edid_version (const uchar *edid, MonitorInfo *info)
-{
-    info->major_version = edid[0x12];
-    info->minor_version = edid[0x13];
-
-    return TRUE;
-}
-
-static int
-decode_display_parameters (const uchar *edid, MonitorInfo *info)
-{
-    /* Digital vs Analog */
-    info->is_digital = get_bit (edid[0x14], 7);
-
-    if (info->is_digital)
-    {
-	int bits;
-	
-	static const int bit_depth[8] =
-	{
-	    -1, 6, 8, 10, 12, 14, 16, -1
-	};
-
-	static const Interface interfaces[6] =
-	{
-	    UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
-	};
-
-	bits = get_bits (edid[0x14], 4, 6);
-	info->digital.bits_per_primary = bit_depth[bits];
-
-	bits = get_bits (edid[0x14], 0, 3);
-	
-	if (bits <= 5)
-	    info->digital.interface = interfaces[bits];
-	else
-	    info->digital.interface = UNDEFINED;
-    }
-    else
-    {
-	int bits = get_bits (edid[0x14], 5, 6);
-	
-	static const double levels[][3] =
-	{
-	    { 0.7,   0.3,    1.0 },
-	    { 0.714, 0.286,  1.0 },
-	    { 1.0,   0.4,    1.4 },
-	    { 0.7,   0.0,    0.7 },
-	};
-
-	info->analog.video_signal_level = levels[bits][0];
-	info->analog.sync_signal_level = levels[bits][1];
-	info->analog.total_signal_level = levels[bits][2];
-
-	info->analog.blank_to_black = get_bit (edid[0x14], 4);
-
-	info->analog.separate_hv_sync = get_bit (edid[0x14], 3);
-	info->analog.composite_sync_on_h = get_bit (edid[0x14], 2);
-	info->analog.composite_sync_on_green = get_bit (edid[0x14], 1);
-
-	info->analog.serration_on_vsync = get_bit (edid[0x14], 0);
-    }
-
-    /* Screen Size / Aspect Ratio */
-    if (edid[0x15] == 0 && edid[0x16] == 0)
-    {
-	info->width_mm = -1;
-	info->height_mm = -1;
-	info->aspect_ratio = -1.0;
-    }
-    else if (edid[0x16] == 0)
-    {
-	info->width_mm = -1;
-	info->height_mm = -1; 
-	info->aspect_ratio = 100.0 / (edid[0x15] + 99);
-    }
-    else if (edid[0x15] == 0)
-    {
-	info->width_mm = -1;
-	info->height_mm = -1;
-	info->aspect_ratio = 100.0 / (edid[0x16] + 99);
-	info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
-    }
-    else
-    {
-	info->width_mm = 10 * edid[0x15];
-	info->height_mm = 10 * edid[0x16];
-    }
-
-    /* Gamma */
-    if (edid[0x17] == 0xFF)
-	info->gamma = -1.0;
-    else
-	info->gamma = (edid[0x17] + 100.0) / 100.0;
-
-    /* Features */
-    info->standby = get_bit (edid[0x18], 7);
-    info->suspend = get_bit (edid[0x18], 6);
-    info->active_off = get_bit (edid[0x18], 5);
-
-    if (info->is_digital)
-    {
-	info->digital.rgb444 = TRUE;
-	if (get_bit (edid[0x18], 3))
-	    info->digital.ycrcb444 = 1;
-	if (get_bit (edid[0x18], 4))
-	    info->digital.ycrcb422 = 1;
-    }
-    else
-    {
-	int bits = get_bits (edid[0x18], 3, 4);
-	ColorType color_type[4] =
-	{
-	    MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
-	};
-
-	info->analog.color_type = color_type[bits];
-    }
-
-    info->srgb_is_standard = get_bit (edid[0x18], 2);
-
-    /* In 1.3 this is called "has preferred timing" */
-    info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
-
-    /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
-    info->continuous_frequency = get_bit (edid[0x18], 0);
-    return TRUE;
-}
-
-static double
-decode_fraction (int high, int low)
-{
-    double result = 0.0;
-    int i;
-
-    high = (high << 2) | low;
-
-    for (i = 0; i < 10; ++i)
-	result += get_bit (high, i) * pow (2, i - 10);
-
-    return result;
-}
-
-static int
-decode_color_characteristics (const uchar *edid, MonitorInfo *info)
-{
-    info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
-    info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
-    info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
-    info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
-    info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
-    info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
-    info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
-    info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
-
-    return TRUE;
-}
-
-static int
-decode_established_timings (const uchar *edid, MonitorInfo *info)
-{
-    static const Timing established[][8] = 
-    {
-	{
-	    { 800, 600, 60 },
-	    { 800, 600, 56 },
-	    { 640, 480, 75 },
-	    { 640, 480, 72 },
-	    { 640, 480, 67 },
-	    { 640, 480, 60 },
-	    { 720, 400, 88 },
-	    { 720, 400, 70 }
-	},
-	{
-	    { 1280, 1024, 75 },
-	    { 1024, 768, 75 },
-	    { 1024, 768, 70 },
-	    { 1024, 768, 60 },
-	    { 1024, 768, 87 },
-	    { 832, 624, 75 },
-	    { 800, 600, 75 },
-	    { 800, 600, 72 }
-	},
-	{
-	    { 0, 0, 0 },
-	    { 0, 0, 0 },
-	    { 0, 0, 0 },
-	    { 0, 0, 0 },
-	    { 0, 0, 0 },
-	    { 0, 0, 0 },
-	    { 0, 0, 0 },
-	    { 1152, 870, 75 }
-	},
-    };
-
-    int i, j, idx;
-
-    idx = 0;
-    for (i = 0; i < 3; ++i)
-    {
-	for (j = 0; j < 8; ++j)
-	{
-	    int byte = edid[0x23 + i];
-
-	    if (get_bit (byte, j) && established[i][j].frequency != 0)
-		info->established[idx++] = established[i][j];
-	}
-    }
-    return TRUE;
-}
-
-static int
-decode_standard_timings (const uchar *edid, MonitorInfo *info)
-{
-    int i;
-    
-    for (i = 0; i < 8; i++)
-    {
-	int first = edid[0x26 + 2 * i];
-	int second = edid[0x27 + 2 * i];
-
-	if (first != 0x01 && second != 0x01)
-	{
-	    int w = 8 * (first + 31);
-	    int h;
-
-	    switch (get_bits (second, 6, 7))
-	    {
-	    case 0x00: h = (w / 16) * 10; break;
-	    case 0x01: h = (w / 4) * 3; break;
-	    case 0x02: h = (w / 5) * 4; break;
-	    case 0x03: h = (w / 16) * 9; break;
-	    }
-
-	    info->standard[i].width = w;
-	    info->standard[i].height = h;
-	    info->standard[i].frequency = get_bits (second, 0, 5) + 60;
-	}
-    }
-    
-    return TRUE;
-}
-
-static void
-decode_lf_string (const uchar *s, int n_chars, char *result)
-{
-    int i;
-    for (i = 0; i < n_chars; ++i)
-    {
-	if (s[i] == 0x0a)
-	{
-	    *result++ = '\0';
-	    break;
-	}
-	else if (s[i] == 0x00)
-	{
-	    /* Convert embedded 0's to spaces */
-	    *result++ = ' ';
-	}
-	else
-	{
-	    *result++ = s[i];
-	}
-    }
-}
-
-static void
-decode_display_descriptor (const uchar *desc,
-			   MonitorInfo *info)
-{
-    switch (desc[0x03])
-    {
-    case 0xFC:
-	decode_lf_string (desc + 5, 13, info->dsc_product_name);
-	break;
-    case 0xFF:
-	decode_lf_string (desc + 5, 13, info->dsc_serial_number);
-	break;
-    case 0xFE:
-	decode_lf_string (desc + 5, 13, info->dsc_string);
-	break;
-    case 0xFD:
-	/* Range Limits */
-	break;
-    case 0xFB:
-	/* Color Point */
-	break;
-    case 0xFA:
-	/* Timing Identifications */
-	break;
-    case 0xF9:
-	/* Color Management */
-	break;
-    case 0xF8:
-	/* Timing Codes */
-	break;
-    case 0xF7:
-	/* Established Timings */
-	break;
-    case 0x10:
-	break;
-    }
-}
-
-static void
-decode_detailed_timing (const uchar *timing,
-			DetailedTiming *detailed)
-{
-    int bits;
-    StereoType stereo[] =
-    {
-	NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
-	TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
-	FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
-    };
-    
-    detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
-    detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
-    detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
-    detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
-    detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
-    detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
-    detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
-    detailed->v_front_porch =
-	get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
-    detailed->v_sync =
-	get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
-    detailed->width_mm =  timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
-    detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
-    detailed->right_border = timing[0x0f];
-    detailed->top_border = timing[0x10];
-
-    detailed->interlaced = get_bit (timing[0x11], 7);
-
-    /* Stereo */
-    bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
-    detailed->stereo = stereo[bits];
-
-    /* Sync */
-    bits = timing[0x11];
-
-    detailed->digital_sync = get_bit (bits, 4);
-    if (detailed->digital_sync)
-    {
-	detailed->digital.composite = !get_bit (bits, 3);
-
-	if (detailed->digital.composite)
-	{
-	    detailed->digital.serrations = get_bit (bits, 2);
-	    detailed->digital.negative_vsync = FALSE;
-	}
-	else
-	{
-	    detailed->digital.serrations = FALSE;
-	    detailed->digital.negative_vsync = !get_bit (bits, 2);
-	}
-
-	detailed->digital.negative_hsync = !get_bit (bits, 0);
-    }
-    else
-    {
-	detailed->analog.bipolar = get_bit (bits, 3);
-	detailed->analog.serrations = get_bit (bits, 2);
-	detailed->analog.sync_on_green = !get_bit (bits, 1);
-    }
-}
-
-static int
-decode_descriptors (const uchar *edid, MonitorInfo *info)
-{
-    int i;
-    int timing_idx;
-    
-    timing_idx = 0;
-    
-    for (i = 0; i < 4; ++i)
-    {
-	int index = 0x36 + i * 18;
-
-	if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
-	{
-	    decode_display_descriptor (edid + index, info);
-	}
-	else
-	{
-	    decode_detailed_timing (
-		edid + index, &(info->detailed_timings[timing_idx++]));
-	}
-    }
-
-    info->n_detailed_timings = timing_idx;
-
-    return TRUE;
-}
-
-static void
-decode_check_sum (const uchar *edid,
-		  MonitorInfo *info)
-{
-    int i;
-    uchar check = 0;
-
-    for (i = 0; i < 128; ++i)
-	check += edid[i];
-
-    info->checksum = check;
-}
-
-MonitorInfo *
-decode_edid (const uchar *edid)
-{
-    MonitorInfo *info = calloc (1, sizeof (MonitorInfo));
-
-    decode_check_sum (edid, info);
-    
-    if (!decode_header (edid))
-	return NULL;
-
-    if (!decode_vendor_and_product_identification (edid, info))
-	return NULL;
-
-    if (!decode_edid_version (edid, info))
-	return NULL;
-
-    if (!decode_display_parameters (edid, info))
-	return NULL;
-
-    if (!decode_color_characteristics (edid, info))
-	return NULL;
-
-    if (!decode_established_timings (edid, info))
-	return NULL;
-
-    if (!decode_standard_timings (edid, info))
-	return NULL;
-    
-    if (!decode_descriptors (edid, info))
-	return NULL;
-    
-    return info;
-}

Modified: branches/randr-12/libgnome-desktop/edid.h
==============================================================================
--- branches/randr-12/libgnome-desktop/edid.h	(original)
+++ branches/randr-12/libgnome-desktop/edid.h	Mon Jun 16 20:16:33 2008
@@ -1,199 +0,0 @@
-/* edid.h
- *
- * Copyright 2007, 2008, Red Hat, Inc.
- * 
- * This file is part of the Gnome Library.
- * 
- * The Gnome Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * The Gnome Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- * 
- * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Author: Soren Sandmann <sandmann redhat com>
- */
-
-#ifndef EDID_H
-#define EDID_H
-
-typedef unsigned char uchar;
-typedef struct MonitorInfo MonitorInfo;
-typedef struct Timing Timing;
-typedef struct DetailedTiming DetailedTiming;
-
-typedef enum
-{
-    UNDEFINED,
-    DVI,
-    HDMI_A,
-    HDMI_B,
-    MDDI,
-    DISPLAY_PORT
-} Interface;
-
-typedef enum
-{
-    UNDEFINED_COLOR,
-    MONOCHROME,
-    RGB,
-    OTHER_COLOR
-} ColorType;
-
-typedef enum
-{
-    NO_STEREO,
-    FIELD_RIGHT,
-    FIELD_LEFT,
-    TWO_WAY_RIGHT_ON_EVEN,
-    TWO_WAY_LEFT_ON_EVEN,
-    FOUR_WAY_INTERLEAVED,
-    SIDE_BY_SIDE
-} StereoType;
-
-struct Timing
-{
-    int width;
-    int height;
-    int frequency;
-};
-
-struct DisplayDescriptor
-{
-};
-
-struct DetailedTiming
-{
-    int		pixel_clock;
-    int		h_addr;
-    int		h_blank;
-    int		h_sync;
-    int		h_front_porch;
-    int		v_addr;
-    int		v_blank;
-    int		v_sync;
-    int		v_front_porch;
-    int		width_mm;
-    int		height_mm;
-    int		right_border;
-    int		top_border;
-    int		interlaced;
-    StereoType	stereo;
-
-    int		digital_sync;
-    union
-    {
-	struct
-	{
-	    int bipolar;
-	    int serrations;
-	    int sync_on_green;
-	} analog;
-
-	struct
-	{
-	    int composite;
-	    int serrations;
-	    int negative_vsync;
-	    int negative_hsync;
-	} digital;
-    };
-};
-
-struct MonitorInfo
-{
-    int			checksum;
-    char		manufacturer_code[4];
-    int			product_code;
-    unsigned int	serial_number;
-    
-    int			production_week;	/* -1 if not specified */
-    int			production_year;	/* -1 if not specified */
-    int			model_year;		/* -1 if not specified */
-
-    int			major_version;
-    int			minor_version;
-
-    int			is_digital;
-    
-    union
-    {
-	struct
-	{
-	    int		bits_per_primary;
-	    Interface	interface;
-	    int		rgb444;
-	    int		ycrcb444;
-	    int		ycrcb422;
-	} digital;
-
-	struct
-	{
-	    double	video_signal_level;
-	    double	sync_signal_level;
-	    double	total_signal_level;
-
-	    int		blank_to_black;
-
-	    int		separate_hv_sync;
-	    int		composite_sync_on_h;
-	    int		composite_sync_on_green;
-	    int		serration_on_vsync;
-	    ColorType	color_type;
-	} analog;
-    };
-
-    int			width_mm;		/* -1 if not specified */
-    int			height_mm;		/* -1 if not specified */
-    double		aspect_ratio;		/* -1.0 if not specififed */
-
-    double		gamma;			/* -1.0 if not specified */
-
-    int			standby;
-    int			suspend;
-    int			active_off;
-
-    int			srgb_is_standard;
-    int			preferred_timing_includes_native;
-    int			continuous_frequency;
-
-    double		red_x;
-    double		red_y;
-    double		green_x;
-    double		green_y;
-    double		blue_x;
-    double		blue_y;
-    double		white_x;
-    double		white_y;
-
-    Timing		established[24];	/* Terminated by 0x0x0 */
-    Timing		standard[8];
-    
-    int			n_detailed_timings;
-    DetailedTiming	detailed_timings[4];	/* If monitor has a preferred
-						 * mode, it is the first one
-						 * (whether it has, is
-						 * determined by the 
-						 * preferred_timing_includes
-						 * bit.
-						 */
-
-    /* Optional product description */
-    char		dsc_serial_number[14];
-    char		dsc_product_name[14];
-    char		dsc_string[14];		/* Unspecified ASCII data */
-};
-
-MonitorInfo *decode_edid (const uchar *data);
-char *       make_display_name (const char        *output_name,
-				const MonitorInfo *info);
-
-#endif

Modified: branches/randr-12/libgnome-desktop/gnome-bg.c
==============================================================================
--- branches/randr-12/libgnome-desktop/gnome-bg.c	(original)
+++ branches/randr-12/libgnome-desktop/gnome-bg.c	Mon Jun 16 20:16:33 2008
@@ -46,8 +46,8 @@
 #define BG_KEY_DRAW_BACKGROUND    GNOME_BG_KEY_DIR "/draw_background"
 #define BG_KEY_PRIMARY_COLOR      GNOME_BG_KEY_DIR "/primary_color"
 #define BG_KEY_SECONDARY_COLOR    GNOME_BG_KEY_DIR "/secondary_color"
-#define BG_KEY_COLOR_SHADING_TYPE GNOME_BG_KEY_DIR "/color_shading_type"
-#define BG_KEY_PICTURE_OPTIONS    GNOME_BG_KEY_DIR "/picture_options"
+#define BG_KEY_COLOR_TYPE         GNOME_BG_KEY_DIR "/color_shading_type"
+#define BG_KEY_PICTURE_PLACEMENT  GNOME_BG_KEY_DIR "/picture_options"
 #define BG_KEY_PICTURE_OPACITY    GNOME_BG_KEY_DIR "/picture_opacity"
 #define BG_KEY_PICTURE_FILENAME   GNOME_BG_KEY_DIR "/picture_filename"
 
@@ -59,8 +59,17 @@
 	double   duration;		/* in seconds */
 	gboolean fixed;
 
-	char *file1;
-	char *file2;		/* NULL if fixed is TRUE */
+	GSList  *file1;
+	GSList  *file2;		/* NULL if fixed is TRUE */
+};
+
+typedef struct _FileSize FileSize;
+struct _FileSize
+{
+	gint width;
+	gint height;
+
+	char *file;
 };
 
 /* This is the size of the GdkRGB dither matrix, in order to avoid
@@ -77,21 +86,26 @@
 struct _GnomeBG
 {
 	GObject                 parent_instance;
-	char *			uri;
+	char *			filename;
 	GnomeBGPlacement	placement;
 	GnomeBGColorType	color_type;
-	GdkColor		c1;
-	GdkColor		c2;
+	GdkColor		primary;
+	GdkColor		secondary;
 
+ 	gint                    last_pixmap_width;
+ 	gint                    last_pixmap_height;
+
+	GFileMonitor *		file_monitor;
+
+	guint                   changed_id;
+	
 	/* Cached information, only access through cache accessor functions */
         SlideShow *		slideshow;
-	time_t			uri_mtime;
+	time_t			file_mtime;
 	GdkPixbuf *		pixbuf_cache;
 	int			timeout_id;
 
 	GList *		        file_cache;
-
-	guint                   changed_id;
 };
 
 struct _GnomeBGClass
@@ -137,8 +151,8 @@
 					double      alpha);
 
 /* Thumbnail utilities */
-static GdkPixbuf *create_thumbnail_for_uri (GnomeThumbnailFactory *factory,
-					    const char            *uri);
+static GdkPixbuf *create_thumbnail_for_filename (GnomeThumbnailFactory *factory,
+						 const char            *filename);
 static gboolean   get_thumb_annotations (GdkPixbuf             *thumb,
 					 int                   *orig_width,
 					 int                   *orig_height);
@@ -147,66 +161,96 @@
 static GdkPixbuf *get_pixbuf           (GnomeBG               *bg);
 static void       clear_cache          (GnomeBG               *bg);
 static gboolean   is_different         (GnomeBG               *bg,
-					const char            *uri);
-static time_t     get_mtime            (const char            *uri);
+					const char            *filename);
+static time_t     get_mtime            (const char            *filename);
 static GdkPixbuf *create_img_thumbnail (GnomeBG               *bg,
 					GnomeThumbnailFactory *factory,
 					GdkScreen             *screen,
 					int                    dest_width,
 					int                    dest_height);
 static SlideShow * get_as_slideshow    (GnomeBG               *bg,
-					const char 	      *uri);
+					const char 	      *filename);
 static Slide *     get_current_slide   (SlideShow 	      *show,
 		   			double    	      *alpha);
+static gboolean    slideshow_changes_with_size (SlideShow *show);
 
 static void
-set_color_from_string (const char *string,
-		       GdkColor   *colorp)
+color_from_string (const char *string,
+		   GdkColor   *colorp)
 {
 	/* If all else fails use black */
-	if (string == NULL || !gdk_color_parse (string, colorp)) {
-		gdk_color_parse ("black", colorp);
-	}
-	gdk_rgb_find_color (gdk_rgb_get_colormap (), colorp);
+	gdk_color_parse ("black", colorp);
+
+	if (!string)
+		return;
+
+	if (!gdk_color_parse (string, colorp))
+		return;
+
+	gdk_rgb_find_color (gdk_rgb_get_colormap(), colorp);
+}
+
+static char *
+color_to_string (const GdkColor *color)
+{
+	return g_strdup_printf ("#%02x%02x%02x",
+				color->red >> 8,
+				color->green >> 8,
+				color->blue >> 8);
 }
 
+static GConfEnumStringPair placement_lookup[] = {
+	{ GNOME_BG_PLACEMENT_CENTERED,    "centered" },
+	{ GNOME_BG_PLACEMENT_FILL_SCREEN, "stretched" },
+	{ GNOME_BG_PLACEMENT_SCALED,      "scaled" },
+	{ GNOME_BG_PLACEMENT_ZOOMED,      "zoom" },
+	{ GNOME_BG_PLACEMENT_TILED,       "wallpaper" },
+	{ 0, NULL }
+};
+
+static GConfEnumStringPair color_type_lookup[] = {
+	{ GNOME_BG_COLOR_SOLID,      "solid" },
+	{ GNOME_BG_COLOR_H_GRADIENT, "horizontal-gradient" },
+	{ GNOME_BG_COLOR_V_GRADIENT, "vertical-gradient" },
+	{ 0, NULL }
+};
 
 static void
-set_color_type_from_string (const char       *string,
-			    GnomeBGColorType *color_type)
+color_type_from_string (const char       *string,
+			GnomeBGColorType *color_type)
 {
 	*color_type = GNOME_BG_COLOR_SOLID;
 
-	if (string != NULL) {
-		if (!strncmp (string, "vertical-gradient", sizeof ("vertical-gradient"))) {
-                        *color_type = GNOME_BG_COLOR_V_GRADIENT;
-		} else if (!strncmp (string, "horizontal-gradient", sizeof ("horizontal-gradient"))) {
-                        *color_type = GNOME_BG_COLOR_H_GRADIENT;
-		}
+	if (string) {
+		gconf_string_to_enum (color_type_lookup,
+				      string, (int *)color_type);
 	}
 }
 
+static const char *
+color_type_to_string (GnomeBGColorType color_type)
+{
+	return gconf_enum_to_string (color_type_lookup, color_type);
+}
+
 static void
-set_placement_from_string (const char       *string,
-			   GnomeBGPlacement *placement)
+placement_from_string (const char       *string,
+		       GnomeBGPlacement *placement)
 {
 	*placement = GNOME_BG_PLACEMENT_ZOOMED;
 
-	if (string != NULL) {
-		if (!strncmp (string, "wallpaper", sizeof ("wallpaper"))) {
-			*placement = GNOME_BG_PLACEMENT_TILED;
-		} else if (!strncmp (string, "centered", sizeof ("centered"))) {
-			*placement = GNOME_BG_PLACEMENT_CENTERED;
-		} else if (!strncmp (string, "scaled", sizeof ("scaled"))) {
-			*placement = GNOME_BG_PLACEMENT_SCALED;
-		} else if (!strncmp (string, "stretched", sizeof ("stretched"))) {
-			*placement = GNOME_BG_PLACEMENT_FILL_SCREEN;
-		} else if (!strncmp (string, "zoom", sizeof ("zoom"))) {
-			*placement = GNOME_BG_PLACEMENT_ZOOMED;
-		}
+	if (string) {
+		gconf_string_to_enum (placement_lookup,
+				      string, (int *)placement);
 	}
 }
 
+static const char *
+placement_to_string (GnomeBGPlacement placement)
+{
+	return gconf_enum_to_string (placement_lookup, placement);
+}
+
 static gboolean
 do_changed (GnomeBG *bg)
 {
@@ -235,48 +279,101 @@
 				GConfClient *client)
 {
 	char    *tmp;
-	char    *uri;
+	char    *filename;
 
 	g_return_if_fail (GNOME_IS_BG (bg));
 	g_return_if_fail (client != NULL);
 
 	/* Filename */
-	uri = NULL;
+	filename = NULL;
 	tmp = gconf_client_get_string (client, BG_KEY_PICTURE_FILENAME, NULL);
 	if (tmp != NULL) {
 		if (g_utf8_validate (tmp, -1, NULL) &&
 		    g_file_test (tmp, G_FILE_TEST_EXISTS)) {
-			uri = g_strdup (tmp);
+			filename = g_strdup (tmp);
 		} else {
-			uri = g_filename_from_utf8 (tmp, -1, NULL, NULL, NULL);
+			filename = g_filename_from_utf8 (tmp, -1, NULL, NULL, NULL);
+		}
+
+		/* Fall back to default background if filename was set
+		   but no longer exists */
+		if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
+			GConfValue *default_value;
+
+			g_free (filename);
+			filename = NULL;
+
+			default_value =
+				gconf_client_get_default_from_schema (client,
+								      BG_KEY_PICTURE_FILENAME,
+								      NULL);
+			if (default_value != NULL) {
+				filename = g_strdup (gconf_value_get_string (default_value));
+				gconf_value_free (default_value);
+			}
 		}
 	}
 	g_free (tmp);
 
 	/* Colors */
 	tmp = gconf_client_get_string (client, BG_KEY_PRIMARY_COLOR, NULL);
-	set_color_from_string (tmp, &bg->c1);
+	color_from_string (tmp, &bg->primary);
 	g_free (tmp);
 
 	tmp = gconf_client_get_string (client, BG_KEY_SECONDARY_COLOR, NULL);
-	set_color_from_string (tmp, &bg->c2);
+	color_from_string (tmp, &bg->secondary);
 	g_free (tmp);
 
 	/* Color type */
-	tmp = gconf_client_get_string (client, BG_KEY_COLOR_SHADING_TYPE, NULL);
-	set_color_type_from_string (tmp, &bg->color_type);
+	tmp = gconf_client_get_string (client, BG_KEY_COLOR_TYPE, NULL);
+	color_type_from_string (tmp, &bg->color_type);
 	g_free (tmp);
 
 	/* Placement */
-	tmp = gconf_client_get_string (client, BG_KEY_PICTURE_OPTIONS, NULL);
-	set_placement_from_string (tmp, &bg->placement);
+	tmp = gconf_client_get_string (client, BG_KEY_PICTURE_PLACEMENT, NULL);
+	placement_from_string (tmp, &bg->placement);
 	g_free (tmp);
 
-	gnome_bg_set_uri (bg, uri);
+	gnome_bg_set_filename (bg, filename);
 
 	queue_changed (bg);
 }
 
+void
+gnome_bg_save_to_preferences (GnomeBG     *bg,
+			      GConfClient *client)
+{
+	const char *color_type;
+	const char *placement;
+        const gchar *filename;
+        gchar *primary;
+        gchar *secondary;
+        
+	primary = color_to_string (&bg->primary);
+	secondary = color_to_string (&bg->secondary);
+
+	color_type = color_type_to_string (bg->color_type);
+
+        if (bg->filename) {
+		filename = bg->filename;
+		placement = placement_to_string (bg->placement);
+        }
+        else {
+                filename = "(none)";
+                placement = "none";
+        }
+
+	gconf_client_set_string (client, BG_KEY_PICTURE_FILENAME, filename, NULL);
+        gconf_client_set_string (client, BG_KEY_PRIMARY_COLOR, primary, NULL);
+        gconf_client_set_string (client, BG_KEY_SECONDARY_COLOR, secondary, NULL);
+        gconf_client_set_string (client, BG_KEY_COLOR_TYPE, color_type, NULL);
+	gconf_client_set_string (client, BG_KEY_PICTURE_PLACEMENT, placement, NULL);
+
+	g_free (primary);
+	g_free (secondary);
+}
+
+
 static void
 gnome_bg_init (GnomeBG *bg)
 {
@@ -320,29 +417,29 @@
 }
 
 static gboolean
-colors_equal (const GdkColor *c1, const GdkColor *c2)
+colors_equal (const GdkColor *primary, const GdkColor *secondary)
 {
-	return  c1->red   == c2->red	&&
-		c1->green == c2->green  &&
-		c1->blue  == c2->blue;
+	return  primary->red   == secondary->red	&&
+		primary->green == secondary->green  &&
+		primary->blue  == secondary->blue;
 }
 
 void
 gnome_bg_set_color (GnomeBG *bg,
 		    GnomeBGColorType type,
-		    GdkColor *c1,
-		    GdkColor *c2)
+		    GdkColor *primary,
+		    GdkColor *secondary)
 {
 	g_return_if_fail (bg != NULL);
 
 	if (bg->color_type != type			||
-	    !colors_equal (&bg->c1, c1)			||
-	    (c2 && !colors_equal (&bg->c2, c2))) {
+	    !colors_equal (&bg->primary, primary)			||
+	    (secondary && !colors_equal (&bg->secondary, secondary))) {
 
 		bg->color_type = type;
-		bg->c1 = *c1;
-		if (c2) {
-			bg->c2 = *c2;
+		bg->primary = *primary;
+		if (secondary) {
+			bg->secondary = *secondary;
 		}
 
 		queue_changed (bg);
@@ -362,26 +459,83 @@
 	}
 }
 
+GnomeBGPlacement
+gnome_bg_get_placement (GnomeBG *bg)
+{
+	g_return_val_if_fail (bg != NULL, -1);
+
+	return bg->placement;
+}
+
+void
+gnome_bg_get_color (GnomeBG               *bg,
+		    GnomeBGColorType      *type,
+		    GdkColor              *primary,
+		    GdkColor              *secondary)
+{
+	g_return_if_fail (bg != NULL);
+
+	if (type)
+		*type = bg->color_type;
+
+	if (primary)
+		*primary = bg->primary;
+
+	if (secondary)
+		*secondary = bg->secondary;
+}
+
+const gchar *
+gnome_bg_get_filename (GnomeBG *bg)
+{
+	g_return_val_if_fail (bg != NULL, NULL);
+
+	return bg->filename;
+}
+
+static void
+file_changed (GFileMonitor *file_monitor,
+	      GFile *child,
+	      GFile *other_file,
+	      GFileMonitorEvent event_type,
+	      gpointer user_data)
+{
+	GnomeBG *bg = GNOME_BG (user_data);
+
+	clear_cache (bg);
+	queue_changed (bg);
+}
+
 void
-gnome_bg_set_uri (GnomeBG     *bg,
-		  const char  *uri)
+gnome_bg_set_filename (GnomeBG     *bg,
+		       const char  *filename)
 {
 	char *free_me = NULL;
 	
 	g_return_if_fail (bg != NULL);
 	
-	if (g_path_is_absolute (uri)) {
-		uri = free_me = g_filename_to_uri (uri, NULL, NULL);
-	}
-	
-	if (is_different (bg, uri)) {
-		char *tmp = g_strdup (uri);
-		
-		/* FIXME: maybe check that it is local */
+	if (is_different (bg, filename)) {
+		char *tmp = g_strdup (filename);
 		
-		g_free (bg->uri);
+		g_free (bg->filename);
 		
-		bg->uri = tmp;
+		bg->filename = tmp;
+		bg->file_mtime = get_mtime (bg->filename);
+
+		if (bg->file_monitor) {
+			g_object_unref (bg->file_monitor);
+			bg->file_monitor = NULL;
+		}
+
+		if (bg->filename) {
+			GFile *f = g_file_new_for_path (bg->filename);
+			
+			bg->file_monitor = g_file_monitor_file (f, 0, NULL, NULL);
+			g_signal_connect (bg->file_monitor, "changed",
+					  G_CALLBACK (file_changed), bg);
+
+			g_object_unref (f);
+		}
 		
 		clear_cache (bg);
 		
@@ -399,20 +553,20 @@
 	switch (bg->color_type)
 	{
 	case GNOME_BG_COLOR_SOLID:
-		pixel = ((bg->c1.red >> 8) << 24)      |
-			((bg->c1.green >> 8) << 16)    |
-			((bg->c1.blue >> 8) << 8)      |
+		pixel = ((bg->primary.red >> 8) << 24)      |
+			((bg->primary.green >> 8) << 16)    |
+			((bg->primary.blue >> 8) << 8)      |
 			(0xff);
 		
 		gdk_pixbuf_fill (dest, pixel);
 		break;
 		
 	case GNOME_BG_COLOR_H_GRADIENT:
-		pixbuf_draw_gradient (dest, TRUE, &(bg->c1), &(bg->c2));
+		pixbuf_draw_gradient (dest, TRUE, &(bg->primary), &(bg->secondary));
 		break;
 		
 	case GNOME_BG_COLOR_V_GRADIENT:
-		pixbuf_draw_gradient (dest, FALSE, &(bg->c1), &(bg->c2));
+		pixbuf_draw_gradient (dest, FALSE, &(bg->primary), &(bg->secondary));
 		break;
 		
 	default:
@@ -478,7 +632,7 @@
 	
 	scaled = get_scaled_pixbuf (
 		placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
-	
+
 	switch (placement) {
 	case GNOME_BG_PLACEMENT_TILED:
 		pixbuf_tile (scaled, dest);
@@ -512,6 +666,10 @@
 gnome_bg_changes_with_size (GnomeBG *bg)
 {
 	g_return_val_if_fail (bg != NULL, FALSE);
+
+	SlideShow *show = get_as_slideshow (bg, bg->filename);
+	if (show) 
+		return slideshow_changes_with_size (show);
 	
 	if (bg->color_type != GNOME_BG_COLOR_SOLID) {
 		if (!get_pixbuf (bg))
@@ -622,7 +780,17 @@
 	
 	g_return_val_if_fail (bg != NULL, NULL);
 	g_return_val_if_fail (window != NULL, NULL);
-	
+
+	if (bg->last_pixmap_width != width ||
+	    bg->last_pixmap_height != height)  {
+		if (bg->pixbuf_cache) {
+			g_object_unref (bg->pixbuf_cache);
+			bg->pixbuf_cache = NULL;
+		}
+	}
+	bg->last_pixmap_width = width;
+	bg->last_pixmap_height = height;
+
 	gnome_bg_get_pixmap_size (bg, width, height, &pm_width, &pm_height);
 	
 	if (root) {
@@ -635,7 +803,7 @@
 	
 	if (!get_pixbuf (bg) && bg->color_type == GNOME_BG_COLOR_SOLID) {
 		GdkGC *gc = gdk_gc_new (pixmap);
-		gdk_gc_set_rgb_fg_color (gc, &(bg->c1));
+		gdk_gc_set_rgb_fg_color (gc, &(bg->primary));
 		
 		gdk_draw_point (pixmap, gc, 0, 0);
 		
@@ -670,11 +838,11 @@
 	g_return_val_if_fail (bg != NULL, FALSE);
 	
 	if (bg->color_type == GNOME_BG_COLOR_SOLID) {
-		color = bg->c1;
+		color = bg->primary;
 	} else {
-		color.red = (bg->c1.red + bg->c2.red) / 2;
-		color.green = (bg->c1.green + bg->c2.green) / 2;
-		color.blue = (bg->c1.blue + bg->c2.blue) / 2;
+		color.red = (bg->primary.red + bg->secondary.red) / 2;
+		color.green = (bg->primary.green + bg->secondary.green) / 2;
+		color.blue = (bg->primary.blue + bg->secondary.blue) / 2;
 	}
 	
 	if (get_pixbuf (bg)) {
@@ -746,24 +914,16 @@
 }
 
 static gboolean
-get_original_size (const char *uri,
+get_original_size (const char *filename,
 		   int        *orig_width,
 		   int        *orig_height)
 {
-	char *filename;
 	gboolean result;
 
-	if (g_str_has_prefix (uri, "file:"))
-		filename = g_filename_from_uri (uri, NULL, NULL);
-	else 
-		filename = g_strdup (uri);
-	
         if (gdk_pixbuf_get_file_info (filename, orig_width, orig_height))
 		result = TRUE;
 	else
 		result = FALSE;
-	
-	g_free (filename);
 
 	return result;
 }
@@ -776,24 +936,26 @@
 {
 	GdkPixbuf *thumb;
 	gboolean result = FALSE;
-	const gchar *uri;
+	const gchar *filename;
 	
 	g_return_val_if_fail (bg != NULL, FALSE);
 	g_return_val_if_fail (factory != NULL, FALSE);
 	
-	if (!bg->uri)
+	if (!bg->filename)
 		return FALSE;
 	
-	uri = bg->uri;
-	thumb = create_thumbnail_for_uri (factory, uri);
+	filename = bg->filename;
+	thumb = create_thumbnail_for_filename (factory, filename);
 	
 	if (!thumb) {
-		SlideShow *show = get_as_slideshow (bg, bg->uri);
+		SlideShow *show = get_as_slideshow (bg, bg->filename);
 		if (show) {
 			double alpha;
+			FileSize *fs;
 			Slide *slide = get_current_slide (show, &alpha);
-			uri = slide->file1;
-			thumb = create_thumbnail_for_uri (factory, uri);
+			fs = slide->file1->data;
+			filename = fs->file;
+			thumb = create_thumbnail_for_filename (factory, filename);
 		}
 	}
 
@@ -805,7 +967,7 @@
 	}
 
 	if (!result) {
-		if (get_original_size (uri, width, height))
+		if (get_original_size (filename, width, height))
 			result = TRUE;
 	}
 
@@ -918,11 +1080,14 @@
 /* Implementation of the pixbuf cache */
 struct _SlideShow
 {
+	gint ref_count;
 	double start_time;
 	double total_duration;
 
 	GQueue *slides;
 	
+	gboolean changes_with_size;
+
 	/* used during parsing */
 	struct tm start_tm;
 	GQueue *stack;
@@ -930,7 +1095,8 @@
 
 static SlideShow *read_slideshow_file (const char *filename,
 				       GError     **err);
-static void       slideshow_free      (SlideShow  *show);
+static void       slideshow_ref       (SlideShow  *show);
+static void       slideshow_unref     (SlideShow  *show);
 
 static double
 now (void)
@@ -983,14 +1149,16 @@
 	GdkPixbuf *tmp;
 
 	if (gdk_pixbuf_get_width (p2) != gdk_pixbuf_get_width (p1) ||
-            gdk_pixbuf_get_height (p2) != gdk_pixbuf_get_height (p1))
-          tmp = gdk_pixbuf_scale_simple (p2, 
-                                         gdk_pixbuf_get_width (p1),
-                                         gdk_pixbuf_get_height (p1),
-                                         GDK_INTERP_BILINEAR);
-        else
-          tmp = g_object_ref (p2);
-
+            gdk_pixbuf_get_height (p2) != gdk_pixbuf_get_height (p1)) {
+		tmp = gdk_pixbuf_scale_simple (p2, 
+					       gdk_pixbuf_get_width (p1),
+					       gdk_pixbuf_get_height (p1),
+					       GDK_INTERP_BILINEAR);
+	}
+        else {
+		tmp = g_object_ref (p2);
+	}
+	
 	pixbuf_blend (tmp, result, 0, 0, -1, -1, 0, 0, alpha);
         
         g_object_unref (tmp);	
@@ -1007,7 +1175,7 @@
 struct FileCacheEntry
 {
 	FileType type;
-	char *uri;
+	char *filename;
 	union {
 		GdkPixbuf *pixbuf;
 		SlideShow *slideshow;
@@ -1018,14 +1186,14 @@
 static void
 file_cache_entry_delete (FileCacheEntry *ent)
 {
-	g_free (ent->uri);
+	g_free (ent->filename);
 	
 	switch (ent->type) {
 	case PIXBUF:
 		g_object_unref (ent->u.pixbuf);
 		break;
 	case SLIDESHOW:
-		slideshow_free (ent->u.slideshow);
+		slideshow_unref (ent->u.slideshow);
 		break;
 	case THUMBNAIL:
 		g_object_unref (ent->u.thumbnail);
@@ -1049,15 +1217,17 @@
 }
 
 static const FileCacheEntry *
-file_cache_lookup (GnomeBG *bg, FileType type, const char *uri)
+file_cache_lookup (GnomeBG *bg, FileType type, const char *filename)
 {
 	GList *list;
 
 	for (list = bg->file_cache; list != NULL; list = list->next) {
 		FileCacheEntry *ent = list->data;
 
-		if (ent && ent->type == type && strcmp (ent->uri, uri) == 0)
+		if (ent && ent->type == type &&
+		    strcmp (ent->filename, filename) == 0) {
 			return ent;
+		}
 	}
 
 	return NULL;
@@ -1066,14 +1236,14 @@
 static FileCacheEntry *
 file_cache_entry_new (GnomeBG *bg,
 		      FileType type,
-		      const char *uri)
+		      const char *filename)
 {
 	FileCacheEntry *ent = g_new0 (FileCacheEntry, 1);
 
-	g_assert (!file_cache_lookup (bg, type, uri));
+	g_assert (!file_cache_lookup (bg, type, filename));
 	
 	ent->type = type;
-	ent->uri = g_strdup (uri);
+	ent->filename = g_strdup (filename);
 
 	bg->file_cache = g_list_prepend (bg->file_cache, ent);
 
@@ -1084,77 +1254,77 @@
 
 static void
 file_cache_add_pixbuf (GnomeBG *bg,
-		       const char *uri,
+		       const char *filename,
 		       GdkPixbuf *pixbuf)
 {
-	FileCacheEntry *ent = file_cache_entry_new (bg, PIXBUF, uri);
+	FileCacheEntry *ent = file_cache_entry_new (bg, PIXBUF, filename);
 	ent->u.pixbuf = pixbuf;
 }
 
 static void
 file_cache_add_thumbnail (GnomeBG *bg,
-			  const char *uri,
+			  const char *filename,
 			  GdkPixbuf *pixbuf)
 {
-	FileCacheEntry *ent = file_cache_entry_new (bg, THUMBNAIL, uri);
+	FileCacheEntry *ent = file_cache_entry_new (bg, THUMBNAIL, filename);
 	ent->u.thumbnail = pixbuf;
 }
 
 static void
 file_cache_add_slide_show (GnomeBG *bg,
-			   const char *uri,
+			   const char *filename,
 			   SlideShow *show)
 {
-	FileCacheEntry *ent = file_cache_entry_new (bg, SLIDESHOW, uri);
+	FileCacheEntry *ent = file_cache_entry_new (bg, SLIDESHOW, filename);
 	ent->u.slideshow = show;
 }
 
 static GdkPixbuf *
-get_as_pixbuf (GnomeBG *bg, const char *uri)
+get_as_pixbuf (GnomeBG *bg, const char *filename)
 {
 	const FileCacheEntry *ent;
-	if ((ent = file_cache_lookup (bg, PIXBUF, uri))) {
+	if ((ent = file_cache_lookup (bg, PIXBUF, filename))) {
 		return ent->u.pixbuf;
 	}
 	else {
-		GdkPixbuf *pixbuf = gnome_gdk_pixbuf_new_from_uri (uri);
+		GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
 
 		if (pixbuf)
-			file_cache_add_pixbuf (bg, uri, pixbuf);
+			file_cache_add_pixbuf (bg, filename, pixbuf);
 
 		return pixbuf;
 	}
 }
 
 static SlideShow *
-get_as_slideshow (GnomeBG *bg, const char *uri)
+get_as_slideshow (GnomeBG *bg, const char *filename)
 {
 	const FileCacheEntry *ent;
-	if ((ent = file_cache_lookup (bg, SLIDESHOW, uri))) {
+	if ((ent = file_cache_lookup (bg, SLIDESHOW, filename))) {
 		return ent->u.slideshow;
 	}
 	else {
-		SlideShow *show = read_slideshow_file (uri, NULL);
+		SlideShow *show = read_slideshow_file (filename, NULL);
 
 		if (show)
-			file_cache_add_slide_show (bg, uri, show);
+			file_cache_add_slide_show (bg, filename, show);
 
 		return show;
 	}
 }
 
 static GdkPixbuf *
-get_as_thumbnail (GnomeBG *bg, GnomeThumbnailFactory *factory, const char *uri)
+get_as_thumbnail (GnomeBG *bg, GnomeThumbnailFactory *factory, const char *filename)
 {
 	const FileCacheEntry *ent;
-	if ((ent = file_cache_lookup (bg, THUMBNAIL, uri))) {
+	if ((ent = file_cache_lookup (bg, THUMBNAIL, filename))) {
 		return ent->u.thumbnail;
 	}
 	else {
-		GdkPixbuf *thumb = create_thumbnail_for_uri (factory, uri);
+		GdkPixbuf *thumb = create_thumbnail_for_filename (factory, filename);
 
 		if (thumb)
-			file_cache_add_thumbnail (bg, uri, thumb);
+			file_cache_add_thumbnail (bg, filename, thumb);
 
 		return thumb;
 	}
@@ -1200,7 +1370,7 @@
 }
 
 static time_t
-get_mtime (const char *uri)
+get_mtime (const char *filename)
 {
 	GFile     *file;
 	GFileInfo *info;
@@ -1208,8 +1378,8 @@
 	
 	mtime = (time_t)-1;
 	
-	if (uri) {
-		file = g_file_new_for_uri (uri);
+	if (filename) {
+		file = g_file_new_for_path (filename);
 		info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
 					  G_FILE_QUERY_INFO_NONE, NULL, NULL);
 		if (info) {
@@ -1225,7 +1395,7 @@
 
 static GdkPixbuf *
 scale_thumbnail (GnomeBGPlacement placement,
-		 const char *uri,
+		 const char *filename,
 		 GdkPixbuf *thumb,
 		 GdkScreen *screen,
 		 int	    dest_width,
@@ -1243,13 +1413,8 @@
 		return g_object_ref (thumb);
 	}
 	
-	/* FIXME: in case of tiled, we should probably scale the pixbuf to
-	 * be maybe dest_width/4 pixels tall. While strictly speaking incorrect,
-	 * it might give a better idea of what the background would actually look
-	 * like.
-	 */
 	if (get_thumb_annotations (thumb, &o_width, &o_height)		||
-	    (uri && get_original_size (uri, &o_width, &o_height))) {
+	    (filename && get_original_size (filename, &o_width, &o_height))) {
 		
 		int scr_height = gdk_screen_get_height (screen);
 		int scr_width = gdk_screen_get_width (screen);
@@ -1264,7 +1429,23 @@
 		
 		new_width = floor (thumb_width * f + 0.5);
 		new_height = floor (thumb_height * f + 0.5);
-		
+
+		if (placement == GNOME_BG_PLACEMENT_TILED) {
+			/* Heuristic to make sure tiles don't become so small that
+			 * they turn into a blur.
+			 *
+			 * This is strictly speaking incorrect, but the resulting
+			 * thumbnail gives a much better idea what the background
+			 * will actually look like.
+			 */
+			
+			if ((new_width < 32 || new_height < 32) &&
+			    (new_width < o_width / 4 || new_height < o_height / 4)) {
+				new_width = o_width / 4;
+				new_height = o_height / 4;
+			}
+		}
+			
 		thumb = gdk_pixbuf_scale_simple (thumb, new_width, new_height,
 						 GDK_INTERP_BILINEAR);
 	}
@@ -1281,42 +1462,57 @@
 		      int                    dest_width,
 		      int                    dest_height)
 {
-	if (bg->uri) {
-		GdkPixbuf *thumb = get_as_thumbnail (bg, factory, bg->uri);
+	if (bg->filename) {
+		GdkPixbuf *thumb = get_as_thumbnail (bg, factory, bg->filename);
 
 		if (thumb) {
 			return scale_thumbnail (
-				bg->placement, bg->uri,
+				bg->placement, bg->filename,
 				thumb, screen, dest_width, dest_height);
 		}
 		else {
-			SlideShow *show = get_as_slideshow (bg, bg->uri);
+			SlideShow *show = get_as_slideshow (bg, bg->filename);
 			
 			if (show) {
 				double alpha;
-				Slide *slide = get_current_slide (show, &alpha);
+				Slide *slide;
+
+				slideshow_ref (show);
+
+				slide = get_current_slide (show, &alpha);
 
 				if (slide->fixed) {
 					GdkPixbuf *tmp;
+					FileSize *fs;
 					
-					tmp = get_as_thumbnail (bg, factory, slide->file1);
+					fs = slide->file1->data;
+					tmp = get_as_thumbnail (bg, factory, fs->file);
 
 					thumb = scale_thumbnail (
-						bg->placement, bg->uri,
+						bg->placement, fs->file,
 						tmp, screen, dest_width, dest_height);
 				}
 				else {
-					GdkPixbuf *p1 = get_as_thumbnail (bg, factory, slide->file1);
-					GdkPixbuf *p2 = get_as_thumbnail (bg, factory, slide->file2);
+					FileSize *fs;
+					GdkPixbuf *p1, *p2;
+
+					fs = slide->file1->data;
+					p1 = get_as_thumbnail (bg, factory, fs->file);
+
+					fs = slide->file2->data;
+					p2 = get_as_thumbnail (bg, factory, fs->file);
 
 					if (p1 && p2) {
 						GdkPixbuf *thumb1, *thumb2;
 
+						fs = slide->file1->data;
 						thumb1 = scale_thumbnail (
-							bg->placement, bg->uri,
+							bg->placement, fs->file,
 							p1, screen, dest_width, dest_height);
+
+						fs = slide->file2->data;
 						thumb2 = scale_thumbnail (
-							bg->placement, bg->uri,
+							bg->placement, fs->file,
 							p2, screen, dest_width, dest_height);
 
 						thumb = blend (thumb1, thumb2, alpha);
@@ -1327,6 +1523,8 @@
 				}
 
 				ensure_timeout (bg, slide);
+
+				slideshow_unref (show);
 			}
 		}
 
@@ -1336,6 +1534,51 @@
 	return NULL;
 }
 
+/*
+ * Find the FileSize that best matches the given size.
+ * Do two passes; the first pass only considers FileSizes
+ * that are larger than the given size.
+ * We are looking for the image that best matches the aspect ratio.
+ * When two images have the same aspect ratio, prefer the one whose
+ * width is closer to the given width.
+ */
+static FileSize *
+find_best_size (GSList *sizes, gint width, gint height)
+{
+	GSList *s;
+	gdouble a, d, distance;
+	FileSize *best = NULL;
+	gint pass;
+
+	a = width/(gdouble)height;
+	distance = 10000.0;
+
+	for (pass = 0; pass < 2; pass++) {
+		for (s = sizes; s; s = s->next) {
+			FileSize *size = s->data;
+
+			if (pass == 0 && (size->width < width || size->height < height))
+				continue;       
+
+			d = fabs (a - size->width/(gdouble)size->height);
+			if (d < distance) {
+				distance = d;
+				best = size;
+			} 
+			else if (d == distance) {
+				if (abs (size->width - width) < abs (best->width - width)) {
+					best = size;
+				}
+			}
+		}
+
+		if (best)
+			break;
+	}
+
+	return best;
+}
+
 static GdkPixbuf *
 get_pixbuf (GnomeBG *bg)
 {
@@ -1343,24 +1586,35 @@
 	
 	gboolean ref = FALSE;
 	
-	if (!bg->pixbuf_cache && bg->uri) {
+	if (!bg->pixbuf_cache && bg->filename) {
 		ref = TRUE;
-		bg->uri_mtime = get_mtime (bg->uri);
+		bg->file_mtime = get_mtime (bg->filename);
 		
-		bg->pixbuf_cache = get_as_pixbuf (bg, bg->uri);
+		bg->pixbuf_cache = get_as_pixbuf (bg, bg->filename);
 		if (!bg->pixbuf_cache) {
-			SlideShow *show = get_as_slideshow (bg, bg->uri);
+			SlideShow *show = get_as_slideshow (bg, bg->filename);
 
 			if (show) {
 				double alpha;
-				Slide *slide = get_current_slide (show, &alpha);
+				Slide *slide;
+
+				slideshow_ref (show);
+
+				slide = get_current_slide (show, &alpha);
 
 				if (slide->fixed) {
-					bg->pixbuf_cache = get_as_pixbuf (bg, slide->file1);
+					FileSize *size;
+					size = find_best_size (slide->file1, bg->last_pixmap_width, bg->last_pixmap_height);
+					bg->pixbuf_cache = get_as_pixbuf (bg, size->file);
 				}
 				else {
-					GdkPixbuf *p1 = get_as_pixbuf (bg, slide->file1);
-					GdkPixbuf *p2 = get_as_pixbuf (bg, slide->file2);
+					FileSize *size;
+					GdkPixbuf *p1, *p2;
+					size = find_best_size (slide->file1, bg->last_pixmap_width, bg->last_pixmap_height);
+					p1 = get_as_pixbuf (bg, size->file);
+					size = find_best_size (slide->file2, bg->last_pixmap_width, bg->last_pixmap_height);
+					p2 = get_as_pixbuf (bg, size->file);
+
 
 					if (p1 && p2) {
 						bg->pixbuf_cache = blend (p1, p2, alpha);
@@ -1369,6 +1623,8 @@
 				}
 
 				ensure_timeout (bg, slide);
+
+				slideshow_unref (show);
 			}
 		}
 	}
@@ -1381,24 +1637,24 @@
 
 static gboolean
 is_different (GnomeBG    *bg,
-	      const char *uri)
+	      const char *filename)
 {
-	if (!uri && bg->uri) {
+	if (!filename && bg->filename) {
 		return TRUE;
 	}
-	else if (uri && !bg->uri) {
+	else if (filename && !bg->filename) {
 		return TRUE;
 	}
-	else if (!uri && !bg->uri) {
+	else if (!filename && !bg->filename) {
 		return FALSE;
 	}
 	else {
-		time_t mtime = get_mtime (uri);
+		time_t mtime = get_mtime (filename);
 		
-		if (mtime != bg->uri_mtime)
+		if (mtime != bg->file_mtime)
 			return TRUE;
 		
-		if (strcmp (uri, bg->uri) != 0)
+		if (strcmp (filename, bg->filename) != 0)
 			return TRUE;
 		
 		return FALSE;
@@ -1533,8 +1789,8 @@
 }
 
 static guchar *
-create_gradient (const GdkColor *c1,
-		 const GdkColor *c2,
+create_gradient (const GdkColor *primary,
+		 const GdkColor *secondary,
 		 int	          n_pixels)
 {
 	guchar *result = g_malloc (n_pixels * 3);
@@ -1543,9 +1799,9 @@
 	for (i = 0; i < n_pixels; ++i) {
 		double ratio = (i + 0.5) / n_pixels;
 		
-		result[3 * i + 0] = ((guint16) (c1->red * (1 - ratio) + c2->red * ratio)) >> 8;
-		result[3 * i + 1] = ((guint16) (c1->green * (1 - ratio) + c2->green * ratio)) >> 8;
-		result[3 * i + 2] = ((guint16) (c1->blue * (1 - ratio) + c2->blue * ratio)) >> 8;
+		result[3 * i + 0] = ((guint16) (primary->red * (1 - ratio) + secondary->red * ratio)) >> 8;
+		result[3 * i + 1] = ((guint16) (primary->green * (1 - ratio) + secondary->green * ratio)) >> 8;
+		result[3 * i + 2] = ((guint16) (primary->blue * (1 - ratio) + secondary->blue * ratio)) >> 8;
 	}
 	
 	return result;
@@ -1554,8 +1810,8 @@
 static void
 pixbuf_draw_gradient (GdkPixbuf *pixbuf,
 		      gboolean   horizontal,
-		      GdkColor  *c1,
-		      GdkColor  *c2)
+		      GdkColor  *primary,
+		      GdkColor  *secondary)
 {
 	int width  = gdk_pixbuf_get_width (pixbuf);
 	int height = gdk_pixbuf_get_height (pixbuf);
@@ -1564,7 +1820,7 @@
 	guchar *dst_limit = dst + height * rowstride;
 	
 	if (horizontal) {
-		guchar *gradient = create_gradient (c1, c2, width);
+		guchar *gradient = create_gradient (primary, secondary, width);
 		int copy_bytes_per_row = width * 3;
 		
 		while (dst < dst_limit) {
@@ -1575,7 +1831,7 @@
 	} else {
 		guchar *gb, *gradient;
 		
-		gb = gradient = create_gradient (c1, c2, height);
+		gb = gradient = create_gradient (primary, secondary, height);
 		while (dst < dst_limit) {
 			int i;
 			guchar *d = dst;
@@ -1656,6 +1912,7 @@
 	}
 }
 
+static gboolean stack_is (SlideShow *parser, const char *s1, ...);
 
 /* Parser for fading background */
 static void
@@ -1667,6 +1924,7 @@
 		      GError             **err)
 {
 	SlideShow *parser = user_data;
+	gint i;
 	
 	if (strcmp (name, "static") == 0 || strcmp (name, "transition") == 0) {
 		Slide *slide = g_new0 (Slide, 1);
@@ -1676,7 +1934,25 @@
 		
 		g_queue_push_tail (parser->slides, slide);
 	}
-	
+	else if (strcmp (name, "size") == 0) {
+		Slide *slide = parser->slides->tail->data;
+		FileSize *size = g_new0 (FileSize, 1);
+		for (i = 0; attr_names[i]; i++) {
+			if (strcmp (attr_names[i], "width") == 0)
+				size->width = atoi (attr_values[i]);
+			else if (strcmp (attr_names[i], "height") == 0)
+				size->height = atoi (attr_values[i]);
+		}
+		if (parser->stack->tail &&
+		    (strcmp (parser->stack->tail->data, "file") == 0 ||
+		     strcmp (parser->stack->tail->data, "from") == 0)) {
+			slide->file1 = g_slist_prepend (slide->file1, size);
+		}
+		else if (parser->stack->tail &&
+			 strcmp (parser->stack->tail->data, "to") == 0) { 
+			slide->file2 = g_slist_prepend (slide->file2, size);
+		}
+	}
 	g_queue_push_tail (parser->stack, g_strdup (name));
 }
 
@@ -1735,21 +2011,6 @@
 	return strtol (text, NULL, 0);
 }
 
-static char *
-make_uri (char *file)
-{
-	if (g_path_is_absolute (file)) {
-		char *result = g_filename_to_uri (file, NULL, NULL);
-
-		g_free (file);
-
-		return result;
-	}
-	else {
-		return file;
-	}
-}
-
 static void
 handle_text (GMarkupParseContext *context,
 	     const gchar         *text,
@@ -1759,6 +2020,8 @@
 {
 	SlideShow *parser = user_data;
 	Slide *slide = parser->slides->tail? parser->slides->tail->data : NULL;
+	FileSize *fs;
+	gint i;
 
 	if (stack_is (parser, "year", "starttime", "background", NULL)) {
 		parser->start_tm.tm_year = parse_int (text) - 1900;
@@ -1785,28 +2048,87 @@
 	}
 	else if (stack_is (parser, "file", "static", "background", NULL) ||
 		 stack_is (parser, "from", "transition", "background", NULL)) {
-		slide->file1 = g_strdup (text);
-		slide->file1 = make_uri (slide->file1);
+		for (i = 0; text[i]; i++) {
+			if (!g_ascii_isspace (text[i]))
+				break;
+		}
+		if (text[i] == 0)
+			return;
+		fs = g_new (FileSize, 1);
+		fs->width = -1;
+		fs->height = -1;
+		fs->file = g_strdup (text);
+		slide->file1 = g_slist_prepend (slide->file1, fs);
+		if (slide->file1->next != NULL)
+			parser->changes_with_size = TRUE;                       
+	}
+	else if (stack_is (parser, "size", "file", "static", "background", NULL) ||
+		 stack_is (parser, "size", "from", "transition", "background", NULL)) {
+		fs = slide->file1->data;
+		fs->file = g_strdup (text);
+		if (slide->file1->next != NULL)
+			parser->changes_with_size = TRUE; 
 	}
 	else if (stack_is (parser, "to", "transition", "background", NULL)) {
-		slide->file2 = g_strdup (text);
-		slide->file2 = make_uri (slide->file2);
+		for (i = 0; text[i]; i++) {
+			if (!g_ascii_isspace (text[i]))
+				break;
+		}
+		if (text[i] == 0)
+			return;
+		fs = g_new (FileSize, 1);
+		fs->width = -1;
+		fs->height = -1;
+		fs->file = g_strdup (text);
+		slide->file2 = g_slist_prepend (slide->file2, fs);
+		if (slide->file2->next != NULL)
+			parser->changes_with_size = TRUE;                       
 	}
+	else if (stack_is (parser, "size", "to", "transition", "background", NULL)) {
+		fs = slide->file2->data;
+		fs->file = g_strdup (text);
+		if (slide->file2->next != NULL)
+			parser->changes_with_size = TRUE;
+	}
+}
+
+static void
+slideshow_ref (SlideShow *show)
+{
+	show->ref_count++;
 }
 
 static void
-slideshow_free (SlideShow *show)
+slideshow_unref (SlideShow *show)
 {
 	GList *list;
-	
+	GSList *slist;
+	FileSize *size;
+
+	show->ref_count--;
+	if (show->ref_count > 0)
+		return;
+
 	for (list = show->slides->head; list != NULL; list = list->next) {
 		Slide *slide = list->data;
-		
-		g_free (slide->file1);
-		g_free (slide->file2);
+
+		for (slist = slide->file1; slist != NULL; slist = slist->next) {
+			size = slist->data;
+			g_free (size->file);
+			g_free (size);
+		}
+		g_slist_free (slide->file1);
+
+		for (slist = slide->file2; slist != NULL; slist = slist->next) {
+			size = slist->data;
+			g_free (size->file);
+			g_free (size);
+		}
+		g_slist_free (slide->file2);
+
 		g_free (slide);
 	}
-	
+
 	g_queue_free (show->slides);
 	
 	for (list = show->stack->head; list != NULL; list = list->next) {
@@ -1825,15 +2147,26 @@
 {
 #if 0
 	GList *list;
+	GSList *slist;
 	
 	for (list = show->slides->head; list != NULL; list = list->next)
 	{
 		Slide *slide = list->data;
 		
 		g_print ("\nSlide: %s\n", slide->fixed? "fixed" : "transition");
-		g_print ("duration: %d\n", slide->duration);
-		g_print ("file1: %p %s\n", slide, slide->file1);
-		g_print ("file2: %s\n", slide->file2);
+		g_print ("duration: %f\n", slide->duration);
+		g_print ("File1:\n");
+		for (slist = slide->file1; slist != NULL; slist = slist->next) {
+			FileSize *size = slist->data;
+			g_print ("\t%s (%dx%d)\n", 
+				 size->file, size->width, size->height);
+		}
+		g_print ("File2:\n");
+		for (slist = slide->file2; slist != NULL; slist = slist->next) {
+			FileSize *size = slist->data;
+			g_print ("\t%s (%dx%d)\n", 
+				 size->file, size->width, size->height);
+		}
 	}
 #endif
 }
@@ -1856,7 +2189,7 @@
 }
 
 static SlideShow *
-read_slideshow_file (const char *uri,
+read_slideshow_file (const char *filename,
 		     GError     **err)
 {
 	GMarkupParser parser = {
@@ -1874,10 +2207,10 @@
 	GMarkupParseContext *context = NULL;
 	time_t t;
 
-	if (!uri)
+	if (!filename)
 		return NULL;
 
-	file = g_file_new_for_uri (uri);
+	file = g_file_new_for_path (filename);
 	if (!g_file_load_contents (file, NULL, &contents, &len, NULL, NULL)) {
 		g_object_unref (file);
 		return NULL;
@@ -1885,6 +2218,7 @@
 	g_object_unref (file);
 	
 	show = g_new0 (SlideShow, 1);
+	show->ref_count = 1;
 	threadsafe_localtime ((time_t)0, &show->start_tm);
 	show->stack = g_queue_new ();
 	show->slides = g_queue_new ();
@@ -1892,13 +2226,14 @@
 	context = g_markup_parse_context_new (&parser, 0, show, NULL);
 	
 	if (!g_markup_parse_context_parse (context, contents, len, err)) {
-		slideshow_free (show);
+		slideshow_unref (show);
 		show = NULL;
 	}
 	
-	if (!g_markup_parse_context_end_parse (context, err)) {
-		if (show) {
-			slideshow_free (show);
+
+	if (show) {
+		if (!g_markup_parse_context_end_parse (context, err)) {
+			slideshow_unref (show);
 			show = NULL;
 		}
 	}
@@ -1920,47 +2255,52 @@
 
 /* Thumbnail utilities */
 static GdkPixbuf *
-create_thumbnail_for_uri (GnomeThumbnailFactory *factory,
-			  const char            *uri)
+create_thumbnail_for_filename (GnomeThumbnailFactory *factory,
+			       const char            *filename)
 {
-	char *filename;
+	char *thumb;
 	time_t mtime;
-	GdkPixbuf *pixbuf, *orig;
+	GdkPixbuf *orig, *result = NULL;
+	char *uri;
 	
-	mtime = get_mtime (uri);
+	mtime = get_mtime (filename);
 	
 	if (mtime == (time_t)-1)
 		return NULL;
 	
-	filename = gnome_thumbnail_factory_lookup (factory, uri, mtime);
+	uri = g_filename_to_uri (filename, NULL, NULL);
 	
-	if (filename) {
-		pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
-		
-		return pixbuf;
-	}
+	thumb = gnome_thumbnail_factory_lookup (factory, uri, mtime);
 	
-	orig = gnome_gdk_pixbuf_new_from_uri (uri);
-	if (orig) {
-		int orig_width = gdk_pixbuf_get_width (orig);
-		int orig_height = gdk_pixbuf_get_height (orig);
-		
-		pixbuf = pixbuf_scale_to_fit (orig, 128, 128);
-		
-		g_object_set_data_full (G_OBJECT (pixbuf), "gnome-thumbnail-height",
-					g_strdup_printf ("%d", orig_height), g_free);
-		g_object_set_data_full (G_OBJECT (pixbuf), "gnome-thumbnail-width",
-					g_strdup_printf ("%d", orig_width), g_free);
-		
-		g_object_unref (orig);
-		
-		gnome_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, mtime);
-		
-		return pixbuf;
+	if (thumb) {
+		result = gdk_pixbuf_new_from_file (thumb, NULL);
+		g_free (thumb);
 	}
-	
-	gnome_thumbnail_factory_create_failed_thumbnail (factory, uri, mtime);
-	return NULL;
+	else {
+		orig = gdk_pixbuf_new_from_file (filename, NULL);
+		if (orig) {
+			int orig_width = gdk_pixbuf_get_width (orig);
+			int orig_height = gdk_pixbuf_get_height (orig);
+			
+			result = pixbuf_scale_to_fit (orig, 128, 128);
+			
+			g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-height",
+						g_strdup_printf ("%d", orig_height), g_free);
+			g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-width",
+						g_strdup_printf ("%d", orig_width), g_free);
+			
+			g_object_unref (orig);
+			
+			gnome_thumbnail_factory_save_thumbnail (factory, result, uri, mtime);
+		}
+		else {
+			gnome_thumbnail_factory_create_failed_thumbnail (factory, uri, mtime);
+		}
+	}
+
+	g_free (uri);
+
+	return result;
 }
 
 static gboolean
@@ -1988,3 +2328,10 @@
 	
 	return FALSE;
 }
+
+static gboolean
+slideshow_changes_with_size (SlideShow *show)
+{
+	return show->changes_with_size;
+}
+

Modified: branches/randr-12/libgnome-desktop/gnome-rr-config.c
==============================================================================
--- branches/randr-12/libgnome-desktop/gnome-rr-config.c	(original)
+++ branches/randr-12/libgnome-desktop/gnome-rr-config.c	Mon Jun 16 20:16:33 2008
@@ -1,1407 +0,0 @@
-/* gnome-rr-config.c
- *
- * Copyright 2007, 2008, Red Hat, Inc.
- * 
- * This file is part of the Gnome Library.
- * 
- * The Gnome Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * The Gnome Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- * 
- * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Author: Soren Sandmann <sandmann redhat com>
- */
-
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include "libgnomeui/gnome-rr-config.h"
-#include "edid.h"
-
-#define CONFIG_BASENAME "monitors.xml"
-
-/* In version 0 of the config file format, we had several <configuration> toplevel elements
- * and no explicit version number.  So, the filed looked like
- *
- *   <configuration>
- *     ...
- *   </configuration>
- *   <configuration>
- *     ...
- *   </configuration>
- *
- * Since version 1 of the config file, the file has a toplevel <monitors> element to group
- * all the configurations.  That element has a "version" attribute which is an integer.
- * So, the file looks like this:
- *
- *   <monitors version="1">
- *     <configuration>
- *       ...
- *     </configuration>
- *     <configuration>
- *       ...
- *     </configuration>
- *   </monitors>
- */
-
-/* A helper wrapper around the GMarkup parser stuff */
-static gboolean parse_file_gmarkup (const gchar *file,
-				    const GMarkupParser *parser,
-				    gpointer data,
-				    GError **err);
-
-typedef struct CrtcAssignment CrtcAssignment;
-
-static void             crtc_assignment_apply (CrtcAssignment   *assign);
-static CrtcAssignment  *crtc_assignment_new   (GnomeRRScreen    *screen,
-					       GnomeOutputInfo **outputs);
-static void             crtc_assignment_free  (CrtcAssignment   *assign);
-static void             output_free           (GnomeOutputInfo  *output);
-static GnomeOutputInfo *output_copy           (GnomeOutputInfo  *output);
-
-static gchar *get_old_config_filename (void);
-static gchar *get_config_filename (void);
-
-typedef struct Parser Parser;
-
-/* Parser for monitor configurations */
-struct Parser
-{
-    int			config_file_version;
-    GnomeOutputInfo *	output;
-    GnomeRRConfig *	configuration;
-    GPtrArray *		outputs;
-    GPtrArray *		configurations;
-    GQueue *		stack;
-};
-
-static int
-parse_int (const char *text)
-{
-    return strtol (text, NULL, 0);
-}
-
-static guint
-parse_uint (const char *text)
-{
-    return strtoul (text, NULL, 0);
-}
-
-static gboolean
-stack_is (Parser *parser,
-	  const char *s1,
-	  ...)
-{
-    GList *stack = NULL;
-    const char *s;
-    GList *l1, *l2;
-    va_list args;
-    
-    stack = g_list_prepend (stack, (gpointer)s1);
-    
-    va_start (args, s1);
-    
-    s = va_arg (args, const char *);
-    while (s)
-    {
-	stack = g_list_prepend (stack, (gpointer)s);
-	s = va_arg (args, const char *);
-    }
-	
-    l1 = stack;
-    l2 = parser->stack->head;
-    
-    while (l1 && l2)
-    {
-	if (strcmp (l1->data, l2->data) != 0)
-	{
-	    g_list_free (stack);
-	    return FALSE;
-	}
-	
-	l1 = l1->next;
-	l2 = l2->next;
-    }
-    
-    g_list_free (stack);
-    
-    return (!l1 && !l2);
-}
-
-static void
-handle_start_element (GMarkupParseContext *context,
-		      const gchar         *name,
-		      const gchar        **attr_names,
-		      const gchar        **attr_values,
-		      gpointer             user_data,
-		      GError             **err)
-{
-    Parser *parser = user_data;
-
-    if (strcmp (name, "output") == 0)
-    {
-	int i;
-	g_assert (parser->output == NULL);
-
-	parser->output = g_new0 (GnomeOutputInfo, 1);
-	parser->output->rotation = 0;
-	
-	for (i = 0; attr_names[i] != NULL; ++i)
-	{
-	    if (strcmp (attr_names[i], "name") == 0)
-	    {
-		parser->output->name = g_strdup (attr_values[i]);
-		break;
-	    }
-	}
-
-	if (!parser->output->name)
-	{
-	    /* This really shouldn't happen, but it's better to make
-	     * something up than to crash later.
-	     */
-	    g_warning ("Malformed monitor configuration file");
-	    
-	    parser->output->name = g_strdup ("default");
-	}	
-	parser->output->connected = FALSE;
-	parser->output->on = FALSE;
-    }
-    else if (strcmp (name, "configuration") == 0)
-    {
-	g_assert (parser->configuration == NULL);
-	
-	parser->configuration = g_new0 (GnomeRRConfig, 1);
-	parser->configuration->clone = FALSE;
-	parser->configuration->outputs = g_new0 (GnomeOutputInfo *, 1);
-    }
-    else if (strcmp (name, "monitors") == 0)
-    {
-	int i;
-
-	for (i = 0; attr_names[i] != NULL; i++)
-	{
-	    if (strcmp (attr_names[i], "version") == 0)
-	    {
-		parser->config_file_version = parse_int (attr_values[i]);
-		break;
-	    }
-	}
-    }
-
-    g_queue_push_tail (parser->stack, g_strdup (name));
-}
-
-static void
-handle_end_element (GMarkupParseContext *context,
-		    const gchar         *name,
-		    gpointer             user_data,
-		    GError             **err)
-{
-    Parser *parser = user_data;
-    
-    if (strcmp (name, "output") == 0)
-    {
-	/* If no rotation properties were set, just use GNOME_RR_ROTATION_0 */
-	if (parser->output->rotation == 0)
-	    parser->output->rotation = GNOME_RR_ROTATION_0;
-	
-	g_ptr_array_add (parser->outputs, parser->output);
-
-	parser->output = NULL;
-    }
-    else if (strcmp (name, "configuration") == 0)
-    {
-	g_ptr_array_add (parser->outputs, NULL);
-	parser->configuration->outputs =
-	    (GnomeOutputInfo **)g_ptr_array_free (parser->outputs, FALSE);
-	parser->outputs = g_ptr_array_new ();
-	g_ptr_array_add (parser->configurations, parser->configuration);
-	parser->configuration = NULL;
-    }
-    
-    g_free (g_queue_pop_tail (parser->stack));
-}
-
-#define TOPLEVEL_ELEMENT (parser->config_file_version > 0 ? "monitors" : NULL)
-
-static void
-handle_text (GMarkupParseContext *context,
-	     const gchar         *text,
-	     gsize                text_len,
-	     gpointer             user_data,
-	     GError             **err)
-{
-    Parser *parser = user_data;
-    
-    if (stack_is (parser, "vendor", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->connected = TRUE;
-	
-	strncpy (parser->output->vendor, text, 3);
-	parser->output->vendor[3] = 0;
-    }
-    else if (stack_is (parser, "clone", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	if (strcmp (text, "yes") == 0)
-	    parser->configuration->clone = TRUE;
-    }
-    else if (stack_is (parser, "product", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->connected = TRUE;
-
-	parser->output->product = parse_int (text);
-    }
-    else if (stack_is (parser, "serial", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->connected = TRUE;
-
-	parser->output->serial = parse_uint (text);
-    }
-    else if (stack_is (parser, "width", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->on = TRUE;
-
-	parser->output->width = parse_int (text);
-    }
-    else if (stack_is (parser, "x", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->on = TRUE;
-
-	parser->output->x = parse_int (text);
-    }
-    else if (stack_is (parser, "y", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->on = TRUE;
-
-	parser->output->y = parse_int (text);
-    }
-    else if (stack_is (parser, "height", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->on = TRUE;
-
-	parser->output->height = parse_int (text);
-    }
-    else if (stack_is (parser, "rate", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	parser->output->on = TRUE;
-
-	parser->output->rate = parse_int (text);
-    }
-    else if (stack_is (parser, "rotation", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	if (strcmp (text, "normal") == 0)
-	{
-	    parser->output->rotation |= GNOME_RR_ROTATION_0;
-	}
-	else if (strcmp (text, "left") == 0)
-	{
-	    parser->output->rotation |= GNOME_RR_ROTATION_90;
-	}
-	else if (strcmp (text, "upside_down") == 0)
-	{
-	    parser->output->rotation |= GNOME_RR_ROTATION_180;
-	}
-	else if (strcmp (text, "right") == 0)
-	{
-	    parser->output->rotation |= GNOME_RR_ROTATION_270;
-	}
-    }
-    else if (stack_is (parser, "reflect_x", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	if (strcmp (text, "yes") == 0)
-	{
-	    parser->output->rotation |= GNOME_RR_REFLECT_X;
-	}
-    }
-    else if (stack_is (parser, "reflect_y", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-	if (strcmp (text, "yes") == 0)
-	{
-	    parser->output->rotation |= GNOME_RR_REFLECT_Y;
-	}
-    }
-    else
-    {
-	/* Ignore other properties so we can expand the format in the future */
-    }
-}
-
-static void
-parser_free (Parser *parser)
-{
-    int i;
-    GList *list;
-
-    g_assert (parser != NULL);
-
-    if (parser->output)
-	output_free (parser->output);
-
-    if (parser->configuration)
-	gnome_rr_config_free (parser->configuration);
-
-    for (i = 0; i < parser->outputs->len; ++i)
-    {
-	GnomeOutputInfo *output = parser->outputs->pdata[i];
-
-	output_free (output);
-    }
-
-    g_ptr_array_free (parser->outputs, TRUE);
-
-    for (i = 0; i < parser->configurations->len; ++i)
-    {
-	GnomeRRConfig *config = parser->configurations->pdata[i];
-
-	gnome_rr_config_free (config);
-    }
-
-    g_ptr_array_free (parser->configurations, TRUE);
-
-    for (list = parser->stack->head; list; list = list->next)
-	g_free (list->data);
-    g_queue_free (parser->stack);
-    
-    g_free (parser);
-}
-
-static GnomeRRConfig **
-configurations_read_from_file (const gchar *filename, GError **error)
-{
-    Parser *parser = g_new0 (Parser, 1);
-    GnomeRRConfig **result;
-    GMarkupParser callbacks = {
-	handle_start_element,
-	handle_end_element,
-	handle_text,
-	NULL, /* passthrough */
-	NULL, /* error */
-    };
-
-    parser->config_file_version = 0;
-    parser->configurations = g_ptr_array_new ();
-    parser->outputs = g_ptr_array_new ();
-    parser->stack = g_queue_new ();
-    
-    if (!parse_file_gmarkup (filename, &callbacks, parser, error))
-    {
-	result = NULL;
-	
-	g_assert (parser->outputs);
-	goto out;
-    }
-
-    g_assert (parser->outputs);
-    
-    g_ptr_array_add (parser->configurations, NULL);
-    result = (GnomeRRConfig **)g_ptr_array_free (parser->configurations, FALSE);
-    parser->configurations = g_ptr_array_new ();
-    
-    g_assert (parser->outputs);
-out:
-    parser_free (parser);
-
-    return result;
-}
-
-static GnomeRRConfig **
-configurations_read (GError **error)
-{
-    char *filename;
-    GnomeRRConfig **configs;
-    GError *err;
-
-    /* Try the new configuration file... */
-
-    filename = get_config_filename ();
-
-    err = NULL;
-    configs = configurations_read_from_file (filename, &err);
-
-    g_free (filename);
-
-    if (g_error_matches (err, G_FILE_ERROR, G_FILE_ERROR_NOENT))
-    {
-	g_error_free (err);
-
-	/* Okay, so try the old configuration file */
-	filename = get_old_config_filename ();
-	configs = configurations_read_from_file (filename, error);
-	g_free (filename);
-
-	return configs;
-    }
-
-    g_propagate_error (error, err);
-    return configs;
-}
-
-GnomeRRConfig *
-gnome_rr_config_new_current (GnomeRRScreen *screen)
-{
-    GnomeRRConfig *config = g_new0 (GnomeRRConfig, 1);
-    GPtrArray *a = g_ptr_array_new ();
-    GnomeRROutput **rr_outputs;
-    int i;
-    int clone_width = -1;
-    int clone_height = -1;
-
-    g_return_val_if_fail (screen != NULL, NULL);
-
-    rr_outputs = gnome_rr_screen_list_outputs (screen);
-
-    config->clone = FALSE;
-    
-    for (i = 0; rr_outputs[i] != NULL; ++i)
-    {
-	GnomeRROutput *rr_output = rr_outputs[i];
-	GnomeOutputInfo *output = g_new0 (GnomeOutputInfo, 1);
-	GnomeRRMode *mode = NULL;
-	const guint8 *edid_data = gnome_rr_output_get_edid_data (rr_output);
-	GnomeRRCrtc *crtc;
-
-	output->name = g_strdup (gnome_rr_output_get_name (rr_output));
-	output->connected = gnome_rr_output_is_connected (rr_output);
-
-	if (!output->connected)
-	{
-	    output->x = -1;
-	    output->y = -1;
-	    output->width = -1;
-	    output->height = -1;
-	    output->rate = -1;
-	    output->rotation = GNOME_RR_ROTATION_0;
-	}
-	else
-	{
-	    MonitorInfo *info = NULL;
-
-	    if (edid_data)
-		info = decode_edid (edid_data);
-
-	    if (info)
-	    {
-		memcpy (output->vendor, info->manufacturer_code,
-			sizeof (output->vendor));
-		
-		output->product = info->product_code;
-		output->serial = info->serial_number;
-		output->aspect = info->aspect_ratio;
-	    }
-	    else
-	    {
-		strcpy (output->vendor, "???");
-		output->product = 0;
-		output->serial = 0;
-	    }
-	    
-	    output->display_name = make_display_name (
-		gnome_rr_output_get_name (rr_output), info);
-		
-	    g_free (info);
-		
-	    crtc = gnome_rr_output_get_crtc (rr_output);
-	    mode = crtc? gnome_rr_crtc_get_current_mode (crtc) : NULL;
-	    
-	    if (crtc && mode)
-	    {
-		output->on = TRUE;
-		
-		gnome_rr_crtc_get_position (crtc, &output->x, &output->y);
-		output->width = gnome_rr_mode_get_width (mode);
-		output->height = gnome_rr_mode_get_height (mode);
-		output->rate = gnome_rr_mode_get_freq (mode);
-		output->rotation = gnome_rr_crtc_get_current_rotation (crtc);
-
-		if (output->x == 0 && output->y == 0) {
-			if (clone_width == -1) {
-				clone_width = output->width;
-				clone_height = output->height;
-			} else if (clone_width == output->width &&
-					clone_height == output->height) {
-				config->clone = TRUE;
-			}
-		}
-	    }
-	    else
-	    {
-		output->on = FALSE;
-		config->clone = FALSE;
-	    }
-
-	    /* Get preferred size for the monitor */
-	    mode = gnome_rr_output_get_preferred_mode (rr_output);
-	    
-	    if (!mode)
-	    {
-		GnomeRRMode **modes = gnome_rr_output_list_modes (rr_output);
-		
-		/* FIXME: we should pick the "best" mode here, where best is
-		 * sorted wrt
-		 *
-		 * - closest aspect ratio
-		 * - mode area
-		 * - refresh rate
-		 * - We may want to extend randrwrap so that get_preferred
-		 *   returns that - although that could also depend on
-		 *   the crtc.
-		 */
-		if (modes[0])
-		    mode = modes[0];
-	    }
-	    
-	    if (mode)
-	    {
-		output->pref_width = gnome_rr_mode_get_width (mode);
-		output->pref_height = gnome_rr_mode_get_height (mode);
-	    }
-	    else
-	    {
-		/* Pick some random numbers. This should basically never happen */
-		output->pref_width = 1024;
-		output->pref_height = 768;
-	    }
-	}
- 
-	g_ptr_array_add (a, output);
-    }
-
-    g_ptr_array_add (a, NULL);
-    
-    config->outputs = (GnomeOutputInfo **)g_ptr_array_free (a, FALSE);
-
-    g_assert (gnome_rr_config_match (config, config));
-    
-    return config;
-}
-
-static void
-output_free (GnomeOutputInfo *output)
-{
-    if (output->display_name)
-	g_free (output->display_name);
-
-    if (output->name)
-	g_free (output->name);
-    
-    g_free (output);
-}
-
-static GnomeOutputInfo *
-output_copy (GnomeOutputInfo *output)
-{
-    GnomeOutputInfo *copy = g_new0 (GnomeOutputInfo, 1);
-
-    *copy = *output;
-
-    copy->name = g_strdup (output->name);
-    copy->display_name = g_strdup (output->display_name);
-
-    return copy;
-}
-
-static void
-outputs_free (GnomeOutputInfo **outputs)
-{
-    int i;
-
-    g_assert (outputs != NULL);
-
-    for (i = 0; outputs[i] != NULL; ++i)
-	output_free (outputs[i]);
-}
-
-void
-gnome_rr_config_free (GnomeRRConfig *config)
-{
-    g_return_if_fail (config != NULL);
-    outputs_free (config->outputs);
-    
-    g_free (config);
-}
-
-static void
-configurations_free (GnomeRRConfig **configurations)
-{
-    int i;
-
-    g_assert (configurations != NULL);
-
-    for (i = 0; configurations[i] != NULL; ++i)
-	gnome_rr_config_free (configurations[i]);
-
-    g_free (configurations);
-}
-
-static gboolean
-parse_file_gmarkup (const gchar          *filename,
-		    const GMarkupParser  *parser,
-		    gpointer             data,
-		    GError              **err)
-{
-    GMarkupParseContext *context = NULL;
-    gchar *contents = NULL;
-    gboolean result = TRUE;
-    gsize len;
-
-    if (!g_file_get_contents (filename, &contents, &len, err))
-    {
-	result = FALSE;
-	goto out;
-    }
-    
-    context = g_markup_parse_context_new (parser, 0, data, NULL);
-
-    if (!g_markup_parse_context_parse (context, contents, len, err))
-    {
-	result = FALSE;
-	goto out;
-    }
-
-    if (!g_markup_parse_context_end_parse (context, err))
-    {
-	result = FALSE;
-	goto out;
-    }
-
-out:
-    if (contents)
-	g_free (contents);
-
-    if (context)
-	g_markup_parse_context_free (context);
-
-    return result;
-}
-
-static gboolean
-output_match (GnomeOutputInfo *output1, GnomeOutputInfo *output2)
-{
-    g_assert (output1 != NULL);
-    g_assert (output2 != NULL);
-
-    if (strcmp (output1->name, output2->name) != 0)
-	return FALSE;
-
-    if (strcmp (output1->vendor, output2->vendor) != 0)
-	return FALSE;
-
-    if (output1->product != output2->product)
-	return FALSE;
-
-    if (output1->serial != output2->serial)
-	return FALSE;
-
-    if (output1->connected != output2->connected)
-	return FALSE;
-    
-    return TRUE;
-}
-
-static GnomeOutputInfo *
-find_output (GnomeRRConfig *config, const char *name)
-{
-    int i;
-
-    for (i = 0; config->outputs[i] != NULL; ++i)
-    {
-	GnomeOutputInfo *output = config->outputs[i];
-	
-	if (strcmp (name, output->name) == 0)
-	    return output;
-    }
-
-    return NULL;
-}
-
-gboolean
-gnome_rr_config_match (GnomeRRConfig *c1, GnomeRRConfig *c2)
-{
-    int i;
-
-    for (i = 0; c1->outputs[i] != NULL; ++i)
-    {
-	GnomeOutputInfo *output1 = c1->outputs[i];
-	GnomeOutputInfo *output2;
-
-	output2 = find_output (c2, output1->name);
-	if (!output2 || !output_match (output1, output2))
-	    return FALSE;
-    }
-    
-    return TRUE;
-}
-
-static GnomeOutputInfo **
-make_outputs (GnomeRRConfig *config)
-{
-    GPtrArray *outputs;
-    GnomeOutputInfo *first_on;;
-    int i;
-
-    outputs = g_ptr_array_new ();
-
-    first_on = NULL;
-    
-    for (i = 0; config->outputs[i] != NULL; ++i)
-    {
-	GnomeOutputInfo *old = config->outputs[i];
-	GnomeOutputInfo *new = output_copy (old);
-
-	if (old->on && !first_on)
-	    first_on = old;
-	
-	if (config->clone && new->on)
-	{
-	    g_assert (first_on);
-
-	    new->width = first_on->width;
-	    new->height = first_on->height;
-	    new->rotation = first_on->rotation;
-	    new->x = 0;
-	    new->y = 0;
-	}
-
-	g_ptr_array_add (outputs, new);
-    }
-
-    g_ptr_array_add (outputs, NULL);
-
-    return (GnomeOutputInfo **)g_ptr_array_free (outputs, FALSE);
-}
-
-gboolean
-gnome_rr_config_applicable (GnomeRRConfig  *configuration,
-			  GnomeRRScreen       *screen)
-{
-    GnomeOutputInfo **outputs = make_outputs (configuration);
-    CrtcAssignment *assign = crtc_assignment_new (screen, outputs);
-    gboolean result;
-
-    if (assign)
-    {
-	result = TRUE;
-	crtc_assignment_free (assign);
-    }
-    else
-    {
-	result = FALSE;
-    }
-
-    outputs_free (outputs);
-
-    return result;
-}
-
-static GnomeRRConfig *
-gnome_rr_config_find (GnomeRRConfig **haystack,
-		    GnomeRRConfig  *needle)
-{
-    int i;
-
-    for (i = 0; haystack[i] != NULL; ++i)
-    {
-	if (gnome_rr_config_match (haystack[i], needle))
-	    return haystack[i];
-    }
-
-    return NULL;
-}
-
-/* Database management */
-
-static gchar *
-get_old_config_filename (void)
-{
-    return g_build_filename (g_get_home_dir(), ".gnome2", CONFIG_BASENAME, NULL);
-}
-
-static gchar *
-get_config_filename (void)
-{
-    return g_build_filename (g_get_user_config_dir (), CONFIG_BASENAME, NULL);
-}
-
-static const char *
-get_rotation_name (GnomeRRRotation r)
-{
-    if (r & GNOME_RR_ROTATION_0)
-	return "normal";
-    if (r & GNOME_RR_ROTATION_90)
-	return "left";
-    if (r & GNOME_RR_ROTATION_180)
-	return "upside_down";
-    if (r & GNOME_RR_ROTATION_270)
-	return "right";
-
-    return "normal";
-}
-
-static const char *
-yes_no (int x)
-{
-    return x? "yes" : "no";
-}
-
-static const char *
-get_reflect_x (GnomeRRRotation r)
-{
-    return yes_no (r & GNOME_RR_REFLECT_X);
-}
-
-static const char *
-get_reflect_y (GnomeRRRotation r)
-{
-    return yes_no (r & GNOME_RR_REFLECT_Y);
-}
-
-static void
-emit_configuration (GnomeRRConfig *config,
-		    GString *string)
-{
-    int j;
-
-    g_string_append_printf (string, "  <configuration>\n");
-
-    g_string_append_printf (string, "      <clone>%s</clone>\n", yes_no (config->clone));
-    
-    for (j = 0; config->outputs[j] != NULL; ++j)
-    {
-	GnomeOutputInfo *output = config->outputs[j];
-	
-	g_string_append_printf (
-	    string, "      <output name=\"%s\">\n", output->name);
-	
-	if (output->connected && *output->vendor != '\0')
-	{
-	    g_string_append_printf (
-		string, "          <vendor>%s</vendor>\n", output->vendor);
-	    g_string_append_printf (
-		string, "          <product>0x%04x</product>\n", output->product);
-	    g_string_append_printf (
-		string, "          <serial>0x%08x</serial>\n", output->serial);
-	}
-	
-	/* An unconnected output which is on does not make sense */
-	if (output->connected && output->on)
-	{
-	    g_string_append_printf (
-		string, "          <width>%d</width>\n", output->width);
-	    g_string_append_printf (
-		string, "          <height>%d</height>\n", output->height);
-	    g_string_append_printf (
-		string, "          <rate>%d</rate>\n", output->rate);
-	    g_string_append_printf (
-		string, "          <x>%d</x>\n", output->x);
-	    g_string_append_printf (
-		string, "          <y>%d</y>\n", output->y);
-	    g_string_append_printf (
-		string, "          <rotation>%s</rotation>\n", get_rotation_name (output->rotation));
-	    g_string_append_printf (
-		string, "          <reflect_x>%s</reflect_x>\n", get_reflect_x (output->rotation));
-	    g_string_append_printf (
-		string, "          <reflect_y>%s</reflect_y>\n", get_reflect_y (output->rotation));
-	}
-	
-	g_string_append_printf (string, "      </output>\n");
-    }
-    
-    g_string_append_printf (string, "  </configuration>\n");
-}
-
-void
-gnome_rr_config_sanitize (GnomeRRConfig *config)
-{
-    int i;
-    int x_offset, y_offset;
-
-    /* Offset everything by the top/left-most coordinate to
-     * make sure the configuration starts at (0, 0)
-     */
-    x_offset = y_offset = G_MAXINT;
-    for (i = 0; config->outputs[i]; ++i)
-    {
-	GnomeOutputInfo *output = config->outputs[i];
-
-	if (output->on)
-	{
-	    x_offset = MIN (x_offset, output->x);
-	    y_offset = MIN (y_offset, output->y);
-	}
-    }
-
-    for (i = 0; config->outputs[i]; ++i)
-    {
-	GnomeOutputInfo *output = config->outputs[i];
-	
-	if (output->on)
-	{
-	    output->x -= x_offset;
-	    output->y -= y_offset;
-	}
-    }
-}
-
-
-gboolean
-gnome_rr_config_save (GnomeRRConfig *configuration, GError **err)
-{
-    GnomeRRConfig **configurations;
-    GString *output = g_string_new("");
-    int i;
-    gchar *filename;
-    gboolean result;
-
-    configurations = configurations_read (NULL); /* NULL-GError */
-    
-    g_string_append_printf (output, "<monitors version=\"1\">\n");
-
-    if (configurations)
-    {
-	for (i = 0; configurations[i] != NULL; ++i)
-	{
-	    if (!gnome_rr_config_match (configurations[i], configuration))
-		emit_configuration (configurations[i], output);
-	}
-
-	configurations_free (configurations);
-    }
-
-    emit_configuration (configuration, output);
-
-    g_string_append_printf (output, "</monitors>\n");
-
-    filename = get_config_filename ();
-    result = g_file_set_contents (filename, output->str, -1, err);
-    g_free (filename);
-
-    if (result)
-    {
-	/* Only remove the old config file if we were successful in saving the new one */
-
-	filename = get_old_config_filename ();
-	if (g_file_test (filename, G_FILE_TEST_EXISTS))
-	    g_unlink (filename);
-
-	g_free (filename);
-    }
-
-    return result;
-}
-
-static gboolean
-apply_configuration (GnomeRRConfig *conf, GnomeRRScreen *screen)
-{
-    CrtcAssignment *assignment;
-    GnomeOutputInfo **outputs;
-
-    outputs = make_outputs (conf);
-
-    assignment = crtc_assignment_new (screen, outputs);
-
-    outputs_free (outputs);
-    
-    if (assignment)
-    {
-	crtc_assignment_apply (assignment);
-	    
-	crtc_assignment_free (assignment);
-
-	return TRUE;
-    }
-
-    return FALSE;
-}
-
-gboolean
-gnome_rr_config_apply_stored (GnomeRRScreen *screen)
-{
-    GnomeRRConfig **configs = configurations_read (NULL); /* NULL-GError */
-    GnomeRRConfig *current;
-    GnomeRRConfig *found;
-    gboolean result = TRUE;
-
-    if (!screen)
-	return FALSE;
-    
-    gnome_rr_screen_refresh (screen);
-    
-    current = gnome_rr_config_new_current (screen);
-    if (configs)
-    {
-	if ((found = gnome_rr_config_find (configs, current)))
-	{
-	    apply_configuration (found, screen);
-	    result = TRUE;
-	}
-	else
-	{
-	    result = FALSE;
-	}
-	
-	configurations_free (configs);
-    }
-	
-    gnome_rr_config_free (current);
-
-    return result;
-}
-
-
-/*
- * CRTC assignment
- */
-typedef struct CrtcInfo CrtcInfo;
-
-struct CrtcInfo
-{
-    GnomeRRMode    *mode;
-    int        x;
-    int        y;
-    GnomeRRRotation rotation;
-    GPtrArray *outputs;
-};
-
-struct CrtcAssignment
-{
-    GnomeRRScreen *screen;
-    GHashTable *info;
-};
-
-static gboolean
-can_clone (CrtcInfo *info,
-	   GnomeRROutput *output)
-{
-    int i;
-
-    for (i = 0; i < info->outputs->len; ++i)
-    {
-	GnomeRROutput *clone = info->outputs->pdata[i];
-
-	if (!gnome_rr_output_can_clone (clone, output))
-	    return FALSE;
-    }
-
-    return TRUE;
-}
-
-static gboolean
-crtc_assignment_assign (CrtcAssignment *assign,
-			GnomeRRCrtc         *crtc,
-			GnomeRRMode         *mode,
-			int             x,
-			int             y,
-			GnomeRRRotation      rotation,
-			GnomeRROutput       *output)
-{
-    /* FIXME: We should reject stuff that is outside the screen ranges */
-    
-    CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
-
-    if (!gnome_rr_crtc_can_drive_output (crtc, output) ||
-	!gnome_rr_output_supports_mode (output, mode)  ||
-	!gnome_rr_crtc_supports_rotation (crtc, rotation))
-    {
-	return FALSE;
-    }
-
-    if (info)
-    {
-	if (info->mode == mode		&&
-	    info->x == x		&&
-	    info->y == y		&&
-	    info->rotation == rotation  &&
-	    can_clone (info, output))
-	{
-	    g_ptr_array_add (info->outputs, output);
-
-	    return TRUE;
-	}
-    }
-    else
-    {	
-	CrtcInfo *info = g_new0 (CrtcInfo, 1);
-	
-	info->mode = mode;
-	info->x = x;
-	info->y = y;
-	info->rotation = rotation;
-	info->outputs = g_ptr_array_new ();
-	
-	g_ptr_array_add (info->outputs, output);
-	
-	g_hash_table_insert (assign->info, crtc, info);
-	    
-	return TRUE;
-    }
-    
-    return FALSE;
-}
-
-static void
-crtc_assignment_unassign (CrtcAssignment *assign,
-			  GnomeRRCrtc         *crtc,
-			  GnomeRROutput       *output)
-{
-    CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
-
-    if (info)
-    {
-	g_ptr_array_remove (info->outputs, output);
-
-	if (info->outputs->len == 0)
-	    g_hash_table_remove (assign->info, crtc);
-    }
-}
-
-static void
-crtc_assignment_free (CrtcAssignment *assign)
-{
-    g_hash_table_destroy (assign->info);
-
-    g_free (assign);
-}
-
-static void
-configure_crtc (gpointer key,
-		gpointer value,
-		gpointer data)
-{
-    GnomeRRCrtc *crtc = key;
-    CrtcInfo *info = value;
-
-    gnome_rr_crtc_set_config (crtc,
-			info->x, info->y,
-			info->mode,
-			info->rotation,
-			(GnomeRROutput **)info->outputs->pdata,
-			info->outputs->len);
-}
-
-static gboolean
-mode_is_rotated (CrtcInfo *info)
-{
-    if ((info->rotation & GNOME_RR_ROTATION_270)		||
-	(info->rotation & GNOME_RR_ROTATION_90))
-    {
-	return TRUE;
-    }
-    return FALSE;
-}
-
-static gboolean
-crtc_is_rotated (GnomeRRCrtc *crtc)
-{
-    GnomeRRRotation r = gnome_rr_crtc_get_current_rotation (crtc);
-
-    if ((r & GNOME_RR_ROTATION_270)		||
-	(r & GNOME_RR_ROTATION_90))
-    {
-	return TRUE;
-    }
-
-    return FALSE;
-}
-
-static void
-crtc_assignment_apply (CrtcAssignment *assign)
-{
-    GList *active_crtcs = g_hash_table_get_keys (assign->info);
-    GnomeRRCrtc **all_crtcs = gnome_rr_screen_list_crtcs (assign->screen);
-    GList *list;
-    int width, height;
-    int i;
-    int min_width, max_width, min_height, max_height;
-    int width_mm, height_mm;
-
-    /* Compute size of the screen */
-    width = height = 1;
-    for (list = active_crtcs; list != NULL; list = list->next)
-    {
-	GnomeRRCrtc *crtc = list->data;
-	CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
-	int w, h;
-
-	w = gnome_rr_mode_get_width (info->mode);
-	h = gnome_rr_mode_get_height (info->mode);
-	
-	if (mode_is_rotated (info))
-	{
-	    int tmp = h;
-	    h = w;
-	    w = tmp;
-	}
-	
-	width = MAX (width, info->x + w);
-	height = MAX (height, info->y + h);
-    }
-    g_list_free (active_crtcs);
-
-    gnome_rr_screen_get_ranges (
-	assign->screen, &min_width, &max_width, &min_height, &max_height);
-
-    width = MAX (min_width, width);
-    width = MIN (max_width, width);
-    height = MAX (min_height, height);
-    height = MIN (max_height, height);
-    
-    /* Turn off all crtcs currently displaying outside the new screen */
-    for (i = 0; all_crtcs[i] != NULL; ++i)
-    {
-	GnomeRRCrtc *crtc = all_crtcs[i];
-	GnomeRRMode *mode = gnome_rr_crtc_get_current_mode (crtc);
-	int x, y;
-
-	if (mode)
-	{
-	    int w, h;
-	    gnome_rr_crtc_get_position (crtc, &x, &y);
-
-	    w = gnome_rr_mode_get_width (mode);
-	    h = gnome_rr_mode_get_height (mode);
-	    
-	    if (crtc_is_rotated (crtc))
-	    {
-		int tmp = h;
-		h = w;
-		w = tmp;
-	    }
-	    
-	    if (x + w > width || y + h > height)
-		gnome_rr_crtc_set_config (crtc, 0, 0, NULL, GNOME_RR_ROTATION_0, NULL, 0);
-	}
-    }
-
-    /* Turn off all CRTC's that are not in the assignment */
-    for (i = 0; all_crtcs[i] != NULL; ++i)
-    {
-	GnomeRRCrtc *crtc = all_crtcs[i];
-	
-	if (!g_hash_table_lookup (assign->info, crtc))
-	    gnome_rr_crtc_set_config (crtc, 0, 0, NULL, GNOME_RR_ROTATION_0, NULL, 0);
-    }
-
-    /* The 'physical size' of an X screen is meaningless if that screen
-     * can consist of many monitors. So just pick a size that make the
-     * dpi 96.
-     *
-     * Firefox and Evince apparently believe what X tells them.
-     */
-    width_mm = (width / 96.0) * 25.4 + 0.5;
-    height_mm = (height / 96.0) * 25.4 + 0.5;
-    
-    gnome_rr_screen_set_size (assign->screen, width, height, width_mm, height_mm);
-
-    g_hash_table_foreach (assign->info, configure_crtc, NULL);
-}
-
-/* Check whether the given set of settings can be used
- * at the same time -- ie. whether there is an assignment
- * of CRTC's to outputs.
- *
- * Brute force - the number of objects involved is small
- * enough that it doesn't matter.
- */
-static gboolean
-real_assign_crtcs (GnomeRRScreen *screen,
-		   GnomeOutputInfo **outputs,
-		   CrtcAssignment *assignment)
-{
-    GnomeRRCrtc **crtcs = gnome_rr_screen_list_crtcs (screen);
-    GnomeOutputInfo *output;
-    int i;
-
-    output = *outputs;
-    if (!output)
-	return TRUE;
-
-    /* It is always allowed for an output to be turned off */
-    if (!output->on)
-    {
-	return real_assign_crtcs (screen, outputs + 1, assignment);
-    }
-
-    for (i = 0; crtcs[i] != NULL; ++i)
-    {
-	int pass;
-
-	/* Make two passses, one where frequencies must match, then
-	 * one where they don't have to
-	 */
-	for (pass = 0; pass < 2; ++pass)
-	{
-	    GnomeRRCrtc *crtc = crtcs[i];
-	    GnomeRROutput *gnome_rr_output =
-		gnome_rr_screen_get_output_by_name (screen, output->name);
-	    GnomeRRMode **modes = gnome_rr_output_list_modes (gnome_rr_output);
-	    int j;
-	
-	    for (j = 0; modes[j] != NULL; ++j)
-	    {
-		GnomeRRMode *mode = modes[j];
-		
-		if (gnome_rr_mode_get_width (mode) == output->width	&&
-		    gnome_rr_mode_get_height (mode) == output->height &&
-		    (pass == 1 || gnome_rr_mode_get_freq (mode) == output->rate))
-		{
-		    if (crtc_assignment_assign (
-			    assignment, crtc, modes[j],
-			    output->x, output->y,
-			    output->rotation,
-			    gnome_rr_output))
-		    {
-			if (real_assign_crtcs (screen, outputs + 1, assignment))
-			    return TRUE;
-			
-			crtc_assignment_unassign (assignment, crtc, gnome_rr_output);
-		    }
-		}
-	    }
-	}
-    }
-
-    return FALSE;
-}
-
-static void
-crtc_info_free (CrtcInfo *info)
-{
-    g_ptr_array_free (info->outputs, TRUE);
-    g_free (info);
-}
-
-static CrtcAssignment *
-crtc_assignment_new (GnomeRRScreen *screen, GnomeOutputInfo **outputs)
-{
-    CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1);
-
-    assignment->info = g_hash_table_new_full (
-	g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free);
-
-    if (real_assign_crtcs (screen, outputs, assignment))
-    {
-	assignment->screen = screen;
-	
-	return assignment;
-    }
-    else
-    {
-	crtc_assignment_free (assignment);
-    
-	return NULL;
-    }
-}

Modified: branches/randr-12/libgnome-desktop/gnome-rr.c
==============================================================================
--- branches/randr-12/libgnome-desktop/gnome-rr.c	(original)
+++ branches/randr-12/libgnome-desktop/gnome-rr.c	Mon Jun 16 20:16:33 2008
@@ -1,1215 +0,0 @@
-/* gnome-rr.c
- *
- * Copyright 2007, 2008, Red Hat, Inc.
- * 
- * This file is part of the Gnome Library.
- * 
- * The Gnome Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * The Gnome Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- * 
- * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Author: Soren Sandmann <sandmann redhat com>
- */
-
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-
-#include "libgnomeui/gnome-rr.h"
-#include <string.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xrandr.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <X11/Xatom.h>
-
-#define DISPLAY(o) ((o)->info->screen->xdisplay)
-
-typedef struct ScreenInfo ScreenInfo;
-
-struct ScreenInfo
-{
-    int			min_width;
-    int			max_width;
-    int			min_height;
-    int			max_height;
-
-    XRRScreenResources *resources;
-    
-    GnomeRROutput **	outputs;
-    GnomeRRCrtc **	crtcs;
-    GnomeRRMode **	modes;
-    
-    GnomeRRScreen *	screen;
-};
-
-struct GnomeRRScreen
-{
-    GdkScreen *			gdk_screen;
-    GdkWindow *			gdk_root;
-    Display *			xdisplay;
-    Screen *			xscreen;
-    Window			xroot;
-    ScreenInfo *		info;
-    
-    int				randr_event_base;
-    
-    GnomeRRScreenChanged	callback;
-    gpointer			data;
-};
-
-struct GnomeRROutput
-{
-    ScreenInfo *	info;
-    RROutput		id;
-    
-    char *		name;
-    GnomeRRCrtc *	current_crtc;
-    gboolean		connected;
-    gulong		width_mm;
-    gulong		height_mm;
-    GnomeRRCrtc **	possible_crtcs;
-    GnomeRROutput **	clones;
-    GnomeRRMode **	modes;
-    int			n_preferred;
-    guint8 *		edid_data;
-};
-
-struct GnomeRROutputWrap
-{
-    RROutput		id;
-};
-
-struct GnomeRRCrtc
-{
-    ScreenInfo *	info;
-    RRCrtc		id;
-    
-    GnomeRRMode *	current_mode;
-    GnomeRROutput **	current_outputs;
-    GnomeRROutput **	possible_outputs;
-    int			x;
-    int			y;
-    
-    GnomeRRRotation	current_rotation;
-    GnomeRRRotation	rotations;
-};
-
-struct GnomeRRMode
-{
-    ScreenInfo *	info;
-    RRMode		id;
-    char *		name;
-    int			width;
-    int			height;
-    int			freq;		/* in mHz */
-};
-
-/* GnomeRRCrtc */
-static GnomeRRCrtc *  crtc_new          (ScreenInfo         *info,
-					 RRCrtc              id);
-static void           crtc_free         (GnomeRRCrtc        *crtc);
-static void           crtc_initialize   (GnomeRRCrtc        *crtc,
-					 XRRScreenResources *res);
-
-/* GnomeRROutput */
-static GnomeRROutput *output_new        (ScreenInfo         *info,
-					 RROutput            id);
-static void           output_initialize (GnomeRROutput      *output,
-					 XRRScreenResources *res);
-static void           output_free       (GnomeRROutput      *output);
-
-/* GnomeRRMode */
-static GnomeRRMode *  mode_new          (ScreenInfo         *info,
-					 RRMode              id);
-static void           mode_initialize   (GnomeRRMode        *mode,
-					 XRRModeInfo        *info);
-static void           mode_free         (GnomeRRMode        *mode);
-
-
-/* Screen */
-static GnomeRROutput *
-gnome_rr_output_by_id (ScreenInfo *info, RROutput id)
-{
-    GnomeRROutput **output;
-    
-    g_assert (info != NULL);
-    
-    for (output = info->outputs; *output; ++output)
-    {
-	if ((*output)->id == id)
-	    return *output;
-    }
-    
-    return NULL;
-}
-
-static GnomeRRCrtc *
-crtc_by_id (ScreenInfo *info, RRCrtc id)
-{
-    GnomeRRCrtc **crtc;
-    
-    if (!info)
-        return NULL;
-    
-    for (crtc = info->crtcs; *crtc; ++crtc)
-    {
-	if ((*crtc)->id == id)
-	    return *crtc;
-    }
-    
-    return NULL;
-}
-
-static GnomeRRMode *
-mode_by_id (ScreenInfo *info, RRMode id)
-{
-    GnomeRRMode **mode;
-    
-    g_assert (info != NULL);
-    
-    for (mode = info->modes; *mode; ++mode)
-    {
-	if ((*mode)->id == id)
-	    return *mode;
-    }
-    
-    return NULL;
-}
-
-static void
-screen_info_free (ScreenInfo *info)
-{
-    GnomeRROutput **output;
-    GnomeRRCrtc **crtc;
-    GnomeRRMode **mode;
-    
-    g_assert (info != NULL);
-    
-    if (info->resources)
-    {
-	XRRFreeScreenResources (info->resources);
-	
-	info->resources = NULL;
-    }
-    
-    if (info->outputs)
-    {
-	for (output = info->outputs; *output; ++output)
-	    output_free (*output);
-	g_free (info->outputs);
-    }
-    
-    if (info->crtcs)
-    {
-	for (crtc = info->crtcs; *crtc; ++crtc)
-	    crtc_free (*crtc);
-	g_free (info->crtcs);
-    }
-    
-    if (info->modes)
-    {
-	for (mode = info->modes; *mode; ++mode)
-	    mode_free (*mode);
-	g_free (info->modes);
-    }
-    
-    g_free (info);
-}
-
-static gboolean
-fill_out_screen_info (Display *xdisplay,
-		      Window xroot,
-		      ScreenInfo *info)
-{
-    XRRScreenResources *resources;
-    
-    g_assert (xdisplay != NULL);
-    g_assert (info != NULL);
-    
-    gdk_error_trap_push ();
-    
-    if (!XRRGetScreenSizeRange (xdisplay, xroot,
-                                &(info->min_width),
-                                &(info->min_height),
-                                &(info->max_width),
-                                &(info->max_height))) {
-        /* XRR caught an error */
-        return False;
-    }
-    
-    gdk_flush ();
-    if (gdk_error_trap_pop ())
-    {
-        /* Unhandled X Error was generated */
-        return False;
-    }
-    
-#if 0
-    g_print ("ranges: %d - %d; %d - %d\n",
-	     screen->min_width, screen->max_width,
-	     screen->min_height, screen->max_height);
-#endif
-    
-    resources = XRRGetScreenResources (xdisplay, xroot);
-    
-    if (resources)
-    {
-	int i;
-	GPtrArray *a;
-	GnomeRRCrtc **crtc;
-	GnomeRROutput **output;
-	
-#if 0
-	g_print ("Resource Timestamp: %u\n", (guint32)resources->timestamp);
-	g_print ("Resource Configuration Timestamp: %u\n", (guint32)resources->configTimestamp);
-#endif
-	
-	info->resources = resources;
-	
-	/* We create all the structures before initializing them, so
-	 * that they can refer to each other.
-	 */
-	a = g_ptr_array_new ();
-	for (i = 0; i < resources->ncrtc; ++i)
-	{
-	    GnomeRRCrtc *crtc = crtc_new (info, resources->crtcs[i]);
-	    
-	    g_ptr_array_add (a, crtc);
-	}
-	g_ptr_array_add (a, NULL);
-	info->crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
-	
-	a = g_ptr_array_new ();
-	for (i = 0; i < resources->noutput; ++i)
-	{
-	    GnomeRROutput *output = output_new (info, resources->outputs[i]);
-	    
-	    g_ptr_array_add (a, output);
-	}
-	g_ptr_array_add (a, NULL);
-	info->outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-	
-	a = g_ptr_array_new ();
-	for (i = 0;  i < resources->nmode; ++i)
-	{
-	    GnomeRRMode *mode = mode_new (info, resources->modes[i].id);
-	    
-	    g_ptr_array_add (a, mode);
-	}
-	g_ptr_array_add (a, NULL);
-	info->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
-	
-	/* Initialize */
-	for (crtc = info->crtcs; *crtc; ++crtc)
-	    crtc_initialize (*crtc, resources);
-	
-	for (output = info->outputs; *output; ++output)
-	    output_initialize (*output, resources);
-	
-	for (i = 0; i < resources->nmode; ++i)
-	{
-	    GnomeRRMode *mode = mode_by_id (info, resources->modes[i].id);
-	    
-	    mode_initialize (mode, &(resources->modes[i]));
-	}
-	
-	return TRUE;
-    }
-    else
-    {
-	g_print ("Couldn't get screen resources\n");
-	
-	return FALSE;
-    }
-}
-
-static ScreenInfo *
-screen_info_new (GnomeRRScreen *screen)
-{
-    ScreenInfo *info = g_new0 (ScreenInfo, 1);
-    
-    g_assert (screen != NULL);
-    
-    info->outputs = NULL;
-    info->crtcs = NULL;
-    info->modes = NULL;
-    info->screen = screen;
-    
-    if (fill_out_screen_info (screen->xdisplay, screen->xroot, info))
-    {
-	return info;
-    }
-    else
-    {
-	g_free (info);
-	return NULL;
-    }
-}
-
-static gboolean
-screen_update (GnomeRRScreen *screen, gboolean force_callback)
-{
-    ScreenInfo *info;
-    gboolean changed = FALSE;
-    
-    g_assert (screen != NULL);
-    
-    info = screen_info_new (screen);
-    if (info)
-    {
-	if (info->resources->configTimestamp != screen->info->resources->configTimestamp)
-	    changed = TRUE;
-	
-	screen_info_free (screen->info);
-	
-	screen->info = info;
-    }
-    
-    if ((changed || force_callback) && screen->callback)
-	screen->callback (screen, screen->data);
-    
-    return changed;
-}
-
-static GdkFilterReturn
-screen_on_event (GdkXEvent *xevent,
-		 GdkEvent *event,
-		 gpointer data)
-{
-    GnomeRRScreen *screen = data;
-    XEvent *e = xevent;
-    
-    if (e && e->type - screen->randr_event_base == RRNotify)
-    {
-	XRRNotifyEvent *event = (XRRNotifyEvent *)e;
-	
-	switch (event->subtype)
-	{
-	default:
-	    break;
-	}
-	
-	/* FIXME: we may need to be more discriminating in
-	 * what causes 'changed' events
-	 */
-	screen_update (screen, TRUE);
-    }
-    
-    /* Pass the event on to GTK+ */
-    return GDK_FILTER_CONTINUE;
-}
-
-/* Returns NULL if screen could not be created.  For instance, if
- * the driver does not support Xrandr 1.2.
- */
-GnomeRRScreen *
-gnome_rr_screen_new (GdkScreen *gdk_screen,
-		     GnomeRRScreenChanged callback,
-		     gpointer data)
-{
-    Display *dpy = GDK_SCREEN_XDISPLAY (gdk_screen);
-    int event_base;
-    int ignore;
-    
-    if (XRRQueryExtension (dpy, &event_base, &ignore))
-    {
-	GnomeRRScreen *screen = g_new0 (GnomeRRScreen, 1);
-	
-	screen->gdk_screen = gdk_screen;
-	screen->gdk_root = gdk_screen_get_root_window (gdk_screen);
-	screen->xroot = gdk_x11_drawable_get_xid (screen->gdk_root);
-	screen->xdisplay = dpy;
-	screen->xscreen = gdk_x11_screen_get_xscreen (screen->gdk_screen);
-	
-	screen->callback = callback;
-	screen->data = data;
-	
-	screen->randr_event_base = event_base;
-	
-	screen->info = screen_info_new (screen);
-	
-	if (!screen->info)
-	    return NULL;
-	
-	XRRSelectInput (screen->xdisplay,
-			screen->xroot,
-			RRScreenChangeNotifyMask	|
-			RRCrtcChangeNotifyMask		|
-			RROutputPropertyNotifyMask);
-	
-	gdk_x11_register_standard_event_type (
-	    gdk_screen_get_display (gdk_screen),
-	    event_base,
-	    RRNotify + 1);
-	
-	gdk_window_add_filter (screen->gdk_root, screen_on_event, screen);
-	return screen;
-    }
-    
-    return NULL;
-}
-
-void
-gnome_rr_screen_set_size (GnomeRRScreen *screen,
-			  int	      width,
-			  int       height,
-			  int       mm_width,
-			  int       mm_height)
-{
-    g_return_if_fail (screen != NULL);
-    
-    XRRSetScreenSize (screen->xdisplay, screen->xroot,
-		      width, height, mm_width, mm_height);
-}
-
-void
-gnome_rr_screen_get_ranges (GnomeRRScreen *screen,
-			    int	          *min_width,
-			    int	          *max_width,
-			    int           *min_height,
-			    int	          *max_height)
-{
-    g_return_if_fail (screen != NULL);
-    
-    if (min_width)
-	*min_width = screen->info->min_width;
-    
-    if (max_width)
-	*max_width = screen->info->max_width;
-    
-    if (min_height)
-	*min_height = screen->info->min_height;
-    
-    if (max_height)
-	*max_height = screen->info->max_height;
-}
-
-gboolean
-gnome_rr_screen_refresh (GnomeRRScreen *screen)
-{
-    return screen_update (screen, FALSE);
-}
-
-GnomeRRMode **
-gnome_rr_screen_list_modes (GnomeRRScreen *screen)
-{
-    g_return_val_if_fail (screen != NULL, NULL);
-    g_return_val_if_fail (screen->info != NULL, NULL);
-    
-    return screen->info->modes;
-}
-
-GnomeRRCrtc **
-gnome_rr_screen_list_crtcs (GnomeRRScreen *screen)
-{
-    g_return_val_if_fail (screen != NULL, NULL);
-    g_return_val_if_fail (screen->info != NULL, NULL);
-    
-    return screen->info->crtcs;
-}
-
-GnomeRROutput **
-gnome_rr_screen_list_outputs (GnomeRRScreen *screen)
-{
-    g_return_val_if_fail (screen != NULL, NULL);
-    g_return_val_if_fail (screen->info != NULL, NULL);
-    
-    return screen->info->outputs;
-}
-
-GnomeRRCrtc *
-gnome_rr_screen_get_crtc_by_id (GnomeRRScreen *screen,
-				guint32        id)
-{
-    int i;
-    
-    g_return_val_if_fail (screen != NULL, NULL);
-    g_return_val_if_fail (screen->info != NULL, NULL);
-    
-    for (i = 0; screen->info->crtcs[i] != NULL; ++i)
-    {
-	if (screen->info->crtcs[i]->id == id)
-	    return screen->info->crtcs[i];
-    }
-    
-    return NULL;
-}
-
-GnomeRROutput *
-gnome_rr_screen_get_output_by_id (GnomeRRScreen *screen,
-				  guint32        id)
-{
-    int i;
-    
-    g_return_val_if_fail (screen != NULL, NULL);
-    g_return_val_if_fail (screen->info != NULL, NULL);
-    
-    for (i = 0; screen->info->outputs[i] != NULL; ++i)
-    {
-	if (screen->info->outputs[i]->id == id)
-	    return screen->info->outputs[i];
-    }
-    
-    return NULL;
-}
-
-/* GnomeRROutput */
-static GnomeRROutput *
-output_new (ScreenInfo *info, RROutput id)
-{
-    GnomeRROutput *output = g_new0 (GnomeRROutput, 1);
-    
-    output->id = id;
-    output->info = info;
-    
-    return output;
-}
-
-static guint8 *
-get_property (Display *dpy,
-	      RROutput output,
-	      Atom atom,
-	      int *len)
-{
-    unsigned char *prop;
-    int actual_format;
-    unsigned long nitems, bytes_after;
-    Atom actual_type;
-    guint8 *result;
-    
-    XRRGetOutputProperty (dpy, output, atom,
-			  0, 100, False, False,
-			  AnyPropertyType,
-			  &actual_type, &actual_format,
-			  &nitems, &bytes_after, &prop);
-    
-    if (actual_type == XA_INTEGER && actual_format == 8)
-    {
-	result = g_memdup (prop, nitems);
-	if (len)
-	    *len = nitems;
-    }
-    else
-    {
-	result = NULL;
-    }
-    
-    XFree (prop);
-    
-    return result;
-}
-
-static guint8 *
-read_edid_data (GnomeRROutput *output)
-{
-    Atom edid_atom = XInternAtom (DISPLAY (output), "EDID_DATA", FALSE);
-    guint8 *result;
-    int len;
-    
-    result = get_property (DISPLAY (output),
-			   output->id, edid_atom, &len);
-    
-    if (result)
-    {
-	if (len == 128)
-	    return result;
-	else
-	    g_free (result);
-    }
-    
-    return NULL;
-}
-
-static void
-output_initialize (GnomeRROutput *output, XRRScreenResources *res)
-{
-    XRROutputInfo *info = XRRGetOutputInfo (
-	DISPLAY (output), res, output->id);
-    GPtrArray *a;
-    int i;
-    
-    g_print ("Output %lx Timestamp: %u\n", output->id, (guint32)info->timestamp);
-    
-    if (!info || !output->info)
-    {
-	/* FIXME */
-	return;
-    }
-    
-    output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */
-    output->current_crtc = crtc_by_id (output->info, info->crtc);
-    output->width_mm = info->mm_width;
-    output->height_mm = info->mm_height;
-    output->connected = (info->connection == RR_Connected);
-    
-    /* Possible crtcs */
-    a = g_ptr_array_new ();
-    
-    for (i = 0; i < info->ncrtc; ++i)
-    {
-	GnomeRRCrtc *crtc = crtc_by_id (output->info, info->crtcs[i]);
-	
-	if (crtc)
-	    g_ptr_array_add (a, crtc);
-    }
-    g_ptr_array_add (a, NULL);
-    output->possible_crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
-    
-    /* Clones */
-    a = g_ptr_array_new ();
-    for (i = 0; i < info->nclone; ++i)
-    {
-	GnomeRROutput *gnome_rr_output = gnome_rr_output_by_id (output->info, info->clones[i]);
-	
-	if (gnome_rr_output)
-	    g_ptr_array_add (a, gnome_rr_output);
-    }
-    g_ptr_array_add (a, NULL);
-    output->clones = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-    
-    /* Modes */
-    a = g_ptr_array_new ();
-    for (i = 0; i < info->nmode; ++i)
-    {
-	GnomeRRMode *mode = mode_by_id (output->info, info->modes[i]);
-	
-	if (mode)
-	    g_ptr_array_add (a, mode);
-    }
-    g_ptr_array_add (a, NULL);
-    output->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
-    
-    output->n_preferred = info->npreferred;
-    
-    /* Edid data */
-    output->edid_data = read_edid_data (output);
-    
-    XRRFreeOutputInfo (info);
-}
-
-static void
-output_free (GnomeRROutput *output)
-{
-    g_free (output);
-}
-
-guint32
-gnome_rr_output_get_id (GnomeRROutput *output)
-{
-    g_assert(output != NULL);
-    
-    return output->id;
-}
-
-const guint8 *
-gnome_rr_output_get_edid_data (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, NULL);
-    
-    return output->edid_data;
-}
-
-GnomeRROutput *
-gnome_rr_screen_get_output_by_name (GnomeRRScreen *screen,
-				    const char    *name)
-{
-    int i;
-    
-    g_return_val_if_fail (screen != NULL, NULL);
-    g_return_val_if_fail (screen->info != NULL, NULL);
-    
-    for (i = 0; screen->info->outputs[i] != NULL; ++i)
-    {
-	GnomeRROutput *output = screen->info->outputs[i];
-	
-	if (strcmp (output->name, name) == 0)
-	    return output;
-    }
-    
-    return NULL;
-}
-
-GnomeRRCrtc *
-gnome_rr_output_get_crtc (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, NULL);
-    
-    return output->current_crtc;
-}
-
-GnomeRRMode *
-gnome_rr_output_get_current_mode (GnomeRROutput *output)
-{
-    GnomeRRCrtc *crtc;
-    
-    g_return_val_if_fail (output != NULL, NULL);
-    
-    if ((crtc = gnome_rr_output_get_crtc (output)))
-	return gnome_rr_crtc_get_current_mode (crtc);
-    
-    return NULL;
-}
-
-void
-gnome_rr_output_get_position (GnomeRROutput   *output,
-			      int             *x,
-			      int             *y)
-{
-    GnomeRRCrtc *crtc;
-    
-    g_return_if_fail (output != NULL);
-    
-    if ((crtc = gnome_rr_output_get_crtc (output)))
-	gnome_rr_crtc_get_position (crtc, x, y);
-}
-
-const char *
-gnome_rr_output_get_name (GnomeRROutput *output)
-{
-    g_assert (output != NULL);
-    return output->name;
-}
-
-int
-gnome_rr_output_get_width_mm (GnomeRROutput *output)
-{
-    g_assert (output != NULL);
-    return output->width_mm;
-}
-
-int
-gnome_rr_output_get_height_mm (GnomeRROutput *output)
-{
-    g_assert (output != NULL);
-    return output->height_mm;
-}
-
-GnomeRRMode *
-gnome_rr_output_get_preferred_mode (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, NULL);
-    if (output->n_preferred)
-	return output->modes[0];
-    
-    return NULL;
-}
-
-GnomeRRMode **
-gnome_rr_output_list_modes (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, NULL);
-    return output->modes;
-}
-
-gboolean
-gnome_rr_output_is_connected (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, FALSE);
-    return output->connected;
-}
-
-gboolean
-gnome_rr_output_supports_mode (GnomeRROutput *output,
-			       GnomeRRMode   *mode)
-{
-    int i;
-    
-    g_return_val_if_fail (output != NULL, FALSE);
-    g_return_val_if_fail (mode != NULL, FALSE);
-    
-    for (i = 0; output->modes[i] != NULL; ++i)
-    {
-	if (output->modes[i] == mode)
-	    return TRUE;
-    }
-    
-    return FALSE;
-}
-
-gboolean
-gnome_rr_output_can_clone (GnomeRROutput *output,
-			   GnomeRROutput *clone)
-{
-    int i;
-    
-    g_return_val_if_fail (output != NULL, FALSE);
-    g_return_val_if_fail (clone != NULL, FALSE);
-    
-    for (i = 0; output->clones[i] != NULL; ++i)
-    {
-	if (output->clones[i] == clone)
-	    return TRUE;
-    }
-    
-    return FALSE;
-}
-
-/* GnomeRRCrtc */
-typedef struct
-{
-    Rotation xrot;
-    GnomeRRRotation rot;
-} RotationMap;
-
-static const RotationMap rotation_map[] =
-{
-    { RR_Rotate_0, GNOME_RR_ROTATION_0 },
-    { RR_Rotate_90, GNOME_RR_ROTATION_90 },
-    { RR_Rotate_180, GNOME_RR_ROTATION_180 },
-    { RR_Rotate_270, GNOME_RR_ROTATION_270 },
-    { RR_Reflect_X, GNOME_RR_REFLECT_X },
-    { RR_Reflect_Y, GNOME_RR_REFLECT_Y },
-};
-
-static GnomeRRRotation
-gnome_rr_rotation_from_xrotation (Rotation r)
-{
-    int i;
-    GnomeRRRotation result = 0;
-    
-    for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
-    {
-	if (r & rotation_map[i].xrot)
-	    result |= rotation_map[i].rot;
-    }
-    
-    return result;
-}
-
-static Rotation
-xrotation_from_rotation (GnomeRRRotation r)
-{
-    int i;
-    Rotation result = 0;
-    
-    for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
-    {
-	if (r & rotation_map[i].rot)
-	    result |= rotation_map[i].xrot;
-    }
-    
-    return result;
-}
-
-gboolean
-gnome_rr_crtc_set_config (GnomeRRCrtc      *crtc,
-			  int               x,
-			  int               y,
-			  GnomeRRMode      *mode,
-			  GnomeRRRotation   rotation,
-			  GnomeRROutput   **outputs,
-			  int               n_outputs)
-{
-    ScreenInfo *info;
-    GArray *output_ids;
-    int i;
-    
-    g_return_val_if_fail (crtc != NULL, FALSE);
-    g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
-    
-    info = crtc->info;
-    
-    if (mode)
-    {
-	g_return_val_if_fail (x + mode->width <= info->max_width, FALSE);
-	g_return_val_if_fail (y + mode->height <= info->max_height, FALSE);
-    }
-    
-    output_ids = g_array_new (FALSE, FALSE, sizeof (RROutput));
-    
-    if (outputs)
-    {
-	for (i = 0; i < n_outputs; ++i)
-	    g_array_append_val (output_ids, outputs[i]->id);
-    }
-    
-    XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id,
-		      CurrentTime, 
-		      x, y,
-		      mode? mode->id : None,
-		      xrotation_from_rotation (rotation),
-		      (RROutput *)output_ids->data,
-		      output_ids->len);
-    
-    g_array_free (output_ids, TRUE);
-    
-    return TRUE;
-}
-
-GnomeRRMode *
-gnome_rr_crtc_get_current_mode (GnomeRRCrtc *crtc)
-{
-    g_return_val_if_fail (crtc != NULL, NULL);
-    
-    return crtc->current_mode;
-}
-
-guint32
-gnome_rr_crtc_get_id (GnomeRRCrtc *crtc)
-{
-    g_return_val_if_fail (crtc != NULL, 0);
-    
-    return crtc->id;
-}
-
-gboolean
-gnome_rr_crtc_can_drive_output (GnomeRRCrtc   *crtc,
-				GnomeRROutput *output)
-{
-    int i;
-    
-    g_return_val_if_fail (crtc != NULL, FALSE);
-    g_return_val_if_fail (output != NULL, FALSE);
-    
-    for (i = 0; crtc->possible_outputs[i] != NULL; ++i)
-    {
-	if (crtc->possible_outputs[i] == output)
-	    return TRUE;
-    }
-    
-    return FALSE;
-}
-
-/* FIXME: merge with get_mode()? */
-void
-gnome_rr_crtc_get_position (GnomeRRCrtc *crtc,
-			    int         *x,
-			    int         *y)
-{
-    g_return_if_fail (crtc != NULL);
-    
-    if (x)
-	*x = crtc->x;
-    
-    if (y)
-	*y = crtc->y;
-}
-
-/* FIXME: merge with get_mode()? */
-GnomeRRRotation
-gnome_rr_crtc_get_current_rotation (GnomeRRCrtc *crtc)
-{
-    g_assert(crtc != NULL);
-    return crtc->current_rotation;
-}
-
-GnomeRRRotation
-gnome_rr_crtc_get_rotations (GnomeRRCrtc *crtc)
-{
-    g_assert(crtc != NULL);
-    return crtc->rotations;
-}
-
-gboolean
-gnome_rr_crtc_supports_rotation (GnomeRRCrtc *   crtc,
-				 GnomeRRRotation rotation)
-{
-    g_return_val_if_fail (crtc != NULL, FALSE);
-    return (crtc->rotations & rotation);
-}
-
-static GnomeRRCrtc *
-crtc_new (ScreenInfo *info, RROutput id)
-{
-    GnomeRRCrtc *crtc = g_new0 (GnomeRRCrtc, 1);
-    
-    crtc->id = id;
-    crtc->info = info;
-    
-    return crtc;
-}
-
-static void
-crtc_initialize (GnomeRRCrtc        *crtc,
-		 XRRScreenResources *res)
-{
-    XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id);
-    GPtrArray *a;
-    int i;
-    
-    g_print ("CRTC %lx Timestamp: %u\n", crtc->id, (guint32)info->timestamp);
-    
-    if (!info)
-    {
-	/* FIXME: We need to reaquire the screen resources */
-	return;
-    }
-    
-    /* GnomeRRMode */
-    crtc->current_mode = mode_by_id (crtc->info, info->mode);
-    
-    crtc->x = info->x;
-    crtc->y = info->y;
-    
-    /* Current outputs */
-    a = g_ptr_array_new ();
-    for (i = 0; i < info->noutput; ++i)
-    {
-	GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->outputs[i]);
-	
-	if (output)
-	    g_ptr_array_add (a, output);
-    }
-    g_ptr_array_add (a, NULL);
-    crtc->current_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-    
-    /* Possible outputs */
-    a = g_ptr_array_new ();
-    for (i = 0; i < info->npossible; ++i)
-    {
-	GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->possible[i]);
-	
-	if (output)
-	    g_ptr_array_add (a, output);
-    }
-    g_ptr_array_add (a, NULL);
-    crtc->possible_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-    
-    /* Rotations */
-    crtc->current_rotation = gnome_rr_rotation_from_xrotation (info->rotation);
-    crtc->rotations = gnome_rr_rotation_from_xrotation (info->rotations);
-    
-    XRRFreeCrtcInfo (info);
-}
-
-static void
-crtc_free (GnomeRRCrtc *crtc)
-{
-    g_free (crtc->current_outputs);
-    g_free (crtc->possible_outputs);
-    g_free (crtc);
-}
-
-/* GnomeRRMode */
-static GnomeRRMode *
-mode_new (ScreenInfo *info, RRMode id)
-{
-    GnomeRRMode *mode = g_new0 (GnomeRRMode, 1);
-    
-    mode->id = id;
-    mode->info = info;
-    
-    return mode;
-}
-
-guint32
-gnome_rr_mode_get_id (GnomeRRMode *mode)
-{
-    g_return_val_if_fail (mode != NULL, 0);
-    return mode->id;
-}
-
-guint
-gnome_rr_mode_get_width (GnomeRRMode *mode)
-{
-    g_return_val_if_fail (mode != NULL, 0);
-    return mode->width;
-}
-
-int
-gnome_rr_mode_get_freq (GnomeRRMode *mode)
-{
-    g_return_val_if_fail (mode != NULL, 0);
-    return (mode->freq) / 1000;
-}
-
-guint
-gnome_rr_mode_get_height (GnomeRRMode *mode)
-{
-    g_return_val_if_fail (mode != NULL, 0);
-    return mode->height;
-}
-
-static void
-mode_initialize (GnomeRRMode *mode, XRRModeInfo *info)
-{
-    g_assert (mode != NULL);
-    g_assert (info != NULL);
-    
-    mode->name = g_strdup (info->name);
-    mode->width = info->width;
-    mode->height = info->height;
-    mode->freq = ((info->dotClock / (double)info->hTotal) / info->vTotal + 0.5) * 1000;
-}
-
-static void
-mode_free (GnomeRRMode *mode)
-{
-    g_free (mode->name);
-    g_free (mode);
-}
-
-
-#ifdef INCLUDE_MAIN
-static void
-on_screen_changed (GnomeRRScreen *screen, gpointer data)
-{
-    g_print ("Changed\n");
-}
-
-static gboolean
-do_refresh (gpointer data)
-{
-    GnomeRRScreen *screen = data;
-    
-    gnome_rr_screen_refresh (screen);
-    
-    return TRUE;
-}
-
-int
-main (int argc, char **argv)
-{
-    int i;
-    
-    gtk_init (&argc, &argv);
-    
-    GnomeRRScreen *screen = gnome_rr_screen_new (gdk_screen_get_default(),
-					    on_screen_changed,
-					    NULL);
-    
-    for (i = 0; screen->info->crtcs[i]; ++i)
-    {
-	GnomeRRCrtc *crtc = screen->info->crtcs[i];
-	
-	if (crtc->current_mode)
-	{
-	    g_print ("CRTC %p: (%d %d %d %d)\n",
-		     crtc, crtc->x, crtc->y,
-		     crtc->current_mode->width, crtc->current_mode->height);
-	}
-	else
-	{
-	    g_print ("CRTC %p: turned off\n", crtc);
-	}
-    }
-    
-    for (i = 0; screen->info->outputs[i]; ++i)
-    {
-	GnomeRROutput *output = screen->info->outputs[i];
-	
-	g_print ("Output %s currently", output->name);
-	
-	if (!output->current_crtc)
-	    g_print (" turned off\n");
-	else
-	    g_print (" driven by CRTC %p\n", output->current_crtc);
-    }
-    
-    g_timeout_add (500, do_refresh, screen);
-    
-    gtk_main ();
-    
-    return 0;
-}
-#endif

Modified: branches/randr-12/libgnome-desktop/libgnomeui/Makefile.am
==============================================================================
--- branches/randr-12/libgnome-desktop/libgnomeui/Makefile.am	(original)
+++ branches/randr-12/libgnome-desktop/libgnomeui/Makefile.am	Mon Jun 16 20:16:33 2008
@@ -1,7 +1,5 @@
 libgnomeui_desktopdir = $(includedir)/gnome-desktop-2.0/libgnomeui
-libgnomeui_desktop_HEADERS =	\
-	gnome-ditem-edit.h	\
-	gnome-hint.h		\
-	gnome-bg.h		\
-	gnome-rr.h		\
-	gnome-rr-config.h
+libgnomeui_desktop_HEADERS = \
+	gnome-ditem-edit.h \
+	gnome-hint.h       \
+	gnome-bg.h

Modified: branches/randr-12/libgnome-desktop/libgnomeui/gnome-bg.h
==============================================================================
--- branches/randr-12/libgnome-desktop/libgnomeui/gnome-bg.h	(original)
+++ branches/randr-12/libgnome-desktop/libgnomeui/gnome-bg.h	Mon Jun 16 20:16:33 2008
@@ -61,43 +61,54 @@
 	GNOME_BG_PLACEMENT_FILL_SCREEN
 } GnomeBGPlacement;
 
-GType      gnome_bg_get_type           (void);
-GnomeBG *  gnome_bg_new                (void);
-
-void       gnome_bg_load_from_preferences (GnomeBG               *bg,
-                                           GConfClient           *client);
-
-void       gnome_bg_set_placement      (GnomeBG               *img,
-					GnomeBGPlacement       placement);
-void       gnome_bg_set_color          (GnomeBG               *img,
-					GnomeBGColorType       type,
-					GdkColor              *c1,
-					GdkColor              *c2);
-void       gnome_bg_set_uri            (GnomeBG               *img,
-					const char            *uri);
-void       gnome_bg_draw               (GnomeBG               *img,
-					GdkPixbuf             *dest);
-GdkPixmap *gnome_bg_create_pixmap      (GnomeBG               *img,
-					GdkWindow             *window,
-					int                    width,
-					int                    height,
-					gboolean               root);
-gboolean   gnome_bg_get_image_size     (GnomeBG	               *bg,
-					GnomeThumbnailFactory *factory,
-					int		       *width,
-					int		       *height);
-GdkPixbuf *gnome_bg_create_thumbnail   (GnomeBG               *bg,
-					GnomeThumbnailFactory *factory,
-					GdkScreen             *screen,
-					int		       dest_width,
-					int		       dest_height);
-gboolean   gnome_bg_is_dark            (GnomeBG               *img);
-gboolean   gnome_bg_changes_with_size  (GnomeBG               *img);
+GType            gnome_bg_get_type              (void);
+GnomeBG *        gnome_bg_new                   (void);
+void             gnome_bg_load_from_preferences (GnomeBG               *bg,
+						 GConfClient           *client);
+void             gnome_bg_save_to_preferences   (GnomeBG               *bg,
+						 GConfClient           *client);
+/* Setters */
+void             gnome_bg_set_filename          (GnomeBG               *bg,
+						 const char            *filename);
+void             gnome_bg_set_placement         (GnomeBG               *bg,
+						 GnomeBGPlacement       placement);
+void             gnome_bg_set_color             (GnomeBG               *bg,
+						 GnomeBGColorType       type,
+						 GdkColor              *primary,
+						 GdkColor              *secondary);
+/* Getters */
+GnomeBGPlacement gnome_bg_get_placement         (GnomeBG               *bg);
+void		 gnome_bg_get_color             (GnomeBG               *bg,
+						 GnomeBGColorType      *type,
+						 GdkColor              *primary,
+						 GdkColor              *secondary);
+const gchar *    gnome_bg_get_filename          (GnomeBG               *bg);
+
+/* Drawing and thumbnailing */
+void             gnome_bg_draw                  (GnomeBG               *bg,
+						 GdkPixbuf             *dest);
+GdkPixmap *      gnome_bg_create_pixmap         (GnomeBG               *bg,
+						 GdkWindow             *window,
+						 int                    width,
+						 int                    height,
+						 gboolean               root);
+gboolean         gnome_bg_get_image_size        (GnomeBG               *bg,
+						 GnomeThumbnailFactory *factory,
+						 int                   *width,
+						 int                   *height);
+GdkPixbuf *      gnome_bg_create_thumbnail      (GnomeBG               *bg,
+						 GnomeThumbnailFactory *factory,
+						 GdkScreen             *screen,
+						 int                    dest_width,
+						 int                    dest_height);
+gboolean         gnome_bg_is_dark               (GnomeBG               *bg);
+gboolean         gnome_bg_changes_with_size     (GnomeBG               *bg);
 
 
 /* Set a pixmap as root - not a GnomeBG method */
-void       gnome_bg_set_pixmap_as_root (GdkScreen             *screen,
-					GdkPixmap             *pixmap);
+void             gnome_bg_set_pixmap_as_root    (GdkScreen             *screen,
+						 GdkPixmap             *pixmap);
+
 
 G_END_DECLS
 

Modified: branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr-config.h
==============================================================================
--- branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr-config.h	(original)
+++ branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr-config.h	Mon Jun 16 20:16:33 2008
@@ -1,79 +0,0 @@
-/* gnome-rr-config.h
- *
- * Copyright 2007, 2008, Red Hat, Inc.
- * 
- * This file is part of the Gnome Library.
- * 
- * The Gnome Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * The Gnome Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- * 
- * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Author: Soren Sandmann <sandmann redhat com>
- */
-#ifndef GNOME_RR_CONFIG_H
-#define GNOME_RR_CONFIG_H
-
-#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
-#error   gnome-rr-config.h is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-rr-config.h
-#endif
-
-#include <libgnomeui/gnome-rr.h>
-#include <glib.h>
-
-typedef struct GnomeOutputInfo GnomeOutputInfo;
-typedef struct GnomeRRConfig GnomeRRConfig;
-
-struct GnomeOutputInfo
-{
-    char *		name;
-
-    gboolean		on;
-    int			width;
-    int			height;
-    int			rate;
-    int			x;
-    int			y;
-    GnomeRRRotation	rotation;
-
-    gboolean		connected;
-    char		vendor[4];
-    guint		product;
-    guint		serial;
-    double		aspect;
-    int			pref_width;
-    int			pref_height;
-    char *		display_name;
-
-    gpointer		user_data;
-};
-
-struct GnomeRRConfig
-{
-    gboolean		clone;
-    
-    GnomeOutputInfo **	outputs;
-};
-
-GnomeRRConfig  *gnome_rr_config_new_current  (GnomeRRScreen  *screen);
-void            gnome_rr_config_free         (GnomeRRConfig  *configuration);
-gboolean        gnome_rr_config_match        (GnomeRRConfig  *config1,
-					      GnomeRRConfig  *config2);
-gboolean        gnome_rr_config_save         (GnomeRRConfig  *configuration,
-					      GError        **err);
-void            gnome_rr_config_sanitize     (GnomeRRConfig  *configuration);
-gboolean        gnome_rr_config_apply_stored (GnomeRRScreen  *screen);
-gboolean        gnome_rr_config_applicable   (GnomeRRConfig  *configuration,
-					      GnomeRRScreen  *screen);
-
-#endif

Modified: branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr.h
==============================================================================
--- branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr.h	(original)
+++ branches/randr-12/libgnome-desktop/libgnomeui/gnome-rr.h	Mon Jun 16 20:16:33 2008
@@ -1,123 +0,0 @@
-/* randrwrap.h
- *
- * Copyright 2007, 2008, Red Hat, Inc.
- * 
- * This file is part of the Gnome Library.
- * 
- * The Gnome Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * The Gnome Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- * 
- * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Author: Soren Sandmann <sandmann redhat com>
- */
-#ifndef RANDR_WRAP_H
-#define RANDR_WRAP_H
-
-#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
-#error    GnomeRR is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnomerr.h
-#endif
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-typedef struct GnomeRRScreen GnomeRRScreen;
-typedef struct GnomeRROutput GnomeRROutput;
-typedef struct GnomeRRCrtc GnomeRRCrtc;
-typedef struct GnomeRRMode GnomeRRMode;
-
-typedef void (* GnomeRRScreenChanged) (GnomeRRScreen *screen, gpointer data);
-
-typedef enum
-{
-    GNOME_RR_ROTATION_0 =	(1 << 0),
-    GNOME_RR_ROTATION_90 =	(1 << 1),
-    GNOME_RR_ROTATION_180 =	(1 << 2),
-    GNOME_RR_ROTATION_270 =	(1 << 3),
-    GNOME_RR_REFLECT_X =	(1 << 4),
-    GNOME_RR_REFLECT_Y =	(1 << 5)
-} GnomeRRRotation;
-
-/* GnomeRRScreen */
-GnomeRRScreen * gnome_rr_screen_new                (GdkScreen             *screen,
-						    GnomeRRScreenChanged   callback,
-						    gpointer               data);
-GnomeRROutput **gnome_rr_screen_list_outputs       (GnomeRRScreen         *screen);
-GnomeRRCrtc **  gnome_rr_screen_list_crtcs         (GnomeRRScreen         *screen);
-GnomeRRMode **  gnome_rr_screen_list_modes         (GnomeRRScreen         *screen);
-void            gnome_rr_screen_set_size           (GnomeRRScreen         *screen,
-						    int                    width,
-						    int                    height,
-						    int                    mm_width,
-						    int                    mm_height);
-GnomeRRCrtc *   gnome_rr_screen_get_crtc_by_id     (GnomeRRScreen         *screen,
-						    guint32                id);
-gboolean        gnome_rr_screen_refresh            (GnomeRRScreen         *screen);
-GnomeRROutput * gnome_rr_screen_get_output_by_id   (GnomeRRScreen         *screen,
-						    guint32                id);
-GnomeRROutput * gnome_rr_screen_get_output_by_name (GnomeRRScreen         *screen,
-						    const char            *name);
-void            gnome_rr_screen_get_ranges         (GnomeRRScreen         *screen,
-						    int                   *min_width,
-						    int                   *max_width,
-						    int                   *min_height,
-						    int                   *max_height);
-
-/* GnomeRROutput */
-guint32         gnome_rr_output_get_id             (GnomeRROutput         *output);
-const char *    gnome_rr_output_get_name           (GnomeRROutput         *output);
-gboolean        gnome_rr_output_is_connected       (GnomeRROutput         *output);
-int             gnome_rr_output_get_size_inches    (GnomeRROutput         *output);
-int             gnome_rr_output_get_width_mm       (GnomeRROutput         *outout);
-int             gnome_rr_output_get_height_mm      (GnomeRROutput         *output);
-const guint8 *  gnome_rr_output_get_edid_data      (GnomeRROutput         *output);
-GnomeRRCrtc **  gnome_rr_output_get_possible_crtcs (GnomeRROutput         *output);
-GnomeRRMode *   gnome_rr_output_get_current_mode   (GnomeRROutput         *output);
-GnomeRRCrtc *   gnome_rr_output_get_crtc           (GnomeRROutput         *output);
-void            gnome_rr_output_get_position       (GnomeRROutput         *output,
-						    int                   *x,
-						    int                   *y);
-gboolean        gnome_rr_output_can_clone          (GnomeRROutput         *output,
-						    GnomeRROutput         *clone);
-GnomeRRMode **  gnome_rr_output_list_modes         (GnomeRROutput         *output);
-GnomeRRMode *   gnome_rr_output_get_preferred_mode (GnomeRROutput         *output);
-gboolean        gnome_rr_output_supports_mode      (GnomeRROutput         *output,
-						    GnomeRRMode           *mode);
-
-/* GnomeRRMode */
-guint32         gnome_rr_mode_get_id               (GnomeRRMode           *mode);
-guint           gnome_rr_mode_get_width            (GnomeRRMode           *mode);
-guint           gnome_rr_mode_get_height           (GnomeRRMode           *mode);
-int             gnome_rr_mode_get_freq             (GnomeRRMode           *mode);
-
-/* GnomeRRCrtc */
-guint32         gnome_rr_crtc_get_id               (GnomeRRCrtc           *crtc);
-gboolean        gnome_rr_crtc_set_config           (GnomeRRCrtc           *crtc,
-						    int                    x,
-						    int                    y,
-						    GnomeRRMode           *mode,
-						    GnomeRRRotation        rotation,
-						    GnomeRROutput        **outputs,
-						    int                    n_outputs);
-gboolean        gnome_rr_crtc_can_drive_output     (GnomeRRCrtc           *crtc,
-						    GnomeRROutput         *output);
-GnomeRRMode *   gnome_rr_crtc_get_current_mode     (GnomeRRCrtc           *crtc);
-void            gnome_rr_crtc_get_position         (GnomeRRCrtc           *crtc,
-						    int                   *x,
-						    int                   *y);
-GnomeRRRotation gnome_rr_crtc_get_current_rotation (GnomeRRCrtc           *crtc);
-GnomeRRRotation gnome_rr_crtc_get_rotations        (GnomeRRCrtc           *crtc);
-gboolean        gnome_rr_crtc_supports_rotation    (GnomeRRCrtc           *crtc,
-						    GnomeRRRotation        rotation);
-
-#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]