Merge lp:~darkxst/ubuntu/utopic/gnome-desktop3/3.12 into lp:ubuntu/utopic/gnome-desktop3

Proposed by Tim Lunn on 2014-09-29
Status: Merged
Approved by: Iain Lane on 2014-09-30
Approved revision: 34
Merge reported by: Martin Pitt
Merged at revision: not available
Proposed branch: lp:~darkxst/ubuntu/utopic/gnome-desktop3/3.12
Merge into: lp:ubuntu/utopic/gnome-desktop3
Diff against target: 74037 lines (+25326/-37286)
183 files modified
.pc/02_refuse_to_break_GL_compositors.patch/configure.ac (+0/-245)
.pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/Makefile.am (+0/-155)
.pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/gnome-rr-config.c (+0/-1950)
.pc/04_compute_average_color.patch/libgnome-desktop/gnome-bg.c (+0/-2682)
.pc/applied-patches (+0/-9)
.pc/backlight-property-name.patch/libgnome-desktop/gnome-rr.c (+0/-2624)
.pc/git_no_filename_warning.patch/libgnome-desktop/gnome-bg.c (+0/-2850)
.pc/git_revert_draw_background.patch/libgnome-desktop/gnome-bg.c (+0/-2823)
.pc/git_revert_draw_background.patch/libgnome-desktop/gnome-bg.h (+0/-121)
.pc/ignore_errors_with_primary_outputs.patch/libgnome-desktop/gnome-rr.c (+0/-2621)
.pc/tweak_color_computation.patch/libgnome-desktop/gnome-bg.c (+0/-2823)
.pc/ubuntu_language.patch/libgnome-desktop/gnome-languages.c (+0/-1487)
.pc/ubuntu_language_list_from_SUPPORTED.patch/libgnome-desktop/gnome-languages.c (+0/-1526)
.pc/ubuntu_language_list_from_SUPPORTED.patch/libgnome-desktop/gnome-languages.h (+0/-55)
ChangeLog (+1782/-311)
NEWS (+133/-61)
aclocal.m4 (+787/-757)
config.guess (+64/-87)
config.sub (+16/-14)
configure (+28/-28)
configure.ac (+3/-6)
debian/changelog (+132/-0)
debian/control (+9/-11)
debian/control.in (+8/-9)
debian/libgnome-desktop-3-10.install (+2/-0)
debian/libgnome-desktop-3-10.symbols (+173/-0)
debian/libgnome-desktop-3-7.install (+0/-2)
debian/libgnome-desktop-3-7.symbols (+0/-184)
debian/patches/02_refuse_to_break_GL_compositors.patch (+0/-318)
debian/patches/backlight-property-name.patch (+0/-35)
debian/patches/git_no_filename_warning.patch (+0/-27)
debian/patches/ignore_errors_with_primary_outputs.patch (+0/-38)
debian/patches/realpath-PATH_MAX.patch (+37/-0)
debian/patches/series (+1/-4)
debian/patches/ubuntu_language.patch (+24/-42)
debian/rules (+2/-2)
desktop-docs/fdl/ca/ca.po (+122/-114)
desktop-docs/fdl/ca/index.docbook (+34/-17)
desktop-docs/fdl/pt_BR/index.docbook (+1/-8)
desktop-docs/fdl/pt_BR/pt_BR.po (+145/-73)
desktop-docs/gpl/Makefile.am (+1/-1)
desktop-docs/gpl/Makefile.in (+1/-1)
desktop-docs/gpl/ca/ca.po (+124/-117)
desktop-docs/gpl/ca/index.docbook (+64/-109)
desktop-docs/gpl/gl/gl.po (+862/-0)
desktop-docs/gpl/gl/index.docbook (+207/-0)
desktop-docs/gpl/pt_BR/index.docbook (+209/-0)
desktop-docs/gpl/pt_BR/pt_BR.po (+839/-0)
desktop-docs/lgpl/Makefile.am (+1/-1)
desktop-docs/lgpl/Makefile.in (+1/-1)
desktop-docs/lgpl/ca/ca.po (+907/-0)
desktop-docs/lgpl/ca/index.docbook (+602/-0)
docs/reference/gnome-desktop3/Makefile.am (+5/-1)
docs/reference/gnome-desktop3/Makefile.in (+6/-1)
docs/reference/gnome-desktop3/gnome-desktop3-sections.txt (+8/-19)
docs/reference/gnome-desktop3/html/GnomeDesktopThumbnailFactory.html (+155/-18)
docs/reference/gnome-desktop3/html/GnomeIdleMonitor.html (+12/-6)
docs/reference/gnome-desktop3/html/GnomeXkbInfo.html (+5/-61)
docs/reference/gnome-desktop3/html/gnome-desktop3-Language-Utilities.html (+5/-5)
docs/reference/gnome-desktop3/html/gnome-desktop3-gnome-bg.html (+18/-18)
docs/reference/gnome-desktop3/html/gnome-desktop3-gnome-pnp-ids.html (+1/-1)
docs/reference/gnome-desktop3/html/gnome-desktop3-gnome-rr-config.html (+37/-90)
docs/reference/gnome-desktop3/html/gnome-desktop3-gnome-rr.html (+89/-180)
docs/reference/gnome-desktop3/html/gnome-desktop3.devhelp2 (+8/-21)
docs/reference/gnome-desktop3/html/index.html (+2/-1)
docs/reference/gnome-desktop3/html/index.sgml (+9/-21)
docs/reference/gnome-desktop3/html/thumbnail.html (+2/-1)
docs/reference/gnome-desktop3/tmpl/edid.sgml (+0/-9)
docs/reference/gnome-desktop3/tmpl/gnome-idle-monitor.sgml (+1/-0)
docs/reference/gnome-desktop3/tmpl/gnome-rr-config.sgml (+28/-69)
docs/reference/gnome-desktop3/tmpl/gnome-rr.sgml (+40/-113)
docs/reference/gnome-desktop3/tmpl/gnome-xkb-info.sgml (+0/-17)
libgnome-desktop/Makefile.am (+30/-14)
libgnome-desktop/Makefile.in (+108/-26)
libgnome-desktop/check_gl_texture_size.c (+0/-86)
libgnome-desktop/default-input-sources.h (+1/-0)
libgnome-desktop/display-name.c (+0/-144)
libgnome-desktop/edid-parse.c (+1/-1)
libgnome-desktop/edid.h (+0/-2)
libgnome-desktop/gnome-bg-slide-show.c (+6/-0)
libgnome-desktop/gnome-bg.c (+10/-174)
libgnome-desktop/gnome-bg.h (+1/-3)
libgnome-desktop/gnome-desktop-3.0.pc.in (+0/-1)
libgnome-desktop/gnome-desktop-thumbnail.c (+224/-56)
libgnome-desktop/gnome-idle-monitor.c (+318/-269)
libgnome-desktop/gnome-idle-monitor.h (+4/-4)
libgnome-desktop/gnome-languages.c (+43/-272)
libgnome-desktop/gnome-languages.h (+1/-3)
libgnome-desktop/gnome-rr-config.c (+157/-1068)
libgnome-desktop/gnome-rr-config.h (+11/-23)
libgnome-desktop/gnome-rr-debug.c (+50/-66)
libgnome-desktop/gnome-rr-output-info.c (+18/-12)
libgnome-desktop/gnome-rr-private.h (+32/-18)
libgnome-desktop/gnome-rr.c (+640/-1271)
libgnome-desktop/gnome-rr.h (+18/-36)
libgnome-desktop/gnome-wall-clock.c (+40/-26)
libgnome-desktop/gnome-xkb-info.c (+77/-113)
libgnome-desktop/gnome-xkb-info.h (+0/-7)
libgnome-desktop/idle-monitor.xml (+35/-0)
libgnome-desktop/libgsystem/Makefile-libgsystem.am (+14/-1)
libgnome-desktop/libgsystem/gsystem-console.c (+443/-0)
libgnome-desktop/libgsystem/gsystem-console.h (+59/-0)
libgnome-desktop/libgsystem/gsystem-file-utils.c (+1561/-19)
libgnome-desktop/libgsystem/gsystem-file-utils.h (+139/-1)
libgnome-desktop/libgsystem/gsystem-glib-compat.h (+54/-0)
libgnome-desktop/libgsystem/gsystem-local-alloc.c (+48/-41)
libgnome-desktop/libgsystem/gsystem-local-alloc.h (+133/-11)
libgnome-desktop/libgsystem/gsystem-log.c (+167/-0)
libgnome-desktop/libgsystem/gsystem-log.h (+42/-0)
libgnome-desktop/libgsystem/gsystem-shutil.c (+459/-0)
libgnome-desktop/libgsystem/gsystem-shutil.h (+47/-0)
libgnome-desktop/libgsystem/gsystem-subprocess-context-private.h (+65/-0)
libgnome-desktop/libgsystem/gsystem-subprocess-context.c (+501/-0)
libgnome-desktop/libgsystem/gsystem-subprocess-context.h (+128/-0)
libgnome-desktop/libgsystem/gsystem-subprocess.c (+966/-0)
libgnome-desktop/libgsystem/gsystem-subprocess.h (+101/-0)
libgnome-desktop/libgsystem/libgsystem.h (+18/-2)
libgnome-desktop/locarchive.h (+0/-97)
libgnome-desktop/meta-dbus-idle-monitor.c (+2239/-0)
libgnome-desktop/meta-dbus-idle-monitor.h (+408/-0)
libgnome-desktop/meta-dbus-xrandr.c (+2495/-0)
libgnome-desktop/meta-dbus-xrandr.h (+353/-0)
libgnome-desktop/meta-xrandr-shared.h (+41/-0)
libgnome-desktop/test-idle-monitor.c (+4/-2)
libgnome-desktop/test-wall-clock.c (+2/-0)
libgnome-desktop/test-xkb-info.c (+0/-3)
libgnome-desktop/xrandr.xml (+293/-0)
m4/libtool.m4 (+9/-3)
po/LINGUAS (+3/-0)
po/POTFILES.in (+0/-1)
po/ar.po (+110/-125)
po/as.po (+129/-150)
po/be.po (+49/-138)
po/ca.po (+49/-571)
po/ca@valencia.po (+50/-572)
po/cs.po (+63/-173)
po/da.po (+114/-144)
po/de.po (+122/-145)
po/el.po (+112/-139)
po/en.po (+74/-0)
po/es.po (+123/-147)
po/et.po (+91/-106)
po/eu.po (+116/-147)
po/fa.po (+120/-139)
po/fi.po (+89/-157)
po/fr.po (+115/-147)
po/ga.po (+133/-259)
po/gd.po (+252/-0)
po/gl.po (+112/-143)
po/gu.po (+13/-9)
po/he.po (+126/-143)
po/hi.po (+77/-111)
po/hu.po (+118/-146)
po/id.po (+51/-137)
po/it.po (+109/-135)
po/ja.po (+109/-140)
po/kk.po (+125/-404)
po/kn.po (+1/-1)
po/ko.po (+50/-427)
po/lt.po (+48/-129)
po/lv.po (+129/-151)
po/ml.po (+38/-57)
po/nb.po (+36/-121)
po/nl.po (+115/-147)
po/pa.po (+114/-136)
po/pl.po (+51/-138)
po/pt.po (+114/-144)
po/pt_BR.po (+99/-399)
po/ru.po (+99/-138)
po/sk.po (+54/-293)
po/sl.po (+114/-147)
po/sr.po (+49/-125)
po/sr@latin.po (+49/-125)
po/ta.po (+143/-178)
po/te.po (+74/-112)
po/tg.po (+211/-0)
po/th.po (+79/-109)
po/tr.po (+149/-123)
po/ug.po (+7/-9)
po/uk.po (+86/-118)
po/zh_CN.po (+75/-171)
po/zh_HK.po (+111/-141)
po/zh_TW.po (+111/-143)
To merge this branch: bzr merge lp:~darkxst/ubuntu/utopic/gnome-desktop3/3.12
Reviewer Review Type Date Requested Status
Ubuntu branches 2014-09-29 Pending
Review via email: mp+236307@code.launchpad.net
To post a comment you must log in.
Iain Lane (laney) wrote :

This is uploaded, hopefully the auto merger will merge the branch

Martin Pitt (pitti) wrote :

It will, but that won't magically close this MP, closing now.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed directory '.pc/02_refuse_to_break_GL_compositors.patch'
2=== removed file '.pc/02_refuse_to_break_GL_compositors.patch/configure.ac'
3--- .pc/02_refuse_to_break_GL_compositors.patch/configure.ac 2013-09-04 15:08:54 +0000
4+++ .pc/02_refuse_to_break_GL_compositors.patch/configure.ac 1970-01-01 00:00:00 +0000
5@@ -1,245 +0,0 @@
6-m4_define(gnome_platform, 3)
7-m4_define(gnome_minor, 8)
8-m4_define(gnome_micro, 4)
9-dnl gnome_sub is an optional sub-version which will not be advertised to the user
10-dnl It allows to release a 2.30.1.1 which is just a better 2.30.1
11-dnl Leave empty if not needed
12-m4_define(gnome_sub, )
13-
14-m4_define(gnome_version, [gnome_platform.gnome_minor.gnome_micro]m4_ifval(gnome_sub, .gnome_sub)),
15-
16-AC_INIT([gnome-desktop], gnome_version,
17- [http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-desktop])
18-AC_CONFIG_SRCDIR([libgnome-desktop])
19-
20-AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
21-AM_MAINTAINER_MODE([enable])
22-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
23-
24-AC_CONFIG_HEADERS([config.h])
25-
26-AC_CONFIG_MACRO_DIR([m4])
27-
28-# Before making a release, the LT_VERSION string should be modified.
29-# The string is of the form C:R:A.
30-# - If interfaces have been changed or added, but binary compatibility has
31-# been preserved, change to C+1:0:A+1
32-# - If binary compatibility has been broken (eg removed or changed interfaces)
33-# change to C+1:0:0
34-# - If the interface is the same as the previous version, change to C:R+1:A
35-
36-LT_VERSION=7:0:0
37-AC_SUBST(LT_VERSION)
38-
39-LT_PREREQ([2.2.6])
40-LT_INIT([dlopen win32-dll disable-static])
41-
42-IT_PROG_INTLTOOL([0.40.6])
43-
44-AC_PROG_CC
45-PKG_PROG_PKG_CONFIG
46-
47-GNOME_PLATFORM=gnome_platform
48-GNOME_MINOR=gnome_minor
49-GNOME_MICRO=gnome_micro
50-GNOME_DISTRIBUTOR="GNOME.Org"
51-GNOME_DATE=`date +"%Y-%m-%d"`
52-
53-AC_ARG_WITH(gnome_distributor, [ --with-gnome-distributor=DISTRIBUTOR Specify name of GNOME distributor])
54-
55-if test "x$with_gnome_distributor" != x ; then
56- GNOME_DISTRIBUTOR=$with_gnome_distributor
57-fi
58-
59-AC_ARG_ENABLE([date-in-gnome-version],
60- [AS_HELP_STRING([--disable-date-in-gnome-version],[do not put the build date in gnome-version.xml])],
61- [],[enable_date_in_gnome_version=yes])
62-if test "$enable_date_in_gnome_version" = "no"; then
63- GNOME_DATE=
64- GNOME_DATE_COMMENT_START="<!--"
65- GNOME_DATE_COMMENT_END="-->"
66-else
67- GNOME_DATE_COMMENT_START=
68- GNOME_DATE_COMMENT_END=
69-fi
70-
71-AC_SUBST(GNOME_PLATFORM)
72-AC_SUBST(GNOME_MINOR)
73-AC_SUBST(GNOME_MICRO)
74-AC_SUBST(GNOME_DISTRIBUTOR)
75-AC_SUBST(GNOME_DATE)
76-AC_SUBST(GNOME_DATE_COMMENT_START)
77-AC_SUBST(GNOME_DATE_COMMENT_END)
78-
79-GNOME_COMPILE_WARNINGS([maximum])
80-GNOME_MAINTAINER_MODE_DEFINES
81-
82-AC_ARG_ENABLE(deprecation_flags,
83- [AC_HELP_STRING([--enable-deprecation-flags],
84- [use *_DISABLE_DEPRECATED flags @<:@default=no@:>@])],,
85- [enable_deprecation_flags=no])
86-
87-if test "x$enable_deprecation_flags" = "xyes"; then
88- DISABLE_DEPRECATED_CFLAGS=$DISABLE_DEPRECATED
89- AC_SUBST(DISABLE_DEPRECATED_CFLAGS)
90-fi
91-
92-# Should we build shared desktop docs? Useful for people who
93-# need to build two gnome-desktop using two different versions of GTK+
94-AC_ARG_ENABLE([desktop-docs],
95- [AS_HELP_STRING([--disable-desktop-docs],[do not build desktop-wide help documents])],
96- [],[enable_desktop_docs=yes])
97-AM_CONDITIONAL(DESKTOP_DOCS_ENABLED, test "x$enable_desktop_docs" = "xyes")
98-
99-# Path to the pnp.ids file -- to know if we use one shipped with another
100-# package, or an internal file
101-
102-AC_ARG_WITH(pnp-ids-path,
103- [AC_HELP_STRING([--with-pnp-ids-path],
104- [Specify the path to pnp.ids @<:@default=(internal)@:>@])],,
105- [with_pnp_ids_path="\${pnpdatadir}/pnp.ids"])
106-
107-AM_CONDITIONAL(USE_INTERNAL_PNP_IDS, test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids")
108-PNP_IDS=$with_pnp_ids_path
109-AC_SUBST(PNP_IDS)
110-if test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids"; then
111- EXTERNAL_PNP_IDS="no (internal)"
112-else
113- EXTERNAL_PNP_IDS="$with_pnp_ids_path"
114-fi
115-
116-dnl If you add a version number here, you *must* add an AC_SUBST line for
117-dnl it too, or it will never make it into the spec file!
118-
119-GDK_PIXBUF_REQUIRED=2.21.3
120-GTK_REQUIRED=3.3.6
121-GLIB_REQUIRED=2.35.0
122-XRANDR_REQUIRED=1.3
123-GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=3.5.91
124-XEXT_REQUIRED=1.1
125-
126-AC_SUBST(GTK_REQUIRED)
127-AC_SUBST(GLIB_REQUIRED)
128-AC_SUBST(GDK_PIXBUF_REQUIRED)
129-AC_SUBST(XRANDR_REQUIRED)
130-AC_SUBST(XEXT_REQUIRED)
131-
132-AC_CHECK_LIBM
133-AC_SUBST(LIBM)
134-
135-dnl we need x11 for GnomeBG
136-
137-PKG_CHECK_MODULES(XLIB, x11,
138- X11_PACKAGE=x11,
139- [X11_PACKAGE=
140- AC_PATH_XTRA
141- if test "x$no_x" = xyes; then
142- AC_MSG_ERROR("no (requires X development libraries)")
143- else
144- XLIB_LIBS="$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS"
145- XLIB_CFLAGS=$X_CFLAGS
146- fi])
147-AC_SUBST(X11_PACKAGE)
148-AC_SUBST(XLIB_CFLAGS)
149-AC_SUBST(XLIB_LIBS)
150-
151-dnl pkg-config dependency checks
152-
153-PKG_CHECK_MODULES(GNOME_DESKTOP, gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQUIRED
154- gtk+-3.0 >= $GTK_REQUIRED
155- glib-2.0 >= $GLIB_REQUIRED
156- gio-2.0 >= $GLIB_REQUIRED
157- gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED
158- xrandr >= $XRANDR_REQUIRED
159- xext >= $XEXT_REQUIRED
160- xkeyboard-config
161- xkbfile
162- iso-codes)
163-
164-XKB_BASE=$($PKG_CONFIG --variable xkb_base xkeyboard-config)
165-AC_SUBST(XKB_BASE)
166-
167-ISO_CODES_PREFIX=$($PKG_CONFIG --variable prefix iso-codes)
168-AC_SUBST(ISO_CODES_PREFIX)
169-
170-AC_CACHE_CHECK(for timerfd_create(2) system call,
171- gnome_cv_timerfd,AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
172-#include <sys/timerfd.h>
173-#include <unistd.h>
174-],[
175-int
176-main (void)
177-{
178- timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC);
179- return 0;
180-}
181-])],gnome_cv_timerfd=yes,gnome_cv_timerfd=no))
182-if test x"$gnome_cv_timerfd" = x"yes"; then
183- AC_DEFINE(HAVE_TIMERFD, 1, [we have the timerfd_create(2) system call])
184-fi
185-
186-dnl Documentation support
187-
188-YELP_HELP_INIT
189-
190-dnl Language Support
191-
192-GETTEXT_PACKAGE=gnome-desktop-3.0
193-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
194- [The gettext translation domain])
195-AC_SUBST(GETTEXT_PACKAGE)
196-
197-AM_GLIB_GNU_GETTEXT
198-
199-GOBJECT_INTROSPECTION_CHECK([0.9.7])
200-
201-# check for gtk-doc
202-GTK_DOC_CHECK([1.4])
203-
204-AC_CONFIG_FILES([
205-Makefile
206-libgnome-desktop/Makefile
207-libgnome-desktop/gnome-desktop-3.0.pc
208-libgnome-desktop/gnome-desktop-3.0-uninstalled.pc
209-docs/Makefile
210-docs/reference/Makefile
211-docs/reference/gnome-desktop3/Makefile
212-gnome-version.xml.in
213-po/Makefile.in
214-desktop-docs/Makefile
215-desktop-docs/fdl/Makefile
216-desktop-docs/gpl/Makefile
217-desktop-docs/lgpl/Makefile
218-])
219-
220-AC_OUTPUT
221-
222-dnl ---------------------------------------------------------------------------
223-dnl - Show summary
224-dnl ---------------------------------------------------------------------------
225-
226-echo "
227- gnome-desktop $VERSION
228- `echo gnome-desktop $VERSION | sed "s/./=/g"`
229-
230- prefix: ${prefix}
231- exec_prefix: ${exec_prefix}
232- libdir: ${libdir}
233- bindir: ${bindir}
234- sbindir: ${sbindir}
235- sysconfdir: ${sysconfdir}
236- localstatedir: ${localstatedir}
237- datadir: ${datadir}
238- source code location: ${srcdir}
239- compiler: ${CC}
240- cflags: ${CFLAGS}
241- Maintainer mode: ${USE_MAINTAINER_MODE}
242- Use *_DISABLE_DEPRECATED: ${enable_deprecation_flags}
243-
244- GNOME Distributor: ${GNOME_DISTRIBUTOR}
245- Build desktop-wide docs: ${enable_desktop_docs}
246- Date in gnome-version.xml: ${enable_date_in_gnome_version}
247- Use external pnp.ids: ${EXTERNAL_PNP_IDS}
248- Build gtk-doc documentation: ${enable_gtk_doc}
249-
250-"
251
252=== removed directory '.pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop'
253=== removed file '.pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/Makefile.am'
254--- .pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/Makefile.am 2013-05-28 09:10:46 +0000
255+++ .pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/Makefile.am 1970-01-01 00:00:00 +0000
256@@ -1,155 +0,0 @@
257-CLEANFILES =
258-
259-noinst_LTLIBRARIES =
260-lib_LTLIBRARIES = libgnome-desktop-3.la
261-
262-AM_CPPFLAGS = \
263- -I$(top_srcdir) \
264- -I$(srcdir)/libgsystem \
265- $(GNOME_DESKTOP_CFLAGS) \
266- $(XLIB_CFLAGS) \
267- -DG_LOG_DOMAIN=\"GnomeDesktop\" \
268- -DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale\"" \
269- -DISO_CODES_PREFIX=\""$(ISO_CODES_PREFIX)"\" \
270- -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \
271- -DPNP_IDS=\""$(PNP_IDS)"\" \
272- -DXKB_BASE=\""$(XKB_BASE)"\" \
273- $(DISABLE_DEPRECATED_CFLAGS)
274-
275-AM_CFLAGS = $(WARN_CFLAGS)
276-
277-libgsystem_srcpath := libgsystem
278-libgsystem_cflags = $(GNOME_DESKTOP_CFLAGS)
279-libgsystem_libs = $(GNOME_DESKTOP_LIBS)
280-include libgsystem/Makefile-libgsystem.am
281-
282-introspection_sources = \
283- gnome-desktop-thumbnail.c \
284- gnome-thumbnail-pixbuf-utils.c \
285- gnome-bg.c \
286- gnome-bg-slide-show.c \
287- gnome-bg-crossfade.c \
288- display-name.c \
289- gnome-rr.c \
290- gnome-rr-config.c \
291- gnome-rr-output-info.c \
292- gnome-pnp-ids.c \
293- gnome-wall-clock.c \
294- gnome-xkb-info.c \
295- gnome-idle-monitor.c \
296- gnome-languages.c \
297- edid-parse.c
298-
299-libgnome_desktop_3_la_SOURCES = \
300- $(introspection_sources) \
301- gnome-datetime-source.h \
302- gnome-datetime-source.c \
303- gnome-rr-private.h \
304- default-input-sources.h \
305- edid.h \
306- locarchive.h
307-
308-libgnome_desktop_3_la_LIBADD = \
309- $(XLIB_LIBS) \
310- $(LIBM) \
311- $(GNOME_DESKTOP_LIBS) \
312- libgsystem.la \
313- -lrt
314-
315-libgnome_desktop_3_la_LDFLAGS = \
316- -version-info $(LT_VERSION) \
317- -export-symbols-regex "^gnome_.*" \
318- -no-undefined
319-
320-pkgconfigdir = $(libdir)/pkgconfig
321-pkgconfig_DATA = gnome-desktop-3.0.pc
322-
323-libgnome_desktopdir = $(includedir)/gnome-desktop-3.0/libgnome-desktop
324-libgnome_desktop_HEADERS = \
325- gnome-bg.h \
326- gnome-bg-crossfade.h \
327- gnome-bg-slide-show.h \
328- gnome-desktop-thumbnail.h \
329- gnome-rr.h \
330- gnome-rr-config.h \
331- gnome-pnp-ids.h \
332- gnome-wall-clock.h \
333- gnome-xkb-info.h \
334- gnome-idle-monitor.h \
335- gnome-languages.h
336-
337-if USE_INTERNAL_PNP_IDS
338-pnpdatadir = $(datadir)/libgnome-desktop-3.0
339-pnpdata_DATA = pnp.ids
340-endif
341-pnpdata_DATA_dist = pnp.ids
342-
343-update-pnp-ids:
344- wget -O $(top_srcdir)/libgnome-desktop/pnp.ids "http://git.fedorahosted.org/git/?p=hwdata.git;a=blob_plain;f=pnp.ids;hb=HEAD"
345-
346-check:
347- test -s $(top_srcdir)/libgnome-desktop/pnp.ids
348-
349--include $(INTROSPECTION_MAKEFILE)
350-INTROSPECTION_GIRS =
351-INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --warn-all
352-INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
353-
354-if HAVE_INTROSPECTION
355-
356-GnomeDesktop-3.0.gir: libgnome-desktop-3.la
357-GnomeDesktop_3_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 GDesktopEnums-3.0
358-GnomeDesktop_3_0_gir_PACKAGES = gdk-pixbuf-2.0 glib-2.0 gobject-2.0 gio-2.0 gtk+-3.0 gsettings-desktop-schemas
359-GnomeDesktop_3_0_gir_EXPORT_PACKAGES = gnome-desktop-3.0
360-GnomeDesktop_3_0_gir_CFLAGS = -DGNOME_DESKTOP_USE_UNSTABLE_API -I$(top_srcdir)
361-GnomeDesktop_3_0_gir_LIBS = libgnome-desktop-3.la
362-GnomeDesktop_3_0_gir_FILES = $(introspection_sources) $(libgnome_desktop_HEADERS)
363-GnomeDesktop_3_0_gir_SCANNERFLAGS = --identifier-prefix=Gnome --symbol-prefix=gnome
364-INTROSPECTION_SCANNER_ARGS += $(patsubst %,--c-include='libgnome-desktop/%',$(libgnome_desktop_HEADERS))
365-INTROSPECTION_GIRS += GnomeDesktop-3.0.gir
366-
367-girdir = $(datadir)/gir-1.0
368-gir_DATA = $(INTROSPECTION_GIRS)
369-
370-typelibdir = $(libdir)/girepository-1.0
371-typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
372-
373-CLEANFILES += $(gir_DATA) $(typelib_DATA)
374-endif
375-
376-EXTRA_DIST = \
377- gnome-desktop-3.0.pc.in \
378- gnome-desktop-3.0-uninstalled.pc.in \
379- $(pnpdata_DATA_dist)
380-
381-MAINTAINERCLEANFILES = \
382- pnp.ids
383-
384-libexec_PROGRAMS = \
385- gnome-rr-debug
386-
387-gnome_rr_debug_SOURCES = \
388- gnome-rr-debug.c
389-
390-gnome_rr_debug_LDADD = \
391- $(GNOME_DESKTOP_LIBS) \
392- $(lib_LTLIBRARIES) \
393- $(XLIB_LIBS)
394-
395-noinst_PROGRAMS = test-xkb-info test-pnp-ids test-wall-clock test-desktop-thumbnail test-idle-monitor test-languages
396-test_xkb_info_LDADD = \
397- $(GNOME_DESKTOP_LIBS) \
398- $(lib_LTLIBRARIES) \
399- $(XLIB_LIBS)
400-
401-test_pnp_ids_LDADD = $(test_xkb_info_LDADD)
402-
403-test_wall_clock_LDADD = $(test_xkb_info_LDADD)
404-
405-test_desktop_thumbnail_LDADD = $(test_xkb_info_LDADD)
406-
407-test_idle_monitor_LDADD = $(test_xkb_info_LDADD)
408-
409-test_languages_LDADD = $(test_xkb_info_LDADD)
410-
411--include $(top_srcdir)/git.mk
412
413=== removed file '.pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/check_gl_texture_size.c'
414=== removed file '.pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/gnome-rr-config.c'
415--- .pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/gnome-rr-config.c 2013-05-28 09:10:46 +0000
416+++ .pc/02_refuse_to_break_GL_compositors.patch/libgnome-desktop/gnome-rr-config.c 1970-01-01 00:00:00 +0000
417@@ -1,1950 +0,0 @@
418-/* gnome-rr-config.c
419- * -*- c-basic-offset: 4 -*-
420- *
421- * Copyright 2007, 2008, Red Hat, Inc.
422- * Copyright 2010 Giovanni Campagna
423- *
424- * This file is part of the Gnome Library.
425- *
426- * The Gnome Library is free software; you can redistribute it and/or
427- * modify it under the terms of the GNU Library General Public License as
428- * published by the Free Software Foundation; either version 2 of the
429- * License, or (at your option) any later version.
430- *
431- * The Gnome Library is distributed in the hope that it will be useful,
432- * but WITHOUT ANY WARRANTY; without even the implied warranty of
433- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
434- * Library General Public License for more details.
435- *
436- * You should have received a copy of the GNU Library General Public
437- * License along with the Gnome Library; see the file COPYING.LIB. If not,
438- * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
439- * Boston, MA 02110-1301, USA.
440- *
441- * Author: Soren Sandmann <sandmann@redhat.com>
442- */
443-
444-#define GNOME_DESKTOP_USE_UNSTABLE_API
445-
446-#include <config.h>
447-#include <glib/gi18n-lib.h>
448-#include <stdlib.h>
449-#include <string.h>
450-#include <glib.h>
451-#include <glib/gstdio.h>
452-
453-#include <X11/Xlib.h>
454-#include <gdk/gdkx.h>
455-
456-#include "gnome-rr-config.h"
457-
458-#include "edid.h"
459-#include "gnome-rr-private.h"
460-
461-#define CONFIG_INTENDED_BASENAME "monitors.xml"
462-#define CONFIG_BACKUP_BASENAME "monitors.xml.backup"
463-
464-/* Look for DPI_FALLBACK in:
465- * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
466- * for the reasoning */
467-#define DPI_FALLBACK 96.0
468-
469-/* In version 0 of the config file format, we had several <configuration>
470- * toplevel elements and no explicit version number. So, the filed looked
471- * like
472- *
473- * <configuration>
474- * ...
475- * </configuration>
476- * <configuration>
477- * ...
478- * </configuration>
479- *
480- * Since version 1 of the config file, the file has a toplevel <monitors>
481- * element to group all the configurations. That element has a "version"
482- * attribute which is an integer. So, the file looks like this:
483- *
484- * <monitors version="1">
485- * <configuration>
486- * ...
487- * </configuration>
488- * <configuration>
489- * ...
490- * </configuration>
491- * </monitors>
492- */
493-
494-/* A helper wrapper around the GMarkup parser stuff */
495-static gboolean parse_file_gmarkup (const gchar *file,
496- const GMarkupParser *parser,
497- gpointer data,
498- GError **err);
499-
500-typedef struct CrtcAssignment CrtcAssignment;
501-
502-static gboolean crtc_assignment_apply (CrtcAssignment *assign,
503- guint32 timestamp,
504- GError **error);
505-static CrtcAssignment *crtc_assignment_new (GnomeRRScreen *screen,
506- GnomeRROutputInfo **outputs,
507- GError **error);
508-static void crtc_assignment_free (CrtcAssignment *assign);
509-
510-enum {
511- PROP_0,
512- PROP_SCREEN,
513- PROP_LAST
514-};
515-
516-G_DEFINE_TYPE (GnomeRRConfig, gnome_rr_config, G_TYPE_OBJECT)
517-
518-typedef struct Parser Parser;
519-
520-/* Parser for monitor configurations */
521-struct Parser
522-{
523- int config_file_version;
524- GnomeRROutputInfo * output;
525- GnomeRRConfig * configuration;
526- GPtrArray * outputs;
527- GPtrArray * configurations;
528- GQueue * stack;
529-};
530-
531-static int
532-parse_int (const char *text)
533-{
534- return strtol (text, NULL, 0);
535-}
536-
537-static guint
538-parse_uint (const char *text)
539-{
540- return strtoul (text, NULL, 0);
541-}
542-
543-static gboolean
544-stack_is (Parser *parser,
545- const char *s1,
546- ...)
547-{
548- GList *stack = NULL;
549- const char *s;
550- GList *l1, *l2;
551- va_list args;
552-
553- stack = g_list_prepend (stack, (gpointer)s1);
554-
555- va_start (args, s1);
556-
557- s = va_arg (args, const char *);
558- while (s)
559- {
560- stack = g_list_prepend (stack, (gpointer)s);
561- s = va_arg (args, const char *);
562- }
563-
564- l1 = stack;
565- l2 = parser->stack->head;
566-
567- while (l1 && l2)
568- {
569- if (strcmp (l1->data, l2->data) != 0)
570- {
571- g_list_free (stack);
572- return FALSE;
573- }
574-
575- l1 = l1->next;
576- l2 = l2->next;
577- }
578-
579- g_list_free (stack);
580-
581- return (!l1 && !l2);
582-}
583-
584-static void
585-handle_start_element (GMarkupParseContext *context,
586- const gchar *name,
587- const gchar **attr_names,
588- const gchar **attr_values,
589- gpointer user_data,
590- GError **err)
591-{
592- Parser *parser = user_data;
593-
594- if (strcmp (name, "output") == 0)
595- {
596- int i;
597- g_assert (parser->output == NULL);
598-
599- parser->output = g_object_new (GNOME_TYPE_RR_OUTPUT_INFO, NULL);
600- parser->output->priv->rotation = 0;
601-
602- for (i = 0; attr_names[i] != NULL; ++i)
603- {
604- if (strcmp (attr_names[i], "name") == 0)
605- {
606- parser->output->priv->name = g_strdup (attr_values[i]);
607- break;
608- }
609- }
610-
611- if (!parser->output->priv->name)
612- {
613- /* This really shouldn't happen, but it's better to make
614- * something up than to crash later.
615- */
616- g_warning ("Malformed monitor configuration file");
617-
618- parser->output->priv->name = g_strdup ("default");
619- }
620- parser->output->priv->connected = FALSE;
621- parser->output->priv->on = FALSE;
622- parser->output->priv->primary = FALSE;
623- }
624- else if (strcmp (name, "configuration") == 0)
625- {
626- g_assert (parser->configuration == NULL);
627-
628- parser->configuration = g_object_new (GNOME_TYPE_RR_CONFIG, NULL);
629- parser->configuration->priv->clone = FALSE;
630- parser->configuration->priv->outputs = NULL;
631- }
632- else if (strcmp (name, "monitors") == 0)
633- {
634- int i;
635-
636- for (i = 0; attr_names[i] != NULL; i++)
637- {
638- if (strcmp (attr_names[i], "version") == 0)
639- {
640- parser->config_file_version = parse_int (attr_values[i]);
641- break;
642- }
643- }
644- }
645-
646- g_queue_push_tail (parser->stack, g_strdup (name));
647-}
648-
649-static void
650-handle_end_element (GMarkupParseContext *context,
651- const gchar *name,
652- gpointer user_data,
653- GError **err)
654-{
655- Parser *parser = user_data;
656-
657- if (strcmp (name, "output") == 0)
658- {
659- /* If no rotation properties were set, just use GNOME_RR_ROTATION_0 */
660- if (parser->output->priv->rotation == 0)
661- parser->output->priv->rotation = GNOME_RR_ROTATION_0;
662-
663- g_ptr_array_add (parser->outputs, parser->output);
664-
665- parser->output = NULL;
666- }
667- else if (strcmp (name, "configuration") == 0)
668- {
669- g_ptr_array_add (parser->outputs, NULL);
670- parser->configuration->priv->outputs =
671- (GnomeRROutputInfo **)g_ptr_array_free (parser->outputs, FALSE);
672- parser->outputs = g_ptr_array_new ();
673- g_ptr_array_add (parser->configurations, parser->configuration);
674- parser->configuration = NULL;
675- }
676-
677- g_free (g_queue_pop_tail (parser->stack));
678-}
679-
680-#define TOPLEVEL_ELEMENT (parser->config_file_version > 0 ? "monitors" : NULL)
681-
682-static void
683-handle_text (GMarkupParseContext *context,
684- const gchar *text,
685- gsize text_len,
686- gpointer user_data,
687- GError **err)
688-{
689- Parser *parser = user_data;
690-
691- if (stack_is (parser, "vendor", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
692- {
693- parser->output->priv->connected = TRUE;
694-
695- strncpy ((gchar*) parser->output->priv->vendor, text, 3);
696- parser->output->priv->vendor[3] = 0;
697- }
698- else if (stack_is (parser, "clone", "configuration", TOPLEVEL_ELEMENT, NULL))
699- {
700- if (strcmp (text, "yes") == 0)
701- parser->configuration->priv->clone = TRUE;
702- }
703- else if (stack_is (parser, "product", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
704- {
705- parser->output->priv->connected = TRUE;
706-
707- parser->output->priv->product = parse_int (text);
708- }
709- else if (stack_is (parser, "serial", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
710- {
711- parser->output->priv->connected = TRUE;
712-
713- parser->output->priv->serial = parse_uint (text);
714- }
715- else if (stack_is (parser, "width", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
716- {
717- parser->output->priv->on = TRUE;
718-
719- parser->output->priv->width = parse_int (text);
720- }
721- else if (stack_is (parser, "x", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
722- {
723- parser->output->priv->on = TRUE;
724-
725- parser->output->priv->x = parse_int (text);
726- }
727- else if (stack_is (parser, "y", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
728- {
729- parser->output->priv->on = TRUE;
730-
731- parser->output->priv->y = parse_int (text);
732- }
733- else if (stack_is (parser, "height", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
734- {
735- parser->output->priv->on = TRUE;
736-
737- parser->output->priv->height = parse_int (text);
738- }
739- else if (stack_is (parser, "rate", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
740- {
741- parser->output->priv->on = TRUE;
742-
743- parser->output->priv->rate = parse_int (text);
744- }
745- else if (stack_is (parser, "rotation", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
746- {
747- if (strcmp (text, "normal") == 0)
748- {
749- parser->output->priv->rotation |= GNOME_RR_ROTATION_0;
750- }
751- else if (strcmp (text, "left") == 0)
752- {
753- parser->output->priv->rotation |= GNOME_RR_ROTATION_90;
754- }
755- else if (strcmp (text, "upside_down") == 0)
756- {
757- parser->output->priv->rotation |= GNOME_RR_ROTATION_180;
758- }
759- else if (strcmp (text, "right") == 0)
760- {
761- parser->output->priv->rotation |= GNOME_RR_ROTATION_270;
762- }
763- }
764- else if (stack_is (parser, "reflect_x", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
765- {
766- if (strcmp (text, "yes") == 0)
767- {
768- parser->output->priv->rotation |= GNOME_RR_REFLECT_X;
769- }
770- }
771- else if (stack_is (parser, "reflect_y", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
772- {
773- if (strcmp (text, "yes") == 0)
774- {
775- parser->output->priv->rotation |= GNOME_RR_REFLECT_Y;
776- }
777- }
778- else if (stack_is (parser, "primary", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
779- {
780- if (strcmp (text, "yes") == 0)
781- {
782- parser->output->priv->primary = TRUE;
783- }
784- }
785- else
786- {
787- /* Ignore other properties so we can expand the format in the future */
788- }
789-}
790-
791-static void
792-parser_free (Parser *parser)
793-{
794- int i;
795- GList *list;
796-
797- g_assert (parser != NULL);
798-
799- if (parser->output)
800- g_object_unref (parser->output);
801-
802- if (parser->configuration)
803- g_object_unref (parser->configuration);
804-
805- for (i = 0; i < parser->outputs->len; ++i)
806- {
807- GnomeRROutputInfo *output = parser->outputs->pdata[i];
808-
809- g_object_unref (output);
810- }
811-
812- g_ptr_array_free (parser->outputs, TRUE);
813-
814- for (i = 0; i < parser->configurations->len; ++i)
815- {
816- GnomeRRConfig *config = parser->configurations->pdata[i];
817-
818- g_object_unref (config);
819- }
820-
821- g_ptr_array_free (parser->configurations, TRUE);
822-
823- for (list = parser->stack->head; list; list = list->next)
824- g_free (list->data);
825- g_queue_free (parser->stack);
826-
827- g_free (parser);
828-}
829-
830-static GnomeRRConfig **
831-configurations_read_from_file (const gchar *filename, GError **error)
832-{
833- Parser *parser = g_new0 (Parser, 1);
834- GnomeRRConfig **result;
835- GMarkupParser callbacks = {
836- handle_start_element,
837- handle_end_element,
838- handle_text,
839- NULL, /* passthrough */
840- NULL, /* error */
841- };
842-
843- parser->config_file_version = 0;
844- parser->configurations = g_ptr_array_new ();
845- parser->outputs = g_ptr_array_new ();
846- parser->stack = g_queue_new ();
847-
848- if (!parse_file_gmarkup (filename, &callbacks, parser, error))
849- {
850- result = NULL;
851-
852- g_assert (parser->outputs);
853- goto out;
854- }
855-
856- g_assert (parser->outputs);
857-
858- g_ptr_array_add (parser->configurations, NULL);
859- result = (GnomeRRConfig **)g_ptr_array_free (parser->configurations, FALSE);
860- parser->configurations = g_ptr_array_new ();
861-
862- g_assert (parser->outputs);
863-out:
864- parser_free (parser);
865-
866- return result;
867-}
868-
869-static void
870-gnome_rr_config_init (GnomeRRConfig *self)
871-{
872- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_RR_CONFIG, GnomeRRConfigPrivate);
873-
874- self->priv->clone = FALSE;
875- self->priv->screen = NULL;
876- self->priv->outputs = NULL;
877-}
878-
879-static void
880-gnome_rr_config_set_property (GObject *gobject, guint property_id, const GValue *value, GParamSpec *property)
881-{
882- GnomeRRConfig *self = GNOME_RR_CONFIG (gobject);
883-
884- switch (property_id) {
885- case PROP_SCREEN:
886- self->priv->screen = g_value_dup_object (value);
887- return;
888- default:
889- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property);
890- }
891-}
892-
893-static void
894-gnome_rr_config_finalize (GObject *gobject)
895-{
896- GnomeRRConfig *self = GNOME_RR_CONFIG (gobject);
897-
898- if (self->priv->screen)
899- g_object_unref (self->priv->screen);
900-
901- if (self->priv->outputs) {
902- int i;
903-
904- for (i = 0; self->priv->outputs[i] != NULL; i++) {
905- GnomeRROutputInfo *output = self->priv->outputs[i];
906- g_object_unref (output);
907- }
908- g_free (self->priv->outputs);
909- }
910-
911- G_OBJECT_CLASS (gnome_rr_config_parent_class)->finalize (gobject);
912-}
913-
914-gboolean
915-gnome_rr_config_load_current (GnomeRRConfig *config, GError **error)
916-{
917- GPtrArray *a;
918- GnomeRROutput **rr_outputs;
919- int i;
920- int clone_width = -1;
921- int clone_height = -1;
922- int last_x;
923-
924- g_return_val_if_fail (GNOME_IS_RR_CONFIG (config), FALSE);
925-
926- a = g_ptr_array_new ();
927- rr_outputs = gnome_rr_screen_list_outputs (config->priv->screen);
928-
929- config->priv->clone = FALSE;
930-
931- for (i = 0; rr_outputs[i] != NULL; ++i)
932- {
933- GnomeRROutput *rr_output = rr_outputs[i];
934- GnomeRROutputInfo *output = g_object_new (GNOME_TYPE_RR_OUTPUT_INFO, NULL);
935- GnomeRRMode *mode = NULL;
936- const guint8 *edid_data = gnome_rr_output_get_edid_data (rr_output, NULL);
937- GnomeRRCrtc *crtc;
938-
939- output->priv->name = g_strdup (gnome_rr_output_get_name (rr_output));
940- output->priv->connected = gnome_rr_output_is_connected (rr_output);
941- output->priv->display_name = g_strdup (gnome_rr_output_get_display_name (rr_output));
942-
943- if (!output->priv->connected)
944- {
945- output->priv->x = -1;
946- output->priv->y = -1;
947- output->priv->width = -1;
948- output->priv->height = -1;
949- output->priv->rate = -1;
950- output->priv->rotation = GNOME_RR_ROTATION_0;
951- }
952- else
953- {
954- MonitorInfo *info = NULL;
955-
956- if (edid_data)
957- info = decode_edid (edid_data);
958-
959- if (info)
960- {
961- memcpy (output->priv->vendor, info->manufacturer_code,
962- sizeof (output->priv->vendor));
963-
964- output->priv->product = info->product_code;
965- output->priv->serial = info->serial_number;
966- output->priv->aspect = info->aspect_ratio;
967- }
968- else
969- {
970- strcpy (output->priv->vendor, "???");
971- output->priv->product = 0;
972- output->priv->serial = 0;
973- }
974- g_free (info);
975-
976- crtc = gnome_rr_output_get_crtc (rr_output);
977- mode = crtc? gnome_rr_crtc_get_current_mode (crtc) : NULL;
978-
979- if (crtc && mode)
980- {
981- output->priv->on = TRUE;
982-
983- gnome_rr_crtc_get_position (crtc, &output->priv->x, &output->priv->y);
984- output->priv->width = gnome_rr_mode_get_width (mode);
985- output->priv->height = gnome_rr_mode_get_height (mode);
986- output->priv->rate = gnome_rr_mode_get_freq (mode);
987- output->priv->rotation = gnome_rr_crtc_get_current_rotation (crtc);
988-
989- if (output->priv->x == 0 && output->priv->y == 0) {
990- if (clone_width == -1) {
991- clone_width = output->priv->width;
992- clone_height = output->priv->height;
993- } else if (clone_width == output->priv->width &&
994- clone_height == output->priv->height) {
995- config->priv->clone = TRUE;
996- }
997- }
998- }
999- else
1000- {
1001- output->priv->on = FALSE;
1002- config->priv->clone = FALSE;
1003- }
1004-
1005- /* Get preferred size for the monitor */
1006- mode = gnome_rr_output_get_preferred_mode (rr_output);
1007-
1008- if (!mode)
1009- {
1010- GnomeRRMode **modes = gnome_rr_output_list_modes (rr_output);
1011-
1012- /* FIXME: we should pick the "best" mode here, where best is
1013- * sorted wrt
1014- *
1015- * - closest aspect ratio
1016- * - mode area
1017- * - refresh rate
1018- * - We may want to extend randrwrap so that get_preferred
1019- * returns that - although that could also depend on
1020- * the crtc.
1021- */
1022- if (modes[0])
1023- mode = modes[0];
1024- }
1025-
1026- if (mode)
1027- {
1028- output->priv->pref_width = gnome_rr_mode_get_width (mode);
1029- output->priv->pref_height = gnome_rr_mode_get_height (mode);
1030- }
1031- else
1032- {
1033- /* Pick some random numbers. This should basically never happen */
1034- output->priv->pref_width = 1024;
1035- output->priv->pref_height = 768;
1036- }
1037- }
1038-
1039- output->priv->primary = gnome_rr_output_get_is_primary (rr_output);
1040-
1041- g_ptr_array_add (a, output);
1042- }
1043-
1044- g_ptr_array_add (a, NULL);
1045-
1046- config->priv->outputs = (GnomeRROutputInfo **)g_ptr_array_free (a, FALSE);
1047-
1048- /* Walk the outputs computing the right-most edge of all
1049- * lit-up displays
1050- */
1051- last_x = 0;
1052- for (i = 0; config->priv->outputs[i] != NULL; ++i)
1053- {
1054- GnomeRROutputInfo *output = config->priv->outputs[i];
1055-
1056- if (output->priv->on)
1057- {
1058- last_x = MAX (last_x, output->priv->x + output->priv->width);
1059- }
1060- }
1061-
1062- /* Now position all off displays to the right of the
1063- * on displays
1064- */
1065- for (i = 0; config->priv->outputs[i] != NULL; ++i)
1066- {
1067- GnomeRROutputInfo *output = config->priv->outputs[i];
1068-
1069- if (output->priv->connected && !output->priv->on)
1070- {
1071- output->priv->x = last_x;
1072- last_x = output->priv->x + output->priv->width;
1073- }
1074- }
1075-
1076- g_assert (gnome_rr_config_match (config, config));
1077-
1078- return TRUE;
1079-}
1080-
1081-gboolean
1082-gnome_rr_config_load_filename (GnomeRRConfig *result, const char *filename, GError **error)
1083-{
1084- GnomeRRConfig *current;
1085- GnomeRRConfig **configs;
1086- gboolean found = FALSE;
1087-
1088- g_return_val_if_fail (GNOME_IS_RR_CONFIG (result), FALSE);
1089- g_return_val_if_fail (filename != NULL, FALSE);
1090- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1091-
1092- current = gnome_rr_config_new_current (result->priv->screen, error);
1093-
1094- configs = configurations_read_from_file (filename, error);
1095-
1096- if (configs)
1097- {
1098- int i;
1099-
1100- for (i = 0; configs[i] != NULL; ++i)
1101- {
1102- if (gnome_rr_config_match (configs[i], current))
1103- {
1104- int j;
1105- GPtrArray *array;
1106- result->priv->clone = configs[i]->priv->clone;
1107-
1108- array = g_ptr_array_new ();
1109- for (j = 0; configs[i]->priv->outputs[j] != NULL; j++) {
1110- g_object_ref (configs[i]->priv->outputs[j]);
1111- g_ptr_array_add (array, configs[i]->priv->outputs[j]);
1112- }
1113- g_ptr_array_add (array, NULL);
1114- result->priv->outputs = (GnomeRROutputInfo **) g_ptr_array_free (array, FALSE);
1115-
1116- found = TRUE;
1117- break;
1118- }
1119- g_object_unref (configs[i]);
1120- }
1121- g_free (configs);
1122-
1123- if (!found)
1124- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG,
1125- _("none of the saved display configurations matched the active configuration"));
1126- }
1127-
1128- g_object_unref (current);
1129- return found;
1130-}
1131-
1132-static void
1133-gnome_rr_config_class_init (GnomeRRConfigClass *klass)
1134-{
1135- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1136-
1137- g_type_class_add_private (klass, sizeof (GnomeRROutputInfoPrivate));
1138-
1139- gobject_class->set_property = gnome_rr_config_set_property;
1140- gobject_class->finalize = gnome_rr_config_finalize;
1141-
1142- g_object_class_install_property (gobject_class, PROP_SCREEN,
1143- g_param_spec_object ("screen", "Screen", "The GnomeRRScreen this config applies to", GNOME_TYPE_RR_SCREEN,
1144- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
1145-}
1146-
1147-GnomeRRConfig *
1148-gnome_rr_config_new_current (GnomeRRScreen *screen, GError **error)
1149-{
1150- GnomeRRConfig *self = g_object_new (GNOME_TYPE_RR_CONFIG, "screen", screen, NULL);
1151-
1152- if (gnome_rr_config_load_current (self, error))
1153- return self;
1154- else
1155- {
1156- g_object_unref (self);
1157- return NULL;
1158- }
1159-}
1160-
1161-GnomeRRConfig *
1162-gnome_rr_config_new_stored (GnomeRRScreen *screen, GError **error)
1163-{
1164- GnomeRRConfig *self = g_object_new (GNOME_TYPE_RR_CONFIG, "screen", screen, NULL);
1165- char *filename;
1166- gboolean success;
1167-
1168- filename = gnome_rr_config_get_intended_filename ();
1169-
1170- success = gnome_rr_config_load_filename (self, filename, error);
1171-
1172- g_free (filename);
1173-
1174- if (success)
1175- return self;
1176- else
1177- {
1178- g_object_unref (self);
1179- return NULL;
1180- }
1181-}
1182-
1183-static gboolean
1184-parse_file_gmarkup (const gchar *filename,
1185- const GMarkupParser *parser,
1186- gpointer data,
1187- GError **err)
1188-{
1189- GMarkupParseContext *context = NULL;
1190- gchar *contents = NULL;
1191- gboolean result = TRUE;
1192- gsize len;
1193-
1194- if (!g_file_get_contents (filename, &contents, &len, err))
1195- {
1196- result = FALSE;
1197- goto out;
1198- }
1199-
1200- context = g_markup_parse_context_new (parser, 0, data, NULL);
1201-
1202- if (!g_markup_parse_context_parse (context, contents, len, err))
1203- {
1204- result = FALSE;
1205- goto out;
1206- }
1207-
1208- if (!g_markup_parse_context_end_parse (context, err))
1209- {
1210- result = FALSE;
1211- goto out;
1212- }
1213-
1214-out:
1215- if (contents)
1216- g_free (contents);
1217-
1218- if (context)
1219- g_markup_parse_context_free (context);
1220-
1221- return result;
1222-}
1223-
1224-static gboolean
1225-output_match (GnomeRROutputInfo *output1, GnomeRROutputInfo *output2)
1226-{
1227- g_assert (GNOME_IS_RR_OUTPUT_INFO (output1));
1228- g_assert (GNOME_IS_RR_OUTPUT_INFO (output2));
1229-
1230- if (strcmp (output1->priv->name, output2->priv->name) != 0)
1231- return FALSE;
1232-
1233- if (strcmp (output1->priv->vendor, output2->priv->vendor) != 0)
1234- return FALSE;
1235-
1236- if (output1->priv->product != output2->priv->product)
1237- return FALSE;
1238-
1239- if (output1->priv->serial != output2->priv->serial)
1240- return FALSE;
1241-
1242- if (output1->priv->connected != output2->priv->connected)
1243- return FALSE;
1244-
1245- return TRUE;
1246-}
1247-
1248-static gboolean
1249-output_equal (GnomeRROutputInfo *output1, GnomeRROutputInfo *output2)
1250-{
1251- g_assert (GNOME_IS_RR_OUTPUT_INFO (output1));
1252- g_assert (GNOME_IS_RR_OUTPUT_INFO (output2));
1253-
1254- if (!output_match (output1, output2))
1255- return FALSE;
1256-
1257- if (output1->priv->on != output2->priv->on)
1258- return FALSE;
1259-
1260- if (output1->priv->on)
1261- {
1262- if (output1->priv->width != output2->priv->width)
1263- return FALSE;
1264-
1265- if (output1->priv->height != output2->priv->height)
1266- return FALSE;
1267-
1268- if (output1->priv->rate != output2->priv->rate)
1269- return FALSE;
1270-
1271- if (output1->priv->x != output2->priv->x)
1272- return FALSE;
1273-
1274- if (output1->priv->y != output2->priv->y)
1275- return FALSE;
1276-
1277- if (output1->priv->rotation != output2->priv->rotation)
1278- return FALSE;
1279- }
1280-
1281- return TRUE;
1282-}
1283-
1284-static GnomeRROutputInfo *
1285-find_output (GnomeRRConfig *config, const char *name)
1286-{
1287- int i;
1288-
1289- for (i = 0; config->priv->outputs[i] != NULL; ++i)
1290- {
1291- GnomeRROutputInfo *output = config->priv->outputs[i];
1292-
1293- if (strcmp (name, output->priv->name) == 0)
1294- return output;
1295- }
1296-
1297- return NULL;
1298-}
1299-
1300-/* Match means "these configurations apply to the same hardware
1301- * setups"
1302- */
1303-gboolean
1304-gnome_rr_config_match (GnomeRRConfig *c1, GnomeRRConfig *c2)
1305-{
1306- int i;
1307- g_return_val_if_fail (GNOME_IS_RR_CONFIG (c1), FALSE);
1308- g_return_val_if_fail (GNOME_IS_RR_CONFIG (c2), FALSE);
1309-
1310- for (i = 0; c1->priv->outputs[i] != NULL; ++i)
1311- {
1312- GnomeRROutputInfo *output1 = c1->priv->outputs[i];
1313- GnomeRROutputInfo *output2;
1314-
1315- output2 = find_output (c2, output1->priv->name);
1316- if (!output2 || !output_match (output1, output2))
1317- return FALSE;
1318- }
1319-
1320- return TRUE;
1321-}
1322-
1323-/* Equal means "the configurations will result in the same
1324- * modes being set on the outputs"
1325- */
1326-gboolean
1327-gnome_rr_config_equal (GnomeRRConfig *c1,
1328- GnomeRRConfig *c2)
1329-{
1330- int i;
1331- g_return_val_if_fail (GNOME_IS_RR_CONFIG (c1), FALSE);
1332- g_return_val_if_fail (GNOME_IS_RR_CONFIG (c2), FALSE);
1333-
1334- for (i = 0; c1->priv->outputs[i] != NULL; ++i)
1335- {
1336- GnomeRROutputInfo *output1 = c1->priv->outputs[i];
1337- GnomeRROutputInfo *output2;
1338-
1339- output2 = find_output (c2, output1->priv->name);
1340- if (!output2 || !output_equal (output1, output2))
1341- return FALSE;
1342- }
1343-
1344- return TRUE;
1345-}
1346-
1347-static GnomeRROutputInfo **
1348-make_outputs (GnomeRRConfig *config)
1349-{
1350- GPtrArray *outputs;
1351- GnomeRROutputInfo *first_on;
1352- int i;
1353-
1354- outputs = g_ptr_array_new ();
1355-
1356- first_on = NULL;
1357-
1358- for (i = 0; config->priv->outputs[i] != NULL; ++i)
1359- {
1360- GnomeRROutputInfo *old = config->priv->outputs[i];
1361- GnomeRROutputInfo *new = g_object_new (GNOME_TYPE_RR_OUTPUT_INFO, NULL);
1362- *(new->priv) = *(old->priv);
1363- if (old->priv->name)
1364- new->priv->name = g_strdup (old->priv->name);
1365- if (old->priv->display_name)
1366- new->priv->display_name = g_strdup (old->priv->display_name);
1367-
1368- if (old->priv->on && !first_on)
1369- first_on = old;
1370-
1371- if (config->priv->clone && new->priv->on)
1372- {
1373- g_assert (first_on);
1374-
1375- new->priv->width = first_on->priv->width;
1376- new->priv->height = first_on->priv->height;
1377- new->priv->rotation = first_on->priv->rotation;
1378- new->priv->x = 0;
1379- new->priv->y = 0;
1380- }
1381-
1382- g_ptr_array_add (outputs, new);
1383- }
1384-
1385- g_ptr_array_add (outputs, NULL);
1386-
1387- return (GnomeRROutputInfo **)g_ptr_array_free (outputs, FALSE);
1388-}
1389-
1390-gboolean
1391-gnome_rr_config_applicable (GnomeRRConfig *configuration,
1392- GnomeRRScreen *screen,
1393- GError **error)
1394-{
1395- GnomeRROutputInfo **outputs;
1396- CrtcAssignment *assign;
1397- gboolean result;
1398- int i;
1399-
1400- g_return_val_if_fail (GNOME_IS_RR_CONFIG (configuration), FALSE);
1401- g_return_val_if_fail (GNOME_IS_RR_SCREEN (screen), FALSE);
1402- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1403-
1404- outputs = make_outputs (configuration);
1405- assign = crtc_assignment_new (screen, outputs, error);
1406-
1407- if (assign)
1408- {
1409- result = TRUE;
1410- crtc_assignment_free (assign);
1411- }
1412- else
1413- {
1414- result = FALSE;
1415- }
1416-
1417- for (i = 0; outputs[i] != NULL; i++) {
1418- g_object_unref (outputs[i]);
1419- }
1420-
1421- return result;
1422-}
1423-
1424-/* Database management */
1425-
1426-static void
1427-ensure_config_directory (void)
1428-{
1429- g_mkdir_with_parents (g_get_user_config_dir (), 0700);
1430-}
1431-
1432-char *
1433-gnome_rr_config_get_backup_filename (void)
1434-{
1435- ensure_config_directory ();
1436- return g_build_filename (g_get_user_config_dir (), CONFIG_BACKUP_BASENAME, NULL);
1437-}
1438-
1439-char *
1440-gnome_rr_config_get_intended_filename (void)
1441-{
1442- ensure_config_directory ();
1443- return g_build_filename (g_get_user_config_dir (), CONFIG_INTENDED_BASENAME, NULL);
1444-}
1445-
1446-static const char *
1447-get_rotation_name (GnomeRRRotation r)
1448-{
1449- if (r & GNOME_RR_ROTATION_0)
1450- return "normal";
1451- if (r & GNOME_RR_ROTATION_90)
1452- return "left";
1453- if (r & GNOME_RR_ROTATION_180)
1454- return "upside_down";
1455- if (r & GNOME_RR_ROTATION_270)
1456- return "right";
1457-
1458- return "normal";
1459-}
1460-
1461-static const char *
1462-yes_no (int x)
1463-{
1464- return x? "yes" : "no";
1465-}
1466-
1467-static const char *
1468-get_reflect_x (GnomeRRRotation r)
1469-{
1470- return yes_no (r & GNOME_RR_REFLECT_X);
1471-}
1472-
1473-static const char *
1474-get_reflect_y (GnomeRRRotation r)
1475-{
1476- return yes_no (r & GNOME_RR_REFLECT_Y);
1477-}
1478-
1479-static void
1480-emit_configuration (GnomeRRConfig *config,
1481- GString *string)
1482-{
1483- int j;
1484-
1485- g_string_append_printf (string, " <configuration>\n");
1486-
1487- g_string_append_printf (string, " <clone>%s</clone>\n", yes_no (config->priv->clone));
1488-
1489- for (j = 0; config->priv->outputs[j] != NULL; ++j)
1490- {
1491- GnomeRROutputInfo *output = config->priv->outputs[j];
1492-
1493- g_string_append_printf (
1494- string, " <output name=\"%s\">\n", output->priv->name);
1495-
1496- if (output->priv->connected && *output->priv->vendor != '\0')
1497- {
1498- g_string_append_printf (
1499- string, " <vendor>%s</vendor>\n", output->priv->vendor);
1500- g_string_append_printf (
1501- string, " <product>0x%04x</product>\n", output->priv->product);
1502- g_string_append_printf (
1503- string, " <serial>0x%08x</serial>\n", output->priv->serial);
1504- }
1505-
1506- /* An unconnected output which is on does not make sense */
1507- if (output->priv->connected && output->priv->on)
1508- {
1509- g_string_append_printf (
1510- string, " <width>%d</width>\n", output->priv->width);
1511- g_string_append_printf (
1512- string, " <height>%d</height>\n", output->priv->height);
1513- g_string_append_printf (
1514- string, " <rate>%d</rate>\n", output->priv->rate);
1515- g_string_append_printf (
1516- string, " <x>%d</x>\n", output->priv->x);
1517- g_string_append_printf (
1518- string, " <y>%d</y>\n", output->priv->y);
1519- g_string_append_printf (
1520- string, " <rotation>%s</rotation>\n", get_rotation_name (output->priv->rotation));
1521- g_string_append_printf (
1522- string, " <reflect_x>%s</reflect_x>\n", get_reflect_x (output->priv->rotation));
1523- g_string_append_printf (
1524- string, " <reflect_y>%s</reflect_y>\n", get_reflect_y (output->priv->rotation));
1525- g_string_append_printf (
1526- string, " <primary>%s</primary>\n", yes_no (output->priv->primary));
1527- }
1528-
1529- g_string_append_printf (string, " </output>\n");
1530- }
1531-
1532- g_string_append_printf (string, " </configuration>\n");
1533-}
1534-
1535-void
1536-gnome_rr_config_sanitize (GnomeRRConfig *config)
1537-{
1538- int i;
1539- int x_offset, y_offset;
1540- gboolean found;
1541-
1542- /* Offset everything by the top/left-most coordinate to
1543- * make sure the configuration starts at (0, 0)
1544- */
1545- x_offset = y_offset = G_MAXINT;
1546- for (i = 0; config->priv->outputs[i]; ++i)
1547- {
1548- GnomeRROutputInfo *output = config->priv->outputs[i];
1549-
1550- if (output->priv->on)
1551- {
1552- x_offset = MIN (x_offset, output->priv->x);
1553- y_offset = MIN (y_offset, output->priv->y);
1554- }
1555- }
1556-
1557- for (i = 0; config->priv->outputs[i]; ++i)
1558- {
1559- GnomeRROutputInfo *output = config->priv->outputs[i];
1560-
1561- if (output->priv->on)
1562- {
1563- output->priv->x -= x_offset;
1564- output->priv->y -= y_offset;
1565- }
1566- }
1567-
1568- /* Only one primary, please */
1569- found = FALSE;
1570- for (i = 0; config->priv->outputs[i]; ++i)
1571- {
1572- if (config->priv->outputs[i]->priv->primary)
1573- {
1574- if (found)
1575- {
1576- config->priv->outputs[i]->priv->primary = FALSE;
1577- }
1578- else
1579- {
1580- found = TRUE;
1581- }
1582- }
1583- }
1584-}
1585-
1586-gboolean
1587-gnome_rr_config_ensure_primary (GnomeRRConfig *configuration)
1588-{
1589- int i;
1590- GnomeRROutputInfo *laptop;
1591- GnomeRROutputInfo *top_left;
1592- gboolean found;
1593- GnomeRRConfigPrivate *priv;
1594-
1595- g_return_val_if_fail (GNOME_IS_RR_CONFIG (configuration), FALSE);
1596-
1597- laptop = NULL;
1598- top_left = NULL;
1599- found = FALSE;
1600- priv = configuration->priv;
1601-
1602- for (i = 0; priv->outputs[i] != NULL; ++i) {
1603- GnomeRROutputInfo *info = priv->outputs[i];
1604-
1605- if (!info->priv->on) {
1606- info->priv->primary = FALSE;
1607- continue;
1608- }
1609-
1610- /* ensure only one */
1611- if (info->priv->primary) {
1612- if (found) {
1613- info->priv->primary = FALSE;
1614- } else {
1615- found = TRUE;
1616- }
1617- }
1618-
1619- if (top_left == NULL
1620- || (info->priv->x < top_left->priv->x
1621- && info->priv->y < top_left->priv->y)) {
1622- top_left = info;
1623- }
1624- if (laptop == NULL
1625- && _gnome_rr_output_name_is_laptop (info->priv->name)) {
1626- /* shame we can't find the connector type
1627- as with gnome_rr_output_is_laptop */
1628- laptop = info;
1629- }
1630- }
1631-
1632- if (!found) {
1633- if (laptop != NULL) {
1634- laptop->priv->primary = TRUE;
1635- } else if (top_left != NULL) {
1636- /* Note: top_left can be NULL if all outputs are off */
1637- top_left->priv->primary = TRUE;
1638- }
1639- }
1640-
1641- return !found;
1642-}
1643-
1644-gboolean
1645-gnome_rr_config_save (GnomeRRConfig *configuration, GError **error)
1646-{
1647- GnomeRRConfig **configurations;
1648- GString *output;
1649- int i;
1650- gchar *intended_filename;
1651- gchar *backup_filename;
1652- gboolean result;
1653-
1654- g_return_val_if_fail (GNOME_IS_RR_CONFIG (configuration), FALSE);
1655- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1656-
1657- output = g_string_new ("");
1658-
1659- backup_filename = gnome_rr_config_get_backup_filename ();
1660- intended_filename = gnome_rr_config_get_intended_filename ();
1661-
1662- configurations = configurations_read_from_file (intended_filename, NULL); /* NULL-GError */
1663-
1664- g_string_append_printf (output, "<monitors version=\"1\">\n");
1665-
1666- if (configurations)
1667- {
1668- for (i = 0; configurations[i] != NULL; ++i)
1669- {
1670- if (!gnome_rr_config_match (configurations[i], configuration))
1671- emit_configuration (configurations[i], output);
1672- g_object_unref (configurations[i]);
1673- }
1674-
1675- g_free (configurations);
1676- }
1677-
1678- emit_configuration (configuration, output);
1679-
1680- g_string_append_printf (output, "</monitors>\n");
1681-
1682- /* backup the file first */
1683- rename (intended_filename, backup_filename); /* no error checking because the intended file may not even exist */
1684-
1685- result = g_file_set_contents (intended_filename, output->str, -1, error);
1686-
1687- if (!result)
1688- rename (backup_filename, intended_filename); /* no error checking because the backup may not even exist */
1689-
1690- g_free (backup_filename);
1691- g_free (intended_filename);
1692-
1693- return result;
1694-}
1695-
1696-gboolean
1697-gnome_rr_config_apply_with_time (GnomeRRConfig *config,
1698- GnomeRRScreen *screen,
1699- guint32 timestamp,
1700- GError **error)
1701-{
1702- CrtcAssignment *assignment;
1703- GnomeRROutputInfo **outputs;
1704- gboolean result = FALSE;
1705- int i;
1706-
1707- g_return_val_if_fail (GNOME_IS_RR_CONFIG (config), FALSE);
1708- g_return_val_if_fail (GNOME_IS_RR_SCREEN (screen), FALSE);
1709-
1710- outputs = make_outputs (config);
1711-
1712- assignment = crtc_assignment_new (screen, outputs, error);
1713-
1714- for (i = 0; outputs[i] != NULL; i++)
1715- g_object_unref (outputs[i]);
1716- g_free (outputs);
1717-
1718- if (assignment)
1719- {
1720- if (crtc_assignment_apply (assignment, timestamp, error))
1721- result = TRUE;
1722-
1723- crtc_assignment_free (assignment);
1724-
1725- gdk_flush ();
1726- }
1727-
1728- return result;
1729-}
1730-
1731-/* gnome_rr_config_apply_from_filename_with_time:
1732- * @screen: A #GnomeRRScreen
1733- * @filename: Path of the file to look in for stored RANDR configurations.
1734- * @timestamp: X server timestamp from the event that causes the screen configuration to change (a user's button press, for example)
1735- * @error: Location to store error, or %NULL
1736- *
1737- * Loads the file in @filename and looks for suitable matching RANDR
1738- * configurations in the file; if one is found, that configuration will be
1739- * applied to the current set of RANDR outputs.
1740- *
1741- * Typically, @filename is the result of gnome_rr_config_get_intended_filename() or
1742- * gnome_rr_config_get_backup_filename().
1743- *
1744- * Returns: TRUE if the RANDR configuration was loaded and applied from
1745- * the specified file, or FALSE otherwise:
1746- *
1747- * If the file in question is loaded successfully but the configuration cannot
1748- * be applied, the @error will have a domain of #GNOME_RR_ERROR. Note that an
1749- * error code of #GNOME_RR_ERROR_NO_MATCHING_CONFIG is not a real error; it
1750- * simply means that there were no stored configurations that match the current
1751- * set of RANDR outputs.
1752- *
1753- * If the file in question cannot be loaded, the @error will have a domain of
1754- * #G_FILE_ERROR. Note that an error code of G_FILE_ERROR_NOENT is not really
1755- * an error, either; it means that there was no stored configuration file and so
1756- * nothing is changed.
1757- */
1758-gboolean
1759-gnome_rr_config_apply_from_filename_with_time (GnomeRRScreen *screen, const char *filename, guint32 timestamp, GError **error)
1760-{
1761- GnomeRRConfig *stored;
1762-
1763- g_return_val_if_fail (GNOME_IS_RR_SCREEN (screen), FALSE);
1764- g_return_val_if_fail (filename != NULL, FALSE);
1765- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1766-
1767- stored = g_object_new (GNOME_TYPE_RR_CONFIG, "screen", screen, NULL);
1768-
1769- if (gnome_rr_config_load_filename (stored, filename, error))
1770- {
1771- gboolean result;
1772-
1773- gnome_rr_config_ensure_primary (stored);
1774- result = gnome_rr_config_apply_with_time (stored, screen, timestamp, error);
1775-
1776- g_object_unref (stored);
1777- return result;
1778- }
1779- else
1780- {
1781- g_object_unref (stored);
1782- return FALSE;
1783- }
1784-}
1785-
1786-/**
1787- * gnome_rr_config_get_outputs:
1788- *
1789- * Returns: (array zero-terminated=1) (element-type GnomeDesktop.RROutputInfo) (transfer none): the output configuration for this #GnomeRRConfig
1790- */
1791-GnomeRROutputInfo **
1792-gnome_rr_config_get_outputs (GnomeRRConfig *self)
1793-{
1794- g_return_val_if_fail (GNOME_IS_RR_CONFIG (self), NULL);
1795-
1796- return self->priv->outputs;
1797-}
1798-
1799-/**
1800- * gnome_rr_config_get_clone:
1801- *
1802- * Returns: whether at least two outputs are at (0, 0) offset and they
1803- * have the same width/height. Those outputs are of course connected and on
1804- * (i.e. they have a CRTC assigned).
1805- */
1806-gboolean
1807-gnome_rr_config_get_clone (GnomeRRConfig *self)
1808-{
1809- g_return_val_if_fail (GNOME_IS_RR_CONFIG (self), FALSE);
1810-
1811- return self->priv->clone;
1812-}
1813-
1814-void
1815-gnome_rr_config_set_clone (GnomeRRConfig *self, gboolean clone)
1816-{
1817- g_return_if_fail (GNOME_IS_RR_CONFIG (self));
1818-
1819- self->priv->clone = clone;
1820-}
1821-
1822-/*
1823- * CRTC assignment
1824- */
1825-typedef struct CrtcInfo CrtcInfo;
1826-
1827-struct CrtcInfo
1828-{
1829- GnomeRRMode *mode;
1830- int x;
1831- int y;
1832- GnomeRRRotation rotation;
1833- GPtrArray *outputs;
1834-};
1835-
1836-struct CrtcAssignment
1837-{
1838- GnomeRRScreen *screen;
1839- GHashTable *info;
1840- GnomeRROutput *primary;
1841-};
1842-
1843-static gboolean
1844-can_clone (CrtcInfo *info,
1845- GnomeRROutput *output)
1846-{
1847- int i;
1848-
1849- for (i = 0; i < info->outputs->len; ++i)
1850- {
1851- GnomeRROutput *clone = info->outputs->pdata[i];
1852-
1853- if (!gnome_rr_output_can_clone (clone, output))
1854- return FALSE;
1855- }
1856-
1857- return TRUE;
1858-}
1859-
1860-static gboolean
1861-crtc_assignment_assign (CrtcAssignment *assign,
1862- GnomeRRCrtc *crtc,
1863- GnomeRRMode *mode,
1864- int x,
1865- int y,
1866- GnomeRRRotation rotation,
1867- gboolean primary,
1868- GnomeRROutput *output,
1869- GError **error)
1870-{
1871- CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
1872- guint32 crtc_id;
1873- const char *output_name;
1874-
1875- crtc_id = gnome_rr_crtc_get_id (crtc);
1876- output_name = gnome_rr_output_get_name (output);
1877-
1878- if (!gnome_rr_crtc_can_drive_output (crtc, output))
1879- {
1880- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
1881- _("CRTC %d cannot drive output %s"), crtc_id, output_name);
1882- return FALSE;
1883- }
1884-
1885- if (!gnome_rr_output_supports_mode (output, mode))
1886- {
1887- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
1888- _("output %s does not support mode %dx%d@%dHz"),
1889- output_name,
1890- gnome_rr_mode_get_width (mode),
1891- gnome_rr_mode_get_height (mode),
1892- gnome_rr_mode_get_freq (mode));
1893- return FALSE;
1894- }
1895-
1896- if (!gnome_rr_crtc_supports_rotation (crtc, rotation))
1897- {
1898- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
1899- _("CRTC %d does not support rotation=%s"),
1900- crtc_id,
1901- get_rotation_name (rotation));
1902- return FALSE;
1903- }
1904-
1905- if (info)
1906- {
1907- if (!(info->mode == mode &&
1908- info->x == x &&
1909- info->y == y &&
1910- info->rotation == rotation))
1911- {
1912- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
1913- _("output %s does not have the same parameters as another cloned output:\n"
1914- "existing mode = %d, new mode = %d\n"
1915- "existing coordinates = (%d, %d), new coordinates = (%d, %d)\n"
1916- "existing rotation = %s, new rotation = %s"),
1917- output_name,
1918- gnome_rr_mode_get_id (info->mode), gnome_rr_mode_get_id (mode),
1919- info->x, info->y,
1920- x, y,
1921- get_rotation_name (info->rotation), get_rotation_name (rotation));
1922- return FALSE;
1923- }
1924-
1925- if (!can_clone (info, output))
1926- {
1927- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
1928- _("cannot clone to output %s"),
1929- output_name);
1930- return FALSE;
1931- }
1932-
1933- g_ptr_array_add (info->outputs, output);
1934-
1935- if (primary && !assign->primary)
1936- {
1937- assign->primary = output;
1938- }
1939-
1940- return TRUE;
1941- }
1942- else
1943- {
1944- CrtcInfo *info = g_new0 (CrtcInfo, 1);
1945-
1946- info->mode = mode;
1947- info->x = x;
1948- info->y = y;
1949- info->rotation = rotation;
1950- info->outputs = g_ptr_array_new ();
1951-
1952- g_ptr_array_add (info->outputs, output);
1953-
1954- g_hash_table_insert (assign->info, crtc, info);
1955-
1956- if (primary && !assign->primary)
1957- {
1958- assign->primary = output;
1959- }
1960-
1961- return TRUE;
1962- }
1963-}
1964-
1965-static void
1966-crtc_assignment_unassign (CrtcAssignment *assign,
1967- GnomeRRCrtc *crtc,
1968- GnomeRROutput *output)
1969-{
1970- CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
1971-
1972- if (info)
1973- {
1974- g_ptr_array_remove (info->outputs, output);
1975-
1976- if (assign->primary == output)
1977- {
1978- assign->primary = NULL;
1979- }
1980-
1981- if (info->outputs->len == 0)
1982- g_hash_table_remove (assign->info, crtc);
1983- }
1984-}
1985-
1986-static void
1987-crtc_assignment_free (CrtcAssignment *assign)
1988-{
1989- g_hash_table_destroy (assign->info);
1990-
1991- g_free (assign);
1992-}
1993-
1994-typedef struct {
1995- guint32 timestamp;
1996- gboolean has_error;
1997- GError **error;
1998-} ConfigureCrtcState;
1999-
2000-static void
2001-configure_crtc (gpointer key,
2002- gpointer value,
2003- gpointer data)
2004-{
2005- GnomeRRCrtc *crtc = key;
2006- CrtcInfo *info = value;
2007- ConfigureCrtcState *state = data;
2008-
2009- if (state->has_error)
2010- return;
2011-
2012- if (!gnome_rr_crtc_set_config_with_time (crtc,
2013- state->timestamp,
2014- info->x, info->y,
2015- info->mode,
2016- info->rotation,
2017- (GnomeRROutput **)info->outputs->pdata,
2018- info->outputs->len,
2019- state->error))
2020- state->has_error = TRUE;
2021-}
2022-
2023-static gboolean
2024-mode_is_rotated (CrtcInfo *info)
2025-{
2026- if ((info->rotation & GNOME_RR_ROTATION_270) ||
2027- (info->rotation & GNOME_RR_ROTATION_90))
2028- {
2029- return TRUE;
2030- }
2031- return FALSE;
2032-}
2033-
2034-static gboolean
2035-crtc_is_rotated (GnomeRRCrtc *crtc)
2036-{
2037- GnomeRRRotation r = gnome_rr_crtc_get_current_rotation (crtc);
2038-
2039- if ((r & GNOME_RR_ROTATION_270) ||
2040- (r & GNOME_RR_ROTATION_90))
2041- {
2042- return TRUE;
2043- }
2044-
2045- return FALSE;
2046-}
2047-
2048-static void
2049-accumulate_error (GString *accumulated_error, GError *error)
2050-{
2051- g_string_append_printf (accumulated_error, " %s\n", error->message);
2052- g_error_free (error);
2053-}
2054-
2055-/* Check whether the given set of settings can be used
2056- * at the same time -- ie. whether there is an assignment
2057- * of CRTC's to outputs.
2058- *
2059- * Brute force - the number of objects involved is small
2060- * enough that it doesn't matter.
2061- */
2062-static gboolean
2063-real_assign_crtcs (GnomeRRScreen *screen,
2064- GnomeRROutputInfo **outputs,
2065- CrtcAssignment *assignment,
2066- GError **error)
2067-{
2068- GnomeRRCrtc **crtcs = gnome_rr_screen_list_crtcs (screen);
2069- GnomeRROutputInfo *output;
2070- int i;
2071- gboolean tried_mode;
2072- GError *my_error;
2073- GString *accumulated_error;
2074- gboolean success;
2075-
2076- output = *outputs;
2077- if (!output)
2078- return TRUE;
2079-
2080- /* It is always allowed for an output to be turned off */
2081- if (!output->priv->on)
2082- {
2083- return real_assign_crtcs (screen, outputs + 1, assignment, error);
2084- }
2085-
2086- success = FALSE;
2087- tried_mode = FALSE;
2088- accumulated_error = g_string_new (NULL);
2089-
2090- for (i = 0; crtcs[i] != NULL; ++i)
2091- {
2092- GnomeRRCrtc *crtc = crtcs[i];
2093- int crtc_id = gnome_rr_crtc_get_id (crtc);
2094- int pass;
2095-
2096- g_string_append_printf (accumulated_error,
2097- _("Trying modes for CRTC %d\n"),
2098- crtc_id);
2099-
2100- /* Make two passes, one where frequencies must match, then
2101- * one where they don't have to
2102- */
2103- for (pass = 0; pass < 2; ++pass)
2104- {
2105- GnomeRROutput *gnome_rr_output = gnome_rr_screen_get_output_by_name (screen, output->priv->name);
2106- GnomeRRMode **modes = gnome_rr_output_list_modes (gnome_rr_output);
2107- int j;
2108-
2109- for (j = 0; modes[j] != NULL; ++j)
2110- {
2111- GnomeRRMode *mode = modes[j];
2112- int mode_width;
2113- int mode_height;
2114- int mode_freq;
2115-
2116- mode_width = gnome_rr_mode_get_width (mode);
2117- mode_height = gnome_rr_mode_get_height (mode);
2118- mode_freq = gnome_rr_mode_get_freq (mode);
2119-
2120- g_string_append_printf (accumulated_error,
2121- _("CRTC %d: trying mode %dx%d@%dHz with output at %dx%d@%dHz (pass %d)\n"),
2122- crtc_id,
2123- mode_width, mode_height, mode_freq,
2124- output->priv->width, output->priv->height, output->priv->rate,
2125- pass);
2126-
2127- if (mode_width == output->priv->width &&
2128- mode_height == output->priv->height &&
2129- (pass == 1 || mode_freq == output->priv->rate))
2130- {
2131- tried_mode = TRUE;
2132-
2133- my_error = NULL;
2134- if (crtc_assignment_assign (
2135- assignment, crtc, modes[j],
2136- output->priv->x, output->priv->y,
2137- output->priv->rotation,
2138- output->priv->primary,
2139- gnome_rr_output,
2140- &my_error))
2141- {
2142- my_error = NULL;
2143- if (real_assign_crtcs (screen, outputs + 1, assignment, &my_error)) {
2144- success = TRUE;
2145- goto out;
2146- } else
2147- accumulate_error (accumulated_error, my_error);
2148-
2149- crtc_assignment_unassign (assignment, crtc, gnome_rr_output);
2150- } else
2151- accumulate_error (accumulated_error, my_error);
2152- }
2153- }
2154- }
2155- }
2156-
2157-out:
2158-
2159- if (success)
2160- g_string_free (accumulated_error, TRUE);
2161- else {
2162- char *str;
2163-
2164- str = g_string_free (accumulated_error, FALSE);
2165-
2166- if (tried_mode)
2167- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
2168- _("could not assign CRTCs to outputs:\n%s"),
2169- str);
2170- else
2171- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
2172- _("none of the selected modes were compatible with the possible modes:\n%s"),
2173- str);
2174-
2175- g_free (str);
2176- }
2177-
2178- return success;
2179-}
2180-
2181-static void
2182-crtc_info_free (CrtcInfo *info)
2183-{
2184- g_ptr_array_free (info->outputs, TRUE);
2185- g_free (info);
2186-}
2187-
2188-static void
2189-get_required_virtual_size (CrtcAssignment *assign, int *width, int *height)
2190-{
2191- GList *active_crtcs = g_hash_table_get_keys (assign->info);
2192- GList *list;
2193- int d;
2194-
2195- if (!width)
2196- width = &d;
2197- if (!height)
2198- height = &d;
2199-
2200- /* Compute size of the screen */
2201- *width = *height = 1;
2202- for (list = active_crtcs; list != NULL; list = list->next)
2203- {
2204- GnomeRRCrtc *crtc = list->data;
2205- CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
2206- int w, h;
2207-
2208- w = gnome_rr_mode_get_width (info->mode);
2209- h = gnome_rr_mode_get_height (info->mode);
2210-
2211- if (mode_is_rotated (info))
2212- {
2213- int tmp = h;
2214- h = w;
2215- w = tmp;
2216- }
2217-
2218- *width = MAX (*width, info->x + w);
2219- *height = MAX (*height, info->y + h);
2220- }
2221-
2222- g_list_free (active_crtcs);
2223-}
2224-
2225-static CrtcAssignment *
2226-crtc_assignment_new (GnomeRRScreen *screen, GnomeRROutputInfo **outputs, GError **error)
2227-{
2228- CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1);
2229-
2230- assignment->info = g_hash_table_new_full (
2231- g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free);
2232-
2233- if (real_assign_crtcs (screen, outputs, assignment, error))
2234- {
2235- int width, height;
2236- int min_width, max_width, min_height, max_height;
2237-
2238- get_required_virtual_size (assignment, &width, &height);
2239-
2240- gnome_rr_screen_get_ranges (
2241- screen, &min_width, &max_width, &min_height, &max_height);
2242-
2243- if (width < min_width || width > max_width ||
2244- height < min_height || height > max_height)
2245- {
2246- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
2247- /* Translators: the "requested", "minimum", and
2248- * "maximum" words here are not keywords; please
2249- * translate them as usual. */
2250- _("required virtual size does not fit available size: "
2251- "requested=(%d, %d), minimum=(%d, %d), maximum=(%d, %d)"),
2252- width, height,
2253- min_width, min_height,
2254- max_width, max_height);
2255- goto fail;
2256- }
2257-
2258- assignment->screen = screen;
2259-
2260- return assignment;
2261- }
2262-
2263-fail:
2264- crtc_assignment_free (assignment);
2265-
2266- return NULL;
2267-}
2268-
2269-static gboolean
2270-crtc_assignment_apply (CrtcAssignment *assign, guint32 timestamp, GError **error)
2271-{
2272- GnomeRRCrtc **all_crtcs = gnome_rr_screen_list_crtcs (assign->screen);
2273- int width, height;
2274- int i;
2275- int min_width, max_width, min_height, max_height;
2276- int width_mm, height_mm;
2277- gboolean success = TRUE;
2278-
2279- /* Compute size of the screen */
2280- get_required_virtual_size (assign, &width, &height);
2281-
2282- gnome_rr_screen_get_ranges (
2283- assign->screen, &min_width, &max_width, &min_height, &max_height);
2284-
2285- /* We should never get here if the dimensions don't fit in the virtual size,
2286- * but just in case we do, fix it up.
2287- */
2288- width = MAX (min_width, width);
2289- width = MIN (max_width, width);
2290- height = MAX (min_height, height);
2291- height = MIN (max_height, height);
2292-
2293- /* FMQ: do we need to check the sizes instead of clamping them? */
2294-
2295- /* Grab the server while we fiddle with the CRTCs and the screen, so that
2296- * apps that listen for RANDR notifications will only receive the final
2297- * status.
2298- */
2299-
2300- gdk_x11_display_grab (gdk_screen_get_display (assign->screen->priv->gdk_screen));
2301-
2302- /* Turn off all crtcs that are currently displaying outside the new screen,
2303- * or are not used in the new setup
2304- */
2305- for (i = 0; all_crtcs[i] != NULL; ++i)
2306- {
2307- GnomeRRCrtc *crtc = all_crtcs[i];
2308- GnomeRRMode *mode = gnome_rr_crtc_get_current_mode (crtc);
2309- int x, y;
2310-
2311- if (mode)
2312- {
2313- int w, h;
2314- gnome_rr_crtc_get_position (crtc, &x, &y);
2315-
2316- w = gnome_rr_mode_get_width (mode);
2317- h = gnome_rr_mode_get_height (mode);
2318-
2319- if (crtc_is_rotated (crtc))
2320- {
2321- int tmp = h;
2322- h = w;
2323- w = tmp;
2324- }
2325-
2326- if (x + w > width || y + h > height || !g_hash_table_lookup (assign->info, crtc))
2327- {
2328- if (!gnome_rr_crtc_set_config_with_time (crtc, timestamp, 0, 0, NULL, GNOME_RR_ROTATION_0, NULL, 0, error))
2329- {
2330- success = FALSE;
2331- break;
2332- }
2333-
2334- }
2335- }
2336- }
2337-
2338- /* The 'physical size' of an X screen is meaningless if that screen
2339- * can consist of many monitors. So just pick a size that make the
2340- * dpi 96.
2341- *
2342- * Firefox and Evince apparently believe what X tells them.
2343- */
2344- width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
2345- height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
2346-
2347- if (success)
2348- {
2349- ConfigureCrtcState state;
2350-
2351- gnome_rr_screen_set_size (assign->screen, width, height, width_mm, height_mm);
2352-
2353- state.timestamp = timestamp;
2354- state.has_error = FALSE;
2355- state.error = error;
2356-
2357- g_hash_table_foreach (assign->info, configure_crtc, &state);
2358-
2359- success = !state.has_error;
2360- }
2361-
2362- gnome_rr_screen_set_primary_output (assign->screen, assign->primary);
2363-
2364- gdk_x11_display_ungrab (gdk_screen_get_display (assign->screen->priv->gdk_screen));
2365-
2366- return success;
2367-}
2368
2369=== removed directory '.pc/04_compute_average_color.patch'
2370=== removed directory '.pc/04_compute_average_color.patch/libgnome-desktop'
2371=== removed file '.pc/04_compute_average_color.patch/libgnome-desktop/gnome-bg.c'
2372--- .pc/04_compute_average_color.patch/libgnome-desktop/gnome-bg.c 2013-05-28 09:10:46 +0000
2373+++ .pc/04_compute_average_color.patch/libgnome-desktop/gnome-bg.c 1970-01-01 00:00:00 +0000
2374@@ -1,2682 +0,0 @@
2375-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2376-
2377-gnomebg.c: Object for the desktop background.
2378-
2379-Copyright (C) 2000 Eazel, Inc.
2380-Copyright (C) 2007-2008 Red Hat, Inc.
2381-
2382-This program is free software; you can redistribute it and/or
2383-modify it under the terms of the GNU Library General Public License as
2384-published by the Free Software Foundation; either version 2 of the
2385-License, or (at your option) any later version.
2386-
2387-This program is distributed in the hope that it will be useful,
2388-but WITHOUT ANY WARRANTY; without even the implied warranty of
2389-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2390-Library General Public License for more details.
2391-
2392-You should have received a copy of the GNU Library General Public
2393-License along with this program; if not, write to the
2394-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2395-Boston, MA 02110-1301, USA.
2396-
2397-Derived from eel-background.c and eel-gdk-pixbuf-extensions.c by
2398-Darin Adler <darin@eazel.com> and Ramiro Estrugo <ramiro@eazel.com>
2399-
2400-Author: Soren Sandmann <sandmann@redhat.com>
2401-
2402-*/
2403-
2404-#include <string.h>
2405-#include <math.h>
2406-#include <stdarg.h>
2407-#include <stdlib.h>
2408-
2409-#include <glib/gstdio.h>
2410-#include <gio/gio.h>
2411-
2412-#include <gdk/gdkx.h>
2413-#include <X11/Xlib.h>
2414-#include <X11/Xatom.h>
2415-
2416-#include <cairo.h>
2417-#include <cairo-xlib.h>
2418-
2419-#define GNOME_DESKTOP_USE_UNSTABLE_API
2420-#include "gnome-bg.h"
2421-#include "gnome-bg-slide-show.h"
2422-#include "gnome-bg-crossfade.h"
2423-
2424-#define BG_KEY_PRIMARY_COLOR "primary-color"
2425-#define BG_KEY_SECONDARY_COLOR "secondary-color"
2426-#define BG_KEY_COLOR_TYPE "color-shading-type"
2427-#define BG_KEY_PICTURE_PLACEMENT "picture-options"
2428-#define BG_KEY_PICTURE_OPACITY "picture-opacity"
2429-#define BG_KEY_PICTURE_URI "picture-uri"
2430-
2431-/* We keep the large pixbufs around if the next update
2432- in the slideshow is less than 60 seconds away */
2433-#define KEEP_EXPENSIVE_CACHE_SECS 60
2434-
2435-/* This is the size of the GdkRGB dither matrix, in order to avoid
2436- * bad dithering when tiling the gradient
2437- */
2438-#define GRADIENT_PIXMAP_TILE_SIZE 128
2439-#define THUMBNAIL_SIZE 256
2440-
2441-typedef struct FileCacheEntry FileCacheEntry;
2442-#define CACHE_SIZE 4
2443-
2444-/*
2445- * Implementation of the GnomeBG class
2446- */
2447-struct _GnomeBG
2448-{
2449- GObject parent_instance;
2450- char * filename;
2451- GDesktopBackgroundStyle placement;
2452- GDesktopBackgroundShading color_type;
2453- GdkColor primary;
2454- GdkColor secondary;
2455-
2456- GFileMonitor * file_monitor;
2457-
2458- guint changed_id;
2459- guint transitioned_id;
2460- guint blow_caches_id;
2461-
2462- /* Cached information, only access through cache accessor functions */
2463- GnomeBGSlideShow * slideshow;
2464- time_t file_mtime;
2465- GdkPixbuf * pixbuf_cache;
2466- int timeout_id;
2467-
2468- GList * file_cache;
2469-};
2470-
2471-struct _GnomeBGClass
2472-{
2473- GObjectClass parent_class;
2474-};
2475-
2476-enum {
2477- CHANGED,
2478- TRANSITIONED,
2479- N_SIGNALS
2480-};
2481-
2482-static const cairo_user_data_key_t average_color_key;
2483-
2484-static guint signals[N_SIGNALS] = { 0 };
2485-
2486-G_DEFINE_TYPE (GnomeBG, gnome_bg, G_TYPE_OBJECT)
2487-
2488-static cairo_surface_t *make_root_pixmap (GdkScreen *screen,
2489- gint width,
2490- gint height);
2491-
2492-/* Pixbuf utils */
2493-static void pixbuf_average_value (GdkPixbuf *pixbuf,
2494- GdkRGBA *result);
2495-static GdkPixbuf *pixbuf_scale_to_fit (GdkPixbuf *src,
2496- int max_width,
2497- int max_height);
2498-static GdkPixbuf *pixbuf_scale_to_min (GdkPixbuf *src,
2499- int min_width,
2500- int min_height);
2501-static void pixbuf_draw_gradient (GdkPixbuf *pixbuf,
2502- gboolean horizontal,
2503- GdkColor *c1,
2504- GdkColor *c2,
2505- GdkRectangle *rect);
2506-static void pixbuf_tile (GdkPixbuf *src,
2507- GdkPixbuf *dest);
2508-static void pixbuf_blend (GdkPixbuf *src,
2509- GdkPixbuf *dest,
2510- int src_x,
2511- int src_y,
2512- int width,
2513- int height,
2514- int dest_x,
2515- int dest_y,
2516- double alpha);
2517-
2518-/* Thumbnail utilities */
2519-static GdkPixbuf *create_thumbnail_for_filename (GnomeDesktopThumbnailFactory *factory,
2520- const char *filename);
2521-static gboolean get_thumb_annotations (GdkPixbuf *thumb,
2522- int *orig_width,
2523- int *orig_height);
2524-
2525-/* Cache */
2526-static GdkPixbuf *get_pixbuf_for_size (GnomeBG *bg,
2527- gint num_monitor,
2528- int width,
2529- int height);
2530-static void clear_cache (GnomeBG *bg);
2531-static gboolean is_different (GnomeBG *bg,
2532- const char *filename);
2533-static time_t get_mtime (const char *filename);
2534-static GdkPixbuf *create_img_thumbnail (GnomeBG *bg,
2535- GnomeDesktopThumbnailFactory *factory,
2536- GdkScreen *screen,
2537- int dest_width,
2538- int dest_height,
2539- int frame_num);
2540-static GnomeBGSlideShow * get_as_slideshow (GnomeBG *bg,
2541- const char *filename);
2542-static GnomeBGSlideShow *read_slideshow_file (const char *filename,
2543- GError **err);
2544-
2545-static void
2546-color_from_string (const char *string,
2547- GdkColor *colorp)
2548-{
2549- /* If all else fails use black */
2550- gdk_color_parse ("black", colorp);
2551-
2552- if (!string)
2553- return;
2554-
2555- gdk_color_parse (string, colorp);
2556-}
2557-
2558-static char *
2559-color_to_string (const GdkColor *color)
2560-{
2561- return g_strdup_printf ("#%02x%02x%02x",
2562- color->red >> 8,
2563- color->green >> 8,
2564- color->blue >> 8);
2565-}
2566-
2567-static gboolean
2568-do_changed (GnomeBG *bg)
2569-{
2570- gboolean ignore_pending_change;
2571- bg->changed_id = 0;
2572-
2573- ignore_pending_change =
2574- GPOINTER_TO_INT (g_object_get_data (G_OBJECT (bg),
2575- "ignore-pending-change"));
2576-
2577- if (!ignore_pending_change) {
2578- g_signal_emit (G_OBJECT (bg), signals[CHANGED], 0);
2579- }
2580-
2581- return FALSE;
2582-}
2583-
2584-static void
2585-queue_changed (GnomeBG *bg)
2586-{
2587- if (bg->changed_id > 0) {
2588- g_source_remove (bg->changed_id);
2589- }
2590-
2591- /* We unset this here to allow apps to set it if they don't want
2592- to get the change event. This is used by nautilus when it
2593- gets the pixmap from the bg (due to a reason other than the changed
2594- event). Because if there is no other change after this time the
2595- pending changed event will just uselessly cause us to recreate
2596- the pixmap. */
2597- g_object_set_data (G_OBJECT (bg), "ignore-pending-change",
2598- GINT_TO_POINTER (FALSE));
2599- bg->changed_id = g_timeout_add_full (G_PRIORITY_LOW,
2600- 100,
2601- (GSourceFunc)do_changed,
2602- bg,
2603- NULL);
2604-}
2605-
2606-static gboolean
2607-do_transitioned (GnomeBG *bg)
2608-{
2609- bg->transitioned_id = 0;
2610-
2611- if (bg->pixbuf_cache) {
2612- g_object_unref (bg->pixbuf_cache);
2613- bg->pixbuf_cache = NULL;
2614- }
2615-
2616- g_signal_emit (G_OBJECT (bg), signals[TRANSITIONED], 0);
2617-
2618- return FALSE;
2619-}
2620-
2621-static void
2622-queue_transitioned (GnomeBG *bg)
2623-{
2624- if (bg->transitioned_id > 0) {
2625- g_source_remove (bg->transitioned_id);
2626- }
2627-
2628- bg->transitioned_id = g_timeout_add_full (G_PRIORITY_LOW,
2629- 100,
2630- (GSourceFunc)do_transitioned,
2631- bg,
2632- NULL);
2633-}
2634-
2635-static gboolean
2636-bg_gsettings_mapping (GVariant *value,
2637- gpointer *result,
2638- gpointer user_data)
2639-{
2640- const gchar *bg_key_value;
2641- char *filename = NULL;
2642-
2643- /* The final fallback if nothing matches is with a NULL value. */
2644- if (value == NULL) {
2645- *result = NULL;
2646- return TRUE;
2647- }
2648-
2649- bg_key_value = g_variant_get_string (value, NULL);
2650-
2651- if (bg_key_value && *bg_key_value != '\0') {
2652- filename = g_filename_from_uri (bg_key_value, NULL, NULL);
2653-
2654- if (filename != NULL && g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE) {
2655- g_free (filename);
2656- return FALSE;
2657- }
2658-
2659- if (filename != NULL) {
2660- *result = filename;
2661- return TRUE;
2662- }
2663- }
2664-
2665- return FALSE;
2666-}
2667-
2668-void
2669-gnome_bg_load_from_preferences (GnomeBG *bg,
2670- GSettings *settings)
2671-{
2672- char *tmp;
2673- char *filename;
2674- GDesktopBackgroundShading ctype;
2675- GdkColor c1, c2;
2676- GDesktopBackgroundStyle placement;
2677-
2678- g_return_if_fail (GNOME_IS_BG (bg));
2679- g_return_if_fail (G_IS_SETTINGS (settings));
2680-
2681- /* Filename */
2682- filename = g_settings_get_mapped (settings, BG_KEY_PICTURE_URI, bg_gsettings_mapping, NULL);
2683-
2684- /* Colors */
2685- tmp = g_settings_get_string (settings, BG_KEY_PRIMARY_COLOR);
2686- color_from_string (tmp, &c1);
2687- g_free (tmp);
2688-
2689- tmp = g_settings_get_string (settings, BG_KEY_SECONDARY_COLOR);
2690- color_from_string (tmp, &c2);
2691- g_free (tmp);
2692-
2693- /* Color type */
2694- ctype = g_settings_get_enum (settings, BG_KEY_COLOR_TYPE);
2695-
2696- /* Placement */
2697- placement = g_settings_get_enum (settings, BG_KEY_PICTURE_PLACEMENT);
2698-
2699- gnome_bg_set_color (bg, ctype, &c1, &c2);
2700- gnome_bg_set_placement (bg, placement);
2701- gnome_bg_set_filename (bg, filename);
2702-
2703- g_free (filename);
2704-}
2705-
2706-void
2707-gnome_bg_save_to_preferences (GnomeBG *bg,
2708- GSettings *settings)
2709-{
2710- gchar *primary;
2711- gchar *secondary;
2712- gchar *uri;
2713-
2714- g_return_if_fail (GNOME_IS_BG (bg));
2715- g_return_if_fail (G_IS_SETTINGS (settings));
2716-
2717- primary = color_to_string (&bg->primary);
2718- secondary = color_to_string (&bg->secondary);
2719-
2720- g_settings_delay (settings);
2721-
2722- uri = NULL;
2723- if (bg->filename != NULL)
2724- uri = g_filename_to_uri (bg->filename, NULL, NULL);
2725- if (uri == NULL)
2726- uri = g_strdup ("");
2727- g_settings_set_string (settings, BG_KEY_PICTURE_URI, uri);
2728- g_settings_set_string (settings, BG_KEY_PRIMARY_COLOR, primary);
2729- g_settings_set_string (settings, BG_KEY_SECONDARY_COLOR, secondary);
2730- g_settings_set_enum (settings, BG_KEY_COLOR_TYPE, bg->color_type);
2731- g_settings_set_enum (settings, BG_KEY_PICTURE_PLACEMENT, bg->placement);
2732-
2733- /* Apply changes atomically. */
2734- g_settings_apply (settings);
2735-
2736- g_free (primary);
2737- g_free (secondary);
2738- g_free (uri);
2739-}
2740-
2741-
2742-static void
2743-gnome_bg_init (GnomeBG *bg)
2744-{
2745-}
2746-
2747-static void
2748-gnome_bg_dispose (GObject *object)
2749-{
2750- GnomeBG *bg = GNOME_BG (object);
2751-
2752- if (bg->file_monitor) {
2753- g_object_unref (bg->file_monitor);
2754- bg->file_monitor = NULL;
2755- }
2756-
2757- clear_cache (bg);
2758-
2759- G_OBJECT_CLASS (gnome_bg_parent_class)->dispose (object);
2760-}
2761-
2762-static void
2763-gnome_bg_finalize (GObject *object)
2764-{
2765- GnomeBG *bg = GNOME_BG (object);
2766-
2767- if (bg->changed_id != 0) {
2768- g_source_remove (bg->changed_id);
2769- bg->changed_id = 0;
2770- }
2771-
2772- if (bg->transitioned_id != 0) {
2773- g_source_remove (bg->transitioned_id);
2774- bg->transitioned_id = 0;
2775- }
2776-
2777- if (bg->blow_caches_id != 0) {
2778- g_source_remove (bg->blow_caches_id);
2779- bg->blow_caches_id = 0;
2780- }
2781-
2782- g_free (bg->filename);
2783- bg->filename = NULL;
2784-
2785- G_OBJECT_CLASS (gnome_bg_parent_class)->finalize (object);
2786-}
2787-
2788-static void
2789-gnome_bg_class_init (GnomeBGClass *klass)
2790-{
2791- GObjectClass *object_class = G_OBJECT_CLASS (klass);
2792-
2793- object_class->dispose = gnome_bg_dispose;
2794- object_class->finalize = gnome_bg_finalize;
2795-
2796- signals[CHANGED] = g_signal_new ("changed",
2797- G_OBJECT_CLASS_TYPE (object_class),
2798- G_SIGNAL_RUN_LAST,
2799- 0,
2800- NULL, NULL,
2801- g_cclosure_marshal_VOID__VOID,
2802- G_TYPE_NONE, 0);
2803-
2804- signals[TRANSITIONED] = g_signal_new ("transitioned",
2805- G_OBJECT_CLASS_TYPE (object_class),
2806- G_SIGNAL_RUN_LAST,
2807- 0,
2808- NULL, NULL,
2809- g_cclosure_marshal_VOID__VOID,
2810- G_TYPE_NONE, 0);
2811-}
2812-
2813-GnomeBG *
2814-gnome_bg_new (void)
2815-{
2816- return g_object_new (GNOME_TYPE_BG, NULL);
2817-}
2818-
2819-void
2820-gnome_bg_set_color (GnomeBG *bg,
2821- GDesktopBackgroundShading type,
2822- GdkColor *primary,
2823- GdkColor *secondary)
2824-{
2825- g_return_if_fail (bg != NULL);
2826- g_return_if_fail (primary != NULL);
2827-
2828- if (bg->color_type != type ||
2829- !gdk_color_equal (&bg->primary, primary) ||
2830- (secondary && !gdk_color_equal (&bg->secondary, secondary))) {
2831-
2832- bg->color_type = type;
2833- bg->primary = *primary;
2834- if (secondary) {
2835- bg->secondary = *secondary;
2836- }
2837-
2838- queue_changed (bg);
2839- }
2840-}
2841-
2842-void
2843-gnome_bg_set_placement (GnomeBG *bg,
2844- GDesktopBackgroundStyle placement)
2845-{
2846- g_return_if_fail (bg != NULL);
2847-
2848- if (bg->placement != placement) {
2849- bg->placement = placement;
2850-
2851- queue_changed (bg);
2852- }
2853-}
2854-
2855-GDesktopBackgroundStyle
2856-gnome_bg_get_placement (GnomeBG *bg)
2857-{
2858- g_return_val_if_fail (bg != NULL, -1);
2859-
2860- return bg->placement;
2861-}
2862-
2863-void
2864-gnome_bg_get_color (GnomeBG *bg,
2865- GDesktopBackgroundShading *type,
2866- GdkColor *primary,
2867- GdkColor *secondary)
2868-{
2869- g_return_if_fail (bg != NULL);
2870-
2871- if (type)
2872- *type = bg->color_type;
2873-
2874- if (primary)
2875- *primary = bg->primary;
2876-
2877- if (secondary)
2878- *secondary = bg->secondary;
2879-}
2880-
2881-const gchar *
2882-gnome_bg_get_filename (GnomeBG *bg)
2883-{
2884- g_return_val_if_fail (bg != NULL, NULL);
2885-
2886- return bg->filename;
2887-}
2888-
2889-static inline gchar *
2890-get_wallpaper_cache_dir (void)
2891-{
2892- return g_build_filename (g_get_user_cache_dir(), "wallpaper", NULL);
2893-}
2894-
2895-static inline gchar *
2896-get_wallpaper_cache_prefix_name (gint num_monitor,
2897- GDesktopBackgroundStyle placement,
2898- gint width,
2899- gint height)
2900-{
2901- return g_strdup_printf ("%i_%i_%i_%i", num_monitor, (gint) placement, width, height);
2902-}
2903-
2904-static char *
2905-get_wallpaper_cache_filename (const char *filename,
2906- gint num_monitor,
2907- GDesktopBackgroundStyle placement,
2908- gint width,
2909- gint height)
2910-{
2911- gchar *cache_filename;
2912- gchar *cache_prefix_name;
2913- gchar *md5_filename;
2914- gchar *cache_basename;
2915- gchar *cache_dir;
2916-
2917- md5_filename = g_compute_checksum_for_data (G_CHECKSUM_MD5, (const guchar *) filename, strlen (filename));
2918- cache_prefix_name = get_wallpaper_cache_prefix_name (num_monitor, placement, width, height);
2919- cache_basename = g_strdup_printf ("%s_%s", cache_prefix_name, md5_filename);
2920- cache_dir = get_wallpaper_cache_dir ();
2921- cache_filename = g_build_filename (cache_dir, cache_basename, NULL);
2922-
2923- g_free (cache_prefix_name);
2924- g_free (md5_filename);
2925- g_free (cache_basename);
2926- g_free (cache_dir);
2927-
2928- return cache_filename;
2929-}
2930-
2931-static void
2932-cleanup_cache_for_monitor (gchar *cache_dir,
2933- gint num_monitor)
2934-{
2935- GDir *g_cache_dir;
2936- gchar *monitor_prefix;
2937- const gchar *file;
2938-
2939- g_cache_dir = g_dir_open (cache_dir, 0, NULL);
2940- monitor_prefix = g_strdup_printf ("%i_", num_monitor);
2941-
2942- file = g_dir_read_name (g_cache_dir);
2943- while (file != NULL) {
2944- gchar *path;
2945-
2946- path = g_build_filename (cache_dir, file, NULL);
2947- /* purge files with same monitor id */
2948- if (g_str_has_prefix (file, monitor_prefix) &&
2949- g_file_test (path, G_FILE_TEST_IS_REGULAR))
2950- g_unlink (path);
2951-
2952- g_free (path);
2953-
2954- file = g_dir_read_name (g_cache_dir);
2955- }
2956-
2957- g_free (monitor_prefix);
2958- g_dir_close (g_cache_dir);
2959-}
2960-
2961-static gboolean
2962-cache_file_is_valid (const char *filename,
2963- const char *cache_filename)
2964-{
2965- time_t mtime;
2966- time_t cache_mtime;
2967-
2968- if (!g_file_test (cache_filename, G_FILE_TEST_IS_REGULAR))
2969- return FALSE;
2970-
2971- mtime = get_mtime (filename);
2972- cache_mtime = get_mtime (cache_filename);
2973-
2974- return (mtime < cache_mtime);
2975-}
2976-
2977-static void
2978-refresh_cache_file (GnomeBG *bg,
2979- GdkPixbuf *new_pixbuf,
2980- gint num_monitor,
2981- gint width,
2982- gint height)
2983-{
2984- gchar *cache_filename;
2985- gchar *cache_dir;
2986- GdkPixbufFormat *format;
2987- gchar *format_name;
2988-
2989- if ((num_monitor == -1) || (width <= 300) || (height <= 300))
2990- return;
2991-
2992- cache_filename = get_wallpaper_cache_filename (bg->filename, num_monitor, bg->placement, width, height);
2993- cache_dir = get_wallpaper_cache_dir ();
2994-
2995- /* Only refresh scaled file on disk if useful (and don't cache slideshow) */
2996- if (!cache_file_is_valid (bg->filename, cache_filename)) {
2997- format = gdk_pixbuf_get_file_info (bg->filename, NULL, NULL);
2998-
2999- if (format != NULL) {
3000- if (!g_file_test (cache_dir, G_FILE_TEST_IS_DIR)) {
3001- g_mkdir_with_parents (cache_dir, 0700);
3002- } else {
3003- cleanup_cache_for_monitor (cache_dir, num_monitor);
3004- }
3005-
3006- format_name = gdk_pixbuf_format_get_name (format);
3007-
3008- if (strcmp (format_name, "jpeg") == 0)
3009- gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, "quality", "100", NULL);
3010- else
3011- gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, NULL);
3012-
3013- g_free (format_name);
3014- }
3015- }
3016-
3017- g_free (cache_filename);
3018- g_free (cache_dir);
3019-}
3020-
3021-static void
3022-file_changed (GFileMonitor *file_monitor,
3023- GFile *child,
3024- GFile *other_file,
3025- GFileMonitorEvent event_type,
3026- gpointer user_data)
3027-{
3028- GnomeBG *bg = GNOME_BG (user_data);
3029-
3030- clear_cache (bg);
3031- queue_changed (bg);
3032-}
3033-
3034-void
3035-gnome_bg_set_filename (GnomeBG *bg,
3036- const char *filename)
3037-{
3038- g_return_if_fail (bg != NULL);
3039-
3040- if (is_different (bg, filename)) {
3041- g_free (bg->filename);
3042-
3043- bg->filename = g_strdup (filename);
3044- bg->file_mtime = get_mtime (bg->filename);
3045-
3046- if (bg->file_monitor) {
3047- g_object_unref (bg->file_monitor);
3048- bg->file_monitor = NULL;
3049- }
3050-
3051- if (bg->filename) {
3052- GFile *f = g_file_new_for_path (bg->filename);
3053-
3054- bg->file_monitor = g_file_monitor_file (f, 0, NULL, NULL);
3055- g_signal_connect (bg->file_monitor, "changed",
3056- G_CALLBACK (file_changed), bg);
3057-
3058- g_object_unref (f);
3059- }
3060-
3061- clear_cache (bg);
3062-
3063- queue_changed (bg);
3064- }
3065-}
3066-
3067-static void
3068-draw_color_area (GnomeBG *bg,
3069- GdkPixbuf *dest,
3070- GdkRectangle *rect)
3071-{
3072- guint32 pixel;
3073- GdkRectangle extent;
3074-
3075- extent.x = 0;
3076- extent.y = 0;
3077- extent.width = gdk_pixbuf_get_width (dest);
3078- extent.height = gdk_pixbuf_get_height (dest);
3079-
3080- gdk_rectangle_intersect (rect, &extent, rect);
3081-
3082- switch (bg->color_type) {
3083- case G_DESKTOP_BACKGROUND_SHADING_SOLID:
3084- /* not really a big deal to ignore the area of interest */
3085- pixel = ((bg->primary.red >> 8) << 24) |
3086- ((bg->primary.green >> 8) << 16) |
3087- ((bg->primary.blue >> 8) << 8) |
3088- (0xff);
3089-
3090- gdk_pixbuf_fill (dest, pixel);
3091- break;
3092-
3093- case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL:
3094- pixbuf_draw_gradient (dest, TRUE, &(bg->primary), &(bg->secondary), rect);
3095- break;
3096-
3097- case G_DESKTOP_BACKGROUND_SHADING_VERTICAL:
3098- pixbuf_draw_gradient (dest, FALSE, &(bg->primary), &(bg->secondary), rect);
3099- break;
3100-
3101- default:
3102- break;
3103- }
3104-}
3105-
3106-static void
3107-draw_color (GnomeBG *bg,
3108- GdkPixbuf *dest)
3109-{
3110- GdkRectangle rect;
3111- rect.x = 0;
3112- rect.y = 0;
3113- rect.width = gdk_pixbuf_get_width (dest);
3114- rect.height = gdk_pixbuf_get_height (dest);
3115- draw_color_area (bg, dest, &rect);
3116-}
3117-
3118-static void
3119-draw_color_each_monitor (GnomeBG *bg,
3120- GdkPixbuf *dest,
3121- GdkScreen *screen)
3122-{
3123- GdkRectangle rect;
3124- gint num_monitors;
3125- int monitor;
3126-
3127- num_monitors = gdk_screen_get_n_monitors (screen);
3128- for (monitor = 0; monitor < num_monitors; monitor++) {
3129- gdk_screen_get_monitor_geometry (screen, monitor, &rect);
3130- draw_color_area (bg, dest, &rect);
3131- }
3132-}
3133-
3134-static GdkPixbuf *
3135-pixbuf_clip_to_fit (GdkPixbuf *src,
3136- int max_width,
3137- int max_height)
3138-{
3139- int src_width, src_height;
3140- int w, h;
3141- int src_x, src_y;
3142- GdkPixbuf *pixbuf;
3143-
3144- src_width = gdk_pixbuf_get_width (src);
3145- src_height = gdk_pixbuf_get_height (src);
3146-
3147- if (src_width < max_width && src_height < max_height)
3148- return g_object_ref (src);
3149-
3150- w = MIN(src_width, max_width);
3151- h = MIN(src_height, max_height);
3152-
3153- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
3154- gdk_pixbuf_get_has_alpha (src),
3155- 8, w, h);
3156-
3157- src_x = (src_width - w) / 2;
3158- src_y = (src_height - h) / 2;
3159- gdk_pixbuf_copy_area (src,
3160- src_x, src_y,
3161- w, h,
3162- pixbuf,
3163- 0, 0);
3164- return pixbuf;
3165-}
3166-
3167-static GdkPixbuf *
3168-get_scaled_pixbuf (GDesktopBackgroundStyle placement,
3169- GdkPixbuf *pixbuf,
3170- int width, int height,
3171- int *x, int *y,
3172- int *w, int *h)
3173-{
3174- GdkPixbuf *new;
3175-
3176-#if 0
3177- g_print ("original_width: %d %d\n",
3178- gdk_pixbuf_get_width (pixbuf),
3179- gdk_pixbuf_get_height (pixbuf));
3180-#endif
3181-
3182- switch (placement) {
3183- case G_DESKTOP_BACKGROUND_STYLE_SPANNED:
3184- new = pixbuf_scale_to_fit (pixbuf, width, height);
3185- break;
3186- case G_DESKTOP_BACKGROUND_STYLE_ZOOM:
3187- new = pixbuf_scale_to_min (pixbuf, width, height);
3188- break;
3189-
3190- case G_DESKTOP_BACKGROUND_STYLE_STRETCHED:
3191- new = gdk_pixbuf_scale_simple (pixbuf, width, height,
3192- GDK_INTERP_BILINEAR);
3193- break;
3194-
3195- case G_DESKTOP_BACKGROUND_STYLE_SCALED:
3196- new = pixbuf_scale_to_fit (pixbuf, width, height);
3197- break;
3198-
3199- case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
3200- case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER:
3201- default:
3202- new = pixbuf_clip_to_fit (pixbuf, width, height);
3203- break;
3204- }
3205-
3206- *w = gdk_pixbuf_get_width (new);
3207- *h = gdk_pixbuf_get_height (new);
3208- *x = (width - *w) / 2;
3209- *y = (height - *h) / 2;
3210-
3211- return new;
3212-}
3213-
3214-static void
3215-draw_image_area (GnomeBG *bg,
3216- gint num_monitor,
3217- GdkPixbuf *pixbuf,
3218- GdkPixbuf *dest,
3219- GdkRectangle *area)
3220-{
3221- int dest_width = area->width;
3222- int dest_height = area->height;
3223- int x, y, w, h;
3224- GdkPixbuf *scaled;
3225-
3226- if (!pixbuf)
3227- return;
3228-
3229- scaled = get_scaled_pixbuf (bg->placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
3230-
3231- switch (bg->placement) {
3232- case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER:
3233- pixbuf_tile (scaled, dest);
3234- break;
3235- case G_DESKTOP_BACKGROUND_STYLE_ZOOM:
3236- case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
3237- case G_DESKTOP_BACKGROUND_STYLE_STRETCHED:
3238- case G_DESKTOP_BACKGROUND_STYLE_SCALED:
3239- pixbuf_blend (scaled, dest, 0, 0, w, h, x + area->x, y + area->y, 1.0);
3240- break;
3241- case G_DESKTOP_BACKGROUND_STYLE_SPANNED:
3242- pixbuf_blend (scaled, dest, 0, 0, w, h, x, y, 1.0);
3243- break;
3244- default:
3245- g_assert_not_reached ();
3246- break;
3247- }
3248-
3249- refresh_cache_file (bg, scaled, num_monitor, dest_width, dest_height);
3250-
3251- g_object_unref (scaled);
3252-}
3253-
3254-static void
3255-draw_image_for_thumb (GnomeBG *bg,
3256- GdkPixbuf *pixbuf,
3257- GdkPixbuf *dest)
3258-{
3259- GdkRectangle rect;
3260-
3261- rect.x = 0;
3262- rect.y = 0;
3263- rect.width = gdk_pixbuf_get_width (dest);
3264- rect.height = gdk_pixbuf_get_height (dest);
3265-
3266- draw_image_area (bg, -1, pixbuf, dest, &rect);
3267-}
3268-
3269-static void
3270-draw_once (GnomeBG *bg,
3271- GdkPixbuf *dest)
3272-{
3273- GdkRectangle rect;
3274- GdkPixbuf *pixbuf;
3275- gint num_monitor;
3276-
3277- /* we just draw on the whole screen */
3278- num_monitor = 0;
3279-
3280- rect.x = 0;
3281- rect.y = 0;
3282- rect.width = gdk_pixbuf_get_width (dest);
3283- rect.height = gdk_pixbuf_get_height (dest);
3284-
3285- pixbuf = get_pixbuf_for_size (bg, num_monitor, rect.width, rect.height);
3286- if (pixbuf) {
3287- draw_image_area (bg,
3288- num_monitor,
3289- pixbuf,
3290- dest,
3291- &rect);
3292- g_object_unref (pixbuf);
3293- }
3294-}
3295-
3296-static void
3297-draw_each_monitor (GnomeBG *bg,
3298- GdkPixbuf *dest,
3299- GdkScreen *screen)
3300-{
3301- GdkRectangle rect;
3302- gint num_monitors;
3303- int monitor;
3304-
3305- num_monitors = gdk_screen_get_n_monitors (screen);
3306- for (monitor = 0; monitor < num_monitors; monitor++) {
3307- GdkPixbuf *pixbuf;
3308- gdk_screen_get_monitor_geometry (screen, monitor, &rect);
3309- pixbuf = get_pixbuf_for_size (bg, monitor, rect.width, rect.height);
3310- if (pixbuf) {
3311- draw_image_area (bg,
3312- monitor,
3313- pixbuf,
3314- dest, &rect);
3315- g_object_unref (pixbuf);
3316- }
3317- }
3318-}
3319-
3320-void
3321-gnome_bg_draw (GnomeBG *bg,
3322- GdkPixbuf *dest,
3323- GdkScreen *screen,
3324- gboolean is_root)
3325-{
3326- if (!bg)
3327- return;
3328-
3329- if (is_root && (bg->placement != G_DESKTOP_BACKGROUND_STYLE_SPANNED)) {
3330- draw_color_each_monitor (bg, dest, screen);
3331- if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) {
3332- draw_each_monitor (bg, dest, screen);
3333- }
3334- } else {
3335- draw_color (bg, dest);
3336- if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) {
3337- draw_once (bg, dest);
3338- }
3339- }
3340-}
3341-
3342-gboolean
3343-gnome_bg_has_multiple_sizes (GnomeBG *bg)
3344-{
3345- GnomeBGSlideShow *show;
3346- gboolean ret;
3347-
3348- g_return_val_if_fail (bg != NULL, FALSE);
3349-
3350- ret = FALSE;
3351-
3352- show = get_as_slideshow (bg, bg->filename);
3353- if (show) {
3354- ret = gnome_bg_slide_show_get_has_multiple_sizes (show);
3355- g_object_unref (show);
3356- }
3357-
3358- return ret;
3359-}
3360-
3361-static void
3362-gnome_bg_get_pixmap_size (GnomeBG *bg,
3363- int width,
3364- int height,
3365- int *pixmap_width,
3366- int *pixmap_height)
3367-{
3368- int dummy;
3369-
3370- if (!pixmap_width)
3371- pixmap_width = &dummy;
3372- if (!pixmap_height)
3373- pixmap_height = &dummy;
3374-
3375- *pixmap_width = width;
3376- *pixmap_height = height;
3377-
3378- if (!bg->filename) {
3379- switch (bg->color_type) {
3380- case G_DESKTOP_BACKGROUND_SHADING_SOLID:
3381- *pixmap_width = 1;
3382- *pixmap_height = 1;
3383- break;
3384-
3385- case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL:
3386- case G_DESKTOP_BACKGROUND_SHADING_VERTICAL:
3387- break;
3388- }
3389-
3390- return;
3391- }
3392-}
3393-
3394-/**
3395- * gnome_bg_create_surface:
3396- * @bg: GnomeBG
3397- * @window:
3398- * @width:
3399- * @height:
3400- * @root:
3401- *
3402- * Create a surface that can be set as background for @window. If @is_root is
3403- * TRUE, the surface created will be created by a temporary X server connection
3404- * so that if someone calls XKillClient on it, it won't affect the application
3405- * who created it.
3406- *
3407- * Returns: %NULL on error (e.g. out of X connections)
3408- **/
3409-cairo_surface_t *
3410-gnome_bg_create_surface (GnomeBG *bg,
3411- GdkWindow *window,
3412- int width,
3413- int height,
3414- gboolean root)
3415-{
3416- int pm_width, pm_height;
3417- cairo_surface_t *surface;
3418- GdkRGBA average;
3419- cairo_t *cr;
3420-
3421- g_return_val_if_fail (bg != NULL, NULL);
3422- g_return_val_if_fail (window != NULL, NULL);
3423-
3424- if (bg->pixbuf_cache &&
3425- gdk_pixbuf_get_width (bg->pixbuf_cache) != width &&
3426- gdk_pixbuf_get_height (bg->pixbuf_cache) != height) {
3427- g_object_unref (bg->pixbuf_cache);
3428- bg->pixbuf_cache = NULL;
3429- }
3430-
3431- /* has the side effect of loading and caching pixbuf only when in tile mode */
3432- gnome_bg_get_pixmap_size (bg, width, height, &pm_width, &pm_height);
3433-
3434- if (root) {
3435- surface = make_root_pixmap (gdk_window_get_screen (window),
3436- pm_width, pm_height);
3437- }
3438- else {
3439- surface = gdk_window_create_similar_surface (window,
3440- CAIRO_CONTENT_COLOR,
3441- pm_width, pm_height);
3442- }
3443-
3444- if (surface == NULL)
3445- return NULL;
3446-
3447- cr = cairo_create (surface);
3448- if (!bg->filename && bg->color_type == G_DESKTOP_BACKGROUND_SHADING_SOLID) {
3449- gdk_cairo_set_source_color (cr, &(bg->primary));
3450- average.red = bg->primary.red / 65535.0;
3451- average.green = bg->primary.green / 65535.0;
3452- average.blue = bg->primary.blue / 65535.0;
3453- average.alpha = 1.0;
3454- }
3455- else {
3456- GdkPixbuf *pixbuf;
3457-
3458- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
3459- width, height);
3460- gnome_bg_draw (bg, pixbuf, gdk_window_get_screen (window), root);
3461- gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
3462- pixbuf_average_value (pixbuf, &average);
3463- g_object_unref (pixbuf);
3464- }
3465-
3466- cairo_paint (cr);
3467-
3468- cairo_destroy (cr);
3469-
3470- cairo_surface_set_user_data (surface, &average_color_key,
3471- gdk_rgba_copy (&average),
3472- (cairo_destroy_func_t) gdk_rgba_free);
3473-
3474- return surface;
3475-}
3476-
3477-
3478-/* determine if a background is darker or lighter than average, to help
3479- * clients know what colors to draw on top with
3480- */
3481-gboolean
3482-gnome_bg_is_dark (GnomeBG *bg,
3483- int width,
3484- int height)
3485-{
3486- GdkColor color;
3487- int intensity;
3488- GdkPixbuf *pixbuf;
3489-
3490- g_return_val_if_fail (bg != NULL, FALSE);
3491-
3492- if (bg->color_type == G_DESKTOP_BACKGROUND_SHADING_SOLID) {
3493- color = bg->primary;
3494- } else {
3495- color.red = (bg->primary.red + bg->secondary.red) / 2;
3496- color.green = (bg->primary.green + bg->secondary.green) / 2;
3497- color.blue = (bg->primary.blue + bg->secondary.blue) / 2;
3498- }
3499- pixbuf = get_pixbuf_for_size (bg, -1, width, height);
3500- if (pixbuf) {
3501- GdkRGBA argb;
3502- guchar a, r, g, b;
3503-
3504- pixbuf_average_value (pixbuf, &argb);
3505- a = argb.alpha * 0xff;
3506- r = argb.red * 0xff;
3507- g = argb.green * 0xff;
3508- b = argb.blue * 0xff;
3509-
3510- color.red = (color.red * (0xFF - a) + r * 0x101 * a) / 0xFF;
3511- color.green = (color.green * (0xFF - a) + g * 0x101 * a) / 0xFF;
3512- color.blue = (color.blue * (0xFF - a) + b * 0x101 * a) / 0xFF;
3513- g_object_unref (pixbuf);
3514- }
3515-
3516- intensity = (color.red * 77 +
3517- color.green * 150 +
3518- color.blue * 28) >> 16;
3519-
3520- return intensity < 160; /* biased slightly to be dark */
3521-}
3522-
3523-/*
3524- * Create a persistent pixmap. We create a separate display
3525- * and set the closedown mode on it to RetainPermanent.
3526- */
3527-static cairo_surface_t *
3528-make_root_pixmap (GdkScreen *screen, gint width, gint height)
3529-{
3530- Display *display;
3531- const char *display_name;
3532- Pixmap result;
3533- cairo_surface_t *surface;
3534- int screen_num;
3535- int depth;
3536-
3537- screen_num = gdk_screen_get_number (screen);
3538-
3539- gdk_flush ();
3540-
3541- display_name = gdk_display_get_name (gdk_screen_get_display (screen));
3542- display = XOpenDisplay (display_name);
3543-
3544- if (display == NULL) {
3545- g_warning ("Unable to open display '%s' when setting "
3546- "background pixmap\n",
3547- (display_name) ? display_name : "NULL");
3548- return NULL;
3549- }
3550-
3551- /* Desktop background pixmap should be created from
3552- * dummy X client since most applications will try to
3553- * kill it with XKillClient later when changing pixmap
3554- */
3555-
3556- XSetCloseDownMode (display, RetainPermanent);
3557-
3558- depth = DefaultDepth (display, screen_num);
3559-
3560- result = XCreatePixmap (display,
3561- RootWindow (display, screen_num),
3562- width, height, depth);
3563-
3564- XCloseDisplay (display);
3565-
3566- surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
3567- result,
3568- GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
3569- width, height);
3570-
3571- return surface;
3572-}
3573-
3574-static gboolean
3575-get_original_size (const char *filename,
3576- int *orig_width,
3577- int *orig_height)
3578-{
3579- gboolean result;
3580-
3581- if (gdk_pixbuf_get_file_info (filename, orig_width, orig_height))
3582- result = TRUE;
3583- else
3584- result = FALSE;
3585-
3586- return result;
3587-}
3588-
3589-static const char *
3590-get_filename_for_size (GnomeBG *bg, gint best_width, gint best_height)
3591-{
3592- GnomeBGSlideShow *show;
3593- const char *file = NULL;
3594-
3595- if (!bg->filename)
3596- return NULL;
3597-
3598- show = get_as_slideshow (bg, bg->filename);
3599- if (!show) {
3600- return bg->filename;
3601- }
3602-
3603- gnome_bg_slide_show_get_current_slide (show, best_width, best_height, NULL, NULL, NULL, &file, NULL);
3604- return file;
3605-}
3606-
3607-gboolean
3608-gnome_bg_get_image_size (GnomeBG *bg,
3609- GnomeDesktopThumbnailFactory *factory,
3610- int best_width,
3611- int best_height,
3612- int *width,
3613- int *height)
3614-{
3615- GdkPixbuf *thumb;
3616- gboolean result = FALSE;
3617- const gchar *filename;
3618-
3619- g_return_val_if_fail (bg != NULL, FALSE);
3620- g_return_val_if_fail (factory != NULL, FALSE);
3621-
3622- if (!bg->filename)
3623- return FALSE;
3624-
3625- filename = get_filename_for_size (bg, best_width, best_height);
3626- thumb = create_thumbnail_for_filename (factory, filename);
3627- if (thumb) {
3628- if (get_thumb_annotations (thumb, width, height))
3629- result = TRUE;
3630-
3631- g_object_unref (thumb);
3632- }
3633-
3634- if (!result) {
3635- if (get_original_size (filename, width, height))
3636- result = TRUE;
3637- }
3638-
3639- return result;
3640-}
3641-
3642-static double
3643-fit_factor (int from_width, int from_height,
3644- int to_width, int to_height)
3645-{
3646- return MIN (to_width / (double) from_width, to_height / (double) from_height);
3647-}
3648-
3649-/**
3650- * gnome_bg_create_thumbnail:
3651- *
3652- * Returns: (transfer full): a #GdkPixbuf showing the background as a thumbnail
3653- */
3654-GdkPixbuf *
3655-gnome_bg_create_thumbnail (GnomeBG *bg,
3656- GnomeDesktopThumbnailFactory *factory,
3657- GdkScreen *screen,
3658- int dest_width,
3659- int dest_height)
3660-{
3661- GdkPixbuf *result;
3662- GdkPixbuf *thumb;
3663-
3664- g_return_val_if_fail (bg != NULL, NULL);
3665-
3666- result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height);
3667-
3668- draw_color (bg, result);
3669-
3670- if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) {
3671- thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, -1);
3672-
3673- if (thumb) {
3674- draw_image_for_thumb (bg, thumb, result);
3675- g_object_unref (thumb);
3676- }
3677- }
3678-
3679- return result;
3680-}
3681-
3682-/**
3683- * gnome_bg_get_surface_from_root:
3684- * @screen: a #GdkScreen
3685- *
3686- * This function queries the _XROOTPMAP_ID property from
3687- * the root window associated with @screen to determine
3688- * the current root window background pixmap and returns
3689- * a copy of it. If the _XROOTPMAP_ID is not set, then
3690- * a black surface is returned.
3691- *
3692- * Return value: a #cairo_surface_t if successful or %NULL
3693- **/
3694-cairo_surface_t *
3695-gnome_bg_get_surface_from_root (GdkScreen *screen)
3696-{
3697- int result;
3698- gint format;
3699- gulong nitems;
3700- gulong bytes_after;
3701- guchar *data;
3702- Atom type;
3703- Display *display;
3704- int screen_num;
3705- cairo_surface_t *surface;
3706- cairo_surface_t *source_pixmap;
3707- int width, height;
3708- cairo_t *cr;
3709-
3710- display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
3711- screen_num = gdk_screen_get_number (screen);
3712-
3713- result = XGetWindowProperty (display,
3714- RootWindow (display, screen_num),
3715- gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"),
3716- 0L, 1L, False, XA_PIXMAP,
3717- &type, &format, &nitems, &bytes_after,
3718- &data);
3719- surface = NULL;
3720- source_pixmap = NULL;
3721-
3722- if (result != Success || type != XA_PIXMAP ||
3723- format != 32 || nitems != 1) {
3724- XFree (data);
3725- data = NULL;
3726- }
3727-
3728- if (data != NULL) {
3729- Pixmap xpixmap = *(Pixmap *) data;
3730- Window root_return;
3731- int x_ret, y_ret;
3732- unsigned int w_ret, h_ret, bw_ret, depth_ret;
3733-
3734- gdk_error_trap_push ();
3735- if (XGetGeometry (GDK_SCREEN_XDISPLAY (screen),
3736- xpixmap,
3737- &root_return,
3738- &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret)) {
3739- source_pixmap = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
3740- xpixmap,
3741- GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
3742- w_ret, h_ret);
3743- }
3744-
3745- gdk_error_trap_pop_ignored ();
3746- }
3747-
3748- width = gdk_screen_get_width (screen);
3749- height = gdk_screen_get_height (screen);
3750-
3751- if (source_pixmap) {
3752- surface = cairo_surface_create_similar (source_pixmap,
3753- CAIRO_CONTENT_COLOR,
3754- width, height);
3755-
3756- cr = cairo_create (surface);
3757- cairo_set_source_surface (cr, source_pixmap, 0, 0);
3758- cairo_paint (cr);
3759-
3760- if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
3761- cairo_surface_destroy (surface);
3762- surface = NULL;
3763- }
3764-
3765- cairo_destroy (cr);
3766- }
3767-
3768- if (surface == NULL) {
3769- surface = gdk_window_create_similar_surface (gdk_screen_get_root_window (screen),
3770- CAIRO_CONTENT_COLOR,
3771- width, height);
3772- }
3773-
3774- if (source_pixmap != NULL)
3775- cairo_surface_destroy (source_pixmap);
3776-
3777- if (data != NULL)
3778- XFree (data);
3779-
3780- return surface;
3781-}
3782-
3783-static void
3784-gnome_bg_set_root_pixmap_id (GdkScreen *screen,
3785- cairo_surface_t *surface)
3786-{
3787- int result;
3788- gint format;
3789- gulong nitems;
3790- gulong bytes_after;
3791- guchar *data_esetroot;
3792- Pixmap pixmap_id;
3793- Atom type;
3794- Display *display;
3795- int screen_num;
3796- GdkRGBA *average;
3797-
3798- screen_num = gdk_screen_get_number (screen);
3799- data_esetroot = NULL;
3800-
3801- display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
3802-
3803- result = XGetWindowProperty (display,
3804- RootWindow (display, screen_num),
3805- gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"),
3806- 0L, 1L, False, XA_PIXMAP,
3807- &type, &format, &nitems,
3808- &bytes_after,
3809- &data_esetroot);
3810-
3811- if (data_esetroot != NULL) {
3812- if (result == Success && type == XA_PIXMAP &&
3813- format == 32 &&
3814- nitems == 1) {
3815- gdk_error_trap_push ();
3816- XKillClient (display, *(Pixmap *)data_esetroot);
3817- gdk_error_trap_pop_ignored ();
3818- }
3819- XFree (data_esetroot);
3820- }
3821-
3822- pixmap_id = cairo_xlib_surface_get_drawable (surface);
3823-
3824- XChangeProperty (display, RootWindow (display, screen_num),
3825- gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"),
3826- XA_PIXMAP, 32, PropModeReplace,
3827- (guchar *) &pixmap_id, 1);
3828- XChangeProperty (display, RootWindow (display, screen_num),
3829- gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"), XA_PIXMAP,
3830- 32, PropModeReplace,
3831- (guchar *) &pixmap_id, 1);
3832-
3833- average = cairo_surface_get_user_data (surface, &average_color_key);
3834- if (average != NULL) {
3835- gchar *string;
3836-
3837- string = gdk_rgba_to_string (average);
3838-
3839- /* X encodes string lists as one big string with a nul
3840- * terminator after each item in the list. That's why
3841- * the strlen has to be given; scanning for nul would
3842- * only find the first item.
3843- *
3844- * For now, we only want to set a single string.
3845- * Fortunately, since this is C, it comes with its own
3846- * nul and we can just give strlen + 1 for the size of
3847- * our "list".
3848- */
3849- XChangeProperty (display, RootWindow (display, screen_num),
3850- gdk_x11_get_xatom_by_name ("_GNOME_BACKGROUND_REPRESENTATIVE_COLORS"),
3851- XA_STRING, 8, PropModeReplace,
3852- (guchar *) string, strlen (string) + 1);
3853- g_free (string);
3854- } else {
3855- /* Could happen if we didn't create the surface... */
3856- XDeleteProperty (display, RootWindow (display, screen_num),
3857- gdk_x11_get_xatom_by_name ("_GNOME_BACKGROUND_REPRESENTATIVE_COLORS"));
3858- }
3859-}
3860-
3861-/**
3862- * gnome_bg_set_surface_as_root:
3863- * @screen: the #GdkScreen to change root background on
3864- * @surface: the #cairo_surface_t to set root background from.
3865- * Must be an xlib surface backing a pixmap.
3866- *
3867- * Set the root pixmap, and properties pointing to it. We
3868- * do this atomically with a server grab to make sure that
3869- * we won't leak the pixmap if somebody else it setting
3870- * it at the same time. (This assumes that they follow the
3871- * same conventions we do). @surface should come from a call
3872- * to gnome_bg_create_surface().
3873- **/
3874-void
3875-gnome_bg_set_surface_as_root (GdkScreen *screen, cairo_surface_t *surface)
3876-{
3877- Display *display;
3878- int screen_num;
3879-
3880- g_return_if_fail (screen != NULL);
3881- g_return_if_fail (surface != NULL);
3882- g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB);
3883-
3884- screen_num = gdk_screen_get_number (screen);
3885-
3886- display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
3887-
3888- gdk_x11_display_grab (gdk_screen_get_display (screen));
3889-
3890- gnome_bg_set_root_pixmap_id (screen, surface);
3891-
3892- XSetWindowBackgroundPixmap (display, RootWindow (display, screen_num),
3893- cairo_xlib_surface_get_drawable (surface));
3894- XClearWindow (display, RootWindow (display, screen_num));
3895-
3896- gdk_display_flush (gdk_screen_get_display (screen));
3897- gdk_x11_display_ungrab (gdk_screen_get_display (screen));
3898-}
3899-
3900-/**
3901- * gnome_bg_set_surface_as_root_with_crossfade:
3902- * @screen: the #GdkScreen to change root background on
3903- * @surface: the cairo xlib surface to set root background from
3904- *
3905- * Set the root pixmap, and properties pointing to it.
3906- * This function differs from gnome_bg_set_surface_as_root()
3907- * in that it adds a subtle crossfade animation from the
3908- * current root pixmap to the new one.
3909- *
3910- * Return value: (transfer full): a #GnomeBGCrossfade object
3911- **/
3912-GnomeBGCrossfade *
3913-gnome_bg_set_surface_as_root_with_crossfade (GdkScreen *screen,
3914- cairo_surface_t *surface)
3915-{
3916- GdkDisplay *display;
3917- GdkWindow *root_window;
3918- cairo_surface_t *old_surface;
3919- int width, height;
3920- GnomeBGCrossfade *fade;
3921-
3922- g_return_val_if_fail (screen != NULL, NULL);
3923- g_return_val_if_fail (surface != NULL, NULL);
3924-
3925- root_window = gdk_screen_get_root_window (screen);
3926-
3927- width = gdk_screen_get_width (screen);
3928- height = gdk_screen_get_height (screen);
3929-
3930- fade = gnome_bg_crossfade_new (width, height);
3931-
3932- display = gdk_screen_get_display (screen);
3933- gdk_x11_display_grab (display);
3934- old_surface = gnome_bg_get_surface_from_root (screen);
3935- gnome_bg_set_root_pixmap_id (screen, surface);
3936- gnome_bg_crossfade_set_start_surface (fade, old_surface);
3937- cairo_surface_destroy (old_surface);
3938- gnome_bg_crossfade_set_end_surface (fade, surface);
3939- gdk_display_flush (display);
3940- gdk_x11_display_ungrab (display);
3941-
3942- gnome_bg_crossfade_start (fade, root_window);
3943-
3944- return fade;
3945-}
3946-
3947-/* Implementation of the pixbuf cache */
3948-struct _SlideShow
3949-{
3950- gint ref_count;
3951- double start_time;
3952- double total_duration;
3953-
3954- GQueue *slides;
3955-
3956- gboolean has_multiple_sizes;
3957-
3958- /* used during parsing */
3959- struct tm start_tm;
3960- GQueue *stack;
3961-};
3962-
3963-
3964-static GdkPixbuf *
3965-blend (GdkPixbuf *p1,
3966- GdkPixbuf *p2,
3967- double alpha)
3968-{
3969- GdkPixbuf *result = gdk_pixbuf_copy (p1);
3970- GdkPixbuf *tmp;
3971-
3972- if (gdk_pixbuf_get_width (p2) != gdk_pixbuf_get_width (p1) ||
3973- gdk_pixbuf_get_height (p2) != gdk_pixbuf_get_height (p1)) {
3974- tmp = gdk_pixbuf_scale_simple (p2,
3975- gdk_pixbuf_get_width (p1),
3976- gdk_pixbuf_get_height (p1),
3977- GDK_INTERP_BILINEAR);
3978- }
3979- else {
3980- tmp = g_object_ref (p2);
3981- }
3982-
3983- pixbuf_blend (tmp, result, 0, 0, -1, -1, 0, 0, alpha);
3984-
3985- g_object_unref (tmp);
3986-
3987- return result;
3988-}
3989-
3990-typedef enum {
3991- PIXBUF,
3992- SLIDESHOW,
3993- THUMBNAIL
3994-} FileType;
3995-
3996-struct FileCacheEntry
3997-{
3998- FileType type;
3999- char *filename;
4000- union {
4001- GdkPixbuf *pixbuf;
4002- GnomeBGSlideShow *slideshow;
4003- GdkPixbuf *thumbnail;
4004- } u;
4005-};
4006-
4007-static void
4008-file_cache_entry_delete (FileCacheEntry *ent)
4009-{
4010- g_free (ent->filename);
4011-
4012- switch (ent->type) {
4013- case PIXBUF:
4014- g_object_unref (ent->u.pixbuf);
4015- break;
4016- case SLIDESHOW:
4017- g_object_unref (ent->u.slideshow);
4018- break;
4019- case THUMBNAIL:
4020- g_object_unref (ent->u.thumbnail);
4021- break;
4022- }
4023-
4024- g_free (ent);
4025-}
4026-
4027-static void
4028-bound_cache (GnomeBG *bg)
4029-{
4030- while (g_list_length (bg->file_cache) >= CACHE_SIZE) {
4031- GList *last_link = g_list_last (bg->file_cache);
4032- FileCacheEntry *ent = last_link->data;
4033-
4034- file_cache_entry_delete (ent);
4035-
4036- bg->file_cache = g_list_delete_link (bg->file_cache, last_link);
4037- }
4038-}
4039-
4040-static const FileCacheEntry *
4041-file_cache_lookup (GnomeBG *bg, FileType type, const char *filename)
4042-{
4043- GList *list;
4044-
4045- for (list = bg->file_cache; list != NULL; list = list->next) {
4046- FileCacheEntry *ent = list->data;
4047-
4048- if (ent && ent->type == type &&
4049- strcmp (ent->filename, filename) == 0) {
4050- return ent;
4051- }
4052- }
4053-
4054- return NULL;
4055-}
4056-
4057-static FileCacheEntry *
4058-file_cache_entry_new (GnomeBG *bg,
4059- FileType type,
4060- const char *filename)
4061-{
4062- FileCacheEntry *ent = g_new0 (FileCacheEntry, 1);
4063-
4064- g_assert (!file_cache_lookup (bg, type, filename));
4065-
4066- ent->type = type;
4067- ent->filename = g_strdup (filename);
4068-
4069- bg->file_cache = g_list_prepend (bg->file_cache, ent);
4070-
4071- bound_cache (bg);
4072-
4073- return ent;
4074-}
4075-
4076-static void
4077-file_cache_add_pixbuf (GnomeBG *bg,
4078- const char *filename,
4079- GdkPixbuf *pixbuf)
4080-{
4081- FileCacheEntry *ent = file_cache_entry_new (bg, PIXBUF, filename);
4082- ent->u.pixbuf = g_object_ref (pixbuf);
4083-}
4084-
4085-static void
4086-file_cache_add_thumbnail (GnomeBG *bg,
4087- const char *filename,
4088- GdkPixbuf *pixbuf)
4089-{
4090- FileCacheEntry *ent = file_cache_entry_new (bg, THUMBNAIL, filename);
4091- ent->u.thumbnail = g_object_ref (pixbuf);
4092-}
4093-
4094-static void
4095-file_cache_add_slide_show (GnomeBG *bg,
4096- const char *filename,
4097- GnomeBGSlideShow *show)
4098-{
4099- FileCacheEntry *ent = file_cache_entry_new (bg, SLIDESHOW, filename);
4100- ent->u.slideshow = g_object_ref (show);
4101-}
4102-
4103-static GdkPixbuf *
4104-load_from_cache_file (GnomeBG *bg,
4105- const char *filename,
4106- gint num_monitor,
4107- gint best_width,
4108- gint best_height)
4109-{
4110- GdkPixbuf *pixbuf = NULL;
4111- gchar *cache_filename;
4112-
4113- cache_filename = get_wallpaper_cache_filename (filename, num_monitor, bg->placement, best_width, best_height);
4114- if (cache_file_is_valid (filename, cache_filename))
4115- pixbuf = gdk_pixbuf_new_from_file (cache_filename, NULL);
4116- g_free (cache_filename);
4117-
4118- return pixbuf;
4119-}
4120-
4121-static GdkPixbuf *
4122-get_as_pixbuf_for_size (GnomeBG *bg,
4123- const char *filename,
4124- gint num_monitor,
4125- gint best_width,
4126- gint best_height)
4127-{
4128- const FileCacheEntry *ent;
4129- if ((ent = file_cache_lookup (bg, PIXBUF, filename))) {
4130- return g_object_ref (ent->u.pixbuf);
4131- }
4132- else {
4133- GdkPixbufFormat *format;
4134- GdkPixbuf *pixbuf;
4135- gchar *tmp;
4136- pixbuf = NULL;
4137-
4138- /* Try to hit local cache first if relevant */
4139- if (num_monitor != -1)
4140- pixbuf = load_from_cache_file (bg, filename, num_monitor, best_width, best_height);
4141-
4142- if (!pixbuf) {
4143- /* If scalable choose maximum size */
4144- format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
4145-
4146- if (format != NULL) {
4147- tmp = gdk_pixbuf_format_get_name (format);
4148- } else {
4149- tmp = NULL;
4150- }
4151-
4152- if (tmp != NULL &&
4153- strcmp (tmp, "svg") == 0 &&
4154- (best_width > 0 && best_height > 0) &&
4155- (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED ||
4156- bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED ||
4157- bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM))
4158- pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL);
4159- else
4160- pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
4161- g_free (tmp);
4162- }
4163-
4164- if (pixbuf)
4165- file_cache_add_pixbuf (bg, filename, pixbuf);
4166-
4167- return pixbuf;
4168- }
4169-}
4170-
4171-static GnomeBGSlideShow *
4172-get_as_slideshow (GnomeBG *bg, const char *filename)
4173-{
4174- const FileCacheEntry *ent;
4175- if ((ent = file_cache_lookup (bg, SLIDESHOW, filename))) {
4176- return g_object_ref (ent->u.slideshow);
4177- }
4178- else {
4179- GnomeBGSlideShow *show = read_slideshow_file (filename, NULL);
4180-
4181- if (show)
4182- file_cache_add_slide_show (bg, filename, show);
4183-
4184- return show;
4185- }
4186-}
4187-
4188-static GdkPixbuf *
4189-get_as_thumbnail (GnomeBG *bg, GnomeDesktopThumbnailFactory *factory, const char *filename)
4190-{
4191- const FileCacheEntry *ent;
4192- if ((ent = file_cache_lookup (bg, THUMBNAIL, filename))) {
4193- return g_object_ref (ent->u.thumbnail);
4194- }
4195- else {
4196- GdkPixbuf *thumb = create_thumbnail_for_filename (factory, filename);
4197-
4198- if (thumb)
4199- file_cache_add_thumbnail (bg, filename, thumb);
4200-
4201- return thumb;
4202- }
4203-}
4204-
4205-static gboolean
4206-blow_expensive_caches (gpointer data)
4207-{
4208- GnomeBG *bg = data;
4209- GList *list, *next;
4210-
4211- bg->blow_caches_id = 0;
4212-
4213- for (list = bg->file_cache; list != NULL; list = next) {
4214- FileCacheEntry *ent = list->data;
4215- next = list->next;
4216-
4217- if (ent->type == PIXBUF) {
4218- file_cache_entry_delete (ent);
4219- bg->file_cache = g_list_delete_link (bg->file_cache,
4220- list);
4221- }
4222- }
4223-
4224- if (bg->pixbuf_cache) {
4225- g_object_unref (bg->pixbuf_cache);
4226- bg->pixbuf_cache = NULL;
4227- }
4228-
4229- return FALSE;
4230-}
4231-
4232-static void
4233-blow_expensive_caches_in_idle (GnomeBG *bg)
4234-{
4235- if (bg->blow_caches_id == 0) {
4236- bg->blow_caches_id =
4237- g_idle_add (blow_expensive_caches,
4238- bg);
4239- }
4240-}
4241-
4242-
4243-static gboolean
4244-on_timeout (gpointer data)
4245-{
4246- GnomeBG *bg = data;
4247-
4248- bg->timeout_id = 0;
4249-
4250- queue_transitioned (bg);
4251-
4252- return FALSE;
4253-}
4254-
4255-static double
4256-get_slide_timeout (gboolean is_fixed,
4257- gdouble duration)
4258-{
4259- double timeout;
4260- if (is_fixed) {
4261- timeout = duration;
4262- } else {
4263- /* Maybe the number of steps should be configurable? */
4264-
4265- /* In the worst case we will do a fade from 0 to 256, which mean
4266- * we will never use more than 255 steps, however in most cases
4267- * the first and last value are similar and users can't percieve
4268- * changes in pixel values as small as 1/255th. So, lets not waste
4269- * CPU cycles on transitioning to often.
4270- *
4271- * 64 steps is enough for each step to be just detectable in a 16bit
4272- * color mode in the worst case, so we'll use this as an approximation
4273- * of whats detectable.
4274- */
4275- timeout = duration / 64.0;
4276- }
4277- return timeout;
4278-}
4279-
4280-static void
4281-ensure_timeout (GnomeBG *bg,
4282- gdouble timeout)
4283-{
4284- if (!bg->timeout_id) {
4285- /* G_MAXUINT means "only one slide" */
4286- if (timeout < G_MAXUINT) {
4287- bg->timeout_id = g_timeout_add_full (
4288- G_PRIORITY_LOW,
4289- timeout * 1000, on_timeout, bg, NULL);
4290- }
4291- }
4292-}
4293-
4294-static time_t
4295-get_mtime (const char *filename)
4296-{
4297- GFile *file;
4298- GFileInfo *info;
4299- time_t mtime;
4300-
4301- mtime = (time_t)-1;
4302-
4303- if (filename) {
4304- file = g_file_new_for_path (filename);
4305- info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
4306- G_FILE_QUERY_INFO_NONE, NULL, NULL);
4307- if (info) {
4308- mtime = g_file_info_get_attribute_uint64 (info,
4309- G_FILE_ATTRIBUTE_TIME_MODIFIED);
4310- g_object_unref (info);
4311- }
4312- g_object_unref (file);
4313- }
4314-
4315- return mtime;
4316-}
4317-
4318-static GdkPixbuf *
4319-scale_thumbnail (GDesktopBackgroundStyle placement,
4320- const char *filename,
4321- GdkPixbuf *thumb,
4322- GdkScreen *screen,
4323- int dest_width,
4324- int dest_height)
4325-{
4326- int o_width;
4327- int o_height;
4328-
4329- if (placement != G_DESKTOP_BACKGROUND_STYLE_WALLPAPER &&
4330- placement != G_DESKTOP_BACKGROUND_STYLE_CENTERED) {
4331-
4332- /* In this case, the pixbuf will be scaled to fit the screen anyway,
4333- * so just return the pixbuf here
4334- */
4335- return g_object_ref (thumb);
4336- }
4337-
4338- if (get_thumb_annotations (thumb, &o_width, &o_height) ||
4339- (filename && get_original_size (filename, &o_width, &o_height))) {
4340-
4341- int scr_height = gdk_screen_get_height (screen);
4342- int scr_width = gdk_screen_get_width (screen);
4343- int thumb_width = gdk_pixbuf_get_width (thumb);
4344- int thumb_height = gdk_pixbuf_get_height (thumb);
4345- double screen_to_dest = fit_factor (scr_width, scr_height,
4346- dest_width, dest_height);
4347- double thumb_to_orig = fit_factor (thumb_width, thumb_height,
4348- o_width, o_height);
4349- double f = thumb_to_orig * screen_to_dest;
4350- int new_width, new_height;
4351-
4352- new_width = floor (thumb_width * f + 0.5);
4353- new_height = floor (thumb_height * f + 0.5);
4354-
4355- if (placement == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER) {
4356- /* Heuristic to make sure tiles don't become so small that
4357- * they turn into a blur.
4358- *
4359- * This is strictly speaking incorrect, but the resulting
4360- * thumbnail gives a much better idea what the background
4361- * will actually look like.
4362- */
4363-
4364- if ((new_width < 32 || new_height < 32) &&
4365- (new_width < o_width / 4 || new_height < o_height / 4)) {
4366- new_width = o_width / 4;
4367- new_height = o_height / 4;
4368- }
4369- }
4370-
4371- thumb = gdk_pixbuf_scale_simple (thumb, new_width, new_height,
4372- GDK_INTERP_BILINEAR);
4373- }
4374- else
4375- g_object_ref (thumb);
4376-
4377- return thumb;
4378-}
4379-
4380-/* frame_num determines which slide to thumbnail.
4381- * -1 means 'current slide'.
4382- */
4383-static GdkPixbuf *
4384-create_img_thumbnail (GnomeBG *bg,
4385- GnomeDesktopThumbnailFactory *factory,
4386- GdkScreen *screen,
4387- int dest_width,
4388- int dest_height,
4389- int frame_num)
4390-{
4391- if (bg->filename) {
4392- GdkPixbuf *thumb;
4393-
4394- thumb = get_as_thumbnail (bg, factory, bg->filename);
4395-
4396- if (thumb) {
4397- GdkPixbuf *result;
4398- result = scale_thumbnail (bg->placement,
4399- bg->filename,
4400- thumb,
4401- screen,
4402- dest_width,
4403- dest_height);
4404- g_object_unref (thumb);
4405- return result;
4406- }
4407- else {
4408- GnomeBGSlideShow *show = get_as_slideshow (bg, bg->filename);
4409-
4410- if (show) {
4411- double alpha;
4412- double duration;
4413- gboolean is_fixed;
4414- const char *file1;
4415- const char *file2;
4416- GdkPixbuf *tmp;
4417-
4418- if (frame_num == -1)
4419- gnome_bg_slide_show_get_current_slide (show,
4420- dest_width,
4421- dest_height,
4422- &alpha,
4423- &duration,
4424- &is_fixed,
4425- &file1,
4426- &file2);
4427- else
4428- gnome_bg_slide_show_get_slide (show,
4429- frame_num,
4430- dest_width,
4431- dest_height,
4432- &alpha,
4433- &duration,
4434- &is_fixed,
4435- &file1,
4436- &file2);
4437-
4438- if (is_fixed) {
4439- tmp = get_as_thumbnail (bg, factory, file1);
4440- if (tmp) {
4441- thumb = scale_thumbnail (bg->placement,
4442- file1,
4443- tmp,
4444- screen,
4445- dest_width,
4446- dest_height);
4447- g_object_unref (tmp);
4448- }
4449- }
4450- else {
4451- GdkPixbuf *p1, *p2;
4452- p1 = get_as_thumbnail (bg, factory, file1);
4453- p2 = get_as_thumbnail (bg, factory, file2);
4454-
4455- if (p1 && p2) {
4456- GdkPixbuf *thumb1, *thumb2;
4457-
4458- thumb1 = scale_thumbnail (bg->placement,
4459- file1,
4460- p1,
4461- screen,
4462- dest_width,
4463- dest_height);
4464-
4465- thumb2 = scale_thumbnail (bg->placement,
4466- file2,
4467- p2,
4468- screen,
4469- dest_width,
4470- dest_height);
4471-
4472- thumb = blend (thumb1, thumb2, alpha);
4473-
4474- g_object_unref (thumb1);
4475- g_object_unref (thumb2);
4476- }
4477- if (p1)
4478- g_object_unref (p1);
4479- if (p2)
4480- g_object_unref (p2);
4481- }
4482-
4483- ensure_timeout (bg, (guint)get_slide_timeout (is_fixed, duration));
4484-
4485- g_object_unref (show);
4486- }
4487- }
4488-
4489- return thumb;
4490- }
4491-
4492- return NULL;
4493-}
4494-
4495-static GdkPixbuf *
4496-get_pixbuf_for_size (GnomeBG *bg,
4497- gint num_monitor,
4498- gint best_width,
4499- gint best_height)
4500-{
4501- guint time_until_next_change;
4502- gboolean hit_cache = FALSE;
4503-
4504- /* only hit the cache if the aspect ratio matches */
4505- if (bg->pixbuf_cache) {
4506- int width, height;
4507- width = gdk_pixbuf_get_width (bg->pixbuf_cache);
4508- height = gdk_pixbuf_get_height (bg->pixbuf_cache);
4509- hit_cache = 0.2 > fabs ((best_width / (double)best_height) - (width / (double)height));
4510- if (!hit_cache) {
4511- g_object_unref (bg->pixbuf_cache);
4512- bg->pixbuf_cache = NULL;
4513- }
4514- }
4515-
4516- if (!hit_cache && bg->filename) {
4517- bg->file_mtime = get_mtime (bg->filename);
4518-
4519- bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, num_monitor, best_width, best_height);
4520- time_until_next_change = G_MAXUINT;
4521- if (!bg->pixbuf_cache) {
4522- GnomeBGSlideShow *show = get_as_slideshow (bg, bg->filename);
4523-
4524- if (show) {
4525- double alpha;
4526- double duration;
4527- gboolean is_fixed;
4528- const char *file1;
4529- const char *file2;
4530-
4531- g_object_ref (show);
4532-
4533- gnome_bg_slide_show_get_current_slide (show,
4534- best_width,
4535- best_height,
4536- &alpha,
4537- &duration,
4538- &is_fixed,
4539- &file1,
4540- &file2);
4541- time_until_next_change = (guint)get_slide_timeout (is_fixed, duration);
4542- if (is_fixed) {
4543- bg->pixbuf_cache = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width, best_height);
4544- }
4545- else {
4546- GdkPixbuf *p1, *p2;
4547- p1 = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width, best_height);
4548- p2 = get_as_pixbuf_for_size (bg, file2, num_monitor, best_width, best_height);
4549-
4550- if (p1 && p2) {
4551- bg->pixbuf_cache = blend (p1, p2, alpha);
4552- }
4553- if (p1)
4554- g_object_unref (p1);
4555- if (p2)
4556- g_object_unref (p2);
4557- }
4558-
4559- ensure_timeout (bg, time_until_next_change);
4560-
4561- g_object_unref (show);
4562- }
4563- }
4564-
4565- /* If the next slideshow step is a long time away then
4566- we blow away the expensive stuff (large pixbufs) from
4567- the cache */
4568- if (time_until_next_change > KEEP_EXPENSIVE_CACHE_SECS)
4569- blow_expensive_caches_in_idle (bg);
4570- }
4571-
4572- if (bg->pixbuf_cache)
4573- g_object_ref (bg->pixbuf_cache);
4574-
4575- return bg->pixbuf_cache;
4576-}
4577-
4578-static gboolean
4579-is_different (GnomeBG *bg,
4580- const char *filename)
4581-{
4582- if (!filename && bg->filename) {
4583- return TRUE;
4584- }
4585- else if (filename && !bg->filename) {
4586- return TRUE;
4587- }
4588- else if (!filename && !bg->filename) {
4589- return FALSE;
4590- }
4591- else {
4592- time_t mtime = get_mtime (filename);
4593-
4594- if (mtime != bg->file_mtime)
4595- return TRUE;
4596-
4597- if (strcmp (filename, bg->filename) != 0)
4598- return TRUE;
4599-
4600- return FALSE;
4601- }
4602-}
4603-
4604-static void
4605-clear_cache (GnomeBG *bg)
4606-{
4607- GList *list;
4608-
4609- if (bg->file_cache) {
4610- for (list = bg->file_cache; list != NULL; list = list->next) {
4611- FileCacheEntry *ent = list->data;
4612-
4613- file_cache_entry_delete (ent);
4614- }
4615- g_list_free (bg->file_cache);
4616- bg->file_cache = NULL;
4617- }
4618-
4619- if (bg->pixbuf_cache) {
4620- g_object_unref (bg->pixbuf_cache);
4621-
4622- bg->pixbuf_cache = NULL;
4623- }
4624-
4625- if (bg->timeout_id) {
4626- g_source_remove (bg->timeout_id);
4627-
4628- bg->timeout_id = 0;
4629- }
4630-}
4631-
4632-/* Pixbuf utilities */
4633-static void
4634-pixbuf_average_value (GdkPixbuf *pixbuf,
4635- GdkRGBA *result)
4636-{
4637- guint64 a_total, r_total, g_total, b_total;
4638- guint row, column;
4639- int row_stride;
4640- const guchar *pixels, *p;
4641- int r, g, b, a;
4642- guint64 dividend;
4643- guint width, height;
4644- gdouble dd;
4645-
4646- width = gdk_pixbuf_get_width (pixbuf);
4647- height = gdk_pixbuf_get_height (pixbuf);
4648- row_stride = gdk_pixbuf_get_rowstride (pixbuf);
4649- pixels = gdk_pixbuf_get_pixels (pixbuf);
4650-
4651- /* iterate through the pixbuf, counting up each component */
4652- a_total = 0;
4653- r_total = 0;
4654- g_total = 0;
4655- b_total = 0;
4656-
4657- if (gdk_pixbuf_get_has_alpha (pixbuf)) {
4658- for (row = 0; row < height; row++) {
4659- p = pixels + (row * row_stride);
4660- for (column = 0; column < width; column++) {
4661- r = *p++;
4662- g = *p++;
4663- b = *p++;
4664- a = *p++;
4665-
4666- a_total += a;
4667- r_total += r * a;
4668- g_total += g * a;
4669- b_total += b * a;
4670- }
4671- }
4672- dividend = height * width * 0xFF;
4673- a_total *= 0xFF;
4674- } else {
4675- for (row = 0; row < height; row++) {
4676- p = pixels + (row * row_stride);
4677- for (column = 0; column < width; column++) {
4678- r = *p++;
4679- g = *p++;
4680- b = *p++;
4681-
4682- r_total += r;
4683- g_total += g;
4684- b_total += b;
4685- }
4686- }
4687- dividend = height * width;
4688- a_total = dividend * 0xFF;
4689- }
4690-
4691- dd = dividend * 0xFF;
4692- result->alpha = a_total / dd;
4693- result->red = r_total / dd;
4694- result->green = g_total / dd;
4695- result->blue = b_total / dd;
4696-}
4697-
4698-static GdkPixbuf *
4699-pixbuf_scale_to_fit (GdkPixbuf *src, int max_width, int max_height)
4700-{
4701- double factor;
4702- int src_width, src_height;
4703- int new_width, new_height;
4704-
4705- src_width = gdk_pixbuf_get_width (src);
4706- src_height = gdk_pixbuf_get_height (src);
4707-
4708- factor = MIN (max_width / (double) src_width, max_height / (double) src_height);
4709-
4710- new_width = floor (src_width * factor + 0.5);
4711- new_height = floor (src_height * factor + 0.5);
4712-
4713- return gdk_pixbuf_scale_simple (src, new_width, new_height, GDK_INTERP_BILINEAR);
4714-}
4715-
4716-static GdkPixbuf *
4717-pixbuf_scale_to_min (GdkPixbuf *src, int min_width, int min_height)
4718-{
4719- double factor;
4720- int src_width, src_height;
4721- int new_width, new_height;
4722- GdkPixbuf *dest;
4723-
4724- src_width = gdk_pixbuf_get_width (src);
4725- src_height = gdk_pixbuf_get_height (src);
4726-
4727- factor = MAX (min_width / (double) src_width, min_height / (double) src_height);
4728-
4729- new_width = floor (src_width * factor + 0.5);
4730- new_height = floor (src_height * factor + 0.5);
4731-
4732- dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
4733- gdk_pixbuf_get_has_alpha (src),
4734- 8, min_width, min_height);
4735- if (!dest)
4736- return NULL;
4737-
4738- /* crop the result */
4739- gdk_pixbuf_scale (src, dest,
4740- 0, 0,
4741- min_width, min_height,
4742- (new_width - min_width) / -2,
4743- (new_height - min_height) / -2,
4744- factor,
4745- factor,
4746- GDK_INTERP_BILINEAR);
4747- return dest;
4748-}
4749-
4750-static guchar *
4751-create_gradient (const GdkColor *primary,
4752- const GdkColor *secondary,
4753- int n_pixels)
4754-{
4755- guchar *result = g_malloc (n_pixels * 3);
4756- int i;
4757-
4758- for (i = 0; i < n_pixels; ++i) {
4759- double ratio = (i + 0.5) / n_pixels;
4760-
4761- result[3 * i + 0] = ((guint16) (primary->red * (1 - ratio) + secondary->red * ratio)) >> 8;
4762- result[3 * i + 1] = ((guint16) (primary->green * (1 - ratio) + secondary->green * ratio)) >> 8;
4763- result[3 * i + 2] = ((guint16) (primary->blue * (1 - ratio) + secondary->blue * ratio)) >> 8;
4764- }
4765-
4766- return result;
4767-}
4768-
4769-static void
4770-pixbuf_draw_gradient (GdkPixbuf *pixbuf,
4771- gboolean horizontal,
4772- GdkColor *primary,
4773- GdkColor *secondary,
4774- GdkRectangle *rect)
4775-{
4776- int width;
4777- int height;
4778- int rowstride;
4779- guchar *dst;
4780- int n_channels = 3;
4781-
4782- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
4783- width = rect->width;
4784- height = rect->height;
4785- dst = gdk_pixbuf_get_pixels (pixbuf) + rect->x * n_channels + rowstride * rect->y;
4786-
4787- if (horizontal) {
4788- guchar *gradient = create_gradient (primary, secondary, width);
4789- int copy_bytes_per_row = width * n_channels;
4790- int i;
4791-
4792- for (i = 0; i < height; i++) {
4793- guchar *d;
4794- d = dst + rowstride * i;
4795- memcpy (d, gradient, copy_bytes_per_row);
4796- }
4797- g_free (gradient);
4798- } else {
4799- guchar *gb, *gradient;
4800- int i;
4801-
4802- gradient = create_gradient (primary, secondary, height);
4803- for (i = 0; i < height; i++) {
4804- int j;
4805- guchar *d;
4806-
4807- d = dst + rowstride * i;
4808- gb = gradient + n_channels * i;
4809- for (j = width; j > 0; j--) {
4810- int k;
4811-
4812- for (k = 0; k < n_channels; k++) {
4813- *(d++) = gb[k];
4814- }
4815- }
4816- }
4817-
4818- g_free (gradient);
4819- }
4820-}
4821-
4822-static void
4823-pixbuf_blend (GdkPixbuf *src,
4824- GdkPixbuf *dest,
4825- int src_x,
4826- int src_y,
4827- int src_width,
4828- int src_height,
4829- int dest_x,
4830- int dest_y,
4831- double alpha)
4832-{
4833- int dest_width = gdk_pixbuf_get_width (dest);
4834- int dest_height = gdk_pixbuf_get_height (dest);
4835- int offset_x = dest_x - src_x;
4836- int offset_y = dest_y - src_y;
4837-
4838- if (src_width < 0)
4839- src_width = gdk_pixbuf_get_width (src);
4840-
4841- if (src_height < 0)
4842- src_height = gdk_pixbuf_get_height (src);
4843-
4844- if (dest_x < 0)
4845- dest_x = 0;
4846-
4847- if (dest_y < 0)
4848- dest_y = 0;
4849-
4850- if (dest_x + src_width > dest_width) {
4851- src_width = dest_width - dest_x;
4852- }
4853-
4854- if (dest_y + src_height > dest_height) {
4855- src_height = dest_height - dest_y;
4856- }
4857-
4858- gdk_pixbuf_composite (src, dest,
4859- dest_x, dest_y,
4860- src_width, src_height,
4861- offset_x, offset_y,
4862- 1, 1, GDK_INTERP_NEAREST,
4863- alpha * 0xFF + 0.5);
4864-}
4865-
4866-static void
4867-pixbuf_tile (GdkPixbuf *src, GdkPixbuf *dest)
4868-{
4869- int x, y;
4870- int tile_width, tile_height;
4871- int dest_width = gdk_pixbuf_get_width (dest);
4872- int dest_height = gdk_pixbuf_get_height (dest);
4873- tile_width = gdk_pixbuf_get_width (src);
4874- tile_height = gdk_pixbuf_get_height (src);
4875-
4876- for (y = 0; y < dest_height; y += tile_height) {
4877- for (x = 0; x < dest_width; x += tile_width) {
4878- pixbuf_blend (src, dest, 0, 0,
4879- tile_width, tile_height, x, y, 1.0);
4880- }
4881- }
4882-}
4883-
4884-static GnomeBGSlideShow *
4885-read_slideshow_file (const char *filename,
4886- GError **err)
4887-{
4888- GnomeBGSlideShow *show;
4889-
4890- show = gnome_bg_slide_show_new (filename);
4891-
4892- if (!gnome_bg_slide_show_load (show, err)) {
4893- g_object_unref (show);
4894- return NULL;
4895- }
4896-
4897- return show;
4898-}
4899-
4900-/* Thumbnail utilities */
4901-static GdkPixbuf *
4902-create_thumbnail_for_filename (GnomeDesktopThumbnailFactory *factory,
4903- const char *filename)
4904-{
4905- char *thumb;
4906- time_t mtime;
4907- GdkPixbuf *orig, *result = NULL;
4908- char *uri;
4909-
4910- mtime = get_mtime (filename);
4911-
4912- if (mtime == (time_t)-1)
4913- return NULL;
4914-
4915- uri = g_filename_to_uri (filename, NULL, NULL);
4916-
4917- if (uri == NULL)
4918- return NULL;
4919-
4920- thumb = gnome_desktop_thumbnail_factory_lookup (factory, uri, mtime);
4921-
4922- if (thumb) {
4923- result = gdk_pixbuf_new_from_file (thumb, NULL);
4924- g_free (thumb);
4925- }
4926- else {
4927- orig = gdk_pixbuf_new_from_file (filename, NULL);
4928- if (orig) {
4929- int orig_width = gdk_pixbuf_get_width (orig);
4930- int orig_height = gdk_pixbuf_get_height (orig);
4931-
4932- result = pixbuf_scale_to_fit (orig, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
4933-
4934- g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-height",
4935- g_strdup_printf ("%d", orig_height), g_free);
4936- g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-width",
4937- g_strdup_printf ("%d", orig_width), g_free);
4938-
4939- g_object_unref (orig);
4940-
4941- gnome_desktop_thumbnail_factory_save_thumbnail (factory, result, uri, mtime);
4942- }
4943- else {
4944- gnome_desktop_thumbnail_factory_create_failed_thumbnail (factory, uri, mtime);
4945- }
4946- }
4947-
4948- g_free (uri);
4949-
4950- return result;
4951-}
4952-
4953-static gboolean
4954-get_thumb_annotations (GdkPixbuf *thumb,
4955- int *orig_width,
4956- int *orig_height)
4957-{
4958- char *end;
4959- const char *wstr, *hstr;
4960-
4961- wstr = gdk_pixbuf_get_option (thumb, "tEXt::Thumb::Image::Width");
4962- hstr = gdk_pixbuf_get_option (thumb, "tEXt::Thumb::Image::Height");
4963-
4964- if (hstr && wstr) {
4965- *orig_width = strtol (wstr, &end, 10);
4966- if (*end != 0)
4967- return FALSE;
4968-
4969- *orig_height = strtol (hstr, &end, 10);
4970- if (*end != 0)
4971- return FALSE;
4972-
4973- return TRUE;
4974- }
4975-
4976- return FALSE;
4977-}
4978-
4979-/*
4980- * Returns whether the background is a slideshow.
4981- */
4982-gboolean
4983-gnome_bg_changes_with_time (GnomeBG *bg)
4984-{
4985- GnomeBGSlideShow *show;
4986-
4987- g_return_val_if_fail (bg != NULL, FALSE);
4988-
4989- show = get_as_slideshow (bg, bg->filename);
4990- if (show)
4991- return gnome_bg_slide_show_get_num_slides (show) > 1;
4992-
4993- return FALSE;
4994-}
4995-
4996-/**
4997- * gnome_bg_create_frame_thumbnail:
4998- *
4999- * Creates a thumbnail for a certain frame, where 'frame' is somewhat
5000- * vaguely defined as 'suitable point to show while single-stepping
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: