summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am31
-rw-r--r--plugins/Makefile.in630
-rw-r--r--plugins/a11y-keyboard/Makefile.am87
-rw-r--r--plugins/a11y-keyboard/Makefile.in809
-rw-r--r--plugins/a11y-keyboard/a11y-keyboard.mate-settings-plugin.in8
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c1347
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-keyboard-manager.h61
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c104
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.h63
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c975
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-preferences-dialog.h59
-rw-r--r--plugins/a11y-keyboard/gsd-a11y-preferences-dialog.ui199
-rw-r--r--plugins/a11y-keyboard/test-a11y-preferences-dialog.c64
-rw-r--r--plugins/background/Makefile.am75
-rw-r--r--plugins/background/Makefile.in758
-rw-r--r--plugins/background/background.mate-settings-plugin.in8
-rw-r--r--plugins/background/gsd-background-manager.c579
-rw-r--r--plugins/background/gsd-background-manager.h61
-rw-r--r--plugins/background/gsd-background-plugin.c104
-rw-r--r--plugins/background/gsd-background-plugin.h63
-rw-r--r--plugins/background/test-background.c59
-rw-r--r--plugins/clipboard/Makefile.am53
-rw-r--r--plugins/clipboard/Makefile.in699
-rw-r--r--plugins/clipboard/clipboard.mate-settings-plugin.in8
-rw-r--r--plugins/clipboard/gsd-clipboard-manager.c1069
-rw-r--r--plugins/clipboard/gsd-clipboard-manager.h61
-rw-r--r--plugins/clipboard/gsd-clipboard-plugin.c104
-rw-r--r--plugins/clipboard/gsd-clipboard-plugin.h63
-rw-r--r--plugins/clipboard/list.c150
-rw-r--r--plugins/clipboard/list.h57
-rw-r--r--plugins/clipboard/xutils.c117
-rw-r--r--plugins/clipboard/xutils.h50
-rw-r--r--plugins/common/Makefile.am23
-rw-r--r--plugins/common/Makefile.in584
-rw-r--r--plugins/common/eggaccelerators.c658
-rw-r--r--plugins/common/eggaccelerators.h99
-rw-r--r--plugins/common/gsd-keygrab.c246
-rw-r--r--plugins/common/gsd-keygrab.h51
-rw-r--r--plugins/common/gsd-osd-window.c573
-rw-r--r--plugins/common/gsd-osd-window.h98
-rw-r--r--plugins/datetime/Makefile.am60
-rw-r--r--plugins/datetime/Makefile.in719
-rw-r--r--plugins/datetime/gsd-datetime-mechanism-main.c171
-rw-r--r--plugins/datetime/gsd-datetime-mechanism.c646
-rw-r--r--plugins/datetime/gsd-datetime-mechanism.h101
-rw-r--r--plugins/datetime/gsd-datetime-mechanism.xml87
-rw-r--r--plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.conf19
-rw-r--r--plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.service.in4
-rw-r--r--plugins/datetime/org.mate.settingsdaemon.datetimemechanism.policy.in38
-rw-r--r--plugins/datetime/system-timezone.c1047
-rw-r--r--plugins/datetime/system-timezone.h89
-rw-r--r--plugins/dummy/Makefile.am44
-rw-r--r--plugins/dummy/Makefile.in646
-rw-r--r--plugins/dummy/dummy.mate-settings-plugin.in8
-rw-r--r--plugins/dummy/gsd-dummy-manager.c186
-rw-r--r--plugins/dummy/gsd-dummy-manager.h61
-rw-r--r--plugins/dummy/gsd-dummy-plugin.c104
-rw-r--r--plugins/dummy/gsd-dummy-plugin.h63
-rw-r--r--plugins/font/Makefile.am51
-rw-r--r--plugins/font/Makefile.in687
-rw-r--r--plugins/font/delayed-dialog.c122
-rw-r--r--plugins/font/delayed-dialog.h36
-rw-r--r--plugins/font/font.mate-settings-plugin.in8
-rw-r--r--plugins/font/gsd-font-manager.c440
-rw-r--r--plugins/font/gsd-font-manager.h61
-rw-r--r--plugins/font/gsd-font-plugin.c104
-rw-r--r--plugins/font/gsd-font-plugin.h63
-rw-r--r--plugins/housekeeping/Makefile.am40
-rw-r--r--plugins/housekeeping/Makefile.in689
-rw-r--r--plugins/housekeeping/gsd-disk-space.c733
-rw-r--r--plugins/housekeeping/gsd-disk-space.h40
-rw-r--r--plugins/housekeeping/gsd-housekeeping-manager.c389
-rw-r--r--plugins/housekeeping/gsd-housekeeping-manager.h59
-rw-r--r--plugins/housekeeping/gsd-housekeeping-plugin.c104
-rw-r--r--plugins/housekeeping/gsd-housekeeping-plugin.h61
-rw-r--r--plugins/housekeeping/gsd-ldsm-dialog.c476
-rw-r--r--plugins/housekeeping/gsd-ldsm-dialog.h72
-rw-r--r--plugins/housekeeping/gsd-ldsm-trash-empty.c398
-rw-r--r--plugins/housekeeping/gsd-ldsm-trash-empty.h27
-rw-r--r--plugins/housekeeping/housekeeping.mate-settings-plugin.in8
-rw-r--r--plugins/keybindings/Makefile.am51
-rw-r--r--plugins/keybindings/Makefile.in682
-rw-r--r--plugins/keybindings/gsd-keybindings-manager.c758
-rw-r--r--plugins/keybindings/gsd-keybindings-manager.h61
-rw-r--r--plugins/keybindings/gsd-keybindings-plugin.c104
-rw-r--r--plugins/keybindings/gsd-keybindings-plugin.h63
-rw-r--r--plugins/keybindings/keybindings.mate-settings-plugin.in8
-rw-r--r--plugins/keyboard/Makefile.am73
-rw-r--r--plugins/keyboard/Makefile.in771
-rw-r--r--plugins/keyboard/delayed-dialog.c122
-rw-r--r--plugins/keyboard/delayed-dialog.h36
-rw-r--r--plugins/keyboard/gsd-keyboard-manager.c570
-rw-r--r--plugins/keyboard/gsd-keyboard-manager.h62
-rw-r--r--plugins/keyboard/gsd-keyboard-plugin.c104
-rw-r--r--plugins/keyboard/gsd-keyboard-plugin.h63
-rw-r--r--plugins/keyboard/gsd-keyboard-xkb.c924
-rw-r--r--plugins/keyboard/gsd-keyboard-xkb.h42
-rw-r--r--plugins/keyboard/gsd-xmodmap.c399
-rw-r--r--plugins/keyboard/gsd-xmodmap.h29
-rw-r--r--plugins/keyboard/kbd-capslock-off.pngbin0 -> 1650 bytes
-rw-r--r--plugins/keyboard/kbd-capslock-on.pngbin0 -> 1488 bytes
-rw-r--r--plugins/keyboard/kbd-numlock-off.pngbin0 -> 1742 bytes
-rw-r--r--plugins/keyboard/kbd-numlock-on.pngbin0 -> 1591 bytes
-rw-r--r--plugins/keyboard/kbd-scrolllock-off.pngbin0 -> 1467 bytes
-rw-r--r--plugins/keyboard/kbd-scrolllock-on.pngbin0 -> 1337 bytes
-rw-r--r--plugins/keyboard/keyboard.mate-settings-plugin.in8
-rw-r--r--plugins/keyboard/modmap-dialog.ui273
-rw-r--r--plugins/media-keys/Makefile.am207
-rw-r--r--plugins/media-keys/Makefile.in1159
-rw-r--r--plugins/media-keys/acme.h78
-rw-r--r--plugins/media-keys/acme.ui33
-rw-r--r--plugins/media-keys/cut-n-paste/Makefile.am39
-rw-r--r--plugins/media-keys/cut-n-paste/Makefile.in586
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-channel-map.c292
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-channel-map.h83
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-card.c493
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-card.h90
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-control.c2123
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-control.h102
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c239
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h61
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c188
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.h61
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-sink.c220
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-sink.h61
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c128
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-source-output.h61
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-source.c220
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-source.h61
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-stream.c875
-rw-r--r--plugins/media-keys/cut-n-paste/gvc-mixer-stream.h128
-rw-r--r--plugins/media-keys/gsd-marshal.list1
-rw-r--r--plugins/media-keys/gsd-media-keys-manager.c1373
-rw-r--r--plugins/media-keys/gsd-media-keys-manager.h72
-rw-r--r--plugins/media-keys/gsd-media-keys-manager.xml14
-rw-r--r--plugins/media-keys/gsd-media-keys-plugin.c104
-rw-r--r--plugins/media-keys/gsd-media-keys-plugin.h63
-rw-r--r--plugins/media-keys/gsd-media-keys-window.c714
-rw-r--r--plugins/media-keys/gsd-media-keys-window.h78
-rw-r--r--plugins/media-keys/libmedia-keys.la41
-rw-r--r--plugins/media-keys/media-keys.mate-settings-plugin136
-rw-r--r--plugins/media-keys/media-keys.mate-settings-plugin.in8
-rw-r--r--plugins/media-keys/test-media-keys.c64
-rw-r--r--plugins/media-keys/test-media-window.c152
-rw-r--r--plugins/media-keys/touchpad-disabled-16.pngbin0 -> 610 bytes
-rw-r--r--plugins/media-keys/touchpad-disabled-22.pngbin0 -> 957 bytes
-rw-r--r--plugins/media-keys/touchpad-disabled-24.pngbin0 -> 985 bytes
-rw-r--r--plugins/media-keys/touchpad-disabled-32.pngbin0 -> 1610 bytes
-rw-r--r--plugins/media-keys/touchpad-disabled-48.pngbin0 -> 2208 bytes
-rw-r--r--plugins/media-keys/touchpad-disabled-template.svg1172
-rw-r--r--plugins/media-keys/touchpad-disabled.svg833
-rw-r--r--plugins/media-keys/touchpad-enabled-16.pngbin0 -> 626 bytes
-rw-r--r--plugins/media-keys/touchpad-enabled-22.pngbin0 -> 938 bytes
-rw-r--r--plugins/media-keys/touchpad-enabled-24.pngbin0 -> 949 bytes
-rw-r--r--plugins/media-keys/touchpad-enabled-32.pngbin0 -> 1494 bytes
-rw-r--r--plugins/media-keys/touchpad-enabled-48.pngbin0 -> 2041 bytes
-rw-r--r--plugins/media-keys/touchpad-enabled-template.svg936
-rw-r--r--plugins/media-keys/touchpad-enabled.svg581
-rw-r--r--plugins/mouse/Makefile.am52
-rw-r--r--plugins/mouse/Makefile.in768
-rw-r--r--plugins/mouse/gsd-locate-pointer.c504
-rw-r--r--plugins/mouse/gsd-locate-pointer.h24
-rw-r--r--plugins/mouse/gsd-mouse-manager.c1124
-rw-r--r--plugins/mouse/gsd-mouse-manager.h61
-rw-r--r--plugins/mouse/gsd-mouse-plugin.c104
-rw-r--r--plugins/mouse/gsd-mouse-plugin.h63
-rw-r--r--plugins/mouse/gsd-timeline.c848
-rw-r--r--plugins/mouse/gsd-timeline.h127
-rw-r--r--plugins/mouse/mouse.mate-settings-plugin.in8
-rw-r--r--plugins/smartcard/Makefile.am47
-rw-r--r--plugins/smartcard/Makefile.in684
-rw-r--r--plugins/smartcard/gsd-smartcard-manager.c1372
-rw-r--r--plugins/smartcard/gsd-smartcard-manager.h90
-rw-r--r--plugins/smartcard/gsd-smartcard-plugin.c340
-rw-r--r--plugins/smartcard/gsd-smartcard-plugin.h63
-rw-r--r--plugins/smartcard/gsd-smartcard.c555
-rw-r--r--plugins/smartcard/gsd-smartcard.h98
-rw-r--r--plugins/smartcard/smartcard.mate-settings-plugin.in8
-rw-r--r--plugins/sound/Makefile.am42
-rw-r--r--plugins/sound/Makefile.in669
-rw-r--r--plugins/sound/gsd-sound-manager.c433
-rw-r--r--plugins/sound/gsd-sound-manager.h61
-rw-r--r--plugins/sound/gsd-sound-plugin.c100
-rw-r--r--plugins/sound/gsd-sound-plugin.h63
-rw-r--r--plugins/sound/sound.mate-settings-plugin.in8
-rw-r--r--plugins/typing-break/Makefile.am49
-rw-r--r--plugins/typing-break/Makefile.in680
-rw-r--r--plugins/typing-break/gsd-typing-break-manager.c339
-rw-r--r--plugins/typing-break/gsd-typing-break-manager.h61
-rw-r--r--plugins/typing-break/gsd-typing-break-plugin.c104
-rw-r--r--plugins/typing-break/gsd-typing-break-plugin.h63
-rw-r--r--plugins/typing-break/typing-break.mate-settings-plugin.in8
-rw-r--r--plugins/xrandr/Makefile.am76
-rw-r--r--plugins/xrandr/Makefile.in711
-rw-r--r--plugins/xrandr/gsd-xrandr-16.pngbin0 -> 613 bytes
-rw-r--r--plugins/xrandr/gsd-xrandr-22.pngbin0 -> 866 bytes
-rw-r--r--plugins/xrandr/gsd-xrandr-24.pngbin0 -> 909 bytes
-rw-r--r--plugins/xrandr/gsd-xrandr-32.pngbin0 -> 1602 bytes
-rw-r--r--plugins/xrandr/gsd-xrandr-manager.c2584
-rw-r--r--plugins/xrandr/gsd-xrandr-manager.h61
-rw-r--r--plugins/xrandr/gsd-xrandr-manager.xml23
-rw-r--r--plugins/xrandr/gsd-xrandr-plugin.c104
-rw-r--r--plugins/xrandr/gsd-xrandr-plugin.h63
-rw-r--r--plugins/xrandr/gsd-xrandr.svg470
-rw-r--r--plugins/xrandr/xrandr.mate-settings-plugin.in8
-rw-r--r--plugins/xrdb/Makefile.am54
-rw-r--r--plugins/xrdb/Makefile.in834
-rw-r--r--plugins/xrdb/data/Editres.ad5
-rw-r--r--plugins/xrdb/data/Emacs.ad21
-rw-r--r--plugins/xrdb/data/General.ad2
-rw-r--r--plugins/xrdb/data/Makefile.am15
-rw-r--r--plugins/xrdb/data/Makefile.in483
-rw-r--r--plugins/xrdb/data/Motif.ad74
-rw-r--r--plugins/xrdb/data/Tk.ad102
-rw-r--r--plugins/xrdb/data/Xaw.ad25
-rw-r--r--plugins/xrdb/gsd-xrdb-manager.c638
-rw-r--r--plugins/xrdb/gsd-xrdb-manager.h61
-rw-r--r--plugins/xrdb/gsd-xrdb-plugin.c104
-rw-r--r--plugins/xrdb/gsd-xrdb-plugin.h63
-rw-r--r--plugins/xrdb/xrdb.mate-settings-plugin.in8
-rw-r--r--plugins/xsettings/Makefile.am65
-rw-r--r--plugins/xsettings/Makefile.in718
-rw-r--r--plugins/xsettings/fontconfig-monitor.c192
-rw-r--r--plugins/xsettings/fontconfig-monitor.h44
-rw-r--r--plugins/xsettings/gsd-xsettings-manager.c1040
-rw-r--r--plugins/xsettings/gsd-xsettings-manager.h61
-rw-r--r--plugins/xsettings/gsd-xsettings-plugin.c104
-rw-r--r--plugins/xsettings/gsd-xsettings-plugin.h63
-rw-r--r--plugins/xsettings/xsettings-common.c264
-rw-r--r--plugins/xsettings/xsettings-common.h110
-rw-r--r--plugins/xsettings/xsettings-manager.c424
-rw-r--r--plugins/xsettings/xsettings-manager.h71
-rw-r--r--plugins/xsettings/xsettings.mate-settings-plugin.in8
233 files changed, 58174 insertions, 0 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
new file mode 100644
index 0000000..f84cdf9
--- /dev/null
+++ b/plugins/Makefile.am
@@ -0,0 +1,31 @@
+NULL =
+
+enabled_plugins = \
+ a11y-keyboard \
+ background \
+ clipboard \
+ datetime \
+ dummy \
+ font \
+ housekeeping \
+ keybindings \
+ keyboard \
+ media-keys \
+ mouse \
+ sound \
+ typing-break \
+ xrandr \
+ xrdb \
+ xsettings \
+ $(NULL)
+
+disabled_plugins = $(NULL)
+
+if SMARTCARD_SUPPORT
+enabled_plugins += smartcard
+else
+disabled_plugins += smartcard
+endif
+
+SUBDIRS = common $(enabled_plugins)
+DIST_SUBDIRS = $(SUBDIRS) $(disabled_plugins)
diff --git a/plugins/Makefile.in b/plugins/Makefile.in
new file mode 100644
index 0000000..82b4310
--- /dev/null
+++ b/plugins/Makefile.in
@@ -0,0 +1,630 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SMARTCARD_SUPPORT_TRUE@am__append_1 = smartcard
+@SMARTCARD_SUPPORT_FALSE@am__append_2 = smartcard
+subdir = plugins
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+enabled_plugins = a11y-keyboard background clipboard datetime dummy \
+ font housekeeping keybindings keyboard media-keys mouse sound \
+ typing-break xrandr xrdb xsettings $(NULL) $(am__append_1)
+disabled_plugins = $(NULL) $(am__append_2)
+SUBDIRS = common $(enabled_plugins)
+DIST_SUBDIRS = $(SUBDIRS) $(disabled_plugins)
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/a11y-keyboard/Makefile.am b/plugins/a11y-keyboard/Makefile.am
new file mode 100644
index 0000000..8396513
--- /dev/null
+++ b/plugins/a11y-keyboard/Makefile.am
@@ -0,0 +1,87 @@
+NULL =
+
+gtkbuilderdir = $(pkgdatadir)
+gtkbuilder_DATA = \
+ gsd-a11y-preferences-dialog.ui \
+ $(NULL)
+
+noinst_PROGRAMS = \
+ test-a11y-preferences-dialog \
+ $(NULL)
+
+test_a11y_preferences_dialog_SOURCES = \
+ gsd-a11y-preferences-dialog.c \
+ gsd-a11y-preferences-dialog.h \
+ test-a11y-preferences-dialog.c \
+ $(NULL)
+
+test_a11y_preferences_dialog_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_a11y_preferences_dialog_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_a11y_preferences_dialog_LDADD = \
+ $(SETTINGS_DAEMON_LIBS) \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_LTLIBRARIES = \
+ liba11y-keyboard.la \
+ $(NULL)
+
+liba11y_keyboard_la_SOURCES = \
+ gsd-a11y-keyboard-plugin.h \
+ gsd-a11y-keyboard-plugin.c \
+ gsd-a11y-keyboard-manager.h \
+ gsd-a11y-keyboard-manager.c \
+ gsd-a11y-preferences-dialog.h \
+ gsd-a11y-preferences-dialog.c \
+ $(NULL)
+
+liba11y_keyboard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ -DGTKBUILDERDIR=\""$(gtkbuilderdir)"\" \
+ $(AM_CPPFLAGS)
+
+liba11y_keyboard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(LIBMATENOTIFY_CFLAGS) \
+ $(AM_CFLAGS)
+
+liba11y_keyboard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+liba11y_keyboard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(LIBMATENOTIFY_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ a11y-keyboard.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(gtkbuilder_DATA) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/a11y-keyboard/Makefile.in b/plugins/a11y-keyboard/Makefile.in
new file mode 100644
index 0000000..e0d9429
--- /dev/null
+++ b/plugins/a11y-keyboard/Makefile.in
@@ -0,0 +1,809 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = test-a11y-preferences-dialog$(EXEEXT) \
+ $(am__EXEEXT_1)
+subdir = plugins/a11y-keyboard
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" \
+ "$(DESTDIR)$(gtkbuilderdir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+liba11y_keyboard_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_liba11y_keyboard_la_OBJECTS = \
+ liba11y_keyboard_la-gsd-a11y-keyboard-plugin.lo \
+ liba11y_keyboard_la-gsd-a11y-keyboard-manager.lo \
+ liba11y_keyboard_la-gsd-a11y-preferences-dialog.lo \
+ $(am__objects_1)
+liba11y_keyboard_la_OBJECTS = $(am_liba11y_keyboard_la_OBJECTS)
+liba11y_keyboard_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) \
+ $(liba11y_keyboard_la_LDFLAGS) $(LDFLAGS) -o $@
+am__EXEEXT_1 =
+PROGRAMS = $(noinst_PROGRAMS)
+am_test_a11y_preferences_dialog_OBJECTS = test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.$(OBJEXT) \
+ test_a11y_preferences_dialog-test-a11y-preferences-dialog.$(OBJEXT) \
+ $(am__objects_1)
+test_a11y_preferences_dialog_OBJECTS = \
+ $(am_test_a11y_preferences_dialog_OBJECTS)
+test_a11y_preferences_dialog_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+test_a11y_preferences_dialog_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(liba11y_keyboard_la_SOURCES) \
+ $(test_a11y_preferences_dialog_SOURCES)
+DIST_SOURCES = $(liba11y_keyboard_la_SOURCES) \
+ $(test_a11y_preferences_dialog_SOURCES)
+DATA = $(gtkbuilder_DATA) $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+gtkbuilderdir = $(pkgdatadir)
+gtkbuilder_DATA = \
+ gsd-a11y-preferences-dialog.ui \
+ $(NULL)
+
+test_a11y_preferences_dialog_SOURCES = \
+ gsd-a11y-preferences-dialog.c \
+ gsd-a11y-preferences-dialog.h \
+ test-a11y-preferences-dialog.c \
+ $(NULL)
+
+test_a11y_preferences_dialog_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_a11y_preferences_dialog_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_a11y_preferences_dialog_LDADD = \
+ $(SETTINGS_DAEMON_LIBS) \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_LTLIBRARIES = \
+ liba11y-keyboard.la \
+ $(NULL)
+
+liba11y_keyboard_la_SOURCES = \
+ gsd-a11y-keyboard-plugin.h \
+ gsd-a11y-keyboard-plugin.c \
+ gsd-a11y-keyboard-manager.h \
+ gsd-a11y-keyboard-manager.c \
+ gsd-a11y-preferences-dialog.h \
+ gsd-a11y-preferences-dialog.c \
+ $(NULL)
+
+liba11y_keyboard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ -DGTKBUILDERDIR=\""$(gtkbuilderdir)"\" \
+ $(AM_CPPFLAGS)
+
+liba11y_keyboard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(LIBMATENOTIFY_CFLAGS) \
+ $(AM_CFLAGS)
+
+liba11y_keyboard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+liba11y_keyboard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(LIBMATENOTIFY_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ a11y-keyboard.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(gtkbuilder_DATA) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/a11y-keyboard/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/a11y-keyboard/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+liba11y-keyboard.la: $(liba11y_keyboard_la_OBJECTS) $(liba11y_keyboard_la_DEPENDENCIES)
+ $(liba11y_keyboard_la_LINK) -rpath $(plugindir) $(liba11y_keyboard_la_OBJECTS) $(liba11y_keyboard_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+test-a11y-preferences-dialog$(EXEEXT): $(test_a11y_preferences_dialog_OBJECTS) $(test_a11y_preferences_dialog_DEPENDENCIES)
+ @rm -f test-a11y-preferences-dialog$(EXEEXT)
+ $(test_a11y_preferences_dialog_LINK) $(test_a11y_preferences_dialog_OBJECTS) $(test_a11y_preferences_dialog_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liba11y_keyboard_la-gsd-a11y-preferences-dialog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+liba11y_keyboard_la-gsd-a11y-keyboard-plugin.lo: gsd-a11y-keyboard-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liba11y_keyboard_la_CPPFLAGS) $(CPPFLAGS) $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) -MT liba11y_keyboard_la-gsd-a11y-keyboard-plugin.lo -MD -MP -MF $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-plugin.Tpo -c -o liba11y_keyboard_la-gsd-a11y-keyboard-plugin.lo `test -f 'gsd-a11y-keyboard-plugin.c' || echo '$(srcdir)/'`gsd-a11y-keyboard-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-plugin.Tpo $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-a11y-keyboard-plugin.c' object='liba11y_keyboard_la-gsd-a11y-keyboard-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liba11y_keyboard_la_CPPFLAGS) $(CPPFLAGS) $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) -c -o liba11y_keyboard_la-gsd-a11y-keyboard-plugin.lo `test -f 'gsd-a11y-keyboard-plugin.c' || echo '$(srcdir)/'`gsd-a11y-keyboard-plugin.c
+
+liba11y_keyboard_la-gsd-a11y-keyboard-manager.lo: gsd-a11y-keyboard-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liba11y_keyboard_la_CPPFLAGS) $(CPPFLAGS) $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) -MT liba11y_keyboard_la-gsd-a11y-keyboard-manager.lo -MD -MP -MF $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-manager.Tpo -c -o liba11y_keyboard_la-gsd-a11y-keyboard-manager.lo `test -f 'gsd-a11y-keyboard-manager.c' || echo '$(srcdir)/'`gsd-a11y-keyboard-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-manager.Tpo $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-keyboard-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-a11y-keyboard-manager.c' object='liba11y_keyboard_la-gsd-a11y-keyboard-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liba11y_keyboard_la_CPPFLAGS) $(CPPFLAGS) $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) -c -o liba11y_keyboard_la-gsd-a11y-keyboard-manager.lo `test -f 'gsd-a11y-keyboard-manager.c' || echo '$(srcdir)/'`gsd-a11y-keyboard-manager.c
+
+liba11y_keyboard_la-gsd-a11y-preferences-dialog.lo: gsd-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liba11y_keyboard_la_CPPFLAGS) $(CPPFLAGS) $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) -MT liba11y_keyboard_la-gsd-a11y-preferences-dialog.lo -MD -MP -MF $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-preferences-dialog.Tpo -c -o liba11y_keyboard_la-gsd-a11y-preferences-dialog.lo `test -f 'gsd-a11y-preferences-dialog.c' || echo '$(srcdir)/'`gsd-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-preferences-dialog.Tpo $(DEPDIR)/liba11y_keyboard_la-gsd-a11y-preferences-dialog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-a11y-preferences-dialog.c' object='liba11y_keyboard_la-gsd-a11y-preferences-dialog.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liba11y_keyboard_la_CPPFLAGS) $(CPPFLAGS) $(liba11y_keyboard_la_CFLAGS) $(CFLAGS) -c -o liba11y_keyboard_la-gsd-a11y-preferences-dialog.lo `test -f 'gsd-a11y-preferences-dialog.c' || echo '$(srcdir)/'`gsd-a11y-preferences-dialog.c
+
+test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.o: gsd-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -MT test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.o -MD -MP -MF $(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Tpo -c -o test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.o `test -f 'gsd-a11y-preferences-dialog.c' || echo '$(srcdir)/'`gsd-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Tpo $(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-a11y-preferences-dialog.c' object='test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -c -o test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.o `test -f 'gsd-a11y-preferences-dialog.c' || echo '$(srcdir)/'`gsd-a11y-preferences-dialog.c
+
+test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.obj: gsd-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -MT test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.obj -MD -MP -MF $(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Tpo -c -o test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.obj `if test -f 'gsd-a11y-preferences-dialog.c'; then $(CYGPATH_W) 'gsd-a11y-preferences-dialog.c'; else $(CYGPATH_W) '$(srcdir)/gsd-a11y-preferences-dialog.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Tpo $(DEPDIR)/test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-a11y-preferences-dialog.c' object='test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -c -o test_a11y_preferences_dialog-gsd-a11y-preferences-dialog.obj `if test -f 'gsd-a11y-preferences-dialog.c'; then $(CYGPATH_W) 'gsd-a11y-preferences-dialog.c'; else $(CYGPATH_W) '$(srcdir)/gsd-a11y-preferences-dialog.c'; fi`
+
+test_a11y_preferences_dialog-test-a11y-preferences-dialog.o: test-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -MT test_a11y_preferences_dialog-test-a11y-preferences-dialog.o -MD -MP -MF $(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Tpo -c -o test_a11y_preferences_dialog-test-a11y-preferences-dialog.o `test -f 'test-a11y-preferences-dialog.c' || echo '$(srcdir)/'`test-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Tpo $(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-a11y-preferences-dialog.c' object='test_a11y_preferences_dialog-test-a11y-preferences-dialog.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -c -o test_a11y_preferences_dialog-test-a11y-preferences-dialog.o `test -f 'test-a11y-preferences-dialog.c' || echo '$(srcdir)/'`test-a11y-preferences-dialog.c
+
+test_a11y_preferences_dialog-test-a11y-preferences-dialog.obj: test-a11y-preferences-dialog.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -MT test_a11y_preferences_dialog-test-a11y-preferences-dialog.obj -MD -MP -MF $(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Tpo -c -o test_a11y_preferences_dialog-test-a11y-preferences-dialog.obj `if test -f 'test-a11y-preferences-dialog.c'; then $(CYGPATH_W) 'test-a11y-preferences-dialog.c'; else $(CYGPATH_W) '$(srcdir)/test-a11y-preferences-dialog.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Tpo $(DEPDIR)/test_a11y_preferences_dialog-test-a11y-preferences-dialog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-a11y-preferences-dialog.c' object='test_a11y_preferences_dialog-test-a11y-preferences-dialog.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_a11y_preferences_dialog_CPPFLAGS) $(CPPFLAGS) $(test_a11y_preferences_dialog_CFLAGS) $(CFLAGS) -c -o test_a11y_preferences_dialog-test-a11y-preferences-dialog.obj `if test -f 'test-a11y-preferences-dialog.c'; then $(CYGPATH_W) 'test-a11y-preferences-dialog.c'; else $(CYGPATH_W) '$(srcdir)/test-a11y-preferences-dialog.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-gtkbuilderDATA: $(gtkbuilder_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(gtkbuilderdir)" || $(MKDIR_P) "$(DESTDIR)$(gtkbuilderdir)"
+ @list='$(gtkbuilder_DATA)'; test -n "$(gtkbuilderdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gtkbuilderdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(gtkbuilderdir)" || exit $$?; \
+ done
+
+uninstall-gtkbuilderDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gtkbuilder_DATA)'; test -n "$(gtkbuilderdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(gtkbuilderdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(gtkbuilderdir)" && rm -f $$files
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(gtkbuilderdir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-gtkbuilderDATA install-pluginDATA \
+ install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-gtkbuilderDATA uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-gtkbuilderDATA install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-gtkbuilderDATA uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/a11y-keyboard/a11y-keyboard.mate-settings-plugin.in b/plugins/a11y-keyboard/a11y-keyboard.mate-settings-plugin.in
new file mode 100644
index 0000000..4909948
--- /dev/null
+++ b/plugins/a11y-keyboard/a11y-keyboard.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=a11y-keyboard
+IAge=0
+_Name=Accessibility Keyboard
+_Description=Accessibility keyboard plugin
+Authors=Jody Goldberg
+Copyright=Copyright © 2001 Ximian, Inc.
+Website=
diff --git a/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c b/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c
new file mode 100644
index 0000000..ac75491
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c
@@ -0,0 +1,1347 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2001 Ximian, Inc.
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBstr.h>
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XIproto.h>
+#endif
+
+#ifdef HAVE_LIBMATENOTIFY
+#include <libmatenotify/notify.h>
+#endif /* HAVE_LIBMATENOTIFY */
+
+#include "mate-settings-profile.h"
+#include "gsd-a11y-keyboard-manager.h"
+#include "gsd-a11y-preferences-dialog.h"
+
+#define CONFIG_ROOT "/desktop/mate/accessibility/keyboard"
+#define NOTIFICATION_TIMEOUT 30
+
+#define GSD_A11Y_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManagerPrivate))
+
+struct GsdA11yKeyboardManagerPrivate
+{
+ int xkbEventBase;
+ gboolean stickykeys_shortcut_val;
+ gboolean slowkeys_shortcut_val;
+ GtkWidget *stickykeys_alert;
+ GtkWidget *slowkeys_alert;
+ GtkWidget *preferences_dialog;
+ GtkStatusIcon *status_icon;
+ XkbDescRec *original_xkb_desc;
+
+ guint mateconf_notify;
+
+#ifdef HAVE_LIBMATENOTIFY
+ NotifyNotification *notification;
+#endif /* HAVE_LIBMATENOTIFY */
+};
+
+static void gsd_a11y_keyboard_manager_class_init (GsdA11yKeyboardManagerClass *klass);
+static void gsd_a11y_keyboard_manager_init (GsdA11yKeyboardManager *a11y_keyboard_manager);
+static void gsd_a11y_keyboard_manager_finalize (GObject *object);
+static void gsd_a11y_keyboard_manager_ensure_status_icon (GsdA11yKeyboardManager *manager);
+static void set_server_from_mateconf (GsdA11yKeyboardManager *manager,
+ MateConfClient *client);
+
+G_DEFINE_TYPE (GsdA11yKeyboardManager, gsd_a11y_keyboard_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+#undef DEBUG_ACCESSIBILITY
+#ifdef DEBUG_ACCESSIBILITY
+#define d(str) g_debug (str)
+#else
+#define d(str) do { } while (0)
+#endif
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+static GdkFilterReturn
+devicepresence_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xev = (XEvent *) xevent;
+ XEventClass class_presence;
+ int xi_presence;
+
+ DevicePresence (gdk_x11_get_default_xdisplay (), xi_presence, class_presence);
+
+ if (xev->type == xi_presence)
+ {
+ XDevicePresenceNotifyEvent *dpn = (XDevicePresenceNotifyEvent *) xev;
+ if (dpn->devchange == DeviceEnabled) {
+ MateConfClient *client;
+ client = mateconf_client_get_default ();
+ set_server_from_mateconf (data, client);
+ g_object_unref (client);
+ }
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+supports_xinput_devices (void)
+{
+ gint op_code, event, error;
+
+ return XQueryExtension (GDK_DISPLAY (),
+ "XInputExtension",
+ &op_code,
+ &event,
+ &error);
+}
+
+static void
+set_devicepresence_handler (GsdA11yKeyboardManager *manager)
+{
+ Display *display;
+ XEventClass class_presence;
+ int xi_presence;
+
+ if (!supports_xinput_devices ())
+ return;
+
+ display = gdk_x11_get_default_xdisplay ();
+
+ gdk_error_trap_push ();
+ DevicePresence (display, xi_presence, class_presence);
+ /* FIXME:
+ * Note that this might overwrite other events, see:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=610245#c2
+ **/
+ XSelectExtensionEvent (display,
+ RootWindow (display, DefaultScreen (display)),
+ &class_presence, 1);
+
+ gdk_flush ();
+ if (!gdk_error_trap_pop ())
+ gdk_window_add_filter (NULL, devicepresence_filter, manager);
+}
+#endif
+
+static gboolean
+xkb_enabled (GsdA11yKeyboardManager *manager)
+{
+ gboolean have_xkb;
+ int opcode, errorBase, major, minor;
+
+ have_xkb = XkbQueryExtension (GDK_DISPLAY (),
+ &opcode,
+ &manager->priv->xkbEventBase,
+ &errorBase,
+ &major,
+ &minor)
+ && XkbUseExtension (GDK_DISPLAY (), &major, &minor);
+
+ return have_xkb;
+}
+
+static XkbDescRec *
+get_xkb_desc_rec (GsdA11yKeyboardManager *manager)
+{
+ XkbDescRec *desc;
+ Status status = Success;
+
+ gdk_error_trap_push ();
+ desc = XkbGetMap (GDK_DISPLAY (), XkbAllMapComponentsMask, XkbUseCoreKbd);
+ if (desc != NULL) {
+ desc->ctrls = NULL;
+ status = XkbGetControls (GDK_DISPLAY (), XkbAllControlsMask, desc);
+ }
+ gdk_error_trap_pop ();
+
+ g_return_val_if_fail (desc != NULL, NULL);
+ g_return_val_if_fail (desc->ctrls != NULL, NULL);
+ g_return_val_if_fail (status == Success, NULL);
+
+ return desc;
+}
+
+static int
+get_int (MateConfClient *client,
+ char const *key)
+{
+ int res = mateconf_client_get_int (client, key, NULL);
+ if (res <= 0) {
+ res = 1;
+ }
+ return res;
+}
+
+static gboolean
+set_int (MateConfClient *client,
+ MateConfChangeSet *cs,
+ char const *key,
+ int val)
+{
+ mateconf_change_set_set_int (cs, key, val);
+#ifdef DEBUG_ACCESSIBILITY
+ if (val != mateconf_client_get_int (client, key, NULL)) {
+ g_warning ("%s changed", key);
+ }
+#endif
+ return val != mateconf_client_get_int (client, key, NULL);
+}
+
+static gboolean
+set_bool (MateConfClient *client,
+ MateConfChangeSet *cs,
+ char const *key,
+ int val)
+{
+ gboolean bval = (val != 0);
+
+ mateconf_change_set_set_bool (cs, key, bval ? TRUE : FALSE);
+#ifdef DEBUG_ACCESSIBILITY
+ if (bval != mateconf_client_get_bool (client, key, NULL)) {
+ d ("%s changed", key);
+ return TRUE;
+ }
+#endif
+ return (bval != mateconf_client_get_bool (client, key, NULL));
+}
+
+static unsigned long
+set_clear (gboolean flag,
+ unsigned long value,
+ unsigned long mask)
+{
+ if (flag) {
+ return value | mask;
+ }
+ return value & ~mask;
+}
+
+static gboolean
+set_ctrl_from_mateconf (XkbDescRec *desc,
+ MateConfClient *client,
+ char const *key,
+ unsigned long mask)
+{
+ gboolean result = mateconf_client_get_bool (client, key, NULL);
+ desc->ctrls->enabled_ctrls = set_clear (result, desc->ctrls->enabled_ctrls, mask);
+ return result;
+}
+
+static void
+set_server_from_mateconf (GsdA11yKeyboardManager *manager,
+ MateConfClient *client)
+{
+ XkbDescRec *desc;
+ gboolean enable_accessX;
+
+ mate_settings_profile_start (NULL);
+
+ desc = get_xkb_desc_rec (manager);
+ if (!desc) {
+ return;
+ }
+
+ /* general */
+ enable_accessX = mateconf_client_get_bool (client, CONFIG_ROOT "/enable", NULL);
+
+ desc->ctrls->enabled_ctrls = set_clear (enable_accessX,
+ desc->ctrls->enabled_ctrls,
+ XkbAccessXKeysMask);
+
+ if (set_ctrl_from_mateconf (desc, client, CONFIG_ROOT "/timeout_enable",
+ XkbAccessXTimeoutMask)) {
+ desc->ctrls->ax_timeout = get_int (client,
+ CONFIG_ROOT "/timeout");
+ /* disable only the master flag via the server we will disable
+ * the rest on the rebound without affecting mateconf state
+ * don't change the option flags at all.
+ */
+ desc->ctrls->axt_ctrls_mask = XkbAccessXKeysMask | XkbAccessXFeedbackMask;
+ desc->ctrls->axt_ctrls_values = 0;
+ desc->ctrls->axt_opts_mask = 0;
+ }
+
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/feature_state_change_beep", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask);
+
+ /* bounce keys */
+ if (set_ctrl_from_mateconf (desc,
+ client,
+ CONFIG_ROOT "/bouncekeys_enable",
+ XkbBounceKeysMask)) {
+ desc->ctrls->debounce_delay = get_int (client,
+ CONFIG_ROOT "/bouncekeys_delay");
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/bouncekeys_beep_reject", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_BKRejectFBMask);
+ }
+
+ /* mouse keys */
+ if (set_ctrl_from_mateconf (desc,
+ client,
+ CONFIG_ROOT "/mousekeys_enable",
+ XkbMouseKeysMask | XkbMouseKeysAccelMask)) {
+ desc->ctrls->mk_interval = 100; /* msec between mousekey events */
+ desc->ctrls->mk_curve = 50;
+
+ /* We store pixels / sec, XKB wants pixels / event */
+ desc->ctrls->mk_max_speed = get_int (client,
+ CONFIG_ROOT "/mousekeys_max_speed") / (1000 / desc->ctrls->mk_interval);
+ if (desc->ctrls->mk_max_speed <= 0)
+ desc->ctrls->mk_max_speed = 1;
+
+ desc->ctrls->mk_time_to_max = get_int (client, /* events before max */
+ CONFIG_ROOT "/mousekeys_accel_time") / desc->ctrls->mk_interval;
+ if (desc->ctrls->mk_time_to_max <= 0)
+ desc->ctrls->mk_time_to_max = 1;
+
+ desc->ctrls->mk_delay = get_int (client, /* ms before 1st event */
+ CONFIG_ROOT "/mousekeys_init_delay");
+ }
+
+ /* slow keys */
+ if (set_ctrl_from_mateconf (desc,
+ client,
+ CONFIG_ROOT "/slowkeys_enable",
+ XkbSlowKeysMask)) {
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/slowkeys_beep_press", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_SKPressFBMask);
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/slowkeys_beep_accept", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_SKAcceptFBMask);
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/slowkeys_beep_reject", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_SKRejectFBMask);
+ desc->ctrls->slow_keys_delay = get_int (client,
+ CONFIG_ROOT "/slowkeys_delay");
+ /* anything larger than 500 seems to loose all keyboard input */
+ if (desc->ctrls->slow_keys_delay > 500)
+ desc->ctrls->slow_keys_delay = 500;
+ }
+
+ /* sticky keys */
+ if (set_ctrl_from_mateconf (desc,
+ client,
+ CONFIG_ROOT "/stickykeys_enable",
+ XkbStickyKeysMask)) {
+ desc->ctrls->ax_options |= XkbAX_LatchToLockMask;
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/stickykeys_two_key_off", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_TwoKeysMask);
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/stickykeys_modifier_beep", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_StickyKeysFBMask);
+ }
+
+ /* toggle keys */
+ desc->ctrls->ax_options = set_clear (mateconf_client_get_bool (client, CONFIG_ROOT "/togglekeys_enable", NULL),
+ desc->ctrls->ax_options,
+ XkbAccessXFeedbackMask | XkbAX_IndicatorFBMask);
+
+ /*
+ g_debug ("CHANGE to : 0x%x", desc->ctrls->enabled_ctrls);
+ g_debug ("CHANGE to : 0x%x (2)", desc->ctrls->ax_options);
+ */
+
+ gdk_error_trap_push ();
+ XkbSetControls (GDK_DISPLAY (),
+ XkbSlowKeysMask |
+ XkbBounceKeysMask |
+ XkbStickyKeysMask |
+ XkbMouseKeysMask |
+ XkbMouseKeysAccelMask |
+ XkbAccessXKeysMask |
+ XkbAccessXTimeoutMask |
+ XkbAccessXFeedbackMask |
+ XkbControlsEnabledMask,
+ desc);
+
+ XkbFreeKeyboard (desc, XkbAllComponentsMask, True);
+
+ XSync (GDK_DISPLAY (), FALSE);
+ gdk_error_trap_pop ();
+
+ mate_settings_profile_end (NULL);
+}
+
+static gboolean
+ax_response_callback (GsdA11yKeyboardManager *manager,
+ GtkWindow *parent,
+ gint response_id,
+ guint revert_controls_mask,
+ gboolean enabled)
+{
+ MateConfClient *client;
+ GdkScreen *screen;
+ GError *err;
+
+ switch (response_id) {
+ case GTK_RESPONSE_DELETE_EVENT:
+ case GTK_RESPONSE_REJECT:
+ case GTK_RESPONSE_CANCEL:
+
+ client = mateconf_client_get_default ();
+
+ /* we're reverting, so we invert sense of 'enabled' flag */
+ d ("cancelling AccessX request");
+ if (revert_controls_mask == XkbStickyKeysMask) {
+ mateconf_client_set_bool (client,
+ CONFIG_ROOT "/stickykeys_enable",
+ !enabled,
+ NULL);
+ }
+ else if (revert_controls_mask == XkbSlowKeysMask) {
+ mateconf_client_set_bool (client,
+ CONFIG_ROOT "/slowkeys_enable",
+ !enabled,
+ NULL);
+ }
+ mateconf_client_suggest_sync (client, NULL);
+ set_server_from_mateconf (manager, client);
+
+ g_object_unref (client);
+
+ break;
+
+ case GTK_RESPONSE_HELP:
+ if (!parent)
+ screen = gdk_screen_get_default ();
+ else
+ screen = gtk_widget_get_screen (GTK_WIDGET (parent));
+
+ err = NULL;
+ if (!gtk_show_uri (screen,
+ "ghelp:user-guide#goscustaccess-6",
+ gtk_get_current_event_time(),
+ &err)) {
+ GtkWidget *error_dialog = gtk_message_dialog_new (parent,
+ 0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("There was an error displaying help: %s"),
+ err->message);
+ g_signal_connect (error_dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE);
+ gtk_widget_show (error_dialog);
+ g_error_free (err);
+ }
+ return FALSE;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+static void
+ax_stickykeys_response (GtkDialog *dialog,
+ gint response_id,
+ GsdA11yKeyboardManager *manager)
+{
+ if (ax_response_callback (manager, GTK_WINDOW (dialog),
+ response_id, XkbStickyKeysMask,
+ manager->priv->stickykeys_shortcut_val)) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+}
+
+static void
+ax_slowkeys_response (GtkDialog *dialog,
+ gint response_id,
+ GsdA11yKeyboardManager *manager)
+{
+ if (ax_response_callback (manager, GTK_WINDOW (dialog),
+ response_id, XkbSlowKeysMask,
+ manager->priv->slowkeys_shortcut_val)) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+}
+
+static void
+maybe_show_status_icon (GsdA11yKeyboardManager *manager)
+{
+ gboolean show;
+ MateConfClient *client;
+
+ /* for now, show if accessx is enabled */
+ client = mateconf_client_get_default ();
+ show = mateconf_client_get_bool (client, CONFIG_ROOT "/enable", NULL);
+ g_object_unref (client);
+
+ if (!show && manager->priv->status_icon == NULL)
+ return;
+
+ gsd_a11y_keyboard_manager_ensure_status_icon (manager);
+ gtk_status_icon_set_visible (manager->priv->status_icon, show);
+}
+
+#ifdef HAVE_LIBMATENOTIFY
+static void
+on_notification_closed (NotifyNotification *notification,
+ GsdA11yKeyboardManager *manager)
+{
+ g_object_unref (manager->priv->notification);
+ manager->priv->notification = NULL;
+}
+
+static void
+on_slow_keys_action (NotifyNotification *notification,
+ const char *action,
+ GsdA11yKeyboardManager *manager)
+{
+ gboolean res;
+ int response_id;
+
+ g_assert (action != NULL);
+
+ if (strcmp (action, "accept") == 0) {
+ response_id = GTK_RESPONSE_ACCEPT;
+ } else if (strcmp (action, "reject") == 0) {
+ response_id = GTK_RESPONSE_REJECT;
+ } else {
+ return;
+ }
+
+ res = ax_response_callback (manager, NULL,
+ response_id, XkbSlowKeysMask,
+ manager->priv->slowkeys_shortcut_val);
+ if (res) {
+ notify_notification_close (manager->priv->notification, NULL);
+ }
+}
+
+static void
+on_sticky_keys_action (NotifyNotification *notification,
+ const char *action,
+ GsdA11yKeyboardManager *manager)
+{
+ gboolean res;
+ int response_id;
+
+ g_assert (action != NULL);
+
+ if (strcmp (action, "accept") == 0) {
+ response_id = GTK_RESPONSE_ACCEPT;
+ } else if (strcmp (action, "reject") == 0) {
+ response_id = GTK_RESPONSE_REJECT;
+ } else {
+ return;
+ }
+
+ res = ax_response_callback (manager, NULL,
+ response_id, XkbStickyKeysMask,
+ manager->priv->stickykeys_shortcut_val);
+ if (res) {
+ notify_notification_close (manager->priv->notification, NULL);
+ }
+}
+
+#endif /* HAVE_LIBMATENOTIFY */
+
+static gboolean
+ax_slowkeys_warning_post_bubble (GsdA11yKeyboardManager *manager,
+ gboolean enabled)
+{
+#ifdef HAVE_LIBMATENOTIFY
+ gboolean res;
+ const char *title;
+ const char *message;
+ GError *error;
+
+ title = enabled ?
+ _("Do you want to activate Slow Keys?") :
+ _("Do you want to deactivate Slow Keys?");
+ message = _("You just held down the Shift key for 8 seconds. This is the shortcut "
+ "for the Slow Keys feature, which affects the way your keyboard works.");
+
+ if (manager->priv->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->priv->status_icon)) {
+ return FALSE;
+ }
+
+ if (manager->priv->slowkeys_alert != NULL) {
+ gtk_widget_destroy (manager->priv->slowkeys_alert);
+ }
+
+ if (manager->priv->notification != NULL) {
+ notify_notification_close (manager->priv->notification, NULL);
+ }
+
+ gsd_a11y_keyboard_manager_ensure_status_icon (manager);
+ manager->priv->notification = notify_notification_new (title,
+ message,
+ "preferences-desktop-accessibility",
+ NULL);
+ notify_notification_attach_to_status_icon (manager->priv->notification, manager->priv->status_icon);
+ notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000);
+
+ notify_notification_add_action (manager->priv->notification,
+ "reject",
+ enabled ? _("Don't activate") : _("Don't deactivate"),
+ (NotifyActionCallback) on_slow_keys_action,
+ manager,
+ NULL);
+ notify_notification_add_action (manager->priv->notification,
+ "accept",
+ enabled ? _("Activate") : _("Deactivate"),
+ (NotifyActionCallback) on_slow_keys_action,
+ manager,
+ NULL);
+
+ g_signal_connect (manager->priv->notification,
+ "closed",
+ G_CALLBACK (on_notification_closed),
+ manager);
+
+ error = NULL;
+ res = notify_notification_show (manager->priv->notification, &error);
+ if (! res) {
+ g_warning ("GsdA11yKeyboardManager: unable to show notification: %s", error->message);
+ g_error_free (error);
+ notify_notification_close (manager->priv->notification, NULL);
+ }
+
+ return res;
+#else
+ return FALSE;
+#endif /* HAVE_LIBMATENOTIFY */
+}
+
+
+static void
+ax_slowkeys_warning_post_dialog (GsdA11yKeyboardManager *manager,
+ gboolean enabled)
+{
+ const char *title;
+ const char *message;
+
+ title = enabled ?
+ _("Do you want to activate Slow Keys?") :
+ _("Do you want to deactivate Slow Keys?");
+ message = _("You just held down the Shift key for 8 seconds. This is the shortcut "
+ "for the Slow Keys feature, which affects the way your keyboard works.");
+
+ if (manager->priv->slowkeys_alert != NULL) {
+ gtk_widget_show (manager->priv->slowkeys_alert);
+ return;
+ }
+
+ manager->priv->slowkeys_alert = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "%s", title);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (manager->priv->slowkeys_alert),
+ "%s", message);
+
+ gtk_dialog_add_button (GTK_DIALOG (manager->priv->slowkeys_alert),
+ GTK_STOCK_HELP,
+ GTK_RESPONSE_HELP);
+ gtk_dialog_add_button (GTK_DIALOG (manager->priv->slowkeys_alert),
+ enabled ? _("Do_n't activate") : _("Do_n't deactivate"),
+ GTK_RESPONSE_REJECT);
+ gtk_dialog_add_button (GTK_DIALOG (manager->priv->slowkeys_alert),
+ enabled ? _("_Activate") : _("_Deactivate"),
+ GTK_RESPONSE_ACCEPT);
+
+ gtk_window_set_title (GTK_WINDOW (manager->priv->slowkeys_alert),
+ _("Slow Keys Alert"));
+ gtk_window_set_icon_name (GTK_WINDOW (manager->priv->slowkeys_alert),
+ "input-keyboard");
+ gtk_dialog_set_default_response (GTK_DIALOG (manager->priv->slowkeys_alert),
+ GTK_RESPONSE_ACCEPT);
+
+ g_signal_connect (manager->priv->slowkeys_alert,
+ "response",
+ G_CALLBACK (ax_slowkeys_response),
+ manager);
+ gtk_widget_show (manager->priv->slowkeys_alert);
+
+ g_object_add_weak_pointer (G_OBJECT (manager->priv->slowkeys_alert),
+ (gpointer*) &manager->priv->slowkeys_alert);
+}
+
+static void
+ax_slowkeys_warning_post (GsdA11yKeyboardManager *manager,
+ gboolean enabled)
+{
+
+ manager->priv->slowkeys_shortcut_val = enabled;
+
+ /* alway try to show something */
+ if (! ax_slowkeys_warning_post_bubble (manager, enabled)) {
+ ax_slowkeys_warning_post_dialog (manager, enabled);
+ }
+}
+
+static gboolean
+ax_stickykeys_warning_post_bubble (GsdA11yKeyboardManager *manager,
+ gboolean enabled)
+{
+#ifdef HAVE_LIBMATENOTIFY
+ gboolean res;
+ const char *title;
+ const char *message;
+ GError *error;
+
+ title = enabled ?
+ _("Do you want to activate Sticky Keys?") :
+ _("Do you want to deactivate Sticky Keys?");
+ message = enabled ?
+ _("You just pressed the Shift key 5 times in a row. This is the shortcut "
+ "for the Sticky Keys feature, which affects the way your keyboard works.") :
+ _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. "
+ "This turns off the Sticky Keys feature, which affects the way your keyboard works.");
+
+ if (manager->priv->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->priv->status_icon)) {
+ return FALSE;
+ }
+
+ if (manager->priv->slowkeys_alert != NULL) {
+ gtk_widget_destroy (manager->priv->slowkeys_alert);
+ }
+
+ if (manager->priv->notification != NULL) {
+ notify_notification_close (manager->priv->notification, NULL);
+ }
+
+ gsd_a11y_keyboard_manager_ensure_status_icon (manager);
+ manager->priv->notification = notify_notification_new (title,
+ message,
+ "preferences-desktop-accessibility",
+ NULL);
+ notify_notification_attach_to_status_icon (manager->priv->notification, manager->priv->status_icon);
+ notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000);
+
+ notify_notification_add_action (manager->priv->notification,
+ "reject",
+ enabled ? _("Don't activate") : _("Don't deactivate"),
+ (NotifyActionCallback) on_sticky_keys_action,
+ manager,
+ NULL);
+ notify_notification_add_action (manager->priv->notification,
+ "accept",
+ enabled ? _("Activate") : _("Deactivate"),
+ (NotifyActionCallback) on_sticky_keys_action,
+ manager,
+ NULL);
+
+ g_signal_connect (manager->priv->notification,
+ "closed",
+ G_CALLBACK (on_notification_closed),
+ manager);
+
+ error = NULL;
+ res = notify_notification_show (manager->priv->notification, &error);
+ if (! res) {
+ g_warning ("GsdA11yKeyboardManager: unable to show notification: %s", error->message);
+ g_error_free (error);
+ notify_notification_close (manager->priv->notification, NULL);
+ }
+
+ return res;
+#else
+ return FALSE;
+#endif /* HAVE_LIBMATENOTIFY */
+}
+
+static void
+ax_stickykeys_warning_post_dialog (GsdA11yKeyboardManager *manager,
+ gboolean enabled)
+{
+ const char *title;
+ const char *message;
+
+ title = enabled ?
+ _("Do you want to activate Sticky Keys?") :
+ _("Do you want to deactivate Sticky Keys?");
+ message = enabled ?
+ _("You just pressed the Shift key 5 times in a row. This is the shortcut "
+ "for the Sticky Keys feature, which affects the way your keyboard works.") :
+ _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. "
+ "This turns off the Sticky Keys feature, which affects the way your keyboard works.");
+
+ if (manager->priv->stickykeys_alert != NULL) {
+ gtk_widget_show (manager->priv->stickykeys_alert);
+ return;
+ }
+
+ manager->priv->stickykeys_alert = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "%s", title);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (manager->priv->stickykeys_alert),
+ "%s", message);
+
+ gtk_dialog_add_button (GTK_DIALOG (manager->priv->stickykeys_alert),
+ GTK_STOCK_HELP,
+ GTK_RESPONSE_HELP);
+ gtk_dialog_add_button (GTK_DIALOG (manager->priv->stickykeys_alert),
+ enabled ? _("Do_n't activate") : _("Do_n't deactivate"),
+ GTK_RESPONSE_REJECT);
+ gtk_dialog_add_button (GTK_DIALOG (manager->priv->stickykeys_alert),
+ enabled ? _("_Activate") : _("_Deactivate"),
+ GTK_RESPONSE_ACCEPT);
+
+ gtk_window_set_title (GTK_WINDOW (manager->priv->stickykeys_alert),
+ _("Sticky Keys Alert"));
+ gtk_window_set_icon_name (GTK_WINDOW (manager->priv->stickykeys_alert),
+ "input-keyboard");
+ gtk_dialog_set_default_response (GTK_DIALOG (manager->priv->stickykeys_alert),
+ GTK_RESPONSE_ACCEPT);
+
+ g_signal_connect (manager->priv->stickykeys_alert,
+ "response",
+ G_CALLBACK (ax_stickykeys_response),
+ manager);
+ gtk_widget_show (manager->priv->stickykeys_alert);
+
+ g_object_add_weak_pointer (G_OBJECT (manager->priv->stickykeys_alert),
+ (gpointer*) &manager->priv->stickykeys_alert);
+}
+
+static void
+ax_stickykeys_warning_post (GsdA11yKeyboardManager *manager,
+ gboolean enabled)
+{
+
+ manager->priv->stickykeys_shortcut_val = enabled;
+
+ /* alway try to show something */
+ if (! ax_stickykeys_warning_post_bubble (manager, enabled)) {
+ ax_stickykeys_warning_post_dialog (manager, enabled);
+ }
+}
+
+static void
+set_mateconf_from_server (GsdA11yKeyboardManager *manager)
+{
+ MateConfClient *client;
+ MateConfChangeSet *cs;
+ XkbDescRec *desc;
+ gboolean changed = FALSE;
+ gboolean slowkeys_changed;
+ gboolean stickykeys_changed;
+
+ cs = mateconf_change_set_new ();
+ desc = get_xkb_desc_rec (manager);
+ if (! desc) {
+ return;
+ }
+
+ client = mateconf_client_get_default ();
+
+ /*
+ fprintf (stderr, "changed to : 0x%x\n", desc->ctrls->enabled_ctrls);
+ fprintf (stderr, "changed to : 0x%x (2)\n", desc->ctrls->ax_options);
+ */
+
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/enable",
+ desc->ctrls->enabled_ctrls & XkbAccessXKeysMask);
+
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/feature_state_change_beep",
+ desc->ctrls->ax_options & (XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask));
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/timeout_enable",
+ desc->ctrls->enabled_ctrls & XkbAccessXTimeoutMask);
+ changed |= set_int (client,
+ cs,
+ CONFIG_ROOT "/timeout",
+ desc->ctrls->ax_timeout);
+
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/bouncekeys_enable",
+ desc->ctrls->enabled_ctrls & XkbBounceKeysMask);
+ changed |= set_int (client,
+ cs,
+ CONFIG_ROOT "/bouncekeys_delay",
+ desc->ctrls->debounce_delay);
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/bouncekeys_beep_reject",
+ desc->ctrls->ax_options & XkbAX_BKRejectFBMask);
+
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/mousekeys_enable",
+ desc->ctrls->enabled_ctrls & XkbMouseKeysMask);
+ changed |= set_int (client,
+ cs,
+ CONFIG_ROOT "/mousekeys_max_speed",
+ desc->ctrls->mk_max_speed * (1000 / desc->ctrls->mk_interval));
+ /* NOTE : mk_time_to_max is measured in events not time */
+ changed |= set_int (client,
+ cs,
+ CONFIG_ROOT "/mousekeys_accel_time",
+ desc->ctrls->mk_time_to_max * desc->ctrls->mk_interval);
+ changed |= set_int (client,
+ cs,
+ CONFIG_ROOT "/mousekeys_init_delay",
+ desc->ctrls->mk_delay);
+
+ slowkeys_changed = set_bool (client,
+ cs,
+ CONFIG_ROOT "/slowkeys_enable",
+ desc->ctrls->enabled_ctrls & XkbSlowKeysMask);
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/slowkeys_beep_press",
+ desc->ctrls->ax_options & XkbAX_SKPressFBMask);
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/slowkeys_beep_accept",
+ desc->ctrls->ax_options & XkbAX_SKAcceptFBMask);
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/slowkeys_beep_reject",
+ desc->ctrls->ax_options & XkbAX_SKRejectFBMask);
+ changed |= set_int (client,
+ cs,
+ CONFIG_ROOT "/slowkeys_delay",
+ desc->ctrls->slow_keys_delay);
+
+ stickykeys_changed = set_bool (client,
+ cs,
+ CONFIG_ROOT "/stickykeys_enable",
+ desc->ctrls->enabled_ctrls & XkbStickyKeysMask);
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/stickykeys_two_key_off",
+ desc->ctrls->ax_options & XkbAX_TwoKeysMask);
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/stickykeys_modifier_beep",
+ desc->ctrls->ax_options & XkbAX_StickyKeysFBMask);
+
+ changed |= set_bool (client,
+ cs,
+ CONFIG_ROOT "/togglekeys_enable",
+ desc->ctrls->ax_options & XkbAX_IndicatorFBMask);
+
+ if (!changed && stickykeys_changed ^ slowkeys_changed) {
+ /*
+ * sticky or slowkeys has changed, singly, without our intervention.
+ * 99% chance this is due to a keyboard shortcut being used.
+ * we need to detect via this hack until we get
+ * XkbAXN_AXKWarning notifications working (probable XKB bug),
+ * at which time we can directly intercept such shortcuts instead.
+ * See cb_xkb_event_filter () below.
+ */
+
+ /* sanity check: are keyboard shortcuts available? */
+ if (desc->ctrls->enabled_ctrls & XkbAccessXKeysMask) {
+ if (slowkeys_changed) {
+ ax_slowkeys_warning_post (manager,
+ desc->ctrls->enabled_ctrls & XkbSlowKeysMask);
+ } else {
+ ax_stickykeys_warning_post (manager,
+ desc->ctrls->enabled_ctrls & XkbStickyKeysMask);
+ }
+ }
+ }
+
+ XkbFreeKeyboard (desc, XkbAllComponentsMask, True);
+
+ changed |= (stickykeys_changed | slowkeys_changed);
+
+ if (changed) {
+ mateconf_client_commit_change_set (client, cs, FALSE, NULL);
+ mateconf_client_suggest_sync (client, NULL);
+ }
+ mateconf_change_set_unref (cs);
+
+ g_object_unref (client);
+}
+
+static GdkFilterReturn
+cb_xkb_event_filter (GdkXEvent *xevent,
+ GdkEvent *ignored1,
+ GsdA11yKeyboardManager *manager)
+{
+ XEvent *xev = (XEvent *) xevent;
+ XkbEvent *xkbEv = (XkbEvent *) xevent;
+
+ if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) &&
+ xkbEv->any.xkb_type == XkbControlsNotify) {
+ d ("XKB state changed");
+ set_mateconf_from_server (manager);
+ } else if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) &&
+ xkbEv->any.xkb_type == XkbAccessXNotify) {
+ if (xkbEv->accessx.detail == XkbAXN_AXKWarning) {
+ d ("About to turn on an AccessX feature from the keyboard!");
+ /*
+ * TODO: when XkbAXN_AXKWarnings start working, we need to
+ * invoke ax_keys_warning_dialog_run here instead of in
+ * set_mateconf_from_server().
+ */
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+keyboard_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdA11yKeyboardManager *manager)
+{
+ set_server_from_mateconf (manager, client);
+ maybe_show_status_icon (manager);
+}
+
+static void
+register_config_callback (GsdA11yKeyboardManager *manager,
+ MateConfClient *client,
+ const char *path,
+ MateConfClientNotifyFunc func,
+ guint *notify)
+{
+ mateconf_client_add_dir (client, path, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ *notify = mateconf_client_notify_add (client, path, func, manager, NULL, NULL);
+}
+
+static gboolean
+start_a11y_keyboard_idle_cb (GsdA11yKeyboardManager *manager)
+{
+ guint event_mask;
+ MateConfClient *client;
+
+ g_debug ("Starting a11y_keyboard manager");
+ mate_settings_profile_start (NULL);
+
+ if (!xkb_enabled (manager))
+ goto out;
+
+ client = mateconf_client_get_default ();
+
+ register_config_callback (manager,
+ client,
+ CONFIG_ROOT,
+ (MateConfClientNotifyFunc) keyboard_callback,
+ &manager->priv->mateconf_notify);
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ set_devicepresence_handler (manager);
+#endif
+
+ /* Save current xkb state so we can restore it on exit
+ */
+ manager->priv->original_xkb_desc = get_xkb_desc_rec (manager);
+
+ event_mask = XkbControlsNotifyMask;
+#ifdef DEBUG_ACCESSIBILITY
+ event_mask |= XkbAccessXNotifyMask; /* make default when AXN_AXKWarning works */
+#endif
+
+ /* be sure to init before starting to monitor the server */
+ set_server_from_mateconf (manager, client);
+ g_object_unref (client);
+
+ XkbSelectEvents (GDK_DISPLAY (),
+ XkbUseCoreKbd,
+ event_mask,
+ event_mask);
+
+ gdk_window_add_filter (NULL,
+ (GdkFilterFunc) cb_xkb_event_filter,
+ manager);
+
+ maybe_show_status_icon (manager);
+
+ out:
+ mate_settings_profile_end (NULL);
+
+ return FALSE;
+}
+
+
+gboolean
+gsd_a11y_keyboard_manager_start (GsdA11yKeyboardManager *manager,
+ GError **error)
+{
+ mate_settings_profile_start (NULL);
+
+ g_idle_add ((GSourceFunc) start_a11y_keyboard_idle_cb, manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+static void
+restore_server_xkb_config (GsdA11yKeyboardManager *manager)
+{
+ gdk_error_trap_push ();
+ XkbSetControls (GDK_DISPLAY (),
+ XkbSlowKeysMask |
+ XkbBounceKeysMask |
+ XkbStickyKeysMask |
+ XkbMouseKeysMask |
+ XkbMouseKeysAccelMask |
+ XkbAccessXKeysMask |
+ XkbAccessXTimeoutMask |
+ XkbAccessXFeedbackMask |
+ XkbControlsEnabledMask,
+ manager->priv->original_xkb_desc);
+
+ XkbFreeKeyboard (manager->priv->original_xkb_desc,
+ XkbAllComponentsMask, True);
+
+ XSync (GDK_DISPLAY (), FALSE);
+ gdk_error_trap_pop ();
+
+ manager->priv->original_xkb_desc = NULL;
+}
+
+void
+gsd_a11y_keyboard_manager_stop (GsdA11yKeyboardManager *manager)
+{
+ GsdA11yKeyboardManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping a11y_keyboard manager");
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ gdk_window_remove_filter (NULL, devicepresence_filter, manager);
+#endif
+
+ if (p->status_icon)
+ gtk_status_icon_set_visible (p->status_icon, FALSE);
+
+ if (p->mateconf_notify != 0) {
+ MateConfClient *client = mateconf_client_get_default ();
+ mateconf_client_remove_dir (client, CONFIG_ROOT, NULL);
+ mateconf_client_notify_remove (client, p->mateconf_notify);
+ g_object_unref (client);
+ p->mateconf_notify = 0;
+ }
+
+ gdk_window_remove_filter (NULL,
+ (GdkFilterFunc) cb_xkb_event_filter,
+ manager);
+
+ /* Disable all the AccessX bits
+ */
+ restore_server_xkb_config (manager);
+
+ if (p->slowkeys_alert != NULL)
+ gtk_widget_destroy (p->slowkeys_alert);
+
+ if (p->stickykeys_alert != NULL)
+ gtk_widget_destroy (p->stickykeys_alert);
+
+ p->slowkeys_shortcut_val = FALSE;
+ p->stickykeys_shortcut_val = FALSE;
+}
+
+static void
+gsd_a11y_keyboard_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdA11yKeyboardManager *self;
+
+ self = GSD_A11Y_KEYBOARD_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_a11y_keyboard_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdA11yKeyboardManager *self;
+
+ self = GSD_A11Y_KEYBOARD_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_a11y_keyboard_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdA11yKeyboardManager *a11y_keyboard_manager;
+ GsdA11yKeyboardManagerClass *klass;
+
+ klass = GSD_A11Y_KEYBOARD_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_A11Y_KEYBOARD_MANAGER));
+
+ a11y_keyboard_manager = GSD_A11Y_KEYBOARD_MANAGER (G_OBJECT_CLASS (gsd_a11y_keyboard_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (a11y_keyboard_manager);
+}
+
+static void
+gsd_a11y_keyboard_manager_dispose (GObject *object)
+{
+ GsdA11yKeyboardManager *a11y_keyboard_manager;
+
+ a11y_keyboard_manager = GSD_A11Y_KEYBOARD_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_a11y_keyboard_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_a11y_keyboard_manager_class_init (GsdA11yKeyboardManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_a11y_keyboard_manager_get_property;
+ object_class->set_property = gsd_a11y_keyboard_manager_set_property;
+ object_class->constructor = gsd_a11y_keyboard_manager_constructor;
+ object_class->dispose = gsd_a11y_keyboard_manager_dispose;
+ object_class->finalize = gsd_a11y_keyboard_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdA11yKeyboardManagerPrivate));
+}
+
+static void
+on_preferences_dialog_response (GtkDialog *dialog,
+ int response,
+ GsdA11yKeyboardManager *manager)
+{
+ g_signal_handlers_disconnect_by_func (dialog,
+ on_preferences_dialog_response,
+ manager);
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ manager->priv->preferences_dialog = NULL;
+}
+
+static void
+on_status_icon_activate (GtkStatusIcon *status_icon,
+ GsdA11yKeyboardManager *manager)
+{
+ if (manager->priv->preferences_dialog == NULL) {
+ manager->priv->preferences_dialog = gsd_a11y_preferences_dialog_new ();
+ g_signal_connect (manager->priv->preferences_dialog,
+ "response",
+ G_CALLBACK (on_preferences_dialog_response),
+ manager);
+
+ gtk_window_present (GTK_WINDOW (manager->priv->preferences_dialog));
+ } else {
+ g_signal_handlers_disconnect_by_func (manager->priv->preferences_dialog,
+ on_preferences_dialog_response,
+ manager);
+ gtk_widget_destroy (GTK_WIDGET (manager->priv->preferences_dialog));
+ manager->priv->preferences_dialog = NULL;
+ }
+}
+
+static void
+gsd_a11y_keyboard_manager_ensure_status_icon (GsdA11yKeyboardManager *manager)
+{
+ mate_settings_profile_start (NULL);
+
+ if (!manager->priv->status_icon) {
+
+ manager->priv->status_icon = gtk_status_icon_new_from_icon_name ("preferences-desktop-accessibility");
+ g_signal_connect (manager->priv->status_icon,
+ "activate",
+ G_CALLBACK (on_status_icon_activate),
+ manager);
+ }
+
+ mate_settings_profile_end (NULL);
+}
+
+static void
+gsd_a11y_keyboard_manager_init (GsdA11yKeyboardManager *manager)
+{
+ manager->priv = GSD_A11Y_KEYBOARD_MANAGER_GET_PRIVATE (manager);
+
+#ifdef HAVE_LIBMATENOTIFY
+ notify_init ("mate-settings-daemon");
+#endif /* HAVE_LIBMATENOTIFY */
+}
+
+static void
+gsd_a11y_keyboard_manager_finalize (GObject *object)
+{
+ GsdA11yKeyboardManager *a11y_keyboard_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_A11Y_KEYBOARD_MANAGER (object));
+
+ a11y_keyboard_manager = GSD_A11Y_KEYBOARD_MANAGER (object);
+
+ g_return_if_fail (a11y_keyboard_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_a11y_keyboard_manager_parent_class)->finalize (object);
+}
+
+GsdA11yKeyboardManager *
+gsd_a11y_keyboard_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_A11Y_KEYBOARD_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_A11Y_KEYBOARD_MANAGER (manager_object);
+}
diff --git a/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.h b/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.h
new file mode 100644
index 0000000..4fb817f
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_A11Y_KEYBOARD_MANAGER_H
+#define __GSD_A11Y_KEYBOARD_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_A11Y_KEYBOARD_MANAGER (gsd_a11y_keyboard_manager_get_type ())
+#define GSD_A11Y_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManager))
+#define GSD_A11Y_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManagerClass))
+#define GSD_IS_A11Y_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER))
+#define GSD_IS_A11Y_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_A11Y_KEYBOARD_MANAGER))
+#define GSD_A11Y_KEYBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManagerClass))
+
+typedef struct GsdA11yKeyboardManagerPrivate GsdA11yKeyboardManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdA11yKeyboardManagerPrivate *priv;
+} GsdA11yKeyboardManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdA11yKeyboardManagerClass;
+
+GType gsd_a11y_keyboard_manager_get_type (void);
+
+GsdA11yKeyboardManager *gsd_a11y_keyboard_manager_new (void);
+gboolean gsd_a11y_keyboard_manager_start (GsdA11yKeyboardManager *manager,
+ GError **error);
+void gsd_a11y_keyboard_manager_stop (GsdA11yKeyboardManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_A11Y_KEYBOARD_MANAGER_H */
diff --git a/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c b/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c
new file mode 100644
index 0000000..7846ba6
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-a11y-keyboard-plugin.h"
+#include "gsd-a11y-keyboard-manager.h"
+
+struct GsdA11yKeyboardPluginPrivate {
+ GsdA11yKeyboardManager *manager;
+};
+
+#define GSD_A11Y_KEYBOARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_A11Y_KEYBOARD_PLUGIN, GsdA11yKeyboardPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdA11yKeyboardPlugin, gsd_a11y_keyboard_plugin)
+
+static void
+gsd_a11y_keyboard_plugin_init (GsdA11yKeyboardPlugin *plugin)
+{
+ plugin->priv = GSD_A11Y_KEYBOARD_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdA11yKeyboardPlugin initializing");
+
+ plugin->priv->manager = gsd_a11y_keyboard_manager_new ();
+}
+
+static void
+gsd_a11y_keyboard_plugin_finalize (GObject *object)
+{
+ GsdA11yKeyboardPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_A11Y_KEYBOARD_PLUGIN (object));
+
+ g_debug ("GsdA11yKeyboardPlugin finalizing");
+
+ plugin = GSD_A11Y_KEYBOARD_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_a11y_keyboard_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating a11y_keyboard plugin");
+
+ error = NULL;
+ res = gsd_a11y_keyboard_manager_start (GSD_A11Y_KEYBOARD_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start a11y_keyboard manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating a11y_keyboard plugin");
+ gsd_a11y_keyboard_manager_stop (GSD_A11Y_KEYBOARD_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_a11y_keyboard_plugin_class_init (GsdA11yKeyboardPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_a11y_keyboard_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdA11yKeyboardPluginPrivate));
+}
diff --git a/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.h b/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.h
new file mode 100644
index 0000000..ebf246c
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_A11Y_KEYBOARD_PLUGIN_H__
+#define __GSD_A11Y_KEYBOARD_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_A11Y_KEYBOARD_PLUGIN (gsd_a11y_keyboard_plugin_get_type ())
+#define GSD_A11Y_KEYBOARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_A11Y_KEYBOARD_PLUGIN, GsdA11yKeyboardPlugin))
+#define GSD_A11Y_KEYBOARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_A11Y_KEYBOARD_PLUGIN, GsdA11yKeyboardPluginClass))
+#define GSD_IS_A11Y_KEYBOARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_A11Y_KEYBOARD_PLUGIN))
+#define GSD_IS_A11Y_KEYBOARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_A11Y_KEYBOARD_PLUGIN))
+#define GSD_A11Y_KEYBOARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_A11Y_KEYBOARD_PLUGIN, GsdA11yKeyboardPluginClass))
+
+typedef struct GsdA11yKeyboardPluginPrivate GsdA11yKeyboardPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdA11yKeyboardPluginPrivate *priv;
+} GsdA11yKeyboardPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdA11yKeyboardPluginClass;
+
+GType gsd_a11y_keyboard_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_A11Y_KEYBOARD_PLUGIN_H__ */
diff --git a/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c b/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c
new file mode 100644
index 0000000..752ee18
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c
@@ -0,0 +1,975 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <mateconf/mateconf-client.h>
+
+#include "gsd-a11y-preferences-dialog.h"
+
+#define SM_DBUS_NAME "org.mate.SessionManager"
+#define SM_DBUS_PATH "/org/mate/SessionManager"
+#define SM_DBUS_INTERFACE "org.mate.SessionManager"
+
+
+#define GSD_A11Y_PREFERENCES_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_A11Y_PREFERENCES_DIALOG, GsdA11yPreferencesDialogPrivate))
+
+#define GTKBUILDER_UI_FILE "gsd-a11y-preferences-dialog.ui"
+
+#define KEY_A11Y_DIR "/desktop/mate/accessibility"
+#define KEY_STICKY_KEYS_ENABLED KEY_A11Y_DIR "/keyboard/stickykeys_enable"
+#define KEY_BOUNCE_KEYS_ENABLED KEY_A11Y_DIR "/keyboard/bouncekeys_enable"
+#define KEY_SLOW_KEYS_ENABLED KEY_A11Y_DIR "/keyboard/slowkeys_enable"
+#define KEY_MOUSE_KEYS_ENABLED KEY_A11Y_DIR "/keyboard/mousekeys_enable"
+
+#define KEY_AT_DIR "/desktop/mate/applications/at"
+#define KEY_AT_SCREEN_KEYBOARD_ENABLED KEY_AT_DIR "/screen_keyboard_enabled"
+#define KEY_AT_SCREEN_MAGNIFIER_ENABLED KEY_AT_DIR "/screen_magnifier_enabled"
+#define KEY_AT_SCREEN_READER_ENABLED KEY_AT_DIR "/screen_reader_enabled"
+
+#define FONT_RENDER_DIR "/desktop/mate/font_rendering"
+#define KEY_FONT_DPI FONT_RENDER_DIR "/dpi"
+/* X servers sometimes lie about the screen's physical dimensions, so we cannot
+ * compute an accurate DPI value. When this happens, the user gets fonts that
+ * are too huge or too tiny. So, we see what the server returns: if it reports
+ * something outside of the range [DPI_LOW_REASONABLE_VALUE,
+ * DPI_HIGH_REASONABLE_VALUE], then we assume that it is lying and we use
+ * DPI_FALLBACK instead.
+ *
+ * See get_dpi_from_mateconf_or_server() below, and also
+ * https://bugzilla.novell.com/show_bug.cgi?id=217790
+ */
+#define DPI_LOW_REASONABLE_VALUE 50
+#define DPI_HIGH_REASONABLE_VALUE 500
+
+#define DPI_FACTOR_LARGE 1.25
+#define DPI_FACTOR_LARGER 1.5
+#define DPI_FACTOR_LARGEST 2.0
+#define DPI_DEFAULT 96
+
+#define KEY_GTK_THEME "/desktop/mate/interface/gtk_theme"
+#define KEY_COLOR_SCHEME "/desktop/mate/interface/gtk_color_scheme"
+#define KEY_MARCO_THEME "/apps/marco/general/theme"
+#define KEY_ICON_THEME "/desktop/mate/interface/icon_theme"
+
+#define HIGH_CONTRAST_THEME "HighContrast"
+
+struct GsdA11yPreferencesDialogPrivate
+{
+ GtkWidget *sticky_keys_checkbutton;
+ GtkWidget *slow_keys_checkbutton;
+ GtkWidget *bounce_keys_checkbutton;
+
+ GtkWidget *large_print_checkbutton;
+ GtkWidget *high_contrast_checkbutton;
+
+ GtkWidget *screen_reader_checkbutton;
+ GtkWidget *screen_keyboard_checkbutton;
+ GtkWidget *screen_magnifier_checkbutton;
+
+ guint a11y_dir_cnxn;
+ guint gsd_a11y_dir_cnxn;
+};
+
+enum {
+ PROP_0,
+};
+
+static void gsd_a11y_preferences_dialog_class_init (GsdA11yPreferencesDialogClass *klass);
+static void gsd_a11y_preferences_dialog_init (GsdA11yPreferencesDialog *a11y_preferences_dialog);
+static void gsd_a11y_preferences_dialog_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdA11yPreferencesDialog, gsd_a11y_preferences_dialog, GTK_TYPE_DIALOG)
+
+static void
+gsd_a11y_preferences_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_a11y_preferences_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_a11y_preferences_dialog_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdA11yPreferencesDialog *a11y_preferences_dialog;
+
+ a11y_preferences_dialog = GSD_A11Y_PREFERENCES_DIALOG (G_OBJECT_CLASS (gsd_a11y_preferences_dialog_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (a11y_preferences_dialog);
+}
+
+static void
+gsd_a11y_preferences_dialog_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (gsd_a11y_preferences_dialog_parent_class)->dispose (object);
+}
+
+static void
+gsd_a11y_preferences_dialog_class_init (GsdA11yPreferencesDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_a11y_preferences_dialog_get_property;
+ object_class->set_property = gsd_a11y_preferences_dialog_set_property;
+ object_class->constructor = gsd_a11y_preferences_dialog_constructor;
+ object_class->dispose = gsd_a11y_preferences_dialog_dispose;
+ object_class->finalize = gsd_a11y_preferences_dialog_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdA11yPreferencesDialogPrivate));
+}
+
+static void
+on_response (GsdA11yPreferencesDialog *dialog,
+ gint response_id)
+{
+ switch (response_id) {
+ default:
+ break;
+ }
+}
+
+static char *
+config_get_string (const char *key,
+ gboolean *is_writable)
+{
+ char *str;
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+
+ if (is_writable) {
+ *is_writable = mateconf_client_key_is_writable (client,
+ key,
+ NULL);
+ }
+
+ str = mateconf_client_get_string (client, key, NULL);
+
+ g_object_unref (client);
+
+ return str;
+}
+
+static gboolean
+config_get_bool (const char *key,
+ gboolean *is_writable)
+{
+ int enabled;
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+
+ if (is_writable) {
+ *is_writable = mateconf_client_key_is_writable (client,
+ key,
+ NULL);
+ }
+
+ enabled = mateconf_client_get_bool (client, key, NULL);
+
+ g_object_unref (client);
+
+ return enabled;
+}
+
+static double
+dpi_from_pixels_and_mm (int pixels,
+ int mm)
+{
+ double dpi;
+
+ if (mm >= 1) {
+ dpi = pixels / (mm / 25.4);
+ } else {
+ dpi = 0;
+ }
+
+ return dpi;
+}
+
+static double
+get_dpi_from_x_server (void)
+{
+ GdkScreen *screen;
+ double dpi;
+
+ screen = gdk_screen_get_default ();
+ if (screen != NULL) {
+ double width_dpi;
+ double height_dpi;
+
+ width_dpi = dpi_from_pixels_and_mm (gdk_screen_get_width (screen),
+ gdk_screen_get_width_mm (screen));
+ height_dpi = dpi_from_pixels_and_mm (gdk_screen_get_height (screen),
+ gdk_screen_get_height_mm (screen));
+ if (width_dpi < DPI_LOW_REASONABLE_VALUE
+ || width_dpi > DPI_HIGH_REASONABLE_VALUE
+ || height_dpi < DPI_LOW_REASONABLE_VALUE
+ || height_dpi > DPI_HIGH_REASONABLE_VALUE) {
+ dpi = DPI_DEFAULT;
+ } else {
+ dpi = (width_dpi + height_dpi) / 2.0;
+ }
+ } else {
+ /* Huh!? No screen? */
+ dpi = DPI_DEFAULT;
+ }
+
+ return dpi;
+}
+
+static gboolean
+config_get_large_print (gboolean *is_writable)
+{
+ gboolean ret;
+ MateConfClient *client;
+ MateConfValue *value;
+ gdouble x_dpi;
+ gdouble u_dpi;
+
+ client = mateconf_client_get_default ();
+ value = mateconf_client_get_without_default (client, KEY_FONT_DPI, NULL);
+
+ if (value != NULL) {
+ u_dpi = mateconf_value_get_float (value);
+ mateconf_value_free (value);
+ } else {
+ u_dpi = DPI_DEFAULT;
+ }
+
+ x_dpi = get_dpi_from_x_server ();
+
+ g_object_unref (client);
+
+ g_debug ("GsdA11yPreferences: got x-dpi=%f user-dpi=%f", x_dpi, u_dpi);
+
+ ret = (((double)DPI_FACTOR_LARGE * x_dpi) < u_dpi);
+
+ return ret;
+}
+
+static void
+config_set_large_print (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+
+ if (enabled) {
+ gdouble x_dpi;
+ gdouble u_dpi;
+
+ x_dpi = get_dpi_from_x_server ();
+ u_dpi = (double)DPI_FACTOR_LARGER * x_dpi;
+
+ g_debug ("GsdA11yPreferences: setting x-dpi=%f user-dpi=%f", x_dpi, u_dpi);
+
+ mateconf_client_set_float (client, KEY_FONT_DPI, u_dpi, NULL);
+ } else {
+ mateconf_client_unset (client, KEY_FONT_DPI, NULL);
+ }
+
+ g_object_unref (client);
+}
+
+static gboolean
+config_get_high_contrast (gboolean *is_writable)
+{
+ gboolean ret;
+ char *gtk_theme;
+
+ ret = FALSE;
+
+ gtk_theme = config_get_string (KEY_GTK_THEME, is_writable);
+ if (gtk_theme != NULL && strcmp (gtk_theme, HIGH_CONTRAST_THEME) == 0) {
+ ret = TRUE;
+ }
+ g_free (gtk_theme);
+
+ return ret;
+}
+
+static void
+config_set_high_contrast (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+
+ if (enabled) {
+ mateconf_client_set_string (client, KEY_GTK_THEME, HIGH_CONTRAST_THEME, NULL);
+ mateconf_client_set_string (client, KEY_ICON_THEME, HIGH_CONTRAST_THEME, NULL);
+ /* there isn't a high contrast marco theme afaik */
+ } else {
+ mateconf_client_unset (client, KEY_GTK_THEME, NULL);
+ mateconf_client_unset (client, KEY_ICON_THEME, NULL);
+ mateconf_client_unset (client, KEY_MARCO_THEME, NULL);
+ }
+
+ g_object_unref (client);
+}
+
+static gboolean
+config_get_sticky_keys (gboolean *is_writable)
+{
+ return config_get_bool (KEY_STICKY_KEYS_ENABLED, is_writable);
+}
+
+static void
+config_set_sticky_keys (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_STICKY_KEYS_ENABLED, enabled, NULL);
+ g_object_unref (client);
+}
+
+static gboolean
+config_get_bounce_keys (gboolean *is_writable)
+{
+ return config_get_bool (KEY_BOUNCE_KEYS_ENABLED, is_writable);
+}
+
+static void
+config_set_bounce_keys (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_BOUNCE_KEYS_ENABLED, enabled, NULL);
+ g_object_unref (client);
+}
+
+static gboolean
+config_get_slow_keys (gboolean *is_writable)
+{
+ return config_get_bool (KEY_SLOW_KEYS_ENABLED, is_writable);
+}
+
+static void
+config_set_slow_keys (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_SLOW_KEYS_ENABLED, enabled, NULL);
+ g_object_unref (client);
+}
+
+static gboolean
+config_have_at_mateconf_condition (const char *condition)
+{
+ DBusGProxy *sm_proxy;
+ DBusGConnection *connection;
+ GError *error;
+ gboolean res;
+ gboolean is_handled;
+
+ error = NULL;
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ g_warning ("Unable to connect to session bus: %s", error->message);
+ return FALSE;
+ }
+ sm_proxy = dbus_g_proxy_new_for_name (connection,
+ SM_DBUS_NAME,
+ SM_DBUS_PATH,
+ SM_DBUS_INTERFACE);
+ if (sm_proxy == NULL) {
+ return FALSE;
+ }
+
+ is_handled = FALSE;
+ res = dbus_g_proxy_call (sm_proxy,
+ "IsAutostartConditionHandled",
+ &error,
+ G_TYPE_STRING, condition,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &is_handled,
+ G_TYPE_INVALID);
+ if (! res) {
+ g_warning ("Unable to call IsAutostartConditionHandled (%s): %s",
+ condition,
+ error->message);
+ }
+
+ g_object_unref (sm_proxy);
+
+ return is_handled;
+}
+
+static gboolean
+config_get_at_screen_reader (gboolean *is_writable)
+{
+ return config_get_bool (KEY_AT_SCREEN_READER_ENABLED, is_writable);
+}
+
+static gboolean
+config_get_at_screen_keyboard (gboolean *is_writable)
+{
+ return config_get_bool (KEY_AT_SCREEN_KEYBOARD_ENABLED, is_writable);
+}
+
+static gboolean
+config_get_at_screen_magnifier (gboolean *is_writable)
+{
+ return config_get_bool (KEY_AT_SCREEN_MAGNIFIER_ENABLED, is_writable);
+}
+
+static void
+config_set_at_screen_reader (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_AT_SCREEN_READER_ENABLED, enabled, NULL);
+ g_object_unref (client);
+}
+
+static void
+config_set_at_screen_keyboard (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_AT_SCREEN_KEYBOARD_ENABLED, enabled, NULL);
+ g_object_unref (client);
+}
+
+static void
+config_set_at_screen_magnifier (gboolean enabled)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_AT_SCREEN_MAGNIFIER_ENABLED, enabled, NULL);
+ g_object_unref (client);
+}
+
+static void
+on_sticky_keys_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_sticky_keys (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_bounce_keys_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_bounce_keys (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_slow_keys_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_slow_keys (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_high_contrast_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_high_contrast (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_at_screen_reader_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_at_screen_reader (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_at_screen_keyboard_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_at_screen_keyboard (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_at_screen_magnifier_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_at_screen_magnifier (gtk_toggle_button_get_active (button));
+}
+
+static void
+on_large_print_checkbutton_toggled (GtkToggleButton *button,
+ GsdA11yPreferencesDialog *dialog)
+{
+ config_set_large_print (gtk_toggle_button_get_active (button));
+}
+
+static void
+ui_set_sticky_keys (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->sticky_keys_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->sticky_keys_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_bounce_keys (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->bounce_keys_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->bounce_keys_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_slow_keys (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->slow_keys_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->slow_keys_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_high_contrast (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->high_contrast_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->high_contrast_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_at_screen_reader (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->screen_reader_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->screen_reader_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_at_screen_keyboard (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->screen_keyboard_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->screen_keyboard_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_at_screen_magnifier (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->screen_magnifier_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->screen_magnifier_checkbutton), enabled);
+ }
+}
+
+static void
+ui_set_large_print (GsdA11yPreferencesDialog *dialog,
+ gboolean enabled)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->large_print_checkbutton));
+ if (active != enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->large_print_checkbutton), enabled);
+ }
+}
+
+static void
+key_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdA11yPreferencesDialog *dialog)
+{
+ const char *key;
+ MateConfValue *value;
+
+ key = mateconf_entry_get_key (entry);
+ value = mateconf_entry_get_value (entry);
+
+ if (strcmp (key, KEY_STICKY_KEYS_ENABLED) == 0) {
+ if (value->type == MATECONF_VALUE_BOOL) {
+ gboolean enabled;
+
+ enabled = mateconf_value_get_bool (value);
+ ui_set_sticky_keys (dialog, enabled);
+ } else {
+ g_warning ("Error retrieving configuration key '%s': Invalid type",
+ key);
+ }
+ } else if (strcmp (key, KEY_BOUNCE_KEYS_ENABLED) == 0) {
+ if (value->type == MATECONF_VALUE_BOOL) {
+ gboolean enabled;
+
+ enabled = mateconf_value_get_bool (value);
+ ui_set_bounce_keys (dialog, enabled);
+ } else {
+ g_warning ("Error retrieving configuration key '%s': Invalid type",
+ key);
+ }
+ } else if (strcmp (key, KEY_SLOW_KEYS_ENABLED) == 0) {
+ if (value->type == MATECONF_VALUE_BOOL) {
+ gboolean enabled;
+
+ enabled = mateconf_value_get_bool (value);
+ ui_set_slow_keys (dialog, enabled);
+ } else {
+ g_warning ("Error retrieving configuration key '%s': Invalid type",
+ key);
+ }
+ } else if (strcmp (key, KEY_AT_SCREEN_READER_ENABLED) == 0) {
+ if (value->type == MATECONF_VALUE_BOOL) {
+ gboolean enabled;
+
+ enabled = mateconf_value_get_bool (value);
+ ui_set_at_screen_reader (dialog, enabled);
+ } else {
+ g_warning ("Error retrieving configuration key '%s': Invalid type",
+ key);
+ }
+ } else if (strcmp (key, KEY_AT_SCREEN_KEYBOARD_ENABLED) == 0) {
+ if (value->type == MATECONF_VALUE_BOOL) {
+ gboolean enabled;
+
+ enabled = mateconf_value_get_bool (value);
+ ui_set_at_screen_keyboard (dialog, enabled);
+ } else {
+ g_warning ("Error retrieving configuration key '%s': Invalid type",
+ key);
+ }
+ } else if (strcmp (key, KEY_AT_SCREEN_MAGNIFIER_ENABLED) == 0) {
+ if (value->type == MATECONF_VALUE_BOOL) {
+ gboolean enabled;
+
+ enabled = mateconf_value_get_bool (value);
+ ui_set_at_screen_magnifier (dialog, enabled);
+ } else {
+ g_warning ("Error retrieving configuration key '%s': Invalid type",
+ key);
+ }
+ } else {
+ g_debug ("Config key not handled: %s", key);
+ }
+}
+
+static void
+setup_dialog (GsdA11yPreferencesDialog *dialog,
+ GtkBuilder *builder)
+{
+ GtkWidget *widget;
+ gboolean enabled;
+ gboolean is_writable;
+ MateConfClient *client;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "sticky_keys_checkbutton"));
+ dialog->priv->sticky_keys_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_sticky_keys_checkbutton_toggled),
+ NULL);
+ enabled = config_get_sticky_keys (&is_writable);
+ ui_set_sticky_keys (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "bounce_keys_checkbutton"));
+ dialog->priv->bounce_keys_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_bounce_keys_checkbutton_toggled),
+ NULL);
+ enabled = config_get_bounce_keys (&is_writable);
+ ui_set_bounce_keys (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "slow_keys_checkbutton"));
+ dialog->priv->slow_keys_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_slow_keys_checkbutton_toggled),
+ NULL);
+ enabled = config_get_slow_keys (&is_writable);
+ ui_set_slow_keys (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "high_contrast_checkbutton"));
+ dialog->priv->high_contrast_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_high_contrast_checkbutton_toggled),
+ NULL);
+ enabled = config_get_high_contrast (&is_writable);
+ ui_set_high_contrast (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "at_screen_keyboard_checkbutton"));
+ dialog->priv->screen_keyboard_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_at_screen_keyboard_checkbutton_toggled),
+ NULL);
+ enabled = config_get_at_screen_keyboard (&is_writable);
+ ui_set_at_screen_keyboard (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+ gtk_widget_set_no_show_all (widget, TRUE);
+ if (config_have_at_mateconf_condition ("MATE " KEY_AT_SCREEN_KEYBOARD_ENABLED)) {
+ gtk_widget_show_all (widget);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "at_screen_reader_checkbutton"));
+ dialog->priv->screen_reader_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_at_screen_reader_checkbutton_toggled),
+ NULL);
+ enabled = config_get_at_screen_reader (&is_writable);
+ ui_set_at_screen_reader (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+ gtk_widget_set_no_show_all (widget, TRUE);
+ if (config_have_at_mateconf_condition ("MATE " KEY_AT_SCREEN_READER_ENABLED)) {
+ gtk_widget_show_all (widget);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "at_screen_magnifier_checkbutton"));
+ dialog->priv->screen_magnifier_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_at_screen_magnifier_checkbutton_toggled),
+ NULL);
+ enabled = config_get_at_screen_magnifier (&is_writable);
+ ui_set_at_screen_magnifier (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+ gtk_widget_set_no_show_all (widget, TRUE);
+ if (config_have_at_mateconf_condition ("MATE " KEY_AT_SCREEN_MAGNIFIER_ENABLED)) {
+ gtk_widget_show_all (widget);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "large_print_checkbutton"));
+ dialog->priv->large_print_checkbutton = widget;
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (on_large_print_checkbutton_toggled),
+ NULL);
+ enabled = config_get_large_print (&is_writable);
+ ui_set_large_print (dialog, enabled);
+ if (! is_writable) {
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+
+ client = mateconf_client_get_default ();
+ mateconf_client_add_dir (client,
+ KEY_A11Y_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+ dialog->priv->a11y_dir_cnxn = mateconf_client_notify_add (client,
+ KEY_A11Y_DIR,
+ (MateConfClientNotifyFunc)key_changed_cb,
+ dialog,
+ NULL,
+ NULL);
+
+ mateconf_client_add_dir (client,
+ KEY_AT_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+ dialog->priv->gsd_a11y_dir_cnxn = mateconf_client_notify_add (client,
+ KEY_AT_DIR,
+ (MateConfClientNotifyFunc)key_changed_cb,
+ dialog,
+ NULL,
+ NULL);
+
+ g_object_unref (client);
+}
+
+static void
+gsd_a11y_preferences_dialog_init (GsdA11yPreferencesDialog *dialog)
+{
+ static const gchar *ui_file_path = GTKBUILDERDIR "/" GTKBUILDER_UI_FILE;
+ gchar *objects[] = {"main_box", NULL};
+ GError *error = NULL;
+ GtkBuilder *builder;
+
+ dialog->priv = GSD_A11Y_PREFERENCES_DIALOG_GET_PRIVATE (dialog);
+
+ builder = gtk_builder_new ();
+ gtk_builder_set_translation_domain (builder, PACKAGE);
+ if (gtk_builder_add_objects_from_file (builder, ui_file_path, objects,
+ &error) == 0) {
+ g_warning ("Could not load A11Y-UI: %s", error->message);
+ g_error_free (error);
+ } else {
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder,
+ "main_box"));
+ gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ widget);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
+ setup_dialog (dialog, builder);
+ }
+
+ g_object_unref (builder);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Universal Access Preferences"));
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "preferences-desktop-accessibility");
+ g_object_set (dialog,
+ "allow-shrink", FALSE,
+ "allow-grow", FALSE,
+ NULL);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ NULL);
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (on_response),
+ dialog);
+
+
+ gtk_widget_show_all (GTK_WIDGET (dialog));
+}
+
+static void
+gsd_a11y_preferences_dialog_finalize (GObject *object)
+{
+ GsdA11yPreferencesDialog *dialog;
+ MateConfClient *client;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_A11Y_PREFERENCES_DIALOG (object));
+
+ dialog = GSD_A11Y_PREFERENCES_DIALOG (object);
+
+ g_return_if_fail (dialog->priv != NULL);
+
+ client = mateconf_client_get_default ();
+
+ if (dialog->priv->a11y_dir_cnxn > 0) {
+ mateconf_client_notify_remove (client, dialog->priv->a11y_dir_cnxn);
+ }
+ if (dialog->priv->gsd_a11y_dir_cnxn > 0) {
+ mateconf_client_notify_remove (client, dialog->priv->gsd_a11y_dir_cnxn);
+ }
+
+ g_object_unref (client);
+
+ G_OBJECT_CLASS (gsd_a11y_preferences_dialog_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gsd_a11y_preferences_dialog_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (GSD_TYPE_A11Y_PREFERENCES_DIALOG,
+ NULL);
+
+ return GTK_WIDGET (object);
+}
diff --git a/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.h b/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.h
new file mode 100644
index 0000000..2be096a
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_A11Y_PREFERENCES_DIALOG_H
+#define __GSD_A11Y_PREFERENCES_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_A11Y_PREFERENCES_DIALOG (gsd_a11y_preferences_dialog_get_type ())
+#define GSD_A11Y_PREFERENCES_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_A11Y_PREFERENCES_DIALOG, GsdA11yPreferencesDialog))
+#define GSD_A11Y_PREFERENCES_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_A11Y_PREFERENCES_DIALOG, GsdA11yPreferencesDialogClass))
+#define GSD_IS_A11Y_PREFERENCES_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_A11Y_PREFERENCES_DIALOG))
+#define GSD_IS_A11Y_PREFERENCES_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_A11Y_PREFERENCES_DIALOG))
+#define GSD_A11Y_PREFERENCES_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_A11Y_PREFERENCES_DIALOG, GsdA11yPreferencesDialogClass))
+
+typedef struct GsdA11yPreferencesDialogPrivate GsdA11yPreferencesDialogPrivate;
+
+typedef struct
+{
+ GtkDialog parent;
+ GsdA11yPreferencesDialogPrivate *priv;
+} GsdA11yPreferencesDialog;
+
+typedef struct
+{
+ GtkDialogClass parent_class;
+} GsdA11yPreferencesDialogClass;
+
+GType gsd_a11y_preferences_dialog_get_type (void);
+
+GtkWidget * gsd_a11y_preferences_dialog_new (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_A11Y_PREFERENCES_DIALOG_H */
diff --git a/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.ui b/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.ui
new file mode 100644
index 0000000..6a0fcb0
--- /dev/null
+++ b/plugins/a11y-keyboard/gsd-a11y-preferences-dialog.ui
@@ -0,0 +1,199 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="dialog1">
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Universal Access Preferences</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="icon_name">preferences-desktop-accessibility</property>
+ <property name="type_hint">dialog</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkHBox" id="main_box">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="yalign">0</property>
+ <property name="icon_name">preferences-desktop-accessibility</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="at_screen_keyboard_checkbutton">
+ <property name="label" translatable="yes">Use on-screen _keyboard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="at_screen_reader_checkbutton">
+ <property name="label" translatable="yes">Use screen _reader</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="at_screen_magnifier_checkbutton">
+ <property name="label" translatable="yes">Use screen _magnifier</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="high_contrast_checkbutton">
+ <property name="label" translatable="yes">Enhance _contrast in colors</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="large_print_checkbutton">
+ <property name="label" translatable="yes">Make _text larger and easier to read</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="sticky_keys_checkbutton">
+ <property name="label" translatable="yes">_Press keyboard shortcuts one key at a time (Sticky Keys)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="bounce_keys_checkbutton">
+ <property name="label" translatable="yes">_Ignore duplicate keypresses (Bounce Keys)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="slow_keys_checkbutton">
+ <property name="label" translatable="yes">Press and _hold keys to accept them (Slow Keys)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button1</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/plugins/a11y-keyboard/test-a11y-preferences-dialog.c b/plugins/a11y-keyboard/test-a11y-preferences-dialog.c
new file mode 100644
index 0000000..343f61c
--- /dev/null
+++ b/plugins/a11y-keyboard/test-a11y-preferences-dialog.c
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-a11y-preferences-dialog.h"
+
+static void
+test_window (void)
+{
+ GtkWidget *window;
+
+ window = gsd_a11y_preferences_dialog_new ();
+ gtk_dialog_run (GTK_DIALOG (window));
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GError *error = NULL;
+
+#ifdef ENABLE_NLS
+ bindtextdomain (GETTEXT_PACKAGE, MATE_SETTINGS_LOCALEDIR);
+# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+# endif
+ textdomain (GETTEXT_PACKAGE);
+#endif
+
+ if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
+ fprintf (stderr, "%s", error->message);
+ g_error_free (error);
+ exit (1);
+ }
+
+ test_window ();
+
+ return 0;
+}
diff --git a/plugins/background/Makefile.am b/plugins/background/Makefile.am
new file mode 100644
index 0000000..f773144
--- /dev/null
+++ b/plugins/background/Makefile.am
@@ -0,0 +1,75 @@
+NULL =
+
+noinst_PROGRAMS = \
+ test-background \
+ $(NULL)
+
+test_background_SOURCES = \
+ test-background.c \
+ gsd-background-manager.h \
+ gsd-background-manager.c \
+ $(NULL)
+
+test_background_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_background_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_background_LDADD = \
+ $(top_builddir)/mate-settings-daemon/libgsd-profile.la \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(X11_LIBS) \
+ $(NULL)
+
+plugin_LTLIBRARIES = \
+ libbackground.la \
+ $(NULL)
+
+libbackground_la_SOURCES = \
+ gsd-background-plugin.h \
+ gsd-background-plugin.c \
+ gsd-background-manager.h \
+ gsd-background-manager.c \
+ $(NULL)
+
+libbackground_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/background/libbackground \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libbackground_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libbackground_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libbackground_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ background.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/background/Makefile.in b/plugins/background/Makefile.in
new file mode 100644
index 0000000..33c5b46
--- /dev/null
+++ b/plugins/background/Makefile.in
@@ -0,0 +1,758 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = test-background$(EXEEXT) $(am__EXEEXT_1)
+subdir = plugins/background
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libbackground_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libbackground_la_OBJECTS = \
+ libbackground_la-gsd-background-plugin.lo \
+ libbackground_la-gsd-background-manager.lo $(am__objects_1)
+libbackground_la_OBJECTS = $(am_libbackground_la_OBJECTS)
+libbackground_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libbackground_la_CFLAGS) \
+ $(CFLAGS) $(libbackground_la_LDFLAGS) $(LDFLAGS) -o $@
+am__EXEEXT_1 =
+PROGRAMS = $(noinst_PROGRAMS)
+am_test_background_OBJECTS = \
+ test_background-test-background.$(OBJEXT) \
+ test_background-gsd-background-manager.$(OBJEXT) \
+ $(am__objects_1)
+test_background_OBJECTS = $(am_test_background_OBJECTS)
+test_background_DEPENDENCIES = \
+ $(top_builddir)/mate-settings-daemon/libgsd-profile.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+test_background_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_background_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libbackground_la_SOURCES) $(test_background_SOURCES)
+DIST_SOURCES = $(libbackground_la_SOURCES) $(test_background_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+test_background_SOURCES = \
+ test-background.c \
+ gsd-background-manager.h \
+ gsd-background-manager.c \
+ $(NULL)
+
+test_background_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_background_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_background_LDADD = \
+ $(top_builddir)/mate-settings-daemon/libgsd-profile.la \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(X11_LIBS) \
+ $(NULL)
+
+plugin_LTLIBRARIES = \
+ libbackground.la \
+ $(NULL)
+
+libbackground_la_SOURCES = \
+ gsd-background-plugin.h \
+ gsd-background-plugin.c \
+ gsd-background-manager.h \
+ gsd-background-manager.c \
+ $(NULL)
+
+libbackground_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/background/libbackground \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libbackground_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libbackground_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libbackground_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ background.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/background/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/background/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libbackground.la: $(libbackground_la_OBJECTS) $(libbackground_la_DEPENDENCIES)
+ $(libbackground_la_LINK) -rpath $(plugindir) $(libbackground_la_OBJECTS) $(libbackground_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+test-background$(EXEEXT): $(test_background_OBJECTS) $(test_background_DEPENDENCIES)
+ @rm -f test-background$(EXEEXT)
+ $(test_background_LINK) $(test_background_OBJECTS) $(test_background_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbackground_la-gsd-background-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbackground_la-gsd-background-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_background-gsd-background-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_background-test-background.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libbackground_la-gsd-background-plugin.lo: gsd-background-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbackground_la_CPPFLAGS) $(CPPFLAGS) $(libbackground_la_CFLAGS) $(CFLAGS) -MT libbackground_la-gsd-background-plugin.lo -MD -MP -MF $(DEPDIR)/libbackground_la-gsd-background-plugin.Tpo -c -o libbackground_la-gsd-background-plugin.lo `test -f 'gsd-background-plugin.c' || echo '$(srcdir)/'`gsd-background-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libbackground_la-gsd-background-plugin.Tpo $(DEPDIR)/libbackground_la-gsd-background-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-background-plugin.c' object='libbackground_la-gsd-background-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbackground_la_CPPFLAGS) $(CPPFLAGS) $(libbackground_la_CFLAGS) $(CFLAGS) -c -o libbackground_la-gsd-background-plugin.lo `test -f 'gsd-background-plugin.c' || echo '$(srcdir)/'`gsd-background-plugin.c
+
+libbackground_la-gsd-background-manager.lo: gsd-background-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbackground_la_CPPFLAGS) $(CPPFLAGS) $(libbackground_la_CFLAGS) $(CFLAGS) -MT libbackground_la-gsd-background-manager.lo -MD -MP -MF $(DEPDIR)/libbackground_la-gsd-background-manager.Tpo -c -o libbackground_la-gsd-background-manager.lo `test -f 'gsd-background-manager.c' || echo '$(srcdir)/'`gsd-background-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libbackground_la-gsd-background-manager.Tpo $(DEPDIR)/libbackground_la-gsd-background-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-background-manager.c' object='libbackground_la-gsd-background-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbackground_la_CPPFLAGS) $(CPPFLAGS) $(libbackground_la_CFLAGS) $(CFLAGS) -c -o libbackground_la-gsd-background-manager.lo `test -f 'gsd-background-manager.c' || echo '$(srcdir)/'`gsd-background-manager.c
+
+test_background-test-background.o: test-background.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -MT test_background-test-background.o -MD -MP -MF $(DEPDIR)/test_background-test-background.Tpo -c -o test_background-test-background.o `test -f 'test-background.c' || echo '$(srcdir)/'`test-background.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_background-test-background.Tpo $(DEPDIR)/test_background-test-background.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-background.c' object='test_background-test-background.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -c -o test_background-test-background.o `test -f 'test-background.c' || echo '$(srcdir)/'`test-background.c
+
+test_background-test-background.obj: test-background.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -MT test_background-test-background.obj -MD -MP -MF $(DEPDIR)/test_background-test-background.Tpo -c -o test_background-test-background.obj `if test -f 'test-background.c'; then $(CYGPATH_W) 'test-background.c'; else $(CYGPATH_W) '$(srcdir)/test-background.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_background-test-background.Tpo $(DEPDIR)/test_background-test-background.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-background.c' object='test_background-test-background.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -c -o test_background-test-background.obj `if test -f 'test-background.c'; then $(CYGPATH_W) 'test-background.c'; else $(CYGPATH_W) '$(srcdir)/test-background.c'; fi`
+
+test_background-gsd-background-manager.o: gsd-background-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -MT test_background-gsd-background-manager.o -MD -MP -MF $(DEPDIR)/test_background-gsd-background-manager.Tpo -c -o test_background-gsd-background-manager.o `test -f 'gsd-background-manager.c' || echo '$(srcdir)/'`gsd-background-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_background-gsd-background-manager.Tpo $(DEPDIR)/test_background-gsd-background-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-background-manager.c' object='test_background-gsd-background-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -c -o test_background-gsd-background-manager.o `test -f 'gsd-background-manager.c' || echo '$(srcdir)/'`gsd-background-manager.c
+
+test_background-gsd-background-manager.obj: gsd-background-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -MT test_background-gsd-background-manager.obj -MD -MP -MF $(DEPDIR)/test_background-gsd-background-manager.Tpo -c -o test_background-gsd-background-manager.obj `if test -f 'gsd-background-manager.c'; then $(CYGPATH_W) 'gsd-background-manager.c'; else $(CYGPATH_W) '$(srcdir)/gsd-background-manager.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_background-gsd-background-manager.Tpo $(DEPDIR)/test_background-gsd-background-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-background-manager.c' object='test_background-gsd-background-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_background_CPPFLAGS) $(CPPFLAGS) $(test_background_CFLAGS) $(CFLAGS) -c -o test_background-gsd-background-manager.obj `if test -f 'gsd-background-manager.c'; then $(CYGPATH_W) 'gsd-background-manager.c'; else $(CYGPATH_W) '$(srcdir)/gsd-background-manager.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginDATA install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/background/background.mate-settings-plugin.in b/plugins/background/background.mate-settings-plugin.in
new file mode 100644
index 0000000..73d27b4
--- /dev/null
+++ b/plugins/background/background.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=background
+IAge=0
+_Name=Background
+_Description=Background plugin
+Authors=
+Copyright=Copyright © 2007
+Website=
diff --git a/plugins/background/gsd-background-manager.c b/plugins/background/gsd-background-manager.c
new file mode 100644
index 0000000..8c42445
--- /dev/null
+++ b/plugins/background/gsd-background-manager.c
@@ -0,0 +1,579 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2001 Ximian, Inc.
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ * Copyright 2007 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <dbus/dbus.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <mateconf/mateconf-client.h>
+
+#define MATE_DESKTOP_USE_UNSTABLE_API
+#include <libmateui/mate-bg.h>
+#include <X11/Xatom.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-background-manager.h"
+
+#define CAJA_SHOW_DESKTOP_KEY "/apps/caja/preferences/show_desktop"
+
+#define GSD_BACKGROUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerPrivate))
+
+struct GsdBackgroundManagerPrivate
+{
+ MateConfClient *client;
+ MateBG *bg;
+ guint bg_notify_id;
+ guint timeout_id;
+
+ DBusConnection *dbus_connection;
+};
+
+static void gsd_background_manager_class_init (GsdBackgroundManagerClass *klass);
+static void gsd_background_manager_init (GsdBackgroundManager *background_manager);
+static void gsd_background_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdBackgroundManager, gsd_background_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static gboolean
+caja_is_running (void)
+{
+ Atom window_id_atom;
+ Window caja_xid;
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems;
+ unsigned long bytes_after;
+ unsigned char *data;
+ int retval;
+ Atom wmclass_atom;
+ gboolean running;
+ gint error;
+
+ window_id_atom = XInternAtom (GDK_DISPLAY (),
+ "CAJA_DESKTOP_WINDOW_ID", True);
+
+ if (window_id_atom == None) {
+ return FALSE;
+ }
+
+ retval = XGetWindowProperty (GDK_DISPLAY (),
+ GDK_ROOT_WINDOW (),
+ window_id_atom,
+ 0,
+ 1,
+ False,
+ XA_WINDOW,
+ &actual_type,
+ &actual_format,
+ &nitems,
+ &bytes_after,
+ &data);
+
+ if (data != NULL) {
+ caja_xid = *(Window *) data;
+ XFree (data);
+ } else {
+ return FALSE;
+ }
+
+ if (actual_type != XA_WINDOW) {
+ return FALSE;
+ }
+ if (actual_format != 32) {
+ return FALSE;
+ }
+
+ wmclass_atom = XInternAtom (GDK_DISPLAY (), "WM_CLASS", False);
+
+ gdk_error_trap_push ();
+
+ retval = XGetWindowProperty (GDK_DISPLAY (),
+ caja_xid,
+ wmclass_atom,
+ 0,
+ 24,
+ False,
+ XA_STRING,
+ &actual_type,
+ &actual_format,
+ &nitems,
+ &bytes_after,
+ &data);
+
+ error = gdk_error_trap_pop ();
+
+ if (error == BadWindow) {
+ return FALSE;
+ }
+
+ if (actual_type == XA_STRING &&
+ nitems == 24 &&
+ bytes_after == 0 &&
+ actual_format == 8 &&
+ data != NULL &&
+ !strcmp ((char *)data, "desktop_window") &&
+ !strcmp ((char *)data + strlen ((char *)data) + 1, "Caja")) {
+ running = TRUE;
+ } else {
+ running = FALSE;
+ }
+
+ if (data != NULL) {
+ XFree (data);
+ }
+
+ return running;
+}
+
+static void
+draw_background (GsdBackgroundManager *manager,
+ gboolean use_crossfade)
+{
+ GdkDisplay *display;
+ int n_screens;
+ int i;
+
+ if (caja_is_running ()) {
+ return;
+ }
+
+ mate_settings_profile_start (NULL);
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+
+ for (i = 0; i < n_screens; ++i) {
+ GdkScreen *screen;
+ GdkWindow *root_window;
+ GdkPixmap *pixmap;
+
+ screen = gdk_display_get_screen (display, i);
+
+ root_window = gdk_screen_get_root_window (screen);
+
+ pixmap = mate_bg_create_pixmap (manager->priv->bg,
+ root_window,
+ gdk_screen_get_width (screen),
+ gdk_screen_get_height (screen),
+ TRUE);
+
+ if (use_crossfade) {
+ MateBGCrossfade *fade;
+
+ fade = mate_bg_set_pixmap_as_root_with_crossfade (screen, pixmap);
+ g_signal_connect (fade, "finished",
+ G_CALLBACK (g_object_unref), NULL);
+ } else {
+ mate_bg_set_pixmap_as_root (screen, pixmap);
+ }
+
+ g_object_unref (pixmap);
+ }
+
+ mate_settings_profile_end (NULL);
+}
+
+static void
+on_bg_changed (MateBG *bg,
+ GsdBackgroundManager *manager)
+{
+ draw_background (manager, TRUE);
+}
+
+static void
+on_bg_transitioned (MateBG *bg,
+ GsdBackgroundManager *manager)
+{
+ draw_background (manager, FALSE);
+}
+
+static void
+mateconf_changed_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdBackgroundManager *manager)
+{
+ mate_bg_load_from_preferences (manager->priv->bg,
+ manager->priv->client);
+}
+
+static void
+watch_bg_preferences (GsdBackgroundManager *manager)
+{
+ g_assert (manager->priv->bg_notify_id == 0);
+
+ mateconf_client_add_dir (manager->priv->client,
+ MATE_BG_KEY_DIR,
+ MATECONF_CLIENT_PRELOAD_NONE,
+ NULL);
+ manager->priv->bg_notify_id = mateconf_client_notify_add (manager->priv->client,
+ MATE_BG_KEY_DIR,
+ (MateConfClientNotifyFunc)mateconf_changed_callback,
+ manager,
+ NULL,
+ NULL);
+}
+
+static void
+setup_bg (GsdBackgroundManager *manager)
+{
+ g_return_if_fail (manager->priv->bg == NULL);
+
+ manager->priv->bg = mate_bg_new ();
+
+ g_signal_connect (manager->priv->bg,
+ "changed",
+ G_CALLBACK (on_bg_changed),
+ manager);
+
+ g_signal_connect (manager->priv->bg,
+ "transitioned",
+ G_CALLBACK (on_bg_transitioned),
+ manager);
+
+ watch_bg_preferences (manager);
+ mate_bg_load_from_preferences (manager->priv->bg,
+ manager->priv->client);
+}
+
+static gboolean
+queue_draw_background (GsdBackgroundManager *manager)
+{
+ manager->priv->timeout_id = 0;
+ if (caja_is_running ()) {
+ return FALSE;
+ }
+ setup_bg (manager);
+ draw_background (manager, FALSE);
+ return FALSE;
+}
+
+static DBusHandlerResult
+on_bus_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GsdBackgroundManager *manager = user_data;
+
+ if (dbus_message_is_signal (message,
+ "org.mate.SessionManager",
+ "SessionRunning")) {
+ /* If the session finishes then check if caja is
+ * running and if not, set the background.
+ *
+ * We wait a few seconds after the session is up
+ * because caja tells the session manager that its
+ * ready before it sets the background.
+ */
+ manager->priv->timeout_id = g_timeout_add_seconds (8,
+ (GSourceFunc)
+ queue_draw_background,
+ manager);
+ dbus_connection_remove_filter (connection,
+ on_bus_message,
+ manager);
+
+ manager->priv->dbus_connection = NULL;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+draw_background_after_session_loads (GsdBackgroundManager *manager)
+{
+ DBusConnection *connection;
+
+ connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+
+ if (connection == NULL) {
+ return;
+ }
+
+ if (!dbus_connection_add_filter (connection, on_bus_message, manager, NULL)) {
+ return;
+ };
+
+ manager->priv->dbus_connection = connection;
+}
+
+static void
+on_screen_size_changed (GdkScreen *screen,
+ GsdBackgroundManager *manager)
+{
+ gboolean caja_show_desktop;
+
+ caja_show_desktop = mateconf_client_get_bool (manager->priv->client,
+ CAJA_SHOW_DESKTOP_KEY,
+ NULL);
+
+ if (!caja_is_running () || !caja_show_desktop) {
+ if (manager->priv->bg == NULL) {
+ setup_bg (manager);
+ }
+ draw_background (manager, FALSE);
+ }
+}
+
+static void
+disconnect_screen_signals (GsdBackgroundManager *manager)
+{
+ GdkDisplay *display;
+ int i;
+ int n_screens;
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+
+ for (i = 0; i < n_screens; ++i) {
+ GdkScreen *screen;
+ screen = gdk_display_get_screen (display, i);
+ g_signal_handlers_disconnect_by_func (screen,
+ G_CALLBACK (on_screen_size_changed),
+ manager);
+ }
+}
+
+static void
+connect_screen_signals (GsdBackgroundManager *manager)
+{
+ GdkDisplay *display;
+ int i;
+ int n_screens;
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+
+ for (i = 0; i < n_screens; ++i) {
+ GdkScreen *screen;
+ screen = gdk_display_get_screen (display, i);
+ g_signal_connect (screen,
+ "monitors-changed",
+ G_CALLBACK (on_screen_size_changed),
+ manager);
+ g_signal_connect (screen,
+ "size-changed",
+ G_CALLBACK (on_screen_size_changed),
+ manager);
+ }
+}
+
+gboolean
+gsd_background_manager_start (GsdBackgroundManager *manager,
+ GError **error)
+{
+ gboolean caja_show_desktop;
+
+ g_debug ("Starting background manager");
+ mate_settings_profile_start (NULL);
+
+ manager->priv->client = mateconf_client_get_default ();
+
+ /* If this is set, caja will draw the background and is
+ * almost definitely in our session. however, it may not be
+ * running yet (so is_caja_running() will fail). so, on
+ * startup, just don't do anything if this key is set so we
+ * don't waste time setting the background only to have
+ * caja overwrite it.
+ */
+ caja_show_desktop = mateconf_client_get_bool (manager->priv->client,
+ CAJA_SHOW_DESKTOP_KEY,
+ NULL);
+
+ if (!caja_show_desktop) {
+ setup_bg (manager);
+ } else {
+ draw_background_after_session_loads (manager);
+ }
+
+ connect_screen_signals (manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_background_manager_stop (GsdBackgroundManager *manager)
+{
+ GsdBackgroundManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping background manager");
+
+ disconnect_screen_signals (manager);
+
+ if (manager->priv->dbus_connection != NULL) {
+ dbus_connection_remove_filter (manager->priv->dbus_connection,
+ on_bus_message,
+ manager);
+ }
+
+ if (manager->priv->bg_notify_id != 0) {
+ mateconf_client_remove_dir (manager->priv->client,
+ MATE_BG_KEY_DIR,
+ NULL);
+ mateconf_client_notify_remove (manager->priv->client,
+ manager->priv->bg_notify_id);
+ manager->priv->bg_notify_id = 0;
+ }
+
+ if (p->client != NULL) {
+ g_object_unref (p->client);
+ p->client = NULL;
+ }
+
+ if (p->timeout_id != 0) {
+ g_source_remove (p->timeout_id);
+ p->timeout_id = 0;
+ }
+
+ if (p->bg != NULL) {
+ g_object_unref (p->bg);
+ p->bg = NULL;
+ }
+}
+
+static void
+gsd_background_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdBackgroundManager *self;
+
+ self = GSD_BACKGROUND_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_background_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdBackgroundManager *self;
+
+ self = GSD_BACKGROUND_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_background_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdBackgroundManager *background_manager;
+ GsdBackgroundManagerClass *klass;
+
+ klass = GSD_BACKGROUND_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_BACKGROUND_MANAGER));
+
+ background_manager = GSD_BACKGROUND_MANAGER (G_OBJECT_CLASS (gsd_background_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (background_manager);
+}
+
+static void
+gsd_background_manager_dispose (GObject *object)
+{
+ GsdBackgroundManager *background_manager;
+
+ background_manager = GSD_BACKGROUND_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_background_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_background_manager_class_init (GsdBackgroundManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_background_manager_get_property;
+ object_class->set_property = gsd_background_manager_set_property;
+ object_class->constructor = gsd_background_manager_constructor;
+ object_class->dispose = gsd_background_manager_dispose;
+ object_class->finalize = gsd_background_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdBackgroundManagerPrivate));
+}
+
+static void
+gsd_background_manager_init (GsdBackgroundManager *manager)
+{
+ manager->priv = GSD_BACKGROUND_MANAGER_GET_PRIVATE (manager);
+}
+
+static void
+gsd_background_manager_finalize (GObject *object)
+{
+ GsdBackgroundManager *background_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_BACKGROUND_MANAGER (object));
+
+ background_manager = GSD_BACKGROUND_MANAGER (object);
+
+ g_return_if_fail (background_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_background_manager_parent_class)->finalize (object);
+}
+
+GsdBackgroundManager *
+gsd_background_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_BACKGROUND_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_BACKGROUND_MANAGER (manager_object);
+}
diff --git a/plugins/background/gsd-background-manager.h b/plugins/background/gsd-background-manager.h
new file mode 100644
index 0000000..27c900a
--- /dev/null
+++ b/plugins/background/gsd-background-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_BACKGROUND_MANAGER_H
+#define __GSD_BACKGROUND_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_BACKGROUND_MANAGER (gsd_background_manager_get_type ())
+#define GSD_BACKGROUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManager))
+#define GSD_BACKGROUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerClass))
+#define GSD_IS_BACKGROUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_BACKGROUND_MANAGER))
+#define GSD_IS_BACKGROUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_BACKGROUND_MANAGER))
+#define GSD_BACKGROUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerClass))
+
+typedef struct GsdBackgroundManagerPrivate GsdBackgroundManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdBackgroundManagerPrivate *priv;
+} GsdBackgroundManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdBackgroundManagerClass;
+
+GType gsd_background_manager_get_type (void);
+
+GsdBackgroundManager * gsd_background_manager_new (void);
+gboolean gsd_background_manager_start (GsdBackgroundManager *manager,
+ GError **error);
+void gsd_background_manager_stop (GsdBackgroundManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_BACKGROUND_MANAGER_H */
diff --git a/plugins/background/gsd-background-plugin.c b/plugins/background/gsd-background-plugin.c
new file mode 100644
index 0000000..e001f39
--- /dev/null
+++ b/plugins/background/gsd-background-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-background-plugin.h"
+#include "gsd-background-manager.h"
+
+struct GsdBackgroundPluginPrivate {
+ GsdBackgroundManager *manager;
+};
+
+#define GSD_BACKGROUND_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_BACKGROUND_PLUGIN, GsdBackgroundPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdBackgroundPlugin, gsd_background_plugin)
+
+static void
+gsd_background_plugin_init (GsdBackgroundPlugin *plugin)
+{
+ plugin->priv = GSD_BACKGROUND_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdBackgroundPlugin initializing");
+
+ plugin->priv->manager = gsd_background_manager_new ();
+}
+
+static void
+gsd_background_plugin_finalize (GObject *object)
+{
+ GsdBackgroundPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_BACKGROUND_PLUGIN (object));
+
+ g_debug ("GsdBackgroundPlugin finalizing");
+
+ plugin = GSD_BACKGROUND_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_background_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating background plugin");
+
+ error = NULL;
+ res = gsd_background_manager_start (GSD_BACKGROUND_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start background manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating background plugin");
+ gsd_background_manager_stop (GSD_BACKGROUND_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_background_plugin_class_init (GsdBackgroundPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_background_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdBackgroundPluginPrivate));
+}
diff --git a/plugins/background/gsd-background-plugin.h b/plugins/background/gsd-background-plugin.h
new file mode 100644
index 0000000..1acaf9f
--- /dev/null
+++ b/plugins/background/gsd-background-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_BACKGROUND_PLUGIN_H__
+#define __GSD_BACKGROUND_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_BACKGROUND_PLUGIN (gsd_background_plugin_get_type ())
+#define GSD_BACKGROUND_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_BACKGROUND_PLUGIN, GsdBackgroundPlugin))
+#define GSD_BACKGROUND_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_BACKGROUND_PLUGIN, GsdBackgroundPluginClass))
+#define GSD_IS_BACKGROUND_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_BACKGROUND_PLUGIN))
+#define GSD_IS_BACKGROUND_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_BACKGROUND_PLUGIN))
+#define GSD_BACKGROUND_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_BACKGROUND_PLUGIN, GsdBackgroundPluginClass))
+
+typedef struct GsdBackgroundPluginPrivate GsdBackgroundPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdBackgroundPluginPrivate *priv;
+} GsdBackgroundPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdBackgroundPluginClass;
+
+GType gsd_background_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_BACKGROUND_PLUGIN_H__ */
diff --git a/plugins/background/test-background.c b/plugins/background/test-background.c
new file mode 100644
index 0000000..a7b5ef7
--- /dev/null
+++ b/plugins/background/test-background.c
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <libintl.h>
+#include <locale.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-background-manager.h"
+
+static gboolean
+idle (GsdBackgroundManager *manager)
+{
+ gsd_background_manager_start (manager, NULL);
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GsdBackgroundManager *manager;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATE_SETTINGS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ setlocale (LC_ALL, "");
+
+ gtk_init (&argc, &argv);
+
+ manager = gsd_background_manager_new ();
+ g_idle_add ((GSourceFunc)idle, manager);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/plugins/clipboard/Makefile.am b/plugins/clipboard/Makefile.am
new file mode 100644
index 0000000..f50a86e
--- /dev/null
+++ b/plugins/clipboard/Makefile.am
@@ -0,0 +1,53 @@
+NULL =
+
+plugin_LTLIBRARIES = \
+ libclipboard.la \
+ $(NULL)
+
+libclipboard_la_SOURCES = \
+ gsd-clipboard-plugin.h \
+ gsd-clipboard-plugin.c \
+ gsd-clipboard-manager.h \
+ gsd-clipboard-manager.c \
+ xutils.h \
+ xutils.c \
+ list.h \
+ list.c \
+ $(NULL)
+
+libclipboard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libclipboard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libclipboard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libclipboard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ clipboard.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/clipboard/Makefile.in b/plugins/clipboard/Makefile.in
new file mode 100644
index 0000000..3516b51
--- /dev/null
+++ b/plugins/clipboard/Makefile.in
@@ -0,0 +1,699 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/clipboard
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libclipboard_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libclipboard_la_OBJECTS = libclipboard_la-gsd-clipboard-plugin.lo \
+ libclipboard_la-gsd-clipboard-manager.lo \
+ libclipboard_la-xutils.lo libclipboard_la-list.lo \
+ $(am__objects_1)
+libclipboard_la_OBJECTS = $(am_libclipboard_la_OBJECTS)
+libclipboard_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libclipboard_la_CFLAGS) \
+ $(CFLAGS) $(libclipboard_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libclipboard_la_SOURCES)
+DIST_SOURCES = $(libclipboard_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+plugin_LTLIBRARIES = \
+ libclipboard.la \
+ $(NULL)
+
+libclipboard_la_SOURCES = \
+ gsd-clipboard-plugin.h \
+ gsd-clipboard-plugin.c \
+ gsd-clipboard-manager.h \
+ gsd-clipboard-manager.c \
+ xutils.h \
+ xutils.c \
+ list.h \
+ list.c \
+ $(NULL)
+
+libclipboard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libclipboard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libclipboard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libclipboard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ clipboard.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/clipboard/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/clipboard/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libclipboard.la: $(libclipboard_la_OBJECTS) $(libclipboard_la_DEPENDENCIES)
+ $(libclipboard_la_LINK) -rpath $(plugindir) $(libclipboard_la_OBJECTS) $(libclipboard_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclipboard_la-gsd-clipboard-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclipboard_la-gsd-clipboard-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclipboard_la-list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclipboard_la-xutils.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libclipboard_la-gsd-clipboard-plugin.lo: gsd-clipboard-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -MT libclipboard_la-gsd-clipboard-plugin.lo -MD -MP -MF $(DEPDIR)/libclipboard_la-gsd-clipboard-plugin.Tpo -c -o libclipboard_la-gsd-clipboard-plugin.lo `test -f 'gsd-clipboard-plugin.c' || echo '$(srcdir)/'`gsd-clipboard-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libclipboard_la-gsd-clipboard-plugin.Tpo $(DEPDIR)/libclipboard_la-gsd-clipboard-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-clipboard-plugin.c' object='libclipboard_la-gsd-clipboard-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -c -o libclipboard_la-gsd-clipboard-plugin.lo `test -f 'gsd-clipboard-plugin.c' || echo '$(srcdir)/'`gsd-clipboard-plugin.c
+
+libclipboard_la-gsd-clipboard-manager.lo: gsd-clipboard-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -MT libclipboard_la-gsd-clipboard-manager.lo -MD -MP -MF $(DEPDIR)/libclipboard_la-gsd-clipboard-manager.Tpo -c -o libclipboard_la-gsd-clipboard-manager.lo `test -f 'gsd-clipboard-manager.c' || echo '$(srcdir)/'`gsd-clipboard-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libclipboard_la-gsd-clipboard-manager.Tpo $(DEPDIR)/libclipboard_la-gsd-clipboard-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-clipboard-manager.c' object='libclipboard_la-gsd-clipboard-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -c -o libclipboard_la-gsd-clipboard-manager.lo `test -f 'gsd-clipboard-manager.c' || echo '$(srcdir)/'`gsd-clipboard-manager.c
+
+libclipboard_la-xutils.lo: xutils.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -MT libclipboard_la-xutils.lo -MD -MP -MF $(DEPDIR)/libclipboard_la-xutils.Tpo -c -o libclipboard_la-xutils.lo `test -f 'xutils.c' || echo '$(srcdir)/'`xutils.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libclipboard_la-xutils.Tpo $(DEPDIR)/libclipboard_la-xutils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xutils.c' object='libclipboard_la-xutils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -c -o libclipboard_la-xutils.lo `test -f 'xutils.c' || echo '$(srcdir)/'`xutils.c
+
+libclipboard_la-list.lo: list.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -MT libclipboard_la-list.lo -MD -MP -MF $(DEPDIR)/libclipboard_la-list.Tpo -c -o libclipboard_la-list.lo `test -f 'list.c' || echo '$(srcdir)/'`list.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libclipboard_la-list.Tpo $(DEPDIR)/libclipboard_la-list.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='list.c' object='libclipboard_la-list.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclipboard_la_CPPFLAGS) $(CPPFLAGS) $(libclipboard_la_CFLAGS) $(CFLAGS) -c -o libclipboard_la-list.lo `test -f 'list.c' || echo '$(srcdir)/'`list.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/clipboard/clipboard.mate-settings-plugin.in b/plugins/clipboard/clipboard.mate-settings-plugin.in
new file mode 100644
index 0000000..3a5536f
--- /dev/null
+++ b/plugins/clipboard/clipboard.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=clipboard
+IAge=0
+_Name=Clipboard
+_Description=Clipboard plugin
+Authors=Matthias Clasen
+Copyright=Copyright © 2007 Matthias Clasen
+Website=
diff --git a/plugins/clipboard/gsd-clipboard-manager.c b/plugins/clipboard/gsd-clipboard-manager.c
new file mode 100644
index 0000000..fcbc839
--- /dev/null
+++ b/plugins/clipboard/gsd-clipboard-manager.c
@@ -0,0 +1,1069 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Matthias Clasen
+ * Copyright (C) 2007 Anders Carlsson
+ * Copyright (C) 2007 Rodrigo Moya
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "xutils.h"
+#include "list.h"
+
+#include "mate-settings-profile.h"
+#include "gsd-clipboard-manager.h"
+
+#define GSD_CLIPBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerPrivate))
+
+struct GsdClipboardManagerPrivate
+{
+ Display *display;
+ Window window;
+ Time timestamp;
+
+ List *contents;
+ List *conversions;
+
+ Window requestor;
+ Atom property;
+ Time time;
+};
+
+typedef struct
+{
+ unsigned char *data;
+ int length;
+ Atom target;
+ Atom type;
+ int format;
+ int refcount;
+} TargetData;
+
+typedef struct
+{
+ Atom target;
+ TargetData *data;
+ Atom property;
+ Window requestor;
+ int offset;
+} IncrConversion;
+
+static void gsd_clipboard_manager_class_init (GsdClipboardManagerClass *klass);
+static void gsd_clipboard_manager_init (GsdClipboardManager *clipboard_manager);
+static void gsd_clipboard_manager_finalize (GObject *object);
+
+static void clipboard_manager_watch_cb (GsdClipboardManager *manager,
+ Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data);
+
+G_DEFINE_TYPE (GsdClipboardManager, gsd_clipboard_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+/* We need to use reference counting for the target data, since we may
+ * need to keep the data around after loosing the CLIPBOARD ownership
+ * to complete incremental transfers.
+ */
+static TargetData *
+target_data_ref (TargetData *data)
+{
+ data->refcount++;
+ return data;
+}
+
+static void
+target_data_unref (TargetData *data)
+{
+ data->refcount--;
+ if (data->refcount == 0) {
+ free (data->data);
+ free (data);
+ }
+}
+
+static void
+conversion_free (IncrConversion *rdata)
+{
+ if (rdata->data) {
+ target_data_unref (rdata->data);
+ }
+ free (rdata);
+}
+
+static void
+send_selection_notify (GsdClipboardManager *manager,
+ Bool success)
+{
+ XSelectionEvent notify;
+
+ notify.type = SelectionNotify;
+ notify.serial = 0;
+ notify.send_event = True;
+ notify.display = manager->priv->display;
+ notify.requestor = manager->priv->requestor;
+ notify.selection = XA_CLIPBOARD_MANAGER;
+ notify.target = XA_SAVE_TARGETS;
+ notify.property = success ? manager->priv->property : None;
+ notify.time = manager->priv->time;
+
+ gdk_error_trap_push ();
+
+ XSendEvent (manager->priv->display,
+ manager->priv->requestor,
+ False,
+ NoEventMask,
+ (XEvent *)&notify);
+ XSync (manager->priv->display, False);
+
+ gdk_error_trap_pop ();
+}
+
+static void
+finish_selection_request (GsdClipboardManager *manager,
+ XEvent *xev,
+ Bool success)
+{
+ XSelectionEvent notify;
+
+ notify.type = SelectionNotify;
+ notify.serial = 0;
+ notify.send_event = True;
+ notify.display = xev->xselectionrequest.display;
+ notify.requestor = xev->xselectionrequest.requestor;
+ notify.selection = xev->xselectionrequest.selection;
+ notify.target = xev->xselectionrequest.target;
+ notify.property = success ? xev->xselectionrequest.property : None;
+ notify.time = xev->xselectionrequest.time;
+
+ gdk_error_trap_push ();
+
+ XSendEvent (xev->xselectionrequest.display,
+ xev->xselectionrequest.requestor,
+ False, NoEventMask, (XEvent *) &notify);
+ XSync (manager->priv->display, False);
+
+ gdk_error_trap_pop ();
+}
+
+static int
+clipboard_bytes_per_item (int format)
+{
+ switch (format) {
+ case 8: return sizeof (char);
+ case 16: return sizeof (short);
+ case 32: return sizeof (long);
+ default: ;
+ }
+
+ return 0;
+}
+
+static void
+save_targets (GsdClipboardManager *manager,
+ Atom *save_targets,
+ int nitems)
+{
+ int nout, i;
+ Atom *multiple;
+ TargetData *tdata;
+
+ multiple = (Atom *) malloc (2 * nitems * sizeof (Atom));
+
+ nout = 0;
+ for (i = 0; i < nitems; i++) {
+ if (save_targets[i] != XA_TARGETS &&
+ save_targets[i] != XA_MULTIPLE &&
+ save_targets[i] != XA_DELETE &&
+ save_targets[i] != XA_INSERT_PROPERTY &&
+ save_targets[i] != XA_INSERT_SELECTION &&
+ save_targets[i] != XA_PIXMAP) {
+ tdata = (TargetData *) malloc (sizeof (TargetData));
+ tdata->data = NULL;
+ tdata->length = 0;
+ tdata->target = save_targets[i];
+ tdata->type = None;
+ tdata->format = 0;
+ tdata->refcount = 1;
+ manager->priv->contents = list_prepend (manager->priv->contents, tdata);
+
+ multiple[nout++] = save_targets[i];
+ multiple[nout++] = save_targets[i];
+ }
+ }
+
+ XFree (save_targets);
+
+ XChangeProperty (manager->priv->display, manager->priv->window,
+ XA_MULTIPLE, XA_ATOM_PAIR,
+ 32, PropModeReplace, (const unsigned char *) multiple, nout);
+ free (multiple);
+
+ XConvertSelection (manager->priv->display, XA_CLIPBOARD,
+ XA_MULTIPLE, XA_MULTIPLE,
+ manager->priv->window, manager->priv->time);
+}
+
+static int
+find_content_target (TargetData *tdata,
+ Atom target)
+{
+ return tdata->target == target;
+}
+
+static int
+find_content_type (TargetData *tdata,
+ Atom type)
+{
+ return tdata->type == type;
+}
+
+static int
+find_conversion_requestor (IncrConversion *rdata,
+ XEvent *xev)
+{
+ return (rdata->requestor == xev->xproperty.window &&
+ rdata->property == xev->xproperty.atom);
+}
+
+static void
+get_property (TargetData *tdata,
+ GsdClipboardManager *manager)
+{
+ Atom type;
+ int format;
+ unsigned long length;
+ unsigned long remaining;
+ unsigned char *data;
+
+ XGetWindowProperty (manager->priv->display,
+ manager->priv->window,
+ tdata->target,
+ 0,
+ 0x1FFFFFFF,
+ True,
+ AnyPropertyType,
+ &type,
+ &format,
+ &length,
+ &remaining,
+ &data);
+
+ if (type == None) {
+ manager->priv->contents = list_remove (manager->priv->contents, tdata);
+ free (tdata);
+ } else if (type == XA_INCR) {
+ tdata->type = type;
+ tdata->length = 0;
+ XFree (data);
+ } else {
+ tdata->type = type;
+ tdata->data = data;
+ tdata->length = length * clipboard_bytes_per_item (format);
+ tdata->format = format;
+ }
+}
+
+static Bool
+receive_incrementally (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ List *list;
+ TargetData *tdata;
+ Atom type;
+ int format;
+ unsigned long length, nitems, remaining;
+ unsigned char *data;
+
+ if (xev->xproperty.window != manager->priv->window)
+ return False;
+
+ list = list_find (manager->priv->contents,
+ (ListFindFunc) find_content_target, (void *) xev->xproperty.atom);
+
+ if (!list)
+ return False;
+
+ tdata = (TargetData *) list->data;
+
+ if (tdata->type != XA_INCR)
+ return False;
+
+ XGetWindowProperty (xev->xproperty.display,
+ xev->xproperty.window,
+ xev->xproperty.atom,
+ 0, 0x1FFFFFFF, True, AnyPropertyType,
+ &type, &format, &nitems, &remaining, &data);
+
+ length = nitems * clipboard_bytes_per_item (format);
+ if (length == 0) {
+ tdata->type = type;
+ tdata->format = format;
+
+ if (!list_find (manager->priv->contents,
+ (ListFindFunc) find_content_type, (void *)XA_INCR)) {
+ /* all incremental transfers done */
+ send_selection_notify (manager, True);
+ manager->priv->requestor = None;
+ }
+
+ XFree (data);
+ } else {
+ if (!tdata->data) {
+ tdata->data = data;
+ tdata->length = length;
+ } else {
+ tdata->data = realloc (tdata->data, tdata->length + length + 1);
+ memcpy (tdata->data + tdata->length, data, length + 1);
+ tdata->length += length;
+ XFree (data);
+ }
+ }
+
+ return True;
+}
+
+static Bool
+send_incrementally (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ List *list;
+ IncrConversion *rdata;
+ unsigned long length;
+ unsigned long items;
+ unsigned char *data;
+
+ list = list_find (manager->priv->conversions,
+ (ListFindFunc) find_conversion_requestor, xev);
+ if (list == NULL)
+ return False;
+
+ rdata = (IncrConversion *) list->data;
+
+ data = rdata->data->data + rdata->offset;
+ length = rdata->data->length - rdata->offset;
+ if (length > SELECTION_MAX_SIZE)
+ length = SELECTION_MAX_SIZE;
+
+ rdata->offset += length;
+
+ items = length / clipboard_bytes_per_item (rdata->data->format);
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property, rdata->data->type,
+ rdata->data->format, PropModeAppend,
+ data, items);
+
+ if (length == 0) {
+ manager->priv->conversions = list_remove (manager->priv->conversions, rdata);
+ conversion_free (rdata);
+ }
+
+ return True;
+}
+
+static void
+convert_clipboard_manager (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ Atom type = None;
+ int format;
+ unsigned long nitems;
+ unsigned long remaining;
+ Atom *targets = NULL;
+
+ if (xev->xselectionrequest.target == XA_SAVE_TARGETS) {
+ if (manager->priv->requestor != None || manager->priv->contents != NULL) {
+ /* We're in the middle of a conversion request, or own
+ * the CLIPBOARD already
+ */
+ finish_selection_request (manager, xev, False);
+ } else {
+ gdk_error_trap_push ();
+
+ clipboard_manager_watch_cb (manager,
+ xev->xselectionrequest.requestor,
+ True,
+ StructureNotifyMask,
+ NULL);
+ XSelectInput (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ StructureNotifyMask);
+ XSync (manager->priv->display, False);
+
+ if (gdk_error_trap_pop () != Success)
+ return;
+
+ gdk_error_trap_push ();
+
+ if (xev->xselectionrequest.property != None) {
+ XGetWindowProperty (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ 0, 0x1FFFFFFF, False, XA_ATOM,
+ &type, &format, &nitems, &remaining,
+ (unsigned char **) &targets);
+
+ if (gdk_error_trap_pop () != Success) {
+ if (targets)
+ XFree (targets);
+
+ return;
+ }
+ }
+
+ manager->priv->requestor = xev->xselectionrequest.requestor;
+ manager->priv->property = xev->xselectionrequest.property;
+ manager->priv->time = xev->xselectionrequest.time;
+
+ if (type == None)
+ XConvertSelection (manager->priv->display, XA_CLIPBOARD,
+ XA_TARGETS, XA_TARGETS,
+ manager->priv->window, manager->priv->time);
+ else
+ save_targets (manager, targets, nitems);
+ }
+ } else if (xev->xselectionrequest.target == XA_TIMESTAMP) {
+ XChangeProperty (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ XA_INTEGER, 32, PropModeReplace,
+ (unsigned char *) &manager->priv->timestamp, 1);
+
+ finish_selection_request (manager, xev, True);
+ } else if (xev->xselectionrequest.target == XA_TARGETS) {
+ int n_targets = 0;
+ Atom targets[3];
+
+ targets[n_targets++] = XA_TARGETS;
+ targets[n_targets++] = XA_TIMESTAMP;
+ targets[n_targets++] = XA_SAVE_TARGETS;
+
+ XChangeProperty (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) targets, n_targets);
+
+ finish_selection_request (manager, xev, True);
+ } else
+ finish_selection_request (manager, xev, False);
+}
+
+static void
+convert_clipboard_target (IncrConversion *rdata,
+ GsdClipboardManager *manager)
+{
+ TargetData *tdata;
+ Atom *targets;
+ int n_targets;
+ List *list;
+ unsigned long items;
+ XWindowAttributes atts;
+
+ if (rdata->target == XA_TARGETS) {
+ n_targets = list_length (manager->priv->contents) + 2;
+ targets = (Atom *) malloc (n_targets * sizeof (Atom));
+
+ n_targets = 0;
+
+ targets[n_targets++] = XA_TARGETS;
+ targets[n_targets++] = XA_MULTIPLE;
+
+ for (list = manager->priv->contents; list; list = list->next) {
+ tdata = (TargetData *) list->data;
+ targets[n_targets++] = tdata->target;
+ }
+
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) targets, n_targets);
+ free (targets);
+ } else {
+ /* Convert from stored CLIPBOARD data */
+ list = list_find (manager->priv->contents,
+ (ListFindFunc) find_content_target, (void *) rdata->target);
+
+ /* We got a target that we don't support */
+ if (!list)
+ return;
+
+ tdata = (TargetData *)list->data;
+ if (tdata->type == XA_INCR) {
+ /* we haven't completely received this target yet */
+ rdata->property = None;
+ return;
+ }
+
+ rdata->data = target_data_ref (tdata);
+ items = tdata->length / clipboard_bytes_per_item (tdata->format);
+ if (tdata->length <= SELECTION_MAX_SIZE)
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property,
+ tdata->type, tdata->format, PropModeReplace,
+ tdata->data, items);
+ else {
+ /* start incremental transfer */
+ rdata->offset = 0;
+
+ gdk_error_trap_push ();
+
+ XGetWindowAttributes (manager->priv->display, rdata->requestor, &atts);
+ XSelectInput (manager->priv->display, rdata->requestor,
+ atts.your_event_mask | PropertyChangeMask);
+
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property,
+ XA_INCR, 32, PropModeReplace,
+ (unsigned char *) &items, 1);
+
+ XSync (manager->priv->display, False);
+
+ gdk_error_trap_pop ();
+ }
+ }
+}
+
+static void
+collect_incremental (IncrConversion *rdata,
+ GsdClipboardManager *manager)
+{
+ if (rdata->offset >= 0)
+ manager->priv->conversions = list_prepend (manager->priv->conversions, rdata);
+ else {
+ if (rdata->data) {
+ target_data_unref (rdata->data);
+ rdata->data = NULL;
+ }
+ free (rdata);
+ }
+}
+
+static void
+convert_clipboard (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ List *list;
+ List *conversions;
+ IncrConversion *rdata;
+ Atom type;
+ int i;
+ int format;
+ unsigned long nitems;
+ unsigned long remaining;
+ Atom *multiple;
+
+ conversions = NULL;
+ type = None;
+
+ if (xev->xselectionrequest.target == XA_MULTIPLE) {
+ XGetWindowProperty (xev->xselectionrequest.display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ 0, 0x1FFFFFFF, False, XA_ATOM_PAIR,
+ &type, &format, &nitems, &remaining,
+ (unsigned char **) &multiple);
+
+ if (type != XA_ATOM_PAIR || nitems == 0) {
+ if (multiple)
+ free (multiple);
+ return;
+ }
+
+ for (i = 0; i < nitems; i += 2) {
+ rdata = (IncrConversion *) malloc (sizeof (IncrConversion));
+ rdata->requestor = xev->xselectionrequest.requestor;
+ rdata->target = multiple[i];
+ rdata->property = multiple[i+1];
+ rdata->data = NULL;
+ rdata->offset = -1;
+ conversions = list_prepend (conversions, rdata);
+ }
+ } else {
+ multiple = NULL;
+
+ rdata = (IncrConversion *) malloc (sizeof (IncrConversion));
+ rdata->requestor = xev->xselectionrequest.requestor;
+ rdata->target = xev->xselectionrequest.target;
+ rdata->property = xev->xselectionrequest.property;
+ rdata->data = NULL;
+ rdata->offset = -1;
+ conversions = list_prepend (conversions, rdata);
+ }
+
+ list_foreach (conversions, (Callback) convert_clipboard_target, manager);
+
+ if (conversions->next == NULL &&
+ ((IncrConversion *) conversions->data)->property == None) {
+ finish_selection_request (manager, xev, False);
+ } else {
+ if (multiple) {
+ i = 0;
+ for (list = conversions; list; list = list->next) {
+ rdata = (IncrConversion *)list->data;
+ multiple[i++] = rdata->target;
+ multiple[i++] = rdata->property;
+ }
+ XChangeProperty (xev->xselectionrequest.display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ XA_ATOM_PAIR, 32, PropModeReplace,
+ (unsigned char *) multiple, nitems);
+ }
+ finish_selection_request (manager, xev, True);
+ }
+
+ list_foreach (conversions, (Callback) collect_incremental, manager);
+ list_free (conversions);
+
+ if (multiple)
+ free (multiple);
+}
+
+static Bool
+clipboard_manager_process_event (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ Atom type;
+ int format;
+ unsigned long nitems;
+ unsigned long remaining;
+ Atom *targets;
+
+ targets = NULL;
+
+ switch (xev->xany.type) {
+ case DestroyNotify:
+ if (xev->xdestroywindow.window == manager->priv->requestor) {
+ list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL);
+ list_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+ }
+ break;
+ case PropertyNotify:
+ if (xev->xproperty.state == PropertyNewValue) {
+ return receive_incrementally (manager, xev);
+ } else {
+ return send_incrementally (manager, xev);
+ }
+
+ case SelectionClear:
+ if (xev->xany.window != manager->priv->window)
+ return False;
+
+ if (xev->xselectionclear.selection == XA_CLIPBOARD_MANAGER) {
+ /* We lost the manager selection */
+ if (manager->priv->contents) {
+ list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL);
+ list_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+
+ XSetSelectionOwner (manager->priv->display,
+ XA_CLIPBOARD,
+ None, manager->priv->time);
+ }
+
+ return True;
+ }
+ if (xev->xselectionclear.selection == XA_CLIPBOARD) {
+ /* We lost the clipboard selection */
+ list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL);
+ list_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+
+ return True;
+ }
+ break;
+
+ case SelectionNotify:
+ if (xev->xany.window != manager->priv->window)
+ return False;
+
+ if (xev->xselection.selection == XA_CLIPBOARD) {
+ /* a CLIPBOARD conversion is done */
+ if (xev->xselection.property == XA_TARGETS) {
+ XGetWindowProperty (xev->xselection.display,
+ xev->xselection.requestor,
+ xev->xselection.property,
+ 0, 0x1FFFFFFF, True, XA_ATOM,
+ &type, &format, &nitems, &remaining,
+ (unsigned char **) &targets);
+
+ save_targets (manager, targets, nitems);
+ } else if (xev->xselection.property == XA_MULTIPLE) {
+ List *tmp;
+
+ tmp = list_copy (manager->priv->contents);
+ list_foreach (tmp, (Callback) get_property, manager);
+ list_free (tmp);
+
+ manager->priv->time = xev->xselection.time;
+ XSetSelectionOwner (manager->priv->display, XA_CLIPBOARD,
+ manager->priv->window, manager->priv->time);
+
+ if (manager->priv->property != None)
+ XChangeProperty (manager->priv->display,
+ manager->priv->requestor,
+ manager->priv->property,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)&XA_NULL, 1);
+
+ if (!list_find (manager->priv->contents,
+ (ListFindFunc)find_content_type, (void *)XA_INCR)) {
+ /* all transfers done */
+ send_selection_notify (manager, True);
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+ }
+ }
+ else if (xev->xselection.property == None) {
+ send_selection_notify (manager, False);
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+ }
+
+ return True;
+ }
+ break;
+
+ case SelectionRequest:
+ if (xev->xany.window != manager->priv->window) {
+ return False;
+ }
+
+ if (xev->xselectionrequest.selection == XA_CLIPBOARD_MANAGER) {
+ convert_clipboard_manager (manager, xev);
+ return True;
+ } else if (xev->xselectionrequest.selection == XA_CLIPBOARD) {
+ convert_clipboard (manager, xev);
+ return True;
+ }
+ break;
+
+ default: ;
+ }
+
+ return False;
+}
+
+static GdkFilterReturn
+clipboard_manager_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ GsdClipboardManager *manager)
+{
+ if (clipboard_manager_process_event (manager, (XEvent *)xevent)) {
+ return GDK_FILTER_REMOVE;
+ } else {
+ return GDK_FILTER_CONTINUE;
+ }
+}
+
+static void
+clipboard_manager_watch_cb (GsdClipboardManager *manager,
+ Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data)
+{
+ GdkWindow *gdkwin;
+ GdkDisplay *display;
+
+ display = gdk_display_get_default ();
+ gdkwin = gdk_window_lookup_for_display (display, window);
+
+ if (is_start) {
+ if (gdkwin == NULL) {
+ gdkwin = gdk_window_foreign_new_for_display (display, window);
+ } else {
+ g_object_ref (gdkwin);
+ }
+
+ gdk_window_add_filter (gdkwin,
+ (GdkFilterFunc)clipboard_manager_event_filter,
+ manager);
+ } else {
+ if (gdkwin == NULL) {
+ return;
+ }
+ gdk_window_remove_filter (gdkwin,
+ (GdkFilterFunc)clipboard_manager_event_filter,
+ manager);
+ g_object_unref (gdkwin);
+ }
+}
+
+static gboolean
+start_clipboard_idle_cb (GsdClipboardManager *manager)
+{
+ XClientMessageEvent xev;
+
+
+ mate_settings_profile_start (NULL);
+
+ init_atoms (manager->priv->display);
+
+ /* check if there is a clipboard manager running */
+ if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER)) {
+ g_warning ("Clipboard manager is already running.");
+ return FALSE;
+ }
+
+ manager->priv->contents = NULL;
+ manager->priv->conversions = NULL;
+ manager->priv->requestor = None;
+
+ manager->priv->window = XCreateSimpleWindow (manager->priv->display,
+ DefaultRootWindow (manager->priv->display),
+ 0, 0, 10, 10, 0,
+ WhitePixel (manager->priv->display,
+ DefaultScreen (manager->priv->display)),
+ WhitePixel (manager->priv->display,
+ DefaultScreen (manager->priv->display)));
+ clipboard_manager_watch_cb (manager,
+ manager->priv->window,
+ True,
+ PropertyChangeMask,
+ NULL);
+ XSelectInput (manager->priv->display,
+ manager->priv->window,
+ PropertyChangeMask);
+ manager->priv->timestamp = get_server_time (manager->priv->display, manager->priv->window);
+
+ XSetSelectionOwner (manager->priv->display,
+ XA_CLIPBOARD_MANAGER,
+ manager->priv->window,
+ manager->priv->timestamp);
+
+ /* Check to see if we managed to claim the selection. If not,
+ * we treat it as if we got it then immediately lost it
+ */
+ if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER) == manager->priv->window) {
+ xev.type = ClientMessage;
+ xev.window = DefaultRootWindow (manager->priv->display);
+ xev.message_type = XA_MANAGER;
+ xev.format = 32;
+ xev.data.l[0] = manager->priv->timestamp;
+ xev.data.l[1] = XA_CLIPBOARD_MANAGER;
+ xev.data.l[2] = manager->priv->window;
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (manager->priv->display,
+ DefaultRootWindow (manager->priv->display),
+ False,
+ StructureNotifyMask,
+ (XEvent *)&xev);
+ } else {
+ clipboard_manager_watch_cb (manager,
+ manager->priv->window,
+ False,
+ 0,
+ NULL);
+ /* FIXME: manager->priv->terminate (manager->priv->cb_data); */
+ }
+
+ mate_settings_profile_end (NULL);
+
+ return FALSE;
+}
+
+gboolean
+gsd_clipboard_manager_start (GsdClipboardManager *manager,
+ GError **error)
+{
+ mate_settings_profile_start (NULL);
+
+ g_idle_add ((GSourceFunc) start_clipboard_idle_cb, manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_clipboard_manager_stop (GsdClipboardManager *manager)
+{
+ g_debug ("Stopping clipboard manager");
+
+ clipboard_manager_watch_cb (manager,
+ manager->priv->window,
+ FALSE,
+ 0,
+ NULL);
+ XDestroyWindow (manager->priv->display, manager->priv->window);
+
+ list_foreach (manager->priv->conversions, (Callback) conversion_free, NULL);
+ list_free (manager->priv->conversions);
+
+ list_foreach (manager->priv->contents, (Callback) target_data_unref, NULL);
+ list_free (manager->priv->contents);
+}
+
+static void
+gsd_clipboard_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdClipboardManager *self;
+
+ self = GSD_CLIPBOARD_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_clipboard_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdClipboardManager *self;
+
+ self = GSD_CLIPBOARD_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_clipboard_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdClipboardManager *clipboard_manager;
+ GsdClipboardManagerClass *klass;
+
+ klass = GSD_CLIPBOARD_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_CLIPBOARD_MANAGER));
+
+ clipboard_manager = GSD_CLIPBOARD_MANAGER (G_OBJECT_CLASS (gsd_clipboard_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (clipboard_manager);
+}
+
+static void
+gsd_clipboard_manager_dispose (GObject *object)
+{
+ GsdClipboardManager *clipboard_manager;
+
+ clipboard_manager = GSD_CLIPBOARD_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_clipboard_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_clipboard_manager_class_init (GsdClipboardManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_clipboard_manager_get_property;
+ object_class->set_property = gsd_clipboard_manager_set_property;
+ object_class->constructor = gsd_clipboard_manager_constructor;
+ object_class->dispose = gsd_clipboard_manager_dispose;
+ object_class->finalize = gsd_clipboard_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdClipboardManagerPrivate));
+}
+
+static void
+gsd_clipboard_manager_init (GsdClipboardManager *manager)
+{
+ manager->priv = GSD_CLIPBOARD_MANAGER_GET_PRIVATE (manager);
+
+ manager->priv->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+}
+
+static void
+gsd_clipboard_manager_finalize (GObject *object)
+{
+ GsdClipboardManager *clipboard_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_CLIPBOARD_MANAGER (object));
+
+ clipboard_manager = GSD_CLIPBOARD_MANAGER (object);
+
+ g_return_if_fail (clipboard_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_clipboard_manager_parent_class)->finalize (object);
+}
+
+GsdClipboardManager *
+gsd_clipboard_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_CLIPBOARD_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_CLIPBOARD_MANAGER (manager_object);
+}
diff --git a/plugins/clipboard/gsd-clipboard-manager.h b/plugins/clipboard/gsd-clipboard-manager.h
new file mode 100644
index 0000000..0338799
--- /dev/null
+++ b/plugins/clipboard/gsd-clipboard-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_CLIPBOARD_MANAGER_H
+#define __GSD_CLIPBOARD_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_CLIPBOARD_MANAGER (gsd_clipboard_manager_get_type ())
+#define GSD_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManager))
+#define GSD_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerClass))
+#define GSD_IS_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_CLIPBOARD_MANAGER))
+#define GSD_IS_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_CLIPBOARD_MANAGER))
+#define GSD_CLIPBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerClass))
+
+typedef struct GsdClipboardManagerPrivate GsdClipboardManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdClipboardManagerPrivate *priv;
+} GsdClipboardManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdClipboardManagerClass;
+
+GType gsd_clipboard_manager_get_type (void);
+
+GsdClipboardManager * gsd_clipboard_manager_new (void);
+gboolean gsd_clipboard_manager_start (GsdClipboardManager *manager,
+ GError **error);
+void gsd_clipboard_manager_stop (GsdClipboardManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_CLIPBOARD_MANAGER_H */
diff --git a/plugins/clipboard/gsd-clipboard-plugin.c b/plugins/clipboard/gsd-clipboard-plugin.c
new file mode 100644
index 0000000..f384b52
--- /dev/null
+++ b/plugins/clipboard/gsd-clipboard-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-clipboard-plugin.h"
+#include "gsd-clipboard-manager.h"
+
+struct GsdClipboardPluginPrivate {
+ GsdClipboardManager *manager;
+};
+
+#define GSD_CLIPBOARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_CLIPBOARD_PLUGIN, GsdClipboardPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdClipboardPlugin, gsd_clipboard_plugin)
+
+static void
+gsd_clipboard_plugin_init (GsdClipboardPlugin *plugin)
+{
+ plugin->priv = GSD_CLIPBOARD_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdClipboardPlugin initializing");
+
+ plugin->priv->manager = gsd_clipboard_manager_new ();
+}
+
+static void
+gsd_clipboard_plugin_finalize (GObject *object)
+{
+ GsdClipboardPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_CLIPBOARD_PLUGIN (object));
+
+ g_debug ("GsdClipboardPlugin finalizing");
+
+ plugin = GSD_CLIPBOARD_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_clipboard_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating clipboard plugin");
+
+ error = NULL;
+ res = gsd_clipboard_manager_start (GSD_CLIPBOARD_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start clipboard manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating clipboard plugin");
+ gsd_clipboard_manager_stop (GSD_CLIPBOARD_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_clipboard_plugin_class_init (GsdClipboardPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_clipboard_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdClipboardPluginPrivate));
+}
diff --git a/plugins/clipboard/gsd-clipboard-plugin.h b/plugins/clipboard/gsd-clipboard-plugin.h
new file mode 100644
index 0000000..4148c09
--- /dev/null
+++ b/plugins/clipboard/gsd-clipboard-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_CLIPBOARD_PLUGIN_H__
+#define __GSD_CLIPBOARD_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_CLIPBOARD_PLUGIN (gsd_clipboard_plugin_get_type ())
+#define GSD_CLIPBOARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_CLIPBOARD_PLUGIN, GsdClipboardPlugin))
+#define GSD_CLIPBOARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_CLIPBOARD_PLUGIN, GsdClipboardPluginClass))
+#define GSD_IS_CLIPBOARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_CLIPBOARD_PLUGIN))
+#define GSD_IS_CLIPBOARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_CLIPBOARD_PLUGIN))
+#define GSD_CLIPBOARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_CLIPBOARD_PLUGIN, GsdClipboardPluginClass))
+
+typedef struct GsdClipboardPluginPrivate GsdClipboardPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdClipboardPluginPrivate *priv;
+} GsdClipboardPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdClipboardPluginClass;
+
+GType gsd_clipboard_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_CLIPBOARD_PLUGIN_H__ */
diff --git a/plugins/clipboard/list.c b/plugins/clipboard/list.c
new file mode 100644
index 0000000..477eead
--- /dev/null
+++ b/plugins/clipboard/list.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Matthias Clasen, Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+#include <list.h>
+
+
+void
+list_foreach (List *list,
+ Callback func,
+ void *user_data)
+{
+ while (list)
+ {
+ func (list->data, user_data);
+
+ list = list->next;
+ }
+}
+
+List *
+list_prepend (List *list,
+ void *data)
+{
+ List *link;
+
+ link = (List *) malloc (sizeof (List));
+ link->next = list;
+ link->data = data;
+
+ return link;
+}
+
+void
+list_free (List *list)
+{
+ while (list)
+ {
+ List *next = list->next;
+
+ free (list);
+
+ list = next;
+ }
+}
+
+List *
+list_find (List *list,
+ ListFindFunc func,
+ void *user_data)
+{
+ List *tmp;
+
+ for (tmp = list; tmp; tmp = tmp->next)
+ {
+ if ((*func) (tmp->data, user_data))
+ break;
+ }
+
+ return tmp;
+}
+
+List *
+list_remove (List *list,
+ void *data)
+{
+ List *tmp, *prev;
+
+ prev = NULL;
+ for (tmp = list; tmp; tmp = tmp->next)
+ {
+ if (tmp->data == data)
+ {
+ if (prev)
+ prev->next = tmp->next;
+ else
+ list = tmp->next;
+
+ free (tmp);
+ break;
+ }
+
+ prev = tmp;
+ }
+
+ return list;
+}
+
+int
+list_length (List *list)
+{
+ List *tmp;
+ int length;
+
+ length = 0;
+ for (tmp = list; tmp; tmp = tmp->next)
+ length++;
+
+ return length;
+}
+
+List *
+list_copy (List *list)
+{
+ List *new_list = NULL;
+
+ if (list)
+ {
+ List *last;
+
+ new_list = (List *) malloc (sizeof (List));
+ new_list->data = list->data;
+ new_list->next = NULL;
+
+ last = new_list;
+ list = list->next;
+
+ while (list)
+ {
+ last->next = (List *) malloc (sizeof (List));
+ last = last->next;
+ last->data = list->data;
+ list = list->next;
+ }
+
+ last->next = NULL;
+ }
+
+ return new_list;
+}
diff --git a/plugins/clipboard/list.h b/plugins/clipboard/list.h
new file mode 100644
index 0000000..158b779
--- /dev/null
+++ b/plugins/clipboard/list.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Matthias Clasen, Red Hat, Inc.
+ */
+#ifndef LIST_H
+#define LIST_H
+
+
+typedef struct _List List;
+typedef void (*Callback) (void *data,
+ void *user_data);
+
+
+struct _List
+{
+ void *data;
+
+ List *next;
+};
+
+typedef int (*ListFindFunc) (void *data,
+ void *user_data);
+
+void list_foreach (List *list,
+ Callback func,
+ void *user_data);
+List *list_prepend (List *list,
+ void *data);
+void list_free (List *list);
+List *list_find (List *list,
+ ListFindFunc func,
+ void *user_data);
+List *list_remove (List *list,
+ void *data);
+int list_length (List *list);
+
+List *list_copy (List *list);
+
+#endif /* LIST_H */
diff --git a/plugins/clipboard/xutils.c b/plugins/clipboard/xutils.c
new file mode 100644
index 0000000..4e48b98
--- /dev/null
+++ b/plugins/clipboard/xutils.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Matthias Clasen, Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+
+#include "xutils.h"
+
+Atom XA_ATOM_PAIR;
+Atom XA_CLIPBOARD_MANAGER;
+Atom XA_CLIPBOARD;
+Atom XA_DELETE;
+Atom XA_INCR;
+Atom XA_INSERT_PROPERTY;
+Atom XA_INSERT_SELECTION;
+Atom XA_MANAGER;
+Atom XA_MULTIPLE;
+Atom XA_NULL;
+Atom XA_SAVE_TARGETS;
+Atom XA_TARGETS;
+Atom XA_TIMESTAMP;
+
+unsigned long SELECTION_MAX_SIZE = 0;
+
+
+void
+init_atoms (Display *display)
+{
+ unsigned long max_request_size;
+
+ if (SELECTION_MAX_SIZE > 0)
+ return;
+
+ XA_ATOM_PAIR = XInternAtom (display, "ATOM_PAIR", False);
+ XA_CLIPBOARD_MANAGER = XInternAtom (display, "CLIPBOARD_MANAGER", False);
+ XA_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False);
+ XA_DELETE = XInternAtom (display, "DELETE", False);
+ XA_INCR = XInternAtom (display, "INCR", False);
+ XA_INSERT_PROPERTY = XInternAtom (display, "INSERT_PROPERTY", False);
+ XA_INSERT_SELECTION = XInternAtom (display, "INSERT_SELECTION", False);
+ XA_MANAGER = XInternAtom (display, "MANAGER", False);
+ XA_MULTIPLE = XInternAtom (display, "MULTIPLE", False);
+ XA_NULL = XInternAtom (display, "NULL", False);
+ XA_SAVE_TARGETS = XInternAtom (display, "SAVE_TARGETS", False);
+ XA_TARGETS = XInternAtom (display, "TARGETS", False);
+ XA_TIMESTAMP = XInternAtom (display, "TIMESTAMP", False);
+
+ max_request_size = XExtendedMaxRequestSize (display);
+ if (max_request_size == 0)
+ max_request_size = XMaxRequestSize (display);
+
+ SELECTION_MAX_SIZE = max_request_size - 100;
+ if (SELECTION_MAX_SIZE > 262144)
+ SELECTION_MAX_SIZE = 262144;
+}
+
+typedef struct
+{
+ Window window;
+ Atom timestamp_prop_atom;
+} TimeStampInfo;
+
+static Bool
+timestamp_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ TimeStampInfo *info = (TimeStampInfo *)arg;
+
+ if (xevent->type == PropertyNotify &&
+ xevent->xproperty.window == info->window &&
+ xevent->xproperty.atom == info->timestamp_prop_atom)
+ return True;
+
+ return False;
+}
+
+Time
+get_server_time (Display *display,
+ Window window)
+{
+ unsigned char c = 'a';
+ XEvent xevent;
+ TimeStampInfo info;
+
+ info.timestamp_prop_atom = XInternAtom (display, "_TIMESTAMP_PROP", False);
+ info.window = window;
+
+ XChangeProperty (display, window,
+ info.timestamp_prop_atom, info.timestamp_prop_atom,
+ 8, PropModeReplace, &c, 1);
+
+ XIfEvent (display, &xevent,
+ timestamp_predicate, (XPointer)&info);
+
+ return xevent.xproperty.time;
+}
+
diff --git a/plugins/clipboard/xutils.h b/plugins/clipboard/xutils.h
new file mode 100644
index 0000000..143fe44
--- /dev/null
+++ b/plugins/clipboard/xutils.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Matthias Clasen, Red Hat, Inc.
+ */
+#ifndef X_UTILS_H
+#define X_UTILS_H
+
+#include <X11/Xlib.h>
+
+
+extern Atom XA_ATOM_PAIR;
+extern Atom XA_CLIPBOARD_MANAGER;
+extern Atom XA_CLIPBOARD;
+extern Atom XA_DELETE;
+extern Atom XA_INCR;
+extern Atom XA_INSERT_PROPERTY;
+extern Atom XA_INSERT_SELECTION;
+extern Atom XA_MANAGER;
+extern Atom XA_MULTIPLE;
+extern Atom XA_NULL;
+extern Atom XA_SAVE_TARGETS;
+extern Atom XA_TARGETS;
+extern Atom XA_TIMESTAMP;
+
+extern unsigned long SELECTION_MAX_SIZE;
+
+void init_atoms (Display *display);
+
+Time get_server_time (Display *display,
+ Window window);
+
+#endif /* X_UTILS_H */
diff --git a/plugins/common/Makefile.am b/plugins/common/Makefile.am
new file mode 100644
index 0000000..447d02d
--- /dev/null
+++ b/plugins/common/Makefile.am
@@ -0,0 +1,23 @@
+
+noinst_LTLIBRARIES = libcommon.la
+
+libcommon_la_SOURCES = \
+ eggaccelerators.c \
+ eggaccelerators.h \
+ gsd-keygrab.c \
+ gsd-keygrab.h \
+ gsd-osd-window.c \
+ gsd-osd-window.h
+
+libcommon_la_CPPFLAGS = \
+ $(AM_CPPFLAGS)
+
+libcommon_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libcommon_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) $(X11_LIBS)
+
+libcommon_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS)
diff --git a/plugins/common/Makefile.in b/plugins/common/Makefile.in
new file mode 100644
index 0000000..840011d
--- /dev/null
+++ b/plugins/common/Makefile.in
@@ -0,0 +1,584 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/common
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libcommon_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libcommon_la_OBJECTS = libcommon_la-eggaccelerators.lo \
+ libcommon_la-gsd-keygrab.lo libcommon_la-gsd-osd-window.lo
+libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS)
+libcommon_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcommon_la_CFLAGS) \
+ $(CFLAGS) $(libcommon_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libcommon_la_SOURCES)
+DIST_SOURCES = $(libcommon_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = libcommon.la
+libcommon_la_SOURCES = \
+ eggaccelerators.c \
+ eggaccelerators.h \
+ gsd-keygrab.c \
+ gsd-keygrab.h \
+ gsd-osd-window.c \
+ gsd-osd-window.h
+
+libcommon_la_CPPFLAGS = \
+ $(AM_CPPFLAGS)
+
+libcommon_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libcommon_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) $(X11_LIBS)
+
+libcommon_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/common/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/common/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES)
+ $(libcommon_la_LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-eggaccelerators.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-gsd-keygrab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-gsd-osd-window.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libcommon_la-eggaccelerators.lo: eggaccelerators.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-eggaccelerators.lo -MD -MP -MF $(DEPDIR)/libcommon_la-eggaccelerators.Tpo -c -o libcommon_la-eggaccelerators.lo `test -f 'eggaccelerators.c' || echo '$(srcdir)/'`eggaccelerators.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libcommon_la-eggaccelerators.Tpo $(DEPDIR)/libcommon_la-eggaccelerators.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eggaccelerators.c' object='libcommon_la-eggaccelerators.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-eggaccelerators.lo `test -f 'eggaccelerators.c' || echo '$(srcdir)/'`eggaccelerators.c
+
+libcommon_la-gsd-keygrab.lo: gsd-keygrab.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-gsd-keygrab.lo -MD -MP -MF $(DEPDIR)/libcommon_la-gsd-keygrab.Tpo -c -o libcommon_la-gsd-keygrab.lo `test -f 'gsd-keygrab.c' || echo '$(srcdir)/'`gsd-keygrab.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libcommon_la-gsd-keygrab.Tpo $(DEPDIR)/libcommon_la-gsd-keygrab.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-keygrab.c' object='libcommon_la-gsd-keygrab.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-gsd-keygrab.lo `test -f 'gsd-keygrab.c' || echo '$(srcdir)/'`gsd-keygrab.c
+
+libcommon_la-gsd-osd-window.lo: gsd-osd-window.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-gsd-osd-window.lo -MD -MP -MF $(DEPDIR)/libcommon_la-gsd-osd-window.Tpo -c -o libcommon_la-gsd-osd-window.lo `test -f 'gsd-osd-window.c' || echo '$(srcdir)/'`gsd-osd-window.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libcommon_la-gsd-osd-window.Tpo $(DEPDIR)/libcommon_la-gsd-osd-window.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-osd-window.c' object='libcommon_la-gsd-osd-window.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-gsd-osd-window.lo `test -f 'gsd-osd-window.c' || echo '$(srcdir)/'`gsd-osd-window.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/common/eggaccelerators.c b/plugins/common/eggaccelerators.c
new file mode 100644
index 0000000..e3b8ae3
--- /dev/null
+++ b/plugins/common/eggaccelerators.c
@@ -0,0 +1,658 @@
+/* eggaccelerators.c
+ * Copyright (C) 2002 Red Hat, Inc.; Copyright 1998, 2001 Tim Janik
+ * Developed by Havoc Pennington, Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "eggaccelerators.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+enum
+{
+ EGG_MODMAP_ENTRY_SHIFT = 0,
+ EGG_MODMAP_ENTRY_LOCK = 1,
+ EGG_MODMAP_ENTRY_CONTROL = 2,
+ EGG_MODMAP_ENTRY_MOD1 = 3,
+ EGG_MODMAP_ENTRY_MOD2 = 4,
+ EGG_MODMAP_ENTRY_MOD3 = 5,
+ EGG_MODMAP_ENTRY_MOD4 = 6,
+ EGG_MODMAP_ENTRY_MOD5 = 7,
+ EGG_MODMAP_ENTRY_LAST = 8
+};
+
+#define MODMAP_ENTRY_TO_MODIFIER(x) (1 << (x))
+
+typedef struct
+{
+ EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST];
+
+} EggModmap;
+
+const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap);
+
+static inline gboolean
+is_alt (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'a' || string[1] == 'A') &&
+ (string[2] == 'l' || string[2] == 'L') &&
+ (string[3] == 't' || string[3] == 'T') &&
+ (string[4] == '>'));
+}
+
+static inline gboolean
+is_ctl (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'c' || string[1] == 'C') &&
+ (string[2] == 't' || string[2] == 'T') &&
+ (string[3] == 'l' || string[3] == 'L') &&
+ (string[4] == '>'));
+}
+
+static inline gboolean
+is_modx (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'm' || string[1] == 'M') &&
+ (string[2] == 'o' || string[2] == 'O') &&
+ (string[3] == 'd' || string[3] == 'D') &&
+ (string[4] >= '1' && string[4] <= '5') &&
+ (string[5] == '>'));
+}
+
+static inline gboolean
+is_ctrl (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'c' || string[1] == 'C') &&
+ (string[2] == 't' || string[2] == 'T') &&
+ (string[3] == 'r' || string[3] == 'R') &&
+ (string[4] == 'l' || string[4] == 'L') &&
+ (string[5] == '>'));
+}
+
+static inline gboolean
+is_shft (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 's' || string[1] == 'S') &&
+ (string[2] == 'h' || string[2] == 'H') &&
+ (string[3] == 'f' || string[3] == 'F') &&
+ (string[4] == 't' || string[4] == 'T') &&
+ (string[5] == '>'));
+}
+
+static inline gboolean
+is_shift (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 's' || string[1] == 'S') &&
+ (string[2] == 'h' || string[2] == 'H') &&
+ (string[3] == 'i' || string[3] == 'I') &&
+ (string[4] == 'f' || string[4] == 'F') &&
+ (string[5] == 't' || string[5] == 'T') &&
+ (string[6] == '>'));
+}
+
+static inline gboolean
+is_control (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'c' || string[1] == 'C') &&
+ (string[2] == 'o' || string[2] == 'O') &&
+ (string[3] == 'n' || string[3] == 'N') &&
+ (string[4] == 't' || string[4] == 'T') &&
+ (string[5] == 'r' || string[5] == 'R') &&
+ (string[6] == 'o' || string[6] == 'O') &&
+ (string[7] == 'l' || string[7] == 'L') &&
+ (string[8] == '>'));
+}
+
+static inline gboolean
+is_release (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'r' || string[1] == 'R') &&
+ (string[2] == 'e' || string[2] == 'E') &&
+ (string[3] == 'l' || string[3] == 'L') &&
+ (string[4] == 'e' || string[4] == 'E') &&
+ (string[5] == 'a' || string[5] == 'A') &&
+ (string[6] == 's' || string[6] == 'S') &&
+ (string[7] == 'e' || string[7] == 'E') &&
+ (string[8] == '>'));
+}
+
+static inline gboolean
+is_meta (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'm' || string[1] == 'M') &&
+ (string[2] == 'e' || string[2] == 'E') &&
+ (string[3] == 't' || string[3] == 'T') &&
+ (string[4] == 'a' || string[4] == 'A') &&
+ (string[5] == '>'));
+}
+
+static inline gboolean
+is_super (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 's' || string[1] == 'S') &&
+ (string[2] == 'u' || string[2] == 'U') &&
+ (string[3] == 'p' || string[3] == 'P') &&
+ (string[4] == 'e' || string[4] == 'E') &&
+ (string[5] == 'r' || string[5] == 'R') &&
+ (string[6] == '>'));
+}
+
+static inline gboolean
+is_hyper (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'h' || string[1] == 'H') &&
+ (string[2] == 'y' || string[2] == 'Y') &&
+ (string[3] == 'p' || string[3] == 'P') &&
+ (string[4] == 'e' || string[4] == 'E') &&
+ (string[5] == 'r' || string[5] == 'R') &&
+ (string[6] == '>'));
+}
+
+static inline gboolean
+is_keycode (const gchar *string)
+{
+ return ((string[0] == '0') &&
+ (string[1] == 'x'));
+}
+
+/**
+ * egg_accelerator_parse_virtual:
+ * @accelerator: string representing an accelerator
+ * @accelerator_key: return location for accelerator keyval
+ * @accelerator_codes: return location for a 0-terminated array
+ * of accelerator keycodes
+ * @accelerator_mods: return location for accelerator modifier mask
+ *
+ * Parses a string representing a virtual accelerator. The format
+ * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
+ * "&lt;Release&gt;z" (the last one is for key release). The parser
+ * is fairly liberal and allows lower or upper case, and also
+ * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
+ *
+ * If the parse fails, @accelerator_key and @accelerator_mods will
+ * be set to 0 (zero) and %FALSE will be returned. If the string contains
+ * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
+ * returned.
+ *
+ * The virtual vs. concrete accelerator distinction is a relic of
+ * how the X Window System works; there are modifiers Mod2-Mod5 that
+ * can represent various keyboard keys (numlock, meta, hyper, etc.),
+ * the virtual modifier represents the keyboard key, the concrete
+ * modifier the actual Mod2-Mod5 bits in the key press event.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+egg_accelerator_parse_virtual (const gchar *accelerator,
+ guint *accelerator_key,
+ guint **accelerator_codes,
+ EggVirtualModifierType *accelerator_mods)
+{
+ guint keyval;
+ GdkModifierType mods;
+ gint len;
+ gboolean bad_keyval;
+
+ if (accelerator_key)
+ *accelerator_key = 0;
+ if (accelerator_mods)
+ *accelerator_mods = 0;
+ if (accelerator_codes)
+ *accelerator_codes = NULL;
+
+ g_return_val_if_fail (accelerator != NULL, FALSE);
+
+ bad_keyval = FALSE;
+
+ keyval = 0;
+ mods = 0;
+ len = strlen (accelerator);
+ while (len)
+ {
+ if (*accelerator == '<')
+ {
+ if (len >= 9 && is_release (accelerator))
+ {
+ accelerator += 9;
+ len -= 9;
+ mods |= EGG_VIRTUAL_RELEASE_MASK;
+ }
+ else if (len >= 9 && is_control (accelerator))
+ {
+ accelerator += 9;
+ len -= 9;
+ mods |= EGG_VIRTUAL_CONTROL_MASK;
+ }
+ else if (len >= 7 && is_shift (accelerator))
+ {
+ accelerator += 7;
+ len -= 7;
+ mods |= EGG_VIRTUAL_SHIFT_MASK;
+ }
+ else if (len >= 6 && is_shft (accelerator))
+ {
+ accelerator += 6;
+ len -= 6;
+ mods |= EGG_VIRTUAL_SHIFT_MASK;
+ }
+ else if (len >= 6 && is_ctrl (accelerator))
+ {
+ accelerator += 6;
+ len -= 6;
+ mods |= EGG_VIRTUAL_CONTROL_MASK;
+ }
+ else if (len >= 6 && is_modx (accelerator))
+ {
+ static const guint mod_vals[] = {
+ EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
+ EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
+ };
+
+ len -= 6;
+ accelerator += 4;
+ mods |= mod_vals[*accelerator - '1'];
+ accelerator += 2;
+ }
+ else if (len >= 5 && is_ctl (accelerator))
+ {
+ accelerator += 5;
+ len -= 5;
+ mods |= EGG_VIRTUAL_CONTROL_MASK;
+ }
+ else if (len >= 5 && is_alt (accelerator))
+ {
+ accelerator += 5;
+ len -= 5;
+ mods |= EGG_VIRTUAL_ALT_MASK;
+ }
+ else if (len >= 6 && is_meta (accelerator))
+ {
+ accelerator += 6;
+ len -= 6;
+ mods |= EGG_VIRTUAL_META_MASK;
+ }
+ else if (len >= 7 && is_hyper (accelerator))
+ {
+ accelerator += 7;
+ len -= 7;
+ mods |= EGG_VIRTUAL_HYPER_MASK;
+ }
+ else if (len >= 7 && is_super (accelerator))
+ {
+ accelerator += 7;
+ len -= 7;
+ mods |= EGG_VIRTUAL_SUPER_MASK;
+ }
+ else
+ {
+ gchar last_ch;
+
+ last_ch = *accelerator;
+ while (last_ch && last_ch != '>')
+ {
+ last_ch = *accelerator;
+ accelerator += 1;
+ len -= 1;
+ }
+ }
+ }
+ else
+ {
+ keyval = gdk_keyval_from_name (accelerator);
+
+ if (keyval == 0)
+ {
+ /* If keyval is 0, then maybe it's a keycode. Check for 0x## */
+ if (len >= 4 && is_keycode (accelerator))
+ {
+ char keystring[5];
+ gchar *endptr;
+ gint tmp_keycode;
+
+ memcpy (keystring, accelerator, 4);
+ keystring [4] = '\000';
+
+ tmp_keycode = strtol (keystring, &endptr, 16);
+
+ if (endptr == NULL || *endptr != '\000')
+ {
+ bad_keyval = TRUE;
+ }
+ else if (accelerator_codes != NULL)
+ {
+ /* 0x00 is an invalid keycode too. */
+ if (tmp_keycode == 0) {
+ bad_keyval = TRUE;
+ } else {
+ *accelerator_codes = g_new0 (guint, 2);
+ (*accelerator_codes)[0] = tmp_keycode;
+ }
+ }
+ }
+ else
+ {
+ bad_keyval = TRUE;
+ }
+ }
+ else if (accelerator_codes != NULL)
+ {
+ GdkKeymapKey *keys;
+ gint n_keys, i, j;
+
+ if (!gdk_keymap_get_entries_for_keyval (NULL, keyval, &keys, &n_keys)) {
+ bad_keyval = TRUE;
+ } else {
+ *accelerator_codes = g_new0 (guint, n_keys + 1);
+
+ for (i = 0, j = 0; i < n_keys; ++i) {
+ if (keys[i].level == 0)
+ (*accelerator_codes)[j++] = keys[i].keycode;
+ }
+
+ if (j == 0) {
+ g_free (*accelerator_codes);
+ *accelerator_codes = NULL;
+ bad_keyval = TRUE;
+ }
+ g_free (keys);
+ }
+ }
+
+ accelerator += len;
+ len -= len;
+ }
+ }
+
+ if (accelerator_key)
+ *accelerator_key = gdk_keyval_to_lower (keyval);
+ if (accelerator_mods)
+ *accelerator_mods = mods;
+
+ return !bad_keyval;
+}
+
+/**
+ * egg_virtual_accelerator_name:
+ * @accelerator_key: accelerator keyval
+ * @accelerator_mods: accelerator modifier mask
+ * @returns: a newly-allocated accelerator name
+ *
+ * Converts an accelerator keyval and modifier mask
+ * into a string parseable by egg_accelerator_parse_virtual().
+ * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
+ * this function returns "&lt;Control&gt;q".
+ *
+ * The caller of this function must free the returned string.
+ */
+gchar*
+egg_virtual_accelerator_name (guint accelerator_key,
+ guint keycode,
+ EggVirtualModifierType accelerator_mods)
+{
+ gchar *gtk_name;
+ GdkModifierType gdkmods = 0;
+
+ egg_keymap_resolve_virtual_modifiers (NULL, accelerator_mods, &gdkmods);
+ gtk_name = gtk_accelerator_name (accelerator_key, gdkmods);
+
+ if (!accelerator_key)
+ {
+ gchar *name;
+ name = g_strdup_printf ("%s0x%02x", gtk_name, keycode);
+ g_free (gtk_name);
+ return name;
+ }
+
+ return gtk_name;
+}
+
+/**
+ * egg_virtual_accelerator_label:
+ * @accelerator_key: accelerator keyval
+ * @accelerator_mods: accelerator modifier mask
+ * @returns: a newly-allocated accelerator label
+ *
+ * Converts an accelerator keyval and modifier mask
+ * into a (possibly translated) string that can be displayed to
+ * a user.
+ * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
+ * and you use a German locale, this function returns "Strg+Q".
+ *
+ * The caller of this function must free the returned string.
+ */
+gchar*
+egg_virtual_accelerator_label (guint accelerator_key,
+ guint keycode,
+ EggVirtualModifierType accelerator_mods)
+{
+ gchar *gtk_label;
+ GdkModifierType gdkmods = 0;
+
+ egg_keymap_resolve_virtual_modifiers (NULL, accelerator_mods, &gdkmods);
+ gtk_label = gtk_accelerator_get_label (accelerator_key, gdkmods);
+
+ if (!accelerator_key)
+ {
+ gchar *label;
+ label = g_strdup_printf ("%s0x%02x", gtk_label, keycode);
+ g_free (gtk_label);
+ return label;
+ }
+
+ return gtk_label;
+}
+
+void
+egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap,
+ EggVirtualModifierType virtual_mods,
+ GdkModifierType *concrete_mods)
+{
+ GdkModifierType concrete;
+ int i;
+ const EggModmap *modmap;
+
+ g_return_if_fail (concrete_mods != NULL);
+ g_return_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap));
+
+ modmap = egg_keymap_get_modmap (keymap);
+
+ /* Not so sure about this algorithm. */
+
+ concrete = 0;
+ for (i = 0; i < EGG_MODMAP_ENTRY_LAST; ++i)
+ {
+ if (modmap->mapping[i] & virtual_mods)
+ concrete |= MODMAP_ENTRY_TO_MODIFIER (i);
+ }
+
+ *concrete_mods = concrete;
+}
+
+void
+egg_keymap_virtualize_modifiers (GdkKeymap *keymap,
+ GdkModifierType concrete_mods,
+ EggVirtualModifierType *virtual_mods)
+{
+ GdkModifierType virtual;
+ int i;
+ const EggModmap *modmap;
+
+ g_return_if_fail (virtual_mods != NULL);
+ g_return_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap));
+
+ modmap = egg_keymap_get_modmap (keymap);
+
+ /* Not so sure about this algorithm. */
+
+ virtual = 0;
+ for (i = 0; i < EGG_MODMAP_ENTRY_LAST; ++i)
+ {
+ if (MODMAP_ENTRY_TO_MODIFIER (i) & concrete_mods)
+ {
+ EggVirtualModifierType cleaned;
+
+ cleaned = modmap->mapping[i] & ~(EGG_VIRTUAL_MOD2_MASK |
+ EGG_VIRTUAL_MOD3_MASK |
+ EGG_VIRTUAL_MOD4_MASK |
+ EGG_VIRTUAL_MOD5_MASK);
+
+ if (cleaned != 0)
+ {
+ virtual |= cleaned;
+ }
+ else
+ {
+ /* Rather than dropping mod2->mod5 if not bound,
+ * go ahead and use the concrete names
+ */
+ virtual |= modmap->mapping[i];
+ }
+ }
+ }
+
+ *virtual_mods = virtual;
+}
+
+static void
+reload_modmap (GdkKeymap *keymap,
+ EggModmap *modmap)
+{
+ XModifierKeymap *xmodmap;
+ int map_size;
+ int i;
+
+ /* FIXME multihead */
+ xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ());
+
+ memset (modmap->mapping, 0, sizeof (modmap->mapping));
+
+ /* there are 8 modifiers in the order shift, shift lock,
+ * control, mod1-5 with up to max_keypermod bindings each
+ */
+ map_size = 8 * xmodmap->max_keypermod;
+ for (i = 3 * xmodmap->max_keypermod; i < map_size; ++i)
+ {
+ /* get the key code at this point in the map,
+ * see if its keysym is one we're interested in
+ */
+ int keycode = xmodmap->modifiermap[i];
+ GdkKeymapKey *keys;
+ guint *keyvals;
+ int n_entries;
+ int j;
+ EggVirtualModifierType mask;
+
+ keys = NULL;
+ keyvals = NULL;
+ n_entries = 0;
+
+ gdk_keymap_get_entries_for_keycode (keymap,
+ keycode,
+ &keys, &keyvals, &n_entries);
+
+ mask = 0;
+ for (j = 0; j < n_entries; ++j)
+ {
+ if (keyvals[j] == GDK_Num_Lock)
+ mask |= EGG_VIRTUAL_NUM_LOCK_MASK;
+ else if (keyvals[j] == GDK_Scroll_Lock)
+ mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK;
+ else if (keyvals[j] == GDK_Meta_L ||
+ keyvals[j] == GDK_Meta_R)
+ mask |= EGG_VIRTUAL_META_MASK;
+ else if (keyvals[j] == GDK_Hyper_L ||
+ keyvals[j] == GDK_Hyper_R)
+ mask |= EGG_VIRTUAL_HYPER_MASK;
+ else if (keyvals[j] == GDK_Super_L ||
+ keyvals[j] == GDK_Super_R)
+ mask |= EGG_VIRTUAL_SUPER_MASK;
+ else if (keyvals[j] == GDK_Mode_switch)
+ mask |= EGG_VIRTUAL_MODE_SWITCH_MASK;
+ }
+
+ /* Mod1Mask is 1 << 3 for example, i.e. the
+ * fourth modifier, i / keyspermod is the modifier
+ * index
+ */
+ modmap->mapping[i/xmodmap->max_keypermod] |= mask;
+
+ g_free (keyvals);
+ g_free (keys);
+ }
+
+ /* Add in the not-really-virtual fixed entries */
+ modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] |= EGG_VIRTUAL_SHIFT_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] |= EGG_VIRTUAL_CONTROL_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_LOCK] |= EGG_VIRTUAL_LOCK_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_MOD1] |= EGG_VIRTUAL_ALT_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_MOD2] |= EGG_VIRTUAL_MOD2_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_MOD3] |= EGG_VIRTUAL_MOD3_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_MOD4] |= EGG_VIRTUAL_MOD4_MASK;
+ modmap->mapping[EGG_MODMAP_ENTRY_MOD5] |= EGG_VIRTUAL_MOD5_MASK;
+
+ XFreeModifiermap (xmodmap);
+}
+
+const EggModmap*
+egg_keymap_get_modmap (GdkKeymap *keymap)
+{
+ EggModmap *modmap;
+
+ if (keymap == NULL)
+ keymap = gdk_keymap_get_default ();
+
+ /* This is all a hack, much simpler when we can just
+ * modify GDK directly.
+ */
+
+ modmap = g_object_get_data (G_OBJECT (keymap), "egg-modmap");
+
+ if (modmap == NULL)
+ {
+ modmap = g_new0 (EggModmap, 1);
+
+ /* FIXME modify keymap change events with an event filter
+ * and force a reload if we get one
+ */
+
+ reload_modmap (keymap, modmap);
+
+ g_object_set_data_full (G_OBJECT (keymap),
+ "egg-modmap",
+ modmap,
+ g_free);
+ }
+
+ g_assert (modmap != NULL);
+
+ return modmap;
+}
diff --git a/plugins/common/eggaccelerators.h b/plugins/common/eggaccelerators.h
new file mode 100644
index 0000000..786b11f
--- /dev/null
+++ b/plugins/common/eggaccelerators.h
@@ -0,0 +1,99 @@
+/* eggaccelerators.h
+ * Copyright (C) 2002 Red Hat, Inc.
+ * Developed by Havoc Pennington
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_ACCELERATORS_H__
+#define __EGG_ACCELERATORS_H__
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Where a value is also in GdkModifierType we coincide,
+ * otherwise we don't overlap.
+ */
+typedef enum
+{
+ EGG_VIRTUAL_SHIFT_MASK = 1 << 0,
+ EGG_VIRTUAL_LOCK_MASK = 1 << 1,
+ EGG_VIRTUAL_CONTROL_MASK = 1 << 2,
+
+ EGG_VIRTUAL_ALT_MASK = 1 << 3, /* fixed as Mod1 */
+
+ EGG_VIRTUAL_MOD2_MASK = 1 << 4,
+ EGG_VIRTUAL_MOD3_MASK = 1 << 5,
+ EGG_VIRTUAL_MOD4_MASK = 1 << 6,
+ EGG_VIRTUAL_MOD5_MASK = 1 << 7,
+
+#if 0
+ GDK_BUTTON1_MASK = 1 << 8,
+ GDK_BUTTON2_MASK = 1 << 9,
+ GDK_BUTTON3_MASK = 1 << 10,
+ GDK_BUTTON4_MASK = 1 << 11,
+ GDK_BUTTON5_MASK = 1 << 12,
+ /* 13, 14 are used by Xkb for the keyboard group */
+#endif
+
+ EGG_VIRTUAL_MODE_SWITCH_MASK = 1 << 23,
+ EGG_VIRTUAL_NUM_LOCK_MASK = 1 << 24,
+ EGG_VIRTUAL_SCROLL_LOCK_MASK = 1 << 25,
+
+ /* Also in GdkModifierType */
+ EGG_VIRTUAL_SUPER_MASK = 1 << 26,
+ EGG_VIRTUAL_HYPER_MASK = 1 << 27,
+ EGG_VIRTUAL_META_MASK = 1 << 28,
+
+ /* Also in GdkModifierType */
+ EGG_VIRTUAL_RELEASE_MASK = 1 << 30,
+
+ /* 28-31 24-27 20-23 16-19 12-15 8-11 4-7 0-3
+ * 5 f 8 0 0 0 f f
+ */
+ EGG_VIRTUAL_MODIFIER_MASK = 0x5f8000ff
+
+} EggVirtualModifierType;
+
+gboolean egg_accelerator_parse_virtual (const gchar *accelerator,
+ guint *accelerator_key,
+ guint **accelerator_codes,
+ EggVirtualModifierType *accelerator_mods);
+void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap,
+ EggVirtualModifierType virtual_mods,
+ GdkModifierType *concrete_mods);
+void egg_keymap_virtualize_modifiers (GdkKeymap *keymap,
+ GdkModifierType concrete_mods,
+ EggVirtualModifierType *virtual_mods);
+
+gchar* egg_virtual_accelerator_name (guint accelerator_key,
+ guint keycode,
+ EggVirtualModifierType accelerator_mods);
+
+gchar* egg_virtual_accelerator_label (guint accelerator_key,
+ guint keycode,
+ EggVirtualModifierType accelerator_mods);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __EGG_ACCELERATORS_H__ */
diff --git a/plugins/common/gsd-keygrab.c b/plugins/common/gsd-keygrab.c
new file mode 100644
index 0000000..7d70665
--- /dev/null
+++ b/plugins/common/gsd-keygrab.c
@@ -0,0 +1,246 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2001-2003 Bastien Nocera <[email protected]>
+ * Copyright (C) 2006-2007 William Jon McCann <[email protected]>
+ * Copyright (C) 2008 Jens Granseuer <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKB.h>
+#include <gdk/gdkkeysyms.h>
+#endif
+
+#include "eggaccelerators.h"
+
+#include "gsd-keygrab.h"
+
+/* these are the mods whose combinations are ignored by the keygrabbing code */
+static GdkModifierType gsd_ignored_mods = 0;
+
+/* these are the ones we actually use for global keys, we always only check
+ * for these set */
+static GdkModifierType gsd_used_mods = 0;
+
+static void
+setup_modifiers (void)
+{
+ if (gsd_used_mods == 0 || gsd_ignored_mods == 0) {
+ GdkModifierType dynmods;
+
+ /* default modifiers */
+ gsd_ignored_mods = \
+ 0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | GDK_HYPER_MASK;
+ gsd_used_mods = \
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK |\
+ GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK |\
+ GDK_MOD5_MASK | GDK_SUPER_MASK | GDK_META_MASK;
+
+ /* NumLock can be assigned to varying keys so we need to
+ * resolve and ignore it specially */
+ dynmods = 0;
+ egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_default (),
+ EGG_VIRTUAL_NUM_LOCK_MASK,
+ &dynmods);
+
+ gsd_ignored_mods |= dynmods;
+ gsd_used_mods &= ~dynmods;
+ }
+}
+
+static void
+grab_key_real (guint keycode,
+ GdkWindow *root,
+ gboolean grab,
+ int mask)
+{
+ if (grab) {
+ XGrabKey (GDK_DISPLAY (),
+ keycode,
+ mask,
+ GDK_WINDOW_XID (root),
+ True,
+ GrabModeAsync,
+ GrabModeAsync);
+ } else {
+ XUngrabKey (GDK_DISPLAY (),
+ keycode,
+ mask,
+ GDK_WINDOW_XID (root));
+ }
+}
+
+/* Grab the key. In order to ignore GSD_IGNORED_MODS we need to grab
+ * all combinations of the ignored modifiers and those actually used
+ * for the binding (if any).
+ *
+ * inspired by all_combinations from mate-panel/mate-panel/global-keys.c
+ *
+ * This may generate X errors. The correct way to use this is like:
+ *
+ * gdk_error_trap_push ();
+ *
+ * grab_key_unsafe (key, grab, screens);
+ *
+ * gdk_flush ();
+ * if (gdk_error_trap_pop ())
+ * g_warning ("Grab failed, another application may already have access to key '%u'",
+ * key->keycode);
+ *
+ * This is not done in the function itself, to allow doing multiple grab_key
+ * operations with one flush only.
+ */
+#define N_BITS 32
+void
+grab_key_unsafe (Key *key,
+ gboolean grab,
+ GSList *screens)
+{
+ int indexes[N_BITS]; /* indexes of bits we need to flip */
+ int i;
+ int bit;
+ int bits_set_cnt;
+ int uppervalue;
+ guint mask;
+
+ setup_modifiers ();
+
+ mask = gsd_ignored_mods & ~key->state & GDK_MODIFIER_MASK;
+
+ bit = 0;
+ /* store the indexes of all set bits in mask in the array */
+ for (i = 0; mask; ++i, mask >>= 1) {
+ if (mask & 0x1) {
+ indexes[bit++] = i;
+ }
+ }
+
+ bits_set_cnt = bit;
+
+ uppervalue = 1 << bits_set_cnt;
+ /* grab all possible modifier combinations for our mask */
+ for (i = 0; i < uppervalue; ++i) {
+ GSList *l;
+ int j;
+ int result = 0;
+
+ /* map bits in the counter to those in the mask */
+ for (j = 0; j < bits_set_cnt; ++j) {
+ if (i & (1 << j)) {
+ result |= (1 << indexes[j]);
+ }
+ }
+
+ for (l = screens; l; l = l->next) {
+ GdkScreen *screen = l->data;
+ guint *code;
+
+ for (code = key->keycodes; *code; ++code) {
+ grab_key_real (*code,
+ gdk_screen_get_root_window (screen),
+ grab,
+ result | key->state);
+ }
+ }
+ }
+}
+
+static gboolean
+have_xkb (Display *dpy)
+{
+ static int have_xkb = -1;
+
+ if (have_xkb == -1) {
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ int opcode, error_base, major, minor, xkb_event_base;
+
+ have_xkb = XkbQueryExtension (dpy,
+ &opcode,
+ &xkb_event_base,
+ &error_base,
+ &major,
+ &minor)
+ && XkbUseExtension (dpy, &major, &minor);
+#else
+ have_xkb = 0;
+#endif
+ }
+
+ return have_xkb;
+}
+
+gboolean
+key_uses_keycode (const Key *key, guint keycode)
+{
+ if (key->keycodes != NULL) {
+ guint *c;
+
+ for (c = key->keycodes; *c; ++c) {
+ if (*c == keycode)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+gboolean
+match_key (Key *key, XEvent *event)
+{
+ guint keyval;
+ GdkModifierType consumed;
+ gint group;
+
+ if (key == NULL)
+ return FALSE;
+
+ setup_modifiers ();
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ if (have_xkb (event->xkey.display))
+ group = XkbGroupForCoreState (event->xkey.state);
+ else
+#endif
+ group = (event->xkey.state & GDK_Mode_switch) ? 1 : 0;
+
+ /* Check if we find a keysym that matches our current state */
+ if (gdk_keymap_translate_keyboard_state (NULL, event->xkey.keycode,
+ event->xkey.state, group,
+ &keyval, NULL, NULL, &consumed)) {
+ guint lower, upper;
+
+ gdk_keyval_convert_case (keyval, &lower, &upper);
+
+ /* If we are checking against the lower version of the
+ * keysym, we might need the Shift state for matching,
+ * so remove it from the consumed modifiers */
+ if (lower == key->keysym)
+ consumed &= ~GDK_SHIFT_MASK;
+
+ return ((lower == key->keysym || upper == key->keysym)
+ && (event->xkey.state & ~consumed & gsd_used_mods) == key->state);
+ }
+
+ /* The key we passed doesn't have a keysym, so try with just the keycode */
+ return (key != NULL
+ && key->state == (event->xkey.state & gsd_used_mods)
+ && key_uses_keycode (key, event->xkey.keycode));
+}
diff --git a/plugins/common/gsd-keygrab.h b/plugins/common/gsd-keygrab.h
new file mode 100644
index 0000000..a157ab4
--- /dev/null
+++ b/plugins/common/gsd-keygrab.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Jens Granseuer <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSD_COMMON_KEYGRAB_H
+#define __GSD_COMMON_KEYGRAB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <glib.h>
+#include <X11/keysym.h>
+
+typedef struct {
+ guint keysym;
+ guint state;
+ guint *keycodes;
+} Key;
+
+
+void grab_key_unsafe (Key *key,
+ gboolean grab,
+ GSList *screens);
+
+gboolean match_key (Key *key,
+ XEvent *event);
+
+gboolean key_uses_keycode (const Key *key,
+ guint keycode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_COMMON_KEYGRAB_H */
diff --git a/plugins/common/gsd-osd-window.c b/plugins/common/gsd-osd-window.c
new file mode 100644
index 0000000..03ca316
--- /dev/null
+++ b/plugins/common/gsd-osd-window.c
@@ -0,0 +1,573 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * On-screen-display (OSD) window for mate-settings-daemon's plugins
+ *
+ * Copyright (C) 2006-2007 William Jon McCann <[email protected]>
+ * Copyright (C) 2009 Novell, Inc
+ *
+ * Authors:
+ * William Jon McCann <[email protected]>
+ * Federico Mena-Quintero <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-osd-window.h"
+
+#define DIALOG_TIMEOUT 2000 /* dialog timeout in ms */
+#define DIALOG_FADE_TIMEOUT 1500 /* timeout before fade starts */
+#define FADE_TIMEOUT 10 /* timeout in ms between each frame of the fade */
+
+#define BG_ALPHA 0.75
+
+#define GSD_OSD_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_OSD_WINDOW, GsdOsdWindowPrivate))
+
+struct GsdOsdWindowPrivate
+{
+ guint is_composited : 1;
+ guint hide_timeout_id;
+ guint fade_timeout_id;
+ double fade_out_alpha;
+};
+
+enum {
+ EXPOSE_WHEN_COMPOSITED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GsdOsdWindow, gsd_osd_window, GTK_TYPE_WINDOW)
+
+static gboolean
+fade_timeout (GsdOsdWindow *window)
+{
+ if (window->priv->fade_out_alpha <= 0.0) {
+ gtk_widget_hide (GTK_WIDGET (window));
+
+ /* Reset it for the next time */
+ window->priv->fade_out_alpha = 1.0;
+ window->priv->fade_timeout_id = 0;
+
+ return FALSE;
+ } else {
+ GdkRectangle rect;
+ GtkWidget *win = GTK_WIDGET (window);
+ GtkAllocation allocation;
+
+ window->priv->fade_out_alpha -= 0.10;
+
+ rect.x = 0;
+ rect.y = 0;
+ gtk_widget_get_allocation (win, &allocation);
+ rect.width = allocation.width;
+ rect.height = allocation.height;
+
+ gtk_widget_realize (win);
+ gdk_window_invalidate_rect (gtk_widget_get_window (win), &rect, FALSE);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+hide_timeout (GsdOsdWindow *window)
+{
+ if (window->priv->is_composited) {
+ window->priv->hide_timeout_id = 0;
+ window->priv->fade_timeout_id = g_timeout_add (FADE_TIMEOUT,
+ (GSourceFunc) fade_timeout,
+ window);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (window));
+ }
+
+ return FALSE;
+}
+
+static void
+remove_hide_timeout (GsdOsdWindow *window)
+{
+ if (window->priv->hide_timeout_id != 0) {
+ g_source_remove (window->priv->hide_timeout_id);
+ window->priv->hide_timeout_id = 0;
+ }
+
+ if (window->priv->fade_timeout_id != 0) {
+ g_source_remove (window->priv->fade_timeout_id);
+ window->priv->fade_timeout_id = 0;
+ window->priv->fade_out_alpha = 1.0;
+ }
+}
+
+static void
+add_hide_timeout (GsdOsdWindow *window)
+{
+ int timeout;
+
+ if (window->priv->is_composited) {
+ timeout = DIALOG_FADE_TIMEOUT;
+ } else {
+ timeout = DIALOG_TIMEOUT;
+ }
+ window->priv->hide_timeout_id = g_timeout_add (timeout,
+ (GSourceFunc) hide_timeout,
+ window);
+}
+
+void
+gsd_osd_window_draw_rounded_rectangle (cairo_t* cr,
+ gdouble aspect,
+ gdouble x,
+ gdouble y,
+ gdouble corner_radius,
+ gdouble width,
+ gdouble height)
+{
+ gdouble radius = corner_radius / aspect;
+
+ cairo_move_to (cr, x + radius, y);
+
+ cairo_line_to (cr,
+ x + width - radius,
+ y);
+ cairo_arc (cr,
+ x + width - radius,
+ y + radius,
+ radius,
+ -90.0f * G_PI / 180.0f,
+ 0.0f * G_PI / 180.0f);
+ cairo_line_to (cr,
+ x + width,
+ y + height - radius);
+ cairo_arc (cr,
+ x + width - radius,
+ y + height - radius,
+ radius,
+ 0.0f * G_PI / 180.0f,
+ 90.0f * G_PI / 180.0f);
+ cairo_line_to (cr,
+ x + radius,
+ y + height);
+ cairo_arc (cr,
+ x + radius,
+ y + height - radius,
+ radius,
+ 90.0f * G_PI / 180.0f,
+ 180.0f * G_PI / 180.0f);
+ cairo_line_to (cr,
+ x,
+ y + radius);
+ cairo_arc (cr,
+ x + radius,
+ y + radius,
+ radius,
+ 180.0f * G_PI / 180.0f,
+ 270.0f * G_PI / 180.0f);
+ cairo_close_path (cr);
+}
+
+void
+gsd_osd_window_color_reverse (const GdkColor *a,
+ GdkColor *b)
+{
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble h;
+ gdouble s;
+ gdouble v;
+
+ red = (gdouble) a->red / 65535.0;
+ green = (gdouble) a->green / 65535.0;
+ blue = (gdouble) a->blue / 65535.0;
+
+ gtk_rgb_to_hsv (red, green, blue, &h, &s, &v);
+
+ v = 0.5 + (0.5 - v);
+ if (v > 1.0)
+ v = 1.0;
+ else if (v < 0.0)
+ v = 0.0;
+
+ gtk_hsv_to_rgb (h, s, v, &red, &green, &blue);
+
+ b->red = red * 65535.0;
+ b->green = green * 65535.0;
+ b->blue = blue * 65535.0;
+}
+
+/* This is our expose-event handler when the window is in a compositing manager.
+ * We draw everything by hand, using Cairo, so that we can have a nice
+ * transparent/rounded look.
+ */
+static void
+expose_when_composited (GtkWidget *widget, GdkEventExpose *event)
+{
+ GsdOsdWindow *window;
+ cairo_t *context;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ int width;
+ int height;
+ GtkStyle *style;
+ GdkColor color;
+ double r, g, b;
+
+ window = GSD_OSD_WINDOW (widget);
+
+ context = gdk_cairo_create (gtk_widget_get_window (widget));
+
+ style = gtk_widget_get_style (widget);
+ cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
+ gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
+
+ surface = cairo_surface_create_similar (cairo_get_target (context),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ width,
+ height);
+
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
+ goto done;
+ }
+
+ cr = cairo_create (surface);
+ if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
+ goto done;
+ }
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_paint (cr);
+
+ /* draw a box */
+ gsd_osd_window_draw_rounded_rectangle (cr, 1.0, 0.5, 0.5, height / 10, width-1, height-1);
+ gsd_osd_window_color_reverse (&style->bg[GTK_STATE_NORMAL], &color);
+ r = (float)color.red / 65535.0;
+ g = (float)color.green / 65535.0;
+ b = (float)color.blue / 65535.0;
+ cairo_set_source_rgba (cr, r, g, b, BG_ALPHA);
+ cairo_fill_preserve (cr);
+
+ gsd_osd_window_color_reverse (&style->text_aa[GTK_STATE_NORMAL], &color);
+ r = (float)color.red / 65535.0;
+ g = (float)color.green / 65535.0;
+ b = (float)color.blue / 65535.0;
+ cairo_set_source_rgba (cr, r, g, b, BG_ALPHA / 2);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+
+ g_signal_emit (window, signals[EXPOSE_WHEN_COMPOSITED], 0, cr);
+
+ cairo_destroy (cr);
+
+ /* Make sure we have a transparent background */
+ cairo_rectangle (context, 0, 0, width, height);
+ cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 0.0);
+ cairo_fill (context);
+
+ cairo_set_source_surface (context, surface, 0, 0);
+ cairo_paint_with_alpha (context, window->priv->fade_out_alpha);
+
+ done:
+ if (surface != NULL) {
+ cairo_surface_destroy (surface);
+ }
+ cairo_destroy (context);
+}
+
+/* This is our expose-event handler when the window is *not* in a compositing manager.
+ * We just draw a rectangular frame by hand. We do this with hardcoded drawing code,
+ * instead of GtkFrame, to avoid changing the window's internal widget hierarchy: in
+ * either case (composited or non-composited), callers can assume that this works
+ * identically to a GtkWindow without any intermediate widgetry.
+ */
+static void
+expose_when_not_composited (GtkWidget *widget, GdkEventExpose *event)
+{
+ GsdOsdWindow *window;
+ GtkAllocation allocation;
+
+ window = GSD_OSD_WINDOW (widget);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ gtk_paint_shadow (gtk_widget_get_style (widget),
+ gtk_widget_get_window (widget),
+ gtk_widget_get_state (widget),
+ GTK_SHADOW_OUT,
+ &event->area,
+ widget,
+ NULL, /* NULL detail -> themes should use the GsdOsdWindow widget name, probably */
+ 0,
+ 0,
+ allocation.width,
+ allocation.height);
+}
+
+static gboolean
+gsd_osd_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GsdOsdWindow *window;
+ GtkWidget *child;
+
+ window = GSD_OSD_WINDOW (widget);
+
+ if (window->priv->is_composited)
+ expose_when_composited (widget, event);
+ else
+ expose_when_not_composited (widget, event);
+
+ child = gtk_bin_get_child (GTK_BIN (window));
+ if (child)
+ gtk_container_propagate_expose (GTK_CONTAINER (window), child, event);
+
+ return FALSE;
+}
+
+static void
+gsd_osd_window_real_show (GtkWidget *widget)
+{
+ GsdOsdWindow *window;
+
+ if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->show) {
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->show (widget);
+ }
+
+ window = GSD_OSD_WINDOW (widget);
+ remove_hide_timeout (window);
+ add_hide_timeout (window);
+}
+
+static void
+gsd_osd_window_real_hide (GtkWidget *widget)
+{
+ GsdOsdWindow *window;
+
+ if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->hide) {
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->hide (widget);
+ }
+
+ window = GSD_OSD_WINDOW (widget);
+ remove_hide_timeout (window);
+}
+
+static void
+gsd_osd_window_real_realize (GtkWidget *widget)
+{
+ GdkColormap *colormap;
+ GtkAllocation allocation;
+ GdkBitmap *mask;
+ cairo_t *cr;
+
+ colormap = gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget));
+
+ if (colormap != NULL) {
+ gtk_widget_set_colormap (widget, colormap);
+ }
+
+ if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->realize) {
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->realize (widget);
+ }
+
+ gtk_widget_get_allocation (widget, &allocation);
+ mask = gdk_pixmap_new (gtk_widget_get_window (widget),
+ allocation.width,
+ allocation.height,
+ 1);
+ cr = gdk_cairo_create (mask);
+
+ cairo_set_source_rgba (cr, 1., 1., 1., 0.);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+ /* make the whole window ignore events */
+ gdk_window_input_shape_combine_mask (gtk_widget_get_window (widget), mask, 0, 0);
+ g_object_unref (mask);
+ cairo_destroy (cr);
+}
+
+static void
+gsd_osd_window_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ GtkStyle *style;
+
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->style_set (widget, previous_style);
+
+ /* We set our border width to 12 (per the MATE standard), plus the
+ * thickness of the frame that we draw in our expose handler. This will
+ * make our child be 12 pixels away from the frame.
+ */
+
+ style = gtk_widget_get_style (widget);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 12 + MAX (style->xthickness, style->ythickness));
+}
+
+static void
+gsd_osd_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkStyle *style;
+
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->size_request (widget, requisition);
+
+ /* See the comment in gsd_osd_window_style_set() for why we add the thickness here */
+
+ style = gtk_widget_get_style (widget);
+
+ requisition->width += style->xthickness;
+ requisition->height += style->ythickness;
+}
+
+static GObject *
+gsd_osd_window_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+
+ object = G_OBJECT_CLASS (gsd_osd_window_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ g_object_set (object,
+ "type", GTK_WINDOW_POPUP,
+ "type-hint", GDK_WINDOW_TYPE_HINT_NOTIFICATION,
+ "skip-taskbar-hint", TRUE,
+ "skip-pager-hint", TRUE,
+ "focus-on-map", FALSE,
+ NULL);
+
+ return object;
+}
+
+static void
+gsd_osd_window_class_init (GsdOsdWindowClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->constructor = gsd_osd_window_constructor;
+
+ widget_class->show = gsd_osd_window_real_show;
+ widget_class->hide = gsd_osd_window_real_hide;
+ widget_class->realize = gsd_osd_window_real_realize;
+ widget_class->style_set = gsd_osd_window_style_set;
+ widget_class->size_request = gsd_osd_window_size_request;
+ widget_class->expose_event = gsd_osd_window_expose_event;
+
+ signals[EXPOSE_WHEN_COMPOSITED] = g_signal_new ("expose-when-composited",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GsdOsdWindowClass, expose_when_composited),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+
+ g_type_class_add_private (klass, sizeof (GsdOsdWindowPrivate));
+}
+
+/**
+ * gsd_osd_window_is_composited:
+ * @window: a #GsdOsdWindow
+ *
+ * Return value: whether the window was created on a composited screen.
+ */
+gboolean
+gsd_osd_window_is_composited (GsdOsdWindow *window)
+{
+ return window->priv->is_composited;
+}
+
+/**
+ * gsd_osd_window_is_valid:
+ * @window: a #GsdOsdWindow
+ *
+ * Return value: TRUE if the @window's idea of being composited matches whether
+ * its current screen is actually composited.
+ */
+gboolean
+gsd_osd_window_is_valid (GsdOsdWindow *window)
+{
+ GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
+ return gdk_screen_is_composited (screen) == window->priv->is_composited;
+}
+
+static void
+gsd_osd_window_init (GsdOsdWindow *window)
+{
+ GdkScreen *screen;
+
+ window->priv = GSD_OSD_WINDOW_GET_PRIVATE (window);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ window->priv->is_composited = gdk_screen_is_composited (screen);
+
+ if (window->priv->is_composited) {
+ gdouble scalew, scaleh, scale;
+ gint size;
+
+ gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
+ gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
+
+ /* assume 130x130 on a 640x480 display and scale from there */
+ scalew = gdk_screen_get_width (screen) / 640.0;
+ scaleh = gdk_screen_get_height (screen) / 480.0;
+ scale = MIN (scalew, scaleh);
+ size = 130 * MAX (1, scale);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), size, size);
+
+ window->priv->fade_out_alpha = 1.0;
+ } else {
+ gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+ }
+}
+
+GtkWidget *
+gsd_osd_window_new (void)
+{
+ return g_object_new (GSD_TYPE_OSD_WINDOW, NULL);
+}
+
+/**
+ * gsd_osd_window_update_and_hide:
+ * @window: a #GsdOsdWindow
+ *
+ * Queues the @window for immediate drawing, and queues a timer to hide the window.
+ */
+void
+gsd_osd_window_update_and_hide (GsdOsdWindow *window)
+{
+ remove_hide_timeout (window);
+ add_hide_timeout (window);
+
+ if (window->priv->is_composited) {
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+ }
+}
diff --git a/plugins/common/gsd-osd-window.h b/plugins/common/gsd-osd-window.h
new file mode 100644
index 0000000..0d8040b
--- /dev/null
+++ b/plugins/common/gsd-osd-window.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * On-screen-display (OSD) window for mate-settings-daemon's plugins
+ *
+ * Copyright (C) 2006 William Jon McCann <[email protected]>
+ * Copyright (C) 2009 Novell, Inc
+ *
+ * Authors:
+ * William Jon McCann <[email protected]>
+ * Federico Mena-Quintero <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* GsdOsdWindow is an "on-screen-display" window (OSD). It is the cute,
+ * semi-transparent, curved popup that appears when you press a hotkey global to
+ * the desktop, such as to change the volume, switch your monitor's parameters,
+ * etc.
+ *
+ * You can create a GsdOsdWindow and use it as a normal GtkWindow. It will
+ * automatically center itself, figure out if it needs to be composited, etc.
+ * Just pack your widgets in it, sit back, and enjoy the ride.
+ */
+
+#ifndef GSD_OSD_WINDOW_H
+#define GSD_OSD_WINDOW_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alpha value to be used for foreground objects drawn in an OSD window */
+#define GSD_OSD_WINDOW_FG_ALPHA 1.0
+
+#define GSD_TYPE_OSD_WINDOW (gsd_osd_window_get_type ())
+#define GSD_OSD_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_OSD_WINDOW, GsdOsdWindow))
+#define GSD_OSD_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_OSD_WINDOW, GsdOsdWindowClass))
+#define GSD_IS_OSD_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_OSD_WINDOW))
+#define GSD_IS_OSD_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), GSD_TYPE_OSD_WINDOW))
+#define GSD_OSD_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_OSD_WINDOW, GsdOsdWindowClass))
+
+typedef struct GsdOsdWindow GsdOsdWindow;
+typedef struct GsdOsdWindowClass GsdOsdWindowClass;
+typedef struct GsdOsdWindowPrivate GsdOsdWindowPrivate;
+
+struct GsdOsdWindow {
+ GtkWindow parent;
+
+ GsdOsdWindowPrivate *priv;
+};
+
+struct GsdOsdWindowClass {
+ GtkWindowClass parent_class;
+
+ void (* expose_when_composited) (GsdOsdWindow *window, cairo_t *cr);
+};
+
+GType gsd_osd_window_get_type (void);
+
+GtkWidget * gsd_osd_window_new (void);
+gboolean gsd_osd_window_is_composited (GsdOsdWindow *window);
+gboolean gsd_osd_window_is_valid (GsdOsdWindow *window);
+void gsd_osd_window_update_and_hide (GsdOsdWindow *window);
+
+void gsd_osd_window_draw_rounded_rectangle (cairo_t *cr,
+ gdouble aspect,
+ gdouble x,
+ gdouble y,
+ gdouble corner_radius,
+ gdouble width,
+ gdouble height);
+
+void gsd_osd_window_color_reverse (const GdkColor *a,
+ GdkColor *b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/datetime/Makefile.am b/plugins/datetime/Makefile.am
new file mode 100644
index 0000000..1ae28f7
--- /dev/null
+++ b/plugins/datetime/Makefile.am
@@ -0,0 +1,60 @@
+dbus_servicesdir = $(datadir)/dbus-1/system-services
+dbus_confdir = $(sysconfdir)/dbus-1/system.d
+polkitdir = $(datadir)/polkit-1/actions
+
+dbus_services_in_files = org.mate.SettingsDaemon.DateTimeMechanism.service.in
+polkit_in_files = org.mate.settingsdaemon.datetimemechanism.policy.in
+
+gsd-datetime-mechanism-glue.h: $(srcdir)/gsd-datetime-mechanism.xml
+ $(AM_V_GEN)dbus-binding-tool \
+ --prefix=gsd_datetime_mechanism --mode=glib-server \
+ --output=gsd-datetime-mechanism-glue.h \
+ $(srcdir)/gsd-datetime-mechanism.xml
+
+if HAVE_POLKIT
+libexec_PROGRAMS = gsd-datetime-mechanism
+endif
+
+gsd_datetime_mechanism_SOURCES = \
+ gsd-datetime-mechanism.c \
+ gsd-datetime-mechanism.h \
+ gsd-datetime-mechanism-main.c \
+ system-timezone.c \
+ system-timezone.h
+
+
+if HAVE_POLKIT
+BUILT_SOURCES = gsd-datetime-mechanism-glue.h
+endif
+
+AM_CFLAGS = $(SETTINGS_PLUGIN_CFLAGS) $(POLKIT_CFLAGS)
+gsd_datetime_mechanism_LDADD = $(POLKIT_LIBS) $(SETTINGS_PLUGIN_LIBS)
+
+
+if HAVE_POLKIT
+dbus_services_DATA = $(dbus_services_in_files:.service.in=.service)
+
+$(dbus_services_DATA): $(dbus_services_in_files)
+ $(AM_V_GEN)sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@
+
+dbus_conf_DATA = org.mate.SettingsDaemon.DateTimeMechanism.conf
+
+@INTLTOOL_POLICY_RULE@
+polkit_DATA = $(polkit_in_files:.policy.in=.policy)
+
+else
+dbus_services_DATA =
+dbus_conf_DATA =
+polkit_DATA =
+endif
+
+EXTRA_DIST = \
+ $(dbus_services_in_files) \
+ org.mate.SettingsDaemon.DateTimeMechanism.conf \
+ $(polkit_in_files) \
+ gsd-datetime-mechanism.xml
+
+CLEANFILES = \
+ org.mate.SettingsDaemon.DateTimeMechanism.service \
+ org.mate.settingsdaemon.datetimemechanism.policy \
+ $(BUILT_SOURCES) \ No newline at end of file
diff --git a/plugins/datetime/Makefile.in b/plugins/datetime/Makefile.in
new file mode 100644
index 0000000..ab5da48
--- /dev/null
+++ b/plugins/datetime/Makefile.in
@@ -0,0 +1,719 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_POLKIT_TRUE@libexec_PROGRAMS = gsd-datetime-mechanism$(EXEEXT)
+subdir = plugins/datetime
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(libexecdir)" \
+ "$(DESTDIR)$(dbus_confdir)" "$(DESTDIR)$(dbus_servicesdir)" \
+ "$(DESTDIR)$(polkitdir)"
+PROGRAMS = $(libexec_PROGRAMS)
+am_gsd_datetime_mechanism_OBJECTS = gsd-datetime-mechanism.$(OBJEXT) \
+ gsd-datetime-mechanism-main.$(OBJEXT) \
+ system-timezone.$(OBJEXT)
+gsd_datetime_mechanism_OBJECTS = $(am_gsd_datetime_mechanism_OBJECTS)
+am__DEPENDENCIES_1 =
+gsd_datetime_mechanism_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(gsd_datetime_mechanism_SOURCES)
+DIST_SOURCES = $(gsd_datetime_mechanism_SOURCES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+DATA = $(dbus_conf_DATA) $(dbus_services_DATA) $(polkit_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+dbus_servicesdir = $(datadir)/dbus-1/system-services
+dbus_confdir = $(sysconfdir)/dbus-1/system.d
+polkitdir = $(datadir)/polkit-1/actions
+dbus_services_in_files = org.mate.SettingsDaemon.DateTimeMechanism.service.in
+polkit_in_files = org.mate.settingsdaemon.datetimemechanism.policy.in
+gsd_datetime_mechanism_SOURCES = \
+ gsd-datetime-mechanism.c \
+ gsd-datetime-mechanism.h \
+ gsd-datetime-mechanism-main.c \
+ system-timezone.c \
+ system-timezone.h
+
+@HAVE_POLKIT_TRUE@BUILT_SOURCES = gsd-datetime-mechanism-glue.h
+AM_CFLAGS = $(SETTINGS_PLUGIN_CFLAGS) $(POLKIT_CFLAGS)
+gsd_datetime_mechanism_LDADD = $(POLKIT_LIBS) $(SETTINGS_PLUGIN_LIBS)
+@HAVE_POLKIT_FALSE@dbus_services_DATA =
+@HAVE_POLKIT_TRUE@dbus_services_DATA = $(dbus_services_in_files:.service.in=.service)
+@HAVE_POLKIT_FALSE@dbus_conf_DATA =
+@HAVE_POLKIT_TRUE@dbus_conf_DATA = org.mate.SettingsDaemon.DateTimeMechanism.conf
+@HAVE_POLKIT_FALSE@polkit_DATA =
+@HAVE_POLKIT_TRUE@polkit_DATA = $(polkit_in_files:.policy.in=.policy)
+EXTRA_DIST = \
+ $(dbus_services_in_files) \
+ org.mate.SettingsDaemon.DateTimeMechanism.conf \
+ $(polkit_in_files) \
+ gsd-datetime-mechanism.xml
+
+CLEANFILES = \
+ org.mate.SettingsDaemon.DateTimeMechanism.service \
+ org.mate.settingsdaemon.datetimemechanism.policy \
+ $(BUILT_SOURCES)
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/datetime/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/datetime/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libexecPROGRAMS: $(libexec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)"
+ @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-libexecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files
+
+clean-libexecPROGRAMS:
+ @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+gsd-datetime-mechanism$(EXEEXT): $(gsd_datetime_mechanism_OBJECTS) $(gsd_datetime_mechanism_DEPENDENCIES)
+ @rm -f gsd-datetime-mechanism$(EXEEXT)
+ $(LINK) $(gsd_datetime_mechanism_OBJECTS) $(gsd_datetime_mechanism_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsd-datetime-mechanism-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsd-datetime-mechanism.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system-timezone.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-dbus_confDATA: $(dbus_conf_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(dbus_confdir)" || $(MKDIR_P) "$(DESTDIR)$(dbus_confdir)"
+ @list='$(dbus_conf_DATA)'; test -n "$(dbus_confdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbus_confdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(dbus_confdir)" || exit $$?; \
+ done
+
+uninstall-dbus_confDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dbus_conf_DATA)'; test -n "$(dbus_confdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(dbus_confdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(dbus_confdir)" && rm -f $$files
+install-dbus_servicesDATA: $(dbus_services_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(dbus_servicesdir)" || $(MKDIR_P) "$(DESTDIR)$(dbus_servicesdir)"
+ @list='$(dbus_services_DATA)'; test -n "$(dbus_servicesdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbus_servicesdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(dbus_servicesdir)" || exit $$?; \
+ done
+
+uninstall-dbus_servicesDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dbus_services_DATA)'; test -n "$(dbus_servicesdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(dbus_servicesdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(dbus_servicesdir)" && rm -f $$files
+install-polkitDATA: $(polkit_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(polkitdir)" || $(MKDIR_P) "$(DESTDIR)$(polkitdir)"
+ @list='$(polkit_DATA)'; test -n "$(polkitdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(polkitdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(polkitdir)" || exit $$?; \
+ done
+
+uninstall-polkitDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(polkit_DATA)'; test -n "$(polkitdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(polkitdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(polkitdir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(dbus_confdir)" "$(DESTDIR)$(dbus_servicesdir)" "$(DESTDIR)$(polkitdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dbus_confDATA install-dbus_servicesDATA \
+ install-polkitDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libexecPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dbus_confDATA uninstall-dbus_servicesDATA \
+ uninstall-libexecPROGRAMS uninstall-polkitDATA
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libexecPROGRAMS clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-dbus_confDATA install-dbus_servicesDATA install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libexecPROGRAMS install-man install-pdf install-pdf-am \
+ install-polkitDATA install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-dbus_confDATA \
+ uninstall-dbus_servicesDATA uninstall-libexecPROGRAMS \
+ uninstall-polkitDATA
+
+
+gsd-datetime-mechanism-glue.h: $(srcdir)/gsd-datetime-mechanism.xml
+ $(AM_V_GEN)dbus-binding-tool \
+ --prefix=gsd_datetime_mechanism --mode=glib-server \
+ --output=gsd-datetime-mechanism-glue.h \
+ $(srcdir)/gsd-datetime-mechanism.xml
+
+@HAVE_POLKIT_TRUE@$(dbus_services_DATA): $(dbus_services_in_files)
+@HAVE_POLKIT_TRUE@ $(AM_V_GEN)sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@
+
+@HAVE_POLKIT_TRUE@@INTLTOOL_POLICY_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/datetime/gsd-datetime-mechanism-main.c b/plugins/datetime/gsd-datetime-mechanism-main.c
new file mode 100644
index 0000000..7d6089f
--- /dev/null
+++ b/plugins/datetime/gsd-datetime-mechanism-main.c
@@ -0,0 +1,171 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+
+#include "gsd-datetime-mechanism.h"
+
+static DBusGProxy *
+get_bus_proxy (DBusGConnection *connection)
+{
+ DBusGProxy *bus_proxy;
+
+ bus_proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ return bus_proxy;
+}
+
+#define BUS_NAME "org.mate.SettingsDaemon.DateTimeMechanism"
+
+static gboolean
+acquire_name_on_proxy (DBusGProxy *bus_proxy)
+{
+ GError *error;
+ guint result;
+ gboolean res;
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (bus_proxy == NULL) {
+ goto out;
+ }
+
+ error = NULL;
+ res = dbus_g_proxy_call (bus_proxy,
+ "RequestName",
+ &error,
+ G_TYPE_STRING, BUS_NAME,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID);
+ if (! res) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to acquire %s", BUS_NAME);
+ }
+ goto out;
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to acquire %s", BUS_NAME);
+ }
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+static DBusGConnection *
+get_system_bus (void)
+{
+ GError *error;
+ DBusGConnection *bus;
+
+ error = NULL;
+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (bus == NULL) {
+ g_warning ("Couldn't connect to system bus: %s", error->message);
+ g_error_free (error);
+ }
+ return bus;
+}
+
+int
+main (int argc, char **argv)
+{
+ GMainLoop *loop;
+ GsdDatetimeMechanism *mechanism;
+ DBusGProxy *bus_proxy;
+ DBusGConnection *connection;
+ int ret;
+
+ ret = 1;
+
+ if (! g_thread_supported ()) {
+ g_thread_init (NULL);
+ }
+ dbus_g_thread_init ();
+ g_type_init ();
+
+ connection = get_system_bus ();
+ if (connection == NULL) {
+ goto out;
+ }
+
+ bus_proxy = get_bus_proxy (connection);
+ if (bus_proxy == NULL) {
+ g_warning ("Could not construct bus_proxy object; bailing out");
+ goto out;
+ }
+
+ if (!acquire_name_on_proxy (bus_proxy) ) {
+ g_warning ("Could not acquire name; bailing out");
+ goto out;
+ }
+
+ mechanism = gsd_datetime_mechanism_new ();
+
+ if (mechanism == NULL) {
+ goto out;
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (loop);
+
+ g_object_unref (mechanism);
+ g_main_loop_unref (loop);
+ ret = 0;
+
+out:
+ return ret;
+}
diff --git a/plugins/datetime/gsd-datetime-mechanism.c b/plugins/datetime/gsd-datetime-mechanism.c
new file mode 100644
index 0000000..5c18040
--- /dev/null
+++ b/plugins/datetime/gsd-datetime-mechanism.c
@@ -0,0 +1,646 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+
+#include "system-timezone.h"
+
+#include "gsd-datetime-mechanism.h"
+#include "gsd-datetime-mechanism-glue.h"
+
+static gboolean
+do_exit (gpointer user_data)
+{
+ g_debug ("Exiting due to inactivity");
+ exit (1);
+ return FALSE;
+}
+
+static void
+reset_killtimer (void)
+{
+ static guint timer_id = 0;
+
+ if (timer_id > 0) {
+ g_source_remove (timer_id);
+ }
+ g_debug ("Setting killtimer to 30 seconds...");
+ timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+}
+
+struct GsdDatetimeMechanismPrivate
+{
+ DBusGConnection *system_bus_connection;
+ DBusGProxy *system_bus_proxy;
+ PolkitAuthority *auth;
+};
+
+static void gsd_datetime_mechanism_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdDatetimeMechanism, gsd_datetime_mechanism, G_TYPE_OBJECT)
+
+#define GSD_DATETIME_MECHANISM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_DATETIME_TYPE_MECHANISM, GsdDatetimeMechanismPrivate))
+
+GQuark
+gsd_datetime_mechanism_error_quark (void)
+{
+ static GQuark ret = 0;
+
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("gsd_datetime_mechanism_error");
+ }
+
+ return ret;
+}
+
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+gsd_datetime_mechanism_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0)
+ {
+ static const GEnumValue values[] =
+ {
+ ENUM_ENTRY (GSD_DATETIME_MECHANISM_ERROR_GENERAL, "GeneralError"),
+ ENUM_ENTRY (GSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+ ENUM_ENTRY (GSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE, "InvalidTimezoneFile"),
+ { 0, 0, 0 }
+ };
+
+ g_assert (GSD_DATETIME_MECHANISM_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+
+ etype = g_enum_register_static ("GsdDatetimeMechanismError", values);
+ }
+
+ return etype;
+}
+
+
+static GObject *
+gsd_datetime_mechanism_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdDatetimeMechanism *mechanism;
+
+ mechanism = GSD_DATETIME_MECHANISM (G_OBJECT_CLASS (gsd_datetime_mechanism_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (mechanism);
+}
+
+static void
+gsd_datetime_mechanism_class_init (GsdDatetimeMechanismClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = gsd_datetime_mechanism_constructor;
+ object_class->finalize = gsd_datetime_mechanism_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdDatetimeMechanismPrivate));
+
+ dbus_g_object_type_install_info (GSD_DATETIME_TYPE_MECHANISM, &dbus_glib_gsd_datetime_mechanism_object_info);
+
+ dbus_g_error_domain_register (GSD_DATETIME_MECHANISM_ERROR, NULL, GSD_DATETIME_MECHANISM_TYPE_ERROR);
+
+}
+
+static void
+gsd_datetime_mechanism_init (GsdDatetimeMechanism *mechanism)
+{
+ mechanism->priv = GSD_DATETIME_MECHANISM_GET_PRIVATE (mechanism);
+
+}
+
+static void
+gsd_datetime_mechanism_finalize (GObject *object)
+{
+ GsdDatetimeMechanism *mechanism;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_DATETIME_IS_MECHANISM (object));
+
+ mechanism = GSD_DATETIME_MECHANISM (object);
+
+ g_return_if_fail (mechanism->priv != NULL);
+
+ g_object_unref (mechanism->priv->system_bus_proxy);
+
+ G_OBJECT_CLASS (gsd_datetime_mechanism_parent_class)->finalize (object);
+}
+
+static gboolean
+register_mechanism (GsdDatetimeMechanism *mechanism)
+{
+ GError *error = NULL;
+
+ mechanism->priv->auth = polkit_authority_get ();
+
+ error = NULL;
+ mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (mechanism->priv->system_bus_connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ goto error;
+ }
+
+ dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
+ G_OBJECT (mechanism));
+
+ mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ reset_killtimer ();
+
+ return TRUE;
+
+error:
+ return FALSE;
+}
+
+
+GsdDatetimeMechanism *
+gsd_datetime_mechanism_new (void)
+{
+ GObject *object;
+ gboolean res;
+
+ object = g_object_new (GSD_DATETIME_TYPE_MECHANISM, NULL);
+
+ res = register_mechanism (GSD_DATETIME_MECHANISM (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return GSD_DATETIME_MECHANISM (object);
+}
+
+static gboolean
+_check_polkit_for_action (GsdDatetimeMechanism *mechanism, DBusGMethodInvocation *context, const char *action)
+{
+ const char *sender;
+ GError *error;
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
+
+ error = NULL;
+
+ /* Check that caller is privileged */
+ sender = dbus_g_method_get_sender (context);
+ subject = polkit_system_bus_name_new (sender);
+
+ result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
+ subject,
+ action,
+ NULL,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ NULL, &error);
+ g_object_unref (subject);
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (!polkit_authorization_result_get_is_authorized (result)) {
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED,
+ "Not Authorized for action %s", action);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_object_unref (result);
+
+ return FALSE;
+ }
+
+ g_object_unref (result);
+
+ return TRUE;
+}
+
+
+static gboolean
+_set_time (GsdDatetimeMechanism *mechanism,
+ const struct timeval *tv,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+
+ if (!_check_polkit_for_action (mechanism, context, "org.mate.settingsdaemon.datetimemechanism.settime"))
+ return FALSE;
+
+ if (settimeofday (tv, NULL) != 0) {
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error calling settimeofday({%lld,%lld}): %s",
+ (gint64) tv->tv_sec, (gint64) tv->tv_usec,
+ strerror (errno));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ if (g_file_test ("/sbin/hwclock",
+ G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
+ int exit_status;
+ if (!g_spawn_command_line_sync ("/sbin/hwclock --systohc", NULL, NULL, &exit_status, &error)) {
+ GError *error2;
+ error2 = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error spawning /sbin/hwclock: %s", error->message);
+ g_error_free (error);
+ dbus_g_method_return_error (context, error2);
+ g_error_free (error2);
+ return FALSE;
+ }
+ if (WEXITSTATUS (exit_status) != 0) {
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "/sbin/hwclock returned %d", exit_status);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+ }
+
+ dbus_g_method_return (context);
+ return TRUE;
+}
+
+static gboolean
+_rh_update_etc_sysconfig_clock (DBusGMethodInvocation *context, const char *key, const char *value)
+{
+ /* On Red Hat / Fedora, the /etc/sysconfig/clock file needs to be kept in sync */
+ if (g_file_test ("/etc/sysconfig/clock", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ char **lines;
+ int n;
+ gboolean replaced;
+ char *data;
+ gsize len;
+ GError *error;
+
+ error = NULL;
+
+ if (!g_file_get_contents ("/etc/sysconfig/clock", &data, &len, &error)) {
+ GError *error2;
+ error2 = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error reading /etc/sysconfig/clock file: %s", error->message);
+ g_error_free (error);
+ dbus_g_method_return_error (context, error2);
+ g_error_free (error2);
+ return FALSE;
+ }
+ replaced = FALSE;
+ lines = g_strsplit (data, "\n", 0);
+ g_free (data);
+
+ for (n = 0; lines[n] != NULL; n++) {
+ if (g_str_has_prefix (lines[n], key)) {
+ g_free (lines[n]);
+ lines[n] = g_strdup_printf ("%s%s", key, value);
+ replaced = TRUE;
+ }
+ }
+ if (replaced) {
+ GString *str;
+
+ str = g_string_new (NULL);
+ for (n = 0; lines[n] != NULL; n++) {
+ g_string_append (str, lines[n]);
+ if (lines[n + 1] != NULL)
+ g_string_append_c (str, '\n');
+ }
+ data = g_string_free (str, FALSE);
+ len = strlen (data);
+ if (!g_file_set_contents ("/etc/sysconfig/clock", data, len, &error)) {
+ GError *error2;
+ error2 = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error updating /etc/sysconfig/clock: %s", error->message);
+ g_error_free (error);
+ dbus_g_method_return_error (context, error2);
+ g_error_free (error2);
+ g_free (data);
+ return FALSE;
+ }
+ g_free (data);
+ }
+ g_strfreev (lines);
+ }
+
+ return TRUE;
+}
+
+/* exported methods */
+
+gboolean
+gsd_datetime_mechanism_set_time (GsdDatetimeMechanism *mechanism,
+ gint64 seconds_since_epoch,
+ DBusGMethodInvocation *context)
+{
+ struct timeval tv;
+
+ reset_killtimer ();
+ g_debug ("SetTime(%lld) called", seconds_since_epoch);
+
+ tv.tv_sec = (time_t) seconds_since_epoch;
+ tv.tv_usec = 0;
+ return _set_time (mechanism, &tv, context);
+}
+
+gboolean
+gsd_datetime_mechanism_adjust_time (GsdDatetimeMechanism *mechanism,
+ gint64 seconds_to_add,
+ DBusGMethodInvocation *context)
+{
+ struct timeval tv;
+
+ reset_killtimer ();
+ g_debug ("AdjustTime(%lld) called", seconds_to_add);
+
+ if (gettimeofday (&tv, NULL) != 0) {
+ GError *error;
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error calling gettimeofday(): %s", strerror (errno));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ tv.tv_sec += (time_t) seconds_to_add;
+ return _set_time (mechanism, &tv, context);
+}
+
+
+gboolean
+gsd_datetime_mechanism_set_timezone (GsdDatetimeMechanism *mechanism,
+ const char *zone_file,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+
+ reset_killtimer ();
+ g_debug ("SetTimezone('%s') called", zone_file);
+
+ if (!_check_polkit_for_action (mechanism, context, "org.mate.settingsdaemon.datetimemechanism.settimezone"))
+ return FALSE;
+
+ error = NULL;
+
+ if (!system_timezone_set_from_file (zone_file, &error)) {
+ GError *error2;
+ int code;
+
+ if (error->code == SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE)
+ code = GSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE;
+ else
+ code = GSD_DATETIME_MECHANISM_ERROR_GENERAL;
+
+ error2 = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ code, "%s", error->message);
+
+ g_error_free (error);
+
+ dbus_g_method_return_error (context, error2);
+ g_error_free (error2);
+
+ return FALSE;
+ }
+
+ dbus_g_method_return (context);
+ return TRUE;
+}
+
+
+gboolean
+gsd_datetime_mechanism_get_timezone (GsdDatetimeMechanism *mechism,
+ DBusGMethodInvocation *context)
+{
+ gchar *timezone;
+
+ reset_killtimer ();
+
+ timezone = system_timezone_find ();
+
+ dbus_g_method_return (context, timezone);
+
+ return TRUE;
+}
+
+gboolean
+gsd_datetime_mechanism_get_hardware_clock_using_utc (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context)
+{
+ char **lines;
+ char *data;
+ gsize len;
+ GError *error;
+ gboolean is_utc;
+
+ error = NULL;
+
+ if (!g_file_get_contents ("/etc/adjtime", &data, &len, &error)) {
+ GError *error2;
+ error2 = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error reading /etc/adjtime file: %s", error->message);
+ g_error_free (error);
+ dbus_g_method_return_error (context, error2);
+ g_error_free (error2);
+ return FALSE;
+ }
+
+ lines = g_strsplit (data, "\n", 0);
+ g_free (data);
+
+ if (g_strv_length (lines) < 3) {
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Cannot parse /etc/adjtime");
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_strfreev (lines);
+ return FALSE;
+ }
+
+ if (strcmp (lines[2], "UTC") == 0) {
+ is_utc = TRUE;
+ } else if (strcmp (lines[2], "LOCAL") == 0) {
+ is_utc = FALSE;
+ } else {
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Expected UTC or LOCAL at line 3 of /etc/adjtime; found '%s'", lines[2]);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_strfreev (lines);
+ return FALSE;
+ }
+ g_strfreev (lines);
+ dbus_g_method_return (context, is_utc);
+ return TRUE;
+}
+
+gboolean
+gsd_datetime_mechanism_set_hardware_clock_using_utc (GsdDatetimeMechanism *mechanism,
+ gboolean using_utc,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+
+ error = NULL;
+
+ if (!_check_polkit_for_action (mechanism, context,
+ "org.mate.settingsdaemon.datetimemechanism.configurehwclock"))
+ return FALSE;
+
+ if (g_file_test ("/sbin/hwclock",
+ G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
+ int exit_status;
+ char *cmd;
+ cmd = g_strdup_printf ("/sbin/hwclock %s --systohc", using_utc ? "--utc" : "--localtime");
+ if (!g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &error)) {
+ GError *error2;
+ error2 = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "Error spawning /sbin/hwclock: %s", error->message);
+ g_error_free (error);
+ dbus_g_method_return_error (context, error2);
+ g_error_free (error2);
+ g_free (cmd);
+ return FALSE;
+ }
+ g_free (cmd);
+ if (WEXITSTATUS (exit_status) != 0) {
+ error = g_error_new (GSD_DATETIME_MECHANISM_ERROR,
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ "/sbin/hwclock returned %d", exit_status);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ if (!_rh_update_etc_sysconfig_clock (context, "UTC=", using_utc ? "true" : "false"))
+ return FALSE;
+
+ }
+ dbus_g_method_return (context);
+ return TRUE;
+}
+
+static void
+check_can_do (GsdDatetimeMechanism *mechanism,
+ const char *action,
+ DBusGMethodInvocation *context)
+{
+ const char *sender;
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
+ GError *error;
+
+ /* Check that caller is privileged */
+ sender = dbus_g_method_get_sender (context);
+ subject = polkit_system_bus_name_new (sender);
+
+ error = NULL;
+ result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
+ subject,
+ action,
+ NULL,
+ 0,
+ NULL,
+ &error);
+ g_object_unref (subject);
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ dbus_g_method_return (context, 2);
+ }
+ else if (polkit_authorization_result_get_is_challenge (result)) {
+ dbus_g_method_return (context, 1);
+ }
+ else {
+ dbus_g_method_return (context, 0);
+ }
+
+ g_object_unref (result);
+}
+
+
+gboolean
+gsd_datetime_mechanism_can_set_time (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context)
+{
+ check_can_do (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settime",
+ context);
+
+ return TRUE;
+}
+
+gboolean
+gsd_datetime_mechanism_can_set_timezone (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context)
+{
+ check_can_do (mechanism,
+ "org.mate.settingsdaemon.datetimemechanism.settimezone",
+ context);
+
+ return TRUE;
+}
diff --git a/plugins/datetime/gsd-datetime-mechanism.h b/plugins/datetime/gsd-datetime-mechanism.h
new file mode 100644
index 0000000..52b3b02
--- /dev/null
+++ b/plugins/datetime/gsd-datetime-mechanism.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef GSD_DATETIME_MECHANISM_H
+#define GSD_DATETIME_MECHANISM_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_DATETIME_TYPE_MECHANISM (gsd_datetime_mechanism_get_type ())
+#define GSD_DATETIME_MECHANISM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_DATETIME_TYPE_MECHANISM, GsdDatetimeMechanism))
+#define GSD_DATETIME_MECHANISM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_DATETIME_TYPE_MECHANISM, GsdDatetimeMechanismClass))
+#define GSD_DATETIME_IS_MECHANISM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_DATETIME_TYPE_MECHANISM))
+#define GSD_DATETIME_IS_MECHANISM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_DATETIME_TYPE_MECHANISM))
+#define GSD_DATETIME_MECHANISM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_DATETIME_TYPE_MECHANISM, GsdDatetimeMechanismClass))
+
+typedef struct GsdDatetimeMechanismPrivate GsdDatetimeMechanismPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdDatetimeMechanismPrivate *priv;
+} GsdDatetimeMechanism;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdDatetimeMechanismClass;
+
+typedef enum
+{
+ GSD_DATETIME_MECHANISM_ERROR_GENERAL,
+ GSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED,
+ GSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE,
+ GSD_DATETIME_MECHANISM_NUM_ERRORS
+} GsdDatetimeMechanismError;
+
+#define GSD_DATETIME_MECHANISM_ERROR gsd_datetime_mechanism_error_quark ()
+
+GType gsd_datetime_mechanism_error_get_type (void);
+#define GSD_DATETIME_MECHANISM_TYPE_ERROR (gsd_datetime_mechanism_error_get_type ())
+
+
+GQuark gsd_datetime_mechanism_error_quark (void);
+GType gsd_datetime_mechanism_get_type (void);
+GsdDatetimeMechanism *gsd_datetime_mechanism_new (void);
+
+/* exported methods */
+gboolean gsd_datetime_mechanism_get_timezone (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context);
+gboolean gsd_datetime_mechanism_set_timezone (GsdDatetimeMechanism *mechanism,
+ const char *zone_file,
+ DBusGMethodInvocation *context);
+
+gboolean gsd_datetime_mechanism_can_set_timezone (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context);
+
+gboolean gsd_datetime_mechanism_set_time (GsdDatetimeMechanism *mechanism,
+ gint64 seconds_since_epoch,
+ DBusGMethodInvocation *context);
+
+gboolean gsd_datetime_mechanism_can_set_time (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context);
+
+gboolean gsd_datetime_mechanism_adjust_time (GsdDatetimeMechanism *mechanism,
+ gint64 seconds_to_add,
+ DBusGMethodInvocation *context);
+
+gboolean gsd_datetime_mechanism_get_hardware_clock_using_utc (GsdDatetimeMechanism *mechanism,
+ DBusGMethodInvocation *context);
+
+gboolean gsd_datetime_mechanism_set_hardware_clock_using_utc (GsdDatetimeMechanism *mechanism,
+ gboolean using_utc,
+ DBusGMethodInvocation *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GSD_DATETIME_MECHANISM_H */
diff --git a/plugins/datetime/gsd-datetime-mechanism.xml b/plugins/datetime/gsd-datetime-mechanism.xml
new file mode 100644
index 0000000..1962235
--- /dev/null
+++ b/plugins/datetime/gsd-datetime-mechanism.xml
@@ -0,0 +1,87 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+ <interface name="org.mate.SettingsDaemon.DateTimeMechanism">
+ <method name="SetTimezone">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="zonefile" direction="in" type="s"/>
+ </method>
+
+ <method name="GetTimezone">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="timezone" direction="out" type="s"/>
+ </method>
+
+ <method name="CanSetTimezone">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="value" direction="out" type="i">
+ <doc:doc>
+ <doc:summary>Whether the caller can set the timezone</doc:summary>
+ <doc:description>
+ <doc:para>
+ The return value is not a boolean, but an integer with the following meaning:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>the caller cannot set the timezone</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>the caller will be challenged before being able to set the timezone</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>the caller is authorized to set the timezone</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </arg>
+ </method>
+ <method name="SetTime">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="seconds_since_epoch" direction="in" type="x"/>
+ </method>
+ <method name="CanSetTime">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="value" direction="out" type="i">
+ <doc:doc>
+ <doc:summary>Whether the caller can set the time</doc:summary>
+ <doc:description>
+ <doc:para>
+ The return value is not a boolean, but an integer with the following meaning:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>the caller cannot set the time</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>the caller will be challenged before being able to set the time</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>the caller is authorized to set the time</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </arg>
+ </method>
+ <method name="AdjustTime">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="seconds_to_add" direction="in" type="x"/>
+ </method>
+
+ <method name="GetHardwareClockUsingUtc">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="is_using_utc" direction="out" type="b"/>
+ </method>
+ <method name="SetHardwareClockUsingUtc">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="is_using_utc" direction="in" type="b"/>
+ </method>
+
+ </interface>
+</node>
diff --git a/plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.conf b/plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.conf
new file mode 100644
index 0000000..c861ace
--- /dev/null
+++ b/plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.conf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <!-- Only root can own the service -->
+ <policy user="root">
+ <allow own="org.mate.SettingsDaemon.DateTimeMechanism"/>
+ <allow send_destination="org.mate.SettingsDaemon.DateTimeMechanism"/>
+ </policy>
+
+ <!-- Allow anyone to invoke methods on the interfaces -->
+ <policy context="default">
+ <allow send_destination="org.mate.SettingsDaemon.DateTimeMechanism"/>
+ </policy>
+
+</busconfig>
diff --git a/plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.service.in b/plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.service.in
new file mode 100644
index 0000000..ac7fa29
--- /dev/null
+++ b/plugins/datetime/org.mate.SettingsDaemon.DateTimeMechanism.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.mate.SettingsDaemon.DateTimeMechanism
+Exec=@LIBEXECDIR@/gsd-datetime-mechanism
+User=root
diff --git a/plugins/datetime/org.mate.settingsdaemon.datetimemechanism.policy.in b/plugins/datetime/org.mate.settingsdaemon.datetimemechanism.policy.in
new file mode 100644
index 0000000..3fb688e
--- /dev/null
+++ b/plugins/datetime/org.mate.settingsdaemon.datetimemechanism.policy.in
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<policyconfig>
+ <vendor>The MATE Project</vendor>
+ <vendor_url>http://www.gnome.org/</vendor_url>
+ <icon_name>mate-panel-clock</icon_name>
+
+ <action id="org.mate.settingsdaemon.datetimemechanism.settimezone">
+ <_description>Change system time zone</_description>
+ <_message>Privileges are required to change the system time zone.</_message>
+ <defaults>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_self_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.mate.settingsdaemon.datetimemechanism.settime">
+ <_description>Change system time</_description>
+ <_message>Privileges are required to change the system time.</_message>
+ <defaults>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.mate.settingsdaemon.datetimemechanism.configurehwclock">
+ <_description>Configure hardware clock</_description>
+ <_message>Privileges are required to configure the hardware clock.</_message>
+ <defaults>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+</policyconfig>
diff --git a/plugins/datetime/system-timezone.c b/plugins/datetime/system-timezone.c
new file mode 100644
index 0000000..43add01
--- /dev/null
+++ b/plugins/datetime/system-timezone.c
@@ -0,0 +1,1047 @@
+/* System timezone handling
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Authors: Vincent Untz <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Some code is based on previous code in clock-location.c and on code from
+ * tz.c (shipped with version <= 2.22.0). Those files were under the same
+ * license, with those authors and copyrights:
+ *
+ * clock-location.c:
+ * ================
+ * No header, but most of the work was done (AFAIK) by
+ * Federico Mena Quintero <[email protected]>
+ * Matthias Clasen <[email protected]>
+ *
+ * tz.c:
+ * ====
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ * Copyright (C) 2004 Sun Microsystems, Inc.
+ *
+ * Authors: Hans Petter Jansson <[email protected]>
+ * additional functions by Erwann Chenede <[email protected]>
+ * reworked by Vincent Untz <[email protected]>
+ *
+ * Largely based on Michael Fulbright's work on Anaconda.
+ */
+
+/* FIXME: it'd be nice to filter out the timezones that we might get when
+ * parsing config files that are not in zone.tab. Note that it's also wrong
+ * in some cases: eg, in tzdata2008b, Asia/Calcutta got renamed to
+ * Asia/Kolkata and the old name is not in zone.tab. */
+
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include "system-timezone.h"
+
+/* Files that we look at and that should be monitored */
+#define CHECK_NB 5
+#define ETC_TIMEZONE "/etc/timezone"
+#define ETC_TIMEZONE_MAJ "/etc/TIMEZONE"
+#define ETC_RC_CONF "/etc/rc.conf"
+#define ETC_SYSCONFIG_CLOCK "/etc/sysconfig/clock"
+#define ETC_CONF_D_CLOCK "/etc/conf.d/clock"
+#define ETC_LOCALTIME "/etc/localtime"
+
+/* The first 4 characters in a timezone file, from tzfile.h */
+#define TZ_MAGIC "TZif"
+
+static char *files_to_check[CHECK_NB] = {
+ ETC_TIMEZONE,
+ ETC_TIMEZONE_MAJ,
+ ETC_SYSCONFIG_CLOCK,
+ ETC_CONF_D_CLOCK,
+ ETC_LOCALTIME
+};
+
+static GObject *systz_singleton = NULL;
+
+G_DEFINE_TYPE (SystemTimezone, system_timezone, G_TYPE_OBJECT)
+
+typedef struct {
+ char *tz;
+ char *env_tz;
+ GFileMonitor *monitors[CHECK_NB];
+} SystemTimezonePrivate;
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint system_timezone_signals[LAST_SIGNAL] = { 0 };
+
+static GObject *system_timezone_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+static void system_timezone_finalize (GObject *obj);
+
+static void system_timezone_monitor_changed (GFileMonitor *handle,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data);
+
+#define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYSTEM_TIMEZONE_TYPE, SystemTimezonePrivate))
+
+SystemTimezone *
+system_timezone_new (void)
+{
+ return g_object_new (SYSTEM_TIMEZONE_TYPE, NULL);
+}
+
+const char *
+system_timezone_get (SystemTimezone *systz)
+{
+ SystemTimezonePrivate *priv;
+
+ g_return_val_if_fail (IS_SYSTEM_TIMEZONE (systz), NULL);
+
+ priv = PRIVATE (systz);
+ return priv->tz;
+}
+
+const char *
+system_timezone_get_env (SystemTimezone *systz)
+{
+ SystemTimezonePrivate *priv;
+
+ g_return_val_if_fail (IS_SYSTEM_TIMEZONE (systz), NULL);
+
+ priv = PRIVATE (systz);
+ return priv->env_tz;
+}
+
+static void
+system_timezone_class_init (SystemTimezoneClass *class)
+{
+ GObjectClass *g_obj_class = G_OBJECT_CLASS (class);
+
+ g_obj_class->constructor = system_timezone_constructor;
+ g_obj_class->finalize = system_timezone_finalize;
+
+ system_timezone_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (g_obj_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (SystemTimezoneClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ g_type_class_add_private (class, sizeof (SystemTimezonePrivate));
+}
+
+static void
+system_timezone_init (SystemTimezone *systz)
+{
+ int i;
+ SystemTimezonePrivate *priv = PRIVATE (systz);
+
+ priv->tz = NULL;
+ priv->env_tz = NULL;
+ for (i = 0; i < CHECK_NB; i++)
+ priv->monitors[i] = NULL;
+}
+
+static GObject *
+system_timezone_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ SystemTimezonePrivate *priv;
+ int i;
+
+ /* This is a singleton, we don't need to have it per-applet */
+ if (systz_singleton)
+ return g_object_ref (systz_singleton);
+
+ obj = G_OBJECT_CLASS (system_timezone_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties);
+
+ priv = PRIVATE (obj);
+
+ priv->tz = system_timezone_find ();
+
+ priv->env_tz = g_strdup (g_getenv ("TZ"));
+
+ for (i = 0; i < CHECK_NB; i++) {
+ GFile *file;
+ GFile *parent;
+ GFileType parent_type;
+
+ file = g_file_new_for_path (files_to_check[i]);
+
+ parent = g_file_get_parent (file);
+ parent_type = g_file_query_file_type (parent, G_FILE_QUERY_INFO_NONE, NULL);
+ g_object_unref (parent);
+
+ /* We don't try to monitor the file if the parent directory
+ * doesn't exist: this means we're on a system where this file
+ * is not useful to determine the system timezone.
+ * Since gio does not monitor file in non-existing directories
+ * in a clever way (as of gio 2.22, it just polls every other
+ * seconds to see if the directory now exists), this avoids
+ * unnecessary wakeups. */
+ if (parent_type == G_FILE_TYPE_DIRECTORY)
+ priv->monitors[i] = g_file_monitor_file (file,
+ G_FILE_MONITOR_NONE,
+ NULL, NULL);
+ g_object_unref (file);
+
+ if (priv->monitors[i])
+ g_signal_connect (G_OBJECT (priv->monitors[i]),
+ "changed",
+ G_CALLBACK (system_timezone_monitor_changed),
+ obj);
+ }
+
+ systz_singleton = obj;
+
+ return systz_singleton;
+}
+
+static void
+system_timezone_finalize (GObject *obj)
+{
+ int i;
+ SystemTimezonePrivate *priv = PRIVATE (obj);
+
+ if (priv->tz) {
+ g_free (priv->tz);
+ priv->tz = NULL;
+ }
+
+ if (priv->env_tz) {
+ g_free (priv->env_tz);
+ priv->env_tz = NULL;
+ }
+
+ for (i = 0; i < CHECK_NB; i++) {
+ if (priv->monitors[i])
+ g_object_unref (priv->monitors[i]);
+ priv->monitors[i] = NULL;
+ }
+
+ G_OBJECT_CLASS (system_timezone_parent_class)->finalize (obj);
+
+ g_assert (obj == systz_singleton);
+
+ systz_singleton = NULL;
+}
+
+static void
+system_timezone_monitor_changed (GFileMonitor *handle,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data)
+{
+ SystemTimezonePrivate *priv = PRIVATE (user_data);
+ char *new_tz;
+
+ if (event != G_FILE_MONITOR_EVENT_CHANGED &&
+ event != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT &&
+ event != G_FILE_MONITOR_EVENT_DELETED &&
+ event != G_FILE_MONITOR_EVENT_CREATED)
+ return;
+
+ new_tz = system_timezone_find ();
+
+ g_assert (priv->tz != NULL && new_tz != NULL);
+
+ if (strcmp (priv->tz, new_tz) != 0) {
+ g_free (priv->tz);
+ priv->tz = new_tz;
+
+ g_signal_emit (G_OBJECT (user_data),
+ system_timezone_signals[CHANGED],
+ 0, priv->tz);
+ } else
+ g_free (new_tz);
+}
+
+
+/*
+ * Code to deal with the system timezone on all distros.
+ * There's no dependency on the SystemTimezone GObject here.
+ *
+ * Here's what we know:
+ *
+ * + /etc/localtime contains the binary data of the timezone.
+ * It can be a symlink to the actual data file, a hard link to the data
+ * file, or just a copy. So we can determine the timezone with this
+ * (reading the symlink, comparing inodes, or comparing content).
+ *
+ * + However, most distributions also have the timezone setting
+ * configured somewhere else. This might be better to read it from there.
+ *
+ * Debian/Ubuntu/Gentoo (new): content of /etc/timezone
+ * Fedora/Mandriva: the ZONE key in /etc/sysconfig/clock
+ * openSUSE: the TIMEZONE key in /etc/sysconfig/clock
+ * Solaris/OpenSolaris: the TZ key in /etc/TIMEZONE
+ * Arch Linux: the TIMEZONE key in /etc/rc.conf
+ * Gentoo (old): the ZONE key in /etc/conf.d/clock
+ *
+ * FIXME: reading the system-tools-backends, it seems there's this too:
+ * Solaris: the TZ key in /etc/default/init
+ * /etc/TIMEZONE seems to be a link to /etc/default/init
+ *
+ * First, some functions to handle those system config files.
+ *
+ */
+
+/* This works for Debian and derivatives (including Ubuntu), and new Gentoo */
+static char *
+system_timezone_read_etc_timezone (void)
+{
+ FILE *etc_timezone;
+ GString *reading;
+ int c;
+
+ etc_timezone = g_fopen (ETC_TIMEZONE, "r");
+ if (!etc_timezone)
+ return NULL;
+
+ reading = g_string_new ("");
+
+ c = fgetc (etc_timezone);
+ /* only get the first line, we'll validate the value later */
+ while (c != EOF && !g_ascii_isspace (c)) {
+ reading = g_string_append_c (reading, c);
+ c = fgetc (etc_timezone);
+ }
+
+ fclose (etc_timezone);
+
+ if (reading->str && reading->str[0] != '\0')
+ return g_string_free (reading, FALSE);
+ else
+ g_string_free (reading, TRUE);
+
+ return NULL;
+}
+
+static gboolean
+system_timezone_write_etc_timezone (const char *tz,
+ GError **error)
+{
+ char *content;
+ GError *our_error;
+ gboolean retval;
+
+ if (!g_file_test (ETC_TIMEZONE, G_FILE_TEST_IS_REGULAR))
+ return TRUE;
+
+ content = g_strdup_printf ("%s\n", tz);
+
+ our_error = NULL;
+ retval = g_file_set_contents (ETC_TIMEZONE, content, -1, &our_error);
+ g_free (content);
+
+ if (!retval) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_GENERAL,
+ ETC_TIMEZONE" cannot be overwritten: %s",
+ our_error->message);
+ g_error_free (our_error);
+ }
+
+ return retval;
+}
+
+
+/* Read a file that looks like a key-file (but there's no need for groups)
+ * and get the last value for a specific key */
+static char *
+system_timezone_read_key_file (const char *filename,
+ const char *key)
+{
+ GIOChannel *channel;
+ char *key_eq;
+ char *line;
+ char *retval;
+
+ if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ return NULL;
+
+ channel = g_io_channel_new_file (filename, "r", NULL);
+ if (!channel)
+ return NULL;
+
+ key_eq = g_strdup_printf ("%s=", key);
+ retval = NULL;
+
+ while (g_io_channel_read_line (channel, &line, NULL,
+ NULL, NULL) == G_IO_STATUS_NORMAL) {
+ if (g_str_has_prefix (line, key_eq)) {
+ char *value;
+ int len;
+
+ value = line + strlen (key_eq);
+ g_strstrip (value);
+
+ len = strlen (value);
+
+ if (value[0] == '\"') {
+ if (value[len - 1] == '\"') {
+ if (retval)
+ g_free (retval);
+
+ retval = g_strndup (value + 1,
+ len - 2);
+ }
+ } else {
+ if (retval)
+ g_free (retval);
+
+ retval = g_strdup (line + strlen (key_eq));
+ }
+
+ g_strstrip (retval);
+ }
+
+ g_free (line);
+ }
+
+ g_free (key_eq);
+ g_io_channel_unref (channel);
+
+ return retval;
+}
+
+static gboolean
+system_timezone_write_key_file (const char *filename,
+ const char *key,
+ const char *value,
+ GError **error)
+{
+ GError *our_error;
+ char *content;
+ gsize len;
+ char *key_eq;
+ char **lines;
+ gboolean replaced;
+ gboolean retval;
+ int n;
+
+ if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ return TRUE;
+
+ our_error = NULL;
+
+ if (!g_file_get_contents (filename, &content, &len, &our_error)) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_GENERAL,
+ "%s cannot be read: %s",
+ filename, our_error->message);
+ g_error_free (our_error);
+ return FALSE;
+ }
+
+ lines = g_strsplit (content, "\n", 0);
+ g_free (content);
+
+ key_eq = g_strdup_printf ("%s=", key);
+ replaced = FALSE;
+
+ for (n = 0; lines[n] != NULL; n++) {
+ if (g_str_has_prefix (lines[n], key_eq)) {
+ char *old_value;
+ gboolean use_quotes;
+
+ old_value = lines[n] + strlen (key_eq);
+ g_strstrip (old_value);
+ use_quotes = old_value[0] == '\"';
+
+ g_free (lines[n]);
+
+ if (use_quotes)
+ lines[n] = g_strdup_printf ("%s\"%s\"",
+ key_eq, value);
+ else
+ lines[n] = g_strdup_printf ("%s%s",
+ key_eq, value);
+
+ replaced = TRUE;
+ }
+ }
+
+ g_free (key_eq);
+
+ if (!replaced) {
+ g_strfreev (lines);
+ return TRUE;
+ }
+
+ content = g_strjoinv ("\n", lines);
+ g_strfreev (lines);
+
+ retval = g_file_set_contents (filename, content, -1, &our_error);
+ g_free (content);
+
+ if (!retval) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_GENERAL,
+ "%s cannot be overwritten: %s",
+ filename, our_error->message);
+ g_error_free (our_error);
+ }
+
+ return retval;
+}
+
+/* This works for Solaris/OpenSolaris */
+static char *
+system_timezone_read_etc_TIMEZONE (void)
+{
+ return system_timezone_read_key_file (ETC_TIMEZONE_MAJ,
+ "TZ");
+}
+
+static gboolean
+system_timezone_write_etc_TIMEZONE (const char *tz,
+ GError **error)
+{
+ return system_timezone_write_key_file (ETC_TIMEZONE_MAJ,
+ "TZ", tz, error);
+}
+
+/* This works for Fedora and Mandriva */
+static char *
+system_timezone_read_etc_sysconfig_clock (void)
+{
+ return system_timezone_read_key_file (ETC_SYSCONFIG_CLOCK,
+ "ZONE");
+}
+
+static gboolean
+system_timezone_write_etc_sysconfig_clock (const char *tz,
+ GError **error)
+{
+ return system_timezone_write_key_file (ETC_SYSCONFIG_CLOCK,
+ "ZONE", tz, error);
+}
+
+/* This works for openSUSE */
+static char *
+system_timezone_read_etc_sysconfig_clock_alt (void)
+{
+ return system_timezone_read_key_file (ETC_SYSCONFIG_CLOCK,
+ "TIMEZONE");
+}
+
+static gboolean
+system_timezone_write_etc_sysconfig_clock_alt (const char *tz,
+ GError **error)
+{
+ return system_timezone_write_key_file (ETC_SYSCONFIG_CLOCK,
+ "TIMEZONE", tz, error);
+}
+
+/* This works for old Gentoo */
+static char *
+system_timezone_read_etc_conf_d_clock (void)
+{
+ return system_timezone_read_key_file (ETC_CONF_D_CLOCK,
+ "TIMEZONE");
+}
+
+static gboolean
+system_timezone_write_etc_conf_d_clock (const char *tz,
+ GError **error)
+{
+ return system_timezone_write_key_file (ETC_CONF_D_CLOCK,
+ "TIMEZONE", tz, error);
+}
+
+/* This works for Arch Linux */
+static char *
+system_timezone_read_etc_rc_conf (void)
+{
+ return system_timezone_read_key_file (ETC_RC_CONF,
+ "TIMEZONE");
+}
+
+static gboolean
+system_timezone_write_etc_rc_conf (const char *tz,
+ GError **error)
+{
+ return system_timezone_write_key_file (ETC_RC_CONF,
+ "TIMEZONE", tz, error);
+}
+
+/*
+ *
+ * First, getting the timezone.
+ *
+ */
+
+static char *
+system_timezone_strip_path_if_valid (const char *filename)
+{
+ int skip;
+
+ if (!filename || !g_str_has_prefix (filename, SYSTEM_ZONEINFODIR"/"))
+ return NULL;
+
+ /* Timezone data files also live under posix/ and right/ for some
+ * reason.
+ * FIXME: make sure accepting those files is valid. I think "posix" is
+ * okay, not sure about "right" */
+ if (g_str_has_prefix (filename, SYSTEM_ZONEINFODIR"/posix/"))
+ skip = strlen (SYSTEM_ZONEINFODIR"/posix/");
+ else if (g_str_has_prefix (filename, SYSTEM_ZONEINFODIR"/right/"))
+ skip = strlen (SYSTEM_ZONEINFODIR"/right/");
+ else
+ skip = strlen (SYSTEM_ZONEINFODIR"/");
+
+ return g_strdup (filename + skip);
+}
+
+/* Read the soft symlink from /etc/localtime */
+static char *
+system_timezone_read_etc_localtime_softlink (void)
+{
+ char *file;
+ char *tz;
+
+ if (!g_file_test (ETC_LOCALTIME, G_FILE_TEST_IS_SYMLINK))
+ return NULL;
+
+ file = g_file_read_link (ETC_LOCALTIME, NULL);
+ tz = system_timezone_strip_path_if_valid (file);
+ g_free (file);
+
+ return tz;
+}
+
+typedef gboolean (*CompareFiles) (struct stat *a_stat,
+ struct stat *b_stat,
+ const char *a_content,
+ gsize a_content_len,
+ const char *b_filename);
+
+static char *
+recursive_compare (struct stat *localtime_stat,
+ const char *localtime_content,
+ gsize localtime_content_len,
+ char *file,
+ CompareFiles compare_func)
+{
+ struct stat file_stat;
+
+ if (g_stat (file, &file_stat) != 0)
+ return NULL;
+
+ if (S_ISREG (file_stat.st_mode)) {
+ if (compare_func (localtime_stat,
+ &file_stat,
+ localtime_content,
+ localtime_content_len,
+ file))
+ return system_timezone_strip_path_if_valid (file);
+ else
+ return NULL;
+ } else if (S_ISDIR (file_stat.st_mode)) {
+ GDir *dir = NULL;
+ char *ret = NULL;
+ const char *subfile = NULL;
+ char *subpath = NULL;
+
+ dir = g_dir_open (file, 0, NULL);
+ if (dir == NULL)
+ return NULL;
+
+ while ((subfile = g_dir_read_name (dir)) != NULL) {
+ subpath = g_build_filename (file, subfile, NULL);
+
+ ret = recursive_compare (localtime_stat,
+ localtime_content,
+ localtime_content_len,
+ subpath,
+ compare_func);
+
+ g_free (subpath);
+
+ if (ret != NULL)
+ break;
+ }
+
+ g_dir_close (dir);
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+
+static gboolean
+files_are_identical_inode (struct stat *a_stat,
+ struct stat *b_stat,
+ const char *a_content,
+ gsize a_content_len,
+ const char *b_filename)
+{
+ return (a_stat->st_ino == b_stat->st_ino);
+}
+
+
+/* Determine if /etc/localtime is a hard link to some file, by looking at
+ * the inodes */
+static char *
+system_timezone_read_etc_localtime_hardlink (void)
+{
+ struct stat stat_localtime;
+
+ if (g_stat (ETC_LOCALTIME, &stat_localtime) != 0)
+ return NULL;
+
+ if (!S_ISREG (stat_localtime.st_mode))
+ return NULL;
+
+ return recursive_compare (&stat_localtime,
+ NULL,
+ 0,
+ SYSTEM_ZONEINFODIR,
+ files_are_identical_inode);
+}
+
+static gboolean
+files_are_identical_content (struct stat *a_stat,
+ struct stat *b_stat,
+ const char *a_content,
+ gsize a_content_len,
+ const char *b_filename)
+{
+ char *b_content = NULL;
+ gsize b_content_len = -1;
+ int cmp;
+
+ if (a_stat->st_size != b_stat->st_size)
+ return FALSE;
+
+ if (!g_file_get_contents (b_filename,
+ &b_content, &b_content_len, NULL))
+ return FALSE;
+
+ if (a_content_len != b_content_len) {
+ g_free (b_content);
+ return FALSE;
+ }
+
+ cmp = memcmp (a_content, b_content, a_content_len);
+ g_free (b_content);
+
+ return (cmp == 0);
+}
+
+/* Determine if /etc/localtime is a copy of a timezone file */
+static char *
+system_timezone_read_etc_localtime_content (void)
+{
+ struct stat stat_localtime;
+ char *localtime_content = NULL;
+ gsize localtime_content_len = -1;
+ char *retval;
+
+ if (g_stat (ETC_LOCALTIME, &stat_localtime) != 0)
+ return NULL;
+
+ if (!S_ISREG (stat_localtime.st_mode))
+ return NULL;
+
+ if (!g_file_get_contents (ETC_LOCALTIME,
+ &localtime_content,
+ &localtime_content_len,
+ NULL))
+ return NULL;
+
+ retval = recursive_compare (&stat_localtime,
+ localtime_content,
+ localtime_content_len,
+ SYSTEM_ZONEINFODIR,
+ files_are_identical_content);
+
+ g_free (localtime_content);
+
+ return retval;
+}
+
+typedef char * (*GetSystemTimezone) (void);
+/* The order of the functions here define the priority of the methods used
+ * to find the timezone. First method has higher priority. */
+static GetSystemTimezone get_system_timezone_methods[] = {
+ /* cheap and "more correct" than data from a config file */
+ system_timezone_read_etc_localtime_softlink,
+ /* reading various config files */
+ system_timezone_read_etc_timezone,
+ system_timezone_read_etc_sysconfig_clock,
+ system_timezone_read_etc_sysconfig_clock_alt,
+ system_timezone_read_etc_TIMEZONE,
+ system_timezone_read_etc_rc_conf,
+ /* reading deprecated config files */
+ system_timezone_read_etc_conf_d_clock,
+ /* reading /etc/timezone directly. Expensive since we have to stat
+ * many files */
+ system_timezone_read_etc_localtime_hardlink,
+ system_timezone_read_etc_localtime_content,
+ NULL
+};
+
+static gboolean
+system_timezone_is_valid (const char *tz)
+{
+ const char *c;
+
+ if (!tz)
+ return FALSE;
+
+ for (c = tz; *c != '\0'; c++) {
+ if (!(g_ascii_isalnum (*c) ||
+ *c == '/' || *c == '-' || *c == '_'))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+char *
+system_timezone_find (void)
+{
+ char *tz;
+ int i;
+
+ for (i = 0; get_system_timezone_methods[i] != NULL; i++) {
+ tz = get_system_timezone_methods[i] ();
+
+ if (system_timezone_is_valid (tz))
+ return tz;
+
+ g_free (tz);
+ }
+
+ return g_strdup ("UTC");
+}
+
+/*
+ *
+ * Now, setting the timezone.
+ *
+ */
+
+static gboolean
+system_timezone_is_zone_file_valid (const char *zone_file,
+ GError **error)
+{
+ GError *our_error;
+ GIOChannel *channel;
+ GIOStatus status;
+ char buffer[strlen (TZ_MAGIC)];
+ gsize read;
+
+ /* First, check the zone_file is properly rooted */
+ if (!g_str_has_prefix (zone_file, SYSTEM_ZONEINFODIR"/")) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+ "Timezone file needs to be under "SYSTEM_ZONEINFODIR);
+ return FALSE;
+ }
+
+ /* Second, check it's a regular file that exists */
+ if (!g_file_test (zone_file, G_FILE_TEST_IS_REGULAR)) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+ "No such timezone file %s", zone_file);
+ return FALSE;
+ }
+
+ /* Third, check that it's a tzfile (see tzfile(5)). The file has a 4
+ * bytes header which is TZ_MAGIC.
+ *
+ * TODO: is there glibc API for this? */
+ our_error = NULL;
+ channel = g_io_channel_new_file (zone_file, "r", &our_error);
+ if (!our_error)
+ status = g_io_channel_read_chars (channel,
+ buffer, strlen (TZ_MAGIC),
+ &read, &our_error);
+ if (channel)
+ g_io_channel_unref (channel);
+
+ if (our_error) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+ "Timezone file %s cannot be read: %s",
+ zone_file, our_error->message);
+ g_error_free (our_error);
+ return FALSE;
+ }
+
+ if (read != strlen (TZ_MAGIC) || strncmp (buffer, TZ_MAGIC, strlen (TZ_MAGIC)) != 0) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+ "%s is not a timezone file",
+ zone_file);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+system_timezone_set_etc_timezone (const char *zone_file,
+ GError **error)
+{
+ GError *our_error;
+ char *content;
+ gsize len;
+
+ if (!system_timezone_is_zone_file_valid (zone_file, error))
+ return FALSE;
+
+ /* If /etc/localtime is a symlink, write a symlink */
+ if (g_file_test (ETC_LOCALTIME, G_FILE_TEST_IS_SYMLINK)) {
+ if (g_unlink (ETC_LOCALTIME) == 0 &&
+ symlink (zone_file, ETC_LOCALTIME) == 0)
+ return TRUE;
+
+ /* If we couldn't symlink the file, we'll just fallback on
+ * copying it */
+ }
+
+ /* Else copy the file to /etc/localtime. We explicitly avoid doing
+ * hard links since they break with different partitions */
+ our_error = NULL;
+ if (!g_file_get_contents (zone_file, &content, &len, &our_error)) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_GENERAL,
+ "Timezone file %s cannot be read: %s",
+ zone_file, our_error->message);
+ g_error_free (our_error);
+ return FALSE;
+ }
+
+ if (!g_file_set_contents (ETC_LOCALTIME, content, len, &our_error)) {
+ g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+ SYSTEM_TIMEZONE_ERROR_GENERAL,
+ ETC_LOCALTIME" cannot be overwritten: %s",
+ our_error->message);
+ g_error_free (our_error);
+ g_free (content);
+ return FALSE;
+ }
+
+ g_free (content);
+
+ return TRUE;
+}
+
+typedef gboolean (*SetSystemTimezone) (const char *tz,
+ GError **error);
+/* The order here does not matter too much: we'll try to change all files
+ * that already have a timezone configured. It matters in case of error,
+ * since the process will be stopped and the last methods won't be called.
+ * So we use the same order as in get_system_timezone_methods */
+static SetSystemTimezone set_system_timezone_methods[] = {
+ /* writing various config files if they exist and have the
+ * setting already present */
+ system_timezone_write_etc_timezone,
+ system_timezone_write_etc_sysconfig_clock,
+ system_timezone_write_etc_sysconfig_clock_alt,
+ system_timezone_write_etc_TIMEZONE,
+ system_timezone_write_etc_rc_conf,
+ /* writing deprecated config files if they exist and have the
+ * setting already present */
+ system_timezone_write_etc_conf_d_clock,
+ NULL
+};
+
+static gboolean
+system_timezone_update_config (const char *tz,
+ GError **error)
+{
+ int i;
+
+ for (i = 0; set_system_timezone_methods[i] != NULL; i++) {
+ if (!set_system_timezone_methods[i] (tz, error))
+ return FALSE;
+ /* FIXME: maybe continue to change all config files if
+ * possible? */
+ }
+
+ return TRUE;
+}
+
+gboolean
+system_timezone_set_from_file (const char *zone_file,
+ GError **error)
+{
+ const char *tz;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ tz = zone_file + strlen (SYSTEM_ZONEINFODIR"/");
+
+ /* FIXME: is it right to return FALSE even when /etc/localtime was
+ * changed but not the config files? */
+ return (system_timezone_set_etc_timezone (zone_file, error) &&
+ system_timezone_update_config (tz, error));
+}
+
+gboolean
+system_timezone_set (const char *tz,
+ GError **error)
+{
+ char *zone_file;
+ gboolean retval;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ zone_file = g_build_filename (SYSTEM_ZONEINFODIR, tz, NULL);
+
+ /* FIXME: is it right to return FALSE even when /etc/localtime was
+ * changed but not the config files? */
+ retval = system_timezone_set_etc_timezone (zone_file, error) &&
+ system_timezone_update_config (tz, error);
+
+ g_free (zone_file);
+
+ return retval;
+}
+
+GQuark
+system_timezone_error_quark (void)
+{
+ static GQuark ret = 0;
+
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("system-timezone-error");
+ }
+
+ return ret;
+}
diff --git a/plugins/datetime/system-timezone.h b/plugins/datetime/system-timezone.h
new file mode 100644
index 0000000..b958cec
--- /dev/null
+++ b/plugins/datetime/system-timezone.h
@@ -0,0 +1,89 @@
+/* System timezone handling
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Authors: Vincent Untz <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SYSTEM_TIMEZONE_H__
+#define __SYSTEM_TIMEZONE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_SOLARIS
+#define SYSTEM_ZONEINFODIR "/usr/share/lib/zoneinfo/tab"
+#else
+#define SYSTEM_ZONEINFODIR "/usr/share/zoneinfo"
+#endif
+
+
+#define SYSTEM_TIMEZONE_TYPE (system_timezone_get_type ())
+#define SYSTEM_TIMEZONE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYSTEM_TIMEZONE_TYPE, SystemTimezone))
+#define SYSTEM_TIMEZONE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), SYSTEM_TIMEZONE_TYPE, SystemTimezoneClass))
+#define IS_SYSTEM_TIMEZONE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYSTEM_TIMEZONE_TYPE))
+#define IS_SYSTEM_TIMEZONE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), SYSTEM_TIMEZONE_TYPE))
+#define SYSTEM_TIMEZONE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SYSTEM_TIMEZONE_TYPE, SystemTimezoneClass))
+
+typedef struct
+{
+ GObject g_object;
+} SystemTimezone;
+
+typedef struct
+{
+ GObjectClass g_object_class;
+
+ void (* changed) (SystemTimezone *systz,
+ const char *tz);
+} SystemTimezoneClass;
+
+GType system_timezone_get_type (void);
+
+SystemTimezone *system_timezone_new (void);
+
+const char *system_timezone_get (SystemTimezone *systz);
+const char *system_timezone_get_env (SystemTimezone *systz);
+
+/* Functions to set the timezone. They won't be used by the applet, but
+ * by a program with more privileges */
+
+#define SYSTEM_TIMEZONE_ERROR system_timezone_error_quark ()
+GQuark system_timezone_error_quark (void);
+
+typedef enum
+{
+ SYSTEM_TIMEZONE_ERROR_GENERAL,
+ SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+ SYSTEM_TIMEZONE_NUM_ERRORS
+} SystemTimezoneError;
+
+char *system_timezone_find (void);
+
+gboolean system_timezone_set_from_file (const char *zone_file,
+ GError **error);
+gboolean system_timezone_set (const char *tz,
+ GError **error);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __SYSTEM_TIMEZONE_H__ */
diff --git a/plugins/dummy/Makefile.am b/plugins/dummy/Makefile.am
new file mode 100644
index 0000000..0f77530
--- /dev/null
+++ b/plugins/dummy/Makefile.am
@@ -0,0 +1,44 @@
+plugin_LTLIBRARIES = \
+ libdummy.la
+
+libdummy_la_SOURCES = \
+ gsd-dummy-manager.c \
+ gsd-dummy-manager.h \
+ gsd-dummy-plugin.c \
+ gsd-dummy-plugin.h
+
+libdummy_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libdummy_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libdummy_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libdummy_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS)
+
+plugin_in_files = \
+ dummy.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files)
+
+CLEANFILES = \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# override to _not_ install the test plugin
+# do not copy into your plugin
+install-pluginDATA:
+install-pluginLTLIBRARIES:
diff --git a/plugins/dummy/Makefile.in b/plugins/dummy/Makefile.in
new file mode 100644
index 0000000..3680d45
--- /dev/null
+++ b/plugins/dummy/Makefile.in
@@ -0,0 +1,646 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/dummy
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libdummy_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libdummy_la_OBJECTS = libdummy_la-gsd-dummy-manager.lo \
+ libdummy_la-gsd-dummy-plugin.lo
+libdummy_la_OBJECTS = $(am_libdummy_la_OBJECTS)
+libdummy_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libdummy_la_CFLAGS) \
+ $(CFLAGS) $(libdummy_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libdummy_la_SOURCES)
+DIST_SOURCES = $(libdummy_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = \
+ libdummy.la
+
+libdummy_la_SOURCES = \
+ gsd-dummy-manager.c \
+ gsd-dummy-manager.h \
+ gsd-dummy-plugin.c \
+ gsd-dummy-plugin.h
+
+libdummy_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libdummy_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libdummy_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libdummy_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS)
+
+plugin_in_files = \
+ dummy.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files)
+
+CLEANFILES = \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dummy/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/dummy/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libdummy.la: $(libdummy_la_OBJECTS) $(libdummy_la_DEPENDENCIES)
+ $(libdummy_la_LINK) -rpath $(plugindir) $(libdummy_la_OBJECTS) $(libdummy_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdummy_la-gsd-dummy-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdummy_la-gsd-dummy-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libdummy_la-gsd-dummy-manager.lo: gsd-dummy-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdummy_la_CPPFLAGS) $(CPPFLAGS) $(libdummy_la_CFLAGS) $(CFLAGS) -MT libdummy_la-gsd-dummy-manager.lo -MD -MP -MF $(DEPDIR)/libdummy_la-gsd-dummy-manager.Tpo -c -o libdummy_la-gsd-dummy-manager.lo `test -f 'gsd-dummy-manager.c' || echo '$(srcdir)/'`gsd-dummy-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libdummy_la-gsd-dummy-manager.Tpo $(DEPDIR)/libdummy_la-gsd-dummy-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-dummy-manager.c' object='libdummy_la-gsd-dummy-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdummy_la_CPPFLAGS) $(CPPFLAGS) $(libdummy_la_CFLAGS) $(CFLAGS) -c -o libdummy_la-gsd-dummy-manager.lo `test -f 'gsd-dummy-manager.c' || echo '$(srcdir)/'`gsd-dummy-manager.c
+
+libdummy_la-gsd-dummy-plugin.lo: gsd-dummy-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdummy_la_CPPFLAGS) $(CPPFLAGS) $(libdummy_la_CFLAGS) $(CFLAGS) -MT libdummy_la-gsd-dummy-plugin.lo -MD -MP -MF $(DEPDIR)/libdummy_la-gsd-dummy-plugin.Tpo -c -o libdummy_la-gsd-dummy-plugin.lo `test -f 'gsd-dummy-plugin.c' || echo '$(srcdir)/'`gsd-dummy-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libdummy_la-gsd-dummy-plugin.Tpo $(DEPDIR)/libdummy_la-gsd-dummy-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-dummy-plugin.c' object='libdummy_la-gsd-dummy-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdummy_la_CPPFLAGS) $(CPPFLAGS) $(libdummy_la_CFLAGS) $(CFLAGS) -c -o libdummy_la-gsd-dummy-plugin.lo `test -f 'gsd-dummy-plugin.c' || echo '$(srcdir)/'`gsd-dummy-plugin.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# override to _not_ install the test plugin
+# do not copy into your plugin
+install-pluginDATA:
+install-pluginLTLIBRARIES:
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/dummy/dummy.mate-settings-plugin.in b/plugins/dummy/dummy.mate-settings-plugin.in
new file mode 100644
index 0000000..c9f8838
--- /dev/null
+++ b/plugins/dummy/dummy.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=dummy
+IAge=0
+_Name=Dummy
+_Description=Dummy plugin
+Authors=AUTHOR
+Copyright=Copyright © 2007 AUTHOR
+Website=
diff --git a/plugins/dummy/gsd-dummy-manager.c b/plugins/dummy/gsd-dummy-manager.c
new file mode 100644
index 0000000..568c832
--- /dev/null
+++ b/plugins/dummy/gsd-dummy-manager.c
@@ -0,0 +1,186 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-dummy-manager.h"
+
+#define GSD_DUMMY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerPrivate))
+
+struct GsdDummyManagerPrivate
+{
+ gboolean padding;
+};
+
+enum {
+ PROP_0,
+};
+
+static void gsd_dummy_manager_class_init (GsdDummyManagerClass *klass);
+static void gsd_dummy_manager_init (GsdDummyManager *dummy_manager);
+static void gsd_dummy_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdDummyManager, gsd_dummy_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+gboolean
+gsd_dummy_manager_start (GsdDummyManager *manager,
+ GError **error)
+{
+ g_debug ("Starting dummy manager");
+ mate_settings_profile_start (NULL);
+ mate_settings_profile_end (NULL);
+ return TRUE;
+}
+
+void
+gsd_dummy_manager_stop (GsdDummyManager *manager)
+{
+ g_debug ("Stopping dummy manager");
+}
+
+static void
+gsd_dummy_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdDummyManager *self;
+
+ self = GSD_DUMMY_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_dummy_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdDummyManager *self;
+
+ self = GSD_DUMMY_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_dummy_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdDummyManager *dummy_manager;
+ GsdDummyManagerClass *klass;
+
+ klass = GSD_DUMMY_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_DUMMY_MANAGER));
+
+ dummy_manager = GSD_DUMMY_MANAGER (G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (dummy_manager);
+}
+
+static void
+gsd_dummy_manager_dispose (GObject *object)
+{
+ GsdDummyManager *dummy_manager;
+
+ dummy_manager = GSD_DUMMY_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_dummy_manager_class_init (GsdDummyManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_dummy_manager_get_property;
+ object_class->set_property = gsd_dummy_manager_set_property;
+ object_class->constructor = gsd_dummy_manager_constructor;
+ object_class->dispose = gsd_dummy_manager_dispose;
+ object_class->finalize = gsd_dummy_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdDummyManagerPrivate));
+}
+
+static void
+gsd_dummy_manager_init (GsdDummyManager *manager)
+{
+ manager->priv = GSD_DUMMY_MANAGER_GET_PRIVATE (manager);
+
+}
+
+static void
+gsd_dummy_manager_finalize (GObject *object)
+{
+ GsdDummyManager *dummy_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_DUMMY_MANAGER (object));
+
+ dummy_manager = GSD_DUMMY_MANAGER (object);
+
+ g_return_if_fail (dummy_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->finalize (object);
+}
+
+GsdDummyManager *
+gsd_dummy_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_DUMMY_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_DUMMY_MANAGER (manager_object);
+}
diff --git a/plugins/dummy/gsd-dummy-manager.h b/plugins/dummy/gsd-dummy-manager.h
new file mode 100644
index 0000000..ba63560
--- /dev/null
+++ b/plugins/dummy/gsd-dummy-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_DUMMY_MANAGER_H
+#define __GSD_DUMMY_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_DUMMY_MANAGER (gsd_dummy_manager_get_type ())
+#define GSD_DUMMY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManager))
+#define GSD_DUMMY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerClass))
+#define GSD_IS_DUMMY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DUMMY_MANAGER))
+#define GSD_IS_DUMMY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DUMMY_MANAGER))
+#define GSD_DUMMY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerClass))
+
+typedef struct GsdDummyManagerPrivate GsdDummyManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdDummyManagerPrivate *priv;
+} GsdDummyManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdDummyManagerClass;
+
+GType gsd_dummy_manager_get_type (void);
+
+GsdDummyManager * gsd_dummy_manager_new (void);
+gboolean gsd_dummy_manager_start (GsdDummyManager *manager,
+ GError **error);
+void gsd_dummy_manager_stop (GsdDummyManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_DUMMY_MANAGER_H */
diff --git a/plugins/dummy/gsd-dummy-plugin.c b/plugins/dummy/gsd-dummy-plugin.c
new file mode 100644
index 0000000..f284423
--- /dev/null
+++ b/plugins/dummy/gsd-dummy-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-dummy-plugin.h"
+#include "gsd-dummy-manager.h"
+
+struct GsdDummyPluginPrivate {
+ GsdDummyManager *manager;
+};
+
+#define GSD_DUMMY_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_DUMMY_PLUGIN, GsdDummyPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdDummyPlugin, gsd_dummy_plugin)
+
+static void
+gsd_dummy_plugin_init (GsdDummyPlugin *plugin)
+{
+ plugin->priv = GSD_DUMMY_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdDummyPlugin initializing");
+
+ plugin->priv->manager = gsd_dummy_manager_new ();
+}
+
+static void
+gsd_dummy_plugin_finalize (GObject *object)
+{
+ GsdDummyPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_DUMMY_PLUGIN (object));
+
+ g_debug ("GsdDummyPlugin finalizing");
+
+ plugin = GSD_DUMMY_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_dummy_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating dummy plugin");
+
+ error = NULL;
+ res = gsd_dummy_manager_start (GSD_DUMMY_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start dummy manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating dummy plugin");
+ gsd_dummy_manager_stop (GSD_DUMMY_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_dummy_plugin_class_init (GsdDummyPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_dummy_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdDummyPluginPrivate));
+}
diff --git a/plugins/dummy/gsd-dummy-plugin.h b/plugins/dummy/gsd-dummy-plugin.h
new file mode 100644
index 0000000..153e0fa
--- /dev/null
+++ b/plugins/dummy/gsd-dummy-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_DUMMY_PLUGIN_H__
+#define __GSD_DUMMY_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_DUMMY_PLUGIN (gsd_dummy_plugin_get_type ())
+#define GSD_DUMMY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DUMMY_PLUGIN, GsdDummyPlugin))
+#define GSD_DUMMY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_DUMMY_PLUGIN, GsdDummyPluginClass))
+#define GSD_IS_DUMMY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DUMMY_PLUGIN))
+#define GSD_IS_DUMMY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DUMMY_PLUGIN))
+#define GSD_DUMMY_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DUMMY_PLUGIN, GsdDummyPluginClass))
+
+typedef struct GsdDummyPluginPrivate GsdDummyPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdDummyPluginPrivate *priv;
+} GsdDummyPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdDummyPluginClass;
+
+GType gsd_dummy_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_DUMMY_PLUGIN_H__ */
diff --git a/plugins/font/Makefile.am b/plugins/font/Makefile.am
new file mode 100644
index 0000000..99dff34
--- /dev/null
+++ b/plugins/font/Makefile.am
@@ -0,0 +1,51 @@
+NULL =
+
+plugin_LTLIBRARIES = \
+ libfont.la \
+ $(NULL)
+
+libfont_la_SOURCES = \
+ gsd-font-plugin.h \
+ gsd-font-plugin.c \
+ gsd-font-manager.h \
+ gsd-font-manager.c \
+ delayed-dialog.h \
+ delayed-dialog.c \
+ $(NULL)
+
+libfont_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libfont_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libfont_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libfont_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ font.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/font/Makefile.in b/plugins/font/Makefile.in
new file mode 100644
index 0000000..a3c90ea
--- /dev/null
+++ b/plugins/font/Makefile.in
@@ -0,0 +1,687 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/font
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libfont_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libfont_la_OBJECTS = libfont_la-gsd-font-plugin.lo \
+ libfont_la-gsd-font-manager.lo libfont_la-delayed-dialog.lo \
+ $(am__objects_1)
+libfont_la_OBJECTS = $(am_libfont_la_OBJECTS)
+libfont_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libfont_la_CFLAGS) \
+ $(CFLAGS) $(libfont_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libfont_la_SOURCES)
+DIST_SOURCES = $(libfont_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+plugin_LTLIBRARIES = \
+ libfont.la \
+ $(NULL)
+
+libfont_la_SOURCES = \
+ gsd-font-plugin.h \
+ gsd-font-plugin.c \
+ gsd-font-manager.h \
+ gsd-font-manager.c \
+ delayed-dialog.h \
+ delayed-dialog.c \
+ $(NULL)
+
+libfont_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libfont_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libfont_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libfont_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ font.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/font/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/font/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libfont.la: $(libfont_la_OBJECTS) $(libfont_la_DEPENDENCIES)
+ $(libfont_la_LINK) -rpath $(plugindir) $(libfont_la_OBJECTS) $(libfont_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfont_la-delayed-dialog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfont_la-gsd-font-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfont_la-gsd-font-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libfont_la-gsd-font-plugin.lo: gsd-font-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfont_la_CPPFLAGS) $(CPPFLAGS) $(libfont_la_CFLAGS) $(CFLAGS) -MT libfont_la-gsd-font-plugin.lo -MD -MP -MF $(DEPDIR)/libfont_la-gsd-font-plugin.Tpo -c -o libfont_la-gsd-font-plugin.lo `test -f 'gsd-font-plugin.c' || echo '$(srcdir)/'`gsd-font-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libfont_la-gsd-font-plugin.Tpo $(DEPDIR)/libfont_la-gsd-font-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-font-plugin.c' object='libfont_la-gsd-font-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfont_la_CPPFLAGS) $(CPPFLAGS) $(libfont_la_CFLAGS) $(CFLAGS) -c -o libfont_la-gsd-font-plugin.lo `test -f 'gsd-font-plugin.c' || echo '$(srcdir)/'`gsd-font-plugin.c
+
+libfont_la-gsd-font-manager.lo: gsd-font-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfont_la_CPPFLAGS) $(CPPFLAGS) $(libfont_la_CFLAGS) $(CFLAGS) -MT libfont_la-gsd-font-manager.lo -MD -MP -MF $(DEPDIR)/libfont_la-gsd-font-manager.Tpo -c -o libfont_la-gsd-font-manager.lo `test -f 'gsd-font-manager.c' || echo '$(srcdir)/'`gsd-font-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libfont_la-gsd-font-manager.Tpo $(DEPDIR)/libfont_la-gsd-font-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-font-manager.c' object='libfont_la-gsd-font-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfont_la_CPPFLAGS) $(CPPFLAGS) $(libfont_la_CFLAGS) $(CFLAGS) -c -o libfont_la-gsd-font-manager.lo `test -f 'gsd-font-manager.c' || echo '$(srcdir)/'`gsd-font-manager.c
+
+libfont_la-delayed-dialog.lo: delayed-dialog.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfont_la_CPPFLAGS) $(CPPFLAGS) $(libfont_la_CFLAGS) $(CFLAGS) -MT libfont_la-delayed-dialog.lo -MD -MP -MF $(DEPDIR)/libfont_la-delayed-dialog.Tpo -c -o libfont_la-delayed-dialog.lo `test -f 'delayed-dialog.c' || echo '$(srcdir)/'`delayed-dialog.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libfont_la-delayed-dialog.Tpo $(DEPDIR)/libfont_la-delayed-dialog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='delayed-dialog.c' object='libfont_la-delayed-dialog.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfont_la_CPPFLAGS) $(CPPFLAGS) $(libfont_la_CFLAGS) $(CFLAGS) -c -o libfont_la-delayed-dialog.lo `test -f 'delayed-dialog.c' || echo '$(srcdir)/'`delayed-dialog.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/font/delayed-dialog.c b/plugins/font/delayed-dialog.c
new file mode 100644
index 0000000..bfc8493
--- /dev/null
+++ b/plugins/font/delayed-dialog.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "delayed-dialog.h"
+
+static gboolean delayed_show_timeout (gpointer data);
+static GdkFilterReturn message_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data);
+
+static GSList *dialogs = NULL;
+
+/**
+ * mate_settings_delayed_show_dialog:
+ * @dialog: the dialog
+ *
+ * Shows the dialog as with gtk_widget_show(), unless a window manager
+ * hasn't been started yet, in which case it will wait up to 5 seconds
+ * for that to happen before showing the dialog.
+ **/
+void
+mate_settings_delayed_show_dialog (GtkWidget *dialog)
+{
+ GdkDisplay *display = gtk_widget_get_display (dialog);
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ GdkScreen *screen = gtk_widget_get_screen (dialog);
+ GdkAtom manager_atom;
+ char selection_name[10];
+ Atom selection_atom;
+
+ /* We can't use gdk_selection_owner_get() for this, because
+ * it's an unknown out-of-process window.
+ */
+ snprintf (selection_name, sizeof (selection_name), "WM_S%d",
+ gdk_screen_get_number (screen));
+ selection_atom = XInternAtom (xdisplay, selection_name, True);
+ if (selection_atom &&
+ XGetSelectionOwner (xdisplay, selection_atom) != None) {
+ gtk_widget_show (dialog);
+ return;
+ }
+
+ dialogs = g_slist_prepend (dialogs, dialog);
+
+ manager_atom = gdk_atom_intern ("MANAGER", FALSE);
+ gdk_display_add_client_message_filter (display, manager_atom,
+ message_filter, NULL);
+
+ g_timeout_add (5000, delayed_show_timeout, NULL);
+}
+
+static gboolean
+delayed_show_timeout (gpointer data)
+{
+ GSList *l;
+
+ for (l = dialogs; l; l = l->next)
+ gtk_widget_show (l->data);
+ g_slist_free (dialogs);
+ dialogs = NULL;
+
+ /* FIXME: There's no gdk_display_remove_client_message_filter */
+
+ return FALSE;
+}
+
+static GdkFilterReturn
+message_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
+{
+ XClientMessageEvent *evt = (XClientMessageEvent *)xevent;
+ char *selection_name = XGetAtomName (evt->display, evt->data.l[1]);
+ int screen;
+ GSList *l, *next;
+
+ if (!dialogs)
+ return GDK_FILTER_CONTINUE;
+
+ if (strncmp (selection_name, "WM_S", 4) != 0) {
+ XFree (selection_name);
+ return GDK_FILTER_CONTINUE;
+ }
+
+ screen = atoi (selection_name + 4);
+
+ for (l = dialogs; l; l = next) {
+ GtkWidget *dialog = l->data;
+ next = l->next;
+
+ if (gdk_screen_get_number (gtk_widget_get_screen (dialog)) == screen) {
+ gtk_widget_show (dialog);
+ dialogs = g_slist_remove (dialogs, dialog);
+ }
+ }
+
+ if (!dialogs) {
+ /* FIXME: There's no gdk_display_remove_client_message_filter */
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
diff --git a/plugins/font/delayed-dialog.h b/plugins/font/delayed-dialog.h
new file mode 100644
index 0000000..0c35317
--- /dev/null
+++ b/plugins/font/delayed-dialog.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+
+#ifndef __DELAYED_DIALOG_H
+#define __DELAYED_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void mate_settings_delayed_show_dialog (GtkWidget *dialog);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/font/font.mate-settings-plugin.in b/plugins/font/font.mate-settings-plugin.in
new file mode 100644
index 0000000..6bb1c47
--- /dev/null
+++ b/plugins/font/font.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=font
+IAge=0
+_Name=Font
+_Description=Font plugin
+Authors=Rodrigo Moya
+Copyright=Copyright © 2007 The MATE Foundation
+Website=
diff --git a/plugins/font/gsd-font-manager.c b/plugins/font/gsd-font-manager.c
new file mode 100644
index 0000000..ed33e1c
--- /dev/null
+++ b/plugins/font/gsd-font-manager.c
@@ -0,0 +1,440 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 The MATE Foundation
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <locale.h>
+
+#include <X11/Xatom.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf.h>
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-font-manager.h"
+#include "delayed-dialog.h"
+
+static void gsd_font_manager_class_init (GsdFontManagerClass *klass);
+static void gsd_font_manager_init (GsdFontManager *font_manager);
+
+G_DEFINE_TYPE (GsdFontManager, gsd_font_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static void
+update_property (GString *props, const gchar* key, const gchar* value)
+{
+ gchar* needle;
+ size_t needle_len;
+ gchar* found = NULL;
+
+ /* update an existing property */
+ needle = g_strconcat (key, ":", NULL);
+ needle_len = strlen (needle);
+ if (g_str_has_prefix (props->str, needle))
+ found = props->str;
+ else
+ found = strstr (props->str, needle);
+
+ if (found) {
+ size_t value_index;
+ gchar* end;
+
+ end = strchr (found, '\n');
+ value_index = (found - props->str) + needle_len + 1;
+ g_string_erase (props, value_index, end ? (end - found - needle_len) : -1);
+ g_string_insert (props, value_index, "\n");
+ g_string_insert (props, value_index, value);
+ } else {
+ g_string_append_printf (props, "%s:\t%s\n", key, value);
+ }
+}
+
+static void
+load_xcursor_theme (MateConfClient *client)
+{
+ char *cursor_theme;
+ int size;
+ GString *add_string;
+ Display *dpy;
+ gchar numbuf[20];
+
+ mate_settings_profile_start (NULL);
+
+ size = mateconf_client_get_int (client,
+ "/desktop/mate/peripherals/mouse/cursor_size",
+ NULL);
+ if (size <= 0) {
+ return;
+ }
+
+ cursor_theme = mateconf_client_get_string (client,
+ "/desktop/mate/peripherals/mouse/cursor_theme",
+ NULL);
+ if (cursor_theme == NULL) {
+ return;
+ }
+
+ /* get existing properties */
+ dpy = XOpenDisplay (NULL);
+ g_return_if_fail (dpy != NULL);
+ add_string = g_string_new (XResourceManagerString (dpy));
+ g_debug("load_xcursor_theme: existing res '%s'", add_string->str);
+
+ update_property (add_string, "Xcursor.theme", cursor_theme);
+ update_property (add_string, "Xcursor.theme_core", "true");
+ g_snprintf (numbuf, sizeof (numbuf), "%i", size);
+ update_property (add_string, "Xcursor.size", numbuf);
+
+ g_debug("load_xcursor_theme: new res '%s'", add_string->str);
+
+ /* Set the new X property */
+ XChangeProperty(dpy, RootWindow (dpy, 0),
+ XA_RESOURCE_MANAGER, XA_STRING, 8, PropModeReplace, add_string->str, add_string->len);
+ XCloseDisplay (dpy);
+
+ g_free (cursor_theme);
+ g_string_free (add_string, TRUE);
+
+ mate_settings_profile_end (NULL);
+}
+
+static char*
+setup_dir (const char *font_dir_name, gboolean create)
+{
+ char *font_dir;
+
+ font_dir = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), ".mate2", "share", font_dir_name, NULL);
+
+ if (create) {
+ if (g_mkdir_with_parents (font_dir, 0755) != 0) {
+ g_warning ("Cannot create needed directory \"%s\".", font_dir);
+ g_free (font_dir);
+ font_dir = NULL;
+ }
+ } else if (! g_file_test (font_dir, G_FILE_TEST_EXISTS)) {
+ g_free (font_dir);
+ font_dir = NULL;
+ }
+
+ return font_dir;
+}
+
+static char *
+empty_check_dir (char *font_dir)
+{
+ char *file_name;
+
+ if (!font_dir)
+ return NULL;
+
+ /* remove the fonts.dir and fonts.scale files that mkfontdir generates. */
+
+ file_name = g_build_filename (G_DIR_SEPARATOR_S, font_dir, "fonts.dir", NULL);
+ unlink (file_name);
+ g_free (file_name);
+
+ file_name = g_build_filename (G_DIR_SEPARATOR_S, font_dir, "fonts.scale", NULL);
+ unlink (file_name);
+ g_free (file_name);
+
+ /* if it's empty, get rid of it. */
+ if (0 == rmdir (font_dir)) {
+ g_free (font_dir);
+ font_dir = NULL;
+ }
+
+ return font_dir;
+}
+
+static char*
+setup_font_dir (MateConfClient *client)
+{
+ return empty_check_dir (setup_dir ("fonts", FALSE));
+}
+
+static char*
+setup_cursor_dir (MateConfClient *client)
+{
+ char *cursor_dir;
+ char *cursor_font;
+ DIR *dir;
+ struct dirent *file_dirent;
+
+ cursor_font = mateconf_client_get_string (client,
+ "/desktop/mate/peripherals/mouse/cursor_font",
+ NULL);
+ if (cursor_font != NULL) {
+ if (!g_path_is_absolute (cursor_font) ||
+ !g_file_test (cursor_font, G_FILE_TEST_IS_REGULAR)) {
+ /* font file is not usable */
+ g_free (cursor_font);
+ cursor_font = NULL;
+ }
+ }
+
+ cursor_dir = setup_dir ("cursor-fonts", cursor_font != NULL);
+
+ /* remove previously made symlinks, if any */
+ if (cursor_dir) {
+ dir = opendir (cursor_dir);
+ while ((file_dirent = readdir (dir)) != NULL) {
+ struct stat st;
+ char *link_name;
+
+ link_name = g_build_filename (cursor_dir, file_dirent->d_name, NULL);
+ if (lstat (link_name, &st)) {
+ g_free (link_name);
+ continue;
+ }
+ g_free (link_name);
+
+ if (S_ISLNK (st.st_mode))
+ unlink (link_name);
+ }
+ closedir (dir);
+ }
+
+ if (cursor_font && cursor_dir) {
+ char *newpath;
+ char *font_name;
+
+ font_name = strrchr (cursor_font, G_DIR_SEPARATOR);
+ newpath = g_build_filename (cursor_dir, font_name, NULL);
+ symlink (cursor_font, newpath);
+ g_free (newpath);
+ g_free (cursor_font);
+ cursor_font = NULL;
+ } else {
+ cursor_dir = empty_check_dir (cursor_dir);
+ }
+
+ return cursor_dir;
+}
+
+static void
+load_font_paths (MateConfClient *client)
+{
+ char *font_dir_name;
+ char *cursor_dir_name;
+
+ char **font_path;
+ char **new_font_path;
+ int n_fonts;
+ int new_n_fonts;
+
+ int i;
+
+ const char *argv[4];
+ int argc = 0;
+
+ mate_settings_profile_start (NULL);
+
+ font_dir_name = setup_font_dir (client);
+ cursor_dir_name = setup_cursor_dir (client);
+
+ if (font_dir_name == NULL && cursor_dir_name == NULL)
+ goto done;
+
+ /* run mkfontdir */
+ argv[argc++] = "mkfontdir";
+ if (font_dir_name)
+ argv[argc++] = font_dir_name;
+ if (cursor_dir_name)
+ argv[argc++] = cursor_dir_name;
+ argv[argc] = NULL;
+ g_spawn_sync (NULL, /* current dir */
+ (char **) (void *) argv, NULL /* envp */,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL, /* child_setup */
+ NULL, NULL, NULL, NULL);
+
+ /* Set the font path */
+ font_path = XGetFontPath (gdk_x11_get_default_xdisplay (), &n_fonts);
+ new_n_fonts = n_fonts;
+ if (cursor_dir_name && (n_fonts == 0 || strcmp (font_path[0], cursor_dir_name)))
+ new_n_fonts++;
+ if (font_dir_name && (n_fonts == 0 || strcmp (font_path[n_fonts-1], font_dir_name)))
+ new_n_fonts++;
+
+ if (new_n_fonts == n_fonts)
+ new_font_path = font_path;
+ else {
+ new_font_path = g_new0 (char *, new_n_fonts);
+
+ if (cursor_dir_name && (n_fonts == 0 || strcmp (font_path[0], cursor_dir_name))) {
+ new_font_path[0] = cursor_dir_name;
+ for (i = 0; i < n_fonts; i++)
+ new_font_path [i+1] = font_path [i];
+ } else {
+ for (i = 0; i < n_fonts; i++)
+ new_font_path [i] = font_path [i];
+ }
+
+ if (font_dir_name && (n_fonts == 0 || strcmp (font_path[n_fonts-1], font_dir_name))) {
+ new_font_path[new_n_fonts-1] = font_dir_name;
+ }
+ }
+
+ /* We set font path even if it was not changed, to enforce dropping
+ * caches in the server */
+ gdk_error_trap_push ();
+ XSetFontPath (gdk_display, new_font_path, new_n_fonts);
+ gdk_flush ();
+
+ /* if there was an error setting the new path, revert */
+ if (gdk_error_trap_pop ()) {
+ XSetFontPath (gdk_display, font_path, n_fonts);
+ }
+
+ g_free (font_dir_name);
+ g_free (cursor_dir_name);
+
+ if (new_font_path != font_path)
+ g_free (new_font_path);
+
+ XFreeFontPath (font_path);
+
+done:
+ mate_settings_profile_end (NULL);
+}
+
+gboolean
+gsd_font_manager_start (GsdFontManager *manager,
+ GError **error)
+{
+ MateConfClient *client;
+
+ g_debug ("Starting font manager");
+ mate_settings_profile_start (NULL);
+
+ client = mateconf_client_get_default ();
+
+ load_xcursor_theme (client);
+ load_font_paths (client);
+
+ g_object_unref (client);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_font_manager_stop (GsdFontManager *manager)
+{
+ g_debug ("Stopping font manager");
+}
+
+static void
+gsd_font_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdFontManager *self;
+
+ self = GSD_FONT_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_font_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdFontManager *self;
+
+ self = GSD_FONT_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_font_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdFontManager *font_manager;
+ GsdFontManagerClass *klass;
+
+ klass = GSD_FONT_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_FONT_MANAGER));
+
+ font_manager = GSD_FONT_MANAGER (G_OBJECT_CLASS (gsd_font_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (font_manager);
+}
+
+static void
+gsd_font_manager_class_init (GsdFontManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_font_manager_get_property;
+ object_class->set_property = gsd_font_manager_set_property;
+ object_class->constructor = gsd_font_manager_constructor;
+}
+
+static void
+gsd_font_manager_init (GsdFontManager *manager)
+{
+}
+
+GsdFontManager *
+gsd_font_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_FONT_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_FONT_MANAGER (manager_object);
+}
diff --git a/plugins/font/gsd-font-manager.h b/plugins/font/gsd-font-manager.h
new file mode 100644
index 0000000..be53d98
--- /dev/null
+++ b/plugins/font/gsd-font-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_FONT_MANAGER_H
+#define __GSD_FONT_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_FONT_MANAGER (gsd_font_manager_get_type ())
+#define GSD_FONT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_FONT_MANAGER, GsdFontManager))
+#define GSD_FONT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_FONT_MANAGER, GsdFontManagerClass))
+#define GSD_IS_FONT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_FONT_MANAGER))
+#define GSD_IS_FONT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_FONT_MANAGER))
+#define GSD_FONT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_FONT_MANAGER, GsdFontManagerClass))
+
+typedef struct GsdFontManagerPrivate GsdFontManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdFontManagerPrivate *priv;
+} GsdFontManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdFontManagerClass;
+
+GType gsd_font_manager_get_type (void);
+
+GsdFontManager * gsd_font_manager_new (void);
+gboolean gsd_font_manager_start (GsdFontManager *manager,
+ GError **error);
+void gsd_font_manager_stop (GsdFontManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_FONT_MANAGER_H */
diff --git a/plugins/font/gsd-font-plugin.c b/plugins/font/gsd-font-plugin.c
new file mode 100644
index 0000000..dc34c6b
--- /dev/null
+++ b/plugins/font/gsd-font-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-font-plugin.h"
+#include "gsd-font-manager.h"
+
+struct GsdFontPluginPrivate {
+ GsdFontManager *manager;
+};
+
+#define GSD_FONT_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_FONT_PLUGIN, GsdFontPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdFontPlugin, gsd_font_plugin)
+
+static void
+gsd_font_plugin_init (GsdFontPlugin *plugin)
+{
+ plugin->priv = GSD_FONT_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdFontPlugin initializing");
+
+ plugin->priv->manager = gsd_font_manager_new ();
+}
+
+static void
+gsd_font_plugin_finalize (GObject *object)
+{
+ GsdFontPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_FONT_PLUGIN (object));
+
+ g_debug ("GsdFontPlugin finalizing");
+
+ plugin = GSD_FONT_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_font_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating font plugin");
+
+ error = NULL;
+ res = gsd_font_manager_start (GSD_FONT_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start font manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating font plugin");
+ gsd_font_manager_stop (GSD_FONT_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_font_plugin_class_init (GsdFontPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_font_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdFontPluginPrivate));
+}
diff --git a/plugins/font/gsd-font-plugin.h b/plugins/font/gsd-font-plugin.h
new file mode 100644
index 0000000..06dd2be
--- /dev/null
+++ b/plugins/font/gsd-font-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_FONT_PLUGIN_H__
+#define __GSD_FONT_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_FONT_PLUGIN (gsd_font_plugin_get_type ())
+#define GSD_FONT_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_FONT_PLUGIN, GsdFontPlugin))
+#define GSD_FONT_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_FONT_PLUGIN, GsdFontPluginClass))
+#define GSD_IS_FONT_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_FONT_PLUGIN))
+#define GSD_IS_FONT_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_FONT_PLUGIN))
+#define GSD_FONT_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_FONT_PLUGIN, GsdFontPluginClass))
+
+typedef struct GsdFontPluginPrivate GsdFontPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdFontPluginPrivate *priv;
+} GsdFontPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdFontPluginClass;
+
+GType gsd_font_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_FONT_PLUGIN_H__ */
diff --git a/plugins/housekeeping/Makefile.am b/plugins/housekeeping/Makefile.am
new file mode 100644
index 0000000..485d4ed
--- /dev/null
+++ b/plugins/housekeeping/Makefile.am
@@ -0,0 +1,40 @@
+plugin_LTLIBRARIES = libhousekeeping.la
+
+libhousekeeping_la_SOURCES = \
+ gsd-ldsm-dialog.c \
+ gsd-ldsm-dialog.h \
+ gsd-ldsm-trash-empty.c \
+ gsd-ldsm-trash-empty.h \
+ gsd-disk-space.c \
+ gsd-disk-space.h \
+ gsd-housekeeping-manager.c \
+ gsd-housekeeping-manager.h \
+ gsd-housekeeping-plugin.c \
+ gsd-housekeeping-plugin.h
+
+libhousekeeping_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libhousekeeping_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(GIOUNIX_CFLAGS) \
+ $(LIBMATENOTIFY_CFLAGS) \
+ $(AM_CFLAGS)
+
+libhousekeeping_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS)
+
+libhousekeeping_la_LIBADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBMATENOTIFY_LIBS)
+
+plugin_in_files = housekeeping.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = $(plugin_in_files)
+
+CLEANFILES = $(plugin_DATA)
+
+DISTCLEANFILES = (plugin_DATA)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/housekeeping/Makefile.in b/plugins/housekeeping/Makefile.in
new file mode 100644
index 0000000..806a4d5
--- /dev/null
+++ b/plugins/housekeeping/Makefile.in
@@ -0,0 +1,689 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/housekeeping
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libhousekeeping_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libhousekeeping_la_OBJECTS = libhousekeeping_la-gsd-ldsm-dialog.lo \
+ libhousekeeping_la-gsd-ldsm-trash-empty.lo \
+ libhousekeeping_la-gsd-disk-space.lo \
+ libhousekeeping_la-gsd-housekeeping-manager.lo \
+ libhousekeeping_la-gsd-housekeeping-plugin.lo
+libhousekeeping_la_OBJECTS = $(am_libhousekeeping_la_OBJECTS)
+libhousekeeping_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libhousekeeping_la_CFLAGS) $(CFLAGS) \
+ $(libhousekeeping_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libhousekeeping_la_SOURCES)
+DIST_SOURCES = $(libhousekeeping_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libhousekeeping.la
+libhousekeeping_la_SOURCES = \
+ gsd-ldsm-dialog.c \
+ gsd-ldsm-dialog.h \
+ gsd-ldsm-trash-empty.c \
+ gsd-ldsm-trash-empty.h \
+ gsd-disk-space.c \
+ gsd-disk-space.h \
+ gsd-housekeeping-manager.c \
+ gsd-housekeeping-manager.h \
+ gsd-housekeeping-plugin.c \
+ gsd-housekeeping-plugin.h
+
+libhousekeeping_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libhousekeeping_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(GIOUNIX_CFLAGS) \
+ $(LIBMATENOTIFY_CFLAGS) \
+ $(AM_CFLAGS)
+
+libhousekeeping_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS)
+libhousekeeping_la_LIBADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBMATENOTIFY_LIBS)
+plugin_in_files = housekeeping.mate-settings-plugin.in
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = $(plugin_in_files)
+CLEANFILES = $(plugin_DATA)
+DISTCLEANFILES = (plugin_DATA)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/housekeeping/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/housekeeping/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libhousekeeping.la: $(libhousekeeping_la_OBJECTS) $(libhousekeeping_la_DEPENDENCIES)
+ $(libhousekeeping_la_LINK) -rpath $(plugindir) $(libhousekeeping_la_OBJECTS) $(libhousekeeping_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhousekeeping_la-gsd-disk-space.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhousekeeping_la-gsd-housekeeping-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhousekeeping_la-gsd-housekeeping-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhousekeeping_la-gsd-ldsm-dialog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhousekeeping_la-gsd-ldsm-trash-empty.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libhousekeeping_la-gsd-ldsm-dialog.lo: gsd-ldsm-dialog.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -MT libhousekeeping_la-gsd-ldsm-dialog.lo -MD -MP -MF $(DEPDIR)/libhousekeeping_la-gsd-ldsm-dialog.Tpo -c -o libhousekeeping_la-gsd-ldsm-dialog.lo `test -f 'gsd-ldsm-dialog.c' || echo '$(srcdir)/'`gsd-ldsm-dialog.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libhousekeeping_la-gsd-ldsm-dialog.Tpo $(DEPDIR)/libhousekeeping_la-gsd-ldsm-dialog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-ldsm-dialog.c' object='libhousekeeping_la-gsd-ldsm-dialog.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -c -o libhousekeeping_la-gsd-ldsm-dialog.lo `test -f 'gsd-ldsm-dialog.c' || echo '$(srcdir)/'`gsd-ldsm-dialog.c
+
+libhousekeeping_la-gsd-ldsm-trash-empty.lo: gsd-ldsm-trash-empty.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -MT libhousekeeping_la-gsd-ldsm-trash-empty.lo -MD -MP -MF $(DEPDIR)/libhousekeeping_la-gsd-ldsm-trash-empty.Tpo -c -o libhousekeeping_la-gsd-ldsm-trash-empty.lo `test -f 'gsd-ldsm-trash-empty.c' || echo '$(srcdir)/'`gsd-ldsm-trash-empty.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libhousekeeping_la-gsd-ldsm-trash-empty.Tpo $(DEPDIR)/libhousekeeping_la-gsd-ldsm-trash-empty.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-ldsm-trash-empty.c' object='libhousekeeping_la-gsd-ldsm-trash-empty.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -c -o libhousekeeping_la-gsd-ldsm-trash-empty.lo `test -f 'gsd-ldsm-trash-empty.c' || echo '$(srcdir)/'`gsd-ldsm-trash-empty.c
+
+libhousekeeping_la-gsd-disk-space.lo: gsd-disk-space.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -MT libhousekeeping_la-gsd-disk-space.lo -MD -MP -MF $(DEPDIR)/libhousekeeping_la-gsd-disk-space.Tpo -c -o libhousekeeping_la-gsd-disk-space.lo `test -f 'gsd-disk-space.c' || echo '$(srcdir)/'`gsd-disk-space.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libhousekeeping_la-gsd-disk-space.Tpo $(DEPDIR)/libhousekeeping_la-gsd-disk-space.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-disk-space.c' object='libhousekeeping_la-gsd-disk-space.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -c -o libhousekeeping_la-gsd-disk-space.lo `test -f 'gsd-disk-space.c' || echo '$(srcdir)/'`gsd-disk-space.c
+
+libhousekeeping_la-gsd-housekeeping-manager.lo: gsd-housekeeping-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -MT libhousekeeping_la-gsd-housekeeping-manager.lo -MD -MP -MF $(DEPDIR)/libhousekeeping_la-gsd-housekeeping-manager.Tpo -c -o libhousekeeping_la-gsd-housekeeping-manager.lo `test -f 'gsd-housekeeping-manager.c' || echo '$(srcdir)/'`gsd-housekeeping-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libhousekeeping_la-gsd-housekeeping-manager.Tpo $(DEPDIR)/libhousekeeping_la-gsd-housekeeping-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-housekeeping-manager.c' object='libhousekeeping_la-gsd-housekeeping-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -c -o libhousekeeping_la-gsd-housekeeping-manager.lo `test -f 'gsd-housekeeping-manager.c' || echo '$(srcdir)/'`gsd-housekeeping-manager.c
+
+libhousekeeping_la-gsd-housekeeping-plugin.lo: gsd-housekeeping-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -MT libhousekeeping_la-gsd-housekeeping-plugin.lo -MD -MP -MF $(DEPDIR)/libhousekeeping_la-gsd-housekeeping-plugin.Tpo -c -o libhousekeeping_la-gsd-housekeeping-plugin.lo `test -f 'gsd-housekeeping-plugin.c' || echo '$(srcdir)/'`gsd-housekeeping-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libhousekeeping_la-gsd-housekeeping-plugin.Tpo $(DEPDIR)/libhousekeeping_la-gsd-housekeeping-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-housekeeping-plugin.c' object='libhousekeeping_la-gsd-housekeeping-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhousekeeping_la_CPPFLAGS) $(CPPFLAGS) $(libhousekeeping_la_CFLAGS) $(CFLAGS) -c -o libhousekeeping_la-gsd-housekeeping-plugin.lo `test -f 'gsd-housekeeping-plugin.c' || echo '$(srcdir)/'`gsd-housekeeping-plugin.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/housekeeping/gsd-disk-space.c b/plugins/housekeeping/gsd-disk-space.c
new file mode 100644
index 0000000..951264f
--- /dev/null
+++ b/plugins/housekeeping/gsd-disk-space.c
@@ -0,0 +1,733 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et sw=8 ts=8:
+ *
+ * Copyright (c) 2008, Novell, Inc.
+ *
+ * Authors: Vincent Untz <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* gcc -DHAVE_LIBMATENOTIFY -DTEST -Wall `pkg-config --cflags --libs gobject-2.0 gio-unix-2.0 glib-2.0 gtk+-2.0 libmatenotify` -o gsd-disk-space-test gsd-disk-space.c */
+
+#include "config.h"
+
+#include <sys/statvfs.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gunixmounts.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include "gsd-disk-space.h"
+#include "gsd-ldsm-dialog.h"
+#include "gsd-ldsm-trash-empty.h"
+
+
+#define GIGABYTE 1024 * 1024 * 1024
+
+#define CHECK_EVERY_X_SECONDS 60
+
+#define DISK_SPACE_ANALYZER "baobab"
+
+#define MATECONF_HOUSEKEEPING_DIR "/apps/mate_settings_daemon/plugins/housekeeping"
+#define MATECONF_FREE_PC_NOTIFY_KEY "free_percent_notify"
+#define MATECONF_FREE_PC_NOTIFY_AGAIN_KEY "free_percent_notify_again"
+#define MATECONF_FREE_SIZE_NO_NOTIFY "free_size_gb_no_notify"
+#define MATECONF_MIN_NOTIFY_PERIOD "min_notify_period"
+#define MATECONF_IGNORE_PATHS "ignore_paths"
+
+typedef struct
+{
+ GUnixMountEntry *mount;
+ struct statvfs buf;
+ time_t notify_time;
+} LdsmMountInfo;
+
+static GHashTable *ldsm_notified_hash = NULL;
+static unsigned int ldsm_timeout_id = 0;
+static GUnixMountMonitor *ldsm_monitor = NULL;
+static double free_percent_notify = 0.05;
+static double free_percent_notify_again = 0.01;
+static unsigned int free_size_gb_no_notify = 2;
+static unsigned int min_notify_period = 10;
+static GSList *ignore_paths = NULL;
+static unsigned int mateconf_notify_id;
+static MateConfClient *client = NULL;
+static GsdLdsmDialog *dialog = NULL;
+static guint64 *time_read;
+
+static gchar*
+ldsm_get_fs_id_for_path (const gchar *path)
+{
+ GFile *file;
+ GFileInfo *fileinfo;
+ gchar *attr_id_fs;
+
+ file = g_file_new_for_path (path);
+ fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
+ if (fileinfo) {
+ attr_id_fs = g_strdup (g_file_info_get_attribute_string (fileinfo, G_FILE_ATTRIBUTE_ID_FILESYSTEM));
+ g_object_unref (fileinfo);
+ } else {
+ attr_id_fs = NULL;
+ }
+
+ g_object_unref (file);
+
+ return attr_id_fs;
+}
+
+static gboolean
+ldsm_mount_has_trash (LdsmMountInfo *mount)
+{
+ const gchar *user_data_dir;
+ gchar *user_data_attr_id_fs;
+ gchar *path_attr_id_fs;
+ gboolean mount_uses_user_trash = FALSE;
+ gchar *trash_files_dir;
+ gboolean has_trash = FALSE;
+ GDir *dir;
+ const gchar *path;
+
+ user_data_dir = g_get_user_data_dir ();
+ user_data_attr_id_fs = ldsm_get_fs_id_for_path (user_data_dir);
+
+ path = g_unix_mount_get_mount_path (mount->mount);
+ path_attr_id_fs = ldsm_get_fs_id_for_path (path);
+
+ if (g_strcmp0 (user_data_attr_id_fs, path_attr_id_fs) == 0) {
+ /* The volume that is low on space is on the same volume as our home
+ * directory. This means the trash is at $XDG_DATA_HOME/Trash,
+ * not at the root of the volume which is full.
+ */
+ mount_uses_user_trash = TRUE;
+ }
+
+ g_free (user_data_attr_id_fs);
+ g_free (path_attr_id_fs);
+
+ /* I can't think of a better way to find out if a volume has any trash. Any suggestions? */
+ if (mount_uses_user_trash) {
+ trash_files_dir = g_build_filename (g_get_user_data_dir (), "Trash", "files", NULL);
+ } else {
+ gchar *uid;
+
+ uid = g_strdup_printf ("%d", getuid ());
+ trash_files_dir = g_build_filename (path, ".Trash", uid, "files", NULL);
+ if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) {
+ gchar *trash_dir;
+
+ g_free (trash_files_dir);
+ trash_dir = g_strdup_printf (".Trash-%s", uid);
+ trash_files_dir = g_build_filename (path, trash_dir, "files", NULL);
+ g_free (trash_dir);
+ if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) {
+ g_free (trash_files_dir);
+ g_free (uid);
+ return has_trash;
+ }
+ }
+ g_free (uid);
+ }
+
+ dir = g_dir_open (trash_files_dir, 0, NULL);
+ if (dir) {
+ if (g_dir_read_name (dir))
+ has_trash = TRUE;
+ g_dir_close (dir);
+ }
+
+ g_free (trash_files_dir);
+
+ return has_trash;
+}
+
+static void
+ldsm_analyze_path (const gchar *path)
+{
+ const gchar *argv[] = { DISK_SPACE_ANALYZER, path, NULL };
+
+ g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+ldsm_notify_for_mount (LdsmMountInfo *mount,
+ gboolean multiple_volumes,
+ gboolean other_usable_volumes)
+{
+ gchar *name, *program;
+ gint64 free_space;
+ gint response;
+ gboolean has_trash;
+ gboolean has_disk_analyzer;
+ gboolean retval = TRUE;
+ const gchar *path;
+
+ /* Don't show a dialog if one is already displayed */
+ if (dialog)
+ return retval;
+
+ name = g_unix_mount_guess_name (mount->mount);
+ free_space = (gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail;
+ has_trash = ldsm_mount_has_trash (mount);
+ path = g_unix_mount_get_mount_path (mount->mount);
+
+ program = g_find_program_in_path (DISK_SPACE_ANALYZER);
+ has_disk_analyzer = (program != NULL);
+ g_free (program);
+
+ dialog = gsd_ldsm_dialog_new (other_usable_volumes,
+ multiple_volumes,
+ has_disk_analyzer,
+ has_trash,
+ free_space,
+ name,
+ path);
+
+ g_free (name);
+
+ g_object_ref (G_OBJECT (dialog));
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ gtk_object_destroy (GTK_OBJECT (dialog));
+ dialog = NULL;
+
+ switch (response) {
+ case GTK_RESPONSE_CANCEL:
+ retval = FALSE;
+ break;
+ case GSD_LDSM_DIALOG_RESPONSE_ANALYZE:
+ retval = FALSE;
+ ldsm_analyze_path (g_unix_mount_get_mount_path (mount->mount));
+ break;
+ case GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH:
+ retval = TRUE;
+ gsd_ldsm_trash_empty ();
+ break;
+ case GTK_RESPONSE_NONE:
+ case GTK_RESPONSE_DELETE_EVENT:
+ retval = TRUE;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return retval;
+}
+
+static gboolean
+ldsm_mount_has_space (LdsmMountInfo *mount)
+{
+ gdouble free_space;
+
+ free_space = (double) mount->buf.f_bavail / (double) mount->buf.f_blocks;
+ /* enough free space, nothing to do */
+ if (free_space > free_percent_notify)
+ return TRUE;
+
+ if (((gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail) > ((gint64) free_size_gb_no_notify * GIGABYTE))
+ return TRUE;
+
+ /* If we got here, then this volume is low on space */
+ return FALSE;
+}
+
+static gboolean
+ldsm_mount_is_virtual (LdsmMountInfo *mount)
+{
+ if (mount->buf.f_blocks == 0) {
+ /* Filesystems with zero blocks are virtual */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+ldsm_ignore_path_compare (gconstpointer a,
+ gconstpointer b)
+{
+ return g_strcmp0 ((const gchar *)a, (const gchar *)b);
+}
+
+static gboolean
+ldsm_mount_is_user_ignore (const gchar *path)
+{
+ if (g_slist_find_custom (ignore_paths, path, (GCompareFunc) ldsm_ignore_path_compare) != NULL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static gboolean
+is_in (const gchar *value, const gchar *set[])
+{
+ int i;
+ for (i = 0; set[i] != NULL; i++)
+ {
+ if (strcmp (set[i], value) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+ldsm_mount_should_ignore (GUnixMountEntry *mount)
+{
+ const gchar *fs, *device, *path;
+
+ path = g_unix_mount_get_mount_path (mount);
+ if (ldsm_mount_is_user_ignore (path))
+ return TRUE;
+
+ /* This is borrowed from GLib and used as a way to determine
+ * which mounts we should ignore by default. GLib doesn't
+ * expose this in a way that allows it to be used for this
+ * purpose
+ */
+
+ const gchar *ignore_fs[] = {
+ "auto",
+ "autofs",
+ "devfs",
+ "devpts",
+ "ecryptfs",
+ "kernfs",
+ "linprocfs",
+ "proc",
+ "procfs",
+ "ptyfs",
+ "selinuxfs",
+ "linsysfs",
+ "sysfs",
+ "tmpfs",
+ "usbfs",
+ "nfsd",
+ "rpc_pipefs",
+ "zfs",
+ NULL
+ };
+ const gchar *ignore_devices[] = {
+ "none",
+ "sunrpc",
+ "devpts",
+ "nfsd",
+ "/dev/loop",
+ "/dev/vn",
+ NULL
+ };
+
+ fs = g_unix_mount_get_fs_type (mount);
+ device = g_unix_mount_get_device_path (mount);
+
+ if (is_in (fs, ignore_fs))
+ return TRUE;
+
+ if (is_in (device, ignore_devices))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+ldsm_free_mount_info (gpointer data)
+{
+ LdsmMountInfo *mount = data;
+
+ g_return_if_fail (mount != NULL);
+
+ g_unix_mount_free (mount->mount);
+ g_free (mount);
+}
+
+static void
+ldsm_maybe_warn_mounts (GList *mounts,
+ gboolean multiple_volumes,
+ gboolean other_usable_volumes)
+{
+ GList *l;
+ gboolean done = FALSE;
+
+ for (l = mounts; l != NULL; l = l->next) {
+ LdsmMountInfo *mount_info = l->data;
+ LdsmMountInfo *previous_mount_info;
+ gdouble free_space;
+ gdouble previous_free_space;
+ time_t curr_time;
+ const gchar *path;
+ gboolean show_notify;
+
+ if (done) {
+ /* Don't show any more dialogs if the user took action with the last one. The user action
+ * might free up space on multiple volumes, making the next dialog redundant.
+ */
+ ldsm_free_mount_info (mount_info);
+ continue;
+ }
+
+ path = g_unix_mount_get_mount_path (mount_info->mount);
+
+ previous_mount_info = g_hash_table_lookup (ldsm_notified_hash, path);
+ if (previous_mount_info != NULL)
+ previous_free_space = (gdouble) previous_mount_info->buf.f_bavail / (gdouble) previous_mount_info->buf.f_blocks;
+
+ free_space = (gdouble) mount_info->buf.f_bavail / (gdouble) mount_info->buf.f_blocks;
+
+ if (previous_mount_info == NULL) {
+ /* We haven't notified for this mount yet */
+ show_notify = TRUE;
+ mount_info->notify_time = time (NULL);
+ g_hash_table_replace (ldsm_notified_hash, g_strdup (path), mount_info);
+ } else if ((previous_free_space - free_space) > free_percent_notify_again) {
+ /* We've notified for this mount before and free space has decreased sufficiently since last time to notify again */
+ curr_time = time (NULL);
+ if (difftime (curr_time, previous_mount_info->notify_time) > (gdouble)(min_notify_period * 60)) {
+ show_notify = TRUE;
+ mount_info->notify_time = curr_time;
+ } else {
+ /* It's too soon to show the dialog again. However, we still replace the LdsmMountInfo
+ * struct in the hash table, but give it the notfiy time from the previous dialog.
+ * This will stop the notification from reappearing unnecessarily as soon as the timeout expires.
+ */
+ show_notify = FALSE;
+ mount_info->notify_time = previous_mount_info->notify_time;
+ }
+ g_hash_table_replace (ldsm_notified_hash, g_strdup (path), mount_info);
+ } else {
+ /* We've notified for this mount before, but the free space hasn't decreased sufficiently to notify again */
+ ldsm_free_mount_info (mount_info);
+ show_notify = FALSE;
+ }
+
+ if (show_notify) {
+ if (ldsm_notify_for_mount (mount_info, multiple_volumes, other_usable_volumes))
+ done = TRUE;
+ }
+ }
+}
+
+static gboolean
+ldsm_check_all_mounts (gpointer data)
+{
+ GList *mounts;
+ GList *l;
+ GList *check_mounts = NULL;
+ GList *full_mounts = NULL;
+ guint number_of_mounts;
+ guint number_of_full_mounts;
+ gboolean multiple_volumes = FALSE;
+ gboolean other_usable_volumes = FALSE;
+
+ /* We iterate through the static mounts in /etc/fstab first, seeing if
+ * they're mounted by checking if the GUnixMountPoint has a corresponding GUnixMountEntry.
+ * Iterating through the static mounts means we automatically ignore dynamically mounted media.
+ */
+ mounts = g_unix_mount_points_get (time_read);
+
+ for (l = mounts; l != NULL; l = l->next) {
+ GUnixMountPoint *mount_point = l->data;
+ GUnixMountEntry *mount;
+ LdsmMountInfo *mount_info;
+ const gchar *path;
+
+ path = g_unix_mount_point_get_mount_path (mount_point);
+ mount = g_unix_mount_at (path, time_read);
+ g_unix_mount_point_free (mount_point);
+ if (mount == NULL) {
+ /* The GUnixMountPoint is not mounted */
+ continue;
+ }
+
+ mount_info = g_new0 (LdsmMountInfo, 1);
+ mount_info->mount = mount;
+
+ path = g_unix_mount_get_mount_path (mount);
+
+ if (g_unix_mount_is_readonly (mount)) {
+ ldsm_free_mount_info (mount_info);
+ continue;
+ }
+
+ if (ldsm_mount_should_ignore (mount)) {
+ ldsm_free_mount_info (mount_info);
+ continue;
+ }
+
+ if (statvfs (path, &mount_info->buf) != 0) {
+ ldsm_free_mount_info (mount_info);
+ continue;
+ }
+
+ if (ldsm_mount_is_virtual (mount_info)) {
+ ldsm_free_mount_info (mount_info);
+ continue;
+ }
+
+ check_mounts = g_list_prepend (check_mounts, mount_info);
+ }
+
+ number_of_mounts = g_list_length (check_mounts);
+ if (number_of_mounts > 1)
+ multiple_volumes = TRUE;
+
+ for (l = check_mounts; l != NULL; l = l->next) {
+ LdsmMountInfo *mount_info = l->data;
+
+ if (!ldsm_mount_has_space (mount_info)) {
+ full_mounts = g_list_prepend (full_mounts, mount_info);
+ } else {
+ g_hash_table_remove (ldsm_notified_hash, g_unix_mount_get_mount_path (mount_info->mount));
+ ldsm_free_mount_info (mount_info);
+ }
+ }
+
+ number_of_full_mounts = g_list_length (full_mounts);
+ if (number_of_mounts > number_of_full_mounts)
+ other_usable_volumes = TRUE;
+
+ ldsm_maybe_warn_mounts (full_mounts, multiple_volumes,
+ other_usable_volumes);
+
+ g_list_free (check_mounts);
+ g_list_free (full_mounts);
+
+ return TRUE;
+}
+
+static gboolean
+ldsm_is_hash_item_not_in_mounts (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GList *l;
+
+ for (l = (GList *) user_data; l != NULL; l = l->next) {
+ GUnixMountEntry *mount = l->data;
+ const char *path;
+
+ path = g_unix_mount_get_mount_path (mount);
+
+ if (strcmp (path, key) == 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+ldsm_mounts_changed (GObject *monitor,
+ gpointer data)
+{
+ GList *mounts;
+
+ /* remove the saved data for mounts that got removed */
+ mounts = g_unix_mounts_get (time_read);
+ g_hash_table_foreach_remove (ldsm_notified_hash,
+ ldsm_is_hash_item_not_in_mounts, mounts);
+ g_list_foreach (mounts, (GFunc) g_unix_mount_free, NULL);
+
+ /* check the status now, for the new mounts */
+ ldsm_check_all_mounts (NULL);
+
+ /* and reset the timeout */
+ if (ldsm_timeout_id)
+ g_source_remove (ldsm_timeout_id);
+ ldsm_timeout_id = g_timeout_add_seconds (CHECK_EVERY_X_SECONDS,
+ ldsm_check_all_mounts, NULL);
+}
+
+static gboolean
+ldsm_is_hash_item_in_ignore_paths (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ return ldsm_mount_is_user_ignore (key);
+}
+
+static void
+gsd_ldsm_get_config ()
+{
+ GError *error = NULL;
+
+ free_percent_notify = mateconf_client_get_float (client,
+ MATECONF_HOUSEKEEPING_DIR "/" MATECONF_FREE_PC_NOTIFY_KEY,
+ &error);
+ if (error != NULL) {
+ g_warning ("Error reading configuration from MateConf: %s", error->message ? error->message : "Unknown error");
+ g_clear_error (&error);
+ }
+ if (free_percent_notify >= 1 || free_percent_notify < 0) {
+ g_warning ("Invalid configuration of free_percent_notify: %f\n" \
+ "Using sensible default", free_percent_notify);
+ free_percent_notify = 0.05;
+ }
+
+ free_percent_notify_again = mateconf_client_get_float (client,
+ MATECONF_HOUSEKEEPING_DIR "/" MATECONF_FREE_PC_NOTIFY_AGAIN_KEY,
+ &error);
+ if (error != NULL) {
+ g_warning ("Error reading configuration from MateConf: %s", error->message ? error->message : "Unknown error");
+ g_clear_error (&error);
+ }
+ if (free_percent_notify_again >= 1 || free_percent_notify_again < 0) {
+ g_warning ("Invalid configuration of free_percent_notify_again: %f\n" \
+ "Using sensible default\n", free_percent_notify_again);
+ free_percent_notify_again = 0.01;
+ }
+
+ free_size_gb_no_notify = mateconf_client_get_int (client,
+ MATECONF_HOUSEKEEPING_DIR "/" MATECONF_FREE_SIZE_NO_NOTIFY,
+ &error);
+ if (error != NULL) {
+ g_warning ("Error reading configuration from MateConf: %s", error->message ? error->message : "Unknown error");
+ g_clear_error (&error);
+ }
+ min_notify_period = mateconf_client_get_int (client,
+ MATECONF_HOUSEKEEPING_DIR "/" MATECONF_MIN_NOTIFY_PERIOD,
+ &error);
+ if (error != NULL) {
+ g_warning ("Error reading configuration from MateConf: %s", error->message ? error->message : "Unkown error");
+ g_clear_error (&error);
+ }
+
+ if (ignore_paths != NULL) {
+ g_slist_foreach (ignore_paths, (GFunc) g_free, NULL);
+ g_slist_free (ignore_paths);
+ }
+ ignore_paths = mateconf_client_get_list (client,
+ MATECONF_HOUSEKEEPING_DIR "/" MATECONF_IGNORE_PATHS,
+ MATECONF_VALUE_STRING, &error);
+ if (error != NULL) {
+ g_warning ("Error reading configuration from MateConf: %s", error->message ? error->message : "Unkown error");
+ g_clear_error (&error);
+ } else {
+ /* Make sure we dont leave stale entries in ldsm_notified_hash */
+ g_hash_table_foreach_remove (ldsm_notified_hash,
+ ldsm_is_hash_item_in_ignore_paths, NULL);
+ }
+}
+
+static void
+gsd_ldsm_update_config (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ gsd_ldsm_get_config ();
+}
+
+void
+gsd_ldsm_setup (gboolean check_now)
+{
+ GError *error = NULL;
+
+ if (ldsm_notified_hash || ldsm_timeout_id || ldsm_monitor) {
+ g_warning ("Low disk space monitor already initialized.");
+ return;
+ }
+
+ ldsm_notified_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free,
+ ldsm_free_mount_info);
+
+ client = mateconf_client_get_default ();
+ if (client != NULL) {
+ gsd_ldsm_get_config ();
+ mateconf_notify_id = mateconf_client_notify_add (client,
+ MATECONF_HOUSEKEEPING_DIR,
+ (MateConfClientNotifyFunc) gsd_ldsm_update_config,
+ NULL, NULL, &error);
+ if (error != NULL) {
+ g_warning ("Cannot register callback for MateConf notification");
+ g_clear_error (&error);
+ }
+ } else {
+ g_warning ("Failed to get default client");
+ }
+
+ ldsm_monitor = g_unix_mount_monitor_new ();
+ g_unix_mount_monitor_set_rate_limit (ldsm_monitor, 1000);
+ g_signal_connect (ldsm_monitor, "mounts-changed",
+ G_CALLBACK (ldsm_mounts_changed), NULL);
+
+ if (check_now)
+ ldsm_check_all_mounts (NULL);
+
+ ldsm_timeout_id = g_timeout_add_seconds (CHECK_EVERY_X_SECONDS,
+ ldsm_check_all_mounts, NULL);
+
+}
+
+void
+gsd_ldsm_clean (void)
+{
+ if (ldsm_timeout_id)
+ g_source_remove (ldsm_timeout_id);
+ ldsm_timeout_id = 0;
+
+ if (ldsm_notified_hash)
+ g_hash_table_destroy (ldsm_notified_hash);
+ ldsm_notified_hash = NULL;
+
+ if (ldsm_monitor)
+ g_object_unref (ldsm_monitor);
+ ldsm_monitor = NULL;
+
+ if (client) {
+ mateconf_client_notify_remove (client, mateconf_notify_id);
+ g_object_unref (client);
+ }
+
+ if (dialog) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ dialog = NULL;
+ }
+
+ if (ignore_paths) {
+ g_slist_foreach (ignore_paths, (GFunc) g_free, NULL);
+ g_slist_free (ignore_paths);
+ }
+}
+
+#ifdef TEST
+int
+main (int argc,
+ char **argv)
+{
+ GMainLoop *loop;
+
+ gtk_init (&argc, &argv);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ gsd_ldsm_setup (TRUE);
+
+ g_main_loop_run (loop);
+
+ gsd_ldsm_clean ();
+ g_main_loop_unref (loop);
+
+ return 0;
+}
+#endif /* TEST */
diff --git a/plugins/housekeeping/gsd-disk-space.h b/plugins/housekeeping/gsd-disk-space.h
new file mode 100644
index 0000000..9a079a4
--- /dev/null
+++ b/plugins/housekeeping/gsd-disk-space.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et sw=8 ts=8:
+ *
+ * Copyright (c) 2008, Novell, Inc.
+ *
+ * Authors: Vincent Untz <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_DISK_SPACE_H
+#define __GSD_DISK_SPACE_H
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gsd_ldsm_setup (gboolean check_now);
+void gsd_ldsm_clean (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_DISK_SPACE_H */
diff --git a/plugins/housekeeping/gsd-housekeeping-manager.c b/plugins/housekeeping/gsd-housekeeping-manager.c
new file mode 100644
index 0000000..bbdea2c
--- /dev/null
+++ b/plugins/housekeeping/gsd-housekeeping-manager.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2008 Michael J. Chudobiak <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <mateconf/mateconf-client.h>
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <string.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-housekeeping-manager.h"
+#include "gsd-disk-space.h"
+
+
+/* General */
+#define INTERVAL_ONCE_A_DAY 24*60*60
+#define INTERVAL_TWO_MINUTES 2*60
+
+
+/* Thumbnail cleaner */
+#define MATECONF_THUMB_AGE "/desktop/mate/thumbnail_cache/maximum_age"
+#define DEFAULT_MAX_AGE_IN_DAYS 180
+#define MATECONF_THUMB_SIZE "/desktop/mate/thumbnail_cache/maximum_size"
+#define DEFAULT_MAX_SIZE_IN_MB 512
+#define MATECONF_THUMB_BINDING_DIR "/desktop/mate/thumbnail_cache"
+
+
+struct GsdHousekeepingManagerPrivate {
+ guint long_term_cb;
+ guint short_term_cb;
+ guint mateconf_notify;
+};
+
+
+#define GSD_HOUSEKEEPING_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerPrivate))
+
+static void gsd_housekeeping_manager_class_init (GsdHousekeepingManagerClass *klass);
+static void gsd_housekeeping_manager_init (GsdHousekeepingManager *housekeeping_manager);
+
+G_DEFINE_TYPE (GsdHousekeepingManager, gsd_housekeeping_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+
+typedef struct {
+ glong now;
+ glong max_age;
+ goffset total_size;
+ goffset max_size;
+} PurgeData;
+
+
+typedef struct {
+ time_t mtime;
+ char *path;
+ glong size;
+} ThumbData;
+
+
+static void
+thumb_data_free (gpointer data)
+{
+ ThumbData *info = data;
+
+ if (info) {
+ g_free (info->path);
+ g_free (info);
+ }
+}
+
+
+static GList *
+read_dir_for_purge (const char *path, GList *files)
+{
+ GFile *read_path;
+ GFileEnumerator *enum_dir;
+
+ read_path = g_file_new_for_path (path);
+ enum_dir = g_file_enumerate_children (read_path,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (enum_dir != NULL) {
+ GFileInfo *info;
+ while ((info = g_file_enumerator_next_file (enum_dir, NULL, NULL)) != NULL) {
+ const char *name;
+ name = g_file_info_get_name (info);
+
+ if (strlen (name) == 36 && strcmp (name + 32, ".png") == 0) {
+ ThumbData *td;
+ GFile *entry;
+ char *entry_path;
+ GTimeVal mod_time;
+
+ entry = g_file_get_child (read_path, name);
+ entry_path = g_file_get_path (entry);
+ g_object_unref (entry);
+
+ g_file_info_get_modification_time (info, &mod_time);
+
+ td = g_new0 (ThumbData, 1);
+ td->path = entry_path;
+ td->mtime = mod_time.tv_sec;
+ td->size = g_file_info_get_size (info);
+
+ files = g_list_prepend (files, td);
+ }
+ g_object_unref (info);
+ }
+ g_object_unref (enum_dir);
+ }
+ g_object_unref (read_path);
+
+ return files;
+}
+
+
+static void
+purge_old_thumbnails (ThumbData *info, PurgeData *purge_data)
+{
+ if ((purge_data->now - info->mtime) > purge_data->max_age) {
+ g_unlink (info->path);
+ info->size = 0;
+ } else {
+ purge_data->total_size += info->size;
+ }
+}
+
+
+static int
+sort_file_mtime (ThumbData *file1, ThumbData *file2)
+{
+ return file1->mtime - file2->mtime;
+}
+
+
+static int
+get_mateconf_int_with_default (char *key, int default_value)
+{
+ /* If the key is unset, we use a non-zero default value.
+ A zero value corresponds to an extra-paranoid level
+ of cleaning - it deletes all files. We don't want that
+ as a default condition. */
+
+ MateConfValue *value;
+ MateConfClient *client;
+ int res;
+
+ client = mateconf_client_get_default ();
+ value = mateconf_client_get (client, key, NULL);
+ g_object_unref (client);
+
+ if (value == NULL || value->type != MATECONF_VALUE_INT) {
+ res = default_value;
+ } else {
+ res = mateconf_value_get_int (value);
+ mateconf_value_free (value);
+ }
+
+ return res;
+}
+
+
+static void
+purge_thumbnail_cache (void)
+{
+
+ char *path;
+ GList *files;
+ PurgeData purge_data;
+ GTimeVal current_time;
+
+ g_debug ("housekeeping: checking thumbnail cache size and freshness");
+
+ path = g_build_filename (g_get_home_dir (),
+ ".thumbnails",
+ "normal",
+ NULL);
+ files = read_dir_for_purge (path, NULL);
+ g_free (path);
+
+ path = g_build_filename (g_get_home_dir (),
+ ".thumbnails",
+ "large",
+ NULL);
+ files = read_dir_for_purge (path, files);
+ g_free (path);
+
+ path = g_build_filename (g_get_home_dir (),
+ ".thumbnails",
+ "fail",
+ "mate-thumbnail-factory",
+ NULL);
+ files = read_dir_for_purge (path, files);
+ g_free (path);
+
+ g_get_current_time (&current_time);
+
+ purge_data.now = current_time.tv_sec;
+ purge_data.max_age = get_mateconf_int_with_default (MATECONF_THUMB_AGE, DEFAULT_MAX_AGE_IN_DAYS) * 24 * 60 * 60;
+ purge_data.max_size = get_mateconf_int_with_default (MATECONF_THUMB_SIZE, DEFAULT_MAX_SIZE_IN_MB) * 1024 * 1024;
+ purge_data.total_size = 0;
+
+ if (purge_data.max_age >= 0)
+ g_list_foreach (files, (GFunc) purge_old_thumbnails, &purge_data);
+
+ if ((purge_data.total_size > purge_data.max_size) && (purge_data.max_size >= 0)) {
+ GList *scan;
+ files = g_list_sort (files, (GCompareFunc) sort_file_mtime);
+ for (scan = files; scan && (purge_data.total_size > purge_data.max_size); scan = scan->next) {
+ ThumbData *info = scan->data;
+ g_unlink (info->path);
+ purge_data.total_size -= info->size;
+ }
+ }
+
+ g_list_foreach (files, (GFunc) thumb_data_free, NULL);
+ g_list_free (files);
+}
+
+
+static gboolean
+do_cleanup (GsdHousekeepingManager *manager)
+{
+ purge_thumbnail_cache ();
+ return TRUE;
+}
+
+
+static gboolean
+do_cleanup_once (GsdHousekeepingManager *manager)
+{
+ do_cleanup (manager);
+ manager->priv->short_term_cb = 0;
+ return FALSE;
+}
+
+
+static void
+do_cleanup_soon (GsdHousekeepingManager *manager)
+{
+ if (manager->priv->short_term_cb == 0) {
+ g_debug ("housekeeping: will tidy up in 2 minutes");
+ manager->priv->short_term_cb = g_timeout_add_seconds (INTERVAL_TWO_MINUTES,
+ (GSourceFunc) do_cleanup_once,
+ manager);
+ }
+}
+
+
+static void
+bindings_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdHousekeepingManager *manager)
+{
+ do_cleanup_soon (manager);
+}
+
+
+static guint
+register_config_callback (GsdHousekeepingManager *manager,
+ const char *path,
+ MateConfClientNotifyFunc func)
+{
+ MateConfClient *client = mateconf_client_get_default ();
+ guint notify;
+
+ mateconf_client_add_dir (client, path, MATECONF_CLIENT_PRELOAD_NONE, NULL);
+ notify = mateconf_client_notify_add (client, path, func, manager, NULL, NULL);
+
+ g_object_unref (client);
+
+ return notify;
+}
+
+
+gboolean
+gsd_housekeeping_manager_start (GsdHousekeepingManager *manager,
+ GError **error)
+{
+ g_debug ("Starting housekeeping manager");
+ mate_settings_profile_start (NULL);
+
+ gsd_ldsm_setup (FALSE);
+
+ manager->priv->mateconf_notify = register_config_callback (manager,
+ MATECONF_THUMB_BINDING_DIR,
+ (MateConfClientNotifyFunc) bindings_callback);
+
+ /* Clean once, a few minutes after start-up */
+ do_cleanup_soon (manager);
+
+ /* Clean periodically, on a daily basis. */
+ manager->priv->long_term_cb = g_timeout_add_seconds (INTERVAL_ONCE_A_DAY,
+ (GSourceFunc) do_cleanup,
+ manager);
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+
+void
+gsd_housekeeping_manager_stop (GsdHousekeepingManager *manager)
+{
+ GsdHousekeepingManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping housekeeping manager");
+
+ if (p->mateconf_notify != 0) {
+ MateConfClient *client = mateconf_client_get_default ();
+
+ mateconf_client_remove_dir (client, MATECONF_THUMB_BINDING_DIR, NULL);
+ mateconf_client_notify_remove (client, p->mateconf_notify);
+
+ g_object_unref (client);
+ p->mateconf_notify = 0;
+ }
+
+ if (p->short_term_cb) {
+ g_source_remove (p->short_term_cb);
+ p->short_term_cb = 0;
+ }
+
+ if (p->long_term_cb) {
+ g_source_remove (p->long_term_cb);
+ p->long_term_cb = 0;
+
+ /* Do a clean-up on shutdown if and only if the size or age
+ limits have been set to paranoid levels (zero) */
+ if ((get_mateconf_int_with_default (MATECONF_THUMB_AGE, DEFAULT_MAX_AGE_IN_DAYS) == 0) ||
+ (get_mateconf_int_with_default (MATECONF_THUMB_SIZE, DEFAULT_MAX_SIZE_IN_MB) == 0)) {
+ do_cleanup (manager);
+ }
+ }
+
+ gsd_ldsm_clean ();
+}
+
+
+static void
+gsd_housekeeping_manager_class_init (GsdHousekeepingManagerClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (GsdHousekeepingManagerPrivate));
+}
+
+
+static void
+gsd_housekeeping_manager_init (GsdHousekeepingManager *manager)
+{
+ manager->priv = GSD_HOUSEKEEPING_MANAGER_GET_PRIVATE (manager);
+}
+
+
+GsdHousekeepingManager *
+gsd_housekeeping_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_HOUSEKEEPING_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_HOUSEKEEPING_MANAGER (manager_object);
+}
diff --git a/plugins/housekeeping/gsd-housekeeping-manager.h b/plugins/housekeeping/gsd-housekeeping-manager.h
new file mode 100644
index 0000000..3cba840
--- /dev/null
+++ b/plugins/housekeeping/gsd-housekeeping-manager.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Michael J. Chudobiak <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_HOUSEKEEPING_MANAGER_H
+#define __GSD_HOUSEKEEPING_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_HOUSEKEEPING_MANAGER (gsd_housekeeping_manager_get_type ())
+#define GSD_HOUSEKEEPING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManager))
+#define GSD_HOUSEKEEPING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerClass))
+#define GSD_IS_HOUSEKEEPING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_HOUSEKEEPING_MANAGER))
+#define GSD_IS_HOUSEKEEPING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_HOUSEKEEPING_MANAGER))
+#define GSD_HOUSEKEEPING_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerClass))
+
+typedef struct GsdHousekeepingManagerPrivate GsdHousekeepingManagerPrivate;
+
+typedef struct {
+ GObject parent;
+ GsdHousekeepingManagerPrivate *priv;
+} GsdHousekeepingManager;
+
+typedef struct {
+ GObjectClass parent_class;
+} GsdHousekeepingManagerClass;
+
+GType gsd_housekeeping_manager_get_type (void);
+
+GsdHousekeepingManager * gsd_housekeeping_manager_new (void);
+gboolean gsd_housekeeping_manager_start (GsdHousekeepingManager *manager,
+ GError **error);
+void gsd_housekeeping_manager_stop (GsdHousekeepingManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_HOUSEKEEPING_MANAGER_H */
diff --git a/plugins/housekeeping/gsd-housekeeping-plugin.c b/plugins/housekeeping/gsd-housekeeping-plugin.c
new file mode 100644
index 0000000..1bbddb0
--- /dev/null
+++ b/plugins/housekeeping/gsd-housekeeping-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Michael J. Chudobiak <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-housekeeping-plugin.h"
+#include "gsd-housekeeping-manager.h"
+
+struct GsdHousekeepingPluginPrivate {
+ GsdHousekeepingManager *manager;
+};
+
+#define GSD_HOUSEKEEPING_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_HOUSEKEEPING_PLUGIN, GsdHousekeepingPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdHousekeepingPlugin, gsd_housekeeping_plugin)
+
+static void
+gsd_housekeeping_plugin_init (GsdHousekeepingPlugin *plugin)
+{
+ plugin->priv = GSD_HOUSEKEEPING_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdHousekeepingPlugin initializing");
+
+ plugin->priv->manager = gsd_housekeeping_manager_new ();
+}
+
+static void
+gsd_housekeeping_plugin_finalize (GObject *object)
+{
+ GsdHousekeepingPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_HOUSEKEEPING_PLUGIN (object));
+
+ g_debug ("GsdHousekeepingPlugin finalizing");
+
+ plugin = GSD_HOUSEKEEPING_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_housekeeping_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating housekeeping plugin");
+
+ error = NULL;
+ res = gsd_housekeeping_manager_start (GSD_HOUSEKEEPING_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start housekeeping manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating housekeeping plugin");
+ gsd_housekeeping_manager_stop (GSD_HOUSEKEEPING_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_housekeeping_plugin_class_init (GsdHousekeepingPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_housekeeping_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdHousekeepingPluginPrivate));
+}
diff --git a/plugins/housekeeping/gsd-housekeeping-plugin.h b/plugins/housekeeping/gsd-housekeeping-plugin.h
new file mode 100644
index 0000000..daca16b
--- /dev/null
+++ b/plugins/housekeeping/gsd-housekeeping-plugin.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Michael J. Chudobiak <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_HOUSEKEEPING_PLUGIN_H__
+#define __GSD_HOUSEKEEPING_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_HOUSEKEEPING_PLUGIN (gsd_housekeeping_plugin_get_type ())
+#define GSD_HOUSEKEEPING_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_HOUSEKEEPING_PLUGIN, GsdHousekeepingPlugin))
+#define GSD_HOUSEKEEPING_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_HOUSEKEEPING_PLUGIN, GsdHousekeepingPluginClass))
+#define GSD_IS_HOUSEKEEPING_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_HOUSEKEEPING_PLUGIN))
+#define GSD_IS_HOUSEKEEPING_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_HOUSEKEEPING_PLUGIN))
+#define GSD_HOUSEKEEPING_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_HOUSEKEEPING_PLUGIN, GsdHousekeepingPluginClass))
+
+typedef struct GsdHousekeepingPluginPrivate GsdHousekeepingPluginPrivate;
+
+typedef struct {
+ MateSettingsPlugin parent;
+ GsdHousekeepingPluginPrivate *priv;
+} GsdHousekeepingPlugin;
+
+typedef struct {
+ MateSettingsPluginClass parent_class;
+} GsdHousekeepingPluginClass;
+
+GType gsd_housekeeping_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_HOUSEKEEPING_PLUGIN_H__ */
diff --git a/plugins/housekeeping/gsd-ldsm-dialog.c b/plugins/housekeeping/gsd-ldsm-dialog.c
new file mode 100644
index 0000000..695db91
--- /dev/null
+++ b/plugins/housekeeping/gsd-ldsm-dialog.c
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * gsd-ldsm-dialog.c
+ * Copyright (C) Chris Coulson 2009 <[email protected]>
+ *
+ * gsd-ldsm-dialog.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gsd-ldsm-dialog.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <mateconf/mateconf-client.h>
+
+#include "gsd-ldsm-dialog.h"
+
+#define MATECONF_CLIENT_IGNORE_PATHS "/apps/mate_settings_daemon/plugins/housekeeping/ignore_paths"
+
+enum
+{
+ PROP_0,
+ PROP_OTHER_USABLE_PARTITIONS,
+ PROP_OTHER_PARTITIONS,
+ PROP_HAS_TRASH,
+ PROP_SPACE_REMAINING,
+ PROP_PARTITION_NAME,
+ PROP_MOUNT_PATH
+};
+
+struct GsdLdsmDialogPrivate
+{
+ GtkWidget *primary_label;
+ GtkWidget *secondary_label;
+ GtkWidget *ignore_check_button;
+ gboolean other_usable_partitions;
+ gboolean other_partitions;
+ gboolean has_trash;
+ gint64 space_remaining;
+ gchar *partition_name;
+ gchar *mount_path;
+};
+
+#define GSD_LDSM_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogPrivate))
+
+static void gsd_ldsm_dialog_class_init (GsdLdsmDialogClass *klass);
+static void gsd_ldsm_dialog_init (GsdLdsmDialog *dialog);
+
+G_DEFINE_TYPE (GsdLdsmDialog, gsd_ldsm_dialog, GTK_TYPE_DIALOG);
+
+static const gchar*
+gsd_ldsm_dialog_get_checkbutton_text (GsdLdsmDialog *dialog)
+{
+ g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL);
+
+ if (dialog->priv->other_partitions)
+ return _("Don't show any warnings again for this file system");
+ else
+ return _("Don't show any warnings again");
+}
+
+static gchar*
+gsd_ldsm_dialog_get_primary_text (GsdLdsmDialog *dialog)
+{
+ gchar *primary_text, *free_space;
+
+ g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL);
+
+ free_space = g_format_size_for_display (dialog->priv->space_remaining);
+
+ if (dialog->priv->other_partitions) {
+ primary_text = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining."),
+ dialog->priv->partition_name, free_space);
+ } else {
+ primary_text = g_strdup_printf (_("This computer has only %s disk space remaining."),
+ free_space);
+ }
+
+ g_free (free_space);
+
+ return primary_text;
+}
+
+static const gchar*
+gsd_ldsm_dialog_get_secondary_text (GsdLdsmDialog *dialog)
+{
+ g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL);
+
+ if (dialog->priv->other_usable_partitions) {
+ if (dialog->priv->has_trash) {
+ return _("You can free up disk space by emptying the Trash, removing " \
+ "unused programs or files, or moving files to another disk or partition.");
+ } else {
+ return _("You can free up disk space by removing unused programs or files, " \
+ "or by moving files to another disk or partition.");
+ }
+ } else {
+ if (dialog->priv->has_trash) {
+ return _("You can free up disk space by emptying the Trash, removing unused " \
+ "programs or files, or moving files to an external disk.");
+ } else {
+ return _("You can free up disk space by removing unused programs or files, " \
+ "or by moving files to an external disk.");
+ }
+ }
+}
+
+static gint
+ignore_path_compare (gconstpointer a,
+ gconstpointer b)
+{
+ return g_strcmp0 ((const gchar *)a, (const gchar *)b);
+}
+
+static gboolean
+update_ignore_paths (GSList **ignore_paths,
+ const gchar *mount_path,
+ gboolean ignore)
+{
+ GSList *found;
+ gchar *path_to_remove;
+
+ found = g_slist_find_custom (*ignore_paths, mount_path, (GCompareFunc) ignore_path_compare);
+
+ if (ignore && (found == NULL)) {
+ *ignore_paths = g_slist_prepend (*ignore_paths, g_strdup (mount_path));
+ return TRUE;
+ }
+
+ if (!ignore && (found != NULL)) {
+ path_to_remove = found->data;
+ *ignore_paths = g_slist_remove (*ignore_paths, path_to_remove);
+ g_free (path_to_remove);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ignore_check_button_toggled_cb (GtkToggleButton *button,
+ gpointer user_data)
+{
+ GsdLdsmDialog *dialog = (GsdLdsmDialog *)user_data;
+ MateConfClient *client;
+ GSList *ignore_paths;
+ GError *error = NULL;
+ gboolean ignore, ret, updated;
+
+ client = mateconf_client_get_default ();
+ if (client != NULL) {
+ ignore_paths = mateconf_client_get_list (client,
+ MATECONF_CLIENT_IGNORE_PATHS,
+ MATECONF_VALUE_STRING, &error);
+ if (error != NULL) {
+ g_warning ("Cannot change ignore preference - failed to read existing configuration: %s",
+ error->message ? error->message : "Unkown error");
+ g_clear_error (&error);
+ return;
+ } else {
+ ignore = gtk_toggle_button_get_active (button);
+ updated = update_ignore_paths (&ignore_paths, dialog->priv->mount_path, ignore);
+ }
+
+ if (!updated)
+ return;
+
+ ret = mateconf_client_set_list (client,
+ MATECONF_CLIENT_IGNORE_PATHS,
+ MATECONF_VALUE_STRING,
+ ignore_paths, &error);
+ if (!ret || error != NULL) {
+ g_warning ("Cannot change ignore preference - failed to commit changes: %s",
+ error->message ? error->message : "Unkown error");
+ g_clear_error (&error);
+ }
+
+ g_slist_foreach (ignore_paths, (GFunc) g_free, NULL);
+ g_slist_free (ignore_paths);
+ g_object_unref (client);
+ } else {
+ g_warning ("Cannot change ignore preference - failed to get MateConfClient");
+ }
+}
+
+static void
+gsd_ldsm_dialog_init (GsdLdsmDialog *dialog)
+{
+ GtkWidget *main_vbox, *text_vbox, *hbox;
+ GtkWidget *image;
+
+ dialog->priv = GSD_LDSM_DIALOG_GET_PRIVATE (dialog);
+
+ main_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ /* Set up all the window stuff here */
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Low Disk Space"));
+ gtk_window_set_icon_name (GTK_WINDOW (dialog),
+ GTK_STOCK_DIALOG_WARNING);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+ gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_focus_on_map (GTK_WINDOW (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ /* We don't want a separator - they're really ugly */
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+ /* Create the image */
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+
+ /* Create the labels */
+ dialog->priv->primary_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (dialog->priv->primary_label), TRUE);
+ gtk_label_set_single_line_mode (GTK_LABEL (dialog->priv->primary_label), FALSE);
+ gtk_misc_set_alignment (GTK_MISC (dialog->priv->primary_label), 0.0, 0.0);
+
+ dialog->priv->secondary_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (dialog->priv->secondary_label), TRUE);
+ gtk_label_set_single_line_mode (GTK_LABEL (dialog->priv->secondary_label), FALSE);
+ gtk_misc_set_alignment (GTK_MISC (dialog->priv->secondary_label), 0.0, 0.0);
+
+ /* Create the check button to ignore future warnings */
+ dialog->priv->ignore_check_button = gtk_check_button_new ();
+ /* The button should be inactive if the dialog was just called.
+ * I suppose it could be possible for the user to manually edit the MateConf key between
+ * the mount being checked and the dialog appearing, but I don't think it matters
+ * too much */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->ignore_check_button), FALSE);
+ g_signal_connect (dialog->priv->ignore_check_button, "toggled",
+ G_CALLBACK (ignore_check_button_toggled_cb), dialog);
+
+ /* Now set up the dialog's GtkBox's' */
+ gtk_box_set_spacing (GTK_BOX (main_vbox), 14);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+
+ text_vbox = gtk_vbox_new (FALSE, 12);
+
+ gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->primary_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->secondary_label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->ignore_check_button, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), text_vbox, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
+
+ /* Set up the action area */
+ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), 6);
+ gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), 5);
+
+ gtk_widget_show_all (hbox);
+}
+
+static void
+gsd_ldsm_dialog_finalize (GObject *object)
+{
+ GsdLdsmDialog *self;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_LDSM_DIALOG (object));
+
+ self = GSD_LDSM_DIALOG (object);
+
+ if (self->priv->partition_name)
+ g_free (self->priv->partition_name);
+
+ if (self->priv->mount_path)
+ g_free (self->priv->mount_path);
+
+ G_OBJECT_CLASS (gsd_ldsm_dialog_parent_class)->finalize (object);
+}
+
+static void
+gsd_ldsm_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GsdLdsmDialog *self;
+
+ g_return_if_fail (GSD_IS_LDSM_DIALOG (object));
+
+ self = GSD_LDSM_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_OTHER_USABLE_PARTITIONS:
+ self->priv->other_usable_partitions = g_value_get_boolean (value);
+ break;
+ case PROP_OTHER_PARTITIONS:
+ self->priv->other_partitions = g_value_get_boolean (value);
+ break;
+ case PROP_HAS_TRASH:
+ self->priv->has_trash = g_value_get_boolean (value);
+ break;
+ case PROP_SPACE_REMAINING:
+ self->priv->space_remaining = g_value_get_int64 (value);
+ break;
+ case PROP_PARTITION_NAME:
+ self->priv->partition_name = g_value_dup_string (value);
+ break;
+ case PROP_MOUNT_PATH:
+ self->priv->mount_path = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_ldsm_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GsdLdsmDialog *self;
+
+ g_return_if_fail (GSD_IS_LDSM_DIALOG (object));
+
+ self = GSD_LDSM_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_OTHER_USABLE_PARTITIONS:
+ g_value_set_boolean (value, self->priv->other_usable_partitions);
+ break;
+ case PROP_OTHER_PARTITIONS:
+ g_value_set_boolean (value, self->priv->other_partitions);
+ break;
+ case PROP_HAS_TRASH:
+ g_value_set_boolean (value, self->priv->has_trash);
+ break;
+ case PROP_SPACE_REMAINING:
+ g_value_set_int64 (value, self->priv->space_remaining);
+ break;
+ case PROP_PARTITION_NAME:
+ g_value_set_string (value, self->priv->partition_name);
+ break;
+ case PROP_MOUNT_PATH:
+ g_value_set_string (value, self->priv->mount_path);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_ldsm_dialog_class_init (GsdLdsmDialogClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gsd_ldsm_dialog_finalize;
+ object_class->set_property = gsd_ldsm_dialog_set_property;
+ object_class->get_property = gsd_ldsm_dialog_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_OTHER_USABLE_PARTITIONS,
+ g_param_spec_boolean ("other-usable-partitions",
+ "other-usable-partitions",
+ "Set to TRUE if there are other usable partitions on the system",
+ FALSE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_OTHER_PARTITIONS,
+ g_param_spec_boolean ("other-partitions",
+ "other-partitions",
+ "Set to TRUE if there are other partitions on the system",
+ FALSE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_HAS_TRASH,
+ g_param_spec_boolean ("has-trash",
+ "has-trash",
+ "Set to TRUE if the partition has files in it's trash folder that can be deleted",
+ FALSE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_SPACE_REMAINING,
+ g_param_spec_int64 ("space-remaining",
+ "space-remaining",
+ "Specify how much space is remaining in bytes",
+ G_MININT64, G_MAXINT64, 0,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_PARTITION_NAME,
+ g_param_spec_string ("partition-name",
+ "partition-name",
+ "Specify the name of the partition",
+ "Unknown",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_MOUNT_PATH,
+ g_param_spec_string ("mount-path",
+ "mount-path",
+ "Specify the mount path for the partition",
+ "Unknown",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (klass, sizeof (GsdLdsmDialogPrivate));
+}
+
+GsdLdsmDialog*
+gsd_ldsm_dialog_new (gboolean other_usable_partitions,
+ gboolean other_partitions,
+ gboolean display_baobab,
+ gboolean display_empty_trash,
+ gint64 space_remaining,
+ const gchar *partition_name,
+ const gchar *mount_path)
+{
+ GsdLdsmDialog *dialog;
+ GtkWidget *button_empty_trash, *button_ignore, *button_analyze;
+ GtkWidget *empty_trash_image, *analyze_image, *ignore_image;
+ gchar *primary_text, *primary_text_markup;
+ const gchar *secondary_text, *checkbutton_text;
+
+ dialog = GSD_LDSM_DIALOG (g_object_new (GSD_TYPE_LDSM_DIALOG,
+ "other-usable-partitions", other_usable_partitions,
+ "other-partitions", other_partitions,
+ "has-trash", display_empty_trash,
+ "space-remaining", space_remaining,
+ "partition-name", partition_name,
+ "mount-path", mount_path,
+ NULL));
+
+ /* Add some buttons */
+ if (dialog->priv->has_trash) {
+ button_empty_trash = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("Empty Trash"),
+ GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH);
+ empty_trash_image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button_empty_trash), empty_trash_image);
+ }
+
+ if (display_baobab) {
+ button_analyze = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("Examine…"),
+ GSD_LDSM_DIALOG_RESPONSE_ANALYZE);
+ analyze_image = gtk_image_new_from_icon_name ("baobab", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button_analyze), analyze_image);
+ }
+
+ button_ignore = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("Ignore"),
+ GTK_RESPONSE_CANCEL);
+ ignore_image = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button_ignore), ignore_image);
+
+ gtk_widget_grab_default (button_ignore);
+
+ /* Set the label text */
+ primary_text = gsd_ldsm_dialog_get_primary_text (dialog);
+ primary_text_markup = g_markup_printf_escaped ("<big><b>%s</b></big>", primary_text);
+ gtk_label_set_markup (GTK_LABEL (dialog->priv->primary_label), primary_text_markup);
+
+ secondary_text = gsd_ldsm_dialog_get_secondary_text (dialog);
+ gtk_label_set_text (GTK_LABEL (dialog->priv->secondary_label), secondary_text);
+
+ checkbutton_text = gsd_ldsm_dialog_get_checkbutton_text (dialog);
+ gtk_button_set_label (GTK_BUTTON (dialog->priv->ignore_check_button), checkbutton_text);
+
+ g_free (primary_text);
+ g_free (primary_text_markup);
+
+ return dialog;
+}
diff --git a/plugins/housekeeping/gsd-ldsm-dialog.h b/plugins/housekeeping/gsd-ldsm-dialog.h
new file mode 100644
index 0000000..81e2f1b
--- /dev/null
+++ b/plugins/housekeeping/gsd-ldsm-dialog.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * gsd-ldsm-dialog.c
+ * Copyright (C) Chris Coulson 2009 <[email protected]>
+ *
+ * gsd-ldsm-dialog.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gsd-ldsm-dialog.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GSD_LDSM_DIALOG_H_
+#define _GSD_LDSM_DIALOG_H_
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_LDSM_DIALOG (gsd_ldsm_dialog_get_type ())
+#define GSD_LDSM_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialog))
+#define GSD_LDSM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogClass))
+#define GSD_IS_LDSM_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_LDSM_DIALOG))
+#define GSD_IS_LDSM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_LDSM_DIALOG))
+#define GSD_LDSM_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogClass))
+
+enum
+{
+ GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH = -20,
+ GSD_LDSM_DIALOG_RESPONSE_ANALYZE = -21
+};
+
+typedef struct GsdLdsmDialogPrivate GsdLdsmDialogPrivate;
+typedef struct _GsdLdsmDialogClass GsdLdsmDialogClass;
+typedef struct _GsdLdsmDialog GsdLdsmDialog;
+
+struct _GsdLdsmDialogClass
+{
+ GtkDialogClass parent_class;
+};
+
+struct _GsdLdsmDialog
+{
+ GtkDialog parent_instance;
+ GsdLdsmDialogPrivate *priv;
+};
+
+GType gsd_ldsm_dialog_get_type (void) G_GNUC_CONST;
+
+GsdLdsmDialog * gsd_ldsm_dialog_new (gboolean other_usable_partitions,
+ gboolean other_partitions,
+ gboolean display_baobab,
+ gboolean display_empty_trash,
+ gint64 space_remaining,
+ const gchar *partition_name,
+ const gchar *mount_path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GSD_LDSM_DIALOG_H_ */
diff --git a/plugins/housekeeping/gsd-ldsm-trash-empty.c b/plugins/housekeeping/gsd-ldsm-trash-empty.c
new file mode 100644
index 0000000..d4ea183
--- /dev/null
+++ b/plugins/housekeeping/gsd-ldsm-trash-empty.c
@@ -0,0 +1,398 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * gsd-ldsm-trash-empty.c
+ * Copyright (C) Chris Coulson 2009 <[email protected]>
+ * (C) Ryan Lortie 2008
+ *
+ * gsd-ldsm-trash-empty.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gsd-ldsm-trash-empty.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <mateconf/mateconf-client.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gsd-ldsm-trash-empty.h"
+
+#define CAJA_CONFIRM_TRASH_KEY "/apps/caja/preferences/confirm_trash"
+
+/* Some of this code has been borrowed from the trash-applet, courtesy of Ryan Lortie */
+
+static GtkWidget *trash_empty_confirm_dialog = NULL;
+static GtkWidget *trash_empty_dialog = NULL;
+static GtkWidget *location_label;
+static GtkWidget *file_label;
+static GtkWidget *progressbar;
+
+static gsize trash_empty_total_files;
+static gboolean trash_empty_update_pending = FALSE;
+static GFile *trash_empty_current_file = NULL;
+static gsize trash_empty_deleted_files;
+static GTimer *timer = NULL;
+static gboolean trash_empty_actually_deleting;
+
+static gboolean
+trash_empty_done (gpointer data)
+{
+ gtk_widget_destroy (trash_empty_dialog);
+ trash_empty_dialog = NULL;
+ if (timer) {
+ g_timer_destroy (timer);
+ timer = NULL;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+trash_empty_update_dialog (gpointer user_data)
+{
+ gsize deleted, total;
+ GFile *file;
+ gboolean actually_deleting;
+
+ g_assert (trash_empty_update_pending);
+
+ deleted = trash_empty_deleted_files;
+ total = trash_empty_total_files;
+ file = trash_empty_current_file;
+ actually_deleting = trash_empty_actually_deleting;
+
+ /* maybe the done() got processed first. */
+ if (!trash_empty_dialog)
+ goto out;
+
+ if (!actually_deleting) {
+ /* If we havent finished counting yet, then pulse the progressbar every 100ms.
+ * This stops the user from thinking the dialog has frozen if there are
+ * a lot of files to delete. We don't pulse it every time we are called from the
+ * worker thread, otherwise it moves to fast and looks hideous
+ */
+ if (timer) {
+ if (g_timer_elapsed (timer, NULL) > 0.1) {
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (progressbar));
+ g_timer_start (timer);
+ }
+ } else {
+ timer = g_timer_new ();
+ g_timer_start (timer);
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (progressbar));
+ }
+ } else {
+ gchar *text;
+ gchar *tmp;
+ gchar *markup;
+ GFile *parent;
+
+ text = g_strdup_printf (_("Removing item %lu of %lu"),
+ deleted, total);
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar), text);
+
+ g_free (text);
+
+ if (deleted > total)
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progressbar), 1.0);
+ else
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progressbar),
+ (gdouble) deleted / (gdouble) total);
+
+ parent = g_file_get_parent (file);
+ text = g_file_get_uri (parent);
+ g_object_unref (parent);
+
+ gtk_label_set_text (GTK_LABEL (location_label), text);
+ g_free (text);
+
+ tmp = g_file_get_basename (file);
+ text = g_markup_printf_escaped (_("Removing: %s"), tmp);
+ markup = g_strdup_printf ("<i>%s</i>", text);
+ gtk_label_set_markup (GTK_LABEL (file_label), text);
+ g_free (markup);
+ g_free (text);
+ g_free (tmp);
+
+ /* unhide the labels */
+ gtk_widget_show_all (GTK_WIDGET (trash_empty_dialog));
+ }
+
+out:
+ trash_empty_current_file = NULL;
+ g_object_unref (file);
+
+ trash_empty_update_pending = FALSE;
+
+ return FALSE;
+}
+
+/* Worker thread begin */
+
+static void
+trash_empty_maybe_schedule_update (GIOSchedulerJob *job,
+ GFile *file,
+ gsize deleted,
+ gboolean actually_deleting)
+{
+ if (!trash_empty_update_pending) {
+ g_assert (trash_empty_current_file == NULL);
+
+ trash_empty_current_file = g_object_ref (file);
+ trash_empty_deleted_files = deleted;
+ trash_empty_actually_deleting = actually_deleting;
+
+ trash_empty_update_pending = TRUE;
+ g_io_scheduler_job_send_to_mainloop_async (job,
+ trash_empty_update_dialog,
+ NULL, NULL);
+ }
+}
+
+static void
+trash_empty_delete_contents (GIOSchedulerJob *job,
+ GCancellable *cancellable,
+ GFile *file,
+ gboolean actually_delete,
+ gsize *deleted)
+{
+ GFileEnumerator *enumerator;
+ GFileInfo *info;
+ GFile *child;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ enumerator = g_file_enumerate_children (file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, NULL);
+
+ if (enumerator) {
+ while ((info = g_file_enumerator_next_file (enumerator,
+ cancellable, NULL)) != NULL) {
+ child = g_file_get_child (file, g_file_info_get_name (info));
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ trash_empty_delete_contents (job, cancellable, child,
+ actually_delete, deleted);
+
+ trash_empty_maybe_schedule_update (job, child, *deleted, actually_delete);
+ if (actually_delete)
+ g_file_delete (child, cancellable, NULL);
+
+ (*deleted)++;
+
+ g_object_unref (child);
+ g_object_unref (info);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+ }
+
+ g_object_unref (enumerator);
+ }
+}
+
+static gboolean
+trash_empty_job (GIOSchedulerJob *job,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ gsize deleted;
+ GFile *trash;
+
+ trash = g_file_new_for_uri ("trash:///");
+
+ /* first do a dry run to count the number of files */
+ deleted = 0;
+ trash_empty_delete_contents (job, cancellable, trash, FALSE, &deleted);
+ trash_empty_total_files = deleted;
+
+ /* now do the real thing */
+ deleted = 0;
+ trash_empty_delete_contents (job, cancellable, trash, TRUE, &deleted);
+
+ /* done */
+ g_object_unref (trash);
+ g_io_scheduler_job_send_to_mainloop_async (job,
+ trash_empty_done,
+ NULL, NULL);
+
+ return FALSE;
+}
+
+/* Worker thread end */
+
+static void
+trash_empty_start ()
+{
+ GtkWidget *vbox1, *vbox2, *hbox;
+ GtkWidget *label1, *label3;
+ gchar *markup;
+ GCancellable *cancellable;
+
+ trash_empty_dialog = gtk_dialog_new ();
+ gtk_window_set_default_size (GTK_WINDOW (trash_empty_dialog), 400, -1);
+ gtk_window_set_icon_name (GTK_WINDOW (trash_empty_dialog), "user-trash");
+ gtk_window_set_title (GTK_WINDOW (trash_empty_dialog),
+ _("Emptying the trash"));
+
+ vbox1 = gtk_vbox_new (FALSE, 12);
+ vbox2 = gtk_vbox_new (FALSE, 0);
+ hbox = gtk_hbox_new (FALSE, 0);
+
+ label1 = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (label1), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label1), 0.0, 0.5);
+
+ label3 = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (label3), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label3), 0.0, 0.5);
+ gtk_widget_hide (label3);
+
+ location_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (location_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (location_label), 0.0, 0.5);
+
+ file_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (file_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (file_label), 0.0, 0.5);
+
+ progressbar = gtk_progress_bar_new ();
+ gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (progressbar), 0.1);
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar), _("Preparing to empty trash…"));
+
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (trash_empty_dialog))), vbox1, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox1), label1, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label3, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), location_label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox1), hbox, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox2), progressbar, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox2), file_label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0);
+
+ gtk_widget_show (label1);
+ gtk_widget_show (vbox1);
+ gtk_widget_show_all (vbox2);
+ gtk_widget_show (hbox);
+ gtk_widget_show (location_label);
+
+ gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (trash_empty_dialog))), 6);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox1), 6);
+
+ gtk_dialog_add_button (GTK_DIALOG (trash_empty_dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+
+ markup = g_markup_printf_escaped ("<big><b>%s</b></big>", _("Emptying the trash"));
+ gtk_label_set_markup (GTK_LABEL (label1), markup);
+ /* Translators: "Emptying trash from <device>" */
+ gtk_label_set_text (GTK_LABEL (label3), _("From: "));
+
+ cancellable = g_cancellable_new ();
+ g_signal_connect_object (trash_empty_dialog, "response",
+ G_CALLBACK (g_cancellable_cancel),
+ cancellable, G_CONNECT_SWAPPED);
+ g_io_scheduler_push_job (trash_empty_job, NULL, NULL, 0, cancellable);
+
+ gtk_widget_show (trash_empty_dialog);
+
+ g_free (markup);
+ g_object_unref (cancellable);
+}
+
+static void
+trash_empty_confirmation_response (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ if (response_id == GTK_RESPONSE_YES)
+ trash_empty_start ();
+
+ gtk_object_destroy (GTK_OBJECT (dialog));
+ trash_empty_confirm_dialog = NULL;
+}
+
+static gboolean
+trash_empty_require_confirmation ()
+{
+ MateConfClient *client;
+ gboolean require_confirmation = TRUE;
+ GError *error = NULL;
+
+ client = mateconf_client_get_default ();
+ if (client) {
+ require_confirmation = mateconf_client_get_bool (client, CAJA_CONFIRM_TRASH_KEY, &error);
+ if (error) {
+ g_warning ("Failed to read confirm_trash key from MateConf: %s", error->message ? error->message : "Unknown error");
+ /* It's safest to assume that confirmation is required here */
+ require_confirmation = TRUE;
+ g_error_free (error);
+ }
+ g_object_unref (client);
+ }
+
+ return require_confirmation;
+}
+
+static void
+trash_empty_show_confirmation_dialog ()
+{
+ GtkWidget *button;
+
+ if (!trash_empty_require_confirmation ()) {
+ trash_empty_start ();
+ return;
+ }
+
+ trash_empty_confirm_dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("Empty all of the items from the trash?"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (trash_empty_confirm_dialog),
+ _("If you choose to empty the trash, all items in "
+ "it will be permanently lost. Please note that "
+ "you can also delete them separately."));
+
+ gtk_dialog_add_button (GTK_DIALOG (trash_empty_confirm_dialog), GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+
+ button = gtk_button_new_with_mnemonic (_("_Empty Trash"));
+ gtk_widget_show (button);
+ gtk_widget_set_can_default (button, TRUE);
+
+ gtk_dialog_add_action_widget (GTK_DIALOG (trash_empty_confirm_dialog),
+ button, GTK_RESPONSE_YES);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (trash_empty_confirm_dialog),
+ GTK_RESPONSE_YES);
+
+ gtk_window_set_icon_name (GTK_WINDOW (trash_empty_confirm_dialog),
+ "user-trash");
+
+ gtk_widget_show (trash_empty_confirm_dialog);
+
+ g_signal_connect (trash_empty_confirm_dialog, "response",
+ G_CALLBACK (trash_empty_confirmation_response), NULL);
+}
+
+void
+gsd_ldsm_trash_empty ()
+{
+ if (trash_empty_confirm_dialog)
+ gtk_window_present (GTK_WINDOW (trash_empty_confirm_dialog));
+ else if (trash_empty_dialog)
+ gtk_window_present (GTK_WINDOW (trash_empty_dialog));
+ else
+ trash_empty_show_confirmation_dialog ();
+}
diff --git a/plugins/housekeeping/gsd-ldsm-trash-empty.h b/plugins/housekeeping/gsd-ldsm-trash-empty.h
new file mode 100644
index 0000000..4d46a5b
--- /dev/null
+++ b/plugins/housekeeping/gsd-ldsm-trash-empty.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * gsd-ldsm-trash-empty.h
+ * Copyright (C) Chris Coulson 2009 <[email protected]>
+ *
+ * gsd-ldsm-trash-empty.h is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gsd-ldsm-trash-empty.h is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _gsd_ldsm_trash_empty_h_
+#define _gsd_ldsm_trash_empty_h_
+
+#include <gtk/gtk.h>
+
+void gsd_ldsm_trash_empty ();
+
+#endif /* _gsd_ldsm_trash_empty_h_ */
diff --git a/plugins/housekeeping/housekeeping.mate-settings-plugin.in b/plugins/housekeeping/housekeeping.mate-settings-plugin.in
new file mode 100644
index 0000000..d10c36c
--- /dev/null
+++ b/plugins/housekeeping/housekeeping.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=housekeeping
+IAge=0
+_Name=Housekeeping
+_Description=Automatically prunes thumbnail caches and other transient files, and warns about low disk space
+Authors=Michael J. Chudobiak
+Copyright=Copyright © 2008 Michael J. Chudobiak
+Website=
diff --git a/plugins/keybindings/Makefile.am b/plugins/keybindings/Makefile.am
new file mode 100644
index 0000000..c4fe7b2
--- /dev/null
+++ b/plugins/keybindings/Makefile.am
@@ -0,0 +1,51 @@
+NULL =
+
+plugin_LTLIBRARIES = \
+ libkeybindings.la \
+ $(NULL)
+
+libkeybindings_la_SOURCES = \
+ gsd-keybindings-plugin.h \
+ gsd-keybindings-plugin.c \
+ gsd-keybindings-manager.h \
+ gsd-keybindings-manager.c \
+ $(NULL)
+
+libkeybindings_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libkeybindings_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libkeybindings_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libkeybindings_la_LIBADD = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ keybindings.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/keybindings/Makefile.in b/plugins/keybindings/Makefile.in
new file mode 100644
index 0000000..698ff16
--- /dev/null
+++ b/plugins/keybindings/Makefile.in
@@ -0,0 +1,682 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/keybindings
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libkeybindings_la_DEPENDENCIES = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libkeybindings_la_OBJECTS = \
+ libkeybindings_la-gsd-keybindings-plugin.lo \
+ libkeybindings_la-gsd-keybindings-manager.lo $(am__objects_1)
+libkeybindings_la_OBJECTS = $(am_libkeybindings_la_OBJECTS)
+libkeybindings_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libkeybindings_la_CFLAGS) $(CFLAGS) \
+ $(libkeybindings_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libkeybindings_la_SOURCES)
+DIST_SOURCES = $(libkeybindings_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+plugin_LTLIBRARIES = \
+ libkeybindings.la \
+ $(NULL)
+
+libkeybindings_la_SOURCES = \
+ gsd-keybindings-plugin.h \
+ gsd-keybindings-plugin.c \
+ gsd-keybindings-manager.h \
+ gsd-keybindings-manager.c \
+ $(NULL)
+
+libkeybindings_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libkeybindings_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libkeybindings_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libkeybindings_la_LIBADD = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ keybindings.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/keybindings/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/keybindings/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libkeybindings.la: $(libkeybindings_la_OBJECTS) $(libkeybindings_la_DEPENDENCIES)
+ $(libkeybindings_la_LINK) -rpath $(plugindir) $(libkeybindings_la_OBJECTS) $(libkeybindings_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybindings_la-gsd-keybindings-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybindings_la-gsd-keybindings-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libkeybindings_la-gsd-keybindings-plugin.lo: gsd-keybindings-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeybindings_la_CPPFLAGS) $(CPPFLAGS) $(libkeybindings_la_CFLAGS) $(CFLAGS) -MT libkeybindings_la-gsd-keybindings-plugin.lo -MD -MP -MF $(DEPDIR)/libkeybindings_la-gsd-keybindings-plugin.Tpo -c -o libkeybindings_la-gsd-keybindings-plugin.lo `test -f 'gsd-keybindings-plugin.c' || echo '$(srcdir)/'`gsd-keybindings-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeybindings_la-gsd-keybindings-plugin.Tpo $(DEPDIR)/libkeybindings_la-gsd-keybindings-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-keybindings-plugin.c' object='libkeybindings_la-gsd-keybindings-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeybindings_la_CPPFLAGS) $(CPPFLAGS) $(libkeybindings_la_CFLAGS) $(CFLAGS) -c -o libkeybindings_la-gsd-keybindings-plugin.lo `test -f 'gsd-keybindings-plugin.c' || echo '$(srcdir)/'`gsd-keybindings-plugin.c
+
+libkeybindings_la-gsd-keybindings-manager.lo: gsd-keybindings-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeybindings_la_CPPFLAGS) $(CPPFLAGS) $(libkeybindings_la_CFLAGS) $(CFLAGS) -MT libkeybindings_la-gsd-keybindings-manager.lo -MD -MP -MF $(DEPDIR)/libkeybindings_la-gsd-keybindings-manager.Tpo -c -o libkeybindings_la-gsd-keybindings-manager.lo `test -f 'gsd-keybindings-manager.c' || echo '$(srcdir)/'`gsd-keybindings-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeybindings_la-gsd-keybindings-manager.Tpo $(DEPDIR)/libkeybindings_la-gsd-keybindings-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-keybindings-manager.c' object='libkeybindings_la-gsd-keybindings-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeybindings_la_CPPFLAGS) $(CPPFLAGS) $(libkeybindings_la_CFLAGS) $(CFLAGS) -c -o libkeybindings_la-gsd-keybindings-manager.lo `test -f 'gsd-keybindings-manager.c' || echo '$(srcdir)/'`gsd-keybindings-manager.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/keybindings/gsd-keybindings-manager.c b/plugins/keybindings/gsd-keybindings-manager.c
new file mode 100644
index 0000000..74014cc
--- /dev/null
+++ b/plugins/keybindings/gsd-keybindings-manager.c
@@ -0,0 +1,758 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <X11/keysym.h>
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-keybindings-manager.h"
+
+#include "gsd-keygrab.h"
+#include "eggaccelerators.h"
+
+#define MATECONF_BINDING_DIR "/desktop/mate/keybindings"
+#define ALLOWED_KEYS_KEY MATECONF_BINDING_DIR "/allowed_keys"
+
+#define GSD_KEYBINDINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBINDINGS_MANAGER, GsdKeybindingsManagerPrivate))
+
+typedef struct {
+ char *binding_str;
+ char *action;
+ char *mateconf_key;
+ Key key;
+ Key previous_key;
+} Binding;
+
+struct GsdKeybindingsManagerPrivate
+{
+ GSList *binding_list;
+ GSList *allowed_keys;
+ GSList *screens;
+ guint notify;
+};
+
+static void gsd_keybindings_manager_class_init (GsdKeybindingsManagerClass *klass);
+static void gsd_keybindings_manager_init (GsdKeybindingsManager *keybindings_manager);
+static void gsd_keybindings_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdKeybindingsManager, gsd_keybindings_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static GSList *
+get_screens_list (void)
+{
+ GdkDisplay *display = gdk_display_get_default();
+ int n_screens;
+ GSList *list = NULL;
+ int i;
+
+ n_screens = gdk_display_get_n_screens (display);
+
+ if (n_screens == 1) {
+ list = g_slist_append (list, gdk_screen_get_default ());
+ } else {
+ for (i = 0; i < n_screens; i++) {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (display, i);
+ if (screen != NULL) {
+ list = g_slist_prepend (list, screen);
+ }
+ }
+ list = g_slist_reverse (list);
+ }
+
+ return list;
+}
+
+static char *
+entry_get_string (MateConfEntry *entry)
+{
+ MateConfValue *value = mateconf_entry_get_value (entry);
+
+ if (value == NULL || value->type != MATECONF_VALUE_STRING) {
+ return NULL;
+ }
+
+ return g_strdup (mateconf_value_get_string (value));
+}
+
+static gboolean
+parse_binding (Binding *binding)
+{
+ gboolean success;
+
+ g_return_val_if_fail (binding != NULL, FALSE);
+
+ binding->key.keysym = 0;
+ binding->key.state = 0;
+ g_free (binding->key.keycodes);
+ binding->key.keycodes = NULL;
+
+ if (binding->binding_str == NULL ||
+ binding->binding_str[0] == '\0' ||
+ strcmp (binding->binding_str, "Disabled") == 0) {
+ return FALSE;
+ }
+
+ success = egg_accelerator_parse_virtual (binding->binding_str,
+ &binding->key.keysym,
+ &binding->key.keycodes,
+ &binding->key.state);
+
+ if (!success)
+ g_warning (_("Key binding (%s) is invalid"), binding->mateconf_key);
+
+ return success;
+}
+
+static gint
+compare_bindings (gconstpointer a,
+ gconstpointer b)
+{
+ Binding *key_a = (Binding *) a;
+ char *key_b = (char *) b;
+
+ return strcmp (key_b, key_a->mateconf_key);
+}
+
+static gboolean
+bindings_get_entry (GsdKeybindingsManager *manager,
+ MateConfClient *client,
+ const char *subdir)
+{
+ Binding *new_binding;
+ GSList *tmp_elem;
+ GSList *list;
+ GSList *li;
+ char *mateconf_key;
+ char *action = NULL;
+ char *key = NULL;
+
+ g_return_val_if_fail (subdir != NULL, FALSE);
+
+ mateconf_key = g_path_get_basename (subdir);
+
+ if (!mateconf_key) {
+ return FALSE;
+ }
+
+ /* Get entries for this binding */
+ list = mateconf_client_all_entries (client, subdir, NULL);
+
+ for (li = list; li != NULL; li = li->next) {
+ MateConfEntry *entry = li->data;
+ char *key_name = g_path_get_basename (mateconf_entry_get_key (entry));
+
+ if (key_name == NULL) {
+ /* ignore entry */
+ } else if (strcmp (key_name, "action") == 0) {
+ action = entry_get_string (entry);
+ } else if (strcmp (key_name, "binding") == 0) {
+ key = entry_get_string (entry);
+ }
+
+ g_free (key_name);
+ mateconf_entry_free (entry);
+ }
+
+ g_slist_free (list);
+
+ if (!action || !key) {
+ g_warning (_("Key binding (%s) is incomplete"), mateconf_key);
+ g_free (mateconf_key);
+ g_free (action);
+ g_free (key);
+ return FALSE;
+ }
+
+ tmp_elem = g_slist_find_custom (manager->priv->binding_list,
+ mateconf_key,
+ compare_bindings);
+
+ if (!tmp_elem) {
+ new_binding = g_new0 (Binding, 1);
+ } else {
+ new_binding = (Binding *) tmp_elem->data;
+ g_free (new_binding->binding_str);
+ g_free (new_binding->action);
+ g_free (new_binding->mateconf_key);
+
+ new_binding->previous_key.keysym = new_binding->key.keysym;
+ new_binding->previous_key.state = new_binding->key.state;
+ new_binding->previous_key.keycodes = new_binding->key.keycodes;
+ new_binding->key.keycodes = NULL;
+ }
+
+ new_binding->binding_str = key;
+ new_binding->action = action;
+ new_binding->mateconf_key = mateconf_key;
+
+ if (parse_binding (new_binding)) {
+ if (!tmp_elem)
+ manager->priv->binding_list = g_slist_prepend (manager->priv->binding_list, new_binding);
+ } else {
+ g_free (new_binding->binding_str);
+ g_free (new_binding->action);
+ g_free (new_binding->mateconf_key);
+ g_free (new_binding->previous_key.keycodes);
+ g_free (new_binding);
+
+ if (tmp_elem)
+ manager->priv->binding_list = g_slist_delete_link (manager->priv->binding_list, tmp_elem);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+same_keycode (const Key *key, const Key *other)
+{
+ if (key->keycodes != NULL && other->keycodes != NULL) {
+ guint *c;
+
+ for (c = key->keycodes; *c; ++c) {
+ if (key_uses_keycode (other, *c))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+same_key (const Key *key, const Key *other)
+{
+ if (key->state == other->state) {
+ if (key->keycodes != NULL && other->keycodes != NULL) {
+ guint *c1, *c2;
+
+ for (c1 = key->keycodes, c2 = other->keycodes;
+ *c1 || *c2; ++c1, ++c2) {
+ if (*c1 != *c2)
+ return FALSE;
+ }
+ } else if (key->keycodes != NULL || other->keycodes != NULL)
+ return FALSE;
+
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+key_already_used (GsdKeybindingsManager *manager,
+ Binding *binding)
+{
+ GSList *li;
+
+ for (li = manager->priv->binding_list; li != NULL; li = li->next) {
+ Binding *tmp_binding = (Binding*) li->data;
+
+ if (tmp_binding != binding &&
+ same_keycode (&tmp_binding->key, &binding->key) &&
+ tmp_binding->key.state == binding->key.state) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+binding_unregister_keys (GsdKeybindingsManager *manager)
+{
+ GSList *li;
+ gboolean need_flush = FALSE;
+
+ gdk_error_trap_push ();
+
+ for (li = manager->priv->binding_list; li != NULL; li = li->next) {
+ Binding *binding = (Binding *) li->data;
+
+ if (binding->key.keycodes) {
+ need_flush = TRUE;
+ grab_key_unsafe (&binding->key, FALSE, manager->priv->screens);
+ }
+ }
+
+ if (need_flush)
+ gdk_flush ();
+ gdk_error_trap_pop ();
+}
+
+static void
+binding_register_keys (GsdKeybindingsManager *manager)
+{
+ GSList *li;
+ gboolean need_flush = FALSE;
+
+ gdk_error_trap_push ();
+
+ /* Now check for changes and grab new key if not already used */
+ for (li = manager->priv->binding_list; li != NULL; li = li->next) {
+ Binding *binding = (Binding *) li->data;
+
+ if (manager->priv->allowed_keys != NULL &&
+ !g_slist_find_custom (manager->priv->allowed_keys,
+ binding->mateconf_key,
+ (GCompareFunc) g_strcmp0)) {
+ continue;
+ }
+
+ if (!same_key (&binding->previous_key, &binding->key)) {
+ /* Ungrab key if it changed and not clashing with previously set binding */
+ if (!key_already_used (manager, binding)) {
+ gint i;
+
+ need_flush = TRUE;
+ if (binding->previous_key.keycodes) {
+ grab_key_unsafe (&binding->previous_key, FALSE, manager->priv->screens);
+ }
+ grab_key_unsafe (&binding->key, TRUE, manager->priv->screens);
+
+ binding->previous_key.keysym = binding->key.keysym;
+ binding->previous_key.state = binding->key.state;
+ g_free (binding->previous_key.keycodes);
+ for (i = 0; binding->key.keycodes[i]; ++i);
+ binding->previous_key.keycodes = g_new0 (guint, i);
+ for (i = 0; binding->key.keycodes[i]; ++i)
+ binding->previous_key.keycodes[i] = binding->key.keycodes[i];
+ } else
+ g_warning ("Key binding (%s) is already in use", binding->binding_str);
+ }
+ }
+
+ if (need_flush)
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ g_warning ("Grab failed for some keys, another application may already have access the them.");
+}
+
+extern char **environ;
+
+static char *
+screen_exec_display_string (GdkScreen *screen)
+{
+ GString *str;
+ const char *old_display;
+ char *p;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ old_display = gdk_display_get_name (gdk_screen_get_display (screen));
+
+ str = g_string_new ("DISPLAY=");
+ g_string_append (str, old_display);
+
+ p = strrchr (str->str, '.');
+ if (p && p > strchr (str->str, ':')) {
+ g_string_truncate (str, p - str->str);
+ }
+
+ g_string_append_printf (str, ".%d", gdk_screen_get_number (screen));
+
+ return g_string_free (str, FALSE);
+}
+
+/**
+ * get_exec_environment:
+ *
+ * Description: Modifies the current program environment to
+ * ensure that $DISPLAY is set such that a launched application
+ * inheriting this environment would appear on screen.
+ *
+ * Returns: a newly-allocated %NULL-terminated array of strings or
+ * %NULL on error. Use g_strfreev() to free it.
+ *
+ * mainly ripped from egg_screen_exec_display_string in
+ * mate-panel/egg-screen-exec.c
+ **/
+static char **
+get_exec_environment (XEvent *xevent)
+{
+ char **retval = NULL;
+ int i;
+ int display_index = -1;
+ GdkScreen *screen = NULL;
+ GdkWindow *window = gdk_xid_table_lookup (xevent->xkey.root);
+
+ if (window) {
+ screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+ }
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ for (i = 0; environ [i]; i++) {
+ if (!strncmp (environ [i], "DISPLAY", 7)) {
+ display_index = i;
+ }
+ }
+
+ if (display_index == -1) {
+ display_index = i++;
+ }
+
+ retval = g_new (char *, i + 1);
+
+ for (i = 0; environ [i]; i++) {
+ if (i == display_index) {
+ retval [i] = screen_exec_display_string (screen);
+ } else {
+ retval [i] = g_strdup (environ [i]);
+ }
+ }
+
+ retval [i] = NULL;
+
+ return retval;
+}
+
+static GdkFilterReturn
+keybindings_filter (GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ GsdKeybindingsManager *manager)
+{
+ XEvent *xevent = (XEvent *) gdk_xevent;
+ GSList *li;
+
+ if (xevent->type != KeyPress) {
+ return GDK_FILTER_CONTINUE;
+ }
+
+ for (li = manager->priv->binding_list; li != NULL; li = li->next) {
+ Binding *binding = (Binding *) li->data;
+
+ if (match_key (&binding->key, xevent)) {
+ GError *error = NULL;
+ gboolean retval;
+ gchar **argv = NULL;
+ gchar **envp = NULL;
+
+ g_return_val_if_fail (binding->action != NULL, GDK_FILTER_CONTINUE);
+
+ if (!g_shell_parse_argv (binding->action,
+ NULL, &argv,
+ &error)) {
+ return GDK_FILTER_CONTINUE;
+ }
+
+ envp = get_exec_environment (xevent);
+
+ retval = g_spawn_async (NULL,
+ argv,
+ envp,
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ NULL,
+ &error);
+ g_strfreev (argv);
+ g_strfreev (envp);
+
+ if (!retval) {
+ GtkWidget *dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CLOSE,
+ _("Error while trying to run (%s)\n"\
+ "which is linked to the key (%s)"),
+ binding->action,
+ binding->binding_str);
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ gtk_widget_show (dialog);
+ }
+ return GDK_FILTER_REMOVE;
+ }
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+bindings_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdKeybindingsManager *manager)
+{
+ char** key_elems;
+ char* binding_entry;
+
+ if (strcmp (mateconf_entry_get_key (entry), ALLOWED_KEYS_KEY) == 0) {
+ g_slist_foreach (manager->priv->allowed_keys, (GFunc)g_free, NULL);
+ g_slist_free (manager->priv->allowed_keys);
+ manager->priv->allowed_keys = mateconf_client_get_list (client,
+ ALLOWED_KEYS_KEY,
+ MATECONF_VALUE_STRING,
+ NULL);
+ }
+ else {
+ /* ensure we get binding dir not a sub component */
+ key_elems = g_strsplit (mateconf_entry_get_key (entry), "/", 15);
+ binding_entry = g_strdup_printf ("/%s/%s/%s/%s",
+ key_elems[1],
+ key_elems[2],
+ key_elems[3],
+ key_elems[4]);
+ g_strfreev (key_elems);
+
+ bindings_get_entry (manager, client, binding_entry);
+ g_free (binding_entry);
+ }
+
+ binding_register_keys (manager);
+}
+
+static guint
+register_config_callback (GsdKeybindingsManager *manager,
+ MateConfClient *client,
+ const char *path,
+ MateConfClientNotifyFunc func)
+{
+ mateconf_client_add_dir (client, path, MATECONF_CLIENT_PRELOAD_RECURSIVE, NULL);
+ return mateconf_client_notify_add (client, path, func, manager, NULL, NULL);
+}
+
+gboolean
+gsd_keybindings_manager_start (GsdKeybindingsManager *manager,
+ GError **error)
+{
+ MateConfClient *client;
+ GSList *list;
+ GSList *li;
+ GdkDisplay *dpy;
+ GdkScreen *screen;
+ int screen_num;
+ int i;
+
+ g_debug ("Starting keybindings manager");
+ mate_settings_profile_start (NULL);
+
+ client = mateconf_client_get_default ();
+
+ manager->priv->notify = register_config_callback (manager,
+ client,
+ MATECONF_BINDING_DIR,
+ (MateConfClientNotifyFunc) bindings_callback);
+
+ manager->priv->allowed_keys = mateconf_client_get_list (client,
+ ALLOWED_KEYS_KEY,
+ MATECONF_VALUE_STRING,
+ NULL);
+
+ dpy = gdk_display_get_default ();
+ screen_num = gdk_display_get_n_screens (dpy);
+
+ for (i = 0; i < screen_num; i++) {
+ screen = gdk_display_get_screen (dpy, i);
+ gdk_window_add_filter (gdk_screen_get_root_window (screen),
+ (GdkFilterFunc) keybindings_filter,
+ manager);
+ }
+
+ list = mateconf_client_all_dirs (client, MATECONF_BINDING_DIR, NULL);
+ manager->priv->screens = get_screens_list ();
+
+ for (li = list; li != NULL; li = li->next) {
+ bindings_get_entry (manager, client, li->data);
+ g_free (li->data);
+ }
+
+ g_slist_free (list);
+ g_object_unref (client);
+
+ binding_register_keys (manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_keybindings_manager_stop (GsdKeybindingsManager *manager)
+{
+ GsdKeybindingsManagerPrivate *p = manager->priv;
+ GSList *l;
+
+ g_debug ("Stopping keybindings manager");
+
+ if (p->notify != 0) {
+ MateConfClient *client = mateconf_client_get_default ();
+ mateconf_client_remove_dir (client, MATECONF_BINDING_DIR, NULL);
+ mateconf_client_notify_remove (client, p->notify);
+ g_object_unref (client);
+ p->notify = 0;
+ }
+
+ for (l = p->screens; l; l = l->next) {
+ GdkScreen *screen = l->data;
+ gdk_window_remove_filter (gdk_screen_get_root_window (screen),
+ (GdkFilterFunc) keybindings_filter,
+ manager);
+ }
+
+ binding_unregister_keys (manager);
+
+ g_slist_free (p->screens);
+ p->screens = NULL;
+
+ for (l = p->binding_list; l; l = l->next) {
+ Binding *b = l->data;
+ g_free (b->binding_str);
+ g_free (b->action);
+ g_free (b->mateconf_key);
+ g_free (b->previous_key.keycodes);
+ g_free (b->key.keycodes);
+ g_free (b);
+ }
+ g_slist_free (p->binding_list);
+ p->binding_list = NULL;
+}
+
+static void
+gsd_keybindings_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdKeybindingsManager *self;
+
+ self = GSD_KEYBINDINGS_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_keybindings_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdKeybindingsManager *self;
+
+ self = GSD_KEYBINDINGS_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_keybindings_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdKeybindingsManager *keybindings_manager;
+ GsdKeybindingsManagerClass *klass;
+
+ klass = GSD_KEYBINDINGS_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_KEYBINDINGS_MANAGER));
+
+ keybindings_manager = GSD_KEYBINDINGS_MANAGER (G_OBJECT_CLASS (gsd_keybindings_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (keybindings_manager);
+}
+
+static void
+gsd_keybindings_manager_dispose (GObject *object)
+{
+ GsdKeybindingsManager *keybindings_manager;
+
+ keybindings_manager = GSD_KEYBINDINGS_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_keybindings_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_keybindings_manager_class_init (GsdKeybindingsManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_keybindings_manager_get_property;
+ object_class->set_property = gsd_keybindings_manager_set_property;
+ object_class->constructor = gsd_keybindings_manager_constructor;
+ object_class->dispose = gsd_keybindings_manager_dispose;
+ object_class->finalize = gsd_keybindings_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdKeybindingsManagerPrivate));
+}
+
+static void
+gsd_keybindings_manager_init (GsdKeybindingsManager *manager)
+{
+ manager->priv = GSD_KEYBINDINGS_MANAGER_GET_PRIVATE (manager);
+
+}
+
+static void
+gsd_keybindings_manager_finalize (GObject *object)
+{
+ GsdKeybindingsManager *keybindings_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_KEYBINDINGS_MANAGER (object));
+
+ keybindings_manager = GSD_KEYBINDINGS_MANAGER (object);
+
+ g_return_if_fail (keybindings_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_keybindings_manager_parent_class)->finalize (object);
+}
+
+GsdKeybindingsManager *
+gsd_keybindings_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_KEYBINDINGS_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_KEYBINDINGS_MANAGER (manager_object);
+}
diff --git a/plugins/keybindings/gsd-keybindings-manager.h b/plugins/keybindings/gsd-keybindings-manager.h
new file mode 100644
index 0000000..7de64d9
--- /dev/null
+++ b/plugins/keybindings/gsd-keybindings-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_KEYBINDINGS_MANAGER_H
+#define __GSD_KEYBINDINGS_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_KEYBINDINGS_MANAGER (gsd_keybindings_manager_get_type ())
+#define GSD_KEYBINDINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_KEYBINDINGS_MANAGER, GsdKeybindingsManager))
+#define GSD_KEYBINDINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_KEYBINDINGS_MANAGER, GsdKeybindingsManagerClass))
+#define GSD_IS_KEYBINDINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_KEYBINDINGS_MANAGER))
+#define GSD_IS_KEYBINDINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_KEYBINDINGS_MANAGER))
+#define GSD_KEYBINDINGS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_KEYBINDINGS_MANAGER, GsdKeybindingsManagerClass))
+
+typedef struct GsdKeybindingsManagerPrivate GsdKeybindingsManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdKeybindingsManagerPrivate *priv;
+} GsdKeybindingsManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdKeybindingsManagerClass;
+
+GType gsd_keybindings_manager_get_type (void);
+
+GsdKeybindingsManager * gsd_keybindings_manager_new (void);
+gboolean gsd_keybindings_manager_start (GsdKeybindingsManager *manager,
+ GError **error);
+void gsd_keybindings_manager_stop (GsdKeybindingsManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_KEYBINDINGS_MANAGER_H */
diff --git a/plugins/keybindings/gsd-keybindings-plugin.c b/plugins/keybindings/gsd-keybindings-plugin.c
new file mode 100644
index 0000000..a96f420
--- /dev/null
+++ b/plugins/keybindings/gsd-keybindings-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-keybindings-plugin.h"
+#include "gsd-keybindings-manager.h"
+
+struct GsdKeybindingsPluginPrivate {
+ GsdKeybindingsManager *manager;
+};
+
+#define GSD_KEYBINDINGS_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_KEYBINDINGS_PLUGIN, GsdKeybindingsPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdKeybindingsPlugin, gsd_keybindings_plugin)
+
+static void
+gsd_keybindings_plugin_init (GsdKeybindingsPlugin *plugin)
+{
+ plugin->priv = GSD_KEYBINDINGS_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdKeybindingsPlugin initializing");
+
+ plugin->priv->manager = gsd_keybindings_manager_new ();
+}
+
+static void
+gsd_keybindings_plugin_finalize (GObject *object)
+{
+ GsdKeybindingsPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_KEYBINDINGS_PLUGIN (object));
+
+ g_debug ("GsdKeybindingsPlugin finalizing");
+
+ plugin = GSD_KEYBINDINGS_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_keybindings_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating keybindings plugin");
+
+ error = NULL;
+ res = gsd_keybindings_manager_start (GSD_KEYBINDINGS_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start keybindings manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating keybindings plugin");
+ gsd_keybindings_manager_stop (GSD_KEYBINDINGS_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_keybindings_plugin_class_init (GsdKeybindingsPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_keybindings_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdKeybindingsPluginPrivate));
+}
diff --git a/plugins/keybindings/gsd-keybindings-plugin.h b/plugins/keybindings/gsd-keybindings-plugin.h
new file mode 100644
index 0000000..dea237d
--- /dev/null
+++ b/plugins/keybindings/gsd-keybindings-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_KEYBINDINGS_PLUGIN_H__
+#define __GSD_KEYBINDINGS_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_KEYBINDINGS_PLUGIN (gsd_keybindings_plugin_get_type ())
+#define GSD_KEYBINDINGS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_KEYBINDINGS_PLUGIN, GsdKeybindingsPlugin))
+#define GSD_KEYBINDINGS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_KEYBINDINGS_PLUGIN, GsdKeybindingsPluginClass))
+#define GSD_IS_KEYBINDINGS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_KEYBINDINGS_PLUGIN))
+#define GSD_IS_KEYBINDINGS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_KEYBINDINGS_PLUGIN))
+#define GSD_KEYBINDINGS_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_KEYBINDINGS_PLUGIN, GsdKeybindingsPluginClass))
+
+typedef struct GsdKeybindingsPluginPrivate GsdKeybindingsPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdKeybindingsPluginPrivate *priv;
+} GsdKeybindingsPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdKeybindingsPluginClass;
+
+GType gsd_keybindings_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_KEYBINDINGS_PLUGIN_H__ */
diff --git a/plugins/keybindings/keybindings.mate-settings-plugin.in b/plugins/keybindings/keybindings.mate-settings-plugin.in
new file mode 100644
index 0000000..f9c7208
--- /dev/null
+++ b/plugins/keybindings/keybindings.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=keybindings
+IAge=0
+_Name=Keybindings
+_Description=Keybindings plugin
+Authors=AUTHOR
+Copyright=Copyright © 2007 AUTHOR
+Website=
diff --git a/plugins/keyboard/Makefile.am b/plugins/keyboard/Makefile.am
new file mode 100644
index 0000000..fdad2a8
--- /dev/null
+++ b/plugins/keyboard/Makefile.am
@@ -0,0 +1,73 @@
+NULL =
+
+plugin_LTLIBRARIES = \
+ libkeyboard.la \
+ $(NULL)
+
+themedir = $(pkgdatadir)/icons/hicolor
+size = 64x64
+context = devices
+
+iconsdir = $(themedir)/$(size)/$(context)
+icons_DATA = \
+ kbd-capslock-off.png kbd-numlock-off.png kbd-scrolllock-off.png \
+ kbd-capslock-on.png kbd-numlock-on.png kbd-scrolllock-on.png
+
+uidir = $(pkgdatadir)
+ui_DATA = modmap-dialog.ui
+
+libkeyboard_la_SOURCES = \
+ gsd-keyboard-plugin.h \
+ gsd-keyboard-plugin.c \
+ gsd-keyboard-manager.h \
+ gsd-keyboard-manager.c \
+ gsd-keyboard-xkb.h \
+ gsd-keyboard-xkb.c \
+ gsd-xmodmap.h \
+ gsd-xmodmap.c \
+ delayed-dialog.h \
+ delayed-dialog.c \
+ $(NULL)
+
+libkeyboard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DDATADIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libkeyboard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(LIBMATEKBDUI_CFLAGS) \
+ $(AM_CFLAGS)
+
+libkeyboard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libkeyboard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(LIBMATEKBDUI_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ keyboard.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(icons_DATA) \
+ $(plugin_in_files) \
+ $(ui_DATA) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/keyboard/Makefile.in b/plugins/keyboard/Makefile.in
new file mode 100644
index 0000000..021ac11
--- /dev/null
+++ b/plugins/keyboard/Makefile.in
@@ -0,0 +1,771 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/keyboard
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(iconsdir)" \
+ "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(uidir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libkeyboard_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libkeyboard_la_OBJECTS = libkeyboard_la-gsd-keyboard-plugin.lo \
+ libkeyboard_la-gsd-keyboard-manager.lo \
+ libkeyboard_la-gsd-keyboard-xkb.lo \
+ libkeyboard_la-gsd-xmodmap.lo libkeyboard_la-delayed-dialog.lo \
+ $(am__objects_1)
+libkeyboard_la_OBJECTS = $(am_libkeyboard_la_OBJECTS)
+libkeyboard_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libkeyboard_la_CFLAGS) \
+ $(CFLAGS) $(libkeyboard_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libkeyboard_la_SOURCES)
+DIST_SOURCES = $(libkeyboard_la_SOURCES)
+DATA = $(icons_DATA) $(plugin_DATA) $(ui_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+plugin_LTLIBRARIES = \
+ libkeyboard.la \
+ $(NULL)
+
+themedir = $(pkgdatadir)/icons/hicolor
+size = 64x64
+context = devices
+iconsdir = $(themedir)/$(size)/$(context)
+icons_DATA = \
+ kbd-capslock-off.png kbd-numlock-off.png kbd-scrolllock-off.png \
+ kbd-capslock-on.png kbd-numlock-on.png kbd-scrolllock-on.png
+
+uidir = $(pkgdatadir)
+ui_DATA = modmap-dialog.ui
+libkeyboard_la_SOURCES = \
+ gsd-keyboard-plugin.h \
+ gsd-keyboard-plugin.c \
+ gsd-keyboard-manager.h \
+ gsd-keyboard-manager.c \
+ gsd-keyboard-xkb.h \
+ gsd-keyboard-xkb.c \
+ gsd-xmodmap.h \
+ gsd-xmodmap.c \
+ delayed-dialog.h \
+ delayed-dialog.c \
+ $(NULL)
+
+libkeyboard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DDATADIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libkeyboard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(LIBMATEKBDUI_CFLAGS) \
+ $(AM_CFLAGS)
+
+libkeyboard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libkeyboard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(LIBMATEKBDUI_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ keyboard.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(icons_DATA) \
+ $(plugin_in_files) \
+ $(ui_DATA) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/keyboard/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/keyboard/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libkeyboard.la: $(libkeyboard_la_OBJECTS) $(libkeyboard_la_DEPENDENCIES)
+ $(libkeyboard_la_LINK) -rpath $(plugindir) $(libkeyboard_la_OBJECTS) $(libkeyboard_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeyboard_la-delayed-dialog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeyboard_la-gsd-keyboard-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeyboard_la-gsd-keyboard-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeyboard_la-gsd-keyboard-xkb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeyboard_la-gsd-xmodmap.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libkeyboard_la-gsd-keyboard-plugin.lo: gsd-keyboard-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -MT libkeyboard_la-gsd-keyboard-plugin.lo -MD -MP -MF $(DEPDIR)/libkeyboard_la-gsd-keyboard-plugin.Tpo -c -o libkeyboard_la-gsd-keyboard-plugin.lo `test -f 'gsd-keyboard-plugin.c' || echo '$(srcdir)/'`gsd-keyboard-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeyboard_la-gsd-keyboard-plugin.Tpo $(DEPDIR)/libkeyboard_la-gsd-keyboard-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-keyboard-plugin.c' object='libkeyboard_la-gsd-keyboard-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -c -o libkeyboard_la-gsd-keyboard-plugin.lo `test -f 'gsd-keyboard-plugin.c' || echo '$(srcdir)/'`gsd-keyboard-plugin.c
+
+libkeyboard_la-gsd-keyboard-manager.lo: gsd-keyboard-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -MT libkeyboard_la-gsd-keyboard-manager.lo -MD -MP -MF $(DEPDIR)/libkeyboard_la-gsd-keyboard-manager.Tpo -c -o libkeyboard_la-gsd-keyboard-manager.lo `test -f 'gsd-keyboard-manager.c' || echo '$(srcdir)/'`gsd-keyboard-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeyboard_la-gsd-keyboard-manager.Tpo $(DEPDIR)/libkeyboard_la-gsd-keyboard-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-keyboard-manager.c' object='libkeyboard_la-gsd-keyboard-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -c -o libkeyboard_la-gsd-keyboard-manager.lo `test -f 'gsd-keyboard-manager.c' || echo '$(srcdir)/'`gsd-keyboard-manager.c
+
+libkeyboard_la-gsd-keyboard-xkb.lo: gsd-keyboard-xkb.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -MT libkeyboard_la-gsd-keyboard-xkb.lo -MD -MP -MF $(DEPDIR)/libkeyboard_la-gsd-keyboard-xkb.Tpo -c -o libkeyboard_la-gsd-keyboard-xkb.lo `test -f 'gsd-keyboard-xkb.c' || echo '$(srcdir)/'`gsd-keyboard-xkb.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeyboard_la-gsd-keyboard-xkb.Tpo $(DEPDIR)/libkeyboard_la-gsd-keyboard-xkb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-keyboard-xkb.c' object='libkeyboard_la-gsd-keyboard-xkb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -c -o libkeyboard_la-gsd-keyboard-xkb.lo `test -f 'gsd-keyboard-xkb.c' || echo '$(srcdir)/'`gsd-keyboard-xkb.c
+
+libkeyboard_la-gsd-xmodmap.lo: gsd-xmodmap.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -MT libkeyboard_la-gsd-xmodmap.lo -MD -MP -MF $(DEPDIR)/libkeyboard_la-gsd-xmodmap.Tpo -c -o libkeyboard_la-gsd-xmodmap.lo `test -f 'gsd-xmodmap.c' || echo '$(srcdir)/'`gsd-xmodmap.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeyboard_la-gsd-xmodmap.Tpo $(DEPDIR)/libkeyboard_la-gsd-xmodmap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xmodmap.c' object='libkeyboard_la-gsd-xmodmap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -c -o libkeyboard_la-gsd-xmodmap.lo `test -f 'gsd-xmodmap.c' || echo '$(srcdir)/'`gsd-xmodmap.c
+
+libkeyboard_la-delayed-dialog.lo: delayed-dialog.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -MT libkeyboard_la-delayed-dialog.lo -MD -MP -MF $(DEPDIR)/libkeyboard_la-delayed-dialog.Tpo -c -o libkeyboard_la-delayed-dialog.lo `test -f 'delayed-dialog.c' || echo '$(srcdir)/'`delayed-dialog.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libkeyboard_la-delayed-dialog.Tpo $(DEPDIR)/libkeyboard_la-delayed-dialog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='delayed-dialog.c' object='libkeyboard_la-delayed-dialog.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkeyboard_la_CPPFLAGS) $(CPPFLAGS) $(libkeyboard_la_CFLAGS) $(CFLAGS) -c -o libkeyboard_la-delayed-dialog.lo `test -f 'delayed-dialog.c' || echo '$(srcdir)/'`delayed-dialog.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-iconsDATA: $(icons_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(iconsdir)" || $(MKDIR_P) "$(DESTDIR)$(iconsdir)"
+ @list='$(icons_DATA)'; test -n "$(iconsdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(iconsdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(iconsdir)" || exit $$?; \
+ done
+
+uninstall-iconsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(icons_DATA)'; test -n "$(iconsdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(iconsdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(iconsdir)" && rm -f $$files
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+install-uiDATA: $(ui_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(uidir)" || $(MKDIR_P) "$(DESTDIR)$(uidir)"
+ @list='$(ui_DATA)'; test -n "$(uidir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(uidir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(uidir)" || exit $$?; \
+ done
+
+uninstall-uiDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ui_DATA)'; test -n "$(uidir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(uidir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(uidir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(iconsdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(uidir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-iconsDATA install-pluginDATA \
+ install-pluginLTLIBRARIES install-uiDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-iconsDATA uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES uninstall-uiDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-iconsDATA install-info install-info-am \
+ install-man install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip install-uiDATA installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-iconsDATA uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES uninstall-uiDATA
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/keyboard/delayed-dialog.c b/plugins/keyboard/delayed-dialog.c
new file mode 100644
index 0000000..1aa13e1
--- /dev/null
+++ b/plugins/keyboard/delayed-dialog.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "delayed-dialog.h"
+
+static gboolean delayed_show_timeout (gpointer data);
+static GdkFilterReturn message_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data);
+
+static GSList *dialogs = NULL;
+
+/**
+ * gsd_delayed_show_dialog:
+ * @dialog: the dialog
+ *
+ * Shows the dialog as with gtk_widget_show(), unless a window manager
+ * hasn't been started yet, in which case it will wait up to 5 seconds
+ * for that to happen before showing the dialog.
+ **/
+void
+gsd_delayed_show_dialog (GtkWidget *dialog)
+{
+ GdkDisplay *display = gtk_widget_get_display (dialog);
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ GdkScreen *screen = gtk_widget_get_screen (dialog);
+ GdkAtom manager_atom;
+ char selection_name[10];
+ Atom selection_atom;
+
+ /* We can't use gdk_selection_owner_get() for this, because
+ * it's an unknown out-of-process window.
+ */
+ snprintf (selection_name, sizeof (selection_name), "WM_S%d",
+ gdk_screen_get_number (screen));
+ selection_atom = XInternAtom (xdisplay, selection_name, True);
+ if (selection_atom &&
+ XGetSelectionOwner (xdisplay, selection_atom) != None) {
+ gtk_widget_show (dialog);
+ return;
+ }
+
+ dialogs = g_slist_prepend (dialogs, dialog);
+
+ manager_atom = gdk_atom_intern ("MANAGER", FALSE);
+ gdk_display_add_client_message_filter (display, manager_atom,
+ message_filter, NULL);
+
+ g_timeout_add (5000, delayed_show_timeout, NULL);
+}
+
+static gboolean
+delayed_show_timeout (gpointer data)
+{
+ GSList *l;
+
+ for (l = dialogs; l; l = l->next)
+ gtk_widget_show (l->data);
+ g_slist_free (dialogs);
+ dialogs = NULL;
+
+ /* FIXME: There's no gdk_display_remove_client_message_filter */
+
+ return FALSE;
+}
+
+static GdkFilterReturn
+message_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
+{
+ XClientMessageEvent *evt = (XClientMessageEvent *)xevent;
+ char *selection_name = XGetAtomName (evt->display, evt->data.l[1]);
+ int screen;
+ GSList *l, *next;
+
+ if (!dialogs)
+ return GDK_FILTER_CONTINUE;
+
+ if (strncmp (selection_name, "WM_S", 4) != 0) {
+ XFree (selection_name);
+ return GDK_FILTER_CONTINUE;
+ }
+
+ screen = atoi (selection_name + 4);
+
+ for (l = dialogs; l; l = next) {
+ GtkWidget *dialog = l->data;
+ next = l->next;
+
+ if (gdk_screen_get_number (gtk_widget_get_screen (dialog)) == screen) {
+ gtk_widget_show (dialog);
+ dialogs = g_slist_remove (dialogs, dialog);
+ }
+ }
+
+ if (!dialogs) {
+ /* FIXME: There's no gdk_display_remove_client_message_filter */
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
diff --git a/plugins/keyboard/delayed-dialog.h b/plugins/keyboard/delayed-dialog.h
new file mode 100644
index 0000000..353dbe6
--- /dev/null
+++ b/plugins/keyboard/delayed-dialog.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+
+#ifndef __DELAYED_DIALOG_H
+#define __DELAYED_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gsd_delayed_show_dialog (GtkWidget *dialog);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/keyboard/gsd-keyboard-manager.c b/plugins/keyboard/gsd-keyboard-manager.c
new file mode 100644
index 0000000..343706d
--- /dev/null
+++ b/plugins/keyboard/gsd-keyboard-manager.c
@@ -0,0 +1,570 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2001 Ximian, Inc.
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
+# include <X11/extensions/xf86misc.h>
+#endif
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+#include <X11/XKBlib.h>
+#include <X11/keysym.h>
+#endif
+
+#include "mate-settings-profile.h"
+#include "gsd-keyboard-manager.h"
+
+#include "gsd-keyboard-xkb.h"
+#include "gsd-xmodmap.h"
+
+#define GSD_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerPrivate))
+
+#ifndef HOST_NAME_MAX
+# define HOST_NAME_MAX 255
+#endif
+
+#define GSD_KEYBOARD_KEY "/desktop/mate/peripherals/keyboard"
+
+#define KEY_REPEAT GSD_KEYBOARD_KEY "/repeat"
+#define KEY_CLICK GSD_KEYBOARD_KEY "/click"
+#define KEY_RATE GSD_KEYBOARD_KEY "/rate"
+#define KEY_DELAY GSD_KEYBOARD_KEY "/delay"
+#define KEY_CLICK_VOLUME GSD_KEYBOARD_KEY "/click_volume"
+
+#define KEY_BELL_VOLUME GSD_KEYBOARD_KEY "/bell_volume"
+#define KEY_BELL_PITCH GSD_KEYBOARD_KEY "/bell_pitch"
+#define KEY_BELL_DURATION GSD_KEYBOARD_KEY "/bell_duration"
+#define KEY_BELL_MODE GSD_KEYBOARD_KEY "/bell_mode"
+
+struct GsdKeyboardManagerPrivate
+{
+ gboolean have_xkb;
+ gint xkb_event_base;
+ guint notify;
+};
+
+static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass);
+static void gsd_keyboard_manager_init (GsdKeyboardManager *keyboard_manager);
+static void gsd_keyboard_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+
+#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
+static gboolean
+xfree86_set_keyboard_autorepeat_rate (int delay, int rate)
+{
+ gboolean res = FALSE;
+ int event_base_return;
+ int error_base_return;
+
+ if (XF86MiscQueryExtension (GDK_DISPLAY (),
+ &event_base_return,
+ &error_base_return) == True) {
+ /* load the current settings */
+ XF86MiscKbdSettings kbdsettings;
+ XF86MiscGetKbdSettings (GDK_DISPLAY (), &kbdsettings);
+
+ /* assign the new values */
+ kbdsettings.delay = delay;
+ kbdsettings.rate = rate;
+ XF86MiscSetKbdSettings (GDK_DISPLAY (), &kbdsettings);
+ res = TRUE;
+ }
+
+ return res;
+}
+#endif /* HAVE_X11_EXTENSIONS_XF86MISC_H */
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+static gboolean
+xkb_set_keyboard_autorepeat_rate (int delay, int rate)
+{
+ int interval = (rate <= 0) ? 1000000 : 1000/rate;
+ if (delay <= 0)
+ delay = 1;
+ return XkbSetAutoRepeatRate (GDK_DISPLAY (),
+ XkbUseCoreKbd,
+ delay,
+ interval);
+}
+#endif
+
+static char *
+gsd_keyboard_get_hostname_key (const char *subkey)
+{
+ char hostname[HOST_NAME_MAX + 1];
+
+ if (gethostname (hostname, sizeof (hostname)) == 0 &&
+ strcmp (hostname, "localhost") != 0 &&
+ strcmp (hostname, "localhost.localdomain") != 0) {
+ char *escaped;
+ char *key;
+
+ escaped = mateconf_escape_key (hostname, -1);
+ key = g_strconcat (GSD_KEYBOARD_KEY
+ "/host-",
+ escaped,
+ "/0/",
+ subkey,
+ NULL);
+ g_free (escaped);
+ return key;
+ } else
+ return NULL;
+}
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+
+typedef enum {
+ NUMLOCK_STATE_OFF = 0,
+ NUMLOCK_STATE_ON = 1,
+ NUMLOCK_STATE_UNKNOWN = 2
+} NumLockState;
+
+static void
+numlock_xkb_init (GsdKeyboardManager *manager)
+{
+ Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ gboolean have_xkb;
+ int opcode, error_base, major, minor;
+
+ have_xkb = XkbQueryExtension (dpy,
+ &opcode,
+ &manager->priv->xkb_event_base,
+ &error_base,
+ &major,
+ &minor)
+ && XkbUseExtension (dpy, &major, &minor);
+
+ if (have_xkb) {
+ XkbSelectEventDetails (dpy,
+ XkbUseCoreKbd,
+ XkbStateNotifyMask,
+ XkbModifierLockMask,
+ XkbModifierLockMask);
+ } else {
+ g_warning ("XKB extension not available");
+ }
+
+ manager->priv->have_xkb = have_xkb;
+}
+
+static unsigned
+numlock_NumLock_modifier_mask (void)
+{
+ Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ return XkbKeysymToModifiers (dpy, XK_Num_Lock);
+}
+
+static void
+numlock_set_xkb_state (NumLockState new_state)
+{
+ unsigned int num_mask;
+ Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ if (new_state != NUMLOCK_STATE_ON && new_state != NUMLOCK_STATE_OFF)
+ return;
+ num_mask = numlock_NumLock_modifier_mask ();
+ XkbLockModifiers (dpy, XkbUseCoreKbd, num_mask, new_state ? num_mask : 0);
+}
+
+static char *
+numlock_mateconf_state_key (void)
+{
+ char *key = gsd_keyboard_get_hostname_key ("numlock_on");
+ if (!key) {
+ g_message ("NumLock remembering disabled because hostname is set to \"localhost\"");
+ }
+ return key;
+}
+
+static NumLockState
+numlock_get_mateconf_state (MateConfClient *client)
+{
+ int curr_state;
+ GError *err = NULL;
+ char *key = numlock_mateconf_state_key ();
+
+ if (!key) {
+ return NUMLOCK_STATE_UNKNOWN;
+ }
+
+ curr_state = mateconf_client_get_bool (client, key, &err);
+ if (err) {
+ curr_state = NUMLOCK_STATE_UNKNOWN;
+ g_error_free (err);
+ }
+
+ g_free (key);
+ return curr_state;
+}
+
+static void
+numlock_set_mateconf_state (MateConfClient *client,
+ NumLockState new_state)
+{
+ char *key;
+
+ if (new_state != NUMLOCK_STATE_ON && new_state != NUMLOCK_STATE_OFF) {
+ return;
+ }
+
+ key = numlock_mateconf_state_key ();
+ if (key) {
+ mateconf_client_set_bool (client, key, new_state, NULL);
+ g_free (key);
+ }
+}
+
+static GdkFilterReturn
+numlock_xkb_callback (GdkXEvent *xev_,
+ GdkEvent *gdkev_,
+ gpointer xkb_event_code)
+{
+ XEvent *xev = (XEvent *) xev_;
+
+ if (xev->type == GPOINTER_TO_INT (xkb_event_code)) {
+ XkbEvent *xkbev = (XkbEvent *)xev;
+ if (xkbev->any.xkb_type == XkbStateNotify)
+ if (xkbev->state.changed & XkbModifierLockMask) {
+ unsigned num_mask = numlock_NumLock_modifier_mask ();
+ unsigned locked_mods = xkbev->state.locked_mods;
+ int numlock_state = !! (num_mask & locked_mods);
+ MateConfClient *client = mateconf_client_get_default ();
+ numlock_set_mateconf_state (client, numlock_state);
+ g_object_unref (client);
+ }
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+numlock_install_xkb_callback (GsdKeyboardManager *manager)
+{
+ if (!manager->priv->have_xkb)
+ return;
+
+ gdk_window_add_filter (NULL,
+ numlock_xkb_callback,
+ GINT_TO_POINTER (manager->priv->xkb_event_base));
+}
+
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+static void
+apply_settings (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdKeyboardManager *manager)
+{
+ XKeyboardControl kbdcontrol;
+ gboolean repeat;
+ gboolean click;
+ int rate;
+ int delay;
+ int click_volume;
+ int bell_volume;
+ int bell_pitch;
+ int bell_duration;
+ char *volume_string;
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ gboolean rnumlock;
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+ repeat = mateconf_client_get_bool (client, KEY_REPEAT, NULL);
+ click = mateconf_client_get_bool (client, KEY_CLICK, NULL);
+ rate = mateconf_client_get_int (client, KEY_RATE, NULL);
+ delay = mateconf_client_get_int (client, KEY_DELAY, NULL);
+ click_volume = mateconf_client_get_int (client, KEY_CLICK_VOLUME, NULL);
+#if 0
+ bell_volume = mateconf_client_get_int (client, KEY_BELL_VOLUME, NULL);
+#endif
+ bell_pitch = mateconf_client_get_int (client, KEY_BELL_PITCH, NULL);
+ bell_duration = mateconf_client_get_int (client, KEY_BELL_DURATION, NULL);
+
+ volume_string = mateconf_client_get_string (client, KEY_BELL_MODE, NULL);
+ bell_volume = (volume_string && !strcmp (volume_string, "on")) ? 50 : 0;
+ g_free (volume_string);
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ rnumlock = mateconf_client_get_bool (client, GSD_KEYBOARD_KEY "/remember_numlock_state", NULL);
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+ gdk_error_trap_push ();
+ if (repeat) {
+ gboolean rate_set = FALSE;
+
+ XAutoRepeatOn (GDK_DISPLAY ());
+ /* Use XKB in preference */
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ rate_set = xkb_set_keyboard_autorepeat_rate (delay, rate);
+#endif
+#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
+ if (!rate_set)
+ rate_set = xfree86_set_keyboard_autorepeat_rate (delay, rate);
+#endif
+ if (!rate_set)
+ g_warning ("Neither XKeyboard not Xfree86's keyboard extensions are available,\n"
+ "no way to support keyboard autorepeat rate settings");
+ } else {
+ XAutoRepeatOff (GDK_DISPLAY ());
+ }
+
+ /* as percentage from 0..100 inclusive */
+ if (click_volume < 0) {
+ click_volume = 0;
+ } else if (click_volume > 100) {
+ click_volume = 100;
+ }
+ kbdcontrol.key_click_percent = click ? click_volume : 0;
+ kbdcontrol.bell_percent = bell_volume;
+ kbdcontrol.bell_pitch = bell_pitch;
+ kbdcontrol.bell_duration = bell_duration;
+ XChangeKeyboardControl (GDK_DISPLAY (),
+ KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration,
+ &kbdcontrol);
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ if (manager->priv->have_xkb && rnumlock) {
+ numlock_set_xkb_state (numlock_get_mateconf_state (client));
+ }
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+ XSync (GDK_DISPLAY (), FALSE);
+ gdk_error_trap_pop ();
+}
+
+void
+gsd_keyboard_manager_apply_settings (GsdKeyboardManager *manager)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ apply_settings (client, 0, NULL, manager);
+ g_object_unref (client);
+}
+
+static gboolean
+start_keyboard_idle_cb (GsdKeyboardManager *manager)
+{
+ MateConfClient *client;
+
+ mate_settings_profile_start (NULL);
+
+ g_debug ("Starting keyboard manager");
+
+ manager->priv->have_xkb = 0;
+ client = mateconf_client_get_default ();
+
+ mateconf_client_add_dir (client, GSD_KEYBOARD_KEY, MATECONF_CLIENT_PRELOAD_RECURSIVE, NULL);
+
+ /* Essential - xkb initialization should happen before */
+ gsd_keyboard_xkb_set_post_activation_callback ((PostActivationCallback) gsd_load_modmap_files, NULL);
+ gsd_keyboard_xkb_init (client, manager);
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ numlock_xkb_init (manager);
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+ /* apply current settings before we install the callback */
+ gsd_keyboard_manager_apply_settings (manager);
+
+ manager->priv->notify = mateconf_client_notify_add (client, GSD_KEYBOARD_KEY,
+ (MateConfClientNotifyFunc) apply_settings, manager,
+ NULL, NULL);
+
+ g_object_unref (client);
+
+#ifdef HAVE_X11_EXTENSIONS_XKB_H
+ numlock_install_xkb_callback (manager);
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+ mate_settings_profile_end (NULL);
+
+ return FALSE;
+}
+
+gboolean
+gsd_keyboard_manager_start (GsdKeyboardManager *manager,
+ GError **error)
+{
+ mate_settings_profile_start (NULL);
+
+ g_idle_add ((GSourceFunc) start_keyboard_idle_cb, manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_keyboard_manager_stop (GsdKeyboardManager *manager)
+{
+ GsdKeyboardManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping keyboard manager");
+
+ if (p->notify != 0) {
+ MateConfClient *client = mateconf_client_get_default ();
+ mateconf_client_remove_dir (client, GSD_KEYBOARD_KEY, NULL);
+ mateconf_client_notify_remove (client, p->notify);
+ g_object_unref (client);
+ p->notify = 0;
+ }
+
+#if HAVE_X11_EXTENSIONS_XKB_H
+ if (p->have_xkb) {
+ gdk_window_remove_filter (NULL,
+ numlock_xkb_callback,
+ GINT_TO_POINTER (p->xkb_event_base));
+ }
+#endif /* HAVE_X11_EXTENSIONS_XKB_H */
+
+ gsd_keyboard_xkb_shutdown ();
+}
+
+static void
+gsd_keyboard_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdKeyboardManager *self;
+
+ self = GSD_KEYBOARD_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_keyboard_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdKeyboardManager *self;
+
+ self = GSD_KEYBOARD_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_keyboard_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdKeyboardManager *keyboard_manager;
+ GsdKeyboardManagerClass *klass;
+
+ klass = GSD_KEYBOARD_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_KEYBOARD_MANAGER));
+
+ keyboard_manager = GSD_KEYBOARD_MANAGER (G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (keyboard_manager);
+}
+
+static void
+gsd_keyboard_manager_dispose (GObject *object)
+{
+ GsdKeyboardManager *keyboard_manager;
+
+ keyboard_manager = GSD_KEYBOARD_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_keyboard_manager_get_property;
+ object_class->set_property = gsd_keyboard_manager_set_property;
+ object_class->constructor = gsd_keyboard_manager_constructor;
+ object_class->dispose = gsd_keyboard_manager_dispose;
+ object_class->finalize = gsd_keyboard_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdKeyboardManagerPrivate));
+}
+
+static void
+gsd_keyboard_manager_init (GsdKeyboardManager *manager)
+{
+ manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager);
+}
+
+static void
+gsd_keyboard_manager_finalize (GObject *object)
+{
+ GsdKeyboardManager *keyboard_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_KEYBOARD_MANAGER (object));
+
+ keyboard_manager = GSD_KEYBOARD_MANAGER (object);
+
+ g_return_if_fail (keyboard_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->finalize (object);
+}
+
+GsdKeyboardManager *
+gsd_keyboard_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_KEYBOARD_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_KEYBOARD_MANAGER (manager_object);
+}
diff --git a/plugins/keyboard/gsd-keyboard-manager.h b/plugins/keyboard/gsd-keyboard-manager.h
new file mode 100644
index 0000000..a518e9a
--- /dev/null
+++ b/plugins/keyboard/gsd-keyboard-manager.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_KEYBOARD_MANAGER_H
+#define __GSD_KEYBOARD_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_KEYBOARD_MANAGER (gsd_keyboard_manager_get_type ())
+#define GSD_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManager))
+#define GSD_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerClass))
+#define GSD_IS_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_KEYBOARD_MANAGER))
+#define GSD_IS_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_KEYBOARD_MANAGER))
+#define GSD_KEYBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerClass))
+
+typedef struct GsdKeyboardManagerPrivate GsdKeyboardManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdKeyboardManagerPrivate *priv;
+} GsdKeyboardManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdKeyboardManagerClass;
+
+GType gsd_keyboard_manager_get_type (void);
+
+GsdKeyboardManager * gsd_keyboard_manager_new (void);
+gboolean gsd_keyboard_manager_start (GsdKeyboardManager *manager,
+ GError **error);
+void gsd_keyboard_manager_stop (GsdKeyboardManager *manager);
+void gsd_keyboard_manager_apply_settings (GsdKeyboardManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_KEYBOARD_MANAGER_H */
diff --git a/plugins/keyboard/gsd-keyboard-plugin.c b/plugins/keyboard/gsd-keyboard-plugin.c
new file mode 100644
index 0000000..b501d80
--- /dev/null
+++ b/plugins/keyboard/gsd-keyboard-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-keyboard-plugin.h"
+#include "gsd-keyboard-manager.h"
+
+struct GsdKeyboardPluginPrivate {
+ GsdKeyboardManager *manager;
+};
+
+#define GSD_KEYBOARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_KEYBOARD_PLUGIN, GsdKeyboardPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdKeyboardPlugin, gsd_keyboard_plugin)
+
+static void
+gsd_keyboard_plugin_init (GsdKeyboardPlugin *plugin)
+{
+ plugin->priv = GSD_KEYBOARD_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdKeyboardPlugin initializing");
+
+ plugin->priv->manager = gsd_keyboard_manager_new ();
+}
+
+static void
+gsd_keyboard_plugin_finalize (GObject *object)
+{
+ GsdKeyboardPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_KEYBOARD_PLUGIN (object));
+
+ g_debug ("GsdKeyboardPlugin finalizing");
+
+ plugin = GSD_KEYBOARD_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_keyboard_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating keyboard plugin");
+
+ error = NULL;
+ res = gsd_keyboard_manager_start (GSD_KEYBOARD_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start keyboard manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating keyboard plugin");
+ gsd_keyboard_manager_stop (GSD_KEYBOARD_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_keyboard_plugin_class_init (GsdKeyboardPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_keyboard_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdKeyboardPluginPrivate));
+}
diff --git a/plugins/keyboard/gsd-keyboard-plugin.h b/plugins/keyboard/gsd-keyboard-plugin.h
new file mode 100644
index 0000000..3d25861
--- /dev/null
+++ b/plugins/keyboard/gsd-keyboard-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_KEYBOARD_PLUGIN_H__
+#define __GSD_KEYBOARD_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_KEYBOARD_PLUGIN (gsd_keyboard_plugin_get_type ())
+#define GSD_KEYBOARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_KEYBOARD_PLUGIN, GsdKeyboardPlugin))
+#define GSD_KEYBOARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_KEYBOARD_PLUGIN, GsdKeyboardPluginClass))
+#define GSD_IS_KEYBOARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_KEYBOARD_PLUGIN))
+#define GSD_IS_KEYBOARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_KEYBOARD_PLUGIN))
+#define GSD_KEYBOARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_KEYBOARD_PLUGIN, GsdKeyboardPluginClass))
+
+typedef struct GsdKeyboardPluginPrivate GsdKeyboardPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdKeyboardPluginPrivate *priv;
+} GsdKeyboardPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdKeyboardPluginClass;
+
+GType gsd_keyboard_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_KEYBOARD_PLUGIN_H__ */
diff --git a/plugins/keyboard/gsd-keyboard-xkb.c b/plugins/keyboard/gsd-keyboard-xkb.c
new file mode 100644
index 0000000..681c665
--- /dev/null
+++ b/plugins/keyboard/gsd-keyboard-xkb.c
@@ -0,0 +1,924 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2001 Udaltsoft
+ *
+ * Written by Sergey V. Oudaltsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include <libmatekbd/matekbd-status.h>
+#include <libmatekbd/matekbd-keyboard-drawing.h>
+#include <libmatekbd/matekbd-desktop-config.h>
+#include <libmatekbd/matekbd-keyboard-config.h>
+#include <libmatekbd/matekbd-util.h>
+
+#include "gsd-xmodmap.h"
+#include "gsd-keyboard-xkb.h"
+#include "delayed-dialog.h"
+#include "mate-settings-profile.h"
+
+#define GTK_RESPONSE_PRINT 2
+
+static GsdKeyboardManager *manager = NULL;
+
+static XklEngine *xkl_engine;
+static XklConfigRegistry *xkl_registry = NULL;
+
+static MatekbdDesktopConfig current_config;
+static MatekbdKeyboardConfig current_kbd_config;
+
+/* never terminated */
+static MatekbdKeyboardConfig initial_sys_kbd_config;
+
+static gboolean inited_ok = FALSE;
+
+static guint notify_desktop = 0;
+static guint notify_keyboard = 0;
+
+static PostActivationCallback pa_callback = NULL;
+static void *pa_callback_user_data = NULL;
+
+static const char KNOWN_FILES_KEY[] =
+ "/desktop/mate/peripherals/keyboard/general/known_file_list";
+
+static const char DISABLE_INDICATOR_KEY[] =
+ "/desktop/mate/peripherals/keyboard/general/disable_indicator";
+
+static const char DUPLICATE_LEDS_KEY[] =
+ "/desktop/mate/peripherals/keyboard/general/duplicate_leds";
+
+static const char *mdm_keyboard_layout = NULL;
+
+static GtkStatusIcon *icon = NULL;
+
+static GHashTable *preview_dialogs = NULL;
+
+static Atom caps_lock;
+static Atom num_lock;
+static Atom scroll_lock;
+
+static GtkStatusIcon *indicator_icons[3];
+static const gchar *indicator_on_icon_names[] = {
+ "kbd-scrolllock-on",
+ "kbd-numlock-on",
+ "kbd-capslock-on"
+};
+
+static const gchar *indicator_off_icon_names[] = {
+ "kbd-scrolllock-off",
+ "kbd-numlock-off",
+ "kbd-capslock-off"
+};
+
+#define noGSDKX
+
+#ifdef GSDKX
+static FILE *logfile;
+
+static void
+gsd_keyboard_log_appender (const char file[],
+ const char function[],
+ int level, const char format[], va_list args)
+{
+ time_t now = time (NULL);
+ fprintf (logfile, "[%08ld,%03d,%s:%s/] \t", now,
+ level, file, function);
+ vfprintf (logfile, format, args);
+ fflush (logfile);
+}
+#endif
+
+static void
+activation_error (void)
+{
+ char const *vendor = ServerVendor (GDK_DISPLAY ());
+ int release = VendorRelease (GDK_DISPLAY ());
+ GtkWidget *dialog;
+ gboolean badXFree430Release;
+
+ badXFree430Release = (vendor != NULL)
+ && (0 == strcmp (vendor, "The XFree86 Project, Inc"))
+ && (release / 100000 == 403);
+
+ /* VNC viewers will not work, do not barrage them with warnings */
+ if (NULL != vendor && NULL != strstr (vendor, "VNC"))
+ return;
+
+ dialog = gtk_message_dialog_new_with_markup (NULL,
+ 0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _
+ ("Error activating XKB configuration.\n"
+ "It can happen under various circumstances:\n"
+ " • a bug in libxklavier library\n"
+ " • a bug in X server (xkbcomp, xmodmap utilities)\n"
+ " • X server with incompatible libxkbfile implementation\n\n"
+ "X server version data:\n%s\n%d\n%s\n"
+ "If you report this situation as a bug, please include:\n"
+ " • The result of <b>%s</b>\n"
+ " • The result of <b>%s</b>"),
+ vendor,
+ release,
+ badXFree430Release
+ ?
+ _
+ ("You are using XFree 4.3.0.\n"
+ "There are known problems with complex XKB configurations.\n"
+ "Try using a simpler configuration or using a later version of the XFree software.")
+ : "",
+ "xprop -root | grep XKB",
+ "mateconftool-2 -R /desktop/mate/peripherals/keyboard/kbd");
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gsd_delayed_show_dialog (dialog);
+}
+
+static void
+apply_desktop_settings (void)
+{
+ MateConfClient *conf_client;
+ gboolean show_leds;
+ int i;
+ if (!inited_ok)
+ return;
+
+ gsd_keyboard_manager_apply_settings (manager);
+ matekbd_desktop_config_load_from_mateconf (&current_config);
+ /* again, probably it would be nice to compare things
+ before activating them */
+ matekbd_desktop_config_activate (&current_config);
+
+ conf_client = mateconf_client_get_default ();
+ show_leds =
+ mateconf_client_get_bool (conf_client, DUPLICATE_LEDS_KEY, NULL);
+ g_object_unref (conf_client);
+ for (i = sizeof (indicator_icons) / sizeof (indicator_icons[0]);
+ --i >= 0;) {
+ gtk_status_icon_set_visible (indicator_icons[i],
+ show_leds);
+ }
+}
+
+static void
+popup_menu_launch_capplet ()
+{
+ GError *error = NULL;
+
+ gdk_spawn_command_line_on_screen (gdk_screen_get_default (),
+ "mate-keyboard-properties",
+ &error);
+
+ if (error != NULL) {
+ g_warning
+ ("Could not execute keyboard properties capplet: [%s]\n",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+show_layout_destroy (GtkWidget * dialog, gint group)
+{
+ g_hash_table_remove (preview_dialogs, GINT_TO_POINTER (group));
+}
+
+static void
+popup_menu_show_layout ()
+{
+ GtkWidget *dialog;
+ XklEngine *engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ XklState *xkl_state = xkl_engine_get_current_state (engine);
+ gpointer p = g_hash_table_lookup (preview_dialogs,
+ GINT_TO_POINTER
+ (xkl_state->group));
+ gchar **group_names = matekbd_status_get_group_names ();
+
+ if (xkl_state->group < 0
+ || xkl_state->group >= g_strv_length (group_names)) {
+ return;
+ }
+
+ if (p != NULL) {
+ /* existing window */
+ gtk_window_present (GTK_WINDOW (p));
+ return;
+ }
+
+ dialog =
+ matekbd_keyboard_drawing_new_dialog (xkl_state->group,
+ group_names
+ [xkl_state->group]);
+ g_signal_connect (GTK_OBJECT (dialog), "destroy",
+ G_CALLBACK (show_layout_destroy),
+ GINT_TO_POINTER (xkl_state->group));
+ g_hash_table_insert (preview_dialogs,
+ GINT_TO_POINTER (xkl_state->group), dialog);
+}
+
+static void
+popup_menu_set_group (GtkMenuItem * item, gpointer param)
+{
+ gint group_number = GPOINTER_TO_INT (param);
+ XklEngine *engine = matekbd_status_get_xkl_engine ();
+ XklState st;
+ Window cur;
+
+ st.group = group_number;
+ xkl_engine_allow_one_switch_to_secondary_group (engine);
+ cur = xkl_engine_get_current_window (engine);
+ if (cur != (Window) NULL) {
+ xkl_debug (150, "Enforcing the state %d for window %lx\n",
+ st.group, cur);
+ xkl_engine_save_state (engine,
+ xkl_engine_get_current_window
+ (engine), &st);
+/* XSetInputFocus( GDK_DISPLAY(), cur, RevertToNone, CurrentTime );*/
+ } else {
+ xkl_debug (150,
+ "??? Enforcing the state %d for unknown window\n",
+ st.group);
+ /* strange situation - bad things can happen */
+ }
+ xkl_engine_lock_group (engine, st.group);
+}
+
+static void
+status_icon_popup_menu_cb (GtkStatusIcon * icon, guint button, guint time)
+{
+ GtkMenu *popup_menu = GTK_MENU (gtk_menu_new ());
+ GtkMenu *groups_menu = GTK_MENU (gtk_menu_new ());
+ int i = 0;
+ gchar **current_name = matekbd_status_get_group_names ();
+
+ GtkWidget *item = gtk_menu_item_new_with_mnemonic (_("_Layouts"));
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item),
+ GTK_WIDGET (groups_menu));
+
+ item =
+ gtk_menu_item_new_with_mnemonic (_("Keyboard _Preferences"));
+ gtk_widget_show (item);
+ g_signal_connect (item, "activate", popup_menu_launch_capplet,
+ NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("Show _Current Layout"));
+ gtk_widget_show (item);
+ g_signal_connect (item, "activate", popup_menu_show_layout, NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+
+ for (i = 0; *current_name; i++, current_name++) {
+ gchar *image_file = matekbd_status_get_image_filename (i);
+
+ if (image_file == NULL) {
+ item =
+ gtk_menu_item_new_with_label (*current_name);
+ } else {
+ GdkPixbuf *pixbuf =
+ gdk_pixbuf_new_from_file_at_size (image_file,
+ 24, 24,
+ NULL);
+ GtkWidget *img =
+ gtk_image_new_from_pixbuf (pixbuf);
+ item =
+ gtk_image_menu_item_new_with_label
+ (*current_name);
+ gtk_widget_show (img);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM
+ (item), img);
+ gtk_image_menu_item_set_always_show_image
+ (GTK_IMAGE_MENU_ITEM (item), TRUE);
+ g_free (image_file);
+ }
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (groups_menu), item);
+ g_signal_connect (item, "activate",
+ G_CALLBACK (popup_menu_set_group),
+ GINT_TO_POINTER (i));
+ }
+
+ gtk_menu_popup (popup_menu, NULL, NULL,
+ gtk_status_icon_position_menu,
+ (gpointer) icon, button, time);
+}
+
+static void
+show_hide_icon ()
+{
+ if (g_slist_length (current_kbd_config.layouts_variants) > 1) {
+ if (icon == NULL) {
+ MateConfClient *conf_client =
+ mateconf_client_get_default ();
+ gboolean disable =
+ mateconf_client_get_bool (conf_client,
+ DISABLE_INDICATOR_KEY,
+ NULL);
+ g_object_unref (conf_client);
+ if (disable)
+ return;
+
+ xkl_debug (150, "Creating new icon\n");
+ icon = matekbd_status_new ();
+ g_signal_connect (icon, "popup-menu",
+ G_CALLBACK
+ (status_icon_popup_menu_cb),
+ NULL);
+
+ }
+ } else {
+ if (icon != NULL) {
+ xkl_debug (150, "Destroying icon\n");
+ g_object_unref (icon);
+ icon = NULL;
+ }
+ }
+}
+
+static gboolean
+try_activating_xkb_config_if_new (MatekbdKeyboardConfig *
+ current_sys_kbd_config)
+{
+ /* Activate - only if different! */
+ if (!matekbd_keyboard_config_equals
+ (&current_kbd_config, current_sys_kbd_config)) {
+ if (matekbd_keyboard_config_activate (&current_kbd_config)) {
+ if (pa_callback != NULL) {
+ (*pa_callback) (pa_callback_user_data);
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+filter_xkb_config (void)
+{
+ XklConfigItem *item;
+ gchar *lname;
+ gchar *vname;
+ GSList *lv;
+ GSList *filtered;
+ gboolean any_change = FALSE;
+
+ xkl_debug (100, "Filtering configuration against the registry\n");
+ if (!xkl_registry) {
+ xkl_registry =
+ xkl_config_registry_get_instance (xkl_engine);
+ /* load all materials, unconditionally! */
+ if (!xkl_config_registry_load (xkl_registry, TRUE)) {
+ g_object_unref (xkl_registry);
+ xkl_registry = NULL;
+ return FALSE;
+ }
+ }
+ lv = current_kbd_config.layouts_variants;
+ item = xkl_config_item_new ();
+ while (lv) {
+ xkl_debug (100, "Checking [%s]\n", lv->data);
+ if (matekbd_keyboard_config_split_items
+ (lv->data, &lname, &vname)) {
+ g_snprintf (item->name, sizeof (item->name), "%s",
+ lname);
+ if (!xkl_config_registry_find_layout
+ (xkl_registry, item)) {
+ xkl_debug (100, "Bad layout [%s]\n",
+ lname);
+ filtered = lv;
+ lv = lv->next;
+ g_free (filtered->data);
+ current_kbd_config.layouts_variants =
+ g_slist_delete_link
+ (current_kbd_config.layouts_variants,
+ filtered);
+ any_change = TRUE;
+ continue;
+ }
+ if (vname) {
+ g_snprintf (item->name,
+ sizeof (item->name), "%s",
+ vname);
+ if (!xkl_config_registry_find_variant
+ (xkl_registry, lname, item)) {
+ xkl_debug (100,
+ "Bad variant [%s(%s)]\n",
+ lname, vname);
+ filtered = lv;
+ lv = lv->next;
+ g_free (filtered->data);
+ current_kbd_config.layouts_variants
+ =
+ g_slist_delete_link
+ (current_kbd_config.layouts_variants,
+ filtered);
+ any_change = TRUE;
+ continue;
+ }
+ }
+ }
+ lv = lv->next;
+ }
+ g_object_unref (item);
+ return any_change;
+}
+
+static void
+apply_xkb_settings (void)
+{
+ MateConfClient *conf_client;
+ MatekbdKeyboardConfig current_sys_kbd_config;
+ int group_to_activate = -1;
+ char *mdm_layout;
+ char *s;
+
+ if (!inited_ok)
+ return;
+
+ conf_client = mateconf_client_get_default ();
+
+ /* With MDM the user can already set a layout from the login
+ * screen. Try to keep that setting.
+ * We clear mdm_keyboard_layout early, so we don't risk
+ * recursion from mateconf notification.
+ */
+ mdm_layout = g_strdup (mdm_keyboard_layout);
+ mdm_keyboard_layout = NULL;
+
+ /* mdm's configuration and $MDM_KEYBOARD_LAYOUT separates layout and
+ * variant with a space, but mateconf uses tabs; so convert to be robust
+ * with both */
+ for (s = mdm_layout; s && *s; ++s) {
+ if (*s == ' ') {
+ *s = '\t';
+ }
+ }
+
+ if (mdm_layout != NULL) {
+ GSList *layouts;
+ GSList *found_node;
+ int max_groups;
+
+ max_groups =
+ MAX (xkl_engine_get_max_num_groups (xkl_engine), 1);
+ layouts =
+ mateconf_client_get_list (conf_client,
+ MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
+ MATECONF_VALUE_STRING, NULL);
+
+ /* Use system layouts as a default if we do not have
+ * user configuration */
+ if (layouts == NULL) {
+ GSList *i;
+ int len;
+
+ for (i = initial_sys_kbd_config.layouts_variants;
+ i; i = g_slist_next (i)) {
+ s = g_strdup (i->data);
+
+ /* chop off empty variants to avoid duplicates */
+ len = strlen (s);
+ if (s[len - 1] == '\t')
+ s[len - 1] = '\0';
+ layouts = g_slist_append (layouts, s);
+ }
+ }
+
+ /* Add the layout if it doesn't already exist. XKB limits the
+ * total number of layouts. If we already have the maximum
+ * number of layouts configured, we replace the last one. This
+ * prevents the list from becoming full if the user has a habit
+ * of selecting many different keyboard layouts in MDM. */
+
+ found_node =
+ g_slist_find_custom (layouts, mdm_layout,
+ (GCompareFunc) g_strcmp0);
+
+ if (!found_node) {
+ /* Insert at the last valid place, or at the end of
+ * list, whichever comes first */
+ layouts =
+ g_slist_insert (layouts, g_strdup (mdm_layout),
+ max_groups - 1);
+ if (g_slist_length (layouts) > max_groups) {
+ GSList *last;
+ GSList *free_layouts;
+
+ last =
+ g_slist_nth (layouts, max_groups - 1);
+ free_layouts = last->next;
+ last->next = NULL;
+
+ g_slist_foreach (free_layouts,
+ (GFunc) g_free, NULL);
+ g_slist_free (free_layouts);
+ }
+
+ mateconf_client_set_list (conf_client,
+ MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
+ MATECONF_VALUE_STRING, layouts,
+ NULL);
+ }
+
+ g_slist_foreach (layouts, (GFunc) g_free, NULL);
+ g_slist_free (layouts);
+ }
+
+ matekbd_keyboard_config_init (&current_sys_kbd_config,
+ conf_client, xkl_engine);
+
+ matekbd_keyboard_config_load_from_mateconf (&current_kbd_config,
+ &initial_sys_kbd_config);
+
+ matekbd_keyboard_config_load_from_x_current (&current_sys_kbd_config,
+ NULL);
+
+ if (!try_activating_xkb_config_if_new (&current_sys_kbd_config)) {
+ if (filter_xkb_config ()) {
+ if (!try_activating_xkb_config_if_new
+ (&current_sys_kbd_config)) {
+ g_warning
+ ("Could not activate the filtered XKB configuration");
+ activation_error ();
+ }
+ } else {
+ g_warning
+ ("Could not activate the XKB configuration");
+ activation_error ();
+ }
+ } else
+ xkl_debug (100,
+ "Actual KBD configuration was not changed: redundant notification\n");
+
+ if (mdm_layout != NULL) {
+ /* If there are multiple layouts,
+ * try to find the one closest to the mdm layout
+ */
+ GSList *l;
+ int i;
+ size_t len = strlen (mdm_layout);
+ for (i = 0, l = current_kbd_config.layouts_variants; l;
+ i++, l = l->next) {
+ char *lv = l->data;
+ if (strncmp (lv, mdm_layout, len) == 0
+ && (lv[len] == '\0' || lv[len] == '\t')) {
+ group_to_activate = i;
+ break;
+ }
+ }
+ }
+
+ g_free (mdm_layout);
+
+ if (group_to_activate != -1)
+ xkl_engine_lock_group (current_config.engine,
+ group_to_activate);
+ matekbd_keyboard_config_term (&current_sys_kbd_config);
+ show_hide_icon ();
+}
+
+static void
+gsd_keyboard_xkb_analyze_sysconfig (void)
+{
+ MateConfClient *conf_client;
+
+ if (!inited_ok)
+ return;
+
+ conf_client = mateconf_client_get_default ();
+ matekbd_keyboard_config_init (&initial_sys_kbd_config,
+ conf_client, xkl_engine);
+ matekbd_keyboard_config_load_from_x_initial (&initial_sys_kbd_config,
+ NULL);
+ g_object_unref (conf_client);
+}
+
+static gboolean
+gsd_chk_file_list (void)
+{
+ GDir *home_dir;
+ const char *fname;
+ GSList *file_list = NULL;
+ GSList *last_login_file_list = NULL;
+ GSList *tmp = NULL;
+ GSList *tmp_l = NULL;
+ gboolean new_file_exist = FALSE;
+ MateConfClient *conf_client;
+
+ home_dir = g_dir_open (g_get_home_dir (), 0, NULL);
+ while ((fname = g_dir_read_name (home_dir)) != NULL) {
+ if (g_strrstr (fname, "modmap")) {
+ file_list =
+ g_slist_append (file_list, g_strdup (fname));
+ }
+ }
+ g_dir_close (home_dir);
+
+ conf_client = mateconf_client_get_default ();
+
+ last_login_file_list = mateconf_client_get_list (conf_client,
+ KNOWN_FILES_KEY,
+ MATECONF_VALUE_STRING,
+ NULL);
+
+ /* Compare between the two file list, currently available modmap files
+ and the files available in the last log in */
+ tmp = file_list;
+ while (tmp != NULL) {
+ tmp_l = last_login_file_list;
+ new_file_exist = TRUE;
+ while (tmp_l != NULL) {
+ if (strcmp (tmp->data, tmp_l->data) == 0) {
+ new_file_exist = FALSE;
+ break;
+ } else {
+ tmp_l = tmp_l->next;
+ }
+ }
+ if (new_file_exist) {
+ break;
+ } else {
+ tmp = tmp->next;
+ }
+ }
+
+ if (new_file_exist) {
+ mateconf_client_set_list (conf_client,
+ KNOWN_FILES_KEY,
+ MATECONF_VALUE_STRING,
+ file_list, NULL);
+ }
+
+ g_object_unref (conf_client);
+
+ g_slist_foreach (file_list, (GFunc) g_free, NULL);
+ g_slist_free (file_list);
+
+ g_slist_foreach (last_login_file_list, (GFunc) g_free, NULL);
+ g_slist_free (last_login_file_list);
+
+ return new_file_exist;
+
+}
+
+static void
+gsd_keyboard_xkb_chk_lcl_xmm (void)
+{
+ if (gsd_chk_file_list ()) {
+ gsd_modmap_dialog_call ();
+ }
+ gsd_load_modmap_files ();
+}
+
+void
+gsd_keyboard_xkb_set_post_activation_callback (PostActivationCallback fun,
+ void *user_data)
+{
+ pa_callback = fun;
+ pa_callback_user_data = user_data;
+}
+
+static GdkFilterReturn
+gsd_keyboard_xkb_evt_filter (GdkXEvent * xev, GdkEvent * event)
+{
+ XEvent *xevent = (XEvent *) xev;
+ xkl_engine_filter_events (xkl_engine, xevent);
+ return GDK_FILTER_CONTINUE;
+}
+
+static guint
+register_config_callback (MateConfClient * client,
+ const char *path, MateConfClientNotifyFunc func)
+{
+ mateconf_client_add_dir (client, path, MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+ return mateconf_client_notify_add (client, path, func, NULL, NULL,
+ NULL);
+}
+
+/* When new Keyboard is plugged in - reload the settings */
+static void
+gsd_keyboard_new_device (XklEngine * engine)
+{
+ apply_desktop_settings ();
+ apply_xkb_settings ();
+}
+
+static void
+gsd_keyboard_update_indicator_icons ()
+{
+ Bool state;
+ int new_state, i;
+ Display *display = GDK_DISPLAY ();
+ XkbGetNamedIndicator (display, caps_lock, NULL, &state,
+ NULL, NULL);
+ new_state = state ? 1 : 0;
+ XkbGetNamedIndicator (display, num_lock, NULL, &state, NULL, NULL);
+ new_state <<= 1;
+ new_state |= (state ? 1 : 0);
+ XkbGetNamedIndicator (display, scroll_lock, NULL, &state,
+ NULL, NULL);
+ new_state <<= 1;
+ new_state |= (state ? 1 : 0);
+ xkl_debug (160, "Indicators state: %d\n", new_state);
+
+
+ for (i = sizeof (indicator_icons) / sizeof (indicator_icons[0]);
+ --i >= 0;) {
+ gtk_status_icon_set_from_icon_name (indicator_icons[i],
+ (new_state & (1 << i))
+ ?
+ indicator_on_icon_names
+ [i] :
+ indicator_off_icon_names
+ [i]);
+ }
+}
+
+static void
+gsd_keyboard_state_changed (XklEngine * engine, XklEngineStateChange type,
+ gint new_group, gboolean restore)
+{
+ xkl_debug (160,
+ "State changed: type %d, new group: %d, restore: %d.\n",
+ type, new_group, restore);
+ if (type == INDICATORS_CHANGED) {
+ gsd_keyboard_update_indicator_icons ();
+ }
+}
+
+void
+gsd_keyboard_xkb_init (MateConfClient * client,
+ GsdKeyboardManager * kbd_manager)
+{
+ int i;
+ Display *display = GDK_DISPLAY ();
+ mate_settings_profile_start (NULL);
+
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ DATADIR G_DIR_SEPARATOR_S
+ "icons");
+
+ caps_lock = XInternAtom (display, "Caps Lock", False);
+ num_lock = XInternAtom (display, "Num Lock", False);
+ scroll_lock = XInternAtom (display, "Scroll Lock", False);
+
+ for (i = sizeof (indicator_icons) / sizeof (indicator_icons[0]);
+ --i >= 0;) {
+ indicator_icons[i] =
+ gtk_status_icon_new_from_icon_name
+ (indicator_off_icon_names[i]);
+ }
+
+ gsd_keyboard_update_indicator_icons ();
+
+#ifdef GSDKX
+ xkl_set_debug_level (200);
+ logfile = fopen ("/tmp/gsdkx.log", "a");
+ xkl_set_log_appender (gsd_keyboard_log_appender);
+#endif
+ manager = kbd_manager;
+ mate_settings_profile_start ("xkl_engine_get_instance");
+ xkl_engine = xkl_engine_get_instance (display);
+ mate_settings_profile_end ("xkl_engine_get_instance");
+ if (xkl_engine) {
+ inited_ok = TRUE;
+
+ mdm_keyboard_layout = g_getenv ("MDM_KEYBOARD_LAYOUT");
+
+ matekbd_desktop_config_init (&current_config,
+ client, xkl_engine);
+ matekbd_keyboard_config_init (&current_kbd_config,
+ client, xkl_engine);
+ xkl_engine_backup_names_prop (xkl_engine);
+ gsd_keyboard_xkb_analyze_sysconfig ();
+ mate_settings_profile_start
+ ("gsd_keyboard_xkb_chk_lcl_xmm");
+ gsd_keyboard_xkb_chk_lcl_xmm ();
+ mate_settings_profile_end
+ ("gsd_keyboard_xkb_chk_lcl_xmm");
+
+ notify_desktop =
+ register_config_callback (client,
+ MATEKBD_DESKTOP_CONFIG_DIR,
+ (MateConfClientNotifyFunc)
+ apply_desktop_settings);
+
+ notify_keyboard =
+ register_config_callback (client,
+ MATEKBD_KEYBOARD_CONFIG_DIR,
+ (MateConfClientNotifyFunc)
+ apply_xkb_settings);
+
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ gsd_keyboard_xkb_evt_filter, NULL);
+
+ if (xkl_engine_get_features (xkl_engine) &
+ XKLF_DEVICE_DISCOVERY)
+ g_signal_connect (xkl_engine, "X-new-device",
+ G_CALLBACK
+ (gsd_keyboard_new_device), NULL);
+ g_signal_connect (xkl_engine, "X-state-changed",
+ G_CALLBACK
+ (gsd_keyboard_state_changed), NULL);
+
+ mate_settings_profile_start ("xkl_engine_start_listen");
+ xkl_engine_start_listen (xkl_engine,
+ XKLL_MANAGE_LAYOUTS |
+ XKLL_MANAGE_WINDOW_STATES);
+ mate_settings_profile_end ("xkl_engine_start_listen");
+
+ mate_settings_profile_start ("apply_desktop_settings");
+ apply_desktop_settings ();
+ mate_settings_profile_end ("apply_desktop_settings");
+ mate_settings_profile_start ("apply_xkb_settings");
+ apply_xkb_settings ();
+ mate_settings_profile_end ("apply_xkb_settings");
+ }
+ preview_dialogs = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ mate_settings_profile_end (NULL);
+}
+
+void
+gsd_keyboard_xkb_shutdown (void)
+{
+ MateConfClient *client;
+ int i;
+
+ pa_callback = NULL;
+ pa_callback_user_data = NULL;
+ manager = NULL;
+
+ for (i = sizeof (indicator_icons) / sizeof (indicator_icons[0]);
+ --i >= 0;) {
+ g_object_unref (G_OBJECT (indicator_icons[i]));
+ indicator_icons[i] = NULL;
+ }
+
+ g_hash_table_destroy (preview_dialogs);
+
+ if (!inited_ok)
+ return;
+
+ xkl_engine_stop_listen (xkl_engine,
+ XKLL_MANAGE_LAYOUTS |
+ XKLL_MANAGE_WINDOW_STATES);
+
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ gsd_keyboard_xkb_evt_filter, NULL);
+
+ client = mateconf_client_get_default ();
+
+ if (notify_desktop != 0) {
+ mateconf_client_remove_dir (client, MATEKBD_DESKTOP_CONFIG_DIR,
+ NULL);
+ mateconf_client_notify_remove (client, notify_desktop);
+ notify_desktop = 0;
+ }
+
+ if (notify_keyboard != 0) {
+ mateconf_client_remove_dir (client, MATEKBD_KEYBOARD_CONFIG_DIR,
+ NULL);
+ mateconf_client_notify_remove (client, notify_keyboard);
+ notify_keyboard = 0;
+ }
+
+ if (xkl_registry) {
+ g_object_unref (xkl_registry);
+ }
+
+ g_object_unref (client);
+ g_object_unref (xkl_engine);
+
+ xkl_engine = NULL;
+ inited_ok = FALSE;
+}
diff --git a/plugins/keyboard/gsd-keyboard-xkb.h b/plugins/keyboard/gsd-keyboard-xkb.h
new file mode 100644
index 0000000..12b2846
--- /dev/null
+++ b/plugins/keyboard/gsd-keyboard-xkb.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * mate-settings-keyboard-xkb.h
+ *
+ * Copyright (C) 2001 Udaltsoft
+ *
+ * Written by Sergey V. Oudaltsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GSD_KEYBOARD_XKB_H
+#define __GSD_KEYBOARD_XKB_H
+
+#include <mateconf/mateconf.h>
+#include <mateconf/mateconf-client.h>
+
+#include <libxklavier/xklavier.h>
+#include "gsd-keyboard-manager.h"
+
+void gsd_keyboard_xkb_init (MateConfClient *client, GsdKeyboardManager *manager);
+void gsd_keyboard_xkb_shutdown (void);
+
+typedef void (*PostActivationCallback) (void *userData);
+
+void
+gsd_keyboard_xkb_set_post_activation_callback (PostActivationCallback fun,
+ void *userData);
+
+#endif
diff --git a/plugins/keyboard/gsd-xmodmap.c b/plugins/keyboard/gsd-xmodmap.c
new file mode 100644
index 0000000..b9ffc9c
--- /dev/null
+++ b/plugins/keyboard/gsd-xmodmap.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2005 Novell Inc.
+ *
+ * Written by Shakti Sen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include "gsd-xmodmap.h"
+
+static const char DISABLE_XMM_WARNING_KEY[] =
+ "/desktop/mate/peripherals/keyboard/disable_xmm_and_xkb_warning";
+
+static const char LOADED_FILES_KEY[] =
+ "/desktop/mate/peripherals/keyboard/general/update_handlers";
+
+
+static void
+check_button_callback (GtkWidget *chk_button,
+ gpointer data)
+{
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ DISABLE_XMM_WARNING_KEY,
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (chk_button)),
+ NULL);
+
+ g_object_unref (client);
+}
+
+void
+gsd_load_modmap_files (void)
+{
+ MateConfClient *client;
+ GSList *tmp;
+ GSList *loaded_file_list;
+
+ client = mateconf_client_get_default ();
+
+ loaded_file_list = mateconf_client_get_list (client, LOADED_FILES_KEY, MATECONF_VALUE_STRING, NULL);
+
+ for (tmp = loaded_file_list; tmp != NULL; tmp = tmp->next) {
+ gchar *file;
+ gchar *command;
+
+ file = g_build_filename (g_get_home_dir (), (gchar *) tmp->data, NULL);
+ command = g_strconcat ("xmodmap ", file, NULL);
+ g_free (file);
+
+ g_spawn_command_line_async (command, NULL);
+
+ g_free (command);
+ g_free (tmp->data);
+ }
+
+ g_slist_free (loaded_file_list);
+ g_object_unref (client);
+}
+
+static void
+response_callback (GtkWidget *dialog,
+ int id,
+ void *data)
+{
+ if (id == GTK_RESPONSE_OK) {
+ GtkWidget *chk_button = g_object_get_data (G_OBJECT (dialog), "check_button");
+ check_button_callback (chk_button, NULL);
+ gsd_load_modmap_files ();
+ }
+ gtk_widget_destroy (dialog);
+}
+
+static void
+get_selected_files_func (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GSList **list = data;
+ gchar *filename;
+
+ filename = NULL;
+ gtk_tree_model_get (model,
+ iter,
+ 0,
+ &filename,
+ -1);
+
+ *list = g_slist_prepend (*list, filename);
+}
+
+static GSList*
+remove_string_from_list (GSList *list,
+ const char *str)
+{
+ GSList *tmp;
+
+ for (tmp = list; tmp != NULL; tmp = tmp->next) {
+ if (strcmp (tmp->data, str) == 0) {
+ g_free (tmp->data);
+ list = g_slist_delete_link (list, tmp);
+ break;
+ }
+ }
+
+ return list;
+}
+
+
+static void
+remove_button_clicked_callback (GtkWidget *button,
+ void *data)
+{
+ GtkWidget *dialog;
+ GtkListStore *tree = NULL;
+ GtkTreeSelection *selection;
+ GtkWidget *treeview;
+ MateConfClient *client;
+ GSList *filenames = NULL;
+ GSList *tmp = NULL;
+ GSList *loaded_files = NULL;
+
+ dialog = data;
+
+ treeview = g_object_get_data (G_OBJECT (dialog), "treeview1");
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ gtk_tree_selection_selected_foreach (selection,
+ get_selected_files_func,
+ &filenames);
+
+ if (!filenames)
+ return;
+
+ /* Remove the selected file */
+
+ client = mateconf_client_get_default ();
+
+ loaded_files = mateconf_client_get_list (client,
+ LOADED_FILES_KEY,
+ MATECONF_VALUE_STRING,
+ NULL);
+ loaded_files = remove_string_from_list (loaded_files, (char *)filenames->data);
+
+ mateconf_client_set_list (client,
+ LOADED_FILES_KEY,
+ MATECONF_VALUE_STRING,
+ loaded_files,
+ NULL);
+ g_object_unref (client);
+
+ tree = g_object_get_data (G_OBJECT (dialog), "tree");
+
+ gtk_list_store_clear (tree);
+ for (tmp = loaded_files; tmp != NULL; tmp = tmp->next) {
+ GtkTreeIter iter;
+ gtk_list_store_append (tree, &iter);
+ gtk_list_store_set (tree, &iter,
+ 0,
+ tmp->data,
+ -1);
+ }
+
+ g_slist_foreach (loaded_files, (GFunc) g_free, NULL);
+ g_slist_free (loaded_files);
+}
+
+static void
+load_button_clicked_callback (GtkWidget *button,
+ void *data)
+{
+ GtkWidget *dialog;
+ GtkListStore *tree = NULL;
+ GtkTreeSelection *selection;
+ GtkWidget *treeview;
+ GSList *filenames = NULL;
+ GSList *tmp = NULL;
+ GSList *loaded_files = NULL;
+ MateConfClient *client;
+
+ dialog = data;
+
+ treeview = g_object_get_data (G_OBJECT (dialog),
+ "loaded-treeview");
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ gtk_tree_selection_selected_foreach (selection,
+ get_selected_files_func,
+ &filenames);
+
+ if (!filenames)
+ return;
+
+ /* Add the files to left-tree-view */
+ client = mateconf_client_get_default ();
+
+ loaded_files = mateconf_client_get_list (client,
+ LOADED_FILES_KEY,
+ MATECONF_VALUE_STRING,
+ NULL);
+
+ if (g_slist_find_custom (loaded_files, filenames->data, (GCompareFunc) strcmp)) {
+ g_free (filenames->data);
+ g_slist_free (filenames);
+ goto out;
+ }
+
+ loaded_files = g_slist_append (loaded_files, filenames->data);
+ mateconf_client_set_list (client,
+ LOADED_FILES_KEY,
+ MATECONF_VALUE_STRING,
+ loaded_files,
+ NULL);
+
+
+ tree = g_object_get_data (G_OBJECT (dialog), "tree");
+
+ gtk_list_store_clear (tree);
+ for (tmp = loaded_files; tmp != NULL; tmp = tmp->next) {
+ GtkTreeIter iter;
+ gtk_list_store_append (tree, &iter);
+ gtk_list_store_set (tree, &iter,
+ 0,
+ tmp->data,
+ -1);
+ }
+
+out:
+ g_object_unref (client);
+ g_slist_foreach (loaded_files, (GFunc) g_free, NULL);
+ g_slist_free (loaded_files);
+}
+
+void
+gsd_modmap_dialog_call (void)
+{
+ GtkBuilder *builder;
+ guint res;
+ GError *error;
+ GtkWidget *load_dialog;
+ GtkListStore *tree;
+ GtkCellRenderer *cell_renderer;
+ GtkTreeIter parent_iter;
+ GtkTreeIter iter;
+ GtkTreeModel *sort_model;
+ GtkTreeSelection *selection;
+ GtkWidget *treeview;
+ GtkWidget *treeview1;
+ GtkTreeViewColumn *column;
+ GtkWidget *add_button;
+ GtkWidget *remove_button;
+ GtkWidget *chk_button;
+ GSList *tmp;
+ GDir *homeDir;
+ GSList *loaded_files;
+ const char *fname;
+ MateConfClient *client;
+
+ homeDir = g_dir_open (g_get_home_dir (), 0, NULL);
+ if (homeDir == NULL)
+ return;
+
+ error = NULL;
+ builder = gtk_builder_new ();
+ res = gtk_builder_add_from_file (builder,
+ DATADIR "/modmap-dialog.ui",
+ &error);
+
+ if (res == 0) {
+ g_warning ("Could not load UI file: %s", error->message);
+ g_error_free (error);
+ g_object_unref (builder);
+ g_dir_close (homeDir);
+ return;
+ }
+
+ load_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "dialog1"));
+ gtk_window_set_modal (GTK_WINDOW (load_dialog), TRUE);
+ g_signal_connect (load_dialog,
+ "response",
+ G_CALLBACK (response_callback),
+ builder);
+ add_button = GTK_WIDGET (gtk_builder_get_object (builder, "button7"));
+ g_signal_connect (add_button,
+ "clicked",
+ G_CALLBACK (load_button_clicked_callback),
+ load_dialog);
+ remove_button = GTK_WIDGET (gtk_builder_get_object (builder,
+ "button6"));
+ g_signal_connect (remove_button,
+ "clicked",
+ G_CALLBACK (remove_button_clicked_callback),
+ load_dialog);
+ chk_button = GTK_WIDGET (gtk_builder_get_object (builder,
+ "checkbutton1"));
+ g_signal_connect (chk_button,
+ "toggled",
+ G_CALLBACK (check_button_callback),
+ NULL);
+ g_object_set_data (G_OBJECT (load_dialog), "check_button", chk_button);
+ treeview = GTK_WIDGET (gtk_builder_get_object (builder, "treeview1"));
+ g_object_set_data (G_OBJECT (load_dialog), "treeview1", treeview);
+ treeview = GTK_WIDGET (gtk_builder_get_object (builder, "treeview2"));
+ g_object_set_data (G_OBJECT (load_dialog), "loaded-treeview", treeview);
+ tree = gtk_list_store_new (1, G_TYPE_STRING);
+ cell_renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("modmap",
+ cell_renderer,
+ "text", 0,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+ gtk_tree_view_column_set_sort_column_id (column, 0);
+
+ /* Add the data */
+ while ((fname = g_dir_read_name (homeDir)) != NULL) {
+ if (g_strrstr (fname, "modmap")) {
+ gtk_list_store_append (tree, &parent_iter);
+ gtk_list_store_set (tree, &parent_iter,
+ 0,
+ fname,
+ -1);
+ }
+ }
+ sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
+ 0,
+ GTK_SORT_ASCENDING);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), sort_model);
+ g_object_unref (G_OBJECT (tree));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
+ GTK_SELECTION_MULTIPLE);
+ gtk_widget_show (load_dialog);
+
+ g_dir_close (homeDir);
+
+ /* Left treeview */
+ treeview1 = GTK_WIDGET (gtk_builder_get_object (builder, "treeview1"));
+ tree = gtk_list_store_new (1, G_TYPE_STRING);
+ cell_renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("modmap",
+ cell_renderer,
+ "text", 0,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview1), column);
+ gtk_tree_view_column_set_sort_column_id (column, 0);
+
+ client = mateconf_client_get_default ();
+ loaded_files = mateconf_client_get_list (client, LOADED_FILES_KEY, MATECONF_VALUE_STRING, NULL);
+ g_object_unref (client);
+
+ /* Add the data */
+ for (tmp = loaded_files; tmp != NULL; tmp = tmp->next) {
+ gtk_list_store_append (tree, &iter);
+ gtk_list_store_set (tree, &iter,
+ 0,
+ tmp->data,
+ -1);
+ }
+
+ g_slist_foreach (loaded_files, (GFunc) g_free, NULL);
+ g_slist_free (loaded_files);
+
+ sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
+ 0,
+ GTK_SORT_ASCENDING);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (treeview1), sort_model);
+ g_object_unref (G_OBJECT (tree));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview1));
+ gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
+ GTK_SELECTION_MULTIPLE);
+ g_object_set_data (G_OBJECT (load_dialog), "tree", tree);
+ g_object_unref (builder);
+}
diff --git a/plugins/keyboard/gsd-xmodmap.h b/plugins/keyboard/gsd-xmodmap.h
new file mode 100644
index 0000000..7cfff74
--- /dev/null
+++ b/plugins/keyboard/gsd-xmodmap.h
@@ -0,0 +1,29 @@
+/* mate-settings-xmodmap.h
+ *
+ * Copyright © 2005 Novell Inc.
+ *
+ * Written by Shakti Sen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef XMODMAP_H
+#define XMODMAP_H
+
+void gsd_load_modmap_files (void);
+void gsd_modmap_dialog_call (void);
+
+#endif
diff --git a/plugins/keyboard/kbd-capslock-off.png b/plugins/keyboard/kbd-capslock-off.png
new file mode 100644
index 0000000..828cfa8
--- /dev/null
+++ b/plugins/keyboard/kbd-capslock-off.png
Binary files differ
diff --git a/plugins/keyboard/kbd-capslock-on.png b/plugins/keyboard/kbd-capslock-on.png
new file mode 100644
index 0000000..32ea0c9
--- /dev/null
+++ b/plugins/keyboard/kbd-capslock-on.png
Binary files differ
diff --git a/plugins/keyboard/kbd-numlock-off.png b/plugins/keyboard/kbd-numlock-off.png
new file mode 100644
index 0000000..21cac59
--- /dev/null
+++ b/plugins/keyboard/kbd-numlock-off.png
Binary files differ
diff --git a/plugins/keyboard/kbd-numlock-on.png b/plugins/keyboard/kbd-numlock-on.png
new file mode 100644
index 0000000..bd9b9fc
--- /dev/null
+++ b/plugins/keyboard/kbd-numlock-on.png
Binary files differ
diff --git a/plugins/keyboard/kbd-scrolllock-off.png b/plugins/keyboard/kbd-scrolllock-off.png
new file mode 100644
index 0000000..2ff8748
--- /dev/null
+++ b/plugins/keyboard/kbd-scrolllock-off.png
Binary files differ
diff --git a/plugins/keyboard/kbd-scrolllock-on.png b/plugins/keyboard/kbd-scrolllock-on.png
new file mode 100644
index 0000000..77a4794
--- /dev/null
+++ b/plugins/keyboard/kbd-scrolllock-on.png
Binary files differ
diff --git a/plugins/keyboard/keyboard.mate-settings-plugin.in b/plugins/keyboard/keyboard.mate-settings-plugin.in
new file mode 100644
index 0000000..2ced59c
--- /dev/null
+++ b/plugins/keyboard/keyboard.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=keyboard
+IAge=0
+_Name=Keyboard
+_Description=Keyboard plugin
+Authors=
+Copyright=Copyright © 2007
+Website=
diff --git a/plugins/keyboard/modmap-dialog.ui b/plugins/keyboard/modmap-dialog.ui
new file mode 100644
index 0000000..12c34a6
--- /dev/null
+++ b/plugins/keyboard/modmap-dialog.ui
@@ -0,0 +1,273 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="dialog1">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Load modmap files</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox4">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox44">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label62">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Would you like to load the modmap files?</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox32">
+ <property name="visible">True</property>
+ <property name="border_width">12</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkVBox" id="vbox45">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label63">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Loaded files:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow7">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox46">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label64">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button7">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox33">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label66">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Load</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button6">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox47">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label65">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">A_vailable files:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow8">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton1">
+ <property name="label" translatable="yes">_Do not show this message again</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area3">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="helpbutton2">
+ <property name="label">gtk-help</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="okbutton1">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-11">helpbutton2</action-widget>
+ <action-widget response="-5">okbutton1</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/plugins/media-keys/Makefile.am b/plugins/media-keys/Makefile.am
new file mode 100644
index 0000000..d8bff08
--- /dev/null
+++ b/plugins/media-keys/Makefile.am
@@ -0,0 +1,207 @@
+icondir = $(datadir)/icons/mate
+context = actions
+
+NULL =
+
+SUBDIRS =
+plugin_LTLIBRARIES =
+
+if HAVE_PULSE
+SUBDIRS += cut-n-paste
+plugin_LTLIBRARIES += libmedia-keys.la
+endif
+
+BUILT_SOURCES = \
+ gsd-media-keys-manager-glue.h \
+ gsd-marshal.h \
+ gsd-marshal.c \
+ $(NULL)
+
+ICON_FILES = \
+ touchpad-disabled-16.png \
+ touchpad-enabled-16.png \
+ touchpad-disabled-22.png \
+ touchpad-enabled-22.png \
+ touchpad-disabled-24.png \
+ touchpad-enabled-24.png \
+ touchpad-disabled-32.png \
+ touchpad-enabled-32.png \
+ touchpad-disabled-48.png \
+ touchpad-enabled-48.png \
+ touchpad-disabled.svg \
+ touchpad-enabled.svg
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/16x16/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/22x22/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/24x24/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/32x32/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/scalable/$(context)
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-16.png $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-22.png $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-24.png $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-32.png $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled.svg $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-enabled.svg
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-16.png $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-22.png $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-24.png $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-32.png $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled.svg $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-disabled.svg
+
+uninstall-local:
+ rm -f $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-enabled.svg
+ rm -f $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-disabled.svg
+
+gsd-media-keys-manager-glue.h: gsd-media-keys-manager.xml Makefile
+ dbus-binding-tool --prefix=gsd_media_keys_manager --mode=glib-server $< > xgen-$(@F) \
+ && ( cmp -s xgen-$(@F) $@ || cp xgen-$(@F) $@ ) \
+ && rm -f xgen-$(@F)
+
+gsd-marshal.c: gsd-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gsd_marshal $< --header --body --internal > $@
+
+gsd-marshal.h: gsd-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gsd_marshal $< --header --internal > $@
+
+libmedia_keys_la_SOURCES = \
+ gsd-media-keys-plugin.h \
+ gsd-media-keys-plugin.c \
+ gsd-media-keys-manager.h \
+ gsd-media-keys-manager.c \
+ gsd-media-keys-window.h \
+ gsd-media-keys-window.c \
+ acme.h \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+libmedia_keys_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -I$(top_srcdir)/plugins/media-keys/cut-n-paste \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libmedia_keys_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libmedia_keys_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libmedia_keys_la_LIBADD = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ -lm
+
+plugin_in_files = \
+ media-keys.mate-settings-plugin.in
+
+if HAVE_PULSE
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+endif
+
+noinst_PROGRAMS = \
+ test-media-keys \
+ test-media-window \
+ $(NULL)
+
+test_media_window_SOURCES = \
+ gsd-media-keys-window.c \
+ gsd-media-keys-window.h \
+ test-media-window.c \
+ $(NULL)
+
+test_media_window_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -I$(top_srcdir)/plugins/media-keys/cut-n-paste \
+ -DDATADIR=\""$(datadir)"\" \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_media_window_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_media_window_LDADD = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(SETTINGS_DAEMON_LIBS) \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(GST_LIBS) \
+ -lm
+
+test_media_keys_SOURCES = \
+ gsd-media-keys-manager.c \
+ gsd-media-keys-manager.h \
+ gsd-media-keys-window.h \
+ gsd-media-keys-window.c \
+ test-media-keys.c \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+test_media_keys_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -I$(top_srcdir)/plugins/media-keys/cut-n-paste \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_media_keys_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_media_keys_LDADD = \
+ $(top_builddir)/mate-settings-daemon/libgsd-profile.la \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(SETTINGS_DAEMON_LIBS) \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(GST_LIBS) \
+ -lm
+
+if HAVE_PULSE
+test_media_keys_LDADD += $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la
+endif
+
+gtkbuilderdir = $(pkgdatadir)
+gtkbuilder_DATA = \
+ acme.ui \
+ $(NULL)
+
+DIST_SUBDIRS = cut-n-paste
+
+EXTRA_DIST = \
+ gsd-media-keys-manager.xml \
+ gsd-marshal.list \
+ $(plugin_in_files) \
+ $(gtkbuilder_DATA) \
+ $(pixmaps_DATA) \
+ touchpad-enabled-template.svg \
+ touchpad-disabled-template.svg \
+ $(ICON_FILES)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/media-keys/Makefile.in b/plugins/media-keys/Makefile.in
new file mode 100644
index 0000000..3a0cec7
--- /dev/null
+++ b/plugins/media-keys/Makefile.in
@@ -0,0 +1,1159 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_PULSE_TRUE@am__append_1 = cut-n-paste
+@HAVE_PULSE_TRUE@am__append_2 = libmedia-keys.la
+noinst_PROGRAMS = test-media-keys$(EXEEXT) test-media-window$(EXEEXT) \
+ $(am__EXEEXT_1)
+@HAVE_PULSE_TRUE@am__append_3 = $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la
+subdir = plugins/media-keys
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" \
+ "$(DESTDIR)$(gtkbuilderdir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libmedia_keys_la_DEPENDENCIES = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__objects_1 =
+am__objects_2 = libmedia_keys_la-gsd-marshal.lo $(am__objects_1)
+am_libmedia_keys_la_OBJECTS = \
+ libmedia_keys_la-gsd-media-keys-plugin.lo \
+ libmedia_keys_la-gsd-media-keys-manager.lo \
+ libmedia_keys_la-gsd-media-keys-window.lo $(am__objects_2) \
+ $(am__objects_1)
+libmedia_keys_la_OBJECTS = $(am_libmedia_keys_la_OBJECTS)
+libmedia_keys_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmedia_keys_la_CFLAGS) \
+ $(CFLAGS) $(libmedia_keys_la_LDFLAGS) $(LDFLAGS) -o $@
+@HAVE_PULSE_TRUE@am_libmedia_keys_la_rpath = -rpath $(plugindir)
+am__EXEEXT_1 =
+PROGRAMS = $(noinst_PROGRAMS)
+am__objects_3 = test_media_keys-gsd-marshal.$(OBJEXT) $(am__objects_1)
+am_test_media_keys_OBJECTS = \
+ test_media_keys-gsd-media-keys-manager.$(OBJEXT) \
+ test_media_keys-gsd-media-keys-window.$(OBJEXT) \
+ test_media_keys-test-media-keys.$(OBJEXT) $(am__objects_3) \
+ $(am__objects_1)
+test_media_keys_OBJECTS = $(am_test_media_keys_OBJECTS)
+test_media_keys_DEPENDENCIES = \
+ $(top_builddir)/mate-settings-daemon/libgsd-profile.la \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__append_3)
+test_media_keys_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_media_keys_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_test_media_window_OBJECTS = \
+ test_media_window-gsd-media-keys-window.$(OBJEXT) \
+ test_media_window-test-media-window.$(OBJEXT) $(am__objects_1)
+test_media_window_OBJECTS = $(am_test_media_window_OBJECTS)
+test_media_window_DEPENDENCIES = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+test_media_window_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(test_media_window_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libmedia_keys_la_SOURCES) $(test_media_keys_SOURCES) \
+ $(test_media_window_SOURCES)
+DIST_SOURCES = $(libmedia_keys_la_SOURCES) $(test_media_keys_SOURCES) \
+ $(test_media_window_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+DATA = $(gtkbuilder_DATA) $(plugin_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+icondir = $(datadir)/icons/mate
+context = actions
+NULL =
+SUBDIRS = $(am__append_1)
+plugin_LTLIBRARIES = $(am__append_2)
+BUILT_SOURCES = \
+ gsd-media-keys-manager-glue.h \
+ gsd-marshal.h \
+ gsd-marshal.c \
+ $(NULL)
+
+ICON_FILES = \
+ touchpad-disabled-16.png \
+ touchpad-enabled-16.png \
+ touchpad-disabled-22.png \
+ touchpad-enabled-22.png \
+ touchpad-disabled-24.png \
+ touchpad-enabled-24.png \
+ touchpad-disabled-32.png \
+ touchpad-enabled-32.png \
+ touchpad-disabled-48.png \
+ touchpad-enabled-48.png \
+ touchpad-disabled.svg \
+ touchpad-enabled.svg
+
+libmedia_keys_la_SOURCES = \
+ gsd-media-keys-plugin.h \
+ gsd-media-keys-plugin.c \
+ gsd-media-keys-manager.h \
+ gsd-media-keys-manager.c \
+ gsd-media-keys-window.h \
+ gsd-media-keys-window.c \
+ acme.h \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+libmedia_keys_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -I$(top_srcdir)/plugins/media-keys/cut-n-paste \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libmedia_keys_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libmedia_keys_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libmedia_keys_la_LIBADD = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ -lm
+
+plugin_in_files = \
+ media-keys.mate-settings-plugin.in
+
+@HAVE_PULSE_TRUE@plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+test_media_window_SOURCES = \
+ gsd-media-keys-window.c \
+ gsd-media-keys-window.h \
+ test-media-window.c \
+ $(NULL)
+
+test_media_window_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -I$(top_srcdir)/plugins/media-keys/cut-n-paste \
+ -DDATADIR=\""$(datadir)"\" \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_media_window_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_media_window_LDADD = \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(SETTINGS_DAEMON_LIBS) \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) \
+ $(GST_LIBS) \
+ -lm
+
+test_media_keys_SOURCES = \
+ gsd-media-keys-manager.c \
+ gsd-media-keys-manager.h \
+ gsd-media-keys-window.h \
+ gsd-media-keys-window.c \
+ test-media-keys.c \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+test_media_keys_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -I$(top_srcdir)/plugins/common \
+ -I$(top_srcdir)/plugins/media-keys/cut-n-paste \
+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+test_media_keys_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+test_media_keys_LDADD = \
+ $(top_builddir)/mate-settings-daemon/libgsd-profile.la \
+ $(top_builddir)/plugins/common/libcommon.la \
+ $(SETTINGS_DAEMON_LIBS) $(SETTINGS_PLUGIN_LIBS) \
+ $(XF86MISC_LIBS) $(GST_LIBS) -lm $(am__append_3)
+gtkbuilderdir = $(pkgdatadir)
+gtkbuilder_DATA = \
+ acme.ui \
+ $(NULL)
+
+DIST_SUBDIRS = cut-n-paste
+EXTRA_DIST = \
+ gsd-media-keys-manager.xml \
+ gsd-marshal.list \
+ $(plugin_in_files) \
+ $(gtkbuilder_DATA) \
+ $(pixmaps_DATA) \
+ touchpad-enabled-template.svg \
+ touchpad-disabled-template.svg \
+ $(ICON_FILES)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/media-keys/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/media-keys/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libmedia-keys.la: $(libmedia_keys_la_OBJECTS) $(libmedia_keys_la_DEPENDENCIES)
+ $(libmedia_keys_la_LINK) $(am_libmedia_keys_la_rpath) $(libmedia_keys_la_OBJECTS) $(libmedia_keys_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+test-media-keys$(EXEEXT): $(test_media_keys_OBJECTS) $(test_media_keys_DEPENDENCIES)
+ @rm -f test-media-keys$(EXEEXT)
+ $(test_media_keys_LINK) $(test_media_keys_OBJECTS) $(test_media_keys_LDADD) $(LIBS)
+test-media-window$(EXEEXT): $(test_media_window_OBJECTS) $(test_media_window_DEPENDENCIES)
+ @rm -f test-media-window$(EXEEXT)
+ $(test_media_window_LINK) $(test_media_window_OBJECTS) $(test_media_window_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmedia_keys_la-gsd-marshal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmedia_keys_la-gsd-media-keys-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmedia_keys_la-gsd-media-keys-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmedia_keys_la-gsd-media-keys-window.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_media_keys-gsd-marshal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_media_keys-gsd-media-keys-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_media_keys-gsd-media-keys-window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_media_keys-test-media-keys.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_media_window-gsd-media-keys-window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_media_window-test-media-window.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libmedia_keys_la-gsd-media-keys-plugin.lo: gsd-media-keys-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -MT libmedia_keys_la-gsd-media-keys-plugin.lo -MD -MP -MF $(DEPDIR)/libmedia_keys_la-gsd-media-keys-plugin.Tpo -c -o libmedia_keys_la-gsd-media-keys-plugin.lo `test -f 'gsd-media-keys-plugin.c' || echo '$(srcdir)/'`gsd-media-keys-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmedia_keys_la-gsd-media-keys-plugin.Tpo $(DEPDIR)/libmedia_keys_la-gsd-media-keys-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-plugin.c' object='libmedia_keys_la-gsd-media-keys-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -c -o libmedia_keys_la-gsd-media-keys-plugin.lo `test -f 'gsd-media-keys-plugin.c' || echo '$(srcdir)/'`gsd-media-keys-plugin.c
+
+libmedia_keys_la-gsd-media-keys-manager.lo: gsd-media-keys-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -MT libmedia_keys_la-gsd-media-keys-manager.lo -MD -MP -MF $(DEPDIR)/libmedia_keys_la-gsd-media-keys-manager.Tpo -c -o libmedia_keys_la-gsd-media-keys-manager.lo `test -f 'gsd-media-keys-manager.c' || echo '$(srcdir)/'`gsd-media-keys-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmedia_keys_la-gsd-media-keys-manager.Tpo $(DEPDIR)/libmedia_keys_la-gsd-media-keys-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-manager.c' object='libmedia_keys_la-gsd-media-keys-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -c -o libmedia_keys_la-gsd-media-keys-manager.lo `test -f 'gsd-media-keys-manager.c' || echo '$(srcdir)/'`gsd-media-keys-manager.c
+
+libmedia_keys_la-gsd-media-keys-window.lo: gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -MT libmedia_keys_la-gsd-media-keys-window.lo -MD -MP -MF $(DEPDIR)/libmedia_keys_la-gsd-media-keys-window.Tpo -c -o libmedia_keys_la-gsd-media-keys-window.lo `test -f 'gsd-media-keys-window.c' || echo '$(srcdir)/'`gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmedia_keys_la-gsd-media-keys-window.Tpo $(DEPDIR)/libmedia_keys_la-gsd-media-keys-window.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-window.c' object='libmedia_keys_la-gsd-media-keys-window.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -c -o libmedia_keys_la-gsd-media-keys-window.lo `test -f 'gsd-media-keys-window.c' || echo '$(srcdir)/'`gsd-media-keys-window.c
+
+libmedia_keys_la-gsd-marshal.lo: gsd-marshal.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -MT libmedia_keys_la-gsd-marshal.lo -MD -MP -MF $(DEPDIR)/libmedia_keys_la-gsd-marshal.Tpo -c -o libmedia_keys_la-gsd-marshal.lo `test -f 'gsd-marshal.c' || echo '$(srcdir)/'`gsd-marshal.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmedia_keys_la-gsd-marshal.Tpo $(DEPDIR)/libmedia_keys_la-gsd-marshal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-marshal.c' object='libmedia_keys_la-gsd-marshal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmedia_keys_la_CPPFLAGS) $(CPPFLAGS) $(libmedia_keys_la_CFLAGS) $(CFLAGS) -c -o libmedia_keys_la-gsd-marshal.lo `test -f 'gsd-marshal.c' || echo '$(srcdir)/'`gsd-marshal.c
+
+test_media_keys-gsd-media-keys-manager.o: gsd-media-keys-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-gsd-media-keys-manager.o -MD -MP -MF $(DEPDIR)/test_media_keys-gsd-media-keys-manager.Tpo -c -o test_media_keys-gsd-media-keys-manager.o `test -f 'gsd-media-keys-manager.c' || echo '$(srcdir)/'`gsd-media-keys-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-gsd-media-keys-manager.Tpo $(DEPDIR)/test_media_keys-gsd-media-keys-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-manager.c' object='test_media_keys-gsd-media-keys-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-gsd-media-keys-manager.o `test -f 'gsd-media-keys-manager.c' || echo '$(srcdir)/'`gsd-media-keys-manager.c
+
+test_media_keys-gsd-media-keys-manager.obj: gsd-media-keys-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-gsd-media-keys-manager.obj -MD -MP -MF $(DEPDIR)/test_media_keys-gsd-media-keys-manager.Tpo -c -o test_media_keys-gsd-media-keys-manager.obj `if test -f 'gsd-media-keys-manager.c'; then $(CYGPATH_W) 'gsd-media-keys-manager.c'; else $(CYGPATH_W) '$(srcdir)/gsd-media-keys-manager.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-gsd-media-keys-manager.Tpo $(DEPDIR)/test_media_keys-gsd-media-keys-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-manager.c' object='test_media_keys-gsd-media-keys-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-gsd-media-keys-manager.obj `if test -f 'gsd-media-keys-manager.c'; then $(CYGPATH_W) 'gsd-media-keys-manager.c'; else $(CYGPATH_W) '$(srcdir)/gsd-media-keys-manager.c'; fi`
+
+test_media_keys-gsd-media-keys-window.o: gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-gsd-media-keys-window.o -MD -MP -MF $(DEPDIR)/test_media_keys-gsd-media-keys-window.Tpo -c -o test_media_keys-gsd-media-keys-window.o `test -f 'gsd-media-keys-window.c' || echo '$(srcdir)/'`gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-gsd-media-keys-window.Tpo $(DEPDIR)/test_media_keys-gsd-media-keys-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-window.c' object='test_media_keys-gsd-media-keys-window.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-gsd-media-keys-window.o `test -f 'gsd-media-keys-window.c' || echo '$(srcdir)/'`gsd-media-keys-window.c
+
+test_media_keys-gsd-media-keys-window.obj: gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-gsd-media-keys-window.obj -MD -MP -MF $(DEPDIR)/test_media_keys-gsd-media-keys-window.Tpo -c -o test_media_keys-gsd-media-keys-window.obj `if test -f 'gsd-media-keys-window.c'; then $(CYGPATH_W) 'gsd-media-keys-window.c'; else $(CYGPATH_W) '$(srcdir)/gsd-media-keys-window.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-gsd-media-keys-window.Tpo $(DEPDIR)/test_media_keys-gsd-media-keys-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-window.c' object='test_media_keys-gsd-media-keys-window.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-gsd-media-keys-window.obj `if test -f 'gsd-media-keys-window.c'; then $(CYGPATH_W) 'gsd-media-keys-window.c'; else $(CYGPATH_W) '$(srcdir)/gsd-media-keys-window.c'; fi`
+
+test_media_keys-test-media-keys.o: test-media-keys.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-test-media-keys.o -MD -MP -MF $(DEPDIR)/test_media_keys-test-media-keys.Tpo -c -o test_media_keys-test-media-keys.o `test -f 'test-media-keys.c' || echo '$(srcdir)/'`test-media-keys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-test-media-keys.Tpo $(DEPDIR)/test_media_keys-test-media-keys.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-media-keys.c' object='test_media_keys-test-media-keys.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-test-media-keys.o `test -f 'test-media-keys.c' || echo '$(srcdir)/'`test-media-keys.c
+
+test_media_keys-test-media-keys.obj: test-media-keys.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-test-media-keys.obj -MD -MP -MF $(DEPDIR)/test_media_keys-test-media-keys.Tpo -c -o test_media_keys-test-media-keys.obj `if test -f 'test-media-keys.c'; then $(CYGPATH_W) 'test-media-keys.c'; else $(CYGPATH_W) '$(srcdir)/test-media-keys.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-test-media-keys.Tpo $(DEPDIR)/test_media_keys-test-media-keys.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-media-keys.c' object='test_media_keys-test-media-keys.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-test-media-keys.obj `if test -f 'test-media-keys.c'; then $(CYGPATH_W) 'test-media-keys.c'; else $(CYGPATH_W) '$(srcdir)/test-media-keys.c'; fi`
+
+test_media_keys-gsd-marshal.o: gsd-marshal.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-gsd-marshal.o -MD -MP -MF $(DEPDIR)/test_media_keys-gsd-marshal.Tpo -c -o test_media_keys-gsd-marshal.o `test -f 'gsd-marshal.c' || echo '$(srcdir)/'`gsd-marshal.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-gsd-marshal.Tpo $(DEPDIR)/test_media_keys-gsd-marshal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-marshal.c' object='test_media_keys-gsd-marshal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-gsd-marshal.o `test -f 'gsd-marshal.c' || echo '$(srcdir)/'`gsd-marshal.c
+
+test_media_keys-gsd-marshal.obj: gsd-marshal.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -MT test_media_keys-gsd-marshal.obj -MD -MP -MF $(DEPDIR)/test_media_keys-gsd-marshal.Tpo -c -o test_media_keys-gsd-marshal.obj `if test -f 'gsd-marshal.c'; then $(CYGPATH_W) 'gsd-marshal.c'; else $(CYGPATH_W) '$(srcdir)/gsd-marshal.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_keys-gsd-marshal.Tpo $(DEPDIR)/test_media_keys-gsd-marshal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-marshal.c' object='test_media_keys-gsd-marshal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_keys_CPPFLAGS) $(CPPFLAGS) $(test_media_keys_CFLAGS) $(CFLAGS) -c -o test_media_keys-gsd-marshal.obj `if test -f 'gsd-marshal.c'; then $(CYGPATH_W) 'gsd-marshal.c'; else $(CYGPATH_W) '$(srcdir)/gsd-marshal.c'; fi`
+
+test_media_window-gsd-media-keys-window.o: gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -MT test_media_window-gsd-media-keys-window.o -MD -MP -MF $(DEPDIR)/test_media_window-gsd-media-keys-window.Tpo -c -o test_media_window-gsd-media-keys-window.o `test -f 'gsd-media-keys-window.c' || echo '$(srcdir)/'`gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_window-gsd-media-keys-window.Tpo $(DEPDIR)/test_media_window-gsd-media-keys-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-window.c' object='test_media_window-gsd-media-keys-window.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -c -o test_media_window-gsd-media-keys-window.o `test -f 'gsd-media-keys-window.c' || echo '$(srcdir)/'`gsd-media-keys-window.c
+
+test_media_window-gsd-media-keys-window.obj: gsd-media-keys-window.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -MT test_media_window-gsd-media-keys-window.obj -MD -MP -MF $(DEPDIR)/test_media_window-gsd-media-keys-window.Tpo -c -o test_media_window-gsd-media-keys-window.obj `if test -f 'gsd-media-keys-window.c'; then $(CYGPATH_W) 'gsd-media-keys-window.c'; else $(CYGPATH_W) '$(srcdir)/gsd-media-keys-window.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_window-gsd-media-keys-window.Tpo $(DEPDIR)/test_media_window-gsd-media-keys-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-media-keys-window.c' object='test_media_window-gsd-media-keys-window.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -c -o test_media_window-gsd-media-keys-window.obj `if test -f 'gsd-media-keys-window.c'; then $(CYGPATH_W) 'gsd-media-keys-window.c'; else $(CYGPATH_W) '$(srcdir)/gsd-media-keys-window.c'; fi`
+
+test_media_window-test-media-window.o: test-media-window.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -MT test_media_window-test-media-window.o -MD -MP -MF $(DEPDIR)/test_media_window-test-media-window.Tpo -c -o test_media_window-test-media-window.o `test -f 'test-media-window.c' || echo '$(srcdir)/'`test-media-window.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_window-test-media-window.Tpo $(DEPDIR)/test_media_window-test-media-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-media-window.c' object='test_media_window-test-media-window.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -c -o test_media_window-test-media-window.o `test -f 'test-media-window.c' || echo '$(srcdir)/'`test-media-window.c
+
+test_media_window-test-media-window.obj: test-media-window.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -MT test_media_window-test-media-window.obj -MD -MP -MF $(DEPDIR)/test_media_window-test-media-window.Tpo -c -o test_media_window-test-media-window.obj `if test -f 'test-media-window.c'; then $(CYGPATH_W) 'test-media-window.c'; else $(CYGPATH_W) '$(srcdir)/test-media-window.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_media_window-test-media-window.Tpo $(DEPDIR)/test_media_window-test-media-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-media-window.c' object='test_media_window-test-media-window.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_media_window_CPPFLAGS) $(CPPFLAGS) $(test_media_window_CFLAGS) $(CFLAGS) -c -o test_media_window-test-media-window.obj `if test -f 'test-media-window.c'; then $(CYGPATH_W) 'test-media-window.c'; else $(CYGPATH_W) '$(srcdir)/test-media-window.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-gtkbuilderDATA: $(gtkbuilder_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(gtkbuilderdir)" || $(MKDIR_P) "$(DESTDIR)$(gtkbuilderdir)"
+ @list='$(gtkbuilder_DATA)'; test -n "$(gtkbuilderdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gtkbuilderdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(gtkbuilderdir)" || exit $$?; \
+ done
+
+uninstall-gtkbuilderDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gtkbuilder_DATA)'; test -n "$(gtkbuilderdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(gtkbuilderdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(gtkbuilderdir)" && rm -f $$files
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(gtkbuilderdir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-data-local install-gtkbuilderDATA \
+ install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-gtkbuilderDATA uninstall-local \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check \
+ ctags-recursive install install-am install-strip \
+ tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-noinstPROGRAMS clean-pluginLTLIBRARIES ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-data-local install-dvi install-dvi-am \
+ install-exec install-exec-am install-gtkbuilderDATA \
+ install-html install-html-am install-info install-info-am \
+ install-man install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-gtkbuilderDATA \
+ uninstall-local uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/16x16/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/22x22/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/24x24/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/32x32/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/scalable/$(context)
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-16.png $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-22.png $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-24.png $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled-32.png $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-enabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-enabled.svg $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-enabled.svg
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-16.png $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-22.png $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-24.png $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled-32.png $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-disabled.png
+ $(INSTALL_DATA) $(srcdir)/touchpad-disabled.svg $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-disabled.svg
+
+uninstall-local:
+ rm -f $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-enabled.png
+ rm -f $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-enabled.svg
+ rm -f $(DESTDIR)$(icondir)/16x16/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/22x22/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/24x24/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/32x32/$(context)/touchpad-disabled.png
+ rm -f $(DESTDIR)$(icondir)/scalable/$(context)/touchpad-disabled.svg
+
+gsd-media-keys-manager-glue.h: gsd-media-keys-manager.xml Makefile
+ dbus-binding-tool --prefix=gsd_media_keys_manager --mode=glib-server $< > xgen-$(@F) \
+ && ( cmp -s xgen-$(@F) $@ || cp xgen-$(@F) $@ ) \
+ && rm -f xgen-$(@F)
+
+gsd-marshal.c: gsd-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gsd_marshal $< --header --body --internal > $@
+
+gsd-marshal.h: gsd-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gsd_marshal $< --header --internal > $@
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/media-keys/acme.h b/plugins/media-keys/acme.h
new file mode 100644
index 0000000..66e13bc
--- /dev/null
+++ b/plugins/media-keys/acme.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2001 Bastien Nocera <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __ACME_H__
+#define __ACME_H__
+
+#include "gsd-keygrab.h"
+
+#define MATECONF_BINDING_DIR "/apps/mate_settings_daemon/keybindings"
+#define MATECONF_MISC_DIR "/apps/mate_settings_daemon"
+
+enum {
+ TOUCHPAD_KEY,
+ MUTE_KEY,
+ VOLUME_DOWN_KEY,
+ VOLUME_UP_KEY,
+ POWER_KEY,
+ EJECT_KEY,
+ HOME_KEY,
+ MEDIA_KEY,
+ CALCULATOR_KEY,
+ SEARCH_KEY,
+ EMAIL_KEY,
+ SCREENSAVER_KEY,
+ HELP_KEY,
+ WWW_KEY,
+ PLAY_KEY,
+ PAUSE_KEY,
+ STOP_KEY,
+ PREVIOUS_KEY,
+ NEXT_KEY,
+ HANDLED_KEYS
+};
+
+static struct {
+ int key_type;
+ const char *mateconf_key;
+ Key *key;
+} keys[HANDLED_KEYS] = {
+ { TOUCHPAD_KEY, MATECONF_BINDING_DIR "/touchpad", NULL },
+ { MUTE_KEY, MATECONF_BINDING_DIR "/volume_mute",NULL },
+ { VOLUME_DOWN_KEY, MATECONF_BINDING_DIR "/volume_down", NULL },
+ { VOLUME_UP_KEY, MATECONF_BINDING_DIR "/volume_up", NULL },
+ { POWER_KEY, MATECONF_BINDING_DIR "/power", NULL },
+ { EJECT_KEY, MATECONF_BINDING_DIR "/eject", NULL },
+ { HOME_KEY, MATECONF_BINDING_DIR "/home", NULL },
+ { MEDIA_KEY, MATECONF_BINDING_DIR "/media", NULL },
+ { CALCULATOR_KEY, MATECONF_BINDING_DIR "/calculator", NULL },
+ { SEARCH_KEY, MATECONF_BINDING_DIR "/search", NULL },
+ { EMAIL_KEY, MATECONF_BINDING_DIR "/email", NULL },
+ { SCREENSAVER_KEY, MATECONF_BINDING_DIR "/screensaver", NULL },
+ { HELP_KEY, MATECONF_BINDING_DIR "/help", NULL },
+ { WWW_KEY, MATECONF_BINDING_DIR "/www", NULL },
+ { PLAY_KEY, MATECONF_BINDING_DIR "/play", NULL },
+ { PAUSE_KEY, MATECONF_BINDING_DIR "/pause", NULL },
+ { STOP_KEY, MATECONF_BINDING_DIR "/stop", NULL },
+ { PREVIOUS_KEY, MATECONF_BINDING_DIR "/previous", NULL },
+ { NEXT_KEY, MATECONF_BINDING_DIR "/next", NULL },
+};
+
+#endif /* __ACME_H__ */
diff --git a/plugins/media-keys/acme.ui b/plugins/media-keys/acme.ui
new file mode 100644
index 0000000..e0457ed
--- /dev/null
+++ b/plugins/media-keys/acme.ui
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkWindow" id="dialog">
+ <child>
+ <object class="GtkVBox" id="acme_box">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="acme_image">
+ <property name="visible">True</property>
+ <property name="icon_name">audio-volume-high</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="acme_volume_progressbar">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/media-keys/cut-n-paste/Makefile.am b/plugins/media-keys/cut-n-paste/Makefile.am
new file mode 100644
index 0000000..bc59a10
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/Makefile.am
@@ -0,0 +1,39 @@
+NULL =
+
+noinst_LTLIBRARIES = libgvc.la
+
+INCLUDES = \
+ $(WARN_CFLAGS) \
+ $(VOLUME_CONTROL_CFLAGS) \
+ $(PULSE_CFLAGS) \
+ $(NULL)
+
+libgvc_la_LIBADD = \
+ $(VOLUME_CONTROL_LIBS) \
+ $(PULSE_LIBS) \
+ $(NULL)
+
+libgvc_la_SOURCES = \
+ gvc-mixer-stream.h \
+ gvc-mixer-stream.c \
+ gvc-channel-map.h \
+ gvc-channel-map.c \
+ gvc-mixer-card.c \
+ gvc-mixer-card.h \
+ gvc-mixer-sink.h \
+ gvc-mixer-sink.c \
+ gvc-mixer-source.h \
+ gvc-mixer-source.c \
+ gvc-mixer-sink-input.h \
+ gvc-mixer-sink-input.c \
+ gvc-mixer-source-output.h \
+ gvc-mixer-source-output.c \
+ gvc-mixer-event-role.h \
+ gvc-mixer-event-role.c \
+ gvc-mixer-control.h \
+ gvc-mixer-control.c \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
diff --git a/plugins/media-keys/cut-n-paste/Makefile.in b/plugins/media-keys/cut-n-paste/Makefile.in
new file mode 100644
index 0000000..9fbfa1c
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/Makefile.in
@@ -0,0 +1,586 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/media-keys/cut-n-paste
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgvc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libgvc_la_OBJECTS = gvc-mixer-stream.lo gvc-channel-map.lo \
+ gvc-mixer-card.lo gvc-mixer-sink.lo gvc-mixer-source.lo \
+ gvc-mixer-sink-input.lo gvc-mixer-source-output.lo \
+ gvc-mixer-event-role.lo gvc-mixer-control.lo $(am__objects_1)
+libgvc_la_OBJECTS = $(am_libgvc_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libgvc_la_SOURCES)
+DIST_SOURCES = $(libgvc_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+noinst_LTLIBRARIES = libgvc.la
+INCLUDES = \
+ $(WARN_CFLAGS) \
+ $(VOLUME_CONTROL_CFLAGS) \
+ $(PULSE_CFLAGS) \
+ $(NULL)
+
+libgvc_la_LIBADD = \
+ $(VOLUME_CONTROL_LIBS) \
+ $(PULSE_LIBS) \
+ $(NULL)
+
+libgvc_la_SOURCES = \
+ gvc-mixer-stream.h \
+ gvc-mixer-stream.c \
+ gvc-channel-map.h \
+ gvc-channel-map.c \
+ gvc-mixer-card.c \
+ gvc-mixer-card.h \
+ gvc-mixer-sink.h \
+ gvc-mixer-sink.c \
+ gvc-mixer-source.h \
+ gvc-mixer-source.c \
+ gvc-mixer-sink-input.h \
+ gvc-mixer-sink-input.c \
+ gvc-mixer-source-output.h \
+ gvc-mixer-source-output.c \
+ gvc-mixer-event-role.h \
+ gvc-mixer-event-role.c \
+ gvc-mixer-control.h \
+ gvc-mixer-control.c \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/media-keys/cut-n-paste/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/media-keys/cut-n-paste/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgvc.la: $(libgvc_la_OBJECTS) $(libgvc_la_DEPENDENCIES)
+ $(LINK) $(libgvc_la_OBJECTS) $(libgvc_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-channel-map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-card.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-control.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-event-role.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-sink-input.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-sink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-source-output.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-source.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvc-mixer-stream.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/media-keys/cut-n-paste/gvc-channel-map.c b/plugins/media-keys/cut-n-paste/gvc-channel-map.c
new file mode 100644
index 0000000..ea3e5af
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-channel-map.c
@@ -0,0 +1,292 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-channel-map.h"
+
+#define GVC_CHANNEL_MAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapPrivate))
+
+#ifndef PA_CHECK_VERSION
+#define PA_CHECK_VERSION(major,minor,micro) \
+ ((PA_MAJOR > (major)) || \
+ (PA_MAJOR == (major) && PA_MINOR > (minor)) || \
+ (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro)))
+#endif
+
+
+struct GvcChannelMapPrivate
+{
+ pa_channel_map pa_map;
+ gboolean pa_volume_is_set;
+ pa_cvolume pa_volume;
+ gdouble extern_volume[NUM_TYPES]; /* volume, balance, fade, lfe */
+ gboolean can_balance;
+ gboolean can_fade;
+ gboolean has_lfe;
+};
+
+enum {
+ VOLUME_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gvc_channel_map_class_init (GvcChannelMapClass *klass);
+static void gvc_channel_map_init (GvcChannelMap *channel_map);
+static void gvc_channel_map_finalize (GObject *object);
+
+G_DEFINE_TYPE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT)
+
+/* FIXME remove when we depend on a newer PA */
+static int
+gvc_pa_channel_map_has_position (const pa_channel_map *map, pa_channel_position_t p) {
+ unsigned c;
+
+ g_return_val_if_fail(pa_channel_map_valid(map), 0);
+ g_return_val_if_fail(p < PA_CHANNEL_POSITION_MAX, 0);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == p)
+ return 1;
+
+ return 0;
+}
+
+#if !PA_CHECK_VERSION(0,9,16)
+/* The PulseAudio master increase version only when tagged, so let's avoid clashing with pa_ namespace */
+#define pa_cvolume_get_position gvc_cvolume_get_position
+static pa_volume_t
+gvc_cvolume_get_position (pa_cvolume *cv, const pa_channel_map *map, pa_channel_position_t t) {
+ unsigned c;
+ pa_volume_t v = PA_VOLUME_MUTED;
+
+ g_assert(cv);
+ g_assert(map);
+
+ g_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), PA_VOLUME_MUTED);
+ g_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, PA_VOLUME_MUTED);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == t)
+ if (cv->values[c] > v)
+ v = cv->values[c];
+
+ return v;
+}
+#endif
+
+guint
+gvc_channel_map_get_num_channels (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), 0);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return 0;
+
+ return map->priv->pa_map.channels;
+}
+
+const gdouble *
+gvc_channel_map_get_volume (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ map->priv->extern_volume[VOLUME] = (gdouble) pa_cvolume_max (&map->priv->pa_volume);
+ if (gvc_channel_map_can_balance (map))
+ map->priv->extern_volume[BALANCE] = (gdouble) pa_cvolume_get_balance (&map->priv->pa_volume, &map->priv->pa_map);
+ else
+ map->priv->extern_volume[BALANCE] = 0;
+ if (gvc_channel_map_can_fade (map))
+ map->priv->extern_volume[FADE] = (gdouble) pa_cvolume_get_fade (&map->priv->pa_volume, &map->priv->pa_map);
+ else
+ map->priv->extern_volume[FADE] = 0;
+ if (gvc_channel_map_has_lfe (map))
+ map->priv->extern_volume[LFE] = (gdouble) pa_cvolume_get_position (&map->priv->pa_volume, &map->priv->pa_map, PA_CHANNEL_POSITION_LFE);
+ else
+ map->priv->extern_volume[LFE] = 0;
+
+ return map->priv->extern_volume;
+}
+
+gboolean
+gvc_channel_map_can_balance (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ return map->priv->can_balance;
+}
+
+gboolean
+gvc_channel_map_can_fade (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ return map->priv->can_fade;
+}
+
+const char *
+gvc_channel_map_get_mapping (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ return pa_channel_map_to_pretty_name (&map->priv->pa_map);
+}
+
+gboolean
+gvc_channel_map_has_lfe (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ return map->priv->has_lfe;
+}
+
+const pa_channel_map *
+gvc_channel_map_get_pa_channel_map (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ return &map->priv->pa_map;
+}
+
+const pa_cvolume *
+gvc_channel_map_get_cvolume (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ return &map->priv->pa_volume;
+}
+
+static void
+gvc_channel_map_class_init (GvcChannelMapClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = gvc_channel_map_finalize;
+
+ signals [VOLUME_CHANGED] =
+ g_signal_new ("volume-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ g_type_class_add_private (klass, sizeof (GvcChannelMapPrivate));
+}
+
+void
+gvc_channel_map_volume_changed (GvcChannelMap *map,
+ const pa_cvolume *cv,
+ gboolean set)
+{
+ g_return_if_fail (GVC_IS_CHANNEL_MAP (map));
+ g_return_if_fail (cv != NULL);
+ g_return_if_fail (pa_cvolume_compatible_with_channel_map(cv, &map->priv->pa_map));
+
+ if (pa_cvolume_equal(cv, &map->priv->pa_volume))
+ return;
+
+ map->priv->pa_volume = *cv;
+
+ if (map->priv->pa_volume_is_set == FALSE) {
+ map->priv->pa_volume_is_set = TRUE;
+ return;
+ }
+ g_signal_emit (map, signals[VOLUME_CHANGED], 0, set);
+}
+
+static void
+gvc_channel_map_init (GvcChannelMap *map)
+{
+ map->priv = GVC_CHANNEL_MAP_GET_PRIVATE (map);
+ map->priv->pa_volume_is_set = FALSE;
+}
+
+static void
+gvc_channel_map_finalize (GObject *object)
+{
+ GvcChannelMap *channel_map;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_CHANNEL_MAP (object));
+
+ channel_map = GVC_CHANNEL_MAP (object);
+
+ g_return_if_fail (channel_map->priv != NULL);
+
+ G_OBJECT_CLASS (gvc_channel_map_parent_class)->finalize (object);
+}
+
+GvcChannelMap *
+gvc_channel_map_new (void)
+{
+ GObject *map;
+ map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL);
+ return GVC_CHANNEL_MAP (map);
+}
+
+static void
+set_from_pa_map (GvcChannelMap *map,
+ const pa_channel_map *pa_map)
+{
+ g_assert (pa_channel_map_valid(pa_map));
+
+ map->priv->can_balance = pa_channel_map_can_balance (pa_map);
+ map->priv->can_fade = pa_channel_map_can_fade (pa_map);
+ map->priv->has_lfe = gvc_pa_channel_map_has_position (pa_map, PA_CHANNEL_POSITION_LFE);
+
+ map->priv->pa_map = *pa_map;
+ pa_cvolume_set(&map->priv->pa_volume, pa_map->channels, PA_VOLUME_NORM);
+}
+
+GvcChannelMap *
+gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *pa_map)
+{
+ GObject *map;
+ map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL);
+
+ set_from_pa_map (GVC_CHANNEL_MAP (map), pa_map);
+
+ return GVC_CHANNEL_MAP (map);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-channel-map.h b/plugins/media-keys/cut-n-paste/gvc-channel-map.h
new file mode 100644
index 0000000..8a9fa93
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-channel-map.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_CHANNEL_MAP_H
+#define __GVC_CHANNEL_MAP_H
+
+#include <glib-object.h>
+#include <pulse/pulseaudio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_CHANNEL_MAP (gvc_channel_map_get_type ())
+#define GVC_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMap))
+#define GVC_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass))
+#define GVC_IS_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_CHANNEL_MAP))
+#define GVC_IS_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_CHANNEL_MAP))
+#define GVC_CHANNEL_MAP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass))
+
+typedef struct GvcChannelMapPrivate GvcChannelMapPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GvcChannelMapPrivate *priv;
+} GvcChannelMap;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (*volume_changed) (GvcChannelMap *channel_map, gboolean set);
+} GvcChannelMapClass;
+
+enum {
+ VOLUME,
+ BALANCE,
+ FADE,
+ LFE,
+};
+
+#define NUM_TYPES LFE + 1
+
+GType gvc_channel_map_get_type (void);
+
+GvcChannelMap * gvc_channel_map_new (void);
+GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *map);
+guint gvc_channel_map_get_num_channels (GvcChannelMap *map);
+const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map);
+gboolean gvc_channel_map_can_balance (GvcChannelMap *map);
+gboolean gvc_channel_map_can_fade (GvcChannelMap *map);
+gboolean gvc_channel_map_has_lfe (GvcChannelMap *map);
+
+void gvc_channel_map_volume_changed (GvcChannelMap *map,
+ const pa_cvolume *cv,
+ gboolean set);
+const char * gvc_channel_map_get_mapping (GvcChannelMap *map);
+
+/* private */
+const pa_cvolume * gvc_channel_map_get_cvolume (GvcChannelMap *map);
+const pa_channel_map * gvc_channel_map_get_pa_channel_map (GvcChannelMap *map);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_CHANNEL_MAP_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-card.c b/plugins/media-keys/cut-n-paste/gvc-mixer-card.c
new file mode 100644
index 0000000..9037ff2
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-card.c
@@ -0,0 +1,493 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ * Copyright (C) 2009 Bastien Nocera
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-mixer-card.h"
+
+#define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate))
+
+static guint32 card_serial = 1;
+
+struct GvcMixerCardPrivate
+{
+ pa_context *pa_context;
+ guint id;
+ guint index;
+ char *name;
+ char *icon_name;
+ char *profile;
+ char *target_profile;
+ char *human_profile;
+ GList *profiles;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ID,
+ PROP_PA_CONTEXT,
+ PROP_INDEX,
+ PROP_NAME,
+ PROP_ICON_NAME,
+ PROP_PROFILE,
+ PROP_HUMAN_PROFILE,
+};
+
+static void gvc_mixer_card_class_init (GvcMixerCardClass *klass);
+static void gvc_mixer_card_init (GvcMixerCard *mixer_card);
+static void gvc_mixer_card_finalize (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT)
+
+static guint32
+get_next_card_serial (void)
+{
+ guint32 serial;
+
+ serial = card_serial++;
+
+ if ((gint32)card_serial < 0) {
+ card_serial = 1;
+ }
+
+ return serial;
+}
+
+pa_context *
+gvc_mixer_card_get_pa_context (GvcMixerCard *card)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
+ return card->priv->pa_context;
+}
+
+guint
+gvc_mixer_card_get_index (GvcMixerCard *card)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
+ return card->priv->index;
+}
+
+guint
+gvc_mixer_card_get_id (GvcMixerCard *card)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
+ return card->priv->id;
+}
+
+const char *
+gvc_mixer_card_get_name (GvcMixerCard *card)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
+ return card->priv->name;
+}
+
+gboolean
+gvc_mixer_card_set_name (GvcMixerCard *card,
+ const char *name)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
+
+ g_free (card->priv->name);
+ card->priv->name = g_strdup (name);
+ g_object_notify (G_OBJECT (card), "name");
+
+ return TRUE;
+}
+
+const char *
+gvc_mixer_card_get_icon_name (GvcMixerCard *card)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
+ return card->priv->icon_name;
+}
+
+gboolean
+gvc_mixer_card_set_icon_name (GvcMixerCard *card,
+ const char *icon_name)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
+
+ g_free (card->priv->icon_name);
+ card->priv->icon_name = g_strdup (icon_name);
+ g_object_notify (G_OBJECT (card), "icon-name");
+
+ return TRUE;
+}
+
+GvcMixerCardProfile *
+gvc_mixer_card_get_profile (GvcMixerCard *card)
+{
+ GList *l;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
+ g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
+
+ for (l = card->priv->profiles; l != NULL; l = l->next) {
+ GvcMixerCardProfile *p = l->data;
+ if (g_str_equal (card->priv->profile, p->profile)) {
+ return p;
+ }
+ }
+
+ g_assert_not_reached ();
+
+ return NULL;
+}
+
+gboolean
+gvc_mixer_card_set_profile (GvcMixerCard *card,
+ const char *profile)
+{
+ GList *l;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
+ g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
+
+ g_free (card->priv->profile);
+ card->priv->profile = g_strdup (profile);
+
+ g_free (card->priv->human_profile);
+ card->priv->human_profile = NULL;
+
+ for (l = card->priv->profiles; l != NULL; l = l->next) {
+ GvcMixerCardProfile *p = l->data;
+ if (g_str_equal (card->priv->profile, p->profile)) {
+ card->priv->human_profile = g_strdup (p->human_profile);
+ break;
+ }
+ }
+
+ g_object_notify (G_OBJECT (card), "profile");
+
+ return TRUE;
+}
+
+static void
+_pa_context_set_card_profile_by_index_cb (pa_context *context,
+ int success,
+ void *userdata)
+{
+ GvcMixerCard *card = GVC_MIXER_CARD (userdata);
+
+ g_assert (card->priv->target_profile);
+
+ if (success > 0) {
+ gvc_mixer_card_set_profile (card, card->priv->target_profile);
+ } else {
+ g_debug ("Failed to switch profile on '%s' from '%s' to '%s'",
+ card->priv->name,
+ card->priv->profile,
+ card->priv->target_profile);
+ }
+ g_free (card->priv->target_profile);
+ card->priv->target_profile = NULL;
+}
+
+gboolean
+gvc_mixer_card_change_profile (GvcMixerCard *card,
+ const char *profile)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
+ g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
+
+ /* Same profile, or already requested? */
+ if (g_strcmp0 (card->priv->profile, profile) == 0)
+ return TRUE;
+ if (g_strcmp0 (profile, card->priv->target_profile) == 0)
+ return TRUE;
+
+ if (card->priv->profile != NULL) {
+ pa_operation *o;
+
+ g_free (card->priv->target_profile);
+ card->priv->target_profile = g_strdup (profile);
+
+ o = pa_context_set_card_profile_by_index (card->priv->pa_context,
+ card->priv->index,
+ card->priv->target_profile,
+ _pa_context_set_card_profile_by_index_cb,
+ card);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_card_profile_by_index() failed");
+ return FALSE;
+ }
+
+ pa_operation_unref (o);
+ } else {
+ g_assert (card->priv->human_profile == NULL);
+ card->priv->profile = g_strdup (profile);
+ }
+
+ return TRUE;
+}
+
+const GList *
+gvc_mixer_card_get_profiles (GvcMixerCard *card)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
+ return card->priv->profiles;
+}
+
+static int
+sort_profiles (GvcMixerCardProfile *a,
+ GvcMixerCardProfile *b)
+{
+ if (a->priority == b->priority)
+ return 0;
+ if (a->priority > b->priority)
+ return 1;
+ return -1;
+}
+
+gboolean
+gvc_mixer_card_set_profiles (GvcMixerCard *card,
+ GList *profiles)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
+ g_return_val_if_fail (card->priv->profiles == NULL, FALSE);
+
+ card->priv->profiles = g_list_sort (profiles, (GCompareFunc) sort_profiles);
+
+ return TRUE;
+}
+
+static void
+gvc_mixer_card_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerCard *self = GVC_MIXER_CARD (object);
+
+ switch (prop_id) {
+ case PROP_PA_CONTEXT:
+ self->priv->pa_context = g_value_get_pointer (value);
+ break;
+ case PROP_INDEX:
+ self->priv->index = g_value_get_ulong (value);
+ break;
+ case PROP_ID:
+ self->priv->id = g_value_get_ulong (value);
+ break;
+ case PROP_NAME:
+ gvc_mixer_card_set_name (self, g_value_get_string (value));
+ break;
+ case PROP_ICON_NAME:
+ gvc_mixer_card_set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_PROFILE:
+ gvc_mixer_card_set_profile (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gvc_mixer_card_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerCard *self = GVC_MIXER_CARD (object);
+
+ switch (prop_id) {
+ case PROP_PA_CONTEXT:
+ g_value_set_pointer (value, self->priv->pa_context);
+ break;
+ case PROP_INDEX:
+ g_value_set_ulong (value, self->priv->index);
+ break;
+ case PROP_ID:
+ g_value_set_ulong (value, self->priv->id);
+ break;
+ case PROP_NAME:
+ g_value_set_string (value, self->priv->name);
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value, self->priv->icon_name);
+ break;
+ case PROP_PROFILE:
+ g_value_set_string (value, self->priv->profile);
+ break;
+ case PROP_HUMAN_PROFILE:
+ g_value_set_string (value, self->priv->human_profile);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gvc_mixer_card_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerCard *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_card_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_CARD (object);
+
+ self->priv->id = get_next_card_serial ();
+
+ return object;
+}
+
+static void
+gvc_mixer_card_class_init (GvcMixerCardClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructor = gvc_mixer_card_constructor;
+ gobject_class->finalize = gvc_mixer_card_finalize;
+
+ gobject_class->set_property = gvc_mixer_card_set_property;
+ gobject_class->get_property = gvc_mixer_card_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_INDEX,
+ g_param_spec_ulong ("index",
+ "Index",
+ "The index for this card",
+ 0, G_MAXULONG, 0,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_ID,
+ g_param_spec_ulong ("id",
+ "id",
+ "The id for this card",
+ 0, G_MAXULONG, 0,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_PA_CONTEXT,
+ g_param_spec_pointer ("pa-context",
+ "PulseAudio context",
+ "The PulseAudio context for this card",
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "Name to display for this card",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_ICON_NAME,
+ g_param_spec_string ("icon-name",
+ "Icon Name",
+ "Name of icon to display for this card",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_PROFILE,
+ g_param_spec_string ("profile",
+ "Profile",
+ "Name of current profile for this card",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_HUMAN_PROFILE,
+ g_param_spec_string ("human-profile",
+ "Profile (Human readable)",
+ "Name of current profile for this card in human readable form",
+ NULL,
+ G_PARAM_READABLE));
+
+ g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate));
+}
+
+static void
+gvc_mixer_card_init (GvcMixerCard *card)
+{
+ card->priv = GVC_MIXER_CARD_GET_PRIVATE (card);
+}
+
+GvcMixerCard *
+gvc_mixer_card_new (pa_context *context,
+ guint index)
+{
+ GObject *object;
+
+ object = g_object_new (GVC_TYPE_MIXER_CARD,
+ "index", index,
+ "pa-context", context,
+ NULL);
+ return GVC_MIXER_CARD (object);
+}
+
+static void
+free_profile (GvcMixerCardProfile *p)
+{
+ g_free (p->profile);
+ g_free (p->human_profile);
+ g_free (p->status);
+ g_free (p);
+}
+
+static void
+gvc_mixer_card_finalize (GObject *object)
+{
+ GvcMixerCard *mixer_card;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_CARD (object));
+
+ mixer_card = GVC_MIXER_CARD (object);
+
+ g_return_if_fail (mixer_card->priv != NULL);
+
+ g_free (mixer_card->priv->name);
+ mixer_card->priv->name = NULL;
+
+ g_free (mixer_card->priv->icon_name);
+ mixer_card->priv->icon_name = NULL;
+
+ g_free (mixer_card->priv->target_profile);
+ mixer_card->priv->target_profile = NULL;
+
+ g_free (mixer_card->priv->profile);
+ mixer_card->priv->profile = NULL;
+
+ g_free (mixer_card->priv->human_profile);
+ mixer_card->priv->human_profile = NULL;
+
+ g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL);
+ g_list_free (mixer_card->priv->profiles);
+ mixer_card->priv->profiles = NULL;
+
+ G_OBJECT_CLASS (gvc_mixer_card_parent_class)->finalize (object);
+}
+
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-card.h b/plugins/media-keys/cut-n-paste/gvc-mixer-card.h
new file mode 100644
index 0000000..eeaa29f
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-card.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_CARD_H
+#define __GVC_MIXER_CARD_H
+
+#include <glib-object.h>
+#include <pulse/pulseaudio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_CARD (gvc_mixer_card_get_type ())
+#define GVC_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CARD, GvcMixerCard))
+#define GVC_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CARD, GvcMixerCardClass))
+#define GVC_IS_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CARD))
+#define GVC_IS_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CARD))
+#define GVC_MIXER_CARD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardClass))
+
+typedef struct GvcMixerCardPrivate GvcMixerCardPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GvcMixerCardPrivate *priv;
+} GvcMixerCard;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ /* vtable */
+} GvcMixerCardClass;
+
+typedef struct
+{
+ char *profile;
+ char *human_profile;
+ char *status;
+ guint priority;
+} GvcMixerCardProfile;
+
+GType gvc_mixer_card_get_type (void);
+GvcMixerCard * gvc_mixer_card_new (pa_context *context,
+ guint index);
+
+guint gvc_mixer_card_get_id (GvcMixerCard *card);
+guint gvc_mixer_card_get_index (GvcMixerCard *card);
+const char * gvc_mixer_card_get_name (GvcMixerCard *card);
+const char * gvc_mixer_card_get_icon_name (GvcMixerCard *card);
+GvcMixerCardProfile * gvc_mixer_card_get_profile (GvcMixerCard *card);
+const GList * gvc_mixer_card_get_profiles (GvcMixerCard *card);
+
+pa_context * gvc_mixer_card_get_pa_context (GvcMixerCard *card);
+gboolean gvc_mixer_card_change_profile (GvcMixerCard *card,
+ const char *profile);
+
+/* private */
+gboolean gvc_mixer_card_set_name (GvcMixerCard *card,
+ const char *name);
+gboolean gvc_mixer_card_set_icon_name (GvcMixerCard *card,
+ const char *name);
+gboolean gvc_mixer_card_set_profile (GvcMixerCard *card,
+ const char *profile);
+gboolean gvc_mixer_card_set_profiles (GvcMixerCard *card,
+ GList *profiles);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_CARD_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-control.c b/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
new file mode 100644
index 0000000..2c8d510
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
@@ -0,0 +1,2123 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2008 Lennart Poettering
+ * Copyright (C) 2008 Sjoerd Simons <[email protected]>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+#include <pulse/glib-mainloop.h>
+#include <pulse/ext-stream-restore.h>
+
+#include "gvc-mixer-control.h"
+#include "gvc-mixer-sink.h"
+#include "gvc-mixer-source.h"
+#include "gvc-mixer-sink-input.h"
+#include "gvc-mixer-source-output.h"
+#include "gvc-mixer-event-role.h"
+#include "gvc-mixer-card.h"
+
+#define GVC_MIXER_CONTROL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlPrivate))
+
+#define RECONNECT_DELAY 5
+
+enum {
+ PROP_0,
+ PROP_NAME
+};
+
+struct GvcMixerControlPrivate
+{
+ pa_glib_mainloop *pa_mainloop;
+ pa_mainloop_api *pa_api;
+ pa_context *pa_context;
+ int n_outstanding;
+ guint reconnect_id;
+ char *name;
+
+ gboolean default_sink_is_set;
+ guint default_sink_id;
+ char *default_sink_name;
+ gboolean default_source_is_set;
+ guint default_source_id;
+ char *default_source_name;
+
+ gboolean event_sink_input_is_set;
+ guint event_sink_input_id;
+
+ GHashTable *all_streams;
+ GHashTable *sinks; /* fixed outputs */
+ GHashTable *sources; /* fixed inputs */
+ GHashTable *sink_inputs; /* routable output streams */
+ GHashTable *source_outputs; /* routable input streams */
+ GHashTable *clients;
+ GHashTable *cards;
+
+ GvcMixerStream *new_default_stream; /* new default stream, used in gvc_mixer_control_set_default_sink () */
+};
+
+enum {
+ CONNECTING,
+ READY,
+ STREAM_ADDED,
+ STREAM_REMOVED,
+ CARD_ADDED,
+ CARD_REMOVED,
+ DEFAULT_SINK_CHANGED,
+ DEFAULT_SOURCE_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gvc_mixer_control_class_init (GvcMixerControlClass *klass);
+static void gvc_mixer_control_init (GvcMixerControl *mixer_control);
+static void gvc_mixer_control_finalize (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerControl, gvc_mixer_control, G_TYPE_OBJECT)
+
+pa_context *
+gvc_mixer_control_get_pa_context (GvcMixerControl *control)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+ return control->priv->pa_context;
+}
+
+GvcMixerStream *
+gvc_mixer_control_get_event_sink_input (GvcMixerControl *control)
+{
+ GvcMixerStream *stream;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ stream = g_hash_table_lookup (control->priv->all_streams,
+ GUINT_TO_POINTER (control->priv->event_sink_input_id));
+
+ return stream;
+}
+
+static void
+gvc_mixer_control_stream_restore_cb (pa_context *c,
+ const pa_ext_stream_restore_info *info,
+ int eol,
+ void *userdata)
+{
+ pa_operation *o;
+ GvcMixerControl *control = (GvcMixerControl *) userdata;
+ pa_ext_stream_restore_info new_info;
+
+ if (eol || control->priv->new_default_stream == NULL)
+ return;
+
+ new_info.name = info->name;
+ new_info.channel_map = info->channel_map;
+ new_info.volume = info->volume;
+ new_info.mute = info->mute;
+
+ new_info.device = gvc_mixer_stream_get_name (control->priv->new_default_stream);
+
+ o = pa_ext_stream_restore_write (control->priv->pa_context,
+ PA_UPDATE_REPLACE,
+ &new_info, 1,
+ TRUE, NULL, NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_ext_stream_restore_write() failed: %s",
+ pa_strerror (pa_context_errno (control->priv->pa_context)));
+ return;
+ }
+
+ g_debug ("Changed default device for %s to %s", info->name, info->device);
+
+ pa_operation_unref (o);
+}
+
+gboolean
+gvc_mixer_control_set_default_sink (GvcMixerControl *control,
+ GvcMixerStream *stream)
+{
+ pa_operation *o;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ o = pa_context_set_default_sink (control->priv->pa_context,
+ gvc_mixer_stream_get_name (stream),
+ NULL,
+ NULL);
+ if (o == NULL) {
+ g_warning ("pa_context_set_default_sink() failed: %s",
+ pa_strerror (pa_context_errno (control->priv->pa_context)));
+ return FALSE;
+ }
+
+ pa_operation_unref (o);
+
+ control->priv->new_default_stream = stream;
+ g_object_add_weak_pointer (G_OBJECT (stream), (gpointer *) &control->priv->new_default_stream);
+
+ o = pa_ext_stream_restore_read (control->priv->pa_context,
+ gvc_mixer_control_stream_restore_cb,
+ control);
+
+ if (o == NULL) {
+ g_warning ("pa_ext_stream_restore_read() failed: %s",
+ pa_strerror (pa_context_errno (control->priv->pa_context)));
+ return FALSE;
+ }
+
+ pa_operation_unref (o);
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_control_set_default_source (GvcMixerControl *control,
+ GvcMixerStream *stream)
+{
+ pa_operation *o;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ o = pa_context_set_default_source (control->priv->pa_context,
+ gvc_mixer_stream_get_name (stream),
+ NULL,
+ NULL);
+ if (o == NULL) {
+ g_warning ("pa_context_set_default_source() failed");
+ return FALSE;
+ }
+
+ pa_operation_unref (o);
+
+ return TRUE;
+}
+
+GvcMixerStream *
+gvc_mixer_control_get_default_sink (GvcMixerControl *control)
+{
+ GvcMixerStream *stream;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ if (control->priv->default_sink_is_set) {
+ stream = g_hash_table_lookup (control->priv->all_streams,
+ GUINT_TO_POINTER (control->priv->default_sink_id));
+ } else {
+ stream = NULL;
+ }
+
+ return stream;
+}
+
+GvcMixerStream *
+gvc_mixer_control_get_default_source (GvcMixerControl *control)
+{
+ GvcMixerStream *stream;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ if (control->priv->default_source_is_set) {
+ stream = g_hash_table_lookup (control->priv->all_streams,
+ GUINT_TO_POINTER (control->priv->default_source_id));
+ } else {
+ stream = NULL;
+ }
+
+ return stream;
+}
+
+static gpointer
+gvc_mixer_control_lookup_id (GHashTable *hash_table,
+ guint id)
+{
+ return g_hash_table_lookup (hash_table,
+ GUINT_TO_POINTER (id));
+}
+
+GvcMixerStream *
+gvc_mixer_control_lookup_stream_id (GvcMixerControl *control,
+ guint id)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ return gvc_mixer_control_lookup_id (control->priv->all_streams, id);
+}
+
+GvcMixerCard *
+gvc_mixer_control_lookup_card_id (GvcMixerControl *control,
+ guint id)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ return gvc_mixer_control_lookup_id (control->priv->cards, id);
+}
+
+static void
+listify_hash_values_hfunc (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **list = user_data;
+
+ *list = g_slist_prepend (*list, value);
+}
+
+static int
+gvc_name_collate (const char *namea,
+ const char *nameb)
+{
+ if (nameb == NULL && namea == NULL)
+ return 0;
+ if (nameb == NULL)
+ return 1;
+ if (namea == NULL)
+ return -1;
+
+ return g_utf8_collate (namea, nameb);
+}
+
+static int
+gvc_card_collate (GvcMixerCard *a,
+ GvcMixerCard *b)
+{
+ const char *namea;
+ const char *nameb;
+
+ g_return_val_if_fail (a == NULL || GVC_IS_MIXER_CARD (a), 0);
+ g_return_val_if_fail (b == NULL || GVC_IS_MIXER_CARD (b), 0);
+
+ namea = gvc_mixer_card_get_name (a);
+ nameb = gvc_mixer_card_get_name (b);
+
+ return gvc_name_collate (namea, nameb);
+}
+
+GSList *
+gvc_mixer_control_get_cards (GvcMixerControl *control)
+{
+ GSList *retval;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ retval = NULL;
+ g_hash_table_foreach (control->priv->cards,
+ listify_hash_values_hfunc,
+ &retval);
+ return g_slist_sort (retval, (GCompareFunc) gvc_card_collate);
+}
+
+static int
+gvc_stream_collate (GvcMixerStream *a,
+ GvcMixerStream *b)
+{
+ const char *namea;
+ const char *nameb;
+
+ g_return_val_if_fail (a == NULL || GVC_IS_MIXER_STREAM (a), 0);
+ g_return_val_if_fail (b == NULL || GVC_IS_MIXER_STREAM (b), 0);
+
+ namea = gvc_mixer_stream_get_name (a);
+ nameb = gvc_mixer_stream_get_name (b);
+
+ return gvc_name_collate (namea, nameb);
+}
+
+GSList *
+gvc_mixer_control_get_streams (GvcMixerControl *control)
+{
+ GSList *retval;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ retval = NULL;
+ g_hash_table_foreach (control->priv->all_streams,
+ listify_hash_values_hfunc,
+ &retval);
+ return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate);
+}
+
+GSList *
+gvc_mixer_control_get_sinks (GvcMixerControl *control)
+{
+ GSList *retval;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ retval = NULL;
+ g_hash_table_foreach (control->priv->sinks,
+ listify_hash_values_hfunc,
+ &retval);
+ return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate);
+}
+
+GSList *
+gvc_mixer_control_get_sources (GvcMixerControl *control)
+{
+ GSList *retval;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ retval = NULL;
+ g_hash_table_foreach (control->priv->sources,
+ listify_hash_values_hfunc,
+ &retval);
+ return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate);
+}
+
+GSList *
+gvc_mixer_control_get_sink_inputs (GvcMixerControl *control)
+{
+ GSList *retval;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ retval = NULL;
+ g_hash_table_foreach (control->priv->sink_inputs,
+ listify_hash_values_hfunc,
+ &retval);
+ return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate);
+}
+
+GSList *
+gvc_mixer_control_get_source_outputs (GvcMixerControl *control)
+{
+ GSList *retval;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+
+ retval = NULL;
+ g_hash_table_foreach (control->priv->source_outputs,
+ listify_hash_values_hfunc,
+ &retval);
+ return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate);
+}
+
+static void
+dec_outstanding (GvcMixerControl *control)
+{
+ if (control->priv->n_outstanding <= 0) {
+ return;
+ }
+
+ if (--control->priv->n_outstanding <= 0) {
+ g_signal_emit (G_OBJECT (control), signals[READY], 0);
+ }
+}
+
+gboolean
+gvc_mixer_control_is_ready (GvcMixerControl *control)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+
+ return (control->priv->n_outstanding == 0);
+}
+
+
+static void
+_set_default_source (GvcMixerControl *control,
+ GvcMixerStream *stream)
+{
+ guint new_id;
+
+ if (stream == NULL) {
+ control->priv->default_source_id = 0;
+ control->priv->default_source_is_set = FALSE;
+ return;
+ }
+
+ new_id = gvc_mixer_stream_get_id (stream);
+
+ if (control->priv->default_source_id != new_id) {
+ control->priv->default_source_id = new_id;
+ control->priv->default_source_is_set = TRUE;
+ g_signal_emit (control,
+ signals[DEFAULT_SOURCE_CHANGED],
+ 0,
+ new_id);
+ }
+}
+
+static void
+_set_default_sink (GvcMixerControl *control,
+ GvcMixerStream *stream)
+{
+ guint new_id;
+
+ if (stream == NULL) {
+ control->priv->default_sink_id = 0;
+ control->priv->default_sink_is_set = FALSE;
+ return;
+ }
+
+ new_id = gvc_mixer_stream_get_id (stream);
+
+ if (control->priv->default_sink_id != new_id) {
+ control->priv->default_sink_id = new_id;
+ control->priv->default_sink_is_set = TRUE;
+
+ g_signal_emit (control,
+ signals[DEFAULT_SINK_CHANGED],
+ 0,
+ new_id);
+ }
+}
+
+static gboolean
+_stream_has_name (gpointer key,
+ GvcMixerStream *stream,
+ const char *name)
+{
+ const char *t_name;
+
+ t_name = gvc_mixer_stream_get_name (stream);
+
+ if (t_name != NULL
+ && name != NULL
+ && strcmp (t_name, name) == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GvcMixerStream *
+find_stream_for_name (GvcMixerControl *control,
+ const char *name)
+{
+ GvcMixerStream *stream;
+
+ stream = g_hash_table_find (control->priv->all_streams,
+ (GHRFunc)_stream_has_name,
+ (char *)name);
+ return stream;
+}
+
+static void
+update_default_source_from_name (GvcMixerControl *control,
+ const char *name)
+{
+ gboolean changed;
+
+ if ((control->priv->default_source_name == NULL
+ && name != NULL)
+ || (control->priv->default_source_name != NULL
+ && name == NULL)
+ || strcmp (control->priv->default_source_name, name) != 0) {
+ changed = TRUE;
+ }
+
+ if (changed) {
+ GvcMixerStream *stream;
+
+ g_free (control->priv->default_source_name);
+ control->priv->default_source_name = g_strdup (name);
+
+ stream = find_stream_for_name (control, name);
+ _set_default_source (control, stream);
+ }
+}
+
+static void
+update_default_sink_from_name (GvcMixerControl *control,
+ const char *name)
+{
+ gboolean changed;
+
+ if ((control->priv->default_sink_name == NULL
+ && name != NULL)
+ || (control->priv->default_sink_name != NULL
+ && name == NULL)
+ || strcmp (control->priv->default_sink_name, name) != 0) {
+ changed = TRUE;
+ }
+
+ if (changed) {
+ GvcMixerStream *stream;
+ g_free (control->priv->default_sink_name);
+ control->priv->default_sink_name = g_strdup (name);
+
+ stream = find_stream_for_name (control, name);
+ _set_default_sink (control, stream);
+ }
+}
+
+static void
+update_server (GvcMixerControl *control,
+ const pa_server_info *info)
+{
+ if (info->default_source_name != NULL) {
+ update_default_source_from_name (control, info->default_source_name);
+ }
+ if (info->default_sink_name != NULL) {
+ update_default_sink_from_name (control, info->default_sink_name);
+ }
+}
+
+static void
+remove_stream (GvcMixerControl *control,
+ GvcMixerStream *stream)
+{
+ guint id;
+
+ g_object_ref (stream);
+
+ id = gvc_mixer_stream_get_id (stream);
+
+ if (id == control->priv->default_sink_id) {
+ _set_default_sink (control, NULL);
+ } else if (id == control->priv->default_source_id) {
+ _set_default_source (control, NULL);
+ }
+
+ g_hash_table_remove (control->priv->all_streams,
+ GUINT_TO_POINTER (id));
+ g_signal_emit (G_OBJECT (control),
+ signals[STREAM_REMOVED],
+ 0,
+ gvc_mixer_stream_get_id (stream));
+ g_object_unref (stream);
+}
+
+static void
+add_stream (GvcMixerControl *control,
+ GvcMixerStream *stream)
+{
+ g_hash_table_insert (control->priv->all_streams,
+ GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)),
+ stream);
+ g_signal_emit (G_OBJECT (control),
+ signals[STREAM_ADDED],
+ 0,
+ gvc_mixer_stream_get_id (stream));
+}
+
+static void
+update_sink (GvcMixerControl *control,
+ const pa_sink_info *info)
+{
+ GvcMixerStream *stream;
+ gboolean is_new;
+ pa_volume_t max_volume;
+ GvcChannelMap *map;
+ char map_buff[PA_CHANNEL_MAP_SNPRINT_MAX];
+
+ pa_channel_map_snprint (map_buff, PA_CHANNEL_MAP_SNPRINT_MAX, &info->channel_map);
+#if 1
+ g_debug ("Updating sink: index=%u name='%s' description='%s' map='%s'",
+ info->index,
+ info->name,
+ info->description,
+ map_buff);
+#endif
+
+ map = NULL;
+ is_new = FALSE;
+ stream = g_hash_table_lookup (control->priv->sinks,
+ GUINT_TO_POINTER (info->index));
+ if (stream == NULL) {
+#if PA_MICRO > 15
+ GList *list = NULL;
+ guint i;
+#endif /* PA_MICRO > 15 */
+
+ map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map);
+ stream = gvc_mixer_sink_new (control->priv->pa_context,
+ info->index,
+ map);
+#if PA_MICRO > 15
+ for (i = 0; i < info->n_ports; i++) {
+ GvcMixerStreamPort *port;
+
+ port = g_new0 (GvcMixerStreamPort, 1);
+ port->port = g_strdup (info->ports[i]->name);
+ port->human_port = g_strdup (info->ports[i]->description);
+ port->priority = info->ports[i]->priority;
+ list = g_list_prepend (list, port);
+ }
+ gvc_mixer_stream_set_ports (stream, list);
+#endif /* PA_MICRO > 15 */
+ g_object_unref (map);
+ is_new = TRUE;
+ } else if (gvc_mixer_stream_is_running (stream)) {
+ /* Ignore events if volume changes are outstanding */
+ g_debug ("Ignoring event, volume changes are outstanding");
+ return;
+ }
+
+ max_volume = pa_cvolume_max (&info->volume);
+ gvc_mixer_stream_set_name (stream, info->name);
+ gvc_mixer_stream_set_description (stream, info->description);
+ gvc_mixer_stream_set_icon_name (stream, "audio-card");
+ gvc_mixer_stream_set_volume (stream, (guint)max_volume);
+ gvc_mixer_stream_set_is_muted (stream, info->mute);
+ gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SINK_DECIBEL_VOLUME));
+#if PA_MICRO > 15
+ if (info->active_port != NULL)
+ gvc_mixer_stream_set_port (stream, info->active_port->name);
+#endif /* PA_MICRO > 15 */
+
+ if (is_new) {
+ g_hash_table_insert (control->priv->sinks,
+ GUINT_TO_POINTER (info->index),
+ g_object_ref (stream));
+ add_stream (control, stream);
+ }
+
+ if (control->priv->default_sink_name != NULL
+ && info->name != NULL
+ && strcmp (control->priv->default_sink_name, info->name) == 0) {
+ _set_default_sink (control, stream);
+ }
+
+ if (map == NULL)
+ map = gvc_mixer_stream_get_channel_map (stream);
+ gvc_channel_map_volume_changed (map, &info->volume, FALSE);
+}
+
+static void
+update_source (GvcMixerControl *control,
+ const pa_source_info *info)
+{
+ GvcMixerStream *stream;
+ gboolean is_new;
+ pa_volume_t max_volume;
+
+#if 1
+ g_debug ("Updating source: index=%u name='%s' description='%s'",
+ info->index,
+ info->name,
+ info->description);
+#endif
+
+ /* completely ignore monitors, they're not real sources */
+ if (info->monitor_of_sink != PA_INVALID_INDEX) {
+ return;
+ }
+
+ is_new = FALSE;
+
+ stream = g_hash_table_lookup (control->priv->sources,
+ GUINT_TO_POINTER (info->index));
+ if (stream == NULL) {
+#if PA_MICRO > 15
+ GList *list = NULL;
+ guint i;
+#endif /* PA_MICRO > 15 */
+ GvcChannelMap *map;
+
+ map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map);
+ stream = gvc_mixer_source_new (control->priv->pa_context,
+ info->index,
+ map);
+#if PA_MICRO > 15
+ for (i = 0; i < info->n_ports; i++) {
+ GvcMixerStreamPort *port;
+
+ port = g_new0 (GvcMixerStreamPort, 1);
+ port->port = g_strdup (info->ports[i]->name);
+ port->human_port = g_strdup (info->ports[i]->description);
+ port->priority = info->ports[i]->priority;
+ list = g_list_prepend (list, port);
+ }
+ gvc_mixer_stream_set_ports (stream, list);
+#endif /* PA_MICRO > 15 */
+
+ g_object_unref (map);
+ is_new = TRUE;
+ } else if (gvc_mixer_stream_is_running (stream)) {
+ /* Ignore events if volume changes are outstanding */
+ g_debug ("Ignoring event, volume changes are outstanding");
+ return;
+ }
+
+ max_volume = pa_cvolume_max (&info->volume);
+
+ gvc_mixer_stream_set_name (stream, info->name);
+ gvc_mixer_stream_set_description (stream, info->description);
+ gvc_mixer_stream_set_icon_name (stream, "audio-input-microphone");
+ gvc_mixer_stream_set_volume (stream, (guint)max_volume);
+ gvc_mixer_stream_set_is_muted (stream, info->mute);
+ gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SOURCE_DECIBEL_VOLUME));
+ gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume);
+#if PA_MICRO > 15
+ if (info->active_port != NULL)
+ gvc_mixer_stream_set_port (stream, info->active_port->name);
+#endif /* PA_MICRO > 15 */
+
+ if (is_new) {
+ g_hash_table_insert (control->priv->sources,
+ GUINT_TO_POINTER (info->index),
+ g_object_ref (stream));
+ add_stream (control, stream);
+ }
+
+ if (control->priv->default_source_name != NULL
+ && info->name != NULL
+ && strcmp (control->priv->default_source_name, info->name) == 0) {
+ _set_default_source (control, stream);
+ }
+}
+
+static void
+set_icon_name_from_proplist (GvcMixerStream *stream,
+ pa_proplist *l,
+ const char *default_icon_name)
+{
+ const char *t;
+
+ if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ICON_NAME))) {
+ goto finish;
+ }
+
+ if ((t = pa_proplist_gets (l, PA_PROP_WINDOW_ICON_NAME))) {
+ goto finish;
+ }
+
+ if ((t = pa_proplist_gets (l, PA_PROP_APPLICATION_ICON_NAME))) {
+ goto finish;
+ }
+
+ if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ROLE))) {
+
+ if (strcmp (t, "video") == 0 ||
+ strcmp (t, "phone") == 0) {
+ goto finish;
+ }
+
+ if (strcmp (t, "music") == 0) {
+ t = "audio";
+ goto finish;
+ }
+
+ if (strcmp (t, "game") == 0) {
+ t = "applications-games";
+ goto finish;
+ }
+
+ if (strcmp (t, "event") == 0) {
+ t = "dialog-information";
+ goto finish;
+ }
+ }
+
+ t = default_icon_name;
+
+ finish:
+ gvc_mixer_stream_set_icon_name (stream, t);
+}
+
+static void
+set_is_event_stream_from_proplist (GvcMixerStream *stream,
+ pa_proplist *l)
+{
+ const char *t;
+ gboolean is_event_stream;
+
+ is_event_stream = FALSE;
+
+ if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ROLE))) {
+ if (g_str_equal (t, "event"))
+ is_event_stream = TRUE;
+ }
+
+ gvc_mixer_stream_set_is_event_stream (stream, is_event_stream);
+}
+
+static void
+set_application_id_from_proplist (GvcMixerStream *stream,
+ pa_proplist *l)
+{
+ const char *t;
+
+ if ((t = pa_proplist_gets (l, PA_PROP_APPLICATION_ID))) {
+ gvc_mixer_stream_set_application_id (stream, t);
+ }
+}
+
+static void
+update_sink_input (GvcMixerControl *control,
+ const pa_sink_input_info *info)
+{
+ GvcMixerStream *stream;
+ gboolean is_new;
+ pa_volume_t max_volume;
+ const char *name;
+
+#if 0
+ g_debug ("Updating sink input: index=%u name='%s' client=%u sink=%u",
+ info->index,
+ info->name,
+ info->client,
+ info->sink);
+#endif
+
+ is_new = FALSE;
+
+ stream = g_hash_table_lookup (control->priv->sink_inputs,
+ GUINT_TO_POINTER (info->index));
+ if (stream == NULL) {
+ GvcChannelMap *map;
+ map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map);
+ stream = gvc_mixer_sink_input_new (control->priv->pa_context,
+ info->index,
+ map);
+ g_object_unref (map);
+ is_new = TRUE;
+ } else if (gvc_mixer_stream_is_running (stream)) {
+ /* Ignore events if volume changes are outstanding */
+ g_debug ("Ignoring event, volume changes are outstanding");
+ return;
+ }
+
+ max_volume = pa_cvolume_max (&info->volume);
+
+ name = (const char *)g_hash_table_lookup (control->priv->clients,
+ GUINT_TO_POINTER (info->client));
+ gvc_mixer_stream_set_name (stream, name);
+ gvc_mixer_stream_set_description (stream, info->name);
+
+ set_application_id_from_proplist (stream, info->proplist);
+ set_is_event_stream_from_proplist (stream, info->proplist);
+ set_icon_name_from_proplist (stream, info->proplist, "applications-multimedia");
+ gvc_mixer_stream_set_volume (stream, (guint)max_volume);
+ gvc_mixer_stream_set_is_muted (stream, info->mute);
+ gvc_mixer_stream_set_is_virtual (stream, info->client == PA_INVALID_INDEX);
+
+ if (is_new) {
+ g_hash_table_insert (control->priv->sink_inputs,
+ GUINT_TO_POINTER (info->index),
+ g_object_ref (stream));
+ add_stream (control, stream);
+ }
+}
+
+static void
+update_source_output (GvcMixerControl *control,
+ const pa_source_output_info *info)
+{
+ GvcMixerStream *stream;
+ gboolean is_new;
+ const char *name;
+
+#if 1
+ g_debug ("Updating source output: index=%u name='%s' client=%u source=%u",
+ info->index,
+ info->name,
+ info->client,
+ info->source);
+#endif
+
+ is_new = FALSE;
+ stream = g_hash_table_lookup (control->priv->source_outputs,
+ GUINT_TO_POINTER (info->index));
+ if (stream == NULL) {
+ GvcChannelMap *map;
+ map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map);
+ stream = gvc_mixer_source_output_new (control->priv->pa_context,
+ info->index,
+ map);
+ g_object_unref (map);
+ is_new = TRUE;
+ }
+
+ name = (const char *)g_hash_table_lookup (control->priv->clients,
+ GUINT_TO_POINTER (info->client));
+
+ gvc_mixer_stream_set_name (stream, name);
+ gvc_mixer_stream_set_description (stream, info->name);
+ set_application_id_from_proplist (stream, info->proplist);
+ set_is_event_stream_from_proplist (stream, info->proplist);
+ set_icon_name_from_proplist (stream, info->proplist, "audio-input-microphone");
+
+ if (is_new) {
+ g_hash_table_insert (control->priv->source_outputs,
+ GUINT_TO_POINTER (info->index),
+ g_object_ref (stream));
+ add_stream (control, stream);
+ }
+}
+
+static void
+update_client (GvcMixerControl *control,
+ const pa_client_info *info)
+{
+#if 1
+ g_debug ("Updating client: index=%u name='%s'",
+ info->index,
+ info->name);
+#endif
+ g_hash_table_insert (control->priv->clients,
+ GUINT_TO_POINTER (info->index),
+ g_strdup (info->name));
+}
+
+static char *
+card_num_streams_to_status (guint sinks,
+ guint sources)
+{
+ char *sinks_str;
+ char *sources_str;
+ char *ret;
+
+ if (sinks == 0 && sources == 0) {
+ /* translators:
+ * The device has been disabled */
+ return g_strdup (_("Disabled"));
+ }
+ if (sinks == 0) {
+ sinks_str = NULL;
+ } else {
+ /* translators:
+ * The number of sound outputs on a particular device */
+ sinks_str = g_strdup_printf (ngettext ("%u Output",
+ "%u Outputs",
+ sinks),
+ sinks);
+ }
+ if (sources == 0) {
+ sources_str = NULL;
+ } else {
+ /* translators:
+ * The number of sound inputs on a particular device */
+ sources_str = g_strdup_printf (ngettext ("%u Input",
+ "%u Inputs",
+ sources),
+ sources);
+ }
+ if (sources_str == NULL)
+ return sinks_str;
+ if (sinks_str == NULL)
+ return sources_str;
+ ret = g_strdup_printf ("%s / %s", sinks_str, sources_str);
+ g_free (sinks_str);
+ g_free (sources_str);
+ return ret;
+}
+
+static void
+update_card (GvcMixerControl *control,
+ const pa_card_info *info)
+{
+ GvcMixerCard *card;
+ gboolean is_new;
+#if 1
+ guint i;
+ const char *key;
+ void *state;
+
+ g_debug ("Udpating card %s (index: %u driver: %s):",
+ info->name, info->index, info->driver);
+
+ for (i = 0; i < info->n_profiles; i++) {
+ struct pa_card_profile_info pi = info->profiles[i];
+ gboolean is_default;
+
+ is_default = (g_strcmp0 (pi.name, info->active_profile->name) == 0);
+ g_debug ("\tProfile '%s': %d sources %d sinks%s",
+ pi.name, pi.n_sources, pi.n_sinks,
+ is_default ? " (Current)" : "");
+ }
+ state = NULL;
+ key = pa_proplist_iterate (info->proplist, &state);
+ while (key != NULL) {
+ g_debug ("\tProperty: '%s' = '%s'",
+ key, pa_proplist_gets (info->proplist, key));
+ key = pa_proplist_iterate (info->proplist, &state);
+ }
+#endif
+ card = g_hash_table_lookup (control->priv->cards,
+ GUINT_TO_POINTER (info->index));
+ if (card == NULL) {
+ GList *list = NULL;
+
+ for (i = 0; i < info->n_profiles; i++) {
+ struct pa_card_profile_info pi = info->profiles[i];
+ GvcMixerCardProfile *profile;
+
+ profile = g_new0 (GvcMixerCardProfile, 1);
+ profile->profile = g_strdup (pi.name);
+ profile->human_profile = g_strdup (pi.description);
+ profile->status = card_num_streams_to_status (pi.n_sinks, pi.n_sources);
+ profile->priority = pi.priority;
+ list = g_list_prepend (list, profile);
+ }
+ card = gvc_mixer_card_new (control->priv->pa_context,
+ info->index);
+ gvc_mixer_card_set_profiles (card, list);
+ is_new = TRUE;
+ }
+
+ gvc_mixer_card_set_name (card, pa_proplist_gets (info->proplist, "device.description"));
+ gvc_mixer_card_set_icon_name (card, pa_proplist_gets (info->proplist, "device.icon_name"));
+ gvc_mixer_card_set_profile (card, info->active_profile->name);
+
+ if (is_new) {
+ g_hash_table_insert (control->priv->cards,
+ GUINT_TO_POINTER (info->index),
+ g_object_ref (card));
+ }
+ g_signal_emit (G_OBJECT (control),
+ signals[CARD_ADDED],
+ 0,
+ info->index);
+}
+
+static void
+_pa_context_get_sink_info_cb (pa_context *context,
+ const pa_sink_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ if (pa_context_errno (context) == PA_ERR_NOENTITY) {
+ return;
+ }
+
+ g_warning ("Sink callback failure");
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_sink (control, i);
+}
+
+static void
+_pa_context_get_source_info_cb (pa_context *context,
+ const pa_source_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ if (pa_context_errno (context) == PA_ERR_NOENTITY) {
+ return;
+ }
+
+ g_warning ("Source callback failure");
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_source (control, i);
+}
+
+static void
+_pa_context_get_sink_input_info_cb (pa_context *context,
+ const pa_sink_input_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ if (pa_context_errno (context) == PA_ERR_NOENTITY) {
+ return;
+ }
+
+ g_warning ("Sink input callback failure");
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_sink_input (control, i);
+}
+
+static void
+_pa_context_get_source_output_info_cb (pa_context *context,
+ const pa_source_output_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ if (pa_context_errno (context) == PA_ERR_NOENTITY) {
+ return;
+ }
+
+ g_warning ("Source output callback failure");
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_source_output (control, i);
+}
+
+static void
+_pa_context_get_client_info_cb (pa_context *context,
+ const pa_client_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ if (pa_context_errno (context) == PA_ERR_NOENTITY) {
+ return;
+ }
+
+ g_warning ("Client callback failure");
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_client (control, i);
+}
+
+static void
+_pa_context_get_card_info_by_index_cb (pa_context *context,
+ const pa_card_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ if (pa_context_errno (context) == PA_ERR_NOENTITY)
+ return;
+
+ g_warning ("Card callback failure");
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_card (control, i);
+}
+
+static void
+_pa_context_get_server_info_cb (pa_context *context,
+ const pa_server_info *i,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (i == NULL) {
+ g_warning ("Server info callback failure");
+ return;
+ }
+
+ update_server (control, i);
+ dec_outstanding (control);
+}
+
+static void
+remove_event_role_stream (GvcMixerControl *control)
+{
+ g_debug ("Removing event role");
+}
+
+static void
+update_event_role_stream (GvcMixerControl *control,
+ const pa_ext_stream_restore_info *info)
+{
+ GvcMixerStream *stream;
+ gboolean is_new;
+ pa_volume_t max_volume;
+
+ if (strcmp (info->name, "sink-input-by-media-role:event") != 0) {
+ return;
+ }
+
+#if 0
+ g_debug ("Updating event role: name='%s' device='%s'",
+ info->name,
+ info->device);
+#endif
+
+ is_new = FALSE;
+
+ if (!control->priv->event_sink_input_is_set) {
+ pa_channel_map pa_map;
+ GvcChannelMap *map;
+
+ pa_map.channels = 1;
+ pa_map.map[0] = PA_CHANNEL_POSITION_MONO;
+ map = gvc_channel_map_new_from_pa_channel_map (&pa_map);
+
+ stream = gvc_mixer_event_role_new (control->priv->pa_context,
+ info->device,
+ map);
+ control->priv->event_sink_input_id = gvc_mixer_stream_get_id (stream);
+ control->priv->event_sink_input_is_set = TRUE;
+
+ is_new = TRUE;
+ } else {
+ stream = g_hash_table_lookup (control->priv->all_streams,
+ GUINT_TO_POINTER (control->priv->event_sink_input_id));
+ }
+
+ max_volume = pa_cvolume_max (&info->volume);
+
+ gvc_mixer_stream_set_name (stream, _("System Sounds"));
+ gvc_mixer_stream_set_icon_name (stream, "multimedia-volume-control");
+ gvc_mixer_stream_set_volume (stream, (guint)max_volume);
+ gvc_mixer_stream_set_is_muted (stream, info->mute);
+
+ if (is_new) {
+ add_stream (control, stream);
+ }
+}
+
+static void
+_pa_ext_stream_restore_read_cb (pa_context *context,
+ const pa_ext_stream_restore_info *i,
+ int eol,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ if (eol < 0) {
+ g_debug ("Failed to initialized stream_restore extension: %s",
+ pa_strerror (pa_context_errno (context)));
+ remove_event_role_stream (control);
+ return;
+ }
+
+ if (eol > 0) {
+ dec_outstanding (control);
+ return;
+ }
+
+ update_event_role_stream (control, i);
+}
+
+static void
+_pa_ext_stream_restore_subscribe_cb (pa_context *context,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+ pa_operation *o;
+
+ o = pa_ext_stream_restore_read (context,
+ _pa_ext_stream_restore_read_cb,
+ control);
+ if (o == NULL) {
+ g_warning ("pa_ext_stream_restore_read() failed");
+ return;
+ }
+
+ pa_operation_unref (o);
+}
+
+static void
+req_update_server_info (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ o = pa_context_get_server_info (control->priv->pa_context,
+ _pa_context_get_server_info_cb,
+ control);
+ if (o == NULL) {
+ g_warning ("pa_context_get_server_info() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+req_update_client_info (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ if (index < 0) {
+ o = pa_context_get_client_info_list (control->priv->pa_context,
+ _pa_context_get_client_info_cb,
+ control);
+ } else {
+ o = pa_context_get_client_info (control->priv->pa_context,
+ index,
+ _pa_context_get_client_info_cb,
+ control);
+ }
+
+ if (o == NULL) {
+ g_warning ("pa_context_client_info_list() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+req_update_card (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ if (index < 0) {
+ o = pa_context_get_card_info_list (control->priv->pa_context,
+ _pa_context_get_card_info_by_index_cb,
+ control);
+ } else {
+ o = pa_context_get_card_info_by_index (control->priv->pa_context,
+ index,
+ _pa_context_get_card_info_by_index_cb,
+ control);
+ }
+
+ if (o == NULL) {
+ g_warning ("pa_context_get_card_info_by_index() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+req_update_sink_info (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ if (index < 0) {
+ o = pa_context_get_sink_info_list (control->priv->pa_context,
+ _pa_context_get_sink_info_cb,
+ control);
+ } else {
+ o = pa_context_get_sink_info_by_index (control->priv->pa_context,
+ index,
+ _pa_context_get_sink_info_cb,
+ control);
+ }
+
+ if (o == NULL) {
+ g_warning ("pa_context_get_sink_info_list() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+req_update_source_info (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ if (index < 0) {
+ o = pa_context_get_source_info_list (control->priv->pa_context,
+ _pa_context_get_source_info_cb,
+ control);
+ } else {
+ o = pa_context_get_source_info_by_index(control->priv->pa_context,
+ index,
+ _pa_context_get_source_info_cb,
+ control);
+ }
+
+ if (o == NULL) {
+ g_warning ("pa_context_get_source_info_list() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+req_update_sink_input_info (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ if (index < 0) {
+ o = pa_context_get_sink_input_info_list (control->priv->pa_context,
+ _pa_context_get_sink_input_info_cb,
+ control);
+ } else {
+ o = pa_context_get_sink_input_info (control->priv->pa_context,
+ index,
+ _pa_context_get_sink_input_info_cb,
+ control);
+ }
+
+ if (o == NULL) {
+ g_warning ("pa_context_get_sink_input_info_list() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+req_update_source_output_info (GvcMixerControl *control,
+ int index)
+{
+ pa_operation *o;
+
+ if (index < 0) {
+ o = pa_context_get_source_output_info_list (control->priv->pa_context,
+ _pa_context_get_source_output_info_cb,
+ control);
+ } else {
+ o = pa_context_get_source_output_info (control->priv->pa_context,
+ index,
+ _pa_context_get_source_output_info_cb,
+ control);
+ }
+
+ if (o == NULL) {
+ g_warning ("pa_context_get_source_output_info_list() failed");
+ return;
+ }
+ pa_operation_unref (o);
+}
+
+static void
+remove_client (GvcMixerControl *control,
+ guint index)
+{
+ g_hash_table_remove (control->priv->clients,
+ GUINT_TO_POINTER (index));
+}
+
+static void
+remove_card (GvcMixerControl *control,
+ guint index)
+{
+ g_hash_table_remove (control->priv->cards,
+ GUINT_TO_POINTER (index));
+
+ g_signal_emit (G_OBJECT (control),
+ signals[CARD_REMOVED],
+ 0,
+ index);
+}
+
+static void
+remove_sink (GvcMixerControl *control,
+ guint index)
+{
+ GvcMixerStream *stream;
+
+#if 0
+ g_debug ("Removing sink: index=%u", index);
+#endif
+
+ stream = g_hash_table_lookup (control->priv->sinks,
+ GUINT_TO_POINTER (index));
+ if (stream == NULL) {
+ return;
+ }
+ g_hash_table_remove (control->priv->sinks,
+ GUINT_TO_POINTER (index));
+
+ remove_stream (control, stream);
+}
+
+static void
+remove_source (GvcMixerControl *control,
+ guint index)
+{
+ GvcMixerStream *stream;
+
+#if 0
+ g_debug ("Removing source: index=%u", index);
+#endif
+
+ stream = g_hash_table_lookup (control->priv->sources,
+ GUINT_TO_POINTER (index));
+ if (stream == NULL) {
+ return;
+ }
+ g_hash_table_remove (control->priv->sources,
+ GUINT_TO_POINTER (index));
+
+ remove_stream (control, stream);
+}
+
+static void
+remove_sink_input (GvcMixerControl *control,
+ guint index)
+{
+ GvcMixerStream *stream;
+
+#if 0
+ g_debug ("Removing sink input: index=%u", index);
+#endif
+ stream = g_hash_table_lookup (control->priv->sink_inputs,
+ GUINT_TO_POINTER (index));
+ if (stream == NULL) {
+ return;
+ }
+ g_hash_table_remove (control->priv->sink_inputs,
+ GUINT_TO_POINTER (index));
+
+ remove_stream (control, stream);
+}
+
+static void
+remove_source_output (GvcMixerControl *control,
+ guint index)
+{
+ GvcMixerStream *stream;
+
+#if 0
+ g_debug ("Removing source output: index=%u", index);
+#endif
+
+ stream = g_hash_table_lookup (control->priv->source_outputs,
+ GUINT_TO_POINTER (index));
+ if (stream == NULL) {
+ return;
+ }
+ g_hash_table_remove (control->priv->source_outputs,
+ GUINT_TO_POINTER (index));
+
+ remove_stream (control, stream);
+}
+
+static void
+_pa_context_subscribe_cb (pa_context *context,
+ pa_subscription_event_type_t t,
+ uint32_t index,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
+ case PA_SUBSCRIPTION_EVENT_SINK:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ remove_sink (control, index);
+ } else {
+ req_update_sink_info (control, index);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_SOURCE:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ remove_source (control, index);
+ } else {
+ req_update_source_info (control, index);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ remove_sink_input (control, index);
+ } else {
+ req_update_sink_input_info (control, index);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ remove_source_output (control, index);
+ } else {
+ req_update_source_output_info (control, index);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_CLIENT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ remove_client (control, index);
+ } else {
+ req_update_client_info (control, index);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_SERVER:
+ req_update_server_info (control, index);
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_CARD:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ remove_card (control, index);
+ } else {
+ req_update_card (control, index);
+ }
+ break;
+ }
+}
+
+static void
+gvc_mixer_control_ready (GvcMixerControl *control)
+{
+ pa_operation *o;
+
+ pa_context_set_subscribe_callback (control->priv->pa_context,
+ _pa_context_subscribe_cb,
+ control);
+ o = pa_context_subscribe (control->priv->pa_context,
+ (pa_subscription_mask_t)
+ (PA_SUBSCRIPTION_MASK_SINK|
+ PA_SUBSCRIPTION_MASK_SOURCE|
+ PA_SUBSCRIPTION_MASK_SINK_INPUT|
+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
+ PA_SUBSCRIPTION_MASK_CLIENT|
+ PA_SUBSCRIPTION_MASK_SERVER|
+ PA_SUBSCRIPTION_MASK_CARD),
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_subscribe() failed");
+ return;
+ }
+ pa_operation_unref (o);
+
+ req_update_server_info (control, -1);
+ req_update_client_info (control, -1);
+ req_update_sink_info (control, -1);
+ req_update_source_info (control, -1);
+ req_update_sink_input_info (control, -1);
+ req_update_source_output_info (control, -1);
+ req_update_card (control, -1);
+
+ control->priv->n_outstanding = 6;
+
+ /* This call is not always supported */
+ o = pa_ext_stream_restore_read (control->priv->pa_context,
+ _pa_ext_stream_restore_read_cb,
+ control);
+ if (o != NULL) {
+ pa_operation_unref (o);
+ control->priv->n_outstanding++;
+
+ pa_ext_stream_restore_set_subscribe_cb (control->priv->pa_context,
+ _pa_ext_stream_restore_subscribe_cb,
+ control);
+
+ o = pa_ext_stream_restore_subscribe (control->priv->pa_context,
+ 1,
+ NULL,
+ NULL);
+ if (o != NULL) {
+ pa_operation_unref (o);
+ }
+
+ } else {
+ g_debug ("Failed to initialized stream_restore extension: %s",
+ pa_strerror (pa_context_errno (control->priv->pa_context)));
+ }
+}
+
+static void
+gvc_mixer_new_pa_context (GvcMixerControl *self)
+{
+ pa_proplist *proplist;
+
+ g_return_if_fail (self);
+ g_return_if_fail (!self->priv->pa_context);
+
+ proplist = pa_proplist_new ();
+ pa_proplist_sets (proplist,
+ PA_PROP_APPLICATION_NAME,
+ self->priv->name);
+ pa_proplist_sets (proplist,
+ PA_PROP_APPLICATION_ID,
+ "org.mate.VolumeControl");
+ pa_proplist_sets (proplist,
+ PA_PROP_APPLICATION_ICON_NAME,
+ "multimedia-volume-control");
+ pa_proplist_sets (proplist,
+ PA_PROP_APPLICATION_VERSION,
+ PACKAGE_VERSION);
+
+ self->priv->pa_context = pa_context_new_with_proplist (self->priv->pa_api, NULL, proplist);
+
+ pa_proplist_free (proplist);
+ g_assert (self->priv->pa_context);
+}
+
+static void
+remove_all_streams (GvcMixerControl *control, GHashTable *hash_table)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, hash_table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ remove_stream (control, value);
+ g_hash_table_iter_remove (&iter);
+ }
+}
+
+static gboolean
+idle_reconnect (gpointer data)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (data);
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_return_val_if_fail (control, FALSE);
+
+ if (control->priv->pa_context) {
+ pa_context_unref (control->priv->pa_context);
+ control->priv->pa_context = NULL;
+ gvc_mixer_new_pa_context (control);
+ }
+
+ remove_all_streams (control, control->priv->sinks);
+ remove_all_streams (control, control->priv->sources);
+ remove_all_streams (control, control->priv->sink_inputs);
+ remove_all_streams (control, control->priv->source_outputs);
+
+ g_hash_table_iter_init (&iter, control->priv->clients);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ g_hash_table_iter_remove (&iter);
+
+ gvc_mixer_control_open (control); /* cannot fail */
+
+ control->priv->reconnect_id = 0;
+ return FALSE;
+}
+
+static void
+_pa_context_state_cb (pa_context *context,
+ void *userdata)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (userdata);
+
+ switch (pa_context_get_state (context)) {
+ case PA_CONTEXT_UNCONNECTED:
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY:
+ gvc_mixer_control_ready (control);
+ break;
+
+ case PA_CONTEXT_FAILED:
+ g_warning ("Connection failed, reconnecting...");
+ if (control->priv->reconnect_id == 0)
+ control->priv->reconnect_id = g_timeout_add_seconds (RECONNECT_DELAY, idle_reconnect, control);
+ break;
+
+ case PA_CONTEXT_TERMINATED:
+ default:
+ /* FIXME: */
+ break;
+ }
+}
+
+gboolean
+gvc_mixer_control_open (GvcMixerControl *control)
+{
+ int res;
+
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+ g_return_val_if_fail (control->priv->pa_context != NULL, FALSE);
+ g_return_val_if_fail (pa_context_get_state (control->priv->pa_context) == PA_CONTEXT_UNCONNECTED, FALSE);
+
+ pa_context_set_state_callback (control->priv->pa_context,
+ _pa_context_state_cb,
+ control);
+
+ g_signal_emit (G_OBJECT (control), signals[CONNECTING], 0);
+ res = pa_context_connect (control->priv->pa_context, NULL, (pa_context_flags_t) PA_CONTEXT_NOFAIL, NULL);
+ if (res < 0) {
+ g_warning ("Failed to connect context: %s",
+ pa_strerror (pa_context_errno (control->priv->pa_context)));
+ }
+
+ return res;
+}
+
+gboolean
+gvc_mixer_control_close (GvcMixerControl *control)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+ g_return_val_if_fail (control->priv->pa_context != NULL, FALSE);
+
+ pa_context_disconnect (control->priv->pa_context);
+ return TRUE;
+}
+
+static void
+gvc_mixer_control_dispose (GObject *object)
+{
+ GvcMixerControl *control = GVC_MIXER_CONTROL (object);
+
+ if (control->priv->pa_context != NULL) {
+ pa_context_unref (control->priv->pa_context);
+ control->priv->pa_context = NULL;
+ }
+
+ if (control->priv->default_source_name != NULL) {
+ g_free (control->priv->default_source_name);
+ control->priv->default_source_name = NULL;
+ }
+ if (control->priv->default_sink_name != NULL) {
+ g_free (control->priv->default_sink_name);
+ control->priv->default_sink_name = NULL;
+ }
+
+ if (control->priv->pa_mainloop != NULL) {
+ pa_glib_mainloop_free (control->priv->pa_mainloop);
+ control->priv->pa_mainloop = NULL;
+ }
+
+ if (control->priv->all_streams != NULL) {
+ g_hash_table_destroy (control->priv->all_streams);
+ control->priv->all_streams = NULL;
+ }
+
+ if (control->priv->sinks != NULL) {
+ g_hash_table_destroy (control->priv->sinks);
+ control->priv->sinks = NULL;
+ }
+ if (control->priv->sources != NULL) {
+ g_hash_table_destroy (control->priv->sources);
+ control->priv->sources = NULL;
+ }
+ if (control->priv->sink_inputs != NULL) {
+ g_hash_table_destroy (control->priv->sink_inputs);
+ control->priv->sink_inputs = NULL;
+ }
+ if (control->priv->source_outputs != NULL) {
+ g_hash_table_destroy (control->priv->source_outputs);
+ control->priv->source_outputs = NULL;
+ }
+ if (control->priv->clients != NULL) {
+ g_hash_table_destroy (control->priv->clients);
+ control->priv->clients = NULL;
+ }
+ if (control->priv->cards != NULL) {
+ g_hash_table_destroy (control->priv->cards);
+ control->priv->cards = NULL;
+ }
+
+ G_OBJECT_CLASS (gvc_mixer_control_parent_class)->dispose (object);
+}
+
+static void
+gvc_mixer_control_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerControl *self = GVC_MIXER_CONTROL (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_free (self->priv->name);
+ self->priv->name = g_value_dup_string (value);
+ g_object_notify (G_OBJECT (self), "name");
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gvc_mixer_control_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerControl *self = GVC_MIXER_CONTROL (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, self->priv->name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static GObject *
+gvc_mixer_control_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerControl *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_control_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_CONTROL (object);
+
+ gvc_mixer_new_pa_context (self);
+
+ return object;
+}
+
+static void
+gvc_mixer_control_class_init (GvcMixerControlClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = gvc_mixer_control_constructor;
+ object_class->dispose = gvc_mixer_control_dispose;
+ object_class->finalize = gvc_mixer_control_finalize;
+ object_class->set_property = gvc_mixer_control_set_property;
+ object_class->get_property = gvc_mixer_control_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "Name to display for this mixer control",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+ signals [CONNECTING] =
+ g_signal_new ("connecting",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, connecting),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [READY] =
+ g_signal_new ("ready",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, ready),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [STREAM_ADDED] =
+ g_signal_new ("stream-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, stream_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals [STREAM_REMOVED] =
+ g_signal_new ("stream-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, stream_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals [CARD_ADDED] =
+ g_signal_new ("card-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, card_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals [CARD_REMOVED] =
+ g_signal_new ("card-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, card_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals [DEFAULT_SINK_CHANGED] =
+ g_signal_new ("default-sink-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, default_sink_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals [DEFAULT_SOURCE_CHANGED] =
+ g_signal_new ("default-source-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, default_source_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+ g_type_class_add_private (klass, sizeof (GvcMixerControlPrivate));
+}
+
+static void
+gvc_mixer_control_init (GvcMixerControl *control)
+{
+ control->priv = GVC_MIXER_CONTROL_GET_PRIVATE (control);
+
+ control->priv->pa_mainloop = pa_glib_mainloop_new (g_main_context_default ());
+ g_assert (control->priv->pa_mainloop);
+
+ control->priv->pa_api = pa_glib_mainloop_get_api (control->priv->pa_mainloop);
+ g_assert (control->priv->pa_api);
+
+ control->priv->all_streams = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+ control->priv->sinks = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+ control->priv->sources = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+ control->priv->sink_inputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+ control->priv->source_outputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+ control->priv->cards = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+
+ control->priv->clients = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_free);
+}
+
+static void
+gvc_mixer_control_finalize (GObject *object)
+{
+ GvcMixerControl *mixer_control;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_CONTROL (object));
+
+ mixer_control = GVC_MIXER_CONTROL (object);
+ g_free (mixer_control->priv->name);
+ mixer_control->priv->name = NULL;
+
+ g_return_if_fail (mixer_control->priv != NULL);
+ G_OBJECT_CLASS (gvc_mixer_control_parent_class)->finalize (object);
+}
+
+GvcMixerControl *
+gvc_mixer_control_new (const char *name)
+{
+ GObject *control;
+ control = g_object_new (GVC_TYPE_MIXER_CONTROL,
+ "name", name,
+ NULL);
+ return GVC_MIXER_CONTROL (control);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-control.h b/plugins/media-keys/cut-n-paste/gvc-mixer-control.h
new file mode 100644
index 0000000..95dc756
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-control.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_CONTROL_H
+#define __GVC_MIXER_CONTROL_H
+
+#include <glib-object.h>
+#include <pulse/pulseaudio.h>
+#include "gvc-mixer-stream.h"
+#include "gvc-mixer-card.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_CONTROL (gvc_mixer_control_get_type ())
+#define GVC_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControl))
+#define GVC_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass))
+#define GVC_IS_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CONTROL))
+#define GVC_IS_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CONTROL))
+#define GVC_MIXER_CONTROL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass))
+
+typedef struct GvcMixerControlPrivate GvcMixerControlPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GvcMixerControlPrivate *priv;
+} GvcMixerControl;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (*connecting) (GvcMixerControl *control);
+ void (*ready) (GvcMixerControl *control);
+ void (*stream_added) (GvcMixerControl *control,
+ guint id);
+ void (*stream_removed) (GvcMixerControl *control,
+ guint id);
+ void (*card_added) (GvcMixerControl *control,
+ guint id);
+ void (*card_removed) (GvcMixerControl *control,
+ guint id);
+ void (*default_sink_changed) (GvcMixerControl *control,
+ guint id);
+ void (*default_source_changed) (GvcMixerControl *control,
+ guint id);
+} GvcMixerControlClass;
+
+GType gvc_mixer_control_get_type (void);
+
+GvcMixerControl * gvc_mixer_control_new (const char *name);
+
+gboolean gvc_mixer_control_open (GvcMixerControl *control);
+gboolean gvc_mixer_control_close (GvcMixerControl *control);
+gboolean gvc_mixer_control_is_ready (GvcMixerControl *control);
+
+pa_context * gvc_mixer_control_get_pa_context (GvcMixerControl *control);
+GSList * gvc_mixer_control_get_cards (GvcMixerControl *control);
+GSList * gvc_mixer_control_get_streams (GvcMixerControl *control);
+GSList * gvc_mixer_control_get_sinks (GvcMixerControl *control);
+GSList * gvc_mixer_control_get_sources (GvcMixerControl *control);
+GSList * gvc_mixer_control_get_sink_inputs (GvcMixerControl *control);
+GSList * gvc_mixer_control_get_source_outputs (GvcMixerControl *control);
+
+GvcMixerStream * gvc_mixer_control_lookup_stream_id (GvcMixerControl *control,
+ guint id);
+GvcMixerCard * gvc_mixer_control_lookup_card_id (GvcMixerControl *control,
+ guint id);
+
+GvcMixerStream * gvc_mixer_control_get_default_sink (GvcMixerControl *control);
+GvcMixerStream * gvc_mixer_control_get_default_source (GvcMixerControl *control);
+GvcMixerStream * gvc_mixer_control_get_event_sink_input (GvcMixerControl *control);
+
+gboolean gvc_mixer_control_set_default_sink (GvcMixerControl *control,
+ GvcMixerStream *stream);
+gboolean gvc_mixer_control_set_default_source (GvcMixerControl *control,
+ GvcMixerStream *stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_CONTROL_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c
new file mode 100644
index 0000000..69e38ce
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c
@@ -0,0 +1,239 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+#include <pulse/ext-stream-restore.h>
+
+#include "gvc-mixer-event-role.h"
+
+#define GVC_MIXER_EVENT_ROLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRolePrivate))
+
+struct GvcMixerEventRolePrivate
+{
+ char *device;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE
+};
+
+static void gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass);
+static void gvc_mixer_event_role_init (GvcMixerEventRole *mixer_event_role);
+static void gvc_mixer_event_role_finalize (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM)
+
+static gboolean
+update_settings (GvcMixerEventRole *role,
+ gboolean is_muted,
+ gpointer *op)
+{
+ pa_operation *o;
+ guint index;
+ GvcChannelMap *map;
+ pa_context *context;
+ pa_ext_stream_restore_info info;
+
+ index = gvc_mixer_stream_get_index (GVC_MIXER_STREAM (role));
+
+ map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role));
+
+ info.volume = *gvc_channel_map_get_cvolume(map);
+ info.name = "sink-input-by-media-role:event";
+ info.channel_map = *gvc_channel_map_get_pa_channel_map(map);
+ info.device = role->priv->device;
+ info.mute = is_muted;
+
+ context = gvc_mixer_stream_get_pa_context (GVC_MIXER_STREAM (role));
+
+ o = pa_ext_stream_restore_write (context,
+ PA_UPDATE_REPLACE,
+ &info,
+ 1,
+ TRUE,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_ext_stream_restore_write() failed");
+ return FALSE;
+ }
+
+ if (op != NULL)
+ *op = o;
+
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_event_role_push_volume (GvcMixerStream *stream, gpointer *op)
+{
+ return update_settings (GVC_MIXER_EVENT_ROLE (stream),
+ gvc_mixer_stream_get_is_muted (stream), op);
+}
+
+static gboolean
+gvc_mixer_event_role_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ return update_settings (GVC_MIXER_EVENT_ROLE (stream),
+ is_muted, NULL);
+}
+
+static gboolean
+gvc_mixer_event_role_set_device (GvcMixerEventRole *role,
+ const char *device)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_EVENT_ROLE (role), FALSE);
+
+ g_free (role->priv->device);
+ role->priv->device = g_strdup (device);
+ g_object_notify (G_OBJECT (role), "device");
+
+ return TRUE;
+}
+
+static void
+gvc_mixer_event_role_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ gvc_mixer_event_role_set_device (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gvc_mixer_event_role_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, self->priv->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gvc_mixer_event_role_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerEventRole *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_EVENT_ROLE (object);
+
+ return object;
+}
+
+static void
+gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
+
+ object_class->constructor = gvc_mixer_event_role_constructor;
+ object_class->finalize = gvc_mixer_event_role_finalize;
+ object_class->set_property = gvc_mixer_event_role_set_property;
+ object_class->get_property = gvc_mixer_event_role_get_property;
+
+ stream_class->push_volume = gvc_mixer_event_role_push_volume;
+ stream_class->change_is_muted = gvc_mixer_event_role_change_is_muted;
+
+ g_object_class_install_property (object_class,
+ PROP_DEVICE,
+ g_param_spec_string ("device",
+ "Device",
+ "Device",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+
+ g_type_class_add_private (klass, sizeof (GvcMixerEventRolePrivate));
+}
+
+static void
+gvc_mixer_event_role_init (GvcMixerEventRole *event_role)
+{
+ event_role->priv = GVC_MIXER_EVENT_ROLE_GET_PRIVATE (event_role);
+
+}
+
+static void
+gvc_mixer_event_role_finalize (GObject *object)
+{
+ GvcMixerEventRole *mixer_event_role;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_EVENT_ROLE (object));
+
+ mixer_event_role = GVC_MIXER_EVENT_ROLE (object);
+
+ g_return_if_fail (mixer_event_role->priv != NULL);
+
+ g_free (mixer_event_role->priv->device);
+
+ G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->finalize (object);
+}
+
+GvcMixerStream *
+gvc_mixer_event_role_new (pa_context *context,
+ const char *device,
+ GvcChannelMap *channel_map)
+{
+ GObject *object;
+
+ object = g_object_new (GVC_TYPE_MIXER_EVENT_ROLE,
+ "pa-context", context,
+ "index", 0,
+ "device", device,
+ "channel-map", channel_map,
+ NULL);
+
+ return GVC_MIXER_STREAM (object);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h
new file mode 100644
index 0000000..ee91fa8
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_EVENT_ROLE_H
+#define __GVC_MIXER_EVENT_ROLE_H
+
+#include <glib-object.h>
+#include "gvc-mixer-stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_EVENT_ROLE (gvc_mixer_event_role_get_type ())
+#define GVC_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRole))
+#define GVC_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass))
+#define GVC_IS_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_EVENT_ROLE))
+#define GVC_IS_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_EVENT_ROLE))
+#define GVC_MIXER_EVENT_ROLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass))
+
+typedef struct GvcMixerEventRolePrivate GvcMixerEventRolePrivate;
+
+typedef struct
+{
+ GvcMixerStream parent;
+ GvcMixerEventRolePrivate *priv;
+} GvcMixerEventRole;
+
+typedef struct
+{
+ GvcMixerStreamClass parent_class;
+} GvcMixerEventRoleClass;
+
+GType gvc_mixer_event_role_get_type (void);
+
+GvcMixerStream * gvc_mixer_event_role_new (pa_context *context,
+ const char *device,
+ GvcChannelMap *channel_map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_EVENT_ROLE_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c b/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c
new file mode 100644
index 0000000..35551bb
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c
@@ -0,0 +1,188 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-mixer-sink-input.h"
+
+#define GVC_MIXER_SINK_INPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputPrivate))
+
+struct GvcMixerSinkInputPrivate
+{
+ gpointer dummy;
+};
+
+static void gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass);
+static void gvc_mixer_sink_input_init (GvcMixerSinkInput *mixer_sink_input);
+static void gvc_mixer_sink_input_finalize (GObject *object);
+static void gvc_mixer_sink_input_dispose (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM)
+
+static gboolean
+gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op)
+{
+ pa_operation *o;
+ guint index;
+ GvcChannelMap *map;
+ pa_context *context;
+ const pa_cvolume *cv;
+ guint num_channels;
+
+ index = gvc_mixer_stream_get_index (stream);
+
+ map = gvc_mixer_stream_get_channel_map (stream);
+ num_channels = gvc_channel_map_get_num_channels (map);
+
+ cv = gvc_channel_map_get_cvolume(map);
+
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_sink_input_volume (context,
+ index,
+ cv,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_sink_input_volume() failed");
+ return FALSE;
+ }
+
+ *op = o;
+
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_sink_input_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ pa_operation *o;
+ guint index;
+ pa_context *context;
+
+ index = gvc_mixer_stream_get_index (stream);
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_sink_input_mute (context,
+ index,
+ is_muted,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_sink_input_mute_by_index() failed");
+ return FALSE;
+ }
+
+ pa_operation_unref(o);
+
+ return TRUE;
+}
+
+static GObject *
+gvc_mixer_sink_input_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerSinkInput *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_SINK_INPUT (object);
+
+ return object;
+}
+
+static void
+gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
+
+ object_class->constructor = gvc_mixer_sink_input_constructor;
+ object_class->dispose = gvc_mixer_sink_input_dispose;
+ object_class->finalize = gvc_mixer_sink_input_finalize;
+
+ stream_class->push_volume = gvc_mixer_sink_input_push_volume;
+ stream_class->change_is_muted = gvc_mixer_sink_input_change_is_muted;
+
+ g_type_class_add_private (klass, sizeof (GvcMixerSinkInputPrivate));
+}
+
+static void
+gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input)
+{
+ sink_input->priv = GVC_MIXER_SINK_INPUT_GET_PRIVATE (sink_input);
+}
+
+static void
+gvc_mixer_sink_input_dispose (GObject *object)
+{
+ GvcMixerSinkInput *mixer_sink_input;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object));
+
+ mixer_sink_input = GVC_MIXER_SINK_INPUT (object);
+
+ G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->dispose (object);
+}
+
+static void
+gvc_mixer_sink_input_finalize (GObject *object)
+{
+ GvcMixerSinkInput *mixer_sink_input;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object));
+
+ mixer_sink_input = GVC_MIXER_SINK_INPUT (object);
+
+ g_return_if_fail (mixer_sink_input->priv != NULL);
+ G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->finalize (object);
+}
+
+GvcMixerStream *
+gvc_mixer_sink_input_new (pa_context *context,
+ guint index,
+ GvcChannelMap *channel_map)
+{
+ GObject *object;
+
+ object = g_object_new (GVC_TYPE_MIXER_SINK_INPUT,
+ "pa-context", context,
+ "index", index,
+ "channel-map", channel_map,
+ NULL);
+
+ return GVC_MIXER_STREAM (object);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.h b/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.h
new file mode 100644
index 0000000..6e44811
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_SINK_INPUT_H
+#define __GVC_MIXER_SINK_INPUT_H
+
+#include <glib-object.h>
+#include "gvc-mixer-stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_SINK_INPUT (gvc_mixer_sink_input_get_type ())
+#define GVC_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInput))
+#define GVC_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass))
+#define GVC_IS_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK_INPUT))
+#define GVC_IS_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK_INPUT))
+#define GVC_MIXER_SINK_INPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass))
+
+typedef struct GvcMixerSinkInputPrivate GvcMixerSinkInputPrivate;
+
+typedef struct
+{
+ GvcMixerStream parent;
+ GvcMixerSinkInputPrivate *priv;
+} GvcMixerSinkInput;
+
+typedef struct
+{
+ GvcMixerStreamClass parent_class;
+} GvcMixerSinkInputClass;
+
+GType gvc_mixer_sink_input_get_type (void);
+
+GvcMixerStream * gvc_mixer_sink_input_new (pa_context *context,
+ guint index,
+ GvcChannelMap *map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_SINK_INPUT_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c b/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c
new file mode 100644
index 0000000..5e95f63
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-mixer-sink.h"
+
+#define GVC_MIXER_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkPrivate))
+
+struct GvcMixerSinkPrivate
+{
+ gpointer dummy;
+};
+
+static void gvc_mixer_sink_class_init (GvcMixerSinkClass *klass);
+static void gvc_mixer_sink_init (GvcMixerSink *mixer_sink);
+static void gvc_mixer_sink_finalize (GObject *object);
+static void gvc_mixer_sink_dispose (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM)
+
+static gboolean
+gvc_mixer_sink_push_volume (GvcMixerStream *stream, gpointer *op)
+{
+ pa_operation *o;
+ guint index;
+ GvcChannelMap *map;
+ pa_context *context;
+ const pa_cvolume *cv;
+
+ index = gvc_mixer_stream_get_index (stream);
+
+ map = gvc_mixer_stream_get_channel_map (stream);
+
+ /* set the volume */
+ cv = gvc_channel_map_get_cvolume(map);
+
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_sink_volume_by_index (context,
+ index,
+ cv,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_sink_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
+ return FALSE;
+ }
+
+ *op = o;
+
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_sink_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ pa_operation *o;
+ guint index;
+ pa_context *context;
+
+ index = gvc_mixer_stream_get_index (stream);
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_sink_mute_by_index (context,
+ index,
+ is_muted,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_sink_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
+ return FALSE;
+ }
+
+ pa_operation_unref(o);
+
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_sink_change_port (GvcMixerStream *stream,
+ const char *port)
+{
+#if PA_MICRO > 15
+ pa_operation *o;
+ guint index;
+ pa_context *context;
+
+ index = gvc_mixer_stream_get_index (stream);
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_sink_port_by_index (context,
+ index,
+ port,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_sink_port_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
+ return FALSE;
+ }
+
+ pa_operation_unref(o);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif /* PA_MICRO > 15 */
+}
+
+static GObject *
+gvc_mixer_sink_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerSink *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_SINK (object);
+
+ return object;
+}
+
+static void
+gvc_mixer_sink_class_init (GvcMixerSinkClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
+
+ object_class->constructor = gvc_mixer_sink_constructor;
+ object_class->dispose = gvc_mixer_sink_dispose;
+ object_class->finalize = gvc_mixer_sink_finalize;
+
+ stream_class->push_volume = gvc_mixer_sink_push_volume;
+ stream_class->change_port = gvc_mixer_sink_change_port;
+ stream_class->change_is_muted = gvc_mixer_sink_change_is_muted;
+
+ g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate));
+}
+
+static void
+gvc_mixer_sink_init (GvcMixerSink *sink)
+{
+ sink->priv = GVC_MIXER_SINK_GET_PRIVATE (sink);
+}
+
+static void
+gvc_mixer_sink_dispose (GObject *object)
+{
+ GvcMixerSink *mixer_sink;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SINK (object));
+
+ mixer_sink = GVC_MIXER_SINK (object);
+
+ G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->dispose (object);
+}
+
+static void
+gvc_mixer_sink_finalize (GObject *object)
+{
+ GvcMixerSink *mixer_sink;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SINK (object));
+
+ mixer_sink = GVC_MIXER_SINK (object);
+
+ g_return_if_fail (mixer_sink->priv != NULL);
+ G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->finalize (object);
+}
+
+GvcMixerStream *
+gvc_mixer_sink_new (pa_context *context,
+ guint index,
+ GvcChannelMap *channel_map)
+
+{
+ GObject *object;
+
+ object = g_object_new (GVC_TYPE_MIXER_SINK,
+ "pa-context", context,
+ "index", index,
+ "channel-map", channel_map,
+ NULL);
+
+ return GVC_MIXER_STREAM (object);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-sink.h b/plugins/media-keys/cut-n-paste/gvc-mixer-sink.h
new file mode 100644
index 0000000..1e457dc
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-sink.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_SINK_H
+#define __GVC_MIXER_SINK_H
+
+#include <glib-object.h>
+#include "gvc-mixer-stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_SINK (gvc_mixer_sink_get_type ())
+#define GVC_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK, GvcMixerSink))
+#define GVC_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass))
+#define GVC_IS_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK))
+#define GVC_IS_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK))
+#define GVC_MIXER_SINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass))
+
+typedef struct GvcMixerSinkPrivate GvcMixerSinkPrivate;
+
+typedef struct
+{
+ GvcMixerStream parent;
+ GvcMixerSinkPrivate *priv;
+} GvcMixerSink;
+
+typedef struct
+{
+ GvcMixerStreamClass parent_class;
+} GvcMixerSinkClass;
+
+GType gvc_mixer_sink_get_type (void);
+
+GvcMixerStream * gvc_mixer_sink_new (pa_context *context,
+ guint index,
+ GvcChannelMap *map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_SINK_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c b/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c
new file mode 100644
index 0000000..b4cc34d
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c
@@ -0,0 +1,128 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-mixer-source-output.h"
+
+#define GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputPrivate))
+
+struct GvcMixerSourceOutputPrivate
+{
+ gpointer dummy;
+};
+
+static void gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass);
+static void gvc_mixer_source_output_init (GvcMixerSourceOutput *mixer_source_output);
+static void gvc_mixer_source_output_finalize (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerSourceOutput, gvc_mixer_source_output, GVC_TYPE_MIXER_STREAM)
+
+static gboolean
+gvc_mixer_source_output_push_volume (GvcMixerStream *stream, gpointer *op)
+{
+ /* FIXME: */
+ *op = NULL;
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_source_output_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ /* FIXME: */
+ return TRUE;
+}
+
+static GObject *
+gvc_mixer_source_output_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerSourceOutput *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_SOURCE_OUTPUT (object);
+
+ return object;
+}
+
+static void
+gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
+
+ object_class->constructor = gvc_mixer_source_output_constructor;
+ object_class->finalize = gvc_mixer_source_output_finalize;
+
+ stream_class->push_volume = gvc_mixer_source_output_push_volume;
+ stream_class->change_is_muted = gvc_mixer_source_output_change_is_muted;
+
+ g_type_class_add_private (klass, sizeof (GvcMixerSourceOutputPrivate));
+}
+
+static void
+gvc_mixer_source_output_init (GvcMixerSourceOutput *source_output)
+{
+ source_output->priv = GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE (source_output);
+
+}
+
+static void
+gvc_mixer_source_output_finalize (GObject *object)
+{
+ GvcMixerSourceOutput *mixer_source_output;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SOURCE_OUTPUT (object));
+
+ mixer_source_output = GVC_MIXER_SOURCE_OUTPUT (object);
+
+ g_return_if_fail (mixer_source_output->priv != NULL);
+ G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->finalize (object);
+}
+
+GvcMixerStream *
+gvc_mixer_source_output_new (pa_context *context,
+ guint index,
+ GvcChannelMap *channel_map)
+{
+ GObject *object;
+
+ object = g_object_new (GVC_TYPE_MIXER_SOURCE_OUTPUT,
+ "pa-context", context,
+ "index", index,
+ "channel-map", channel_map,
+ NULL);
+
+ return GVC_MIXER_STREAM (object);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.h b/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.h
new file mode 100644
index 0000000..6ebaca9
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_SOURCE_OUTPUT_H
+#define __GVC_MIXER_SOURCE_OUTPUT_H
+
+#include <glib-object.h>
+#include "gvc-mixer-stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_SOURCE_OUTPUT (gvc_mixer_source_output_get_type ())
+#define GVC_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutput))
+#define GVC_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass))
+#define GVC_IS_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT))
+#define GVC_IS_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE_OUTPUT))
+#define GVC_MIXER_SOURCE_OUTPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass))
+
+typedef struct GvcMixerSourceOutputPrivate GvcMixerSourceOutputPrivate;
+
+typedef struct
+{
+ GvcMixerStream parent;
+ GvcMixerSourceOutputPrivate *priv;
+} GvcMixerSourceOutput;
+
+typedef struct
+{
+ GvcMixerStreamClass parent_class;
+} GvcMixerSourceOutputClass;
+
+GType gvc_mixer_source_output_get_type (void);
+
+GvcMixerStream * gvc_mixer_source_output_new (pa_context *context,
+ guint index,
+ GvcChannelMap *map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_SOURCE_OUTPUT_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-source.c b/plugins/media-keys/cut-n-paste/gvc-mixer-source.c
new file mode 100644
index 0000000..d13be9d
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-source.c
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-mixer-source.h"
+
+#define GVC_MIXER_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourcePrivate))
+
+struct GvcMixerSourcePrivate
+{
+ gpointer dummy;
+};
+
+static void gvc_mixer_source_class_init (GvcMixerSourceClass *klass);
+static void gvc_mixer_source_init (GvcMixerSource *mixer_source);
+static void gvc_mixer_source_finalize (GObject *object);
+static void gvc_mixer_source_dispose (GObject *object);
+
+G_DEFINE_TYPE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM)
+
+static gboolean
+gvc_mixer_source_push_volume (GvcMixerStream *stream, gpointer *op)
+{
+ pa_operation *o;
+ guint index;
+ GvcChannelMap *map;
+ pa_context *context;
+ const pa_cvolume *cv;
+
+ index = gvc_mixer_stream_get_index (stream);
+
+ map = gvc_mixer_stream_get_channel_map (stream);
+
+ /* set the volume */
+ cv = gvc_channel_map_get_cvolume (map);
+
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_source_volume_by_index (context,
+ index,
+ cv,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_source_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
+ return FALSE;
+ }
+
+ *op = o;
+
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_source_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ pa_operation *o;
+ guint index;
+ pa_context *context;
+
+ index = gvc_mixer_stream_get_index (stream);
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_source_mute_by_index (context,
+ index,
+ is_muted,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_source_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
+ return FALSE;
+ }
+
+ pa_operation_unref(o);
+
+ return TRUE;
+}
+
+static gboolean
+gvc_mixer_source_change_port (GvcMixerStream *stream,
+ const char *port)
+{
+#if PA_MICRO > 15
+ pa_operation *o;
+ guint index;
+ pa_context *context;
+
+ index = gvc_mixer_stream_get_index (stream);
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ o = pa_context_set_source_port_by_index (context,
+ index,
+ port,
+ NULL,
+ NULL);
+
+ if (o == NULL) {
+ g_warning ("pa_context_set_source_port_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
+ return FALSE;
+ }
+
+ pa_operation_unref(o);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif /* PA_MICRO > 15 */
+}
+
+static GObject *
+gvc_mixer_source_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerSource *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_source_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_SOURCE (object);
+
+ return object;
+}
+
+static void
+gvc_mixer_source_class_init (GvcMixerSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
+
+ object_class->constructor = gvc_mixer_source_constructor;
+ object_class->dispose = gvc_mixer_source_dispose;
+ object_class->finalize = gvc_mixer_source_finalize;
+
+ stream_class->push_volume = gvc_mixer_source_push_volume;
+ stream_class->change_is_muted = gvc_mixer_source_change_is_muted;
+ stream_class->change_port = gvc_mixer_source_change_port;
+
+ g_type_class_add_private (klass, sizeof (GvcMixerSourcePrivate));
+}
+
+static void
+gvc_mixer_source_init (GvcMixerSource *source)
+{
+ source->priv = GVC_MIXER_SOURCE_GET_PRIVATE (source);
+}
+
+static void
+gvc_mixer_source_dispose (GObject *object)
+{
+ GvcMixerSource *mixer_source;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SOURCE (object));
+
+ mixer_source = GVC_MIXER_SOURCE (object);
+
+ G_OBJECT_CLASS (gvc_mixer_source_parent_class)->dispose (object);
+}
+
+static void
+gvc_mixer_source_finalize (GObject *object)
+{
+ GvcMixerSource *mixer_source;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_SOURCE (object));
+
+ mixer_source = GVC_MIXER_SOURCE (object);
+
+ g_return_if_fail (mixer_source->priv != NULL);
+ G_OBJECT_CLASS (gvc_mixer_source_parent_class)->finalize (object);
+}
+
+GvcMixerStream *
+gvc_mixer_source_new (pa_context *context,
+ guint index,
+ GvcChannelMap *channel_map)
+
+{
+ GObject *object;
+
+ object = g_object_new (GVC_TYPE_MIXER_SOURCE,
+ "pa-context", context,
+ "index", index,
+ "channel-map", channel_map,
+ NULL);
+
+ return GVC_MIXER_STREAM (object);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-source.h b/plugins/media-keys/cut-n-paste/gvc-mixer-source.h
new file mode 100644
index 0000000..502f31c
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-source.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_SOURCE_H
+#define __GVC_MIXER_SOURCE_H
+
+#include <glib-object.h>
+#include "gvc-mixer-stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_SOURCE (gvc_mixer_source_get_type ())
+#define GVC_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSource))
+#define GVC_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass))
+#define GVC_IS_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE))
+#define GVC_IS_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE))
+#define GVC_MIXER_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass))
+
+typedef struct GvcMixerSourcePrivate GvcMixerSourcePrivate;
+
+typedef struct
+{
+ GvcMixerStream parent;
+ GvcMixerSourcePrivate *priv;
+} GvcMixerSource;
+
+typedef struct
+{
+ GvcMixerStreamClass parent_class;
+} GvcMixerSourceClass;
+
+GType gvc_mixer_source_get_type (void);
+
+GvcMixerStream * gvc_mixer_source_new (pa_context *context,
+ guint index,
+ GvcChannelMap *map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_SOURCE_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
new file mode 100644
index 0000000..4662d46
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
@@ -0,0 +1,875 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pulse/pulseaudio.h>
+
+#include "gvc-mixer-stream.h"
+
+#define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate))
+
+static guint32 stream_serial = 1;
+
+struct GvcMixerStreamPrivate
+{
+ pa_context *pa_context;
+ guint id;
+ guint index;
+ GvcChannelMap *channel_map;
+ char *name;
+ char *description;
+ char *application_id;
+ char *icon_name;
+ gboolean is_muted;
+ gboolean can_decibel;
+ gboolean is_event_stream;
+ gboolean is_virtual;
+ pa_volume_t base_volume;
+ pa_operation *change_volume_op;
+ char *port;
+ char *human_port;
+ GList *ports;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ID,
+ PROP_PA_CONTEXT,
+ PROP_CHANNEL_MAP,
+ PROP_INDEX,
+ PROP_NAME,
+ PROP_DESCRIPTION,
+ PROP_APPLICATION_ID,
+ PROP_ICON_NAME,
+ PROP_VOLUME,
+ PROP_DECIBEL,
+ PROP_IS_MUTED,
+ PROP_CAN_DECIBEL,
+ PROP_IS_EVENT_STREAM,
+ PROP_IS_VIRTUAL,
+ PROP_PORT,
+};
+
+static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass);
+static void gvc_mixer_stream_init (GvcMixerStream *mixer_stream);
+static void gvc_mixer_stream_finalize (GObject *object);
+
+G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
+
+static guint32
+get_next_stream_serial (void)
+{
+ guint32 serial;
+
+ serial = stream_serial++;
+
+ if ((gint32)stream_serial < 0) {
+ stream_serial = 1;
+ }
+
+ return serial;
+}
+
+pa_context *
+gvc_mixer_stream_get_pa_context (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
+ return stream->priv->pa_context;
+}
+
+guint
+gvc_mixer_stream_get_index (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
+ return stream->priv->index;
+}
+
+guint
+gvc_mixer_stream_get_id (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
+ return stream->priv->id;
+}
+
+GvcChannelMap *
+gvc_mixer_stream_get_channel_map (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+ return stream->priv->channel_map;
+}
+
+pa_volume_t
+gvc_mixer_stream_get_volume (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
+
+ return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME];
+}
+
+gdouble
+gvc_mixer_stream_get_decibel (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
+
+ return pa_sw_volume_to_dB(
+ (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
+}
+
+gboolean
+gvc_mixer_stream_set_volume (GvcMixerStream *stream,
+ pa_volume_t volume)
+{
+ pa_cvolume cv;
+
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
+ pa_cvolume_scale(&cv, volume);
+
+ if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
+ gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
+ g_object_notify (G_OBJECT (stream), "volume");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
+ gdouble db)
+{
+ pa_cvolume cv;
+
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
+ pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db));
+
+ if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
+ gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
+ g_object_notify (G_OBJECT (stream), "volume");
+ }
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_stream_get_is_muted (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ return stream->priv->is_muted;
+}
+
+gboolean
+gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ return stream->priv->can_decibel;
+}
+
+gboolean
+gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ if (is_muted != stream->priv->is_muted) {
+ stream->priv->is_muted = is_muted;
+ g_object_notify (G_OBJECT (stream), "is-muted");
+ }
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream,
+ gboolean can_decibel)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ if (can_decibel != stream->priv->can_decibel) {
+ stream->priv->can_decibel = can_decibel;
+ g_object_notify (G_OBJECT (stream), "can-decibel");
+ }
+
+ return TRUE;
+}
+
+const char *
+gvc_mixer_stream_get_name (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+ return stream->priv->name;
+}
+
+const char *
+gvc_mixer_stream_get_description (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+ return stream->priv->description;
+}
+
+gboolean
+gvc_mixer_stream_set_name (GvcMixerStream *stream,
+ const char *name)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ g_free (stream->priv->name);
+ stream->priv->name = g_strdup (name);
+ g_object_notify (G_OBJECT (stream), "name");
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_stream_set_description (GvcMixerStream *stream,
+ const char *description)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ g_free (stream->priv->description);
+ stream->priv->description = g_strdup (description);
+ g_object_notify (G_OBJECT (stream), "description");
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_stream_is_event_stream (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ return stream->priv->is_event_stream;
+}
+
+gboolean
+gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
+ gboolean is_event_stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ stream->priv->is_event_stream = is_event_stream;
+ g_object_notify (G_OBJECT (stream), "is-event-stream");
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_stream_is_virtual (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ return stream->priv->is_virtual;
+}
+
+gboolean
+gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
+ gboolean is_virtual)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ stream->priv->is_virtual = is_virtual;
+ g_object_notify (G_OBJECT (stream), "is-virtual");
+
+ return TRUE;
+}
+
+const char *
+gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+ return stream->priv->application_id;
+}
+
+gboolean
+gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
+ const char *application_id)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ g_free (stream->priv->application_id);
+ stream->priv->application_id = g_strdup (application_id);
+ g_object_notify (G_OBJECT (stream), "application-id");
+
+ return TRUE;
+}
+
+static void
+on_channel_map_volume_changed (GvcChannelMap *channel_map,
+ gboolean set,
+ GvcMixerStream *stream)
+{
+ if (set == TRUE)
+ gvc_mixer_stream_push_volume (stream);
+
+ g_object_notify (G_OBJECT (stream), "volume");
+}
+
+static gboolean
+gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
+ GvcChannelMap *channel_map)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ if (channel_map != NULL) {
+ g_object_ref (channel_map);
+ }
+
+ if (stream->priv->channel_map != NULL) {
+ g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
+ on_channel_map_volume_changed,
+ stream);
+ g_object_unref (stream->priv->channel_map);
+ }
+
+ stream->priv->channel_map = channel_map;
+
+ if (stream->priv->channel_map != NULL) {
+ g_signal_connect (stream->priv->channel_map,
+ "volume-changed",
+ G_CALLBACK (on_channel_map_volume_changed),
+ stream);
+
+ g_object_notify (G_OBJECT (stream), "channel-map");
+ }
+
+ return TRUE;
+}
+
+const char *
+gvc_mixer_stream_get_icon_name (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+ return stream->priv->icon_name;
+}
+
+gboolean
+gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
+ const char *icon_name)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ g_free (stream->priv->icon_name);
+ stream->priv->icon_name = g_strdup (icon_name);
+ g_object_notify (G_OBJECT (stream), "icon-name");
+
+ return TRUE;
+}
+
+pa_volume_t
+gvc_mixer_stream_get_base_volume (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
+
+ return stream->priv->base_volume;
+}
+
+gboolean
+gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
+ pa_volume_t base_volume)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ stream->priv->base_volume = base_volume;
+
+ return TRUE;
+}
+
+GvcMixerStreamPort *
+gvc_mixer_stream_get_port (GvcMixerStream *stream)
+{
+ GList *l;
+
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+ g_return_val_if_fail (stream->priv->ports != NULL, NULL);
+
+ for (l = stream->priv->ports; l != NULL; l = l->next) {
+ GvcMixerStreamPort *p = l->data;
+ if (g_strcmp0 (stream->priv->port, p->port) == 0) {
+ return p;
+ }
+ }
+
+ g_assert_not_reached ();
+
+ return NULL;
+}
+
+gboolean
+gvc_mixer_stream_set_port (GvcMixerStream *stream,
+ const char *port)
+{
+ GList *l;
+
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ g_return_val_if_fail (stream->priv->ports != NULL, FALSE);
+
+ g_free (stream->priv->port);
+ stream->priv->port = g_strdup (port);
+
+ g_free (stream->priv->human_port);
+ stream->priv->human_port = NULL;
+
+ for (l = stream->priv->ports; l != NULL; l = l->next) {
+ GvcMixerStreamPort *p = l->data;
+ if (g_str_equal (stream->priv->port, p->port)) {
+ stream->priv->human_port = g_strdup (p->human_port);
+ break;
+ }
+ }
+
+ g_object_notify (G_OBJECT (stream), "port");
+
+ return TRUE;
+}
+
+gboolean
+gvc_mixer_stream_change_port (GvcMixerStream *stream,
+ const char *port)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port);
+}
+
+const GList *
+gvc_mixer_stream_get_ports (GvcMixerStream *stream)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ return stream->priv->ports;
+}
+
+static int
+sort_ports (GvcMixerStreamPort *a,
+ GvcMixerStreamPort *b)
+{
+ if (a->priority == b->priority)
+ return 0;
+ if (a->priority > b->priority)
+ return 1;
+ return -1;
+}
+
+gboolean
+gvc_mixer_stream_set_ports (GvcMixerStream *stream,
+ GList *ports)
+{
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
+
+ stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
+
+ return TRUE;
+}
+
+static void
+gvc_mixer_stream_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerStream *self = GVC_MIXER_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_PA_CONTEXT:
+ self->priv->pa_context = g_value_get_pointer (value);
+ break;
+ case PROP_INDEX:
+ self->priv->index = g_value_get_ulong (value);
+ break;
+ case PROP_ID:
+ self->priv->id = g_value_get_ulong (value);
+ break;
+ case PROP_CHANNEL_MAP:
+ gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
+ break;
+ case PROP_NAME:
+ gvc_mixer_stream_set_name (self, g_value_get_string (value));
+ break;
+ case PROP_DESCRIPTION:
+ gvc_mixer_stream_set_description (self, g_value_get_string (value));
+ break;
+ case PROP_APPLICATION_ID:
+ gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
+ break;
+ case PROP_ICON_NAME:
+ gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_VOLUME:
+ gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
+ break;
+ case PROP_DECIBEL:
+ gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
+ break;
+ case PROP_IS_MUTED:
+ gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
+ break;
+ case PROP_IS_EVENT_STREAM:
+ gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
+ break;
+ case PROP_IS_VIRTUAL:
+ gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
+ break;
+ case PROP_CAN_DECIBEL:
+ gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
+ break;
+ case PROP_PORT:
+ gvc_mixer_stream_set_port (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gvc_mixer_stream_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GvcMixerStream *self = GVC_MIXER_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_PA_CONTEXT:
+ g_value_set_pointer (value, self->priv->pa_context);
+ break;
+ case PROP_INDEX:
+ g_value_set_ulong (value, self->priv->index);
+ break;
+ case PROP_ID:
+ g_value_set_ulong (value, self->priv->id);
+ break;
+ case PROP_CHANNEL_MAP:
+ g_value_set_object (value, self->priv->channel_map);
+ break;
+ case PROP_NAME:
+ g_value_set_string (value, self->priv->name);
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, self->priv->description);
+ break;
+ case PROP_APPLICATION_ID:
+ g_value_set_string (value, self->priv->application_id);
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value, self->priv->icon_name);
+ break;
+ case PROP_VOLUME:
+ g_value_set_ulong (value,
+ pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
+ break;
+ case PROP_DECIBEL:
+ g_value_set_double (value,
+ pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
+ break;
+ case PROP_IS_MUTED:
+ g_value_set_boolean (value, self->priv->is_muted);
+ break;
+ case PROP_IS_EVENT_STREAM:
+ g_value_set_boolean (value, self->priv->is_event_stream);
+ break;
+ case PROP_IS_VIRTUAL:
+ g_value_set_boolean (value, self->priv->is_virtual);
+ break;
+ case PROP_CAN_DECIBEL:
+ g_value_set_boolean (value, self->priv->can_decibel);
+ break;
+ case PROP_PORT:
+ g_value_set_string (value, self->priv->port);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gvc_mixer_stream_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GvcMixerStream *self;
+
+ object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
+
+ self = GVC_MIXER_STREAM (object);
+
+ self->priv->id = get_next_stream_serial ();
+
+ return object;
+}
+
+static gboolean
+gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
+ const char *port)
+{
+ return FALSE;
+}
+
+static gboolean
+gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
+{
+ return FALSE;
+}
+
+static gboolean
+gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ return FALSE;
+}
+
+gboolean
+gvc_mixer_stream_push_volume (GvcMixerStream *stream)
+{
+ pa_operation *op;
+ gboolean ret;
+
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+ if (stream->priv->is_event_stream != FALSE)
+ return TRUE;
+
+ g_debug ("Pushing new volume to stream '%s' (%s)",
+ stream->priv->description, stream->priv->name);
+
+ ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
+ if (ret) {
+ if (stream->priv->change_volume_op != NULL)
+ pa_operation_unref (stream->priv->change_volume_op);
+ stream->priv->change_volume_op = op;
+ }
+ return ret;
+}
+
+gboolean
+gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted)
+{
+ gboolean ret;
+ g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+ ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted);
+ return ret;
+}
+
+gboolean
+gvc_mixer_stream_is_running (GvcMixerStream *stream)
+{
+ if (stream->priv->change_volume_op == NULL)
+ return FALSE;
+
+ if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
+ return TRUE;
+
+ pa_operation_unref(stream->priv->change_volume_op);
+ stream->priv->change_volume_op = NULL;
+
+ return FALSE;
+}
+
+static void
+gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructor = gvc_mixer_stream_constructor;
+ gobject_class->finalize = gvc_mixer_stream_finalize;
+ gobject_class->set_property = gvc_mixer_stream_set_property;
+ gobject_class->get_property = gvc_mixer_stream_get_property;
+
+ klass->push_volume = gvc_mixer_stream_real_push_volume;
+ klass->change_port = gvc_mixer_stream_real_change_port;
+ klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
+
+ g_object_class_install_property (gobject_class,
+ PROP_INDEX,
+ g_param_spec_ulong ("index",
+ "Index",
+ "The index for this stream",
+ 0, G_MAXULONG, 0,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_ID,
+ g_param_spec_ulong ("id",
+ "id",
+ "The id for this stream",
+ 0, G_MAXULONG, 0,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_CHANNEL_MAP,
+ g_param_spec_object ("channel-map",
+ "channel map",
+ "The channel map for this stream",
+ GVC_TYPE_CHANNEL_MAP,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_PA_CONTEXT,
+ g_param_spec_pointer ("pa-context",
+ "PulseAudio context",
+ "The PulseAudio context for this stream",
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_VOLUME,
+ g_param_spec_ulong ("volume",
+ "Volume",
+ "The volume for this stream",
+ 0, G_MAXULONG, 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_DECIBEL,
+ g_param_spec_double ("decibel",
+ "Decibel",
+ "The decibel level for this stream",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (gobject_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "Name to display for this stream",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_DESCRIPTION,
+ g_param_spec_string ("description",
+ "Description",
+ "Description to display for this stream",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_APPLICATION_ID,
+ g_param_spec_string ("application-id",
+ "Application identifier",
+ "Application identifier for this stream",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_ICON_NAME,
+ g_param_spec_string ("icon-name",
+ "Icon Name",
+ "Name of icon to display for this stream",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_IS_MUTED,
+ g_param_spec_boolean ("is-muted",
+ "is muted",
+ "Whether stream is muted",
+ FALSE,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_CAN_DECIBEL,
+ g_param_spec_boolean ("can-decibel",
+ "can decibel",
+ "Whether stream volume can be converted to decibel units",
+ FALSE,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_IS_EVENT_STREAM,
+ g_param_spec_boolean ("is-event-stream",
+ "is event stream",
+ "Whether stream's role is to play an event",
+ FALSE,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_IS_VIRTUAL,
+ g_param_spec_boolean ("is-virtual",
+ "is virtual stream",
+ "Whether the stream is virtual",
+ FALSE,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ g_object_class_install_property (gobject_class,
+ PROP_PORT,
+ g_param_spec_string ("port",
+ "Port",
+ "The name of the current port for this stream",
+ NULL,
+ G_PARAM_READWRITE));
+ g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
+}
+
+static void
+gvc_mixer_stream_init (GvcMixerStream *stream)
+{
+ stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
+}
+
+static void
+free_port (GvcMixerStreamPort *p)
+{
+ g_free (p->port);
+ g_free (p->human_port);
+ g_free (p);
+}
+
+static void
+gvc_mixer_stream_finalize (GObject *object)
+{
+ GvcMixerStream *mixer_stream;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GVC_IS_MIXER_STREAM (object));
+
+ mixer_stream = GVC_MIXER_STREAM (object);
+
+ g_return_if_fail (mixer_stream->priv != NULL);
+
+ g_free (mixer_stream->priv->name);
+ mixer_stream->priv->name = NULL;
+
+ g_free (mixer_stream->priv->description);
+ mixer_stream->priv->description = NULL;
+
+ g_free (mixer_stream->priv->application_id);
+ mixer_stream->priv->application_id = NULL;
+
+ g_free (mixer_stream->priv->icon_name);
+ mixer_stream->priv->icon_name = NULL;
+
+ g_free (mixer_stream->priv->port);
+ mixer_stream->priv->port = NULL;
+
+ g_free (mixer_stream->priv->human_port);
+ mixer_stream->priv->human_port = NULL;
+
+ g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
+ g_list_free (mixer_stream->priv->ports);
+ mixer_stream->priv->ports = NULL;
+
+ if (mixer_stream->priv->change_volume_op) {
+ pa_operation_unref(mixer_stream->priv->change_volume_op);
+ mixer_stream->priv->change_volume_op = NULL;
+ }
+
+ G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);
+}
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h
new file mode 100644
index 0000000..16ab21e
--- /dev/null
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h
@@ -0,0 +1,128 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GVC_MIXER_STREAM_H
+#define __GVC_MIXER_STREAM_H
+
+#include <glib-object.h>
+#include <pulse/pulseaudio.h>
+
+#include "gvc-channel-map.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GVC_TYPE_MIXER_STREAM (gvc_mixer_stream_get_type ())
+#define GVC_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStream))
+#define GVC_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass))
+#define GVC_IS_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_STREAM))
+#define GVC_IS_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_STREAM))
+#define GVC_MIXER_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass))
+
+typedef struct GvcMixerStreamPrivate GvcMixerStreamPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GvcMixerStreamPrivate *priv;
+} GvcMixerStream;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ /* vtable */
+ gboolean (*push_volume) (GvcMixerStream *stream,
+ gpointer *operation);
+ gboolean (*change_is_muted) (GvcMixerStream *stream,
+ gboolean is_muted);
+ gboolean (*change_port) (GvcMixerStream *stream,
+ const char *port);
+} GvcMixerStreamClass;
+
+typedef struct
+{
+ char *port;
+ char *human_port;
+ guint priority;
+} GvcMixerStreamPort;
+
+GType gvc_mixer_stream_get_type (void);
+
+pa_context * gvc_mixer_stream_get_pa_context (GvcMixerStream *stream);
+guint gvc_mixer_stream_get_index (GvcMixerStream *stream);
+guint gvc_mixer_stream_get_id (GvcMixerStream *stream);
+GvcChannelMap * gvc_mixer_stream_get_channel_map (GvcMixerStream *stream);
+GvcMixerStreamPort *gvc_mixer_stream_get_port (GvcMixerStream *stream);
+const GList * gvc_mixer_stream_get_ports (GvcMixerStream *stream);
+gboolean gvc_mixer_stream_change_port (GvcMixerStream *stream,
+ const char *port);
+
+pa_volume_t gvc_mixer_stream_get_volume (GvcMixerStream *stream);
+gdouble gvc_mixer_stream_get_decibel (GvcMixerStream *stream);
+gboolean gvc_mixer_stream_push_volume (GvcMixerStream *stream);
+pa_volume_t gvc_mixer_stream_get_base_volume (GvcMixerStream *stream);
+
+gboolean gvc_mixer_stream_get_is_muted (GvcMixerStream *stream);
+gboolean gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream);
+gboolean gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
+ gboolean is_muted);
+gboolean gvc_mixer_stream_is_running (GvcMixerStream *stream);
+const char * gvc_mixer_stream_get_name (GvcMixerStream *stream);
+const char * gvc_mixer_stream_get_icon_name (GvcMixerStream *stream);
+const char * gvc_mixer_stream_get_description (GvcMixerStream *stream);
+const char * gvc_mixer_stream_get_application_id (GvcMixerStream *stream);
+gboolean gvc_mixer_stream_is_event_stream (GvcMixerStream *stream);
+gboolean gvc_mixer_stream_is_virtual (GvcMixerStream *stream);
+
+/* private */
+gboolean gvc_mixer_stream_set_volume (GvcMixerStream *stream,
+ pa_volume_t volume);
+gboolean gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
+ gdouble db);
+gboolean gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
+ gboolean is_muted);
+gboolean gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream,
+ gboolean can_decibel);
+gboolean gvc_mixer_stream_set_name (GvcMixerStream *stream,
+ const char *name);
+gboolean gvc_mixer_stream_set_description (GvcMixerStream *stream,
+ const char *description);
+gboolean gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
+ const char *name);
+gboolean gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
+ gboolean is_event_stream);
+gboolean gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
+ gboolean is_event_stream);
+gboolean gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
+ const char *application_id);
+gboolean gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
+ pa_volume_t base_volume);
+gboolean gvc_mixer_stream_set_port (GvcMixerStream *stream,
+ const char *port);
+gboolean gvc_mixer_stream_set_ports (GvcMixerStream *stream,
+ GList *ports);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GVC_MIXER_STREAM_H */
diff --git a/plugins/media-keys/gsd-marshal.list b/plugins/media-keys/gsd-marshal.list
new file mode 100644
index 0000000..72f9937
--- /dev/null
+++ b/plugins/media-keys/gsd-marshal.list
@@ -0,0 +1 @@
+VOID:STRING,STRING
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
new file mode 100644
index 0000000..ae6383a
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -0,0 +1,1373 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2001-2003 Bastien Nocera <[email protected]>
+ * Copyright (C) 2006-2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-marshal.h"
+#include "gsd-media-keys-manager.h"
+#include "gsd-media-keys-manager-glue.h"
+
+#include "eggaccelerators.h"
+#include "acme.h"
+#include "gsd-media-keys-window.h"
+
+#ifdef HAVE_PULSE
+#include <canberra-gtk.h>
+#include "gvc-mixer-control.h"
+#endif /* HAVE_PULSE */
+
+#define GSD_DBUS_PATH "/org/mate/SettingsDaemon"
+#define GSD_DBUS_NAME "org.mate.SettingsDaemon"
+#define GSD_MEDIA_KEYS_DBUS_PATH GSD_DBUS_PATH "/MediaKeys"
+#define GSD_MEDIA_KEYS_DBUS_NAME GSD_DBUS_NAME ".MediaKeys"
+
+#define TOUCHPAD_ENABLED_KEY "/desktop/mate/peripherals/touchpad/touchpad_enabled"
+
+#define VOLUME_STEP 6 /* percents for one volume button press */
+#define MAX_VOLUME 65536.0
+
+#define GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerPrivate))
+
+typedef struct {
+ char *application;
+ guint32 time;
+} MediaPlayer;
+
+struct GsdMediaKeysManagerPrivate
+{
+#ifdef HAVE_PULSE
+ /* Volume bits */
+ GvcMixerControl *volume;
+ GvcMixerStream *stream;
+#endif /* HAVE_PULSE */
+ GtkWidget *dialog;
+ MateConfClient *conf_client;
+ GVolumeMonitor *volume_monitor;
+
+ /* Multihead stuff */
+ GdkScreen *current_screen;
+ GSList *screens;
+
+ GList *media_players;
+
+ DBusGConnection *connection;
+ guint notify[HANDLED_KEYS];
+};
+
+enum {
+ MEDIA_PLAYER_KEY_PRESSED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass);
+static void gsd_media_keys_manager_init (GsdMediaKeysManager *media_keys_manager);
+static void gsd_media_keys_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdMediaKeysManager, gsd_media_keys_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+
+static void
+init_screens (GsdMediaKeysManager *manager)
+{
+ GdkDisplay *display;
+ int i;
+
+ display = gdk_display_get_default ();
+ for (i = 0; i < gdk_display_get_n_screens (display); i++) {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (display, i);
+ if (screen == NULL) {
+ continue;
+ }
+ manager->priv->screens = g_slist_append (manager->priv->screens, screen);
+ }
+
+ manager->priv->current_screen = manager->priv->screens->data;
+}
+
+
+static void
+acme_error (char * msg)
+{
+ GtkWidget *error_dialog;
+
+ error_dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ msg, NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (error_dialog),
+ GTK_RESPONSE_OK);
+ gtk_widget_show (error_dialog);
+ g_signal_connect (error_dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+}
+
+static char *
+get_term_command (GsdMediaKeysManager *manager)
+{
+ char *cmd_term;
+ char *cmd = NULL;
+
+ cmd_term = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/applications/terminal/exec", NULL);
+ if ((cmd_term != NULL) && (strcmp (cmd_term, "") != 0)) {
+ char *cmd_args;
+ cmd_args = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/applications/terminal/exec_arg", NULL);
+ if ((cmd_args != NULL) && (strcmp (cmd_term, "") != 0)) {
+ cmd = g_strdup_printf ("%s %s -e", cmd_term, cmd_args);
+ } else {
+ cmd = g_strdup_printf ("%s -e", cmd_term);
+ }
+
+ g_free (cmd_args);
+ }
+
+ g_free (cmd_term);
+
+ return cmd;
+}
+
+static void
+execute (GsdMediaKeysManager *manager,
+ char *cmd,
+ gboolean sync,
+ gboolean need_term)
+{
+ gboolean retval;
+ char **argv;
+ int argc;
+ char *exec;
+ char *term = NULL;
+
+ retval = FALSE;
+
+ if (need_term) {
+ term = get_term_command (manager);
+ if (term == NULL) {
+ acme_error (_("Could not get default terminal. Verify that your default "
+ "terminal command is set and points to a valid application."));
+ return;
+ }
+ }
+
+ if (term) {
+ exec = g_strdup_printf ("%s %s", term, cmd);
+ g_free (term);
+ } else {
+ exec = g_strdup (cmd);
+ }
+
+ if (g_shell_parse_argv (exec, &argc, &argv, NULL)) {
+ if (sync != FALSE) {
+ retval = g_spawn_sync (g_get_home_dir (),
+ argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ } else {
+ retval = g_spawn_async (g_get_home_dir (),
+ argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
+ g_strfreev (argv);
+ }
+
+ if (retval == FALSE) {
+ char *msg;
+ msg = g_strdup_printf (_("Couldn't execute command: %s\n"
+ "Verify that this is a valid command."),
+ exec);
+
+ acme_error (msg);
+ g_free (msg);
+ }
+ g_free (exec);
+}
+
+static void
+dialog_init (GsdMediaKeysManager *manager)
+{
+ if (manager->priv->dialog != NULL
+ && !gsd_osd_window_is_valid (GSD_OSD_WINDOW (manager->priv->dialog))) {
+ gtk_widget_destroy (manager->priv->dialog);
+ manager->priv->dialog = NULL;
+ }
+
+ if (manager->priv->dialog == NULL) {
+ manager->priv->dialog = gsd_media_keys_window_new ();
+ }
+}
+
+static gboolean
+is_valid_shortcut (const char *string)
+{
+ if (string == NULL || string[0] == '\0') {
+ return FALSE;
+ }
+ if (strcmp (string, "disabled") == 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+update_kbd_cb (MateConfClient *client,
+ guint id,
+ MateConfEntry *entry,
+ GsdMediaKeysManager *manager)
+{
+ int i;
+ gboolean need_flush = TRUE;
+
+ g_return_if_fail (entry->key != NULL);
+
+ gdk_error_trap_push ();
+
+ /* Find the key that was modified */
+ for (i = 0; i < HANDLED_KEYS; i++) {
+ if (strcmp (entry->key, keys[i].mateconf_key) == 0) {
+ char *tmp;
+ Key *key;
+
+ if (keys[i].key != NULL) {
+ need_flush = TRUE;
+ grab_key_unsafe (keys[i].key, FALSE, manager->priv->screens);
+ }
+
+ g_free (keys[i].key);
+ keys[i].key = NULL;
+
+ tmp = mateconf_client_get_string (manager->priv->conf_client,
+ keys[i].mateconf_key, NULL);
+
+ if (is_valid_shortcut (tmp) == FALSE) {
+ g_free (tmp);
+ break;
+ }
+
+ key = g_new0 (Key, 1);
+ if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycodes, &key->state)) {
+ g_free (tmp);
+ g_free (key);
+ break;
+ }
+
+ need_flush = TRUE;
+ grab_key_unsafe (key, TRUE, manager->priv->screens);
+ keys[i].key = key;
+
+ g_free (tmp);
+
+ break;
+ }
+ }
+
+ if (need_flush)
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ g_warning ("Grab failed for some keys, another application may already have access the them.");
+}
+
+static void
+init_kbd (GsdMediaKeysManager *manager)
+{
+ int i;
+ gboolean need_flush = FALSE;
+
+ mate_settings_profile_start (NULL);
+
+ gdk_error_trap_push ();
+
+ for (i = 0; i < HANDLED_KEYS; i++) {
+ char *tmp;
+ Key *key;
+
+ manager->priv->notify[i] =
+ mateconf_client_notify_add (manager->priv->conf_client,
+ keys[i].mateconf_key,
+ (MateConfClientNotifyFunc) update_kbd_cb,
+ manager,
+ NULL,
+ NULL);
+
+ tmp = mateconf_client_get_string (manager->priv->conf_client,
+ keys[i].mateconf_key,
+ NULL);
+
+ if (!is_valid_shortcut (tmp)) {
+ g_debug ("Not a valid shortcut: '%s'", tmp);
+ g_free (tmp);
+ continue;
+ }
+
+ key = g_new0 (Key, 1);
+ if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycodes, &key->state)) {
+ g_debug ("Unable to parse: '%s'", tmp);
+ g_free (tmp);
+ g_free (key);
+ continue;
+ }
+
+ g_free (tmp);
+
+ keys[i].key = key;
+
+ need_flush = TRUE;
+ grab_key_unsafe (key, TRUE, manager->priv->screens);
+ }
+
+ if (need_flush)
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ g_warning ("Grab failed for some keys, another application may already have access the them.");
+
+ mate_settings_profile_end (NULL);
+}
+
+static void
+dialog_show (GsdMediaKeysManager *manager)
+{
+ int orig_w;
+ int orig_h;
+ int screen_w;
+ int screen_h;
+ int x;
+ int y;
+ int pointer_x;
+ int pointer_y;
+ GtkRequisition win_req;
+ GdkScreen *pointer_screen;
+ GdkRectangle geometry;
+ int monitor;
+
+ gtk_window_set_screen (GTK_WINDOW (manager->priv->dialog),
+ manager->priv->current_screen);
+
+ /*
+ * get the window size
+ * if the window hasn't been mapped, it doesn't necessarily
+ * know its true size, yet, so we need to jump through hoops
+ */
+ gtk_window_get_default_size (GTK_WINDOW (manager->priv->dialog), &orig_w, &orig_h);
+ gtk_widget_size_request (manager->priv->dialog, &win_req);
+
+ if (win_req.width > orig_w) {
+ orig_w = win_req.width;
+ }
+ if (win_req.height > orig_h) {
+ orig_h = win_req.height;
+ }
+
+ pointer_screen = NULL;
+ gdk_display_get_pointer (gdk_screen_get_display (manager->priv->current_screen),
+ &pointer_screen,
+ &pointer_x,
+ &pointer_y,
+ NULL);
+ if (pointer_screen != manager->priv->current_screen) {
+ /* The pointer isn't on the current screen, so just
+ * assume the default monitor
+ */
+ monitor = 0;
+ } else {
+ monitor = gdk_screen_get_monitor_at_point (manager->priv->current_screen,
+ pointer_x,
+ pointer_y);
+ }
+
+ gdk_screen_get_monitor_geometry (manager->priv->current_screen,
+ monitor,
+ &geometry);
+
+ screen_w = geometry.width;
+ screen_h = geometry.height;
+
+ x = ((screen_w - orig_w) / 2) + geometry.x;
+ y = geometry.y + (screen_h / 2) + (screen_h / 2 - orig_h) / 2;
+
+ gtk_window_move (GTK_WINDOW (manager->priv->dialog), x, y);
+
+ gtk_widget_show (manager->priv->dialog);
+
+ gdk_display_sync (gdk_screen_get_display (manager->priv->current_screen));
+}
+
+static void
+do_unknown_action (GsdMediaKeysManager *manager,
+ const char *url)
+{
+ char *string;
+
+ g_return_if_fail (url != NULL);
+
+ string = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/url-handlers/unknown/command",
+ NULL);
+
+ if ((string != NULL) && (strcmp (string, "") != 0)) {
+ char *cmd;
+ cmd = g_strdup_printf (string, url);
+ execute (manager, cmd, FALSE, FALSE);
+ g_free (cmd);
+ }
+ g_free (string);
+}
+
+static void
+do_help_action (GsdMediaKeysManager *manager)
+{
+ char *string;
+
+ string = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/url-handlers/ghelp/command",
+ NULL);
+
+ if ((string != NULL) && (strcmp (string, "") != 0)) {
+ char *cmd;
+ cmd = g_strdup_printf (string, "");
+ execute (manager, cmd, FALSE, FALSE);
+ g_free (cmd);
+ } else {
+ do_unknown_action (manager, "ghelp:");
+ }
+
+ g_free (string);
+}
+
+static void
+do_mail_action (GsdMediaKeysManager *manager)
+{
+ char *string;
+
+ string = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/url-handlers/mailto/command",
+ NULL);
+
+ if ((string != NULL) && (strcmp (string, "") != 0)) {
+ char *cmd;
+ cmd = g_strdup_printf (string, "");
+ execute (manager,
+ cmd,
+ FALSE,
+ mateconf_client_get_bool (manager->priv->conf_client,
+ "/desktop/mate/url-handlers/mailto/needs_terminal", NULL));
+ g_free (cmd);
+ }
+ g_free (string);
+}
+
+static void
+do_media_action (GsdMediaKeysManager *manager)
+{
+ char *command;
+
+ command = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/applications/media/exec", NULL);
+ if ((command != NULL) && (strcmp (command, "") != 0)) {
+ execute (manager,
+ command,
+ FALSE,
+ mateconf_client_get_bool (manager->priv->conf_client,
+ "/desktop/mate/applications/media/needs_term", NULL));
+ }
+ g_free (command);
+}
+
+static void
+do_www_action (GsdMediaKeysManager *manager,
+ const char *url)
+{
+ char *string;
+
+ string = mateconf_client_get_string (manager->priv->conf_client,
+ "/desktop/mate/url-handlers/http/command",
+ NULL);
+
+ if ((string != NULL) && (strcmp (string, "") != 0)) {
+ gchar *cmd;
+
+ if (url == NULL) {
+ cmd = g_strdup_printf (string, "");
+ } else {
+ cmd = g_strdup_printf (string, url);
+ }
+
+ execute (manager,
+ cmd,
+ FALSE,
+ mateconf_client_get_bool (manager->priv->conf_client,
+ "/desktop/mate/url-handlers/http/needs_terminal", NULL));
+ g_free (cmd);
+ } else {
+ do_unknown_action (manager, url ? url : "");
+ }
+ g_free (string);
+}
+
+static void
+do_exit_action (GsdMediaKeysManager *manager)
+{
+ execute (manager, "mate-session-save --shutdown-dialog", FALSE, FALSE);
+}
+
+static void
+do_eject_action_cb (GDrive *drive,
+ GAsyncResult *res,
+ GsdMediaKeysManager *manager)
+{
+ g_drive_eject_with_operation_finish (drive, res, NULL);
+}
+
+#define NO_SCORE 0
+#define SCORE_CAN_EJECT 50
+#define SCORE_HAS_MEDIA 100
+static void
+do_eject_action (GsdMediaKeysManager *manager)
+{
+ GList *drives, *l;
+ GDrive *fav_drive;
+ guint score;
+
+ /* Find the best drive to eject */
+ fav_drive = NULL;
+ score = NO_SCORE;
+ drives = g_volume_monitor_get_connected_drives (manager->priv->volume_monitor);
+ for (l = drives; l != NULL; l = l->next) {
+ GDrive *drive = l->data;
+
+ if (g_drive_can_eject (drive) == FALSE)
+ continue;
+ if (g_drive_is_media_removable (drive) == FALSE)
+ continue;
+ if (score < SCORE_CAN_EJECT) {
+ fav_drive = drive;
+ score = SCORE_CAN_EJECT;
+ }
+ if (g_drive_has_media (drive) == FALSE)
+ continue;
+ if (score < SCORE_HAS_MEDIA) {
+ fav_drive = drive;
+ score = SCORE_HAS_MEDIA;
+ break;
+ }
+ }
+
+ /* Show the dialogue */
+ dialog_init (manager);
+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
+ "media-eject",
+ FALSE);
+ dialog_show (manager);
+
+ /* Clean up the drive selection and exit if no suitable
+ * drives are found */
+ if (fav_drive != NULL)
+ fav_drive = g_object_ref (fav_drive);
+
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ if (fav_drive == NULL)
+ return;
+
+ /* Eject! */
+ g_drive_eject_with_operation (fav_drive, G_MOUNT_UNMOUNT_FORCE,
+ NULL, NULL,
+ (GAsyncReadyCallback) do_eject_action_cb,
+ manager);
+ g_object_unref (fav_drive);
+}
+
+static void
+do_touchpad_action (GsdMediaKeysManager *manager)
+{
+ MateConfClient *client = manager->priv->conf_client;
+ gboolean state = mateconf_client_get_bool (client, TOUCHPAD_ENABLED_KEY, NULL);
+
+ dialog_init (manager);
+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
+ (!state) ? "touchpad-enabled" : "touchpad-disabled",
+ FALSE);
+ dialog_show (manager);
+
+ mateconf_client_set_bool (client, TOUCHPAD_ENABLED_KEY, !state, NULL);
+}
+
+#ifdef HAVE_PULSE
+static void
+update_dialog (GsdMediaKeysManager *manager,
+ guint vol,
+ gboolean muted,
+ gboolean sound_changed)
+{
+ vol = (int) (100 * (double) vol / PA_VOLUME_NORM);
+ vol = CLAMP (vol, 0, 100);
+
+ dialog_init (manager);
+ gsd_media_keys_window_set_volume_muted (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
+ muted);
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), vol);
+ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
+ dialog_show (manager);
+
+ if (sound_changed != FALSE && muted == FALSE)
+ ca_gtk_play_for_widget (manager->priv->dialog, 0,
+ CA_PROP_EVENT_ID, "audio-volume-change",
+ CA_PROP_EVENT_DESCRIPTION, "volume changed through key press",
+ CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+ NULL);
+}
+
+static void
+do_sound_action (GsdMediaKeysManager *manager,
+ int type)
+{
+ gboolean muted;
+ guint vol, norm_vol_step;
+ int vol_step;
+ gboolean sound_changed;
+
+ if (manager->priv->stream == NULL)
+ return;
+
+ vol_step = mateconf_client_get_int (manager->priv->conf_client,
+ MATECONF_MISC_DIR "/volume_step",
+ NULL);
+
+ if (vol_step <= 0 || vol_step > 100)
+ vol_step = VOLUME_STEP;
+
+ norm_vol_step = PA_VOLUME_NORM * vol_step / 100;
+
+ /* FIXME: this is racy */
+ vol = gvc_mixer_stream_get_volume (manager->priv->stream);
+ muted = gvc_mixer_stream_get_is_muted (manager->priv->stream);
+ sound_changed = FALSE;
+
+ switch (type) {
+ case MUTE_KEY:
+ muted = !muted;
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
+ sound_changed = TRUE;
+ break;
+ case VOLUME_DOWN_KEY:
+ if (!muted && (vol <= norm_vol_step)) {
+ muted = !muted;
+ vol = 0;
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) {
+ gvc_mixer_stream_push_volume (manager->priv->stream);
+ sound_changed = TRUE;
+ }
+ } else if (!muted) {
+ vol = vol - norm_vol_step;
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) {
+ gvc_mixer_stream_push_volume (manager->priv->stream);
+ sound_changed = TRUE;
+ }
+ }
+ break;
+ case VOLUME_UP_KEY:
+ if (muted) {
+ muted = !muted;
+ if (vol == 0) {
+ vol = vol + norm_vol_step;
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) {
+ gvc_mixer_stream_push_volume (manager->priv->stream);
+ sound_changed = TRUE;
+ }
+ } else {
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
+ sound_changed = TRUE;
+ }
+ } else {
+ if (vol < MAX_VOLUME) {
+ if (vol + norm_vol_step >= MAX_VOLUME) {
+ vol = MAX_VOLUME;
+ } else {
+ vol = vol + norm_vol_step;
+ }
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) {
+ gvc_mixer_stream_push_volume (manager->priv->stream);
+ sound_changed = TRUE;
+ }
+ }
+ }
+ break;
+ }
+
+ update_dialog (manager, vol, muted, sound_changed);
+}
+
+static void
+update_default_sink (GsdMediaKeysManager *manager)
+{
+ GvcMixerStream *stream;
+
+ stream = gvc_mixer_control_get_default_sink (manager->priv->volume);
+ if (stream == manager->priv->stream)
+ return;
+
+ if (manager->priv->stream != NULL) {
+ g_object_unref (manager->priv->stream);
+ manager->priv->stream = NULL;
+ }
+
+ if (stream != NULL) {
+ manager->priv->stream = g_object_ref (stream);
+ } else {
+ g_warning ("Unable to get default sink");
+ }
+}
+
+static void
+on_control_ready (GvcMixerControl *control,
+ GsdMediaKeysManager *manager)
+{
+ update_default_sink (manager);
+}
+
+static void
+on_control_default_sink_changed (GvcMixerControl *control,
+ guint id,
+ GsdMediaKeysManager *manager)
+{
+ update_default_sink (manager);
+}
+
+#endif /* HAVE_PULSE */
+
+static gint
+find_by_application (gconstpointer a,
+ gconstpointer b)
+{
+ return strcmp (((MediaPlayer *)a)->application, b);
+}
+
+static gint
+find_by_time (gconstpointer a,
+ gconstpointer b)
+{
+ return ((MediaPlayer *)a)->time < ((MediaPlayer *)b)->time;
+}
+
+/*
+ * Register a new media player. Most applications will want to call
+ * this with time = GDK_CURRENT_TIME. This way, the last registered
+ * player will receive media events. In some cases, applications
+ * may want to register with a lower priority (usually 1), to grab
+ * events only nobody is interested.
+ */
+gboolean
+gsd_media_keys_manager_grab_media_player_keys (GsdMediaKeysManager *manager,
+ const char *application,
+ guint32 time,
+ GError **error)
+{
+ GList *iter;
+ MediaPlayer *media_player;
+
+ if (time == GDK_CURRENT_TIME) {
+ GTimeVal tv;
+
+ g_get_current_time (&tv);
+ time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ }
+
+ iter = g_list_find_custom (manager->priv->media_players,
+ application,
+ find_by_application);
+
+ if (iter != NULL) {
+ if (((MediaPlayer *)iter->data)->time < time) {
+ g_free (((MediaPlayer *)iter->data)->application);
+ g_free (iter->data);
+ manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter);
+ } else {
+ return TRUE;
+ }
+ }
+
+ g_debug ("Registering %s at %u", application, time);
+ media_player = g_new0 (MediaPlayer, 1);
+ media_player->application = g_strdup (application);
+ media_player->time = time;
+
+ manager->priv->media_players = g_list_insert_sorted (manager->priv->media_players,
+ media_player,
+ find_by_time);
+
+ return TRUE;
+}
+
+gboolean
+gsd_media_keys_manager_release_media_player_keys (GsdMediaKeysManager *manager,
+ const char *application,
+ GError **error)
+{
+ GList *iter;
+
+ iter = g_list_find_custom (manager->priv->media_players,
+ application,
+ find_by_application);
+
+ if (iter != NULL) {
+ g_debug ("Deregistering %s", application);
+ g_free (((MediaPlayer *)iter->data)->application);
+ g_free (iter->data);
+ manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gsd_media_player_key_pressed (GsdMediaKeysManager *manager,
+ const char *key)
+{
+ const char *application = NULL;
+ gboolean have_listeners;
+
+ have_listeners = (manager->priv->media_players != NULL);
+
+ if (have_listeners) {
+ application = ((MediaPlayer *)manager->priv->media_players->data)->application;
+ }
+
+ g_signal_emit (manager, signals[MEDIA_PLAYER_KEY_PRESSED], 0, application, key);
+
+ return !have_listeners;
+}
+
+static gboolean
+do_multimedia_player_action (GsdMediaKeysManager *manager,
+ const char *key)
+{
+ return gsd_media_player_key_pressed (manager, key);
+}
+
+static gboolean
+do_action (GsdMediaKeysManager *manager,
+ int type)
+{
+ char *cmd;
+ char *path;
+
+ switch (type) {
+ case TOUCHPAD_KEY:
+ do_touchpad_action (manager);
+ break;
+ case MUTE_KEY:
+ case VOLUME_DOWN_KEY:
+ case VOLUME_UP_KEY:
+#ifdef HAVE_PULSE
+ do_sound_action (manager, type);
+#endif /* HAVE_PULSE */
+ break;
+ case POWER_KEY:
+ do_exit_action (manager);
+ break;
+ case EJECT_KEY:
+ do_eject_action (manager);
+ break;
+ case HOME_KEY:
+ path = g_shell_quote (g_get_home_dir ());
+ cmd = g_strconcat ("caja --no-desktop ", path, NULL);
+ g_free (path);
+ execute (manager, cmd, FALSE, FALSE);
+ g_free (cmd);
+ break;
+ case SEARCH_KEY:
+ cmd = NULL;
+ if ((cmd = g_find_program_in_path ("beagle-search"))) {
+ execute (manager, "beagle-search", FALSE, FALSE);
+ } else if ((cmd = g_find_program_in_path ("tracker-search-tool"))) {
+ execute (manager, "tracker-search-tool", FALSE, FALSE);
+ } else {
+ execute (manager, "mate-search-tool", FALSE, FALSE);
+ }
+ g_free (cmd);
+ break;
+ case EMAIL_KEY:
+ do_mail_action (manager);
+ break;
+ case SCREENSAVER_KEY:
+ if ((cmd = g_find_program_in_path ("mate-screensaver-command"))) {
+ execute (manager, "mate-screensaver-command --lock", FALSE, FALSE);
+ } else {
+ execute (manager, "xscreensaver-command -lock", FALSE, FALSE);
+ }
+
+ g_free (cmd);
+ break;
+ case HELP_KEY:
+ do_help_action (manager);
+ break;
+ case WWW_KEY:
+ do_www_action (manager, NULL);
+ break;
+ case MEDIA_KEY:
+ do_media_action (manager);
+ break;
+ case CALCULATOR_KEY:
+ execute (manager, "gcalctool", FALSE, FALSE);
+ break;
+ case PLAY_KEY:
+ return do_multimedia_player_action (manager, "Play");
+ break;
+ case PAUSE_KEY:
+ return do_multimedia_player_action (manager, "Pause");
+ break;
+ case STOP_KEY:
+ return do_multimedia_player_action (manager, "Stop");
+ break;
+ case PREVIOUS_KEY:
+ return do_multimedia_player_action (manager, "Previous");
+ break;
+ case NEXT_KEY:
+ return do_multimedia_player_action (manager, "Next");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return FALSE;
+}
+
+static GdkScreen *
+acme_get_screen_from_event (GsdMediaKeysManager *manager,
+ XAnyEvent *xanyev)
+{
+ GdkWindow *window;
+ GdkScreen *screen;
+ GSList *l;
+
+ /* Look for which screen we're receiving events */
+ for (l = manager->priv->screens; l != NULL; l = l->next) {
+ screen = (GdkScreen *) l->data;
+ window = gdk_screen_get_root_window (screen);
+
+ if (GDK_WINDOW_XID (window) == xanyev->window) {
+ return screen;
+ }
+ }
+
+ return NULL;
+}
+
+static GdkFilterReturn
+acme_filter_events (GdkXEvent *xevent,
+ GdkEvent *event,
+ GsdMediaKeysManager *manager)
+{
+ XEvent *xev = (XEvent *) xevent;
+ XAnyEvent *xany = (XAnyEvent *) xevent;
+ int i;
+
+ /* verify we have a key event */
+ if (xev->type != KeyPress && xev->type != KeyRelease) {
+ return GDK_FILTER_CONTINUE;
+ }
+
+ for (i = 0; i < HANDLED_KEYS; i++) {
+ if (match_key (keys[i].key, xev)) {
+ switch (keys[i].key_type) {
+ case VOLUME_DOWN_KEY:
+ case VOLUME_UP_KEY:
+ /* auto-repeatable keys */
+ if (xev->type != KeyPress) {
+ return GDK_FILTER_CONTINUE;
+ }
+ break;
+ default:
+ if (xev->type != KeyRelease) {
+ return GDK_FILTER_CONTINUE;
+ }
+ }
+
+ manager->priv->current_screen = acme_get_screen_from_event (manager, xany);
+
+ if (do_action (manager, keys[i].key_type) == FALSE) {
+ return GDK_FILTER_REMOVE;
+ } else {
+ return GDK_FILTER_CONTINUE;
+ }
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+start_media_keys_idle_cb (GsdMediaKeysManager *manager)
+{
+ GSList *l;
+
+ g_debug ("Starting media_keys manager");
+ mate_settings_profile_start (NULL);
+ manager->priv->volume_monitor = g_volume_monitor_get ();
+ manager->priv->conf_client = mateconf_client_get_default ();
+
+ mateconf_client_add_dir (manager->priv->conf_client,
+ MATECONF_BINDING_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ init_screens (manager);
+ init_kbd (manager);
+
+ /* Start filtering the events */
+ for (l = manager->priv->screens; l != NULL; l = l->next) {
+ mate_settings_profile_start ("gdk_window_add_filter");
+
+ g_debug ("adding key filter for screen: %d",
+ gdk_screen_get_number (l->data));
+
+ gdk_window_add_filter (gdk_screen_get_root_window (l->data),
+ (GdkFilterFunc)acme_filter_events,
+ manager);
+ mate_settings_profile_end ("gdk_window_add_filter");
+ }
+
+ mate_settings_profile_end (NULL);
+
+ return FALSE;
+}
+
+gboolean
+gsd_media_keys_manager_start (GsdMediaKeysManager *manager,
+ GError **error)
+{
+ mate_settings_profile_start (NULL);
+
+#ifdef HAVE_PULSE
+ /* initialise Volume handler
+ *
+ * We do this one here to force checking gstreamer cache, etc.
+ * The rest (grabbing and setting the keys) can happen in an
+ * idle.
+ */
+ mate_settings_profile_start ("gvc_mixer_control_new");
+
+ manager->priv->volume = gvc_mixer_control_new ("MATE Volume Control Media Keys");
+
+ g_signal_connect (manager->priv->volume,
+ "ready",
+ G_CALLBACK (on_control_ready),
+ manager);
+ g_signal_connect (manager->priv->volume,
+ "default-sink-changed",
+ G_CALLBACK (on_control_default_sink_changed),
+ manager);
+
+ gvc_mixer_control_open (manager->priv->volume);
+
+ mate_settings_profile_end ("gvc_mixer_control_new");
+#endif /* HAVE_PULSE */
+ g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
+{
+ GsdMediaKeysManagerPrivate *priv = manager->priv;
+ GSList *ls;
+ GList *l;
+ int i;
+ gboolean need_flush;
+
+ g_debug ("Stopping media_keys manager");
+
+ for (ls = priv->screens; ls != NULL; ls = ls->next) {
+ gdk_window_remove_filter (gdk_screen_get_root_window (ls->data),
+ (GdkFilterFunc) acme_filter_events,
+ manager);
+ }
+
+ if (priv->conf_client) {
+ mateconf_client_remove_dir (priv->conf_client,
+ MATECONF_BINDING_DIR,
+ NULL);
+
+ for (i = 0; i < HANDLED_KEYS; ++i) {
+ if (priv->notify[i] != 0) {
+ mateconf_client_notify_remove (priv->conf_client, priv->notify[i]);
+ priv->notify[i] = 0;
+ }
+ }
+
+ g_object_unref (priv->conf_client);
+ priv->conf_client = NULL;
+ }
+
+ if (priv->volume_monitor != NULL) {
+ g_object_unref (priv->volume_monitor);
+ priv->volume_monitor = NULL;
+ }
+
+ if (priv->connection != NULL) {
+ dbus_g_connection_unref (priv->connection);
+ priv->connection = NULL;
+ }
+
+ need_flush = FALSE;
+ gdk_error_trap_push ();
+
+ for (i = 0; i < HANDLED_KEYS; ++i) {
+ if (keys[i].key) {
+ need_flush = TRUE;
+ grab_key_unsafe (keys[i].key, FALSE, priv->screens);
+
+ g_free (keys[i].key->keycodes);
+ g_free (keys[i].key);
+ keys[i].key = NULL;
+ }
+ }
+
+ if (need_flush)
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+ g_slist_free (priv->screens);
+ priv->screens = NULL;
+
+#ifdef HAVE_PULSE
+ if (priv->stream) {
+ g_object_unref (priv->stream);
+ priv->stream = NULL;
+ }
+
+ if (priv->volume) {
+ g_object_unref (priv->volume);
+ priv->volume = NULL;
+ }
+#endif /* HAVE_PULSE */
+
+ if (priv->dialog != NULL) {
+ gtk_widget_destroy (priv->dialog);
+ priv->dialog = NULL;
+ }
+
+ for (l = priv->media_players; l; l = l->next) {
+ MediaPlayer *mp = l->data;
+ g_free (mp->application);
+ g_free (mp);
+ }
+ g_list_free (priv->media_players);
+ priv->media_players = NULL;
+}
+
+static void
+gsd_media_keys_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdMediaKeysManager *self;
+
+ self = GSD_MEDIA_KEYS_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_media_keys_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdMediaKeysManager *self;
+
+ self = GSD_MEDIA_KEYS_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_media_keys_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdMediaKeysManager *media_keys_manager;
+ GsdMediaKeysManagerClass *klass;
+
+ klass = GSD_MEDIA_KEYS_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_MEDIA_KEYS_MANAGER));
+
+ media_keys_manager = GSD_MEDIA_KEYS_MANAGER (G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (media_keys_manager);
+}
+
+static void
+gsd_media_keys_manager_dispose (GObject *object)
+{
+ GsdMediaKeysManager *media_keys_manager;
+
+ media_keys_manager = GSD_MEDIA_KEYS_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_media_keys_manager_get_property;
+ object_class->set_property = gsd_media_keys_manager_set_property;
+ object_class->constructor = gsd_media_keys_manager_constructor;
+ object_class->dispose = gsd_media_keys_manager_dispose;
+ object_class->finalize = gsd_media_keys_manager_finalize;
+
+ signals[MEDIA_PLAYER_KEY_PRESSED] =
+ g_signal_new ("media-player-key-pressed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdMediaKeysManagerClass, media_player_key_pressed),
+ NULL,
+ NULL,
+ gsd_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ dbus_g_object_type_install_info (GSD_TYPE_MEDIA_KEYS_MANAGER, &dbus_glib_gsd_media_keys_manager_object_info);
+
+ g_type_class_add_private (klass, sizeof (GsdMediaKeysManagerPrivate));
+}
+
+static void
+gsd_media_keys_manager_init (GsdMediaKeysManager *manager)
+{
+ manager->priv = GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager);
+
+}
+
+static void
+gsd_media_keys_manager_finalize (GObject *object)
+{
+ GsdMediaKeysManager *media_keys_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_MEDIA_KEYS_MANAGER (object));
+
+ media_keys_manager = GSD_MEDIA_KEYS_MANAGER (object);
+
+ g_return_if_fail (media_keys_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->finalize (object);
+}
+
+static gboolean
+register_manager (GsdMediaKeysManager *manager)
+{
+ GError *error = NULL;
+
+ manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (manager->priv->connection == NULL) {
+ if (error != NULL) {
+ g_error ("Error getting session bus: %s", error->message);
+ g_error_free (error);
+ }
+ return FALSE;
+ }
+
+ dbus_g_connection_register_g_object (manager->priv->connection, GSD_MEDIA_KEYS_DBUS_PATH, G_OBJECT (manager));
+
+ return TRUE;
+}
+
+GsdMediaKeysManager *
+gsd_media_keys_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ gboolean res;
+
+ manager_object = g_object_new (GSD_TYPE_MEDIA_KEYS_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ res = register_manager (manager_object);
+ if (! res) {
+ g_object_unref (manager_object);
+ return NULL;
+ }
+ }
+
+ return GSD_MEDIA_KEYS_MANAGER (manager_object);
+}
diff --git a/plugins/media-keys/gsd-media-keys-manager.h b/plugins/media-keys/gsd-media-keys-manager.h
new file mode 100644
index 0000000..19dafd5
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-manager.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_MEDIA_KEYS_MANAGER_H
+#define __GSD_MEDIA_KEYS_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_MEDIA_KEYS_MANAGER (gsd_media_keys_manager_get_type ())
+#define GSD_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManager))
+#define GSD_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerClass))
+#define GSD_IS_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_MEDIA_KEYS_MANAGER))
+#define GSD_IS_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_MEDIA_KEYS_MANAGER))
+#define GSD_MEDIA_KEYS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerClass))
+
+typedef struct GsdMediaKeysManagerPrivate GsdMediaKeysManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdMediaKeysManagerPrivate *priv;
+} GsdMediaKeysManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* media_player_key_pressed) (GsdMediaKeysManager *manager,
+ const char *application,
+ const char *key);
+} GsdMediaKeysManagerClass;
+
+GType gsd_media_keys_manager_get_type (void);
+
+GsdMediaKeysManager * gsd_media_keys_manager_new (void);
+gboolean gsd_media_keys_manager_start (GsdMediaKeysManager *manager,
+ GError **error);
+void gsd_media_keys_manager_stop (GsdMediaKeysManager *manager);
+
+gboolean gsd_media_keys_manager_grab_media_player_keys (GsdMediaKeysManager *manager,
+ const char *application,
+ guint32 time,
+ GError **error);
+gboolean gsd_media_keys_manager_release_media_player_keys (GsdMediaKeysManager *manager,
+ const char *application,
+ GError **error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_MEDIA_KEYS_MANAGER_H */
diff --git a/plugins/media-keys/gsd-media-keys-manager.xml b/plugins/media-keys/gsd-media-keys-manager.xml
new file mode 100644
index 0000000..12cd03a
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-manager.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.mate.SettingsDaemon.MediaKeys">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="gsd_media_keys_manager"/>
+ <method name="GrabMediaPlayerKeys">
+ <arg name="application" direction="in" type="s"/>
+ <arg name="time" direction="in" type="u"/>
+ </method>
+ <method name="ReleaseMediaPlayerKeys">
+ <arg name="application" direction="in" type="s"/>
+ </method>
+ <signal name="MediaPlayerKeyPressed"/>
+ </interface>
+</node>
diff --git a/plugins/media-keys/gsd-media-keys-plugin.c b/plugins/media-keys/gsd-media-keys-plugin.c
new file mode 100644
index 0000000..319a42a
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-media-keys-plugin.h"
+#include "gsd-media-keys-manager.h"
+
+struct GsdMediaKeysPluginPrivate {
+ GsdMediaKeysManager *manager;
+};
+
+#define GSD_MEDIA_KEYS_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_MEDIA_KEYS_PLUGIN, GsdMediaKeysPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdMediaKeysPlugin, gsd_media_keys_plugin)
+
+static void
+gsd_media_keys_plugin_init (GsdMediaKeysPlugin *plugin)
+{
+ plugin->priv = GSD_MEDIA_KEYS_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdMediaKeysPlugin initializing");
+
+ plugin->priv->manager = gsd_media_keys_manager_new ();
+}
+
+static void
+gsd_media_keys_plugin_finalize (GObject *object)
+{
+ GsdMediaKeysPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_MEDIA_KEYS_PLUGIN (object));
+
+ g_debug ("GsdMediaKeysPlugin finalizing");
+
+ plugin = GSD_MEDIA_KEYS_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_media_keys_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating media_keys plugin");
+
+ error = NULL;
+ res = gsd_media_keys_manager_start (GSD_MEDIA_KEYS_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start media_keys manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating media_keys plugin");
+ gsd_media_keys_manager_stop (GSD_MEDIA_KEYS_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_media_keys_plugin_class_init (GsdMediaKeysPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_media_keys_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdMediaKeysPluginPrivate));
+}
diff --git a/plugins/media-keys/gsd-media-keys-plugin.h b/plugins/media-keys/gsd-media-keys-plugin.h
new file mode 100644
index 0000000..fa092b5
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_MEDIA_KEYS_PLUGIN_H__
+#define __GSD_MEDIA_KEYS_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_MEDIA_KEYS_PLUGIN (gsd_media_keys_plugin_get_type ())
+#define GSD_MEDIA_KEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_MEDIA_KEYS_PLUGIN, GsdMediaKeysPlugin))
+#define GSD_MEDIA_KEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_MEDIA_KEYS_PLUGIN, GsdMediaKeysPluginClass))
+#define GSD_IS_MEDIA_KEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_MEDIA_KEYS_PLUGIN))
+#define GSD_IS_MEDIA_KEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_MEDIA_KEYS_PLUGIN))
+#define GSD_MEDIA_KEYS_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_MEDIA_KEYS_PLUGIN, GsdMediaKeysPluginClass))
+
+typedef struct GsdMediaKeysPluginPrivate GsdMediaKeysPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdMediaKeysPluginPrivate *priv;
+} GsdMediaKeysPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdMediaKeysPluginClass;
+
+GType gsd_media_keys_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_MEDIA_KEYS_PLUGIN_H__ */
diff --git a/plugins/media-keys/gsd-media-keys-window.c b/plugins/media-keys/gsd-media-keys-window.c
new file mode 100644
index 0000000..2547068
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-window.c
@@ -0,0 +1,714 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2007 William Jon McCann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-media-keys-window.h"
+
+#define GSD_MEDIA_KEYS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindowPrivate))
+
+struct GsdMediaKeysWindowPrivate
+{
+ GsdMediaKeysWindowAction action;
+ char *icon_name;
+ gboolean show_level;
+
+ guint volume_muted : 1;
+ int volume_level;
+
+ GtkImage *image;
+ GtkWidget *progress;
+};
+
+G_DEFINE_TYPE (GsdMediaKeysWindow, gsd_media_keys_window, GSD_TYPE_OSD_WINDOW)
+
+static void
+volume_controls_set_visible (GsdMediaKeysWindow *window,
+ gboolean visible)
+{
+ if (window->priv->progress == NULL)
+ return;
+
+ if (visible) {
+ gtk_widget_show (window->priv->progress);
+ } else {
+ gtk_widget_hide (window->priv->progress);
+ }
+}
+
+static void
+window_set_icon_name (GsdMediaKeysWindow *window,
+ const char *name)
+{
+ if (window->priv->image == NULL)
+ return;
+
+ gtk_image_set_from_icon_name (window->priv->image,
+ name, GTK_ICON_SIZE_DIALOG);
+}
+
+static void
+action_changed (GsdMediaKeysWindow *window)
+{
+ if (!gsd_osd_window_is_composited (GSD_OSD_WINDOW (window))) {
+ switch (window->priv->action) {
+ case GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME:
+ volume_controls_set_visible (window, TRUE);
+
+ if (window->priv->volume_muted) {
+ window_set_icon_name (window, "audio-volume-muted");
+ } else {
+ window_set_icon_name (window, "audio-volume-high");
+ }
+
+ break;
+ case GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM:
+ volume_controls_set_visible (window, window->priv->show_level);
+ window_set_icon_name (window, window->priv->icon_name);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ gsd_osd_window_update_and_hide (GSD_OSD_WINDOW (window));
+}
+
+static void
+volume_level_changed (GsdMediaKeysWindow *window)
+{
+ gsd_osd_window_update_and_hide (GSD_OSD_WINDOW (window));
+
+ if (!gsd_osd_window_is_composited (GSD_OSD_WINDOW (window)) && window->priv->progress != NULL) {
+ double fraction;
+
+ fraction = (double) window->priv->volume_level / 100.0;
+
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress),
+ fraction);
+ }
+}
+
+static void
+volume_muted_changed (GsdMediaKeysWindow *window)
+{
+ gsd_osd_window_update_and_hide (GSD_OSD_WINDOW (window));
+
+ if (!gsd_osd_window_is_composited (GSD_OSD_WINDOW (window))) {
+ if (window->priv->volume_muted) {
+ window_set_icon_name (window, "audio-volume-muted");
+ } else {
+ window_set_icon_name (window, "audio-volume-high");
+ }
+ }
+}
+
+void
+gsd_media_keys_window_set_action (GsdMediaKeysWindow *window,
+ GsdMediaKeysWindowAction action)
+{
+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
+ g_return_if_fail (action == GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
+
+ if (window->priv->action != action) {
+ window->priv->action = action;
+ action_changed (window);
+ } else {
+ gsd_osd_window_update_and_hide (GSD_OSD_WINDOW (window));
+ }
+}
+
+void
+gsd_media_keys_window_set_action_custom (GsdMediaKeysWindow *window,
+ const char *icon_name,
+ gboolean show_level)
+{
+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
+ g_return_if_fail (icon_name != NULL);
+
+ if (window->priv->action != GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM ||
+ g_strcmp0 (window->priv->icon_name, icon_name) != 0 ||
+ window->priv->show_level != show_level) {
+ window->priv->action = GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM;
+ g_free (window->priv->icon_name);
+ window->priv->icon_name = g_strdup (icon_name);
+ window->priv->show_level = show_level;
+ action_changed (window);
+ } else {
+ gsd_osd_window_update_and_hide (GSD_OSD_WINDOW (window));
+ }
+}
+
+void
+gsd_media_keys_window_set_volume_muted (GsdMediaKeysWindow *window,
+ gboolean muted)
+{
+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
+
+ if (window->priv->volume_muted != muted) {
+ window->priv->volume_muted = muted;
+ volume_muted_changed (window);
+ }
+}
+
+void
+gsd_media_keys_window_set_volume_level (GsdMediaKeysWindow *window,
+ int level)
+{
+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
+
+ if (window->priv->volume_level != level) {
+ window->priv->volume_level = level;
+ volume_level_changed (window);
+ }
+}
+
+static GdkPixbuf *
+load_pixbuf (GsdMediaKeysWindow *window,
+ const char *name,
+ int icon_size)
+{
+ GtkIconTheme *theme;
+ GdkPixbuf *pixbuf;
+
+ if (window != NULL && gtk_widget_has_screen (GTK_WIDGET (window))) {
+ theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
+ } else {
+ theme = gtk_icon_theme_get_default ();
+ }
+
+ pixbuf = gtk_icon_theme_load_icon (theme,
+ name,
+ icon_size,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ NULL);
+
+ return pixbuf;
+}
+
+static void
+draw_eject (cairo_t *cr,
+ double _x0,
+ double _y0,
+ double width,
+ double height)
+{
+ int box_height;
+ int tri_height;
+ int separation;
+
+ box_height = height * 0.2;
+ separation = box_height / 3;
+ tri_height = height - box_height - separation;
+
+ cairo_rectangle (cr, _x0, _y0 + height - box_height, width, box_height);
+
+ cairo_move_to (cr, _x0, _y0 + tri_height);
+ cairo_rel_line_to (cr, width, 0);
+ cairo_rel_line_to (cr, -width / 2, -tri_height);
+ cairo_rel_line_to (cr, -width / 2, tri_height);
+ cairo_close_path (cr);
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, GSD_OSD_WINDOW_FG_ALPHA);
+ cairo_fill_preserve (cr);
+
+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, GSD_OSD_WINDOW_FG_ALPHA / 2);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+}
+
+static void
+draw_waves (cairo_t *cr,
+ double cx,
+ double cy,
+ double max_radius,
+ int volume_level)
+{
+ const int n_waves = 3;
+ int last_wave;
+ int i;
+
+ last_wave = n_waves * volume_level / 100;
+
+ for (i = 0; i < n_waves; i++) {
+ double angle1;
+ double angle2;
+ double radius;
+ double alpha;
+
+ angle1 = -M_PI / 4;
+ angle2 = M_PI / 4;
+
+ if (i < last_wave)
+ alpha = 1.0;
+ else if (i > last_wave)
+ alpha = 0.1;
+ else alpha = 0.1 + 0.9 * (n_waves * volume_level % 100) / 100.0;
+
+ radius = (i + 1) * (max_radius / n_waves);
+ cairo_arc (cr, cx, cy, radius, angle1, angle2);
+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, alpha / 2);
+ cairo_set_line_width (cr, 14);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_stroke_preserve (cr);
+
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha);
+ cairo_set_line_width (cr, 10);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_stroke (cr);
+ }
+}
+
+static void
+draw_cross (cairo_t *cr,
+ double cx,
+ double cy,
+ double size)
+{
+ cairo_move_to (cr, cx, cy - size/2.0);
+ cairo_rel_line_to (cr, size, size);
+
+ cairo_move_to (cr, cx, cy + size/2.0);
+ cairo_rel_line_to (cr, size, -size);
+
+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, GSD_OSD_WINDOW_FG_ALPHA / 2);
+ cairo_set_line_width (cr, 14);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_stroke_preserve (cr);
+
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, GSD_OSD_WINDOW_FG_ALPHA);
+ cairo_set_line_width (cr, 10);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_stroke (cr);
+}
+
+static void
+draw_speaker (cairo_t *cr,
+ double cx,
+ double cy,
+ double width,
+ double height)
+{
+ double box_width;
+ double box_height;
+ double _x0;
+ double _y0;
+
+ box_width = width / 3;
+ box_height = height / 3;
+
+ _x0 = cx - (width / 2) + box_width;
+ _y0 = cy - box_height / 2;
+
+ cairo_move_to (cr, _x0, _y0);
+ cairo_rel_line_to (cr, - box_width, 0);
+ cairo_rel_line_to (cr, 0, box_height);
+ cairo_rel_line_to (cr, box_width, 0);
+
+ cairo_line_to (cr, cx + box_width, cy + height / 2);
+ cairo_rel_line_to (cr, 0, -height);
+ cairo_line_to (cr, _x0, _y0);
+ cairo_close_path (cr);
+
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, GSD_OSD_WINDOW_FG_ALPHA);
+ cairo_fill_preserve (cr);
+
+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, GSD_OSD_WINDOW_FG_ALPHA / 2);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+}
+
+static gboolean
+render_speaker (GsdMediaKeysWindow *window,
+ cairo_t *cr,
+ double _x0,
+ double _y0,
+ double width,
+ double height)
+{
+ GdkPixbuf *pixbuf;
+ int icon_size;
+ int n;
+ static const char *icon_names[] = {
+ "audio-volume-muted",
+ "audio-volume-low",
+ "audio-volume-medium",
+ "audio-volume-high",
+ NULL
+ };
+
+ if (window->priv->volume_muted) {
+ n = 0;
+ } else {
+ /* select image */
+ n = 3 * window->priv->volume_level / 100 + 1;
+ if (n < 1) {
+ n = 1;
+ } else if (n > 3) {
+ n = 3;
+ }
+ }
+
+ icon_size = (int)width;
+
+ pixbuf = load_pixbuf (window, icon_names[n], icon_size);
+
+ if (pixbuf == NULL) {
+ return FALSE;
+ }
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0);
+ cairo_paint_with_alpha (cr, GSD_OSD_WINDOW_FG_ALPHA);
+
+ g_object_unref (pixbuf);
+
+ return TRUE;
+}
+
+static void
+draw_volume_boxes (GsdMediaKeysWindow *window,
+ cairo_t *cr,
+ double percentage,
+ double _x0,
+ double _y0,
+ double width,
+ double height)
+{
+ gdouble x1;
+ GdkColor color;
+ double r, g, b;
+ GtkStyle *style;
+
+ _x0 += 0.5;
+ _y0 += 0.5;
+ height = round (height) - 1;
+ width = round (width) - 1;
+ x1 = round ((width - 1) * percentage);
+ style = gtk_widget_get_style (GTK_WIDGET (window));
+
+ /* bar background */
+ gsd_osd_window_color_reverse (&style->dark[GTK_STATE_NORMAL], &color);
+ r = (float)color.red / 65535.0;
+ g = (float)color.green / 65535.0;
+ b = (float)color.blue / 65535.0;
+ gsd_osd_window_draw_rounded_rectangle (cr, 1.0, _x0, _y0, height / 6, width, height);
+ cairo_set_source_rgba (cr, r, g, b, GSD_OSD_WINDOW_FG_ALPHA / 2);
+ cairo_fill_preserve (cr);
+
+ /* bar border */
+ gsd_osd_window_color_reverse (&style->light[GTK_STATE_NORMAL], &color);
+ r = (float)color.red / 65535.0;
+ g = (float)color.green / 65535.0;
+ b = (float)color.blue / 65535.0;
+ cairo_set_source_rgba (cr, r, g, b, GSD_OSD_WINDOW_FG_ALPHA / 2);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+
+ /* bar progress */
+ if (percentage < 0.01)
+ return;
+ color = style->bg[GTK_STATE_NORMAL];
+ r = (float)color.red / 65535.0;
+ g = (float)color.green / 65535.0;
+ b = (float)color.blue / 65535.0;
+ gsd_osd_window_draw_rounded_rectangle (cr, 1.0, _x0 + 0.5, _y0 + 0.5, height / 6 - 0.5, x1, height - 1);
+ cairo_set_source_rgba (cr, r, g, b, GSD_OSD_WINDOW_FG_ALPHA);
+ cairo_fill (cr);
+}
+
+static void
+draw_action_volume (GsdMediaKeysWindow *window,
+ cairo_t *cr)
+{
+ int window_width;
+ int window_height;
+ double icon_box_width;
+ double icon_box_height;
+ double icon_box_x0;
+ double icon_box_y0;
+ double volume_box_x0;
+ double volume_box_y0;
+ double volume_box_width;
+ double volume_box_height;
+ gboolean res;
+
+ gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height);
+
+ icon_box_width = round (window_width * 0.65);
+ icon_box_height = round (window_height * 0.65);
+ volume_box_width = icon_box_width;
+ volume_box_height = round (window_height * 0.05);
+
+ icon_box_x0 = (window_width - icon_box_width) / 2;
+ icon_box_y0 = (window_height - icon_box_height - volume_box_height) / 2;
+ volume_box_x0 = round (icon_box_x0);
+ volume_box_y0 = round (icon_box_height + icon_box_y0);
+
+#if 0
+ g_message ("icon box: w=%f h=%f _x0=%f _y0=%f",
+ icon_box_width,
+ icon_box_height,
+ icon_box_x0,
+ icon_box_y0);
+ g_message ("volume box: w=%f h=%f _x0=%f _y0=%f",
+ volume_box_width,
+ volume_box_height,
+ volume_box_x0,
+ volume_box_y0);
+#endif
+
+ res = render_speaker (window,
+ cr,
+ icon_box_x0, icon_box_y0,
+ icon_box_width, icon_box_height);
+ if (! res) {
+ double speaker_width;
+ double speaker_height;
+ double speaker_cx;
+ double speaker_cy;
+
+ speaker_width = icon_box_width * 0.5;
+ speaker_height = icon_box_height * 0.75;
+ speaker_cx = icon_box_x0 + speaker_width / 2;
+ speaker_cy = icon_box_y0 + speaker_height / 2;
+
+#if 0
+ g_message ("speaker box: w=%f h=%f cx=%f cy=%f",
+ speaker_width,
+ speaker_height,
+ speaker_cx,
+ speaker_cy);
+#endif
+
+ /* draw speaker symbol */
+ draw_speaker (cr, speaker_cx, speaker_cy, speaker_width, speaker_height);
+
+ if (! window->priv->volume_muted) {
+ /* draw sound waves */
+ double wave_x0;
+ double wave_y0;
+ double wave_radius;
+
+ wave_x0 = window_width / 2;
+ wave_y0 = speaker_cy;
+ wave_radius = icon_box_width / 2;
+
+ draw_waves (cr, wave_x0, wave_y0, wave_radius, window->priv->volume_level);
+ } else {
+ /* draw 'mute' cross */
+ double cross_x0;
+ double cross_y0;
+ double cross_size;
+
+ cross_size = speaker_width * 3 / 4;
+ cross_x0 = icon_box_x0 + icon_box_width - cross_size;
+ cross_y0 = speaker_cy;
+
+ draw_cross (cr, cross_x0, cross_y0, cross_size);
+ }
+ }
+
+ /* draw volume meter */
+ draw_volume_boxes (window,
+ cr,
+ (double)window->priv->volume_level / 100.0,
+ volume_box_x0,
+ volume_box_y0,
+ volume_box_width,
+ volume_box_height);
+}
+
+static gboolean
+render_custom (GsdMediaKeysWindow *window,
+ cairo_t *cr,
+ double _x0,
+ double _y0,
+ double width,
+ double height)
+{
+ GdkPixbuf *pixbuf;
+ int icon_size;
+
+ icon_size = (int)width;
+
+ pixbuf = load_pixbuf (window, window->priv->icon_name, icon_size);
+
+ if (pixbuf == NULL) {
+ char *name;
+ if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL)
+ name = g_strdup_printf ("%s-rtl", window->priv->icon_name);
+ else
+ name = g_strdup_printf ("%s-ltr", window->priv->icon_name);
+ pixbuf = load_pixbuf (window, name, icon_size);
+ g_free (name);
+ if (pixbuf == NULL)
+ return FALSE;
+ }
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0);
+ cairo_paint_with_alpha (cr, GSD_OSD_WINDOW_FG_ALPHA);
+
+ g_object_unref (pixbuf);
+
+ return TRUE;
+}
+
+static void
+draw_action_custom (GsdMediaKeysWindow *window,
+ cairo_t *cr)
+{
+ int window_width;
+ int window_height;
+ double icon_box_width;
+ double icon_box_height;
+ double icon_box_x0;
+ double icon_box_y0;
+ double bright_box_x0;
+ double bright_box_y0;
+ double bright_box_width;
+ double bright_box_height;
+ gboolean res;
+
+ gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height);
+
+ icon_box_width = round (window_width * 0.65);
+ icon_box_height = round (window_height * 0.65);
+ bright_box_width = round (icon_box_width);
+ bright_box_height = round (window_height * 0.05);
+
+ icon_box_x0 = (window_width - icon_box_width) / 2;
+ icon_box_y0 = (window_height - icon_box_height - bright_box_height) / 2;
+ bright_box_x0 = round (icon_box_x0);
+ bright_box_y0 = round (icon_box_height + icon_box_y0);
+
+#if 0
+ g_message ("icon box: w=%f h=%f _x0=%f _y0=%f",
+ icon_box_width,
+ icon_box_height,
+ icon_box_x0,
+ icon_box_y0);
+ g_message ("brightness box: w=%f h=%f _x0=%f _y0=%f",
+ bright_box_width,
+ bright_box_height,
+ bright_box_x0,
+ bright_box_y0);
+#endif
+
+ res = render_custom (window,
+ cr,
+ icon_box_x0, icon_box_y0,
+ icon_box_width, icon_box_height);
+ if (! res && g_strcmp0 (window->priv->icon_name, "media-eject") == 0) {
+ /* draw eject symbol */
+ draw_eject (cr,
+ icon_box_x0, icon_box_y0,
+ icon_box_width, icon_box_height);
+ }
+
+ if (window->priv->show_level != FALSE) {
+ /* draw volume meter */
+ draw_volume_boxes (window,
+ cr,
+ (double)window->priv->volume_level / 100.0,
+ bright_box_x0,
+ bright_box_y0,
+ bright_box_width,
+ bright_box_height);
+ }
+}
+
+static void
+gsd_media_keys_window_expose_when_composited (GsdOsdWindow *osd_window,
+ cairo_t *cr)
+{
+ GsdMediaKeysWindow *window = GSD_MEDIA_KEYS_WINDOW (osd_window);
+
+ switch (window->priv->action) {
+ case GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME:
+ draw_action_volume (window, cr);
+ break;
+ case GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM:
+ draw_action_custom (window, cr);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gsd_media_keys_window_class_init (GsdMediaKeysWindowClass *klass)
+{
+ GsdOsdWindowClass *osd_window_class = GSD_OSD_WINDOW_CLASS (klass);
+
+ osd_window_class->expose_when_composited = gsd_media_keys_window_expose_when_composited;
+
+ g_type_class_add_private (klass, sizeof (GsdMediaKeysWindowPrivate));
+}
+
+static void
+gsd_media_keys_window_init (GsdMediaKeysWindow *window)
+{
+ GdkScreen *screen;
+
+ window->priv = GSD_MEDIA_KEYS_WINDOW_GET_PRIVATE (window);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ if (!gsd_osd_window_is_composited (GSD_OSD_WINDOW (window))) {
+ GtkBuilder *builder;
+ const gchar *objects[] = {"acme_box", NULL};
+ GtkWidget *box;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_objects_from_file (builder,
+ GTKBUILDERDIR "/acme.ui",
+ (char **) objects,
+ NULL);
+
+ window->priv->image = GTK_IMAGE (gtk_builder_get_object (builder, "acme_image"));
+ window->priv->progress = GTK_WIDGET (gtk_builder_get_object (builder, "acme_volume_progressbar"));
+ box = GTK_WIDGET (gtk_builder_get_object (builder, "acme_box"));
+
+ if (box != NULL) {
+ gtk_container_add (GTK_CONTAINER (window), box);
+ gtk_widget_show_all (box);
+ }
+
+ /* The builder needs to stay alive until the window
+ takes ownership of the box (and its children) */
+ g_object_unref (builder);
+ }
+}
+
+GtkWidget *
+gsd_media_keys_window_new (void)
+{
+ return g_object_new (GSD_TYPE_MEDIA_KEYS_WINDOW, NULL);
+}
diff --git a/plugins/media-keys/gsd-media-keys-window.h b/plugins/media-keys/gsd-media-keys-window.h
new file mode 100644
index 0000000..236d011
--- /dev/null
+++ b/plugins/media-keys/gsd-media-keys-window.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef GSD_MEDIA_KEYS_WINDOW_H
+#define GSD_MEDIA_KEYS_WINDOW_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gsd-osd-window.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_MEDIA_KEYS_WINDOW (gsd_media_keys_window_get_type ())
+#define GSD_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindow))
+#define GSD_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindowClass))
+#define GSD_IS_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_MEDIA_KEYS_WINDOW))
+#define GSD_IS_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), GSD_TYPE_MEDIA_KEYS_WINDOW))
+
+typedef struct GsdMediaKeysWindow GsdMediaKeysWindow;
+typedef struct GsdMediaKeysWindowClass GsdMediaKeysWindowClass;
+typedef struct GsdMediaKeysWindowPrivate GsdMediaKeysWindowPrivate;
+
+struct GsdMediaKeysWindow {
+ GsdOsdWindow parent;
+
+ GsdMediaKeysWindowPrivate *priv;
+};
+
+struct GsdMediaKeysWindowClass {
+ GsdOsdWindowClass parent_class;
+};
+
+typedef enum {
+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME,
+ GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM
+} GsdMediaKeysWindowAction;
+
+GType gsd_media_keys_window_get_type (void);
+
+GtkWidget * gsd_media_keys_window_new (void);
+void gsd_media_keys_window_set_action (GsdMediaKeysWindow *window,
+ GsdMediaKeysWindowAction action);
+void gsd_media_keys_window_set_action_custom (GsdMediaKeysWindow *window,
+ const char *icon_name,
+ gboolean show_level);
+void gsd_media_keys_window_set_volume_muted (GsdMediaKeysWindow *window,
+ gboolean muted);
+void gsd_media_keys_window_set_volume_level (GsdMediaKeysWindow *window,
+ int level);
+gboolean gsd_media_keys_window_is_valid (GsdMediaKeysWindow *window);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/media-keys/libmedia-keys.la b/plugins/media-keys/libmedia-keys.la
new file mode 100644
index 0000000..26117f7
--- /dev/null
+++ b/plugins/media-keys/libmedia-keys.la
@@ -0,0 +1,41 @@
+# libmedia-keys.la - a libtool library file
+# Generated by libtool (GNU libtool) 2.4
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='libmedia-keys.so'
+
+# Names of this library.
+library_names='libmedia-keys.so libmedia-keys.so libmedia-keys.so'
+
+# The name of the static archive.
+old_library='libmedia-keys.a'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags=' -pthread'
+
+# Libraries that this one depends upon.
+dependency_libs=' -lXext -lpulse-mainloop-glib -lpulse /usr/lib/libcanberra-gtk.la -lgobject-2.0 -lgthread-2.0 -lglib-2.0 -lfontconfig /usr/lib/libcanberra.la -lvorbisfile -lvorbis -logg -ltdb -lltdl /usr/lib/libmate-desktop-2.la /usr/lib/libmateconf-2.la /usr/lib/libMateCORBA-2.la -lXrandr /usr/lib/libgtk-x11-2.0.la /usr/lib/libstartup-notification-1.la -lSM -lICE /usr/lib/libgdk-x11-2.0.la /usr/lib/libatk-1.0.la /usr/lib/libpangocairo-1.0.la /usr/lib/libpangoft2-1.0.la /usr/lib/libgdk_pixbuf-2.0.la /usr/lib/libcairo.la -lpixman-1 -lpng14 -lXrender -lX11 /usr/lib/libpango-1.0.la /usr/lib/libfontconfig.la -lfreetype -lexpat /usr/lib/libgio-2.0.la -lresolv -lz /usr/lib/libgmodule-2.0.la -ldl /usr/lib/libdbus-glib-1.la /usr/lib/libdbus-1.la /usr/lib/libgobject-2.0.la /usr/lib/libgthread-2.0.la -lpthread -lrt /usr/lib/libglib-2.0.la -lm'
+
+# Names of additional weak libraries provided by this library
+weak_library_names=''
+
+# Version information for libmedia-keys.
+current=0
+age=0
+revision=0
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/lib/mate-settings-daemon-2.0'
diff --git a/plugins/media-keys/media-keys.mate-settings-plugin b/plugins/media-keys/media-keys.mate-settings-plugin
new file mode 100644
index 0000000..48b62bc
--- /dev/null
+++ b/plugins/media-keys/media-keys.mate-settings-plugin
@@ -0,0 +1,136 @@
+[MATE Settings Plugin]
+Module=media-keys
+IAge=0
+Name=Media keys
+Name[af]=Mediasleutels
+Name[ar]=مفاتيح الوسائط
+Name[as]=মিডিয়া কি
+Name[ast]=Tecles multimedia
+Name[be@latin]=Medyja-klavišy
+Name[bg]=Мултимедийни клавиши
+Name[bn]=মিডিয়া কী
+Name[bn_IN]=মিডিয়া কি
+Name[br]=Alc'hwezioù ar media
+Name[ca]=Tecles multimèdia
+Name[ca@valencia]=Tecles multimèdia
+Name[crh]=Ortam tuşları
+Name[cs]=Multimediální klávesy
+Name[da]=Medietaster
+Name[de]=Medientasten
+Name[el]=Πλήκτρα πολυμέσων
+Name[en@shaw]=𐑥𐑰𐑛𐑦𐑩 𐑒𐑰𐑟
+Name[en_GB]=Media keys
+Name[es]=Teclas multimedia
+Name[et]=Meediaklahvid
+Name[eu]=Multimedia-teklak
+Name[fi]=Medianäppäimet
+Name[fr]=Touches multimédias
+Name[ga]=Eochracha meán
+Name[gl]=Teclas multimedia
+Name[gu]=મીડિયા કીઓ
+Name[he]=מקשי מדיה
+Name[hi]=मीडिया कुंजी
+Name[hu]=Médiabillentyűk
+Name[id]=Kunci media
+Name[it]=Tasti multimediali
+Name[ja]=メディア・キー
+Name[kn]=ಮೀಡಿಯಾ ಕೀಲಿಗಳು
+Name[ko]=미디어 키
+Name[lt]=Multimedijos klavišai
+Name[lv]=Mediju taustiņi
+Name[mk]=Музички копчиња
+Name[ml]=മാധ്യമ സംയോജകം
+Name[mr]=मिडीया कि
+Name[nb]=Medietaster
+Name[nds]=Medienknöppe
+Name[nl]=Mediatoetsen
+Name[nn]=Mediatastar
+Name[or]=ମେଡିଆ କିଗୁଡ଼ିକ
+Name[pa]=ਮੀਡਿਆ ਸਵਿੱਚਾਂ
+Name[pl]=Klawisze multimedialne
+Name[pt]=Teclas de Media
+Name[pt_BR]=Teclas de mídia
+Name[ro]=Taste media
+Name[ru]=Мультимедийные клавиши
+Name[sk]=Multimediálne klávesy
+Name[sl]=Večpredstavnostne tipke
+Name[sr]=Мултимедијални тастери
+Name[sr@latin]=Multimedijalni tasteri
+Name[sv]=Mediatangenter
+Name[ta]=ஊடக விசைகள்
+Name[te]=మాద్యమం కీలు
+Name[th]=ปุ่มสั่งการสื่อ
+Name[tr]=Ortam tuşları
+Name[uk]=Мультимедійний клавіші
+Name[vi]=Phím nhạc/phim
+Name[zh_CN]=媒体键
+Name[zh_HK]=多媒體按鍵
+Name[zh_TW]=多媒體按鍵
+Description=Media keys plugin
+Description[af]=Inprop vir mediasleutels
+Description[ar]=ملحق مفاتيح الوسائط
+Description[as]=মিডিয়া-কি প্লাগ-ইন
+Description[ast]=Complementu de tecles multimedia
+Description[be@latin]=Plugin medyja-klavišaŭ
+Description[bg]=Приставка за мултимедийни клавиши
+Description[bn]=মিডিয়া-কি প্লাগ-ইন
+Description[bn_IN]=মিডিয়া-কি প্লাগ-ইন
+Description[br]=Enlugellad alc'hwezioù ar media
+Description[ca]=Connector de les tecles multimèdia
+Description[ca@valencia]=Connector de les tecles multimèdia
+Description[crh]=Ortam tuşları eklentisi
+Description[cs]=Zásuvný modul multimediálních kláves
+Description[da]=Medietastmodul
+Description[de]=Medientastenmodul
+Description[el]=Πρόσθετη λειτουργία πλήκτρων πολυμέσων
+Description[en@shaw]=𐑥𐑰𐑛𐑦𐑩 𐑒𐑰𐑟 𐑐𐑤𐑳𐑜𐑦𐑯
+Description[en_GB]=Media keys plugin
+Description[es]=Complemento de teclas multimedia
+Description[et]=Meediaklahvide plugin
+Description[eu]=Multimedia-teklen plugina
+Description[fi]=Medianäppäinten liitännäinen
+Description[fr]=Greffon des touches multimédias
+Description[ga]=Breiseán eochracha meán
+Description[gl]=Engadido das teclas multimedia
+Description[gu]=મીડિયા કી પલ્ગઇન
+Description[he]=תוסף מקשי מדיה
+Description[hi]=मीडिया कुंजी प्लगिन
+Description[hu]=Médiabillentyűk bővítmény
+Description[id]=Plugin kunci media
+Description[it]=Plugin per i tasti multimediali
+Description[ja]=メディア・キーのプラグイン
+Description[kn]=ಮೀಡಿಯಾ ಕೀಲಿಗಳು ಪ್ಲಗ್ಇನ್
+Description[ko]=미디어 키 플러그인
+Description[lt]=Multimedijos klavišų įskiepis
+Description[lv]=Mediju taustiņu spraudnis
+Description[mk]=Додаток за копчињата за музика
+Description[ml]= സംയോജകം
+Description[mr]=मिडीया कि पल्गइन
+Description[nb]=Tillegg for medietaster
+Description[nds]=Medienknöppeplugin
+Description[nl]=Mediatoetsen-plugin
+Description[nn]=Tillegg for medietastar
+Description[or]=ମେଡ଼ିଆ କିଗୁଡ଼ିକର ପ୍ଲଗଇନ
+Description[pa]=ਮੀਡਿਆ ਸਵਿੱਚ ਪਲੱਗਇਨ
+Description[pl]=Wtyczka klawiszy multimedialnych
+Description[pt]=Plugin de teclas de media
+Description[pt_BR]=Plug-in de teclas de mídia
+Description[ro]=Modul taste media
+Description[ru]=Модуль мультимедийных клавиш
+Description[sk]=Modul multimediálnych kláves
+Description[sl]=Vstavek večpredstavnostnih tipk
+Description[sr]=Додатак за мултимедијалне тастере
+Description[sr@latin]=Dodatak za multimedijalne tastere
+Description[sv]=Insticksmodul för mediatangenter
+Description[ta]=ஊடக விசைகள் சொருகி
+Description[te]=మాద్యమం కీల ప్లగ్ఇన్
+Description[th]=ปลั๊กอินจัดการปุ่มสั่งการสื่อ
+Description[tr]=Ortam tuşları eklentisi
+Description[uk]=Модуль мультимедійних клавіш
+Description[vi]=Phần mở rộng phím nhạc/phim
+Description[zh_CN]=媒体键插件
+Description[zh_HK]=多媒體按鍵外掛程式
+Description[zh_TW]=多媒體按鍵外掛程式
+Authors=
+Copyright=Copyright © 2007
+Website=
diff --git a/plugins/media-keys/media-keys.mate-settings-plugin.in b/plugins/media-keys/media-keys.mate-settings-plugin.in
new file mode 100644
index 0000000..fdaf931
--- /dev/null
+++ b/plugins/media-keys/media-keys.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=media-keys
+IAge=0
+_Name=Media keys
+_Description=Media keys plugin
+Authors=
+Copyright=Copyright © 2007
+Website=
diff --git a/plugins/media-keys/test-media-keys.c b/plugins/media-keys/test-media-keys.c
new file mode 100644
index 0000000..e3345f9
--- /dev/null
+++ b/plugins/media-keys/test-media-keys.c
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-media-keys-manager.h"
+
+static GsdMediaKeysManager *manager = NULL;
+
+int
+main (int argc,
+ char **argv)
+{
+ GError *error;
+ gboolean res;
+
+#ifdef ENABLE_NLS
+ bindtextdomain (GETTEXT_PACKAGE, MATE_SETTINGS_LOCALEDIR);
+# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+# endif
+ textdomain (GETTEXT_PACKAGE);
+#endif
+
+ error = NULL;
+ if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
+ fprintf (stderr, "%s", error->message);
+ g_error_free (error);
+ exit (1);
+ }
+
+ manager = gsd_media_keys_manager_new ();
+
+ error = NULL;
+ res = gsd_media_keys_manager_start (manager, &error);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/plugins/media-keys/test-media-window.c b/plugins/media-keys/test-media-window.c
new file mode 100644
index 0000000..c97f3d9
--- /dev/null
+++ b/plugins/media-keys/test-media-window.c
@@ -0,0 +1,152 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-media-keys-window.h"
+
+static gboolean
+update_state (GtkWidget *window)
+{
+ static int count = 0;
+
+ count++;
+
+ switch (count) {
+ case 1:
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (window),
+ 50);
+ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (window),
+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
+
+ gtk_widget_show (window);
+ break;
+ case 2:
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (window),
+ 100);
+ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (window),
+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
+
+ gtk_widget_show (window);
+ break;
+ case 3:
+ gsd_media_keys_window_set_volume_muted (GSD_MEDIA_KEYS_WINDOW (window),
+ TRUE);
+ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (window),
+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
+
+ gtk_widget_show (window);
+ break;
+ case 4:
+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (window),
+ "media-eject",
+ FALSE);
+
+ gtk_widget_show (window);
+ break;
+ case 5:
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (window),
+ 0);
+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (window),
+ "gpm-brightness-lcd",
+ TRUE);
+
+ gtk_widget_show (window);
+ break;
+ case 6:
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (window),
+ 50);
+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (window),
+ "gpm-brightness-lcd",
+ TRUE);
+
+ gtk_widget_show (window);
+ break;
+ case 7:
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (window),
+ 100);
+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (window),
+ "gpm-brightness-lcd",
+ TRUE);
+
+ gtk_widget_show (window);
+ break;
+ default:
+ gtk_main_quit ();
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+test_window (void)
+{
+ GtkWidget *window;
+
+ window = gsd_media_keys_window_new ();
+ gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ALWAYS);
+
+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (window),
+ 0);
+ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (window),
+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
+
+ gtk_widget_show (window);
+
+ g_timeout_add (3000, (GSourceFunc) update_state, window);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GError *error = NULL;
+
+#ifdef ENABLE_NLS
+ bindtextdomain (GETTEXT_PACKAGE, MATE_SETTINGS_LOCALEDIR);
+# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+# endif
+ textdomain (GETTEXT_PACKAGE);
+#endif
+
+ if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
+ fprintf (stderr, "%s", error->message);
+ g_error_free (error);
+ exit (1);
+ }
+
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ DATADIR G_DIR_SEPARATOR_S "mate-power-manager" G_DIR_SEPARATOR_S "icons");
+
+ test_window ();
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/plugins/media-keys/touchpad-disabled-16.png b/plugins/media-keys/touchpad-disabled-16.png
new file mode 100644
index 0000000..c8355de
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled-16.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-disabled-22.png b/plugins/media-keys/touchpad-disabled-22.png
new file mode 100644
index 0000000..706fbc7
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled-22.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-disabled-24.png b/plugins/media-keys/touchpad-disabled-24.png
new file mode 100644
index 0000000..fc0bac7
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled-24.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-disabled-32.png b/plugins/media-keys/touchpad-disabled-32.png
new file mode 100644
index 0000000..1311c60
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled-32.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-disabled-48.png b/plugins/media-keys/touchpad-disabled-48.png
new file mode 100644
index 0000000..8f6ee03
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled-48.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-disabled-template.svg b/plugins/media-keys/touchpad-disabled-template.svg
new file mode 100644
index 0000000..4d08198
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled-template.svg
@@ -0,0 +1,1172 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="300"
+ id="svg11300"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:version="0.46+devel"
+ sodipodi:docname="hicolor_status_scalable_touchpad-disabled.svg"
+ sodipodi:version="0.32"
+ style="display:inline;enable-background:new"
+ version="1.0"
+ width="400">
+ <title
+ id="title3835">Touchpad</title>
+ <metadata
+ id="metadata154">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Touchpad</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Lapo Calamandrei</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:contributor>
+ <dc:source />
+ <cc:license
+ rdf:resource="" />
+ <dc:subject>
+ <rdf:Bag />
+ </dc:subject>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ fill="#f57900"
+ gridtolerance="12"
+ guidetolerance="13"
+ height="300px"
+ id="base"
+ inkscape:current-layer="layer2"
+ inkscape:cx="433.90068"
+ inkscape:cy="165.06237"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:showpageshadow="false"
+ inkscape:snap-bbox="true"
+ inkscape:snap-nodes="true"
+ inkscape:window-height="1177"
+ inkscape:window-width="1920"
+ inkscape:window-x="1440"
+ inkscape:window-y="0"
+ inkscape:zoom="1.4142136"
+ objecttolerance="7"
+ pagecolor="#ffffff"
+ showgrid="false"
+ stroke="#ef2929"
+ width="400px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ showborder="true"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ enabled="true"
+ id="grid5883"
+ spacingx="0.5px"
+ spacingy="0.5px"
+ type="xygrid"
+ visible="true"
+ empspacing="2"
+ snapvisiblegridlinesonly="true" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="313.98438,106.53125"
+ id="guide4872" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="312.32813,105.01563"
+ id="guide4874" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="312.90625,147"
+ id="guide4876" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="313,161.6875"
+ id="guide4878" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="341.64306,213.01592"
+ id="guide4880" />
+ </sodipodi:namedview>
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 150 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="400 : 150 : 1"
+ inkscape:persp3d-origin="200 : 100 : 1"
+ id="perspective147" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2972">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="0"
+ id="stop2974" />
+ <stop
+ style="stop-color:#555753;stop-opacity:1"
+ offset="1"
+ id="stop2976" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3100">
+ <stop
+ id="stop3102"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106" />
+ <stop
+ id="stop3108"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7"
+ id="radialGradient3766-2"
+ cx="311"
+ cy="225.23932"
+ fx="311"
+ fy="225.23932"
+ r="8"
+ gradientTransform="matrix(1.4590081,0,0,1.0942561,-142.75153,-21.969492)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3752-2">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0"
+ id="stop3754-2" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="1"
+ id="stop3756-8" />
+ </linearGradient>
+ <linearGradient
+ y2="238.1875"
+ x2="324.875"
+ y1="231.5"
+ x1="304.8125"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3794"
+ xlink:href="#linearGradient3752-2"
+ inkscape:collect="always"
+ gradientTransform="translate(0,-1)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6"
+ id="radialGradient3766-2-5"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(2.0157047,0,0,1.5117786,-315.08929,-153.04762)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3752-2-3">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0"
+ id="stop3754-2-2" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="1"
+ id="stop3756-8-6" />
+ </linearGradient>
+ <linearGradient
+ y2="238.1875"
+ x2="324.875"
+ y1="231.5"
+ x1="304.8125"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2894"
+ xlink:href="#linearGradient3752-2-3"
+ inkscape:collect="always"
+ gradientTransform="translate(1,-38)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3743"
+ id="linearGradient3749"
+ x1="304"
+ y1="177"
+ x2="304"
+ y2="195"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6-4"
+ id="radialGradient3766-2-5-1"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(3.7131449,0,0,3.563472,-838.85008,-725.00376)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="177"
+ x1="304"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2910"
+ xlink:href="#linearGradient3743-4"
+ inkscape:collect="always"
+ gradientTransform="matrix(1.9473685,0,0,1.9444446,-291.47369,-291.58337)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100"
+ id="linearGradient3092"
+ x1="302"
+ y1="82.375"
+ x2="338"
+ y2="92.75"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100-5"
+ id="linearGradient3092-9"
+ x1="305.89941"
+ y1="83.784264"
+ x2="334.10059"
+ y2="91.340736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,66)" />
+ <linearGradient
+ id="linearGradient3100-5">
+ <stop
+ id="stop3102-6"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104-13" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106-5" />
+ <stop
+ id="stop3108-50"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110-4"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2-3" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="180.95102"
+ x1="304"
+ gradientTransform="matrix(1.8448754,0,0,1.8333335,-257.26455,-204.75003)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4350"
+ xlink:href="#linearGradient3743-4-4"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4-66-6">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6-61-7" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4-0-6" />
+ </linearGradient>
+ <radialGradient
+ r="8"
+ fy="222.91086"
+ fx="312.22864"
+ cy="222.91086"
+ cx="312.22864"
+ gradientTransform="matrix(2.8880002,0,0,2.9155676,-583.21633,-511.91208)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient4444"
+ xlink:href="#linearGradient3760-7-6-4-66-6"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2978"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient3756"
+ x1="318.5"
+ y1="147.03621"
+ x2="318.5"
+ y2="155.96379"
+ gradientUnits="userSpaceOnUse" />
+ <inkscape:perspective
+ id="perspective3111"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3912"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective4331"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective4799"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="artwork"
+ style="display:inline">
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="disabled"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <rect
+ height="256"
+ id="rect6282"
+ inkscape:label="256x256"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="256"
+ x="16"
+ y="28" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:groupmode="layer"
+ inkscape:label="baseplate"
+ style="display:none">
+ <rect
+ height="48"
+ id="rect6284"
+ inkscape:label="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="48"
+ x="296"
+ y="50" />
+ <rect
+ height="32"
+ id="rect6592"
+ inkscape:label="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="32"
+ x="303"
+ y="126" />
+ <rect
+ height="22"
+ id="rect6749"
+ inkscape:label="22x22"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="22"
+ x="303"
+ y="177" />
+ <rect
+ height="16"
+ id="rect6833"
+ inkscape:label="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="16"
+ x="303"
+ y="219" />
+ <rect
+ height="24"
+ id="rect8104"
+ inkscape:label="24x24"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="24"
+ x="302"
+ y="176" />
+ <text
+ id="context"
+ inkscape:label="context"
+ style="font-size:18.30070686px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Bitstream Vera Sans"
+ x="20.970737"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan2716"
+ sodipodi:role="line"
+ x="20.970737"
+ y="21.513618">devices</tspan></text>
+ <text
+ id="icon-name"
+ inkscape:label="icon-name"
+ sodipodi:linespacing="125%"
+ style="font-size:18.30070686px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold"
+ x="141.97073"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan3023"
+ sodipodi:role="line"
+ x="141.97073"
+ y="21.513618">input-touchpad</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="small sizes"
+ style="display:inline">
+ <path
+ style="color:#000000;fill:url(#linearGradient3794);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 303.5,227.5 0,4 c 0,1.108 0.892,2 2,2 l 11,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,1.108 -0.892,2 -2,2 l -11,0 c -1.108,0 -2,-0.892 -2,-2 z"
+ id="rect2846-2-3"
+ sodipodi:nodetypes="ccccccccc" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846"
+ width="15"
+ height="10"
+ x="303.5"
+ y="219.5"
+ rx="2"
+ ry="2" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3694"
+ width="13"
+ height="12"
+ x="304.5"
+ y="220.5"
+ rx="1"
+ ry="1" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 304,229.5 0,1 c 0,0.0541 0.002,0.1029 0,0.15625 0.45244,0.21377 0.96717,0.34375 1.5,0.34375 l 11,0 c 0.53283,0 1.04756,-0.12998 1.5,-0.34375 L 318,229.5 c -0.41577,0.30853 -0.93558,0.5 -1.5,0.5 l -11,0 c -0.56442,0 -1.08423,-0.19147 -1.5,-0.5 z"
+ id="rect2846-2"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728"
+ width="1"
+ height="3"
+ x="310"
+ y="230"
+ rx="0"
+ ry="0" />
+ <rect
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728-4"
+ width="1"
+ height="3"
+ x="311"
+ y="230"
+ rx="0"
+ ry="0" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient3749);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6"
+ width="19"
+ height="18"
+ x="304.5"
+ y="178.5"
+ rx="2"
+ ry="2" />
+ <path
+ style="color:#000000;fill:url(#linearGradient2894);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 304.5,190.5 0,4 c 0,1.108 0.892,2 2,2 l 15,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,1.108 -0.892,2 -2,2 l -15,0 c -1.108,0 -2,-0.892 -2,-2 z"
+ id="rect2846-2-3-0"
+ sodipodi:nodetypes="ccccccccc" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2-5);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28"
+ width="18.999943"
+ height="14.000024"
+ x="304.5"
+ y="178.5"
+ rx="2"
+ ry="2" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3694-0"
+ width="17.000095"
+ height="16.000011"
+ x="305.5"
+ y="179.5"
+ rx="1"
+ ry="1" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 305,192.5 0,1 c 0,0.0541 0.002,0.1029 0,0.15625 0.45244,0.21377 0.96717,0.34375 1.5,0.34375 l 15,0 c 0.53283,0 1.04756,-0.12998 1.5,-0.34375 L 323,192.5 c -0.41577,0.30853 -0.93558,0.5 -1.5,0.5 l -15,0 c -0.56442,0 -1.08423,-0.19147 -1.5,-0.5 z"
+ id="rect2846-2-1"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728-5"
+ width="1"
+ height="3"
+ x="313"
+ y="193"
+ rx="0"
+ ry="0" />
+ <rect
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728-4-5"
+ width="1"
+ height="3"
+ x="314"
+ y="193"
+ rx="0"
+ ry="0" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient2910);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6-4"
+ width="38"
+ height="35"
+ x="301.5"
+ y="55.5"
+ rx="4"
+ ry="4" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2-5-1);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-66"
+ width="35.999939"
+ height="33.000004"
+ x="302.50006"
+ y="56.499996"
+ rx="3.0000038"
+ ry="3.0000038" />
+ <rect
+ ry="2"
+ rx="2"
+ y="57.5"
+ x="303.5"
+ height="25"
+ width="34"
+ id="rect3694-0-0"
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g4205">
+ <path
+ id="rect3694-0-0-9"
+ d="m 303,84.5 0,2 c 0,1.367703 1.1323,2.5 2.5,2.5 l 14.5,0 0,-2 -14.5,0 c -0.0657,0 -0.1232,-0.02642 -0.1875,-0.03125 C 304.01204,86.871142 303,85.827989 303,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ <path
+ id="rect3694-0-0-9-8"
+ d="m 338,84.5 0,2 c 0,1.367703 -1.1323,2.5 -2.5,2.5 l -14.5,0 0,-2 14.5,0 c 0.0657,0 0.1232,-0.02642 0.1875,-0.03125 C 336.98796,86.871142 338,85.827989 338,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ </g>
+ <g
+ id="g2958"
+ style="fill-opacity:1;stroke:url(#linearGradient2978)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="rect2846-28-66-1"
+ d="m 302.5,80.5 0,6 c 0,1.662002 1.338,3 3,3 l 30,0 c 1.662,0 3,-1.337998 3,-3 l 0,-6 c 0,1.662002 -1.338,3 -3,3 l -30,0 c -1.662,0 -3,-1.337998 -3,-3 z"
+ style="color:#000000;fill:url(#linearGradient3092);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2978);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path3112"
+ d="m 320.5,83.5 0,6"
+ style="fill:none;stroke:url(#linearGradient2978);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
+ </g>
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 303.5,83.875 0,2.625 c 0,1.12494 0.87506,2 2,2 l 14,0 0,-4 -14,0 c -0.74347,0 -1.40165,-0.267405 -2,-0.625 z"
+ id="path3161-2"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 337.5,83.875 0,2.625 c 0,1.12494 -0.87506,2 -2,2 l -14,0 0,-4 14,0 c 0.74347,0 1.40165,-0.267405 2,-0.625 z"
+ id="path3161-2-0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 303,82.65625 0,1.3125 C 303.8401,84.608417 304.86264,85 306,85 l 14,0 0,-1 -14,0 c -1.20201,0 -2.2695,-0.516326 -3,-1.34375 z"
+ id="rect2846-28-66-0" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 338,82.65625 0,1.3125 C 337.1599,84.608417 336.13736,85 335,85 l -14,0 0,-1 14,0 c 1.20201,0 2.2695,-0.516326 3,-1.34375 z"
+ id="rect2846-28-66-0-6" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 309.49911,81.5 22.00265,0"
+ id="path4233" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 336.5,76.504425 0,-13.00885"
+ id="path4235" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237"
+ width="0.99953973"
+ height="0.99999803"
+ x="307.00046"
+ y="81" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6"
+ width="0.99953973"
+ height="0.99999803"
+ x="333.00046"
+ y="81" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="78" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-5"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="61" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient4350);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6-4-0"
+ width="28"
+ height="27"
+ x="304.5"
+ y="128.5"
+ rx="3"
+ ry="3" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient4444);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-66-3-9"
+ width="28"
+ height="26"
+ x="304.5"
+ y="128.5"
+ rx="3"
+ ry="3" />
+ <rect
+ ry="2"
+ rx="2"
+ y="129.5"
+ x="305.5"
+ height="20"
+ width="26"
+ id="rect3694-0-0-2"
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g3752"
+ style="stroke:url(#linearGradient3756)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="rect2846-28-66-1-2"
+ d="m 304.5,147.5 0,5 c 0,1.662 1.338,3 3,3 l 22,0 c 1.662,0 3,-1.338 3,-3 l 0,-5 c 0,1.662 -1.338,3 -3,3 l -22,0 c -1.662,0 -3,-1.338 -3,-3 z"
+ style="color:#000000;fill:url(#linearGradient3092-9);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3756);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3112-3"
+ d="m 318.5,150.5 0,5"
+ style="fill:none;stroke:url(#linearGradient3756);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g4205-5"
+ transform="translate(-2,66)">
+ <path
+ id="rect3694-0-0-9-83"
+ d="m 307,84.5 0,2 c 0,1.367703 1.1323,2.5 2.5,2.5 l 10.5,0 0,-2 -10.5,0 c -0.0657,0 -0.1232,-0.02642 -0.1875,-0.03125 C 308.01204,86.871142 307,85.827989 307,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ sodipodi:nodetypes="ccccccsc" />
+ <path
+ id="rect3694-0-0-9-8-9"
+ d="m 334,84.5 0,2 c 0,1.367703 -1.1323,2.5 -2.5,2.5 l -10.5,0 0,-2 10.5,0 c 0.0657,0 0.1232,-0.02642 0.1875,-0.03125 C 332.98796,86.871142 334,85.827989 334,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ sodipodi:nodetypes="ccccccsc" />
+ </g>
+ <path
+ style="opacity:0.6;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 305.5,150.875 0,1.625 c 0,1.12494 0.87506,2 2,2 l 10,0 0,-3 -10,0 c -0.74347,0 -1.40165,-0.2674 -2,-0.625 z"
+ id="path3161-2-4"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.6;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 331.5,150.875 0,1.625 c 0,1.12494 -0.87506,2 -2,2 l -10,0 0,-3 10,0 c 0.74347,0 1.40165,-0.2674 2,-0.625 z"
+ id="path3161-2-0-7"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 305,149.65625 0,1.3125 c 0.8401,0.63967 1.86264,1.03125 3,1.03125 l 10,0 0,-1 -10,0 c -1.20201,0 -2.2695,-0.51633 -3,-1.34375 z"
+ id="rect2846-28-66-0-7"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 332,149.65625 0,1.3125 C 331.1599,151.60842 330.13736,152 329,152 l -10,0 0,-1 10,0 c 1.20201,0 2.2695,-0.51633 3,-1.34375 z"
+ id="rect2846-28-66-0-6-4"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 310.49911,148.5 15.00265,0"
+ id="path4233-4"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 330.5,143.50442 0,-9.00884"
+ id="path4235-3"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-5"
+ width="0.99953973"
+ height="0.99999803"
+ x="308.00046"
+ y="148" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-80"
+ width="0.99953973"
+ height="0.99999803"
+ x="327.00046"
+ y="148" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-3"
+ width="0.99953973"
+ height="0.99999803"
+ x="330.00046"
+ y="145" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-5-0"
+ width="0.99953973"
+ height="0.99999803"
+ x="330.00046"
+ y="132" />
+ <g
+ id="g6998"
+ transform="translate(297.68228,160.06933)">
+ <rect
+ style="fill:#ef2929;fill-opacity:1;stroke:#a40000;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect5861"
+ width="7.9959006"
+ height="7.9958639"
+ x="12.802565"
+ y="26.419176"
+ rx="1.5753298"
+ ry="1.5876297" />
+ <g
+ id="g6991">
+ <rect
+ y="27.918909"
+ x="14.302099"
+ height="2"
+ width="2"
+ id="rect6981"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ y="30.918909"
+ x="14.302099"
+ height="2"
+ width="2"
+ id="rect6983"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ y="28.918909"
+ x="15.302099"
+ height="3.0000005"
+ width="2.9999998"
+ id="rect6985"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ y="30.918909"
+ x="17.302099"
+ height="2"
+ width="2"
+ id="rect6987"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ y="27.918909"
+ x="17.302099"
+ height="2"
+ width="2"
+ id="rect6989"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ </g>
+ </g>
+ <g
+ id="g7188"
+ transform="translate(300.694,231.07228)">
+ <rect
+ ry="1.1537831"
+ rx="1.0881115"
+ y="-6.0811005"
+ x="7.3020992"
+ height="7"
+ width="7"
+ id="rect7176"
+ style="fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ ry="0"
+ rx="0"
+ y="-5.0811005"
+ x="8.3020992"
+ height="2"
+ width="2"
+ id="rect7178"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ ry="0"
+ rx="0"
+ y="-5.0811005"
+ x="11.302099"
+ height="2"
+ width="2"
+ id="rect7180"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ ry="0"
+ rx="0"
+ y="-2.0811005"
+ x="11.302099"
+ height="2"
+ width="2"
+ id="rect7182"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ ry="0"
+ rx="0"
+ y="-2.0811005"
+ x="8.3020992"
+ height="2"
+ width="2"
+ id="rect7184"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <rect
+ ry="0"
+ rx="0"
+ y="-4.0811005"
+ x="9.3020992"
+ height="3.0000005"
+ width="3.0000002"
+ id="rect7186"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.9980467,0,0,0.9980473,271.08457,122.06151)"
+ id="g7081">
+ <rect
+ style="fill:#ef2929;fill-opacity:0.98473283;fill-rule:evenodd;stroke:#a40000;stroke-width:1.0019567;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10.43299961;stroke-opacity:1;stroke-dasharray:none"
+ id="rect7069"
+ width="10.000005"
+ height="10"
+ x="42.5"
+ y="21.5"
+ rx="1.7585585"
+ ry="1.7585585" />
+ <g
+ id="g7075"
+ transform="matrix(0.7692308,0,0,0.7692308,2.5,6.1153846)">
+ <path
+ id="path7071"
+ d="m 56,24 5,5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.69330692;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path7073"
+ d="m 56,29 5,-5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.69330692;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <rect
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1.00195682;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10.43299961;stroke-opacity:1;stroke-dasharray:none"
+ id="rect7079"
+ width="8.0156603"
+ height="8.0156527"
+ x="43.492176"
+ y="22.492174"
+ rx="0.78614295"
+ ry="0.78614295" />
+ </g>
+ <g
+ id="layer4-3"
+ inkscape:label="Muted"
+ style="display:inline"
+ transform="translate(284.98438,57.984079)">
+ <g
+ id="g4694"
+ transform="translate(-2,0)">
+ <rect
+ ry="1.4868355"
+ rx="1.4868355"
+ y="16.498245"
+ x="31.498245"
+ height="12.00351"
+ width="12.00351"
+ id="rect2021"
+ style="fill:#ef2929;fill-opacity:1;stroke:#cc0000;stroke-width:0.9964897;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:1.20000057;display:inline" />
+ <rect
+ ry="0.4861359"
+ rx="0.4861359"
+ y="17.500002"
+ x="32.5"
+ height="9.9999962"
+ width="9.9999962"
+ id="rect3795"
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:0.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:1.20000057;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4682"
+ d="m 35,20 5,5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4684"
+ d="m 40,20 -5,5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="hires"
+ style="display:inline" />
+ <g
+ id="g256"
+ style="display:inline;enable-background:new"
+ transform="translate(20,30)" />
+ <g
+ id="g4021"
+ style="display:inline;enable-background:new"
+ transform="translate(-577.97771,370.7754)" />
+ <g
+ transform="translate(-457.73144,-1.374928)"
+ id="g10306"
+ style="enable-background:new">
+ <g
+ id="layer3"
+ inkscape:label="plate"
+ style="display:none">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6282-8"
+ width="256"
+ height="256"
+ x="20"
+ y="20"
+ inkscape:label="256x256" />
+ <rect
+ inkscape:label="48x48"
+ y="39.99633"
+ x="296.0625"
+ height="48"
+ width="48"
+ id="rect6284-8"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6592-5"
+ width="32"
+ height="32"
+ x="303"
+ y="115.99633"
+ inkscape:label="32x32" />
+ <rect
+ inkscape:label="22x22"
+ y="167.05884"
+ x="303"
+ height="22"
+ width="22"
+ id="rect6749-0"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6833-9"
+ width="16"
+ height="16"
+ x="303"
+ y="209"
+ inkscape:label="16x16" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5028"
+ width="24"
+ height="24"
+ x="301.95709"
+ y="165.95343"
+ inkscape:label="24x24" />
+ </g>
+ <g
+ id="layer1-6"
+ inkscape:label="artwork"
+ style="display:inline">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="256x256"
+ width="256"
+ height="256"
+ x="23.5"
+ y="171.59863"
+ inkscape:label="256x256" />
+ <rect
+ y="171.59863"
+ x="-38.5"
+ height="48"
+ width="48"
+ id="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="48x48" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="24x24"
+ width="24"
+ height="24"
+ x="-123.5"
+ y="171.59863"
+ inkscape:label="24x24" />
+ <rect
+ y="171.59863"
+ x="-155.5"
+ height="16"
+ width="16"
+ id="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="16x16" />
+ <rect
+ inkscape:label="32x32"
+ y="171.59863"
+ x="-87.5"
+ height="32"
+ width="32"
+ id="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g4445"
+ style="display:inline;enable-background:new"
+ transform="translate(-393,-62.246031)" />
+ <g
+ id="g5542"
+ style="display:inline;enable-background:new"
+ transform="translate(-364.39697,166.26869)" />
+ </g>
+</svg>
diff --git a/plugins/media-keys/touchpad-disabled.svg b/plugins/media-keys/touchpad-disabled.svg
new file mode 100644
index 0000000..4f1b37f
--- /dev/null
+++ b/plugins/media-keys/touchpad-disabled.svg
@@ -0,0 +1,833 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="38"
+ id="svg11300"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="touchpad-disabled.svg"
+ sodipodi:version="0.32"
+ style="display:inline;enable-background:new"
+ version="1.0"
+ width="41">
+ <title
+ id="title3835">Touchpad</title>
+ <metadata
+ id="metadata154">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Touchpad</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Lapo Calamandrei</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:contributor>
+ <dc:source />
+ <cc:license
+ rdf:resource="" />
+ <dc:subject>
+ <rdf:Bag />
+ </dc:subject>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ fill="#f57900"
+ gridtolerance="12"
+ guidetolerance="13"
+ height="300px"
+ id="base"
+ inkscape:current-layer="layer2"
+ inkscape:cx="133.90068"
+ inkscape:cy="-44.351844"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:showpageshadow="false"
+ inkscape:snap-bbox="true"
+ inkscape:snap-nodes="true"
+ inkscape:window-height="975"
+ inkscape:window-width="1680"
+ inkscape:window-x="0"
+ inkscape:window-y="25"
+ inkscape:zoom="1.4142136"
+ objecttolerance="7"
+ pagecolor="#ffffff"
+ showgrid="false"
+ stroke="#ef2929"
+ width="400px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ showborder="true"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ enabled="true"
+ id="grid5883"
+ spacingx="0.5px"
+ spacingy="0.5px"
+ type="xygrid"
+ visible="true"
+ empspacing="2"
+ snapvisiblegridlinesonly="true" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="13.98438,-101.46875"
+ id="guide4872" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="12.32813,-102.98437"
+ id="guide4874" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="12.90625,-61"
+ id="guide4876" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="13,-46.3125"
+ id="guide4878" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="41.64306,5.01592"
+ id="guide4880" />
+ </sodipodi:namedview>
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 150 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="400 : 150 : 1"
+ inkscape:persp3d-origin="200 : 100 : 1"
+ id="perspective147" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2972">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="0"
+ id="stop2974" />
+ <stop
+ style="stop-color:#555753;stop-opacity:1"
+ offset="1"
+ id="stop2976" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3100">
+ <stop
+ id="stop3102"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106" />
+ <stop
+ id="stop3108"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7"
+ id="radialGradient3766-2"
+ cx="311"
+ cy="225.23932"
+ fx="311"
+ fy="225.23932"
+ r="8"
+ gradientTransform="matrix(1.4590081,0,0,1.0942561,-142.75153,-21.969492)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3752-2">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0"
+ id="stop3754-2" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="1"
+ id="stop3756-8" />
+ </linearGradient>
+ <linearGradient
+ y2="238.1875"
+ x2="324.875"
+ y1="231.5"
+ x1="304.8125"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3794"
+ xlink:href="#linearGradient3752-2"
+ inkscape:collect="always"
+ gradientTransform="translate(0,-1)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6"
+ id="radialGradient3766-2-5"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(2.0157047,0,0,1.5117786,-315.08929,-153.04762)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3752-2-3">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0"
+ id="stop3754-2-2" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="1"
+ id="stop3756-8-6" />
+ </linearGradient>
+ <linearGradient
+ y2="238.1875"
+ x2="324.875"
+ y1="231.5"
+ x1="304.8125"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2894"
+ xlink:href="#linearGradient3752-2-3"
+ inkscape:collect="always"
+ gradientTransform="translate(1,-38)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3743"
+ id="linearGradient3749"
+ x1="304"
+ y1="177"
+ x2="304"
+ y2="195"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6-4"
+ id="radialGradient3766-2-5-1"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(3.7131449,0,0,3.563472,-838.85008,-725.00376)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="177"
+ x1="304"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2910"
+ xlink:href="#linearGradient3743-4"
+ inkscape:collect="always"
+ gradientTransform="matrix(1.9473685,0,0,1.9444446,-291.47369,-291.58337)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100"
+ id="linearGradient3092"
+ x1="302"
+ y1="82.375"
+ x2="338"
+ y2="92.75"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100-5"
+ id="linearGradient3092-9"
+ x1="305.89941"
+ y1="83.784264"
+ x2="334.10059"
+ y2="91.340736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,66)" />
+ <linearGradient
+ id="linearGradient3100-5">
+ <stop
+ id="stop3102-6"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104-13" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106-5" />
+ <stop
+ id="stop3108-50"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110-4"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2-3" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="180.95102"
+ x1="304"
+ gradientTransform="matrix(1.8448754,0,0,1.8333335,-257.26455,-204.75003)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4350"
+ xlink:href="#linearGradient3743-4-4"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4-66-6">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6-61-7" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4-0-6" />
+ </linearGradient>
+ <radialGradient
+ r="8"
+ fy="222.91086"
+ fx="312.22864"
+ cy="222.91086"
+ cx="312.22864"
+ gradientTransform="matrix(2.8880002,0,0,2.9155676,-583.21633,-511.91208)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient4444"
+ xlink:href="#linearGradient3760-7-6-4-66-6"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2978"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient3756"
+ x1="318.5"
+ y1="147.03621"
+ x2="318.5"
+ y2="155.96379"
+ gradientUnits="userSpaceOnUse" />
+ <inkscape:perspective
+ id="perspective3111"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3912"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective4331"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective4799"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2988"
+ gradientUnits="userSpaceOnUse"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2990"
+ gradientUnits="userSpaceOnUse"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135" />
+ </defs>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="artwork"
+ style="display:inline"
+ transform="translate(-300,-54)">
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="disabled"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <rect
+ height="256"
+ id="rect6282"
+ inkscape:label="256x256"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="256"
+ x="16"
+ y="28" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:groupmode="layer"
+ inkscape:label="baseplate"
+ style="display:none">
+ <rect
+ height="48"
+ id="rect6284"
+ inkscape:label="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="48"
+ x="296"
+ y="50" />
+ <rect
+ height="32"
+ id="rect6592"
+ inkscape:label="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="32"
+ x="303"
+ y="126" />
+ <rect
+ height="22"
+ id="rect6749"
+ inkscape:label="22x22"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="22"
+ x="303"
+ y="177" />
+ <rect
+ height="16"
+ id="rect6833"
+ inkscape:label="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="16"
+ x="303"
+ y="219" />
+ <rect
+ height="24"
+ id="rect8104"
+ inkscape:label="24x24"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="24"
+ x="302"
+ y="176" />
+ <text
+ id="context"
+ inkscape:label="context"
+ style="font-size:18.30070686px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Bitstream Vera Sans"
+ x="20.970737"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan2716"
+ sodipodi:role="line"
+ x="20.970737"
+ y="21.513618">devices</tspan></text>
+ <text
+ id="icon-name"
+ inkscape:label="icon-name"
+ sodipodi:linespacing="125%"
+ style="font-size:18.30070686px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold"
+ x="141.97073"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan3023"
+ sodipodi:role="line"
+ x="141.97073"
+ y="21.513618">input-touchpad</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="small sizes"
+ style="display:inline">
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient2910);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6-4"
+ width="38"
+ height="35"
+ x="301.5"
+ y="55.5"
+ rx="4"
+ ry="4" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2-5-1);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-66"
+ width="35.999939"
+ height="33.000004"
+ x="302.50006"
+ y="56.499996"
+ rx="3.0000038"
+ ry="3.0000038" />
+ <rect
+ ry="2"
+ rx="2"
+ y="57.5"
+ x="303.5"
+ height="25"
+ width="34"
+ id="rect3694-0-0"
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g4205">
+ <path
+ id="rect3694-0-0-9"
+ d="m 303,84.5 0,2 c 0,1.367703 1.1323,2.5 2.5,2.5 l 14.5,0 0,-2 -14.5,0 c -0.0657,0 -0.1232,-0.02642 -0.1875,-0.03125 C 304.01204,86.871142 303,85.827989 303,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ <path
+ id="rect3694-0-0-9-8"
+ d="m 338,84.5 0,2 c 0,1.367703 -1.1323,2.5 -2.5,2.5 l -14.5,0 0,-2 14.5,0 c 0.0657,0 0.1232,-0.02642 0.1875,-0.03125 C 336.98796,86.871142 338,85.827989 338,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ </g>
+ <g
+ id="g2958"
+ style="fill-opacity:1;stroke:url(#linearGradient2978)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="rect2846-28-66-1"
+ d="m 302.5,80.5 0,6 c 0,1.662002 1.338,3 3,3 l 30,0 c 1.662,0 3,-1.337998 3,-3 l 0,-6 c 0,1.662002 -1.338,3 -3,3 l -30,0 c -1.662,0 -3,-1.337998 -3,-3 z"
+ style="color:#000000;fill:url(#linearGradient3092);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2988);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path3112"
+ d="m 320.5,83.5 0,6"
+ style="fill:none;stroke:url(#linearGradient2990);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 303.5,83.875 0,2.625 c 0,1.12494 0.87506,2 2,2 l 14,0 0,-4 -14,0 c -0.74347,0 -1.40165,-0.267405 -2,-0.625 z"
+ id="path3161-2"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 337.5,83.875 0,2.625 c 0,1.12494 -0.87506,2 -2,2 l -14,0 0,-4 14,0 c 0.74347,0 1.40165,-0.267405 2,-0.625 z"
+ id="path3161-2-0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 303,82.65625 0,1.3125 C 303.8401,84.608417 304.86264,85 306,85 l 14,0 0,-1 -14,0 c -1.20201,0 -2.2695,-0.516326 -3,-1.34375 z"
+ id="rect2846-28-66-0" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 338,82.65625 0,1.3125 C 337.1599,84.608417 336.13736,85 335,85 l -14,0 0,-1 14,0 c 1.20201,0 2.2695,-0.516326 3,-1.34375 z"
+ id="rect2846-28-66-0-6" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 309.49911,81.5 22.00265,0"
+ id="path4233" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 336.5,76.504425 0,-13.00885"
+ id="path4235" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237"
+ width="0.99953973"
+ height="0.99999803"
+ x="307.00046"
+ y="81" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6"
+ width="0.99953973"
+ height="0.99999803"
+ x="333.00046"
+ y="81" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="78" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-5"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="61" />
+ <g
+ id="layer4-3"
+ inkscape:label="Muted"
+ style="display:inline"
+ transform="translate(284.98438,57.984079)">
+ <g
+ id="g4694"
+ transform="translate(-2,0)">
+ <rect
+ ry="1.4868355"
+ rx="1.4868355"
+ y="16.498245"
+ x="31.498245"
+ height="12.00351"
+ width="12.00351"
+ id="rect2021"
+ style="fill:#ef2929;fill-opacity:1;stroke:#cc0000;stroke-width:0.9964897;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:1.20000057;display:inline" />
+ <rect
+ ry="0.4861359"
+ rx="0.4861359"
+ y="17.500002"
+ x="32.5"
+ height="9.9999962"
+ width="9.9999962"
+ id="rect3795"
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:0.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:1.20000057;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4682"
+ d="m 35,20 5,5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4684"
+ d="m 40,20 -5,5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="hires"
+ style="display:inline" />
+ <g
+ id="g256"
+ style="display:inline;enable-background:new"
+ transform="translate(20,30)" />
+ <g
+ id="g4021"
+ style="display:inline;enable-background:new"
+ transform="translate(-577.97771,370.7754)" />
+ <g
+ transform="translate(-457.73144,-1.374928)"
+ id="g10306"
+ style="enable-background:new">
+ <g
+ id="layer3"
+ inkscape:label="plate"
+ style="display:none">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6282-8"
+ width="256"
+ height="256"
+ x="20"
+ y="20"
+ inkscape:label="256x256" />
+ <rect
+ inkscape:label="48x48"
+ y="39.99633"
+ x="296.0625"
+ height="48"
+ width="48"
+ id="rect6284-8"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6592-5"
+ width="32"
+ height="32"
+ x="303"
+ y="115.99633"
+ inkscape:label="32x32" />
+ <rect
+ inkscape:label="22x22"
+ y="167.05884"
+ x="303"
+ height="22"
+ width="22"
+ id="rect6749-0"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6833-9"
+ width="16"
+ height="16"
+ x="303"
+ y="209"
+ inkscape:label="16x16" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5028"
+ width="24"
+ height="24"
+ x="301.95709"
+ y="165.95343"
+ inkscape:label="24x24" />
+ </g>
+ <g
+ id="layer1-6"
+ inkscape:label="artwork"
+ style="display:inline">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="256x256"
+ width="256"
+ height="256"
+ x="23.5"
+ y="171.59863"
+ inkscape:label="256x256" />
+ <rect
+ y="171.59863"
+ x="-38.5"
+ height="48"
+ width="48"
+ id="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="48x48" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="24x24"
+ width="24"
+ height="24"
+ x="-123.5"
+ y="171.59863"
+ inkscape:label="24x24" />
+ <rect
+ y="171.59863"
+ x="-155.5"
+ height="16"
+ width="16"
+ id="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="16x16" />
+ <rect
+ inkscape:label="32x32"
+ y="171.59863"
+ x="-87.5"
+ height="32"
+ width="32"
+ id="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g4445"
+ style="display:inline;enable-background:new"
+ transform="translate(-393,-62.246031)" />
+ <g
+ id="g5542"
+ style="display:inline;enable-background:new"
+ transform="translate(-364.39697,166.26869)" />
+ </g>
+</svg>
diff --git a/plugins/media-keys/touchpad-enabled-16.png b/plugins/media-keys/touchpad-enabled-16.png
new file mode 100644
index 0000000..58fc1d4
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled-16.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-enabled-22.png b/plugins/media-keys/touchpad-enabled-22.png
new file mode 100644
index 0000000..ae23118
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled-22.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-enabled-24.png b/plugins/media-keys/touchpad-enabled-24.png
new file mode 100644
index 0000000..b8617e9
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled-24.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-enabled-32.png b/plugins/media-keys/touchpad-enabled-32.png
new file mode 100644
index 0000000..7bbfa48
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled-32.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-enabled-48.png b/plugins/media-keys/touchpad-enabled-48.png
new file mode 100644
index 0000000..ebad680
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled-48.png
Binary files differ
diff --git a/plugins/media-keys/touchpad-enabled-template.svg b/plugins/media-keys/touchpad-enabled-template.svg
new file mode 100644
index 0000000..fe07b68
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled-template.svg
@@ -0,0 +1,936 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="300"
+ id="svg11300"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:version="0.47pre4 r22446"
+ sodipodi:docname="input-touchpad.svg"
+ sodipodi:version="0.32"
+ style="display:inline;enable-background:new"
+ version="1.0"
+ width="400">
+ <title
+ id="title3835">Touchpad</title>
+ <metadata
+ id="metadata154">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Touchpad</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Lapo Calamandrei</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:contributor>
+ <dc:source />
+ <cc:license
+ rdf:resource="" />
+ <dc:subject>
+ <rdf:Bag />
+ </dc:subject>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ fill="#f57900"
+ gridtolerance="12"
+ guidetolerance="13"
+ height="300px"
+ id="base"
+ inkscape:current-layer="layer2"
+ inkscape:cx="329.26576"
+ inkscape:cy="97.934968"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:showpageshadow="false"
+ inkscape:snap-bbox="true"
+ inkscape:snap-nodes="true"
+ inkscape:window-height="935"
+ inkscape:window-width="968"
+ inkscape:window-x="213"
+ inkscape:window-y="37"
+ inkscape:zoom="1"
+ objecttolerance="7"
+ pagecolor="#ffffff"
+ showgrid="false"
+ stroke="#ef2929"
+ width="400px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ showborder="true"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ enabled="true"
+ id="grid5883"
+ spacingx="0.5px"
+ spacingy="0.5px"
+ type="xygrid"
+ visible="true"
+ empspacing="2"
+ snapvisiblegridlinesonly="true" />
+ </sodipodi:namedview>
+ <defs
+ id="defs3">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2972">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="0"
+ id="stop2974" />
+ <stop
+ style="stop-color:#555753;stop-opacity:1"
+ offset="1"
+ id="stop2976" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3100">
+ <stop
+ id="stop3102"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106" />
+ <stop
+ id="stop3108"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7"
+ id="radialGradient3766-2"
+ cx="311"
+ cy="225.23932"
+ fx="311"
+ fy="225.23932"
+ r="8"
+ gradientTransform="matrix(1.4590081,0,0,1.0942561,-142.75153,-21.969492)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3752-2">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0"
+ id="stop3754-2" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="1"
+ id="stop3756-8" />
+ </linearGradient>
+ <linearGradient
+ y2="238.1875"
+ x2="324.875"
+ y1="231.5"
+ x1="304.8125"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3794"
+ xlink:href="#linearGradient3752-2"
+ inkscape:collect="always"
+ gradientTransform="translate(0,-1)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6"
+ id="radialGradient3766-2-5"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(2.0157047,0,0,1.5117786,-315.08929,-153.04762)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3752-2-3">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0"
+ id="stop3754-2-2" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="1"
+ id="stop3756-8-6" />
+ </linearGradient>
+ <linearGradient
+ y2="238.1875"
+ x2="324.875"
+ y1="231.5"
+ x1="304.8125"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2894"
+ xlink:href="#linearGradient3752-2-3"
+ inkscape:collect="always"
+ gradientTransform="translate(1,-38)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3743"
+ id="linearGradient3749"
+ x1="304"
+ y1="177"
+ x2="304"
+ y2="195"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6-4"
+ id="radialGradient3766-2-5-1"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(3.7131449,0,0,3.563472,-838.85008,-725.00376)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="177"
+ x1="304"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2910"
+ xlink:href="#linearGradient3743-4"
+ inkscape:collect="always"
+ gradientTransform="matrix(1.9473685,0,0,1.9444446,-291.47369,-291.58337)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100"
+ id="linearGradient3092"
+ x1="302"
+ y1="82.375"
+ x2="338"
+ y2="92.75"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100-5"
+ id="linearGradient3092-9"
+ x1="305.89941"
+ y1="83.784264"
+ x2="334.10059"
+ y2="91.340736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,66)" />
+ <linearGradient
+ id="linearGradient3100-5">
+ <stop
+ id="stop3102-6"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104-13" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106-5" />
+ <stop
+ id="stop3108-50"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110-4"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2-3" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="180.95102"
+ x1="304"
+ gradientTransform="matrix(1.8448754,0,0,1.8333335,-257.26455,-204.75003)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4350"
+ xlink:href="#linearGradient3743-4-4"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4-66-6">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6-61-7" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4-0-6" />
+ </linearGradient>
+ <radialGradient
+ r="8"
+ fy="222.91086"
+ fx="312.22864"
+ cy="222.91086"
+ cx="312.22864"
+ gradientTransform="matrix(2.8880002,0,0,2.9155676,-583.21633,-511.91208)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient4444"
+ xlink:href="#linearGradient3760-7-6-4-66-6"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2978"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient3756"
+ x1="318.5"
+ y1="147.03621"
+ x2="318.5"
+ y2="155.96379"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="artwork"
+ style="display:inline">
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="disabled"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <rect
+ height="256"
+ id="rect6282"
+ inkscape:label="256x256"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="256"
+ x="16"
+ y="28" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:groupmode="layer"
+ inkscape:label="baseplate"
+ style="display:none">
+ <rect
+ height="48"
+ id="rect6284"
+ inkscape:label="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="48"
+ x="296"
+ y="50" />
+ <rect
+ height="32"
+ id="rect6592"
+ inkscape:label="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="32"
+ x="303"
+ y="126" />
+ <rect
+ height="22"
+ id="rect6749"
+ inkscape:label="22x22"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="22"
+ x="303"
+ y="177" />
+ <rect
+ height="16"
+ id="rect6833"
+ inkscape:label="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="16"
+ x="303"
+ y="219" />
+ <rect
+ height="24"
+ id="rect8104"
+ inkscape:label="24x24"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="24"
+ x="302"
+ y="176" />
+ <text
+ id="context"
+ inkscape:label="context"
+ style="font-size:18.30070686px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Bitstream Vera Sans"
+ x="20.970737"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan2716"
+ sodipodi:role="line"
+ x="20.970737"
+ y="21.513618">devices</tspan></text>
+ <text
+ id="icon-name"
+ inkscape:label="icon-name"
+ sodipodi:linespacing="125%"
+ style="font-size:18.30070686px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold"
+ x="141.97073"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan3023"
+ sodipodi:role="line"
+ x="141.97073"
+ y="21.513618">input-touchpad</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="small sizes"
+ style="display:inline">
+ <path
+ style="color:#000000;fill:url(#linearGradient3794);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 303.5,227.5 0,4 c 0,1.108 0.892,2 2,2 l 11,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,1.108 -0.892,2 -2,2 l -11,0 c -1.108,0 -2,-0.892 -2,-2 z"
+ id="rect2846-2-3"
+ sodipodi:nodetypes="ccccccccc" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846"
+ width="15"
+ height="10"
+ x="303.5"
+ y="219.5"
+ rx="2"
+ ry="2" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3694"
+ width="13"
+ height="12"
+ x="304.5"
+ y="220.5"
+ rx="1"
+ ry="1" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 304,229.5 0,1 c 0,0.0541 0.002,0.1029 0,0.15625 0.45244,0.21377 0.96717,0.34375 1.5,0.34375 l 11,0 c 0.53283,0 1.04756,-0.12998 1.5,-0.34375 L 318,229.5 c -0.41577,0.30853 -0.93558,0.5 -1.5,0.5 l -11,0 c -0.56442,0 -1.08423,-0.19147 -1.5,-0.5 z"
+ id="rect2846-2"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728"
+ width="1"
+ height="3"
+ x="310"
+ y="230"
+ rx="0"
+ ry="0" />
+ <rect
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728-4"
+ width="1"
+ height="3"
+ x="311"
+ y="230"
+ rx="0"
+ ry="0" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient3749);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6"
+ width="19"
+ height="18"
+ x="304.5"
+ y="178.5"
+ rx="2"
+ ry="2" />
+ <path
+ style="color:#000000;fill:url(#linearGradient2894);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 304.5,190.5 0,4 c 0,1.108 0.892,2 2,2 l 15,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,1.108 -0.892,2 -2,2 l -15,0 c -1.108,0 -2,-0.892 -2,-2 z"
+ id="rect2846-2-3-0"
+ sodipodi:nodetypes="ccccccccc" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2-5);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28"
+ width="18.999943"
+ height="14.000024"
+ x="304.5"
+ y="178.5"
+ rx="2"
+ ry="2" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3694-0"
+ width="17.000095"
+ height="16.000011"
+ x="305.5"
+ y="179.5"
+ rx="1"
+ ry="1" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 305,192.5 0,1 c 0,0.0541 0.002,0.1029 0,0.15625 0.45244,0.21377 0.96717,0.34375 1.5,0.34375 l 15,0 c 0.53283,0 1.04756,-0.12998 1.5,-0.34375 L 323,192.5 c -0.41577,0.30853 -0.93558,0.5 -1.5,0.5 l -15,0 c -0.56442,0 -1.08423,-0.19147 -1.5,-0.5 z"
+ id="rect2846-2-1"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728-5"
+ width="1"
+ height="3"
+ x="313"
+ y="193"
+ rx="0"
+ ry="0" />
+ <rect
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3728-4-5"
+ width="1"
+ height="3"
+ x="314"
+ y="193"
+ rx="0"
+ ry="0" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient2910);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6-4"
+ width="38"
+ height="35"
+ x="301.5"
+ y="55.5"
+ rx="4"
+ ry="4" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2-5-1);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-66"
+ width="35.999939"
+ height="33.000004"
+ x="302.50006"
+ y="56.499996"
+ rx="3.0000038"
+ ry="3.0000038" />
+ <rect
+ ry="2"
+ rx="2"
+ y="57.5"
+ x="303.5"
+ height="25"
+ width="34"
+ id="rect3694-0-0"
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g4205">
+ <path
+ id="rect3694-0-0-9"
+ d="m 303,84.5 0,2 c 0,1.367703 1.1323,2.5 2.5,2.5 l 14.5,0 0,-2 -14.5,0 c -0.0657,0 -0.1232,-0.02642 -0.1875,-0.03125 C 304.01204,86.871142 303,85.827989 303,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ <path
+ id="rect3694-0-0-9-8"
+ d="m 338,84.5 0,2 c 0,1.367703 -1.1323,2.5 -2.5,2.5 l -14.5,0 0,-2 14.5,0 c 0.0657,0 0.1232,-0.02642 0.1875,-0.03125 C 336.98796,86.871142 338,85.827989 338,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ </g>
+ <g
+ id="g2958"
+ style="fill-opacity:1;stroke:url(#linearGradient2978)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="rect2846-28-66-1"
+ d="m 302.5,80.5 0,6 c 0,1.662002 1.338,3 3,3 l 30,0 c 1.662,0 3,-1.337998 3,-3 l 0,-6 c 0,1.662002 -1.338,3 -3,3 l -30,0 c -1.662,0 -3,-1.337998 -3,-3 z"
+ style="color:#000000;fill:url(#linearGradient3092);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2978);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path3112"
+ d="m 320.5,83.5 0,6"
+ style="fill:none;stroke:url(#linearGradient2978);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
+ </g>
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 303.5,83.875 0,2.625 c 0,1.12494 0.87506,2 2,2 l 14,0 0,-4 -14,0 c -0.74347,0 -1.40165,-0.267405 -2,-0.625 z"
+ id="path3161-2"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 337.5,83.875 0,2.625 c 0,1.12494 -0.87506,2 -2,2 l -14,0 0,-4 14,0 c 0.74347,0 1.40165,-0.267405 2,-0.625 z"
+ id="path3161-2-0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 303,82.65625 0,1.3125 C 303.8401,84.608417 304.86264,85 306,85 l 14,0 0,-1 -14,0 c -1.20201,0 -2.2695,-0.516326 -3,-1.34375 z"
+ id="rect2846-28-66-0" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 338,82.65625 0,1.3125 C 337.1599,84.608417 336.13736,85 335,85 l -14,0 0,-1 14,0 c 1.20201,0 2.2695,-0.516326 3,-1.34375 z"
+ id="rect2846-28-66-0-6" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 309.49911,81.5 22.00265,0"
+ id="path4233" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 336.5,76.504425 0,-13.00885"
+ id="path4235" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237"
+ width="0.99953973"
+ height="0.99999803"
+ x="307.00046"
+ y="81" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6"
+ width="0.99953973"
+ height="0.99999803"
+ x="333.00046"
+ y="81" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="78" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-5"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="61" />
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient4350);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6-4-0"
+ width="28"
+ height="27"
+ x="304.5"
+ y="128.5"
+ rx="3"
+ ry="3" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient4444);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-66-3-9"
+ width="28"
+ height="26"
+ x="304.5"
+ y="128.5"
+ rx="3"
+ ry="3" />
+ <rect
+ ry="2"
+ rx="2"
+ y="129.5"
+ x="305.5"
+ height="20"
+ width="26"
+ id="rect3694-0-0-2"
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g3752"
+ style="stroke:url(#linearGradient3756)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="rect2846-28-66-1-2"
+ d="m 304.5,147.5 0,5 c 0,1.662 1.338,3 3,3 l 22,0 c 1.662,0 3,-1.338 3,-3 l 0,-5 c 0,1.662 -1.338,3 -3,3 l -22,0 c -1.662,0 -3,-1.338 -3,-3 z"
+ style="color:#000000;fill:url(#linearGradient3092-9);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3756);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3112-3"
+ d="m 318.5,150.5 0,5"
+ style="fill:none;stroke:url(#linearGradient3756);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g4205-5"
+ transform="translate(-2,66)">
+ <path
+ id="rect3694-0-0-9-83"
+ d="m 307,84.5 0,2 c 0,1.367703 1.1323,2.5 2.5,2.5 l 10.5,0 0,-2 -10.5,0 c -0.0657,0 -0.1232,-0.02642 -0.1875,-0.03125 C 308.01204,86.871142 307,85.827989 307,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ sodipodi:nodetypes="ccccccsc" />
+ <path
+ id="rect3694-0-0-9-8-9"
+ d="m 334,84.5 0,2 c 0,1.367703 -1.1323,2.5 -2.5,2.5 l -10.5,0 0,-2 10.5,0 c 0.0657,0 0.1232,-0.02642 0.1875,-0.03125 C 332.98796,86.871142 334,85.827989 334,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ sodipodi:nodetypes="ccccccsc" />
+ </g>
+ <path
+ style="opacity:0.6;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 305.5,150.875 0,1.625 c 0,1.12494 0.87506,2 2,2 l 10,0 0,-3 -10,0 c -0.74347,0 -1.40165,-0.2674 -2,-0.625 z"
+ id="path3161-2-4"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.6;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 331.5,150.875 0,1.625 c 0,1.12494 -0.87506,2 -2,2 l -10,0 0,-3 10,0 c 0.74347,0 1.40165,-0.2674 2,-0.625 z"
+ id="path3161-2-0-7"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 305,149.65625 0,1.3125 c 0.8401,0.63967 1.86264,1.03125 3,1.03125 l 10,0 0,-1 -10,0 c -1.20201,0 -2.2695,-0.51633 -3,-1.34375 z"
+ id="rect2846-28-66-0-7"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 332,149.65625 0,1.3125 C 331.1599,151.60842 330.13736,152 329,152 l -10,0 0,-1 10,0 c 1.20201,0 2.2695,-0.51633 3,-1.34375 z"
+ id="rect2846-28-66-0-6-4"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 310.49911,148.5 15.00265,0"
+ id="path4233-4"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 330.5,143.50442 0,-9.00884"
+ id="path4235-3"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-5"
+ width="0.99953973"
+ height="0.99999803"
+ x="308.00046"
+ y="148" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-80"
+ width="0.99953973"
+ height="0.99999803"
+ x="327.00046"
+ y="148" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-3"
+ width="0.99953973"
+ height="0.99999803"
+ x="330.00046"
+ y="145" />
+ <rect
+ style="opacity:1;color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-5-0"
+ width="0.99953973"
+ height="0.99999803"
+ x="330.00046"
+ y="132" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="hires"
+ style="display:inline" />
+ <g
+ id="g256"
+ style="display:inline;enable-background:new"
+ transform="translate(20,30)" />
+ <g
+ id="g4021"
+ style="display:inline;enable-background:new"
+ transform="translate(-577.97771,370.7754)" />
+ <g
+ transform="translate(-457.73144,-1.374928)"
+ id="g10306"
+ style="enable-background:new">
+ <g
+ id="layer3"
+ inkscape:label="plate"
+ style="display:none">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6282-8"
+ width="256"
+ height="256"
+ x="20"
+ y="20"
+ inkscape:label="256x256" />
+ <rect
+ inkscape:label="48x48"
+ y="39.99633"
+ x="296.0625"
+ height="48"
+ width="48"
+ id="rect6284-8"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6592-5"
+ width="32"
+ height="32"
+ x="303"
+ y="115.99633"
+ inkscape:label="32x32" />
+ <rect
+ inkscape:label="22x22"
+ y="167.05884"
+ x="303"
+ height="22"
+ width="22"
+ id="rect6749-0"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6833-9"
+ width="16"
+ height="16"
+ x="303"
+ y="209"
+ inkscape:label="16x16" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5028"
+ width="24"
+ height="24"
+ x="301.95709"
+ y="165.95343"
+ inkscape:label="24x24" />
+ </g>
+ <g
+ id="layer1-6"
+ inkscape:label="artwork"
+ style="display:inline">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="256x256"
+ width="256"
+ height="256"
+ x="23.5"
+ y="171.59863"
+ inkscape:label="256x256" />
+ <rect
+ y="171.59863"
+ x="-38.5"
+ height="48"
+ width="48"
+ id="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="48x48" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="24x24"
+ width="24"
+ height="24"
+ x="-123.5"
+ y="171.59863"
+ inkscape:label="24x24" />
+ <rect
+ y="171.59863"
+ x="-155.5"
+ height="16"
+ width="16"
+ id="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="16x16" />
+ <rect
+ inkscape:label="32x32"
+ y="171.59863"
+ x="-87.5"
+ height="32"
+ width="32"
+ id="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g4445"
+ style="display:inline;enable-background:new"
+ transform="translate(-393,-62.246031)" />
+ <g
+ id="g5542"
+ style="display:inline;enable-background:new"
+ transform="translate(-364.39697,166.26869)" />
+ </g>
+</svg>
diff --git a/plugins/media-keys/touchpad-enabled.svg b/plugins/media-keys/touchpad-enabled.svg
new file mode 100644
index 0000000..98fa258
--- /dev/null
+++ b/plugins/media-keys/touchpad-enabled.svg
@@ -0,0 +1,581 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="38"
+ id="svg11300"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="touchpad-enabled.svg"
+ sodipodi:version="0.32"
+ style="display:inline;enable-background:new"
+ version="1.0"
+ width="41">
+ <title
+ id="title3835">Touchpad</title>
+ <metadata
+ id="metadata154">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Touchpad</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Lapo Calamandrei</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:contributor>
+ <dc:source />
+ <cc:license
+ rdf:resource="" />
+ <dc:subject>
+ <rdf:Bag />
+ </dc:subject>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ fill="#f57900"
+ gridtolerance="12"
+ guidetolerance="13"
+ height="300px"
+ id="base"
+ inkscape:current-layer="layer2"
+ inkscape:cx="29.26576"
+ inkscape:cy="-112.06503"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:showpageshadow="false"
+ inkscape:snap-bbox="true"
+ inkscape:snap-nodes="true"
+ inkscape:window-height="935"
+ inkscape:window-width="968"
+ inkscape:window-x="213"
+ inkscape:window-y="37"
+ inkscape:zoom="1"
+ objecttolerance="7"
+ pagecolor="#ffffff"
+ showgrid="false"
+ stroke="#ef2929"
+ width="400px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ showborder="true"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ enabled="true"
+ id="grid5883"
+ spacingx="0.5px"
+ spacingy="0.5px"
+ type="xygrid"
+ visible="true"
+ empspacing="2"
+ snapvisiblegridlinesonly="true" />
+ </sodipodi:namedview>
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 150 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="400 : 150 : 1"
+ inkscape:persp3d-origin="200 : 100 : 1"
+ id="perspective147" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2972">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1"
+ offset="0"
+ id="stop2974" />
+ <stop
+ style="stop-color:#555753;stop-opacity:1"
+ offset="1"
+ id="stop2976" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3100">
+ <stop
+ id="stop3102"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106" />
+ <stop
+ id="stop3108"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3760-7-6-4"
+ id="radialGradient3766-2-5-1"
+ cx="312.09396"
+ cy="224.27068"
+ fx="312.09396"
+ fy="224.27068"
+ r="8"
+ gradientTransform="matrix(3.7131449,0,0,3.563472,-838.85008,-725.00376)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3760-7-6-4">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0"
+ id="stop3762-0-6-6" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="1"
+ id="stop3764-5-1-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3743-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.2"
+ offset="0"
+ id="stop3745-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3747-2" />
+ </linearGradient>
+ <linearGradient
+ y2="195"
+ x2="304"
+ y1="177"
+ x1="304"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2910"
+ xlink:href="#linearGradient3743-4"
+ inkscape:collect="always"
+ gradientTransform="matrix(1.9473685,0,0,1.9444446,-291.47369,-291.58337)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3100"
+ id="linearGradient3092"
+ x1="302"
+ y1="82.375"
+ x2="338"
+ y2="92.75"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3100-5">
+ <stop
+ id="stop3102-6"
+ offset="0"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1"
+ offset="0.25"
+ id="stop3104-13" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1"
+ offset="0.5"
+ id="stop3106-5" />
+ <stop
+ id="stop3108-50"
+ offset="0.75"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop3110-4"
+ offset="1"
+ style="stop-color:#babdb6;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2978"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient3756"
+ x1="318.5"
+ y1="147.03621"
+ x2="318.5"
+ y2="155.96379"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2953"
+ gradientUnits="userSpaceOnUse"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2955"
+ gradientUnits="userSpaceOnUse"
+ x1="315.81155"
+ y1="82.20932"
+ x2="315.81155"
+ y2="89.25135" />
+ </defs>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="artwork"
+ style="display:inline"
+ transform="translate(-300,-54)">
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="disabled"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <rect
+ height="256"
+ id="rect6282"
+ inkscape:label="256x256"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="256"
+ x="16"
+ y="28" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:groupmode="layer"
+ inkscape:label="baseplate"
+ style="display:none">
+ <rect
+ height="48"
+ id="rect6284"
+ inkscape:label="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="48"
+ x="296"
+ y="50" />
+ <rect
+ height="32"
+ id="rect6592"
+ inkscape:label="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="32"
+ x="303"
+ y="126" />
+ <rect
+ height="22"
+ id="rect6749"
+ inkscape:label="22x22"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="22"
+ x="303"
+ y="177" />
+ <rect
+ height="16"
+ id="rect6833"
+ inkscape:label="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="16"
+ x="303"
+ y="219" />
+ <rect
+ height="24"
+ id="rect8104"
+ inkscape:label="24x24"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="24"
+ x="302"
+ y="176" />
+ <text
+ id="context"
+ inkscape:label="context"
+ style="font-size:18.30070686px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Bitstream Vera Sans"
+ x="20.970737"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan2716"
+ sodipodi:role="line"
+ x="20.970737"
+ y="21.513618">devices</tspan></text>
+ <text
+ id="icon-name"
+ inkscape:label="icon-name"
+ sodipodi:linespacing="125%"
+ style="font-size:18.30070686px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold"
+ x="141.97073"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan3023"
+ sodipodi:role="line"
+ x="141.97073"
+ y="21.513618">input-touchpad</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="small sizes"
+ style="display:inline">
+ <rect
+ style="opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient2910);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-6-4"
+ width="38"
+ height="35"
+ x="301.5"
+ y="55.5"
+ rx="4"
+ ry="4" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient3766-2-5-1);fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2846-28-66"
+ width="35.999939"
+ height="33.000004"
+ x="302.50006"
+ y="56.499996"
+ rx="3.0000038"
+ ry="3.0000038" />
+ <rect
+ ry="2"
+ rx="2"
+ y="57.5"
+ x="303.5"
+ height="25"
+ width="34"
+ id="rect3694-0-0"
+ style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g4205">
+ <path
+ id="rect3694-0-0-9"
+ d="m 303,84.5 0,2 c 0,1.367703 1.1323,2.5 2.5,2.5 l 14.5,0 0,-2 -14.5,0 c -0.0657,0 -0.1232,-0.02642 -0.1875,-0.03125 C 304.01204,86.871142 303,85.827989 303,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ <path
+ id="rect3694-0-0-9-8"
+ d="m 338,84.5 0,2 c 0,1.367703 -1.1323,2.5 -2.5,2.5 l -14.5,0 0,-2 14.5,0 c 0.0657,0 0.1232,-0.02642 0.1875,-0.03125 C 336.98796,86.871142 338,85.827989 338,84.5 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.1;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane" />
+ </g>
+ <g
+ id="g2958"
+ style="fill-opacity:1;stroke:url(#linearGradient2978)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="rect2846-28-66-1"
+ d="m 302.5,80.5 0,6 c 0,1.662002 1.338,3 3,3 l 30,0 c 1.662,0 3,-1.337998 3,-3 l 0,-6 c 0,1.662002 -1.338,3 -3,3 l -30,0 c -1.662,0 -3,-1.337998 -3,-3 z"
+ style="color:#000000;fill:url(#linearGradient3092);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2953);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path3112"
+ d="m 320.5,83.5 0,6"
+ style="fill:none;stroke:url(#linearGradient2955);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 303.5,83.875 0,2.625 c 0,1.12494 0.87506,2 2,2 l 14,0 0,-4 -14,0 c -0.74347,0 -1.40165,-0.267405 -2,-0.625 z"
+ id="path3161-2"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 337.5,83.875 0,2.625 c 0,1.12494 -0.87506,2 -2,2 l -14,0 0,-4 14,0 c 0.74347,0 1.40165,-0.267405 2,-0.625 z"
+ id="path3161-2-0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 303,82.65625 0,1.3125 C 303.8401,84.608417 304.86264,85 306,85 l 14,0 0,-1 -14,0 c -1.20201,0 -2.2695,-0.516326 -3,-1.34375 z"
+ id="rect2846-28-66-0" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.4;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Abandoned Bitplane;-inkscape-font-specification:Abandoned Bitplane"
+ d="m 338,82.65625 0,1.3125 C 337.1599,84.608417 336.13736,85 335,85 l -14,0 0,-1 14,0 c 1.20201,0 2.2695,-0.516326 3,-1.34375 z"
+ id="rect2846-28-66-0-6" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 309.49911,81.5 22.00265,0"
+ id="path4233" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 336.5,76.504425 0,-13.00885"
+ id="path4235" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237"
+ width="0.99953973"
+ height="0.99999803"
+ x="307.00046"
+ y="81" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6"
+ width="0.99953973"
+ height="0.99999803"
+ x="333.00046"
+ y="81" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="78" />
+ <rect
+ style="color:#000000;fill:#729fcf;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect4237-6-8-5"
+ width="0.99953973"
+ height="0.99999803"
+ x="336.00046"
+ y="61" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="hires"
+ style="display:inline" />
+ <g
+ id="g256"
+ style="display:inline;enable-background:new"
+ transform="translate(20,30)" />
+ <g
+ id="g4021"
+ style="display:inline;enable-background:new"
+ transform="translate(-577.97771,370.7754)" />
+ <g
+ transform="translate(-457.73144,-1.374928)"
+ id="g10306"
+ style="enable-background:new">
+ <g
+ id="layer3"
+ inkscape:label="plate"
+ style="display:none">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6282-8"
+ width="256"
+ height="256"
+ x="20"
+ y="20"
+ inkscape:label="256x256" />
+ <rect
+ inkscape:label="48x48"
+ y="39.99633"
+ x="296.0625"
+ height="48"
+ width="48"
+ id="rect6284-8"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6592-5"
+ width="32"
+ height="32"
+ x="303"
+ y="115.99633"
+ inkscape:label="32x32" />
+ <rect
+ inkscape:label="22x22"
+ y="167.05884"
+ x="303"
+ height="22"
+ width="22"
+ id="rect6749-0"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6833-9"
+ width="16"
+ height="16"
+ x="303"
+ y="209"
+ inkscape:label="16x16" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5028"
+ width="24"
+ height="24"
+ x="301.95709"
+ y="165.95343"
+ inkscape:label="24x24" />
+ </g>
+ <g
+ id="layer1-6"
+ inkscape:label="artwork"
+ style="display:inline">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="256x256"
+ width="256"
+ height="256"
+ x="23.5"
+ y="171.59863"
+ inkscape:label="256x256" />
+ <rect
+ y="171.59863"
+ x="-38.5"
+ height="48"
+ width="48"
+ id="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="48x48" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ id="24x24"
+ width="24"
+ height="24"
+ x="-123.5"
+ y="171.59863"
+ inkscape:label="24x24" />
+ <rect
+ y="171.59863"
+ x="-155.5"
+ height="16"
+ width="16"
+ id="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate"
+ inkscape:label="16x16" />
+ <rect
+ inkscape:label="32x32"
+ y="171.59863"
+ x="-87.5"
+ height="32"
+ width="32"
+ id="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:none;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g4445"
+ style="display:inline;enable-background:new"
+ transform="translate(-393,-62.246031)" />
+ <g
+ id="g5542"
+ style="display:inline;enable-background:new"
+ transform="translate(-364.39697,166.26869)" />
+ </g>
+</svg>
diff --git a/plugins/mouse/Makefile.am b/plugins/mouse/Makefile.am
new file mode 100644
index 0000000..f99aefc
--- /dev/null
+++ b/plugins/mouse/Makefile.am
@@ -0,0 +1,52 @@
+plugin_LTLIBRARIES = libmouse.la
+
+libmouse_la_SOURCES = \
+ gsd-mouse-plugin.h \
+ gsd-mouse-plugin.c \
+ gsd-mouse-manager.h \
+ gsd-mouse-manager.c
+
+libmouse_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ $(AM_CPPFLAGS)
+
+libmouse_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libmouse_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libmouse_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(X11_LIBS) \
+ $(XINPUT_LIBS)
+
+plugin_in_files = mouse.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+libexec_PROGRAMS = gsd-locate-pointer
+
+gsd_locate_pointer_SOURCES = \
+ gsd-locate-pointer.h \
+ gsd-locate-pointer.c \
+ gsd-timeline.h \
+ gsd-timeline.c
+
+gsd_locate_pointer_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+gsd_locate_pointer_LDADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(X11_LIBS) \
+ -lm
+
+EXTRA_DIST = $(plugin_in_files)
+CLEANFILES = $(plugin_DATA)
+DISTCLEANFILES = $(plugin_DATA)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/mouse/Makefile.in b/plugins/mouse/Makefile.in
new file mode 100644
index 0000000..c4bc74c
--- /dev/null
+++ b/plugins/mouse/Makefile.in
@@ -0,0 +1,768 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+libexec_PROGRAMS = gsd-locate-pointer$(EXEEXT)
+subdir = plugins/mouse
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" \
+ "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libmouse_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libmouse_la_OBJECTS = libmouse_la-gsd-mouse-plugin.lo \
+ libmouse_la-gsd-mouse-manager.lo
+libmouse_la_OBJECTS = $(am_libmouse_la_OBJECTS)
+libmouse_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmouse_la_CFLAGS) \
+ $(CFLAGS) $(libmouse_la_LDFLAGS) $(LDFLAGS) -o $@
+PROGRAMS = $(libexec_PROGRAMS)
+am_gsd_locate_pointer_OBJECTS = \
+ gsd_locate_pointer-gsd-locate-pointer.$(OBJEXT) \
+ gsd_locate_pointer-gsd-timeline.$(OBJEXT)
+gsd_locate_pointer_OBJECTS = $(am_gsd_locate_pointer_OBJECTS)
+gsd_locate_pointer_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+gsd_locate_pointer_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(gsd_locate_pointer_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libmouse_la_SOURCES) $(gsd_locate_pointer_SOURCES)
+DIST_SOURCES = $(libmouse_la_SOURCES) $(gsd_locate_pointer_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libmouse.la
+libmouse_la_SOURCES = \
+ gsd-mouse-plugin.h \
+ gsd-mouse-plugin.c \
+ gsd-mouse-manager.h \
+ gsd-mouse-manager.c
+
+libmouse_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ $(AM_CPPFLAGS)
+
+libmouse_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libmouse_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libmouse_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(X11_LIBS) \
+ $(XINPUT_LIBS)
+
+plugin_in_files = mouse.mate-settings-plugin.in
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+gsd_locate_pointer_SOURCES = \
+ gsd-locate-pointer.h \
+ gsd-locate-pointer.c \
+ gsd-timeline.h \
+ gsd-timeline.c
+
+gsd_locate_pointer_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+gsd_locate_pointer_LDADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(X11_LIBS) \
+ -lm
+
+EXTRA_DIST = $(plugin_in_files)
+CLEANFILES = $(plugin_DATA)
+DISTCLEANFILES = $(plugin_DATA)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/mouse/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mouse/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libmouse.la: $(libmouse_la_OBJECTS) $(libmouse_la_DEPENDENCIES)
+ $(libmouse_la_LINK) -rpath $(plugindir) $(libmouse_la_OBJECTS) $(libmouse_la_LIBADD) $(LIBS)
+install-libexecPROGRAMS: $(libexec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)"
+ @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-libexecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files
+
+clean-libexecPROGRAMS:
+ @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+gsd-locate-pointer$(EXEEXT): $(gsd_locate_pointer_OBJECTS) $(gsd_locate_pointer_DEPENDENCIES)
+ @rm -f gsd-locate-pointer$(EXEEXT)
+ $(gsd_locate_pointer_LINK) $(gsd_locate_pointer_OBJECTS) $(gsd_locate_pointer_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsd_locate_pointer-gsd-timeline.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmouse_la-gsd-mouse-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmouse_la-gsd-mouse-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libmouse_la-gsd-mouse-plugin.lo: gsd-mouse-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmouse_la_CPPFLAGS) $(CPPFLAGS) $(libmouse_la_CFLAGS) $(CFLAGS) -MT libmouse_la-gsd-mouse-plugin.lo -MD -MP -MF $(DEPDIR)/libmouse_la-gsd-mouse-plugin.Tpo -c -o libmouse_la-gsd-mouse-plugin.lo `test -f 'gsd-mouse-plugin.c' || echo '$(srcdir)/'`gsd-mouse-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmouse_la-gsd-mouse-plugin.Tpo $(DEPDIR)/libmouse_la-gsd-mouse-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-mouse-plugin.c' object='libmouse_la-gsd-mouse-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmouse_la_CPPFLAGS) $(CPPFLAGS) $(libmouse_la_CFLAGS) $(CFLAGS) -c -o libmouse_la-gsd-mouse-plugin.lo `test -f 'gsd-mouse-plugin.c' || echo '$(srcdir)/'`gsd-mouse-plugin.c
+
+libmouse_la-gsd-mouse-manager.lo: gsd-mouse-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmouse_la_CPPFLAGS) $(CPPFLAGS) $(libmouse_la_CFLAGS) $(CFLAGS) -MT libmouse_la-gsd-mouse-manager.lo -MD -MP -MF $(DEPDIR)/libmouse_la-gsd-mouse-manager.Tpo -c -o libmouse_la-gsd-mouse-manager.lo `test -f 'gsd-mouse-manager.c' || echo '$(srcdir)/'`gsd-mouse-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmouse_la-gsd-mouse-manager.Tpo $(DEPDIR)/libmouse_la-gsd-mouse-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-mouse-manager.c' object='libmouse_la-gsd-mouse-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmouse_la_CPPFLAGS) $(CPPFLAGS) $(libmouse_la_CFLAGS) $(CFLAGS) -c -o libmouse_la-gsd-mouse-manager.lo `test -f 'gsd-mouse-manager.c' || echo '$(srcdir)/'`gsd-mouse-manager.c
+
+gsd_locate_pointer-gsd-locate-pointer.o: gsd-locate-pointer.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -MT gsd_locate_pointer-gsd-locate-pointer.o -MD -MP -MF $(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Tpo -c -o gsd_locate_pointer-gsd-locate-pointer.o `test -f 'gsd-locate-pointer.c' || echo '$(srcdir)/'`gsd-locate-pointer.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Tpo $(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-locate-pointer.c' object='gsd_locate_pointer-gsd-locate-pointer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -c -o gsd_locate_pointer-gsd-locate-pointer.o `test -f 'gsd-locate-pointer.c' || echo '$(srcdir)/'`gsd-locate-pointer.c
+
+gsd_locate_pointer-gsd-locate-pointer.obj: gsd-locate-pointer.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -MT gsd_locate_pointer-gsd-locate-pointer.obj -MD -MP -MF $(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Tpo -c -o gsd_locate_pointer-gsd-locate-pointer.obj `if test -f 'gsd-locate-pointer.c'; then $(CYGPATH_W) 'gsd-locate-pointer.c'; else $(CYGPATH_W) '$(srcdir)/gsd-locate-pointer.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Tpo $(DEPDIR)/gsd_locate_pointer-gsd-locate-pointer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-locate-pointer.c' object='gsd_locate_pointer-gsd-locate-pointer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -c -o gsd_locate_pointer-gsd-locate-pointer.obj `if test -f 'gsd-locate-pointer.c'; then $(CYGPATH_W) 'gsd-locate-pointer.c'; else $(CYGPATH_W) '$(srcdir)/gsd-locate-pointer.c'; fi`
+
+gsd_locate_pointer-gsd-timeline.o: gsd-timeline.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -MT gsd_locate_pointer-gsd-timeline.o -MD -MP -MF $(DEPDIR)/gsd_locate_pointer-gsd-timeline.Tpo -c -o gsd_locate_pointer-gsd-timeline.o `test -f 'gsd-timeline.c' || echo '$(srcdir)/'`gsd-timeline.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gsd_locate_pointer-gsd-timeline.Tpo $(DEPDIR)/gsd_locate_pointer-gsd-timeline.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-timeline.c' object='gsd_locate_pointer-gsd-timeline.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -c -o gsd_locate_pointer-gsd-timeline.o `test -f 'gsd-timeline.c' || echo '$(srcdir)/'`gsd-timeline.c
+
+gsd_locate_pointer-gsd-timeline.obj: gsd-timeline.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -MT gsd_locate_pointer-gsd-timeline.obj -MD -MP -MF $(DEPDIR)/gsd_locate_pointer-gsd-timeline.Tpo -c -o gsd_locate_pointer-gsd-timeline.obj `if test -f 'gsd-timeline.c'; then $(CYGPATH_W) 'gsd-timeline.c'; else $(CYGPATH_W) '$(srcdir)/gsd-timeline.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gsd_locate_pointer-gsd-timeline.Tpo $(DEPDIR)/gsd_locate_pointer-gsd-timeline.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-timeline.c' object='gsd_locate_pointer-gsd-timeline.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsd_locate_pointer_CFLAGS) $(CFLAGS) -c -o gsd_locate_pointer-gsd-timeline.obj `if test -f 'gsd-timeline.c'; then $(CYGPATH_W) 'gsd-timeline.c'; else $(CYGPATH_W) '$(srcdir)/gsd-timeline.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libexecPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libexecPROGRAMS uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libexecPROGRAMS clean-libtool clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libexecPROGRAMS install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-libexecPROGRAMS uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/mouse/gsd-locate-pointer.c b/plugins/mouse/gsd-locate-pointer.c
new file mode 100644
index 0000000..acb2445
--- /dev/null
+++ b/plugins/mouse/gsd-locate-pointer.c
@@ -0,0 +1,504 @@
+/* gsd-locate-pointer.c
+ *
+ * Copyright (C) 2008 Carlos Garnacho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include "gsd-timeline.h"
+#include "gsd-locate-pointer.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <X11/keysym.h>
+
+#define ANIMATION_LENGTH 750
+#define WINDOW_SIZE 101
+#define N_CIRCLES 4
+
+/* All circles are supposed to be moving when progress
+ * reaches 0.5, and each of them are supposed to long
+ * for half of the progress, hence the need of 0.5 to
+ * get the circles interval, and the multiplication
+ * by 2 to know a circle progress */
+#define CIRCLES_PROGRESS_INTERVAL (0.5 / N_CIRCLES)
+#define CIRCLE_PROGRESS(p) (MIN (1., ((gdouble) (p) * 2.)))
+
+typedef struct GsdLocatePointerData GsdLocatePointerData;
+
+struct GsdLocatePointerData
+{
+ GsdTimeline *timeline;
+ GtkWidget *widget;
+ GdkWindow *window;
+
+ gdouble progress;
+};
+
+static GsdLocatePointerData *data = NULL;
+
+static void
+locate_pointer_paint (GsdLocatePointerData *data,
+ cairo_t *cr,
+ gboolean composite)
+{
+ GdkColor color;
+ gdouble progress, circle_progress;
+ gint width, height, i;
+ GtkStyle *style;
+
+ progress = data->progress;
+
+ #if GTK_CHECK_VERSION(3, 0, 0)
+ width = gdk_window_get_width(GDK_WINDOW(data->window));
+ height = gdk_window_get_height(GDK_WINDOW(data->window));
+ #else
+ gdk_drawable_get_size(data->window, &width, &height);
+ #endif
+
+ style = gtk_widget_get_style (data->widget);
+ color = style->bg[GTK_STATE_SELECTED];
+
+ cairo_set_source_rgba (cr, 1., 1., 1., 0.);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+ for (i = 0; i <= N_CIRCLES; i++)
+ {
+ if (progress < 0.)
+ break;
+
+ circle_progress = MIN (1., (progress * 2));
+ progress -= CIRCLES_PROGRESS_INTERVAL;
+
+ if (circle_progress >= 1.)
+ continue;
+
+ if (composite)
+ {
+ cairo_set_source_rgba (cr,
+ color.red / 65535.,
+ color.green / 65535.,
+ color.blue / 65535.,
+ 1 - circle_progress);
+ cairo_arc (cr,
+ width / 2,
+ height / 2,
+ circle_progress * width / 2,
+ 0, 2 * G_PI);
+
+ cairo_fill (cr);
+ cairo_stroke (cr);
+ }
+ else
+ {
+ cairo_set_source_rgb (cr, 0., 0., 0.);
+ cairo_set_line_width (cr, 3.);
+ cairo_arc (cr,
+ width / 2,
+ height / 2,
+ circle_progress * width / 2,
+ 0, 2 * G_PI);
+ cairo_stroke (cr);
+
+ cairo_set_source_rgb (cr, 1., 1., 1.);
+ cairo_set_line_width (cr, 1.);
+ cairo_arc (cr,
+ width / 2,
+ height / 2,
+ circle_progress * width / 2,
+ 0, 2 * G_PI);
+ cairo_stroke (cr);
+ }
+ }
+}
+
+static gboolean
+locate_pointer_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data)
+{
+ GsdLocatePointerData *data = (GsdLocatePointerData *) user_data;
+ cairo_t *cr;
+
+ if (event->window != data->window)
+ return FALSE;
+
+ cr = gdk_cairo_create (data->window);
+ locate_pointer_paint (data, cr, gtk_widget_is_composited (data->widget));
+ cairo_destroy (cr);
+
+ return TRUE;
+}
+
+static void
+update_shape (GsdLocatePointerData *data)
+{
+ cairo_t *cr;
+ GdkBitmap *mask;
+
+ mask = gdk_pixmap_new (data->window, WINDOW_SIZE, WINDOW_SIZE, 1);
+ cr = gdk_cairo_create (mask);
+ locate_pointer_paint (data, cr, FALSE);
+ gdk_window_shape_combine_mask (data->window, mask, 0, 0);
+ g_object_unref (mask);
+ cairo_destroy (cr);
+}
+
+static void
+timeline_frame_cb (GsdTimeline *timeline,
+ gdouble progress,
+ gpointer user_data)
+{
+ GsdLocatePointerData *data = (GsdLocatePointerData *) user_data;
+ GdkScreen *screen;
+ gint cursor_x, cursor_y;
+
+ if (gtk_widget_is_composited (data->widget))
+ {
+ gdk_window_invalidate_rect (data->window, NULL, FALSE);
+ data->progress = progress;
+ }
+ else if (progress >= data->progress + CIRCLES_PROGRESS_INTERVAL)
+ {
+ /* only invalidate window each circle interval */
+ update_shape (data);
+ gdk_window_invalidate_rect (data->window, NULL, FALSE);
+ data->progress += CIRCLES_PROGRESS_INTERVAL;
+ }
+
+ screen = gdk_drawable_get_screen (data->window);
+ gdk_window_get_pointer (gdk_screen_get_root_window (screen),
+ &cursor_x, &cursor_y, NULL);
+ gdk_window_move (data->window,
+ cursor_x - WINDOW_SIZE / 2,
+ cursor_y - WINDOW_SIZE / 2);
+}
+
+static void
+set_transparent_shape (GdkWindow *window)
+{
+ GdkBitmap *mask;
+ cairo_t *cr;
+
+ mask = gdk_pixmap_new (data->window, WINDOW_SIZE, WINDOW_SIZE, 1);
+ cr = gdk_cairo_create (mask);
+
+ cairo_set_source_rgba (cr, 1., 1., 1., 0.);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+ gdk_window_shape_combine_mask (data->window, mask, 0, 0);
+ g_object_unref (mask);
+ cairo_destroy (cr);
+}
+
+static void
+unset_transparent_shape (GdkWindow *window)
+{
+ gdk_window_shape_combine_mask (data->window, NULL, 0, 0);
+}
+
+static void
+composited_changed (GtkWidget *widget,
+ GsdLocatePointerData *data)
+{
+ if (!gtk_widget_is_composited (widget))
+ set_transparent_shape (data->window);
+ else
+ unset_transparent_shape (data->window);
+}
+
+static void
+timeline_finished_cb (GsdTimeline *timeline,
+ gpointer user_data)
+{
+ GsdLocatePointerData *data = (GsdLocatePointerData *) user_data;
+
+ /* set transparent shape and hide window */
+ if (!gtk_widget_is_composited (data->widget))
+ set_transparent_shape (data->window);
+
+ gdk_window_hide (data->window);
+}
+
+static void
+create_window (GsdLocatePointerData *data,
+ GdkScreen *screen)
+{
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkWindowAttr attributes;
+
+ colormap = gdk_screen_get_rgba_colormap (screen);
+ visual = gdk_screen_get_rgba_visual (screen);
+
+ if (!colormap)
+ {
+ colormap = gdk_screen_get_rgb_colormap (screen);
+ visual = gdk_screen_get_rgb_visual (screen);
+ }
+
+ attributes.window_type = GDK_WINDOW_TEMP;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = visual;
+ attributes.colormap = colormap;
+ attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK;
+ attributes.width = 1;
+ attributes.height = 1;
+
+ data->window = gdk_window_new (gdk_screen_get_root_window (screen),
+ &attributes,
+ GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
+
+ gdk_window_set_user_data (data->window, data->widget);
+}
+
+static GsdLocatePointerData *
+gsd_locate_pointer_data_new (GdkScreen *screen)
+{
+ GsdLocatePointerData *data;
+
+ data = g_new0 (GsdLocatePointerData, 1);
+
+ /* this widget will never be shown, it's
+ * mainly used to get signals/events from
+ */
+ data->widget = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_widget_realize (data->widget);
+
+ g_signal_connect (G_OBJECT (data->widget), "expose_event",
+ G_CALLBACK (locate_pointer_expose),
+ data);
+
+ data->timeline = gsd_timeline_new (ANIMATION_LENGTH);
+ g_signal_connect (data->timeline, "frame",
+ G_CALLBACK (timeline_frame_cb), data);
+ g_signal_connect (data->timeline, "finished",
+ G_CALLBACK (timeline_finished_cb), data);
+
+ create_window (data, screen);
+
+ return data;
+}
+
+static void
+move_locate_pointer_window (GsdLocatePointerData *data,
+ GdkScreen *screen)
+{
+ gint cursor_x, cursor_y;
+ GdkBitmap *mask;
+ GdkColor col;
+ GdkGC *gc;
+
+ gdk_window_get_pointer (gdk_screen_get_root_window (screen), &cursor_x, &cursor_y, NULL);
+
+ gdk_window_move_resize (data->window,
+ cursor_x - WINDOW_SIZE / 2,
+ cursor_y - WINDOW_SIZE / 2,
+ WINDOW_SIZE, WINDOW_SIZE);
+
+ col.pixel = 0;
+ mask = gdk_pixmap_new (data->window, WINDOW_SIZE, WINDOW_SIZE, 1);
+
+ gc = gdk_gc_new (mask);
+ gdk_gc_set_foreground (gc, &col);
+ gdk_draw_rectangle (mask, gc, TRUE, 0, 0, WINDOW_SIZE, WINDOW_SIZE);
+
+ /* allow events to happen through the window */
+ gdk_window_input_shape_combine_mask (data->window, mask, 0, 0);
+
+ g_object_unref (mask);
+ g_object_unref (gc);
+}
+
+void
+gsd_locate_pointer (GdkScreen *screen)
+{
+ if (!data)
+ data = gsd_locate_pointer_data_new (screen);
+
+ gsd_timeline_pause (data->timeline);
+ gsd_timeline_rewind (data->timeline);
+
+ /* Create again the window if it is not for the current screen */
+ if (gdk_screen_get_number (screen) != gdk_screen_get_number (gdk_drawable_get_screen (data->window)))
+ {
+ gdk_window_set_user_data (data->window, NULL);
+ gdk_window_destroy (data->window);
+
+ create_window (data, screen);
+ }
+
+ data->progress = 0.;
+
+ g_signal_connect (data->widget, "composited-changed",
+ G_CALLBACK (composited_changed), data);
+
+ move_locate_pointer_window (data, screen);
+ composited_changed (data->widget, data);
+ gdk_window_show (data->window);
+
+ gsd_timeline_start (data->timeline);
+}
+
+
+#define KEYBOARD_GROUP_SHIFT 13
+#define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
+
+/* Owen magic */
+static GdkFilterReturn
+filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xev = (XEvent *) xevent;
+ guint keyval;
+ gint group;
+
+ GdkScreen *screen = (GdkScreen *)data;
+
+ if (xev->type == KeyPress || xev->type == KeyRelease)
+ {
+ /* get the keysym */
+ group = (xev->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
+ gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
+ xev->xkey.keycode,
+ xev->xkey.state,
+ group,
+ &keyval,
+ NULL, NULL, NULL);
+ if (keyval == GDK_Control_L || keyval == GDK_Control_R)
+ {
+ if (xev->type == KeyPress)
+ {
+ XAllowEvents (xev->xkey.display,
+ SyncKeyboard,
+ xev->xkey.time);
+ }
+ else
+ {
+ XAllowEvents (xev->xkey.display,
+ AsyncKeyboard,
+ xev->xkey.time);
+ gsd_locate_pointer (screen);
+ }
+ }
+ else
+ {
+ XAllowEvents (xev->xkey.display,
+ ReplayKeyboard,
+ xev->xkey.time);
+ XUngrabKeyboard (gdk_x11_get_default_xdisplay (),
+ xev->xkey.time);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+set_locate_pointer (void)
+{
+ GdkKeymapKey *keys;
+ GdkDisplay *display;
+ int n_screens;
+ int n_keys;
+ gboolean has_entries;
+ static const guint keyvals[] = { GDK_Control_L, GDK_Control_R };
+ unsigned j;
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+
+ for (j = 0 ; j < G_N_ELEMENTS (keyvals) ; j++)
+ {
+ has_entries = gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
+ keyvals[j],
+ &keys,
+ &n_keys);
+ if (has_entries)
+ {
+ gint i, j;
+ for (i = 0; i < n_keys; i++)
+ {
+ for (j=0; j< n_screens; j++)
+ {
+ GdkScreen *screen;
+ Window xroot;
+
+ screen = gdk_display_get_screen (display, j);
+ xroot = gdk_x11_drawable_get_xid (gdk_screen_get_root_window (screen));
+
+ XGrabKey (GDK_DISPLAY_XDISPLAY (display),
+ keys[i].keycode,
+ 0,
+ xroot,
+ False,
+ GrabModeAsync,
+ GrabModeSync);
+ XGrabKey (GDK_DISPLAY_XDISPLAY (display),
+ keys[i].keycode,
+ LockMask,
+ xroot,
+ False,
+ GrabModeAsync,
+ GrabModeSync);
+ XGrabKey (GDK_DISPLAY_XDISPLAY (display),
+ keys[i].keycode,
+ Mod2Mask,
+ xroot,
+ False,
+ GrabModeAsync,
+ GrabModeSync);
+ XGrabKey (GDK_DISPLAY_XDISPLAY (display),
+ keys[i].keycode,
+ Mod4Mask,
+ xroot,
+ False,
+ GrabModeAsync,
+ GrabModeSync);
+ }
+ }
+
+ g_free (keys);
+
+ for (i = 0; i < n_screens; i++)
+ {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (display, i);
+ gdk_window_add_filter (gdk_screen_get_root_window (screen),
+ filter,
+ screen);
+ }
+ }
+ }
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ gtk_init (&argc, &argv);
+
+ set_locate_pointer ();
+
+ gtk_main ();
+
+ return 0;
+}
+
diff --git a/plugins/mouse/gsd-locate-pointer.h b/plugins/mouse/gsd-locate-pointer.h
new file mode 100644
index 0000000..3b261a5
--- /dev/null
+++ b/plugins/mouse/gsd-locate-pointer.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright � 2001 Jonathan Blandford <[email protected]>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * Authors: Jonathan Blandford
+ */
+
+#ifndef LOCATE_POINTER_H
+#define LOCATE_POINTER_H
+
+#include <gdk/gdk.h>
+
+void gsd_locate_pointer (GdkScreen *screen);
+
+#endif
diff --git a/plugins/mouse/gsd-mouse-manager.c b/plugins/mouse/gsd-mouse-manager.c
new file mode 100644
index 0000000..124653a
--- /dev/null
+++ b/plugins/mouse/gsd-mouse-manager.c
@@ -0,0 +1,1124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XIproto.h>
+#endif
+#include <mateconf/mateconf.h>
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-mouse-manager.h"
+
+#define GSD_MOUSE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerPrivate))
+
+#define MATECONF_MOUSE_DIR "/desktop/mate/peripherals/mouse"
+#define MATECONF_MOUSE_A11Y_DIR "/desktop/mate/accessibility/mouse"
+#define MATECONF_TOUCHPAD_DIR "/desktop/mate/peripherals/touchpad"
+
+#define KEY_LEFT_HANDED MATECONF_MOUSE_DIR "/left_handed"
+#define KEY_MOTION_ACCELERATION MATECONF_MOUSE_DIR "/motion_acceleration"
+#define KEY_MOTION_THRESHOLD MATECONF_MOUSE_DIR "/motion_threshold"
+#define KEY_LOCATE_POINTER MATECONF_MOUSE_DIR "/locate_pointer"
+#define KEY_DWELL_ENABLE MATECONF_MOUSE_A11Y_DIR "/dwell_enable"
+#define KEY_DELAY_ENABLE MATECONF_MOUSE_A11Y_DIR "/delay_enable"
+#define KEY_TOUCHPAD_DISABLE_W_TYPING MATECONF_TOUCHPAD_DIR "/disable_while_typing"
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#define KEY_TAP_TO_CLICK MATECONF_TOUCHPAD_DIR "/tap_to_click"
+#define KEY_SCROLL_METHOD MATECONF_TOUCHPAD_DIR "/scroll_method"
+#define KEY_PAD_HORIZ_SCROLL MATECONF_TOUCHPAD_DIR "/horiz_scroll_enabled"
+#define KEY_TOUCHPAD_ENABLED MATECONF_TOUCHPAD_DIR "/touchpad_enabled"
+#endif
+
+struct GsdMouseManagerPrivate
+{
+ guint notify;
+ guint notify_a11y;
+ guint notify_touchpad;
+
+ gboolean mousetweaks_daemon_running;
+ gboolean syndaemon_spawned;
+ GPid syndaemon_pid;
+ gboolean locate_pointer_spawned;
+ GPid locate_pointer_pid;
+};
+
+static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass);
+static void gsd_mouse_manager_init (GsdMouseManager *mouse_manager);
+static void gsd_mouse_manager_finalize (GObject *object);
+static void set_mouse_settings (GsdMouseManager *manager);
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+static int set_tap_to_click (gboolean state, gboolean left_handed);
+static XDevice* device_is_touchpad (XDeviceInfo deviceinfo);
+#endif
+
+G_DEFINE_TYPE (GsdMouseManager, gsd_mouse_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static void
+gsd_mouse_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdMouseManager *self;
+
+ self = GSD_MOUSE_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_mouse_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdMouseManager *self;
+
+ self = GSD_MOUSE_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_mouse_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdMouseManager *mouse_manager;
+ GsdMouseManagerClass *klass;
+
+ klass = GSD_MOUSE_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_MOUSE_MANAGER));
+
+ mouse_manager = GSD_MOUSE_MANAGER (G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (mouse_manager);
+}
+
+static void
+gsd_mouse_manager_dispose (GObject *object)
+{
+ GsdMouseManager *mouse_manager;
+
+ mouse_manager = GSD_MOUSE_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_mouse_manager_class_init (GsdMouseManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_mouse_manager_get_property;
+ object_class->set_property = gsd_mouse_manager_set_property;
+ object_class->constructor = gsd_mouse_manager_constructor;
+ object_class->dispose = gsd_mouse_manager_dispose;
+ object_class->finalize = gsd_mouse_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdMouseManagerPrivate));
+}
+
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+static gboolean
+supports_xinput_devices (void)
+{
+ gint op_code, event, error;
+
+ return XQueryExtension (GDK_DISPLAY (),
+ "XInputExtension",
+ &op_code,
+ &event,
+ &error);
+}
+#endif
+
+static void
+configure_button_layout (guchar *buttons,
+ gint n_buttons,
+ gboolean left_handed)
+{
+ const gint left_button = 1;
+ gint right_button;
+ gint i;
+
+ /* if the button is higher than 2 (3rd button) then it's
+ * probably one direction of a scroll wheel or something else
+ * uninteresting
+ */
+ right_button = MIN (n_buttons, 3);
+
+ /* If we change things we need to make sure we only swap buttons.
+ * If we end up with multiple physical buttons assigned to the same
+ * logical button the server will complain. This code assumes physical
+ * button 0 is the physical left mouse button, and that the physical
+ * button other than 0 currently assigned left_button or right_button
+ * is the physical right mouse button.
+ */
+
+ /* check if the current mapping satisfies the above assumptions */
+ if (buttons[left_button - 1] != left_button &&
+ buttons[left_button - 1] != right_button)
+ /* The current mapping is weird. Swapping buttons is probably not a
+ * good idea.
+ */
+ return;
+
+ /* check if we are left_handed and currently not swapped */
+ if (left_handed && buttons[left_button - 1] == left_button) {
+ /* find the right button */
+ for (i = 0; i < n_buttons; i++) {
+ if (buttons[i] == right_button) {
+ buttons[i] = left_button;
+ break;
+ }
+ }
+ /* swap the buttons */
+ buttons[left_button - 1] = right_button;
+ }
+ /* check if we are not left_handed but are swapped */
+ else if (!left_handed && buttons[left_button - 1] == right_button) {
+ /* find the right button */
+ for (i = 0; i < n_buttons; i++) {
+ if (buttons[i] == left_button) {
+ buttons[i] = right_button;
+ break;
+ }
+ }
+ /* swap the buttons */
+ buttons[left_button - 1] = left_button;
+ }
+}
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+static gboolean
+xinput_device_has_buttons (XDeviceInfo *device_info)
+{
+ int i;
+ XAnyClassInfo *class_info;
+
+ class_info = device_info->inputclassinfo;
+ for (i = 0; i < device_info->num_classes; i++) {
+ if (class_info->class == ButtonClass) {
+ XButtonInfo *button_info;
+
+ button_info = (XButtonInfo *) class_info;
+ if (button_info->num_buttons > 0)
+ return TRUE;
+ }
+
+ class_info = (XAnyClassInfo *) (((guchar *) class_info) +
+ class_info->length);
+ }
+ return FALSE;
+}
+
+static gboolean
+touchpad_has_single_button (XDevice *device)
+{
+ Atom type, prop;
+ int format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ gboolean is_single_button = FALSE;
+ int rc;
+
+ prop = XInternAtom (GDK_DISPLAY (), "Synaptics Capabilities", False);
+ if (!prop)
+ return FALSE;
+
+ gdk_error_trap_push ();
+ rc = XGetDeviceProperty (GDK_DISPLAY (), device, prop, 0, 1, False,
+ XA_INTEGER, &type, &format, &nitems,
+ &bytes_after, &data);
+ if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 3)
+ is_single_button = (data[0] == 1 && data[1] == 0 && data[2] == 0);
+
+ if (rc == Success)
+ XFree (data);
+
+ gdk_error_trap_pop ();
+
+ return is_single_button;
+}
+
+
+static void
+set_xinput_devices_left_handed (gboolean left_handed)
+{
+ XDeviceInfo *device_info;
+ gint n_devices;
+ guchar *buttons;
+ gsize buttons_capacity = 16;
+ gint n_buttons;
+ gint i;
+
+ device_info = XListInputDevices (GDK_DISPLAY (), &n_devices);
+
+ if (n_devices > 0)
+ buttons = g_new (guchar, buttons_capacity);
+ else
+ buttons = NULL;
+
+ for (i = 0; i < n_devices; i++) {
+ XDevice *device = NULL;
+
+ if ((device_info[i].use == IsXPointer) ||
+ (device_info[i].use == IsXKeyboard) ||
+ (!xinput_device_has_buttons (&device_info[i])))
+ continue;
+
+ /* If the device is a touchpad, swap tap buttons
+ * around too, otherwise a tap would be a right-click */
+ device = device_is_touchpad (device_info[i]);
+ if (device != NULL) {
+ MateConfClient *client = mateconf_client_get_default ();
+ gboolean tap = mateconf_client_get_bool (client, KEY_TAP_TO_CLICK, NULL);
+ gboolean single_button = touchpad_has_single_button (device);
+
+ if (tap && !single_button)
+ set_tap_to_click (tap, left_handed);
+ XCloseDevice (GDK_DISPLAY (), device);
+ g_object_unref (client);
+
+ if (single_button)
+ continue;
+ }
+
+ gdk_error_trap_push ();
+
+ device = XOpenDevice (GDK_DISPLAY (), device_info[i].id);
+
+ if ((gdk_error_trap_pop () != 0) ||
+ (device == NULL))
+ continue;
+
+ n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY (), device,
+ buttons,
+ buttons_capacity);
+
+ while (n_buttons > buttons_capacity) {
+ buttons_capacity = n_buttons;
+ buttons = (guchar *) g_realloc (buttons,
+ buttons_capacity * sizeof (guchar));
+
+ n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY (), device,
+ buttons,
+ buttons_capacity);
+ }
+
+ configure_button_layout (buttons, n_buttons, left_handed);
+
+ XSetDeviceButtonMapping (GDK_DISPLAY (), device, buttons, n_buttons);
+ XCloseDevice (GDK_DISPLAY (), device);
+ }
+ g_free (buttons);
+
+ if (device_info != NULL)
+ XFreeDeviceList (device_info);
+}
+
+static GdkFilterReturn
+devicepresence_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xev = (XEvent *) xevent;
+ XEventClass class_presence;
+ int xi_presence;
+
+ DevicePresence (gdk_x11_get_default_xdisplay (), xi_presence, class_presence);
+
+ if (xev->type == xi_presence)
+ {
+ XDevicePresenceNotifyEvent *dpn = (XDevicePresenceNotifyEvent *) xev;
+ if (dpn->devchange == DeviceEnabled)
+ set_mouse_settings ((GsdMouseManager *) data);
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+set_devicepresence_handler (GsdMouseManager *manager)
+{
+ Display *display;
+ XEventClass class_presence;
+ int xi_presence;
+
+ if (!supports_xinput_devices ())
+ return;
+
+ display = gdk_x11_get_default_xdisplay ();
+
+ gdk_error_trap_push ();
+ DevicePresence (display, xi_presence, class_presence);
+ XSelectExtensionEvent (display,
+ RootWindow (display, DefaultScreen (display)),
+ &class_presence, 1);
+
+ gdk_flush ();
+ if (!gdk_error_trap_pop ())
+ gdk_window_add_filter (NULL, devicepresence_filter, manager);
+}
+#endif
+
+static void
+set_left_handed (GsdMouseManager *manager,
+ gboolean left_handed)
+{
+ guchar *buttons ;
+ gsize buttons_capacity = 16;
+ gint n_buttons, i;
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ if (supports_xinput_devices ()) {
+ /* When XInput support is available, never set the
+ * button ordering on the core pointer as that would
+ * revert the changes we make on the devices themselves */
+ set_xinput_devices_left_handed (left_handed);
+ return;
+ }
+#endif
+
+ buttons = g_new (guchar, buttons_capacity);
+ n_buttons = XGetPointerMapping (GDK_DISPLAY (),
+ buttons,
+ (gint) buttons_capacity);
+ while (n_buttons > buttons_capacity) {
+ buttons_capacity = n_buttons;
+ buttons = (guchar *) g_realloc (buttons,
+ buttons_capacity * sizeof (guchar));
+
+ n_buttons = XGetPointerMapping (GDK_DISPLAY (),
+ buttons,
+ (gint) buttons_capacity);
+ }
+
+ configure_button_layout (buttons, n_buttons, left_handed);
+
+ /* X refuses to change the mapping while buttons are engaged,
+ * so if this is the case we'll retry a few times
+ */
+ for (i = 0;
+ i < 20 && XSetPointerMapping (GDK_DISPLAY (), buttons, n_buttons) == MappingBusy;
+ ++i) {
+ g_usleep (300);
+ }
+
+ g_free (buttons);
+}
+
+static void
+set_motion_acceleration (GsdMouseManager *manager,
+ gfloat motion_acceleration)
+{
+ gint numerator, denominator;
+
+ if (motion_acceleration >= 1.0) {
+ /* we want to get the acceleration, with a resolution of 0.5
+ */
+ if ((motion_acceleration - floor (motion_acceleration)) < 0.25) {
+ numerator = floor (motion_acceleration);
+ denominator = 1;
+ } else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) {
+ numerator = ceil (2.0 * motion_acceleration);
+ denominator = 2;
+ } else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) {
+ numerator = floor (2.0 *motion_acceleration);
+ denominator = 2;
+ } else {
+ numerator = ceil (motion_acceleration);
+ denominator = 1;
+ }
+ } else if (motion_acceleration < 1.0 && motion_acceleration > 0) {
+ /* This we do to 1/10ths */
+ numerator = floor (motion_acceleration * 10) + 1;
+ denominator= 10;
+ } else {
+ numerator = -1;
+ denominator = -1;
+ }
+
+ XChangePointerControl (GDK_DISPLAY (), True, False,
+ numerator, denominator,
+ 0);
+}
+
+static void
+set_motion_threshold (GsdMouseManager *manager,
+ int motion_threshold)
+{
+ XChangePointerControl (GDK_DISPLAY (), False, True,
+ 0, 0, motion_threshold);
+}
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+static XDevice*
+device_is_touchpad (XDeviceInfo deviceinfo)
+{
+ XDevice *device;
+ Atom realtype, prop;
+ int realformat;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+
+ if (deviceinfo.type != XInternAtom (GDK_DISPLAY (), XI_TOUCHPAD, False))
+ return NULL;
+
+ prop = XInternAtom (GDK_DISPLAY (), "Synaptics Off", False);
+ if (!prop)
+ return NULL;
+
+ gdk_error_trap_push ();
+ device = XOpenDevice (GDK_DISPLAY (), deviceinfo.id);
+ if (gdk_error_trap_pop () || (device == NULL))
+ return NULL;
+
+ gdk_error_trap_push ();
+ if ((XGetDeviceProperty (GDK_DISPLAY (), device, prop, 0, 1, False,
+ XA_INTEGER, &realtype, &realformat, &nitems,
+ &bytes_after, &data) == Success) && (realtype != None)) {
+ gdk_error_trap_pop ();
+ XFree (data);
+ return device;
+ }
+ gdk_error_trap_pop ();
+
+ XCloseDevice (GDK_DISPLAY (), device);
+ return NULL;
+}
+#endif
+
+static int
+set_disable_w_typing (GsdMouseManager *manager, gboolean state)
+{
+
+ if (state) {
+ GError *error = NULL;
+ char *args[5];
+
+ if (manager->priv->syndaemon_spawned)
+ return 0;
+
+ args[0] = "syndaemon";
+ args[1] = "-i";
+ args[2] = "0.5";
+ args[3] = "-k";
+ args[4] = NULL;
+
+ if (!g_find_program_in_path (args[0]))
+ return 0;
+
+ g_spawn_async (g_get_home_dir (), args, NULL,
+ G_SPAWN_SEARCH_PATH, NULL, NULL,
+ &manager->priv->syndaemon_pid, &error);
+
+ manager->priv->syndaemon_spawned = (error == NULL);
+
+ if (error) {
+ MateConfClient *client;
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_TOUCHPAD_DISABLE_W_TYPING, FALSE, NULL);
+ g_object_unref (client);
+ g_error_free (error);
+ }
+
+ } else if (manager->priv->syndaemon_spawned)
+ {
+ kill (manager->priv->syndaemon_pid, SIGHUP);
+ g_spawn_close_pid (manager->priv->syndaemon_pid);
+ manager->priv->syndaemon_spawned = FALSE;
+ }
+
+ return 0;
+}
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+static int
+set_tap_to_click (gboolean state, gboolean left_handed)
+{
+ int numdevices, i, format, rc;
+ unsigned long nitems, bytes_after;
+ XDeviceInfo *devicelist = XListInputDevices (GDK_DISPLAY (), &numdevices);
+ XDevice * device;
+ unsigned char* data;
+ Atom prop, type;
+
+ if (devicelist == NULL)
+ return 0;
+
+ prop = XInternAtom (GDK_DISPLAY (), "Synaptics Tap Action", False);
+
+ if (!prop)
+ return 0;
+
+ for (i = 0; i < numdevices; i++) {
+ if ((device = device_is_touchpad (devicelist[i]))) {
+ gdk_error_trap_push ();
+ rc = XGetDeviceProperty (GDK_DISPLAY (), device, prop, 0, 2,
+ False, XA_INTEGER, &type, &format, &nitems,
+ &bytes_after, &data);
+
+ if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 7)
+ {
+ /* Set RLM mapping for 1/2/3 fingers*/
+ data[4] = (state) ? ((left_handed) ? 3 : 1) : 0;
+ data[5] = (state) ? ((left_handed) ? 1 : 3) : 0;
+ data[6] = (state) ? 2 : 0;
+ XChangeDeviceProperty (GDK_DISPLAY (), device, prop, XA_INTEGER, 8,
+ PropModeReplace, data, nitems);
+ }
+
+ if (rc == Success)
+ XFree (data);
+ XCloseDevice (GDK_DISPLAY (), device);
+ if (gdk_error_trap_pop ()) {
+ g_warning ("Error in setting tap to click on \"%s\"", devicelist[i].name);
+ continue;
+ }
+ }
+ }
+
+ XFreeDeviceList (devicelist);
+ return 0;
+}
+
+static int
+set_horiz_scroll (gboolean state)
+{
+ int numdevices, i, rc;
+ XDeviceInfo *devicelist = XListInputDevices (GDK_DISPLAY (), &numdevices);
+ XDevice *device;
+ Atom act_type, prop_edge, prop_twofinger;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+
+ if (devicelist == NULL)
+ return 0;
+
+ prop_edge = XInternAtom (GDK_DISPLAY (), "Synaptics Edge Scrolling", False);
+ prop_twofinger = XInternAtom (GDK_DISPLAY (), "Synaptics Two-Finger Scrolling", False);
+
+ if (!prop_edge || !prop_twofinger)
+ return 0;
+
+ for (i = 0; i < numdevices; i++) {
+ if ((device = device_is_touchpad (devicelist[i]))) {
+ gdk_error_trap_push ();
+ rc = XGetDeviceProperty (GDK_DISPLAY (), device,
+ prop_edge, 0, 1, False,
+ XA_INTEGER, &act_type, &act_format, &nitems,
+ &bytes_after, &data);
+ if (rc == Success && act_type == XA_INTEGER &&
+ act_format == 8 && nitems >= 2) {
+ data[1] = (state && data[0]);
+ XChangeDeviceProperty (GDK_DISPLAY (), device,
+ prop_edge, XA_INTEGER, 8,
+ PropModeReplace, data, nitems);
+ }
+
+ XFree (data);
+
+ rc = XGetDeviceProperty (GDK_DISPLAY (), device,
+ prop_twofinger, 0, 1, False,
+ XA_INTEGER, &act_type, &act_format, &nitems,
+ &bytes_after, &data);
+ if (rc == Success && act_type == XA_INTEGER &&
+ act_format == 8 && nitems >= 2) {
+ data[1] = (state && data[0]);
+ XChangeDeviceProperty (GDK_DISPLAY (), device,
+ prop_twofinger, XA_INTEGER, 8,
+ PropModeReplace, data, nitems);
+ }
+
+ XFree (data);
+ XCloseDevice (GDK_DISPLAY (), device);
+ if (gdk_error_trap_pop ()) {
+ g_warning ("Error in setting horiz scroll on \"%s\"", devicelist[i].name);
+ continue;
+ }
+ }
+ }
+
+ XFreeDeviceList (devicelist);
+ return 0;
+}
+
+
+/**
+ * Scroll methods are: 0 - disabled, 1 - edge scrolling, 2 - twofinger
+ * scrolling
+ */
+static int
+set_edge_scroll (int method)
+{
+ int numdevices, i, rc;
+ XDeviceInfo *devicelist = XListInputDevices (GDK_DISPLAY (), &numdevices);
+ XDevice *device;
+ Atom act_type, prop_edge, prop_twofinger;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+
+ if (devicelist == NULL)
+ return 0;
+
+ prop_edge = XInternAtom (GDK_DISPLAY (), "Synaptics Edge Scrolling", False);
+ prop_twofinger = XInternAtom (GDK_DISPLAY (), "Synaptics Two-Finger Scrolling", False);
+
+ if (!prop_edge || !prop_twofinger)
+ return 0;
+
+ for (i = 0; i < numdevices; i++) {
+ if ((device = device_is_touchpad (devicelist[i]))) {
+ gdk_error_trap_push ();
+ rc = XGetDeviceProperty (GDK_DISPLAY (), device,
+ prop_edge, 0, 1, False,
+ XA_INTEGER, &act_type, &act_format, &nitems,
+ &bytes_after, &data);
+ if (rc == Success && act_type == XA_INTEGER &&
+ act_format == 8 && nitems >= 2) {
+ data[0] = (method == 1) ? 1 : 0;
+ XChangeDeviceProperty (GDK_DISPLAY (), device,
+ prop_edge, XA_INTEGER, 8,
+ PropModeReplace, data, nitems);
+ }
+
+ XFree (data);
+
+ rc = XGetDeviceProperty (GDK_DISPLAY (), device,
+ prop_twofinger, 0, 1, False,
+ XA_INTEGER, &act_type, &act_format, &nitems,
+ &bytes_after, &data);
+ if (rc == Success && act_type == XA_INTEGER &&
+ act_format == 8 && nitems >= 2) {
+ data[0] = (method == 2) ? 1 : 0;
+ XChangeDeviceProperty (GDK_DISPLAY (), device,
+ prop_twofinger, XA_INTEGER, 8,
+ PropModeReplace, data, nitems);
+ }
+
+ XFree (data);
+ XCloseDevice (GDK_DISPLAY (), device);
+ if (gdk_error_trap_pop ()) {
+ g_warning ("Error in setting edge scroll on \"%s\"", devicelist[i].name);
+ continue;
+ }
+ }
+ }
+
+ XFreeDeviceList (devicelist);
+ return 0;
+}
+
+static int
+set_touchpad_enabled (gboolean state)
+{
+ int numdevices, i;
+ XDeviceInfo *devicelist = XListInputDevices (GDK_DISPLAY (), &numdevices);
+ XDevice *device;
+ Atom prop_enabled;
+
+ if (devicelist == NULL)
+ return 0;
+
+ prop_enabled = XInternAtom (GDK_DISPLAY (), "Device Enabled", False);
+
+ if (!prop_enabled)
+ return 0;
+
+ for (i = 0; i < numdevices; i++) {
+ if ((device = device_is_touchpad (devicelist[i]))) {
+ unsigned char data = state;
+ gdk_error_trap_push ();
+ XChangeDeviceProperty (GDK_DISPLAY (), device,
+ prop_enabled, XA_INTEGER, 8,
+ PropModeReplace, &data, 1);
+ XCloseDevice (GDK_DISPLAY (), device);
+ gdk_flush ();
+ if (gdk_error_trap_pop ()) {
+ g_warning ("Error %s device \"%s\"",
+ (state) ? "enabling" : "disabling",
+ devicelist[i].name);
+ continue;
+ }
+ }
+ }
+
+ XFreeDeviceList (devicelist);
+ return 0;
+}
+#endif
+
+static void
+set_locate_pointer (GsdMouseManager *manager,
+ gboolean state)
+{
+ if (state) {
+ GError *error = NULL;
+ char *args[2];
+
+ if (manager->priv->locate_pointer_spawned)
+ return;
+
+ args[0] = LIBEXECDIR "/gsd-locate-pointer";
+ args[1] = NULL;
+
+ g_spawn_async (NULL, args, NULL,
+ 0, NULL, NULL,
+ &manager->priv->locate_pointer_pid, &error);
+
+ manager->priv->locate_pointer_spawned = (error == NULL);
+
+ if (error) {
+ MateConfClient *client;
+ client = mateconf_client_get_default ();
+ mateconf_client_set_bool (client, KEY_LOCATE_POINTER, FALSE, NULL);
+ g_object_unref (client);
+ g_error_free (error);
+ }
+
+ }
+ else if (manager->priv->locate_pointer_spawned) {
+ kill (manager->priv->locate_pointer_pid, SIGHUP);
+ g_spawn_close_pid (manager->priv->locate_pointer_pid);
+ manager->priv->locate_pointer_spawned = FALSE;
+ }
+}
+
+static void
+set_mousetweaks_daemon (GsdMouseManager *manager,
+ gboolean dwell_enable,
+ gboolean delay_enable)
+{
+ GError *error = NULL;
+ gchar *comm;
+ gboolean run_daemon = dwell_enable || delay_enable;
+
+ if (run_daemon || manager->priv->mousetweaks_daemon_running)
+ comm = g_strdup_printf ("mousetweaks %s",
+ run_daemon ? "" : "-s");
+ else
+ return;
+
+ if (run_daemon)
+ manager->priv->mousetweaks_daemon_running = TRUE;
+
+
+ if (! g_spawn_command_line_async (comm, &error)) {
+ if (error->code == G_SPAWN_ERROR_NOENT &&
+ (dwell_enable || delay_enable)) {
+ GtkWidget *dialog;
+ MateConfClient *client;
+
+ client = mateconf_client_get_default ();
+ if (dwell_enable)
+ mateconf_client_set_bool (client,
+ KEY_DWELL_ENABLE,
+ FALSE, NULL);
+ else if (delay_enable)
+ mateconf_client_set_bool (client,
+ KEY_DELAY_ENABLE,
+ FALSE, NULL);
+ g_object_unref (client);
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ _("Could not enable mouse accessibility features"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Mouse accessibility requires Mousetweaks "
+ "to be installed on your system."));
+ gtk_window_set_title (GTK_WINDOW (dialog),
+ _("Mouse Preferences"));
+ gtk_window_set_icon_name (GTK_WINDOW (dialog),
+ "input-mouse");
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+ g_error_free (error);
+ }
+ g_free (comm);
+}
+
+static void
+set_mouse_settings (GsdMouseManager *manager)
+{
+ MateConfClient *client = mateconf_client_get_default ();
+ gboolean left_handed = mateconf_client_get_bool (client, KEY_LEFT_HANDED, NULL);
+
+ set_left_handed (manager, left_handed);
+ set_motion_acceleration (manager, mateconf_client_get_float (client, KEY_MOTION_ACCELERATION , NULL));
+ set_motion_threshold (manager, mateconf_client_get_int (client, KEY_MOTION_THRESHOLD, NULL));
+
+ set_disable_w_typing (manager, mateconf_client_get_bool (client, KEY_TOUCHPAD_DISABLE_W_TYPING, NULL));
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ set_tap_to_click (mateconf_client_get_bool (client, KEY_TAP_TO_CLICK, NULL), left_handed);
+ set_edge_scroll (mateconf_client_get_int (client, KEY_SCROLL_METHOD, NULL));
+ set_horiz_scroll (mateconf_client_get_bool (client, KEY_PAD_HORIZ_SCROLL, NULL));
+ set_touchpad_enabled (mateconf_client_get_bool (client, KEY_TOUCHPAD_ENABLED, NULL));
+#endif
+
+ g_object_unref (client);
+}
+
+static void
+mouse_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdMouseManager *manager)
+{
+ if (! strcmp (entry->key, KEY_LEFT_HANDED)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ set_left_handed (manager, mateconf_value_get_bool (entry->value));
+ }
+ } else if (! strcmp (entry->key, KEY_MOTION_ACCELERATION)) {
+ if (entry->value->type == MATECONF_VALUE_FLOAT) {
+ set_motion_acceleration (manager, mateconf_value_get_float (entry->value));
+ }
+ } else if (! strcmp (entry->key, KEY_MOTION_THRESHOLD)) {
+ if (entry->value->type == MATECONF_VALUE_INT) {
+ set_motion_threshold (manager, mateconf_value_get_int (entry->value));
+ }
+ } else if (! strcmp (entry->key, KEY_TOUCHPAD_DISABLE_W_TYPING)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL)
+ set_disable_w_typing (manager, mateconf_value_get_bool (entry->value));
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ } else if (! strcmp (entry->key, KEY_TAP_TO_CLICK)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ set_tap_to_click (mateconf_value_get_bool (entry->value),
+ mateconf_client_get_bool (client, KEY_LEFT_HANDED, NULL));
+ }
+ } else if (! strcmp (entry->key, KEY_SCROLL_METHOD)) {
+ if (entry->value->type == MATECONF_VALUE_INT) {
+ set_edge_scroll (mateconf_value_get_int (entry->value));
+ set_horiz_scroll (mateconf_client_get_bool (client, KEY_PAD_HORIZ_SCROLL, NULL));
+ }
+ } else if (! strcmp (entry->key, KEY_PAD_HORIZ_SCROLL)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL)
+ set_horiz_scroll (mateconf_value_get_bool (entry->value));
+#endif
+ } else if (! strcmp (entry->key, KEY_LOCATE_POINTER)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ set_locate_pointer (manager, mateconf_value_get_bool (entry->value));
+ }
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ } else if (! strcmp (entry->key, KEY_TOUCHPAD_ENABLED)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ set_touchpad_enabled (mateconf_value_get_bool (entry->value));
+ }
+#endif
+ } else if (! strcmp (entry->key, KEY_DWELL_ENABLE)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ set_mousetweaks_daemon (manager,
+ mateconf_value_get_bool (entry->value),
+ mateconf_client_get_bool (client, KEY_DELAY_ENABLE, NULL));
+ }
+ } else if (! strcmp (entry->key, KEY_DELAY_ENABLE)) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ set_mousetweaks_daemon (manager,
+ mateconf_client_get_bool (client, KEY_DWELL_ENABLE, NULL),
+ mateconf_value_get_bool (entry->value));
+ }
+ }
+}
+
+static guint
+register_config_callback (GsdMouseManager *manager,
+ MateConfClient *client,
+ const char *path,
+ MateConfClientNotifyFunc func)
+{
+ mateconf_client_add_dir (client, path, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ return mateconf_client_notify_add (client, path, func, manager, NULL, NULL);
+}
+
+static void
+gsd_mouse_manager_init (GsdMouseManager *manager)
+{
+ manager->priv = GSD_MOUSE_MANAGER_GET_PRIVATE (manager);
+}
+
+static gboolean
+gsd_mouse_manager_idle_cb (GsdMouseManager *manager)
+{
+ MateConfClient *client;
+
+ mate_settings_profile_start (NULL);
+
+ client = mateconf_client_get_default ();
+
+ manager->priv->notify =
+ register_config_callback (manager,
+ client,
+ MATECONF_MOUSE_DIR,
+ (MateConfClientNotifyFunc) mouse_callback);
+ manager->priv->notify_a11y =
+ register_config_callback (manager,
+ client,
+ MATECONF_MOUSE_A11Y_DIR,
+ (MateConfClientNotifyFunc) mouse_callback);
+ manager->priv->notify_touchpad =
+ register_config_callback (manager,
+ client,
+ MATECONF_TOUCHPAD_DIR,
+ (MateConfClientNotifyFunc) mouse_callback);
+ manager->priv->syndaemon_spawned = FALSE;
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ set_devicepresence_handler (manager);
+#endif
+ set_mouse_settings (manager);
+ set_locate_pointer (manager, mateconf_client_get_bool (client, KEY_LOCATE_POINTER, NULL));
+ set_mousetweaks_daemon (manager,
+ mateconf_client_get_bool (client, KEY_DWELL_ENABLE, NULL),
+ mateconf_client_get_bool (client, KEY_DELAY_ENABLE, NULL));
+
+ set_disable_w_typing (manager, mateconf_client_get_bool (client, KEY_TOUCHPAD_DISABLE_W_TYPING, NULL));
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ set_tap_to_click (mateconf_client_get_bool (client, KEY_TAP_TO_CLICK, NULL),
+ mateconf_client_get_bool (client, KEY_LEFT_HANDED, NULL));
+ set_edge_scroll (mateconf_client_get_int (client, KEY_SCROLL_METHOD, NULL));
+ set_horiz_scroll (mateconf_client_get_bool (client, KEY_PAD_HORIZ_SCROLL, NULL));
+ set_touchpad_enabled (mateconf_client_get_bool (client, KEY_TOUCHPAD_ENABLED, NULL));
+#endif
+
+ g_object_unref (client);
+
+ mate_settings_profile_end (NULL);
+
+ return FALSE;
+}
+
+gboolean
+gsd_mouse_manager_start (GsdMouseManager *manager,
+ GError **error)
+{
+ mate_settings_profile_start (NULL);
+
+ g_idle_add ((GSourceFunc) gsd_mouse_manager_idle_cb, manager);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_mouse_manager_stop (GsdMouseManager *manager)
+{
+ GsdMouseManagerPrivate *p = manager->priv;
+ MateConfClient *client;
+
+ g_debug ("Stopping mouse manager");
+
+ client = mateconf_client_get_default ();
+
+ if (p->notify != 0) {
+ mateconf_client_remove_dir (client, MATECONF_MOUSE_DIR, NULL);
+ mateconf_client_notify_remove (client, p->notify);
+ p->notify = 0;
+ }
+
+ if (p->notify_a11y != 0) {
+ mateconf_client_remove_dir (client, MATECONF_MOUSE_A11Y_DIR, NULL);
+ mateconf_client_notify_remove (client, p->notify_a11y);
+ p->notify_a11y = 0;
+ }
+
+ if (p->notify_touchpad != 0) {
+ mateconf_client_remove_dir (client, MATECONF_TOUCHPAD_DIR, NULL);
+ mateconf_client_notify_remove (client, p->notify_touchpad);
+ p->notify_touchpad = 0;
+ }
+
+ g_object_unref (client);
+
+ set_locate_pointer (manager, FALSE);
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ gdk_window_remove_filter (NULL, devicepresence_filter, manager);
+#endif
+}
+
+static void
+gsd_mouse_manager_finalize (GObject *object)
+{
+ GsdMouseManager *mouse_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_MOUSE_MANAGER (object));
+
+ mouse_manager = GSD_MOUSE_MANAGER (object);
+
+ g_return_if_fail (mouse_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->finalize (object);
+}
+
+GsdMouseManager *
+gsd_mouse_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_MOUSE_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_MOUSE_MANAGER (manager_object);
+}
diff --git a/plugins/mouse/gsd-mouse-manager.h b/plugins/mouse/gsd-mouse-manager.h
new file mode 100644
index 0000000..f8f513c
--- /dev/null
+++ b/plugins/mouse/gsd-mouse-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_MOUSE_MANAGER_H
+#define __GSD_MOUSE_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_MOUSE_MANAGER (gsd_mouse_manager_get_type ())
+#define GSD_MOUSE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManager))
+#define GSD_MOUSE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerClass))
+#define GSD_IS_MOUSE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_MOUSE_MANAGER))
+#define GSD_IS_MOUSE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_MOUSE_MANAGER))
+#define GSD_MOUSE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerClass))
+
+typedef struct GsdMouseManagerPrivate GsdMouseManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdMouseManagerPrivate *priv;
+} GsdMouseManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdMouseManagerClass;
+
+GType gsd_mouse_manager_get_type (void);
+
+GsdMouseManager * gsd_mouse_manager_new (void);
+gboolean gsd_mouse_manager_start (GsdMouseManager *manager,
+ GError **error);
+void gsd_mouse_manager_stop (GsdMouseManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_MOUSE_MANAGER_H */
diff --git a/plugins/mouse/gsd-mouse-plugin.c b/plugins/mouse/gsd-mouse-plugin.c
new file mode 100644
index 0000000..900a6d5
--- /dev/null
+++ b/plugins/mouse/gsd-mouse-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-mouse-plugin.h"
+#include "gsd-mouse-manager.h"
+
+struct GsdMousePluginPrivate {
+ GsdMouseManager *manager;
+};
+
+#define GSD_MOUSE_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_MOUSE_PLUGIN, GsdMousePluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdMousePlugin, gsd_mouse_plugin)
+
+static void
+gsd_mouse_plugin_init (GsdMousePlugin *plugin)
+{
+ plugin->priv = GSD_MOUSE_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdMousePlugin initializing");
+
+ plugin->priv->manager = gsd_mouse_manager_new ();
+}
+
+static void
+gsd_mouse_plugin_finalize (GObject *object)
+{
+ GsdMousePlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_MOUSE_PLUGIN (object));
+
+ g_debug ("GsdMousePlugin finalizing");
+
+ plugin = GSD_MOUSE_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_mouse_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating mouse plugin");
+
+ error = NULL;
+ res = gsd_mouse_manager_start (GSD_MOUSE_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start mouse manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating mouse plugin");
+ gsd_mouse_manager_stop (GSD_MOUSE_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_mouse_plugin_class_init (GsdMousePluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_mouse_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdMousePluginPrivate));
+}
diff --git a/plugins/mouse/gsd-mouse-plugin.h b/plugins/mouse/gsd-mouse-plugin.h
new file mode 100644
index 0000000..e442450
--- /dev/null
+++ b/plugins/mouse/gsd-mouse-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_MOUSE_PLUGIN_H__
+#define __GSD_MOUSE_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_MOUSE_PLUGIN (gsd_mouse_plugin_get_type ())
+#define GSD_MOUSE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_MOUSE_PLUGIN, GsdMousePlugin))
+#define GSD_MOUSE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_MOUSE_PLUGIN, GsdMousePluginClass))
+#define GSD_IS_MOUSE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_MOUSE_PLUGIN))
+#define GSD_IS_MOUSE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_MOUSE_PLUGIN))
+#define GSD_MOUSE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_MOUSE_PLUGIN, GsdMousePluginClass))
+
+typedef struct GsdMousePluginPrivate GsdMousePluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdMousePluginPrivate *priv;
+} GsdMousePlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdMousePluginClass;
+
+GType gsd_mouse_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_MOUSE_PLUGIN_H__ */
diff --git a/plugins/mouse/gsd-timeline.c b/plugins/mouse/gsd-timeline.c
new file mode 100644
index 0000000..748a0ad
--- /dev/null
+++ b/plugins/mouse/gsd-timeline.c
@@ -0,0 +1,848 @@
+/* gsd-timeline.c
+ *
+ * Copyright (C) 2008 Carlos Garnacho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <math.h>
+#include "gsd-timeline.h"
+
+#define GSD_TIMELINE_GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSD_TYPE_TIMELINE, GsdTimelinePriv))
+#define MSECS_PER_SEC 1000
+#define FRAME_INTERVAL(nframes) (MSECS_PER_SEC / nframes)
+#define DEFAULT_FPS 30
+
+typedef struct GsdTimelinePriv GsdTimelinePriv;
+
+struct GsdTimelinePriv
+{
+ guint duration;
+ guint fps;
+ guint source_id;
+
+ GTimer *timer;
+
+ GdkScreen *screen;
+ GsdTimelineProgressType progress_type;
+ GsdTimelineProgressFunc progress_func;
+
+ guint loop : 1;
+ guint direction : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_FPS,
+ PROP_DURATION,
+ PROP_LOOP,
+ PROP_DIRECTION,
+ PROP_SCREEN,
+ PROP_PROGRESS_TYPE,
+};
+
+enum {
+ STARTED,
+ PAUSED,
+ FINISHED,
+ FRAME,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+
+static void gsd_timeline_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gsd_timeline_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gsd_timeline_finalize (GObject *object);
+
+
+G_DEFINE_TYPE (GsdTimeline, gsd_timeline, G_TYPE_OBJECT)
+
+
+GType
+gsd_timeline_direction_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ static const GEnumValue values[] = {
+ { GSD_TIMELINE_DIRECTION_FORWARD, "GSD_TIMELINE_DIRECTION_FORWARD", "forward" },
+ { GSD_TIMELINE_DIRECTION_BACKWARD, "GSD_TIMELINE_DIRECTION_BACKWARD", "backward" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static (g_intern_static_string ("GsdTimelineDirection"), values);
+ }
+
+ return type;
+}
+
+GType
+gsd_timeline_progress_type_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ static const GEnumValue values[] = {
+ { GSD_TIMELINE_PROGRESS_LINEAR, "GSD_TIMELINE_PROGRESS_LINEAR", "linear" },
+ { GSD_TIMELINE_PROGRESS_SINUSOIDAL, "GSD_TIMELINE_PROGRESS_SINUSOIDAL", "sinusoidal" },
+ { GSD_TIMELINE_PROGRESS_EXPONENTIAL, "GSD_TIMELINE_PROGRESS_EXPONENTIAL", "exponential" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static (g_intern_static_string ("GsdTimelineProgressType"), values);
+ }
+
+ return type;
+}
+
+static void
+gsd_timeline_class_init (GsdTimelineClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->set_property = gsd_timeline_set_property;
+ object_class->get_property = gsd_timeline_get_property;
+ object_class->finalize = gsd_timeline_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_FPS,
+ g_param_spec_uint ("fps",
+ "FPS",
+ "Frames per second for the timeline",
+ 1,
+ G_MAXUINT,
+ DEFAULT_FPS,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_DURATION,
+ g_param_spec_uint ("duration",
+ "Animation Duration",
+ "Animation Duration",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_LOOP,
+ g_param_spec_boolean ("loop",
+ "Loop",
+ "Whether the timeline loops or not",
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_DIRECTION,
+ g_param_spec_enum ("direction",
+ "Direction",
+ "Whether the timeline moves forward or backward in time",
+ GSD_TYPE_TIMELINE_DIRECTION,
+ GSD_TIMELINE_DIRECTION_FORWARD,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_DIRECTION,
+ g_param_spec_enum ("progress-type",
+ "Progress type",
+ "Type of progress through the timeline",
+ GSD_TYPE_TIMELINE_PROGRESS_TYPE,
+ GSD_TIMELINE_PROGRESS_LINEAR,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SCREEN,
+ g_param_spec_object ("screen",
+ "Screen",
+ "Screen to get the settings from",
+ GDK_TYPE_SCREEN,
+ G_PARAM_READWRITE));
+
+ signals[STARTED] =
+ g_signal_new ("started",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdTimelineClass, started),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[PAUSED] =
+ g_signal_new ("paused",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdTimelineClass, paused),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[FINISHED] =
+ g_signal_new ("finished",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdTimelineClass, finished),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[FRAME] =
+ g_signal_new ("frame",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdTimelineClass, frame),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__DOUBLE,
+ G_TYPE_NONE, 1,
+ G_TYPE_DOUBLE);
+
+ g_type_class_add_private (class, sizeof (GsdTimelinePriv));
+}
+
+static void
+gsd_timeline_init (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ priv->fps = DEFAULT_FPS;
+ priv->duration = 0;
+ priv->direction = GSD_TIMELINE_DIRECTION_FORWARD;
+ priv->screen = gdk_screen_get_default ();
+}
+
+static void
+gsd_timeline_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdTimeline *timeline;
+ GsdTimelinePriv *priv;
+
+ timeline = GSD_TIMELINE (object);
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ switch (prop_id)
+ {
+ case PROP_FPS:
+ gsd_timeline_set_fps (timeline, g_value_get_uint (value));
+ break;
+ case PROP_DURATION:
+ gsd_timeline_set_duration (timeline, g_value_get_uint (value));
+ break;
+ case PROP_LOOP:
+ gsd_timeline_set_loop (timeline, g_value_get_boolean (value));
+ break;
+ case PROP_DIRECTION:
+ gsd_timeline_set_direction (timeline, g_value_get_enum (value));
+ break;
+ case PROP_SCREEN:
+ gsd_timeline_set_screen (timeline,
+ GDK_SCREEN (g_value_get_object (value)));
+ break;
+ case PROP_PROGRESS_TYPE:
+ gsd_timeline_set_progress_type (timeline, g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gsd_timeline_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdTimeline *timeline;
+ GsdTimelinePriv *priv;
+
+ timeline = GSD_TIMELINE (object);
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ switch (prop_id)
+ {
+ case PROP_FPS:
+ g_value_set_uint (value, priv->fps);
+ break;
+ case PROP_DURATION:
+ g_value_set_uint (value, priv->duration);
+ break;
+ case PROP_LOOP:
+ g_value_set_boolean (value, priv->loop);
+ break;
+ case PROP_DIRECTION:
+ g_value_set_enum (value, priv->direction);
+ break;
+ case PROP_SCREEN:
+ g_value_set_object (value, priv->screen);
+ break;
+ case PROP_PROGRESS_TYPE:
+ g_value_set_enum (value, priv->progress_type);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gsd_timeline_finalize (GObject *object)
+{
+ GsdTimelinePriv *priv;
+
+ priv = GSD_TIMELINE_GET_PRIV (object);
+
+ if (priv->source_id)
+ {
+ g_source_remove (priv->source_id);
+ priv->source_id = 0;
+ }
+
+ if (priv->timer)
+ g_timer_destroy (priv->timer);
+
+ G_OBJECT_CLASS (gsd_timeline_parent_class)->finalize (object);
+}
+
+/* Sinusoidal progress */
+static gdouble
+sinusoidal_progress (gdouble progress)
+{
+ return (sinf ((progress * G_PI) / 2));
+}
+
+static gdouble
+exponential_progress (gdouble progress)
+{
+ return progress * progress;
+}
+
+static GsdTimelineProgressFunc
+progress_type_to_func (GsdTimelineProgressType type)
+{
+ if (type == GSD_TIMELINE_PROGRESS_SINUSOIDAL)
+ return sinusoidal_progress;
+ else if (type == GSD_TIMELINE_PROGRESS_EXPONENTIAL)
+ return exponential_progress;
+
+ return NULL;
+}
+
+static gboolean
+gsd_timeline_run_frame (GsdTimeline *timeline,
+ gboolean enable_animations)
+{
+ GsdTimelinePriv *priv;
+ gdouble linear_progress, progress;
+ guint elapsed_time;
+ GsdTimelineProgressFunc progress_func = NULL;
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ if (enable_animations)
+ {
+ elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000);
+
+ linear_progress = (gdouble) elapsed_time / priv->duration;
+
+ if (priv->direction == GSD_TIMELINE_DIRECTION_BACKWARD)
+ linear_progress = 1 - linear_progress;
+
+ linear_progress = CLAMP (linear_progress, 0., 1.);
+
+ if (priv->progress_func)
+ progress_func = priv->progress_func;
+ else if (priv->progress_type)
+ progress_func = progress_type_to_func (priv->progress_type);
+
+ if (progress_func)
+ progress = (progress_func) (linear_progress);
+ else
+ progress = linear_progress;
+ }
+ else
+ progress = (priv->direction == GSD_TIMELINE_DIRECTION_FORWARD) ? 1.0 : 0.0;
+
+ g_signal_emit (timeline, signals [FRAME], 0,
+ CLAMP (progress, 0.0, 1.0));
+
+ if ((priv->direction == GSD_TIMELINE_DIRECTION_FORWARD && progress >= 1.0) ||
+ (priv->direction == GSD_TIMELINE_DIRECTION_BACKWARD && progress <= 0.0))
+ {
+ if (!priv->loop)
+ {
+ if (priv->source_id)
+ {
+ g_source_remove (priv->source_id);
+ priv->source_id = 0;
+ }
+
+ g_signal_emit (timeline, signals [FINISHED], 0);
+ return FALSE;
+ }
+ else
+ gsd_timeline_rewind (timeline);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gsd_timeline_frame_idle_func (GsdTimeline *timeline)
+{
+ return gsd_timeline_run_frame (timeline, TRUE);
+}
+
+/**
+ * gsd_timeline_new:
+ * @duration: duration in milliseconds for the timeline
+ *
+ * Creates a new #GsdTimeline with the specified number of frames.
+ *
+ * Return Value: the newly created #GsdTimeline
+ **/
+GsdTimeline *
+gsd_timeline_new (guint duration)
+{
+ return g_object_new (GSD_TYPE_TIMELINE,
+ "duration", duration,
+ NULL);
+}
+
+GsdTimeline *
+gsd_timeline_new_for_screen (guint duration,
+ GdkScreen *screen)
+{
+ return g_object_new (GSD_TYPE_TIMELINE,
+ "duration", duration,
+ "screen", screen,
+ NULL);
+}
+
+/**
+ * gsd_timeline_start:
+ * @timeline: A #GsdTimeline
+ *
+ * Runs the timeline from the current frame.
+ **/
+void
+gsd_timeline_start (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+ GtkSettings *settings;
+ gboolean enable_animations = FALSE;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ if (priv->screen)
+ {
+ settings = gtk_settings_get_for_screen (priv->screen);
+ g_object_get (settings, "gtk-enable-animations", &enable_animations, NULL);
+ }
+
+ if (enable_animations)
+ {
+ if (!priv->source_id)
+ {
+ if (priv->timer)
+ g_timer_continue (priv->timer);
+ else
+ priv->timer = g_timer_new ();
+
+ /* sanity check */
+ g_assert (priv->fps > 0);
+
+ g_signal_emit (timeline, signals [STARTED], 0);
+
+ priv->source_id = gdk_threads_add_timeout (FRAME_INTERVAL (priv->fps),
+ (GSourceFunc) gsd_timeline_frame_idle_func,
+ timeline);
+ }
+ }
+ else
+ {
+ /* If animations are not enabled, only run the last frame,
+ * it take us instantaneously to the last state of the animation.
+ * The only potential flaw happens when people use the ::finished
+ * signal to trigger another animation, or even worse, finally
+ * loop into this animation again.
+ */
+ g_signal_emit (timeline, signals [STARTED], 0);
+ gsd_timeline_run_frame (timeline, FALSE);
+ }
+}
+
+/**
+ * gsd_timeline_pause:
+ * @timeline: A #GsdTimeline
+ *
+ * Pauses the timeline.
+ **/
+void
+gsd_timeline_pause (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ if (priv->source_id)
+ {
+ g_source_remove (priv->source_id);
+ priv->source_id = 0;
+ g_timer_stop (priv->timer);
+ g_signal_emit (timeline, signals [PAUSED], 0);
+ }
+}
+
+/**
+ * gsd_timeline_rewind:
+ * @timeline: A #GsdTimeline
+ *
+ * Rewinds the timeline.
+ **/
+void
+gsd_timeline_rewind (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ /* destroy and re-create timer if neccesary */
+ if (priv->timer)
+ {
+ g_timer_destroy (priv->timer);
+
+ if (gsd_timeline_is_running (timeline))
+ priv->timer = g_timer_new ();
+ else
+ priv->timer = NULL;
+ }
+}
+
+/**
+ * gsd_timeline_is_running:
+ * @timeline: A #GsdTimeline
+ *
+ * Returns whether the timeline is running or not.
+ *
+ * Return Value: %TRUE if the timeline is running
+ **/
+gboolean
+gsd_timeline_is_running (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), FALSE);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ return (priv->source_id != 0);
+}
+
+/**
+ * gsd_timeline_get_fps:
+ * @timeline: A #GsdTimeline
+ *
+ * Returns the number of frames per second.
+ *
+ * Return Value: frames per second
+ **/
+guint
+gsd_timeline_get_fps (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), 1);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ return priv->fps;
+}
+
+/**
+ * gsd_timeline_set_fps:
+ * @timeline: A #GsdTimeline
+ * @fps: frames per second
+ *
+ * Sets the number of frames per second that
+ * the timeline will play.
+ **/
+void
+gsd_timeline_set_fps (GsdTimeline *timeline,
+ guint fps)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+ g_return_if_fail (fps > 0);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ priv->fps = fps;
+
+ if (gsd_timeline_is_running (timeline))
+ {
+ g_source_remove (priv->source_id);
+ priv->source_id = gdk_threads_add_timeout (FRAME_INTERVAL (priv->fps),
+ (GSourceFunc) gsd_timeline_run_frame,
+ timeline);
+ }
+
+ g_object_notify (G_OBJECT (timeline), "fps");
+}
+
+/**
+ * gsd_timeline_get_loop:
+ * @timeline: A #GsdTimeline
+ *
+ * Returns whether the timeline loops to the
+ * beginning when it has reached the end.
+ *
+ * Return Value: %TRUE if the timeline loops
+ **/
+gboolean
+gsd_timeline_get_loop (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), FALSE);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ return priv->loop;
+}
+
+/**
+ * gsd_timeline_set_loop:
+ * @timeline: A #GsdTimeline
+ * @loop: %TRUE to make the timeline loop
+ *
+ * Sets whether the timeline loops to the beginning
+ * when it has reached the end.
+ **/
+void
+gsd_timeline_set_loop (GsdTimeline *timeline,
+ gboolean loop)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ priv->loop = loop;
+
+ g_object_notify (G_OBJECT (timeline), "loop");
+}
+
+void
+gsd_timeline_set_duration (GsdTimeline *timeline,
+ guint duration)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ priv->duration = duration;
+
+ g_object_notify (G_OBJECT (timeline), "duration");
+}
+
+guint
+gsd_timeline_get_duration (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), 0);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ return priv->duration;
+}
+
+/**
+ * gsd_timeline_get_direction:
+ * @timeline: A #GsdTimeline
+ *
+ * Returns the direction of the timeline.
+ *
+ * Return Value: direction
+ **/
+GsdTimelineDirection
+gsd_timeline_get_direction (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), GSD_TIMELINE_DIRECTION_FORWARD);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ return priv->direction;
+}
+
+/**
+ * gsd_timeline_set_direction:
+ * @timeline: A #GsdTimeline
+ * @direction: direction
+ *
+ * Sets the direction of the timeline.
+ **/
+void
+gsd_timeline_set_direction (GsdTimeline *timeline,
+ GsdTimelineDirection direction)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ priv->direction = direction;
+
+ g_object_notify (G_OBJECT (timeline), "direction");
+}
+
+GdkScreen *
+gsd_timeline_get_screen (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), NULL);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ return priv->screen;
+}
+
+void
+gsd_timeline_set_screen (GsdTimeline *timeline,
+ GdkScreen *screen)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+ g_return_if_fail (GDK_IS_SCREEN (screen));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ if (priv->screen)
+ g_object_unref (priv->screen);
+
+ priv->screen = g_object_ref (screen);
+
+ g_object_notify (G_OBJECT (timeline), "screen");
+}
+
+void
+gsd_timeline_set_progress_type (GsdTimeline *timeline,
+ GsdTimelineProgressType type)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ priv->progress_type = type;
+
+ g_object_notify (G_OBJECT (timeline), "progress-type");
+}
+
+GsdTimelineProgressType
+gsd_timeline_get_progress_type (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), GSD_TIMELINE_PROGRESS_LINEAR);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ if (priv->progress_func)
+ return GSD_TIMELINE_PROGRESS_LINEAR;
+
+ return priv->progress_type;
+}
+
+/**
+ * gsd_timeline_set_progress_func:
+ * @timeline: A #GsdTimeline
+ * @progress_func: progress function
+ *
+ * Sets the progress function. This function will be used to calculate
+ * a different progress to pass to the ::frame signal based on the
+ * linear progress through the timeline. Setting progress_func
+ * to %NULL will make the timeline use the default function,
+ * which is just a linear progress.
+ *
+ * All progresses are in the [0.0, 1.0] range.
+ **/
+void
+gsd_timeline_set_progress_func (GsdTimeline *timeline,
+ GsdTimelineProgressFunc progress_func)
+{
+ GsdTimelinePriv *priv;
+
+ g_return_if_fail (GSD_IS_TIMELINE (timeline));
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+ priv->progress_func = progress_func;
+}
+
+gdouble
+gsd_timeline_get_progress (GsdTimeline *timeline)
+{
+ GsdTimelinePriv *priv;
+ GsdTimelineProgressFunc progress_func = NULL;
+ gdouble linear_progress, progress;
+ guint elapsed_time;
+
+ g_return_val_if_fail (GSD_IS_TIMELINE (timeline), 0.0);
+
+ priv = GSD_TIMELINE_GET_PRIV (timeline);
+
+ if (!priv->timer)
+ return 0.;
+
+ elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000);
+
+ linear_progress = (gdouble) elapsed_time / priv->duration;
+
+ if (priv->direction == GSD_TIMELINE_DIRECTION_BACKWARD)
+ linear_progress = 1 - linear_progress;
+
+ linear_progress = CLAMP (linear_progress, 0., 1.);
+
+ if (priv->progress_func)
+ progress_func = priv->progress_func;
+ else if (priv->progress_type)
+ progress_func = progress_type_to_func (priv->progress_type);
+
+ if (progress_func)
+ progress = (progress_func) (linear_progress);
+ else
+ progress = linear_progress;
+
+ return CLAMP (progress, 0., 1.);
+}
diff --git a/plugins/mouse/gsd-timeline.h b/plugins/mouse/gsd-timeline.h
new file mode 100644
index 0000000..d4ecbcc
--- /dev/null
+++ b/plugins/mouse/gsd-timeline.h
@@ -0,0 +1,127 @@
+/* gsdtimeline.c
+ *
+ * Copyright (C) 2008 Carlos Garnacho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSD_TIMELINE_H__
+#define __GSD_TIMELINE_H__
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_TIMELINE_DIRECTION (gsd_timeline_direction_get_type ())
+#define GSD_TYPE_TIMELINE_PROGRESS_TYPE (gsd_timeline_progress_type_get_type ())
+#define GSD_TYPE_TIMELINE (gsd_timeline_get_type ())
+#define GSD_TIMELINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_TIMELINE, GsdTimeline))
+#define GSD_TIMELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_TIMELINE, GsdTimelineClass))
+#define GSD_IS_TIMELINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_TIMELINE))
+#define GSD_IS_TIMELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_TIMELINE))
+#define GSD_TIMELINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_TIMELINE, GsdTimelineClass))
+
+typedef enum {
+ GSD_TIMELINE_DIRECTION_FORWARD,
+ GSD_TIMELINE_DIRECTION_BACKWARD
+} GsdTimelineDirection;
+
+typedef enum {
+ GSD_TIMELINE_PROGRESS_LINEAR,
+ GSD_TIMELINE_PROGRESS_SINUSOIDAL,
+ GSD_TIMELINE_PROGRESS_EXPONENTIAL
+} GsdTimelineProgressType;
+
+typedef struct GsdTimeline GsdTimeline;
+typedef struct GsdTimelineClass GsdTimelineClass;
+
+struct GsdTimeline
+{
+ GObject parent_instance;
+};
+
+struct GsdTimelineClass
+{
+ GObjectClass parent_class;
+
+ void (* started) (GsdTimeline *timeline);
+ void (* finished) (GsdTimeline *timeline);
+ void (* paused) (GsdTimeline *timeline);
+
+ void (* frame) (GsdTimeline *timeline,
+ gdouble progress);
+
+ void (* __gsd_reserved1) (void);
+ void (* __gsd_reserved2) (void);
+ void (* __gsd_reserved3) (void);
+ void (* __gsd_reserved4) (void);
+};
+
+typedef gdouble (*GsdTimelineProgressFunc) (gdouble progress);
+
+
+GType gsd_timeline_get_type (void) G_GNUC_CONST;
+GType gsd_timeline_direction_get_type (void) G_GNUC_CONST;
+GType gsd_timeline_progress_type_get_type (void) G_GNUC_CONST;
+
+GsdTimeline *gsd_timeline_new (guint duration);
+GsdTimeline *gsd_timeline_new_for_screen (guint duration,
+ GdkScreen *screen);
+
+void gsd_timeline_start (GsdTimeline *timeline);
+void gsd_timeline_pause (GsdTimeline *timeline);
+void gsd_timeline_rewind (GsdTimeline *timeline);
+
+gboolean gsd_timeline_is_running (GsdTimeline *timeline);
+
+guint gsd_timeline_get_fps (GsdTimeline *timeline);
+void gsd_timeline_set_fps (GsdTimeline *timeline,
+ guint fps);
+
+gboolean gsd_timeline_get_loop (GsdTimeline *timeline);
+void gsd_timeline_set_loop (GsdTimeline *timeline,
+ gboolean loop);
+
+guint gsd_timeline_get_duration (GsdTimeline *timeline);
+void gsd_timeline_set_duration (GsdTimeline *timeline,
+ guint duration);
+
+GdkScreen *gsd_timeline_get_screen (GsdTimeline *timeline);
+void gsd_timeline_set_screen (GsdTimeline *timeline,
+ GdkScreen *screen);
+
+GsdTimelineDirection gsd_timeline_get_direction (GsdTimeline *timeline);
+void gsd_timeline_set_direction (GsdTimeline *timeline,
+ GsdTimelineDirection direction);
+
+GsdTimelineProgressType gsd_timeline_get_progress_type (GsdTimeline *timeline);
+void gsd_timeline_set_progress_type (GsdTimeline *timeline,
+ GsdTimelineProgressType type);
+void gsd_timeline_get_progress_func (GsdTimeline *timeline);
+
+void gsd_timeline_set_progress_func (GsdTimeline *timeline,
+ GsdTimelineProgressFunc progress_func);
+
+gdouble gsd_timeline_get_progress (GsdTimeline *timeline);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_TIMELINE_H__ */
diff --git a/plugins/mouse/mouse.mate-settings-plugin.in b/plugins/mouse/mouse.mate-settings-plugin.in
new file mode 100644
index 0000000..8cf5272
--- /dev/null
+++ b/plugins/mouse/mouse.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=mouse
+IAge=0
+_Name=Mouse
+_Description=Mouse plugin
+Authors=
+Copyright=Copyright © 2007
+Website=
diff --git a/plugins/smartcard/Makefile.am b/plugins/smartcard/Makefile.am
new file mode 100644
index 0000000..a70e0a0
--- /dev/null
+++ b/plugins/smartcard/Makefile.am
@@ -0,0 +1,47 @@
+plugin_LTLIBRARIES = \
+ libsmartcard.la
+
+libsmartcard_la_SOURCES = \
+ gsd-smartcard-plugin.h \
+ gsd-smartcard-plugin.c \
+ gsd-smartcard.h \
+ gsd-smartcard.c \
+ gsd-smartcard-manager.h \
+ gsd-smartcard-manager.c
+
+libsmartcard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \
+ $(AM_CPPFLAGS)
+
+libsmartcard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(MATE_CFLAGS) \
+ $(NSS_CFLAGS) \
+ $(AM_CFLAGS)
+
+libsmartcard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libsmartcard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NSS_LIBS)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+plugin_in_files = \
+ smartcard.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files)
+
+CLEANFILES = \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
diff --git a/plugins/smartcard/Makefile.in b/plugins/smartcard/Makefile.in
new file mode 100644
index 0000000..5e77c45
--- /dev/null
+++ b/plugins/smartcard/Makefile.in
@@ -0,0 +1,684 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/smartcard
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libsmartcard_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libsmartcard_la_OBJECTS = libsmartcard_la-gsd-smartcard-plugin.lo \
+ libsmartcard_la-gsd-smartcard.lo \
+ libsmartcard_la-gsd-smartcard-manager.lo
+libsmartcard_la_OBJECTS = $(am_libsmartcard_la_OBJECTS)
+libsmartcard_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libsmartcard_la_CFLAGS) \
+ $(CFLAGS) $(libsmartcard_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libsmartcard_la_SOURCES)
+DIST_SOURCES = $(libsmartcard_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = \
+ libsmartcard.la
+
+libsmartcard_la_SOURCES = \
+ gsd-smartcard-plugin.h \
+ gsd-smartcard-plugin.c \
+ gsd-smartcard.h \
+ gsd-smartcard.c \
+ gsd-smartcard-manager.h \
+ gsd-smartcard-manager.c
+
+libsmartcard_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \
+ $(AM_CPPFLAGS)
+
+libsmartcard_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(MATE_CFLAGS) \
+ $(NSS_CFLAGS) \
+ $(AM_CFLAGS)
+
+libsmartcard_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libsmartcard_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NSS_LIBS)
+
+plugin_in_files = \
+ smartcard.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files)
+
+CLEANFILES = \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/smartcard/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/smartcard/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libsmartcard.la: $(libsmartcard_la_OBJECTS) $(libsmartcard_la_DEPENDENCIES)
+ $(libsmartcard_la_LINK) -rpath $(plugindir) $(libsmartcard_la_OBJECTS) $(libsmartcard_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsmartcard_la-gsd-smartcard-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsmartcard_la-gsd-smartcard-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsmartcard_la-gsd-smartcard.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libsmartcard_la-gsd-smartcard-plugin.lo: gsd-smartcard-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsmartcard_la_CPPFLAGS) $(CPPFLAGS) $(libsmartcard_la_CFLAGS) $(CFLAGS) -MT libsmartcard_la-gsd-smartcard-plugin.lo -MD -MP -MF $(DEPDIR)/libsmartcard_la-gsd-smartcard-plugin.Tpo -c -o libsmartcard_la-gsd-smartcard-plugin.lo `test -f 'gsd-smartcard-plugin.c' || echo '$(srcdir)/'`gsd-smartcard-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libsmartcard_la-gsd-smartcard-plugin.Tpo $(DEPDIR)/libsmartcard_la-gsd-smartcard-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-smartcard-plugin.c' object='libsmartcard_la-gsd-smartcard-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsmartcard_la_CPPFLAGS) $(CPPFLAGS) $(libsmartcard_la_CFLAGS) $(CFLAGS) -c -o libsmartcard_la-gsd-smartcard-plugin.lo `test -f 'gsd-smartcard-plugin.c' || echo '$(srcdir)/'`gsd-smartcard-plugin.c
+
+libsmartcard_la-gsd-smartcard.lo: gsd-smartcard.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsmartcard_la_CPPFLAGS) $(CPPFLAGS) $(libsmartcard_la_CFLAGS) $(CFLAGS) -MT libsmartcard_la-gsd-smartcard.lo -MD -MP -MF $(DEPDIR)/libsmartcard_la-gsd-smartcard.Tpo -c -o libsmartcard_la-gsd-smartcard.lo `test -f 'gsd-smartcard.c' || echo '$(srcdir)/'`gsd-smartcard.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libsmartcard_la-gsd-smartcard.Tpo $(DEPDIR)/libsmartcard_la-gsd-smartcard.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-smartcard.c' object='libsmartcard_la-gsd-smartcard.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsmartcard_la_CPPFLAGS) $(CPPFLAGS) $(libsmartcard_la_CFLAGS) $(CFLAGS) -c -o libsmartcard_la-gsd-smartcard.lo `test -f 'gsd-smartcard.c' || echo '$(srcdir)/'`gsd-smartcard.c
+
+libsmartcard_la-gsd-smartcard-manager.lo: gsd-smartcard-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsmartcard_la_CPPFLAGS) $(CPPFLAGS) $(libsmartcard_la_CFLAGS) $(CFLAGS) -MT libsmartcard_la-gsd-smartcard-manager.lo -MD -MP -MF $(DEPDIR)/libsmartcard_la-gsd-smartcard-manager.Tpo -c -o libsmartcard_la-gsd-smartcard-manager.lo `test -f 'gsd-smartcard-manager.c' || echo '$(srcdir)/'`gsd-smartcard-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libsmartcard_la-gsd-smartcard-manager.Tpo $(DEPDIR)/libsmartcard_la-gsd-smartcard-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-smartcard-manager.c' object='libsmartcard_la-gsd-smartcard-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsmartcard_la_CPPFLAGS) $(CPPFLAGS) $(libsmartcard_la_CFLAGS) $(CFLAGS) -c -o libsmartcard_la-gsd-smartcard-manager.lo `test -f 'gsd-smartcard-manager.c' || echo '$(srcdir)/'`gsd-smartcard-manager.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
new file mode 100644
index 0000000..a231e20
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -0,0 +1,1372 @@
+/* gsd-smartcard-manager.c - object for monitoring smartcard insertion and
+ * removal events
+ *
+ * Copyright (C) 2006, 2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written By: Ray Strode
+ */
+#include "config.h"
+
+#include "gsd-smartcard-manager.h"
+
+#define SMARTCARD_ENABLE_INTERNAL_API
+#include "gsd-smartcard.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <prerror.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <secmod.h>
+#include <secerr.h>
+
+#ifndef GSD_SMARTCARD_MANAGER_NSS_DB
+#define GSD_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb"
+#endif
+
+typedef enum _GsdSmartcardManagerState GsdSmartcardManagerState;
+typedef struct _GsdSmartcardManagerWorker GsdSmartcardManagerWorker;
+
+enum _GsdSmartcardManagerState {
+ GSD_SMARTCARD_MANAGER_STATE_STOPPED = 0,
+ GSD_SMARTCARD_MANAGER_STATE_STARTING,
+ GSD_SMARTCARD_MANAGER_STATE_STARTED,
+ GSD_SMARTCARD_MANAGER_STATE_STOPPING,
+};
+
+struct _GsdSmartcardManagerPrivate {
+ GsdSmartcardManagerState state;
+ SECMODModule *module;
+ char *module_path;
+
+ GSource *smartcard_event_source;
+ GPid smartcard_event_watcher_pid;
+ GHashTable *smartcards;
+
+ GThread *worker_thread;
+
+ guint poll_timeout_id;
+
+ guint32 is_unstoppable : 1;
+ guint32 nss_is_loaded : 1;
+};
+
+struct _GsdSmartcardManagerWorker {
+ SECMODModule *module;
+ GHashTable *smartcards;
+ int write_fd;
+
+ guint32 nss_is_loaded : 1;
+};
+
+static void gsd_smartcard_manager_finalize (GObject *object);
+static void gsd_smartcard_manager_class_install_signals (GsdSmartcardManagerClass *service_class);
+static void gsd_smartcard_manager_class_install_properties (GsdSmartcardManagerClass *service_class);
+static void gsd_smartcard_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gsd_smartcard_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gsd_smartcard_manager_set_module_path (GsdSmartcardManager *manager,
+ const char *module_path);
+static void gsd_smartcard_manager_card_removed_handler (GsdSmartcardManager *manager,
+ GsdSmartcard *card);
+static void gsd_smartcard_manager_card_inserted_handler (GsdSmartcardManager *manager_class,
+ GsdSmartcard *card);
+static gboolean gsd_smartcard_manager_stop_now (GsdSmartcardManager *manager);
+static void gsd_smartcard_manager_queue_stop (GsdSmartcardManager *manager);
+
+static gboolean gsd_smartcard_manager_create_worker (GsdSmartcardManager *manager,
+ int *worker_fd, GThread **worker_thread);
+
+static GsdSmartcardManagerWorker * gsd_smartcard_manager_worker_new (int write_fd);
+static void gsd_smartcard_manager_worker_free (GsdSmartcardManagerWorker *worker);
+static gboolean open_pipe (int *write_fd, int *read_fd);
+static gboolean read_bytes (int fd, gpointer bytes, gsize num_bytes);
+static gboolean write_bytes (int fd, gconstpointer bytes, gsize num_bytes);
+static GsdSmartcard *read_smartcard (int fd, SECMODModule *module);
+static gboolean write_smartcard (int fd, GsdSmartcard *card);
+
+enum {
+ PROP_0 = 0,
+ PROP_MODULE_PATH,
+ NUMBER_OF_PROPERTIES
+};
+
+enum {
+ SMARTCARD_INSERTED = 0,
+ SMARTCARD_REMOVED,
+ ERROR,
+ NUMBER_OF_SIGNALS
+};
+
+static guint gsd_smartcard_manager_signals[NUMBER_OF_SIGNALS];
+
+G_DEFINE_TYPE (GsdSmartcardManager,
+ gsd_smartcard_manager,
+ G_TYPE_OBJECT);
+
+static void
+gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *manager_class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (manager_class);
+
+ gobject_class->finalize = gsd_smartcard_manager_finalize;
+
+ gsd_smartcard_manager_class_install_signals (manager_class);
+ gsd_smartcard_manager_class_install_properties (manager_class);
+
+ g_type_class_add_private (manager_class,
+ sizeof (GsdSmartcardManagerPrivate));
+}
+
+static void
+gsd_smartcard_manager_class_install_properties (GsdSmartcardManagerClass *card_class)
+{
+ GObjectClass *object_class;
+ GParamSpec *param_spec;
+
+ object_class = G_OBJECT_CLASS (card_class);
+ object_class->set_property = gsd_smartcard_manager_set_property;
+ object_class->get_property = gsd_smartcard_manager_get_property;
+
+ param_spec = g_param_spec_string ("module-path", _("Module Path"),
+ _("path to smartcard PKCS #11 driver"),
+ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec);
+}
+
+static void
+gsd_smartcard_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdSmartcardManager *manager = GSD_SMARTCARD_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_MODULE_PATH:
+ gsd_smartcard_manager_set_module_path (manager,
+ g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_smartcard_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdSmartcardManager *manager = GSD_SMARTCARD_MANAGER (object);
+ char *module_path;
+
+ switch (prop_id) {
+ case PROP_MODULE_PATH:
+ module_path = gsd_smartcard_manager_get_module_path (manager);
+ g_value_set_string (value, module_path);
+ g_free (module_path);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+char *
+gsd_smartcard_manager_get_module_path (GsdSmartcardManager *manager)
+{
+ return manager->priv->module_path;
+}
+
+static void
+gsd_smartcard_manager_set_module_path (GsdSmartcardManager *manager,
+ const char *module_path)
+{
+ if ((manager->priv->module_path == NULL) && (module_path == NULL)) {
+ return;
+ }
+
+ if (((manager->priv->module_path == NULL) ||
+ (module_path == NULL) ||
+ (strcmp (manager->priv->module_path, module_path) != 0))) {
+ g_free (manager->priv->module_path);
+ manager->priv->module_path = g_strdup (module_path);
+ g_object_notify (G_OBJECT (manager), "module-path");
+ }
+}
+
+static void
+gsd_smartcard_manager_card_removed_handler (GsdSmartcardManager *manager,
+ GsdSmartcard *card)
+{
+ g_debug ("informing smartcard of its removal");
+ _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED);
+ g_debug ("done");
+}
+
+static void
+gsd_smartcard_manager_card_inserted_handler (GsdSmartcardManager *manager,
+ GsdSmartcard *card)
+{
+ g_debug ("informing smartcard of its insertion");
+
+ _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED);
+ g_debug ("done");
+
+}
+
+static void
+gsd_smartcard_manager_class_install_signals (GsdSmartcardManagerClass *manager_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (manager_class);
+
+ gsd_smartcard_manager_signals[SMARTCARD_INSERTED] =
+ g_signal_new ("smartcard-inserted",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GsdSmartcardManagerClass,
+ smartcard_inserted),
+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ manager_class->smartcard_inserted = gsd_smartcard_manager_card_inserted_handler;
+
+ gsd_smartcard_manager_signals[SMARTCARD_REMOVED] =
+ g_signal_new ("smartcard-removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GsdSmartcardManagerClass,
+ smartcard_removed),
+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ manager_class->smartcard_removed = gsd_smartcard_manager_card_removed_handler;
+
+ gsd_smartcard_manager_signals[ERROR] =
+ g_signal_new ("error",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdSmartcardManagerClass, error),
+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ manager_class->error = NULL;
+}
+
+static gboolean
+slot_id_equal (CK_SLOT_ID *slot_id_1,
+ CK_SLOT_ID *slot_id_2)
+{
+ g_assert (slot_id_1 != NULL);
+ g_assert (slot_id_2 != NULL);
+
+ return *slot_id_1 == *slot_id_2;
+}
+
+static gboolean
+slot_id_hash (CK_SLOT_ID *slot_id)
+{
+ guint32 upper_bits, lower_bits;
+ int temp;
+
+ if (sizeof (CK_SLOT_ID) == sizeof (int)) {
+ return g_int_hash (slot_id);
+ }
+
+ upper_bits = ((*slot_id) >> 31) - 1;
+ lower_bits = (*slot_id) & 0xffffffff;
+
+ /* The upper bits are almost certainly always zero,
+ * so let's degenerate to g_int_hash for the
+ * (very) common case
+ */
+ temp = lower_bits + upper_bits;
+ return upper_bits + g_int_hash (&temp);
+}
+
+static void
+gsd_smartcard_manager_init (GsdSmartcardManager *manager)
+{
+ g_debug ("initializing smartcard manager");
+
+ manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
+ GSD_TYPE_SMARTCARD_MANAGER,
+ GsdSmartcardManagerPrivate);
+ manager->priv->poll_timeout_id = 0;
+ manager->priv->is_unstoppable = FALSE;
+ manager->priv->module = NULL;
+
+ manager->priv->smartcards =
+ g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ if (!g_thread_supported ()) {
+ g_thread_init (NULL);
+ }
+
+}
+
+static void
+gsd_smartcard_manager_finalize (GObject *object)
+{
+ GsdSmartcardManager *manager;
+ GObjectClass *gobject_class;
+
+ manager = GSD_SMARTCARD_MANAGER (object);
+ gobject_class =
+ G_OBJECT_CLASS (gsd_smartcard_manager_parent_class);
+
+ gsd_smartcard_manager_stop_now (manager);
+
+ g_hash_table_destroy (manager->priv->smartcards);
+ manager->priv->smartcards = NULL;
+
+ gobject_class->finalize (object);
+}
+
+GQuark
+gsd_smartcard_manager_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0) {
+ error_quark = g_quark_from_static_string ("gsd-smartcard-manager-error-quark");
+ }
+
+ return error_quark;
+}
+
+GsdSmartcardManager *
+gsd_smartcard_manager_new (const char *module_path)
+{
+ GsdSmartcardManager *instance;
+
+ instance = GSD_SMARTCARD_MANAGER (g_object_new (GSD_TYPE_SMARTCARD_MANAGER,
+ "module-path", module_path,
+ NULL));
+
+ return instance;
+}
+
+static void
+gsd_smartcard_manager_emit_error (GsdSmartcardManager *manager,
+ GError *error)
+{
+ manager->priv->is_unstoppable = TRUE;
+ g_signal_emit (manager, gsd_smartcard_manager_signals[ERROR], 0,
+ error);
+ manager->priv->is_unstoppable = FALSE;
+}
+
+static void
+gsd_smartcard_manager_emit_smartcard_inserted (GsdSmartcardManager *manager,
+ GsdSmartcard *card)
+{
+ manager->priv->is_unstoppable = TRUE;
+ g_signal_emit (manager, gsd_smartcard_manager_signals[SMARTCARD_INSERTED], 0,
+ card);
+ manager->priv->is_unstoppable = FALSE;
+}
+
+static void
+gsd_smartcard_manager_emit_smartcard_removed (GsdSmartcardManager *manager,
+ GsdSmartcard *card)
+{
+ GsdSmartcardManagerState old_state;
+
+ old_state = manager->priv->state;
+ manager->priv->is_unstoppable = TRUE;
+ g_signal_emit (manager, gsd_smartcard_manager_signals[SMARTCARD_REMOVED], 0,
+ card);
+ manager->priv->is_unstoppable = FALSE;
+}
+
+static gboolean
+gsd_smartcard_manager_check_for_and_process_events (GIOChannel *io_channel,
+ GIOCondition condition,
+ GsdSmartcardManager *manager)
+{
+ GsdSmartcard *card;
+ gboolean should_stop;
+ gchar event_type;
+ char *card_name;
+ int fd;
+
+ card = NULL;
+ should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR);
+
+ if (should_stop) {
+ g_debug ("received %s on event socket, stopping "
+ "manager...",
+ (condition & G_IO_HUP) && (condition & G_IO_ERR)?
+ "error and hangup" :
+ (condition & G_IO_HUP)?
+ "hangup" : "error");
+ }
+
+ if (!(condition & G_IO_IN)) {
+ goto out;
+ }
+
+ fd = g_io_channel_unix_get_fd (io_channel);
+
+ event_type = '\0';
+ if (!read_bytes (fd, &event_type, 1)) {
+ should_stop = TRUE;
+ goto out;
+ }
+
+ card = read_smartcard (fd, manager->priv->module);
+
+ if (card == NULL) {
+ should_stop = TRUE;
+ goto out;
+ }
+
+ card_name = gsd_smartcard_get_name (card);
+
+ switch (event_type) {
+ case 'I':
+ g_hash_table_replace (manager->priv->smartcards,
+ card_name, card);
+ card_name = NULL;
+
+ gsd_smartcard_manager_emit_smartcard_inserted (manager, card);
+ card = NULL;
+ break;
+
+ case 'R':
+ gsd_smartcard_manager_emit_smartcard_removed (manager, card);
+ if (!g_hash_table_remove (manager->priv->smartcards, card_name)) {
+ g_debug ("got removal event of unknown card!");
+ }
+ g_free (card_name);
+ card_name = NULL;
+ card = NULL;
+ break;
+
+ default:
+ g_free (card_name);
+ card_name = NULL;
+ g_object_unref (card);
+
+ should_stop = TRUE;
+ break;
+ }
+
+out:
+ if (should_stop) {
+ GError *error;
+
+ error = g_error_new (GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
+ "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source"));
+
+ gsd_smartcard_manager_emit_error (manager, error);
+ g_error_free (error);
+ gsd_smartcard_manager_stop_now (manager);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+gsd_smartcard_manager_event_processing_stopped_handler (GsdSmartcardManager *manager)
+{
+ manager->priv->smartcard_event_source = NULL;
+ gsd_smartcard_manager_stop_now (manager);
+}
+
+static gboolean
+open_pipe (int *write_fd,
+ int *read_fd)
+{
+ int pipe_fds[2] = { -1, -1 };
+
+ g_assert (write_fd != NULL);
+ g_assert (read_fd != NULL);
+
+ if (pipe (pipe_fds) < 0) {
+ return FALSE;
+ }
+
+ if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) {
+ close (pipe_fds[0]);
+ close (pipe_fds[1]);
+ return FALSE;
+ }
+
+ if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) {
+ close (pipe_fds[0]);
+ close (pipe_fds[1]);
+ return FALSE;
+ }
+
+ *read_fd = pipe_fds[0];
+ *write_fd = pipe_fds[1];
+
+ return TRUE;
+}
+
+static void
+gsd_smartcard_manager_stop_watching_for_events (GsdSmartcardManager *manager)
+{
+ if (manager->priv->smartcard_event_source != NULL) {
+ g_source_destroy (manager->priv->smartcard_event_source);
+ manager->priv->smartcard_event_source = NULL;
+ }
+
+ if (manager->priv->worker_thread != NULL) {
+ SECMOD_CancelWait (manager->priv->module);
+ manager->priv->worker_thread = NULL;
+ }
+}
+
+static gboolean
+load_nss (GError **error)
+{
+ SECStatus status = SECSuccess;
+ static const guint32 flags =
+ NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB |
+ NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT |
+ NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD;
+
+ g_debug ("attempting to load NSS database '%s'",
+ GSD_SMARTCARD_MANAGER_NSS_DB);
+
+ status = NSS_Initialize (GSD_SMARTCARD_MANAGER_NSS_DB,
+ "", "", SECMOD_DB, flags);
+
+ if (status != SECSuccess) {
+ gsize error_message_size;
+ char *error_message;
+
+ error_message_size = PR_GetErrorTextLength ();
+
+ if (error_message_size == 0) {
+ g_debug ("NSS security system could not be initialized");
+ g_set_error (error,
+ GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+ _("NSS security system could not be initialized"));
+ goto out;
+ }
+
+ error_message = g_slice_alloc0 (error_message_size);
+ PR_GetErrorText (error_message);
+
+ g_set_error (error,
+ GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+ "%s", error_message);
+ g_debug ("NSS security system could not be initialized - %s",
+ error_message);
+
+ g_slice_free1 (error_message_size, error_message);
+
+ goto out;
+ }
+
+ g_debug ("NSS database sucessfully loaded");
+ return TRUE;
+
+out:
+ g_debug ("NSS database couldn't be sucessfully loaded");
+ return FALSE;
+}
+
+static SECMODModule *
+load_driver (char *module_path,
+ GError **error)
+{
+ SECMODModule *module;
+ char *module_spec;
+ gboolean module_explicitly_specified;
+
+ g_debug ("attempting to load driver...");
+
+ module = NULL;
+ module_explicitly_specified = module_path != NULL;
+ if (module_explicitly_specified) {
+ module_spec = g_strdup_printf ("library=\"%s\"", module_path);
+ g_debug ("loading smartcard driver using spec '%s'",
+ module_spec);
+
+ module = SECMOD_LoadUserModule (module_spec,
+ NULL /* parent */,
+ FALSE /* recurse */);
+ g_free (module_spec);
+ module_spec = NULL;
+
+ } else {
+ SECMODModuleList *modules, *tmp;
+
+ modules = SECMOD_GetDefaultModuleList ();
+
+ for (tmp = modules; tmp != NULL; tmp = tmp->next) {
+ if (!SECMOD_HasRemovableSlots (tmp->module) ||
+ !tmp->module->loaded)
+ continue;
+
+ module = SECMOD_ReferenceModule (tmp->module);
+ break;
+ }
+ }
+
+ if (!module_explicitly_specified && module == NULL) {
+ g_set_error (error,
+ GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
+ _("no suitable smartcard driver could be found"));
+ } else if (module == NULL || !module->loaded) {
+
+ gsize error_message_size;
+ char *error_message;
+
+ if (module != NULL && !module->loaded) {
+ g_debug ("module found but not loaded?!");
+ SECMOD_DestroyModule (module);
+ module = NULL;
+ }
+
+ error_message_size = PR_GetErrorTextLength ();
+
+ if (error_message_size == 0) {
+ g_debug ("smartcard driver '%s' could not be loaded",
+ module_path);
+ g_set_error (error,
+ GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
+ _("smartcard driver '%s' could not be "
+ "loaded"), module_path);
+ goto out;
+ }
+
+ error_message = g_slice_alloc0 (error_message_size);
+ PR_GetErrorText (error_message);
+
+ g_set_error (error,
+ GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
+ "%s", error_message);
+
+ g_debug ("smartcard driver '%s' could not be loaded - %s",
+ module_path, error_message);
+ g_slice_free1 (error_message_size, error_message);
+ }
+
+out:
+ return module;
+}
+
+static void
+gsd_smartcard_manager_get_all_cards (GsdSmartcardManager *manager)
+{
+ int i;
+
+ for (i = 0; i < manager->priv->module->slotCount; i++) {
+ GsdSmartcard *card;
+ CK_SLOT_ID slot_id;
+ int slot_series;
+ char *card_name;
+
+ slot_id = PK11_GetSlotID (manager->priv->module->slots[i]);
+ slot_series = PK11_GetSlotSeries (manager->priv->module->slots[i]);
+
+ card = _gsd_smartcard_new (manager->priv->module,
+ slot_id, slot_series);
+
+ card_name = gsd_smartcard_get_name (card);
+
+ g_hash_table_replace (manager->priv->smartcards,
+ card_name, card);
+ }
+}
+
+gboolean
+gsd_smartcard_manager_start (GsdSmartcardManager *manager,
+ GError **error)
+{
+ GError *watching_error;
+ int worker_fd;
+ GPid worker_pid;
+ GIOChannel *io_channel;
+ GSource *source;
+ GIOFlags channel_flags;
+ GError *nss_error;
+
+ if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STARTED) {
+ g_debug ("smartcard manager already started");
+ return TRUE;
+ }
+
+ manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STARTING;
+
+ worker_fd = -1;
+ worker_pid = 0;
+
+ nss_error = NULL;
+ if (!manager->priv->nss_is_loaded && !load_nss (&nss_error)) {
+ g_propagate_error (error, nss_error);
+ goto out;
+ }
+ manager->priv->nss_is_loaded = TRUE;
+
+ if (manager->priv->module == NULL) {
+ manager->priv->module = load_driver (manager->priv->module_path, &nss_error);
+ }
+
+ if (manager->priv->module == NULL) {
+ g_propagate_error (error, nss_error);
+ goto out;
+ }
+
+ if (!gsd_smartcard_manager_create_worker (manager, &worker_fd, &manager->priv->worker_thread)) {
+
+ g_set_error (error,
+ GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
+ _("could not watch for incoming card events - %s"),
+ g_strerror (errno));
+
+ goto out;
+ }
+
+ io_channel = g_io_channel_unix_new (worker_fd);
+
+ channel_flags = g_io_channel_get_flags (io_channel);
+ watching_error = NULL;
+
+ source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP);
+ g_io_channel_unref (io_channel);
+ io_channel = NULL;
+
+ manager->priv->smartcard_event_source = source;
+
+ g_source_set_callback (manager->priv->smartcard_event_source,
+ (GSourceFunc) (GIOFunc)
+ gsd_smartcard_manager_check_for_and_process_events,
+ manager,
+ (GDestroyNotify)
+ gsd_smartcard_manager_event_processing_stopped_handler);
+ g_source_attach (manager->priv->smartcard_event_source, NULL);
+ g_source_unref (manager->priv->smartcard_event_source);
+
+ /* populate the hash with cards that are already inserted
+ */
+ gsd_smartcard_manager_get_all_cards (manager);
+
+ manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STARTED;
+
+out:
+ /* don't leave it in a half started state
+ */
+ if (manager->priv->state != GSD_SMARTCARD_MANAGER_STATE_STARTED) {
+ g_debug ("smartcard manager could not be completely started");
+ gsd_smartcard_manager_stop (manager);
+ } else {
+ g_debug ("smartcard manager started");
+ }
+
+ return manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STARTED;
+}
+
+static gboolean
+gsd_smartcard_manager_stop_now (GsdSmartcardManager *manager)
+{
+ if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STOPPED) {
+ return FALSE;
+ }
+
+ manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STOPPED;
+ gsd_smartcard_manager_stop_watching_for_events (manager);
+
+ if (manager->priv->module != NULL) {
+ SECMOD_DestroyModule (manager->priv->module);
+ manager->priv->module = NULL;
+ }
+
+ if (manager->priv->nss_is_loaded) {
+ NSS_Shutdown ();
+ manager->priv->nss_is_loaded = FALSE;
+ }
+
+ g_debug ("smartcard manager stopped");
+
+ return FALSE;
+}
+
+static void
+gsd_smartcard_manager_queue_stop (GsdSmartcardManager *manager)
+{
+
+ manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STOPPING;
+
+ g_idle_add ((GSourceFunc) gsd_smartcard_manager_stop_now, manager);
+}
+
+void
+gsd_smartcard_manager_stop (GsdSmartcardManager *manager)
+{
+ if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STOPPED) {
+ return;
+ }
+
+ if (manager->priv->is_unstoppable) {
+ gsd_smartcard_manager_queue_stop (manager);
+ return;
+ }
+
+ gsd_smartcard_manager_stop_now (manager);
+}
+
+static void
+gsd_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id,
+ GsdSmartcard *card,
+ gboolean *is_inserted)
+{
+ g_assert (is_inserted != NULL);
+
+ if (gsd_smartcard_is_login_card (card)) {
+ *is_inserted = TRUE;
+ }
+
+}
+
+gboolean
+gsd_smartcard_manager_login_card_is_inserted (GsdSmartcardManager *manager)
+
+{
+ gboolean is_inserted;
+
+ is_inserted = FALSE;
+ g_hash_table_foreach (manager->priv->smartcards,
+ (GHFunc)
+ gsd_smartcard_manager_check_for_login_card,
+ &is_inserted);
+ return is_inserted;
+}
+
+static GsdSmartcardManagerWorker *
+gsd_smartcard_manager_worker_new (int write_fd)
+{
+ GsdSmartcardManagerWorker *worker;
+
+ worker = g_slice_new0 (GsdSmartcardManagerWorker);
+ worker->write_fd = write_fd;
+ worker->module = NULL;
+
+ worker->smartcards =
+ g_hash_table_new_full ((GHashFunc) slot_id_hash,
+ (GEqualFunc) slot_id_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ return worker;
+}
+
+static void
+gsd_smartcard_manager_worker_free (GsdSmartcardManagerWorker *worker)
+{
+ if (worker->smartcards != NULL) {
+ g_hash_table_destroy (worker->smartcards);
+ worker->smartcards = NULL;
+ }
+
+ g_slice_free (GsdSmartcardManagerWorker, worker);
+}
+
+static gboolean
+read_bytes (int fd,
+ gpointer bytes,
+ gsize num_bytes)
+{
+ size_t bytes_left;
+ size_t total_bytes_read;
+ ssize_t bytes_read;
+
+ bytes_left = (size_t) num_bytes;
+ total_bytes_read = 0;
+
+ do {
+ bytes_read = read (fd,
+ (char *) bytes + total_bytes_read,
+ bytes_left);
+ g_assert (bytes_read <= (ssize_t) bytes_left);
+
+ if (bytes_read <= 0) {
+ if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN)) {
+ continue;
+ }
+
+ bytes_left = 0;
+ } else {
+ bytes_left -= bytes_read;
+ total_bytes_read += bytes_read;
+ }
+ } while (bytes_left > 0);
+
+ if (total_bytes_read < (size_t) num_bytes) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+write_bytes (int fd,
+ gconstpointer bytes,
+ gsize num_bytes)
+{
+ size_t bytes_left;
+ size_t total_bytes_written;
+ ssize_t bytes_written;
+
+ bytes_left = (size_t) num_bytes;
+ total_bytes_written = 0;
+
+ do {
+ bytes_written = write (fd,
+ (char *) bytes + total_bytes_written,
+ bytes_left);
+ g_assert (bytes_written <= (ssize_t) bytes_left);
+
+ if (bytes_written <= 0) {
+ if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN)) {
+ continue;
+ }
+
+ bytes_left = 0;
+ } else {
+ bytes_left -= bytes_written;
+ total_bytes_written += bytes_written;
+ }
+ } while (bytes_left > 0);
+
+ if (total_bytes_written < (size_t) num_bytes) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GsdSmartcard *
+read_smartcard (int fd,
+ SECMODModule *module)
+{
+ GsdSmartcard *card;
+ char *card_name;
+ gsize card_name_size;
+
+ card_name_size = 0;
+ if (!read_bytes (fd, &card_name_size, sizeof (card_name_size))) {
+ return NULL;
+ }
+
+ card_name = g_slice_alloc0 (card_name_size);
+ if (!read_bytes (fd, card_name, card_name_size)) {
+ g_slice_free1 (card_name_size, card_name);
+ return NULL;
+ }
+ card = _gsd_smartcard_new_from_name (module, card_name);
+ g_slice_free1 (card_name_size, card_name);
+
+ return card;
+}
+
+static gboolean
+write_smartcard (int fd,
+ GsdSmartcard *card)
+{
+ gsize card_name_size;
+ char *card_name;
+
+ card_name = gsd_smartcard_get_name (card);
+ card_name_size = strlen (card_name) + 1;
+
+ if (!write_bytes (fd, &card_name_size, sizeof (card_name_size))) {
+ g_free (card_name);
+ return FALSE;
+ }
+
+ if (!write_bytes (fd, card_name, card_name_size)) {
+ g_free (card_name);
+ return FALSE;
+ }
+ g_free (card_name);
+
+ return TRUE;
+}
+
+static gboolean
+gsd_smartcard_manager_worker_emit_smartcard_removed (GsdSmartcardManagerWorker *worker,
+ GsdSmartcard *card,
+ GError **error)
+{
+ g_debug ("card '%s' removed!", gsd_smartcard_get_name (card));
+
+ if (!write_bytes (worker->write_fd, "R", 1)) {
+ goto error_out;
+ }
+
+ if (!write_smartcard (worker->write_fd, card)) {
+ goto error_out;
+ }
+
+ return TRUE;
+
+error_out:
+ g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS,
+ "%s", g_strerror (errno));
+ return FALSE;
+}
+
+static gboolean
+gsd_smartcard_manager_worker_emit_smartcard_inserted (GsdSmartcardManagerWorker *worker,
+ GsdSmartcard *card,
+ GError **error)
+{
+ GError *write_error;
+
+ write_error = NULL;
+ g_debug ("card '%s' inserted!", gsd_smartcard_get_name (card));
+ if (!write_bytes (worker->write_fd, "I", 1)) {
+ goto error_out;
+ }
+
+ if (!write_smartcard (worker->write_fd, card)) {
+ goto error_out;
+ }
+
+ return TRUE;
+
+error_out:
+ g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS,
+ "%s", g_strerror (errno));
+ return FALSE;
+}
+
+static gboolean
+gsd_smartcard_manager_worker_watch_for_and_process_event (GsdSmartcardManagerWorker *worker,
+ GError **error)
+{
+ PK11SlotInfo *slot;
+ CK_SLOT_ID slot_id, *key;
+ int slot_series, card_slot_series;
+ GsdSmartcard *card;
+ GError *processing_error;
+ gboolean ret;
+
+ g_debug ("waiting for card event");
+ ret = FALSE;
+
+ slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1));
+ processing_error = NULL;
+
+ if (slot == NULL) {
+ int error_code;
+
+ error_code = PORT_GetError ();
+ if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) {
+ g_debug ("spurrious event occurred");
+ return TRUE;
+ }
+
+ /* FIXME: is there a function to convert from a PORT error
+ * code to a translated string?
+ */
+ g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR,
+ GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+ _("encountered unexpected error while "
+ "waiting for smartcard events"));
+ goto out;
+ }
+
+ /* the slot id and series together uniquely identify a card.
+ * You can never have two cards with the same slot id at the
+ * same time, however (I think), so we can key off of it.
+ */
+ slot_id = PK11_GetSlotID (slot);
+ slot_series = PK11_GetSlotSeries (slot);
+
+ /* First check to see if there is a card that we're currently
+ * tracking in the slot.
+ */
+ key = g_new (CK_SLOT_ID, 1);
+ *key = slot_id;
+ card = g_hash_table_lookup (worker->smartcards, key);
+
+ if (card != NULL) {
+ card_slot_series = gsd_smartcard_get_slot_series (card);
+ } else {
+ card_slot_series = -1;
+ }
+
+ if (PK11_IsPresent (slot)) {
+ /* Now, check to see if their is a new card in the slot.
+ * If there was a different card in the slot now than
+ * there was before, then we need to emit a removed signal
+ * for the old card (we don't want unpaired insertion events).
+ */
+ if ((card != NULL) &&
+ card_slot_series != slot_series) {
+ if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) {
+ g_propagate_error (error, processing_error);
+ goto out;
+ }
+ }
+
+ card = _gsd_smartcard_new (worker->module,
+ slot_id, slot_series);
+
+ g_hash_table_replace (worker->smartcards,
+ key, card);
+ key = NULL;
+
+ if (!gsd_smartcard_manager_worker_emit_smartcard_inserted (worker,
+ card,
+ &processing_error)) {
+ g_propagate_error (error, processing_error);
+ goto out;
+ }
+ } else {
+ /* if we aren't tracking the card, just discard the event.
+ * We don't want unpaired remove events. Note on startup
+ * NSS will generate an "insertion" event if a card is
+ * already inserted in the slot.
+ */
+ if ((card != NULL)) {
+ /* FIXME: i'm not sure about this code. Maybe we
+ * shouldn't do this at all, or maybe we should do it
+ * n times (where n = slot_series - card_slot_series + 1)
+ *
+ * Right now, i'm just doing it once.
+ */
+ if ((slot_series - card_slot_series) > 1) {
+
+ if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) {
+ g_propagate_error (error, processing_error);
+ goto out;
+ }
+ g_hash_table_remove (worker->smartcards, key);
+
+ card = _gsd_smartcard_new (worker->module,
+ slot_id, slot_series);
+ g_hash_table_replace (worker->smartcards,
+ key, card);
+ key = NULL;
+ if (!gsd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) {
+ g_propagate_error (error, processing_error);
+ goto out;
+ }
+ }
+
+ if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) {
+ g_propagate_error (error, processing_error);
+ goto out;
+ }
+
+ g_hash_table_remove (worker->smartcards, key);
+ card = NULL;
+ } else {
+ g_debug ("got spurious remove event");
+ }
+ }
+
+ ret = TRUE;
+
+out:
+ g_free (key);
+ PK11_FreeSlot (slot);
+
+ return ret;
+}
+
+static void
+gsd_smartcard_manager_worker_run (GsdSmartcardManagerWorker *worker)
+{
+ GError *error;
+
+
+ error = NULL;
+
+ while (gsd_smartcard_manager_worker_watch_for_and_process_event (worker, &error));
+
+ if (error != NULL) {
+ g_debug ("could not process card event - %s", error->message);
+ g_error_free (error);
+ }
+
+ gsd_smartcard_manager_worker_free (worker);
+}
+
+static gboolean
+gsd_smartcard_manager_create_worker (GsdSmartcardManager *manager,
+ int *worker_fd,
+ GThread **worker_thread)
+{
+ GsdSmartcardManagerWorker *worker;
+ int write_fd, read_fd;
+
+ write_fd = -1;
+ read_fd = -1;
+ if (!open_pipe (&write_fd, &read_fd)) {
+ return FALSE;
+ }
+
+ worker = gsd_smartcard_manager_worker_new (write_fd);
+ worker->module = manager->priv->module;
+
+ *worker_thread = g_thread_create ((GThreadFunc)
+ gsd_smartcard_manager_worker_run,
+ worker, FALSE, NULL);
+
+ if (*worker_thread == NULL) {
+ gsd_smartcard_manager_worker_free (worker);
+ return FALSE;
+ }
+
+ if (worker_fd) {
+ *worker_fd = read_fd;
+ }
+
+ return TRUE;
+}
+
+#ifdef GSD_SMARTCARD_MANAGER_ENABLE_TEST
+#include <glib.h>
+
+static GMainLoop *event_loop;
+static gboolean should_exit_on_next_remove = FALSE;
+
+static gboolean
+on_timeout (GsdSmartcardManager *manager)
+{
+ GError *error;
+ g_print ("Re-enabling manager.\n");
+
+ if (!gsd_smartcard_manager_start (manager, &error)) {
+ g_warning ("could not start smartcard manager - %s",
+ error->message);
+ g_error_free (error);
+ return 1;
+ }
+ g_print ("Please re-insert smartcard\n");
+
+ should_exit_on_next_remove = TRUE;
+
+ return FALSE;
+}
+
+static void
+on_device_inserted (GsdSmartcardManager *manager,
+ GsdSmartcard *card)
+{
+ g_print ("smartcard inserted!\n");
+ g_print ("Please remove it.\n");
+}
+
+static void
+on_device_removed (GsdSmartcardManager *manager,
+ GsdSmartcard *card)
+{
+ g_print ("smartcard removed!\n");
+
+ if (should_exit_on_next_remove) {
+ g_main_loop_quit (event_loop);
+ } else {
+ g_print ("disabling manager for 2 seconds\n");
+ gsd_smartcard_manager_stop (manager);
+ g_timeout_add (2000, (GSourceFunc) on_timeout, manager);
+ }
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ GsdSmartcardManager *manager;
+ GError *error;
+
+ g_log_set_always_fatal (G_LOG_LEVEL_ERROR
+ | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
+ g_type_init ();
+
+ g_message ("creating instance of 'smartcard manager' object...");
+ manager = gsd_smartcard_manager_new (NULL);
+ g_message ("'smartcard manager' object created successfully");
+
+ g_signal_connect (manager, "smartcard-inserted",
+ G_CALLBACK (on_device_inserted), NULL);
+
+ g_signal_connect (manager, "smartcard-removed",
+ G_CALLBACK (on_device_removed), NULL);
+
+ g_message ("starting listener...");
+
+ error = NULL;
+ if (!gsd_smartcard_manager_start (manager, &error)) {
+ g_warning ("could not start smartcard manager - %s",
+ error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ event_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (event_loop);
+ g_main_loop_unref (event_loop);
+ event_loop = NULL;
+
+ g_message ("destroying previously created 'smartcard manager' object...");
+ g_object_unref (manager);
+ manager = NULL;
+ g_message ("'smartcard manager' object destroyed successfully");
+
+ return 0;
+}
+#endif
diff --git a/plugins/smartcard/gsd-smartcard-manager.h b/plugins/smartcard/gsd-smartcard-manager.h
new file mode 100644
index 0000000..9663124
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-manager.h
@@ -0,0 +1,90 @@
+/* gsd-smartcard-manager.h - object for monitoring smartcard insertion and
+ * removal events
+ *
+ * Copyright (C) 2006, 2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode
+ */
+#ifndef GSD_SMARTCARD_MANAGER_H
+#define GSD_SMARTCARD_MANAGER_H
+
+#define GSD_SMARTCARD_ENABLE_INTERNAL_API
+#include "gsd-smartcard.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define GSD_TYPE_SMARTCARD_MANAGER (gsd_smartcard_manager_get_type ())
+#define GSD_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManager))
+#define GSD_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass))
+#define GSD_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER))
+#define GSD_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER))
+#define GSD_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass))
+#define GSD_SMARTCARD_MANAGER_ERROR (gsd_smartcard_manager_error_quark ())
+typedef struct _GsdSmartcardManager GsdSmartcardManager;
+typedef struct _GsdSmartcardManagerClass GsdSmartcardManagerClass;
+typedef struct _GsdSmartcardManagerPrivate GsdSmartcardManagerPrivate;
+typedef enum _GsdSmartcardManagerError GsdSmartcardManagerError;
+
+struct _GsdSmartcardManager {
+ GObject parent;
+
+ /*< private > */
+ GsdSmartcardManagerPrivate *priv;
+};
+
+struct _GsdSmartcardManagerClass {
+ GObjectClass parent_class;
+
+ /* Signals */
+ void (*smartcard_inserted) (GsdSmartcardManager *manager,
+ GsdSmartcard *token);
+ void (*smartcard_removed) (GsdSmartcardManager *manager,
+ GsdSmartcard *token);
+ void (*error) (GsdSmartcardManager *manager,
+ GError *error);
+};
+
+enum _GsdSmartcardManagerError {
+ GSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0,
+ GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+ GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
+ GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
+ GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS
+};
+
+GType gsd_smartcard_manager_get_type (void) G_GNUC_CONST;
+GQuark gsd_smartcard_manager_error_quark (void) G_GNUC_CONST;
+
+GsdSmartcardManager *gsd_smartcard_manager_new (const char *module);
+
+gboolean gsd_smartcard_manager_start (GsdSmartcardManager *manager,
+ GError **error);
+
+void gsd_smartcard_manager_stop (GsdSmartcardManager *manager);
+
+char *gsd_smartcard_manager_get_module_path (GsdSmartcardManager *manager);
+gboolean gsd_smartcard_manager_login_card_is_inserted (GsdSmartcardManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GSD_SMARTCARD_MANAGER_H */
diff --git a/plugins/smartcard/gsd-smartcard-plugin.c b/plugins/smartcard/gsd-smartcard-plugin.c
new file mode 100644
index 0000000..9e3b4f2
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-plugin.c
@@ -0,0 +1,340 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-smartcard-plugin.h"
+#include "gsd-smartcard-manager.h"
+
+struct GsdSmartcardPluginPrivate {
+ GsdSmartcardManager *manager;
+ DBusGConnection *bus_connection;
+
+ guint32 is_active : 1;
+};
+
+typedef enum
+{
+ GSD_SMARTCARD_REMOVE_ACTION_NONE,
+ GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN,
+ GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT,
+} GsdSmartcardRemoveAction;
+
+#define SCREENSAVER_DBUS_NAME "org.mate.ScreenSaver"
+#define SCREENSAVER_DBUS_PATH "/"
+#define SCREENSAVER_DBUS_INTERFACE "org.mate.ScreenSaver"
+
+#define SM_DBUS_NAME "org.mate.SessionManager"
+#define SM_DBUS_PATH "/org/mate/SessionManager"
+#define SM_DBUS_INTERFACE "org.mate.SessionManager"
+#define SM_LOGOUT_MODE_FORCE 2
+
+#define GSD_SMARTCARD_KEY "/desktop/mate/peripherals/smartcard"
+#define KEY_REMOVE_ACTION GSD_SMARTCARD_KEY "/removal_action"
+
+#define GSD_SMARTCARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdSmartcardPlugin, gsd_smartcard_plugin);
+
+static void
+simulate_user_activity (GsdSmartcardPlugin *plugin)
+{
+ DBusGProxy *screensaver_proxy;
+
+ g_debug ("GsdSmartcardPlugin telling screensaver about smart card insertion");
+ screensaver_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection,
+ SCREENSAVER_DBUS_NAME,
+ SCREENSAVER_DBUS_PATH,
+ SCREENSAVER_DBUS_INTERFACE);
+
+ dbus_g_proxy_call_no_reply (screensaver_proxy,
+ "SimulateUserActivity",
+ G_TYPE_INVALID, G_TYPE_INVALID);
+
+ g_object_unref (screensaver_proxy);
+}
+
+static void
+lock_screen (GsdSmartcardPlugin *plugin)
+{
+ DBusGProxy *screensaver_proxy;
+
+ g_debug ("GsdSmartcardPlugin telling screensaver to lock screen");
+ screensaver_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection,
+ SCREENSAVER_DBUS_NAME,
+ SCREENSAVER_DBUS_PATH,
+ SCREENSAVER_DBUS_INTERFACE);
+
+ dbus_g_proxy_call_no_reply (screensaver_proxy,
+ "Lock",
+ G_TYPE_INVALID, G_TYPE_INVALID);
+
+ g_object_unref (screensaver_proxy);
+}
+
+static void
+force_logout (GsdSmartcardPlugin *plugin)
+{
+ DBusGProxy *sm_proxy;
+ GError *error;
+ gboolean res;
+
+ g_debug ("GsdSmartcardPlugin telling session manager to force logout");
+ sm_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection,
+ SM_DBUS_NAME,
+ SM_DBUS_PATH,
+ SM_DBUS_INTERFACE);
+
+ error = NULL;
+ res = dbus_g_proxy_call (sm_proxy,
+ "Logout",
+ &error,
+ G_TYPE_UINT, SM_LOGOUT_MODE_FORCE,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+
+ if (! res) {
+ g_warning ("GsdSmartcardPlugin Unable to force logout: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (sm_proxy);
+}
+
+static void
+gsd_smartcard_plugin_init (GsdSmartcardPlugin *plugin)
+{
+ plugin->priv = GSD_SMARTCARD_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdSmartcardPlugin initializing");
+
+ plugin->priv->manager = gsd_smartcard_manager_new (NULL);
+}
+
+static void
+gsd_smartcard_plugin_finalize (GObject *object)
+{
+ GsdSmartcardPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_SMARTCARD_PLUGIN (object));
+
+ g_debug ("GsdSmartcardPlugin finalizing");
+
+ plugin = GSD_SMARTCARD_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_smartcard_plugin_parent_class)->finalize (object);
+}
+
+static void
+smartcard_inserted_cb (GsdSmartcardManager *card_monitor,
+ GsdSmartcard *card,
+ GsdSmartcardPlugin *plugin)
+{
+ char *name;
+
+ name = gsd_smartcard_get_name (card);
+ g_debug ("GsdSmartcardPlugin smart card '%s' inserted", name);
+ g_free (name);
+
+ simulate_user_activity (plugin);
+}
+
+static gboolean
+user_logged_in_with_smartcard (void)
+{
+ return g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL;
+}
+
+static GsdSmartcardRemoveAction
+get_configured_remove_action (GsdSmartcardPlugin *plugin)
+{
+ MateConfClient *client;
+ char *remove_action_string;
+ GsdSmartcardRemoveAction remove_action;
+
+ client = mateconf_client_get_default ();
+ remove_action_string = mateconf_client_get_string (client,
+ KEY_REMOVE_ACTION, NULL);
+
+ if (remove_action_string == NULL) {
+ g_warning ("GsdSmartcardPlugin unable to get smartcard remove action");
+ remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE;
+ } else if (strcmp (remove_action_string, "none") == 0) {
+ remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE;
+ } else if (strcmp (remove_action_string, "lock_screen") == 0) {
+ remove_action = GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN;
+ } else if (strcmp (remove_action_string, "force_logout") == 0) {
+ remove_action = GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT;
+ } else {
+ g_warning ("GsdSmartcardPlugin unknown smartcard remove action");
+ remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE;
+ }
+
+ g_object_unref (client);
+
+ return remove_action;
+}
+
+static void
+process_smartcard_removal (GsdSmartcardPlugin *plugin)
+{
+ GsdSmartcardRemoveAction remove_action;
+
+ g_debug ("GsdSmartcardPlugin processing smartcard removal");
+ remove_action = get_configured_remove_action (plugin);
+
+ switch (remove_action)
+ {
+ case GSD_SMARTCARD_REMOVE_ACTION_NONE:
+ return;
+ case GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN:
+ lock_screen (plugin);
+ break;
+ case GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT:
+ force_logout (plugin);
+ break;
+ }
+}
+
+static void
+smartcard_removed_cb (GsdSmartcardManager *card_monitor,
+ GsdSmartcard *card,
+ GsdSmartcardPlugin *plugin)
+{
+
+ char *name;
+
+ name = gsd_smartcard_get_name (card);
+ g_debug ("GsdSmartcardPlugin smart card '%s' removed", name);
+ g_free (name);
+
+ if (!gsd_smartcard_is_login_card (card)) {
+ g_debug ("GsdSmartcardPlugin removed smart card was not used to login");
+ return;
+ }
+
+ process_smartcard_removal (plugin);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ GError *error;
+ GsdSmartcardPlugin *smartcard_plugin = GSD_SMARTCARD_PLUGIN (plugin);
+
+ if (smartcard_plugin->priv->is_active) {
+ g_debug ("GsdSmartcardPlugin Not activating smartcard plugin, because it's "
+ "already active");
+ return;
+ }
+
+ if (!user_logged_in_with_smartcard ()) {
+ g_debug ("GsdSmartcardPlugin Not activating smartcard plugin, because user didn't use "
+ " smartcard to log in");
+ smartcard_plugin->priv->is_active = FALSE;
+ return;
+ }
+
+ g_debug ("GsdSmartcardPlugin Activating smartcard plugin");
+
+ error = NULL;
+ smartcard_plugin->priv->bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (smartcard_plugin->priv->bus_connection == NULL) {
+ g_warning ("GsdSmartcardPlugin Unable to connect to session bus: %s", error->message);
+ return;
+ }
+
+ if (!gsd_smartcard_manager_start (smartcard_plugin->priv->manager, &error)) {
+ g_warning ("GsdSmartcardPlugin Unable to start smartcard manager: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_signal_connect (smartcard_plugin->priv->manager,
+ "smartcard-removed",
+ G_CALLBACK (smartcard_removed_cb), smartcard_plugin);
+
+ g_signal_connect (smartcard_plugin->priv->manager,
+ "smartcard-inserted",
+ G_CALLBACK (smartcard_inserted_cb), smartcard_plugin);
+
+ if (!gsd_smartcard_manager_login_card_is_inserted (smartcard_plugin->priv->manager)) {
+ g_debug ("GsdSmartcardPlugin processing smartcard removal immediately user logged in with smartcard "
+ "and it's not inserted");
+ process_smartcard_removal (smartcard_plugin);
+ }
+
+ smartcard_plugin->priv->is_active = TRUE;
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ GsdSmartcardPlugin *smartcard_plugin = GSD_SMARTCARD_PLUGIN (plugin);
+
+ if (!smartcard_plugin->priv->is_active) {
+ g_debug ("GsdSmartcardPlugin Not deactivating smartcard plugin, "
+ "because it's already inactive");
+ return;
+ }
+
+ g_debug ("GsdSmartcardPlugin Deactivating smartcard plugin");
+
+ gsd_smartcard_manager_stop (smartcard_plugin->priv->manager);
+
+ g_signal_handlers_disconnect_by_func (smartcard_plugin->priv->manager,
+ smartcard_removed_cb, smartcard_plugin);
+
+ g_signal_handlers_disconnect_by_func (smartcard_plugin->priv->manager,
+ smartcard_inserted_cb, smartcard_plugin);
+ smartcard_plugin->priv->bus_connection = NULL;
+ smartcard_plugin->priv->is_active = FALSE;
+}
+
+static void
+gsd_smartcard_plugin_class_init (GsdSmartcardPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_smartcard_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdSmartcardPluginPrivate));
+}
diff --git a/plugins/smartcard/gsd-smartcard-plugin.h b/plugins/smartcard/gsd-smartcard-plugin.h
new file mode 100644
index 0000000..4c61686
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_SMARTCARD_PLUGIN_H__
+#define __GSD_SMARTCARD_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_SMARTCARD_PLUGIN (gsd_smartcard_plugin_get_type ())
+#define GSD_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPlugin))
+#define GSD_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginClass))
+#define GSD_IS_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SMARTCARD_PLUGIN))
+#define GSD_IS_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SMARTCARD_PLUGIN))
+#define GSD_SMARTCARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginClass))
+
+typedef struct GsdSmartcardPluginPrivate GsdSmartcardPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdSmartcardPluginPrivate *priv;
+} GsdSmartcardPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdSmartcardPluginClass;
+
+GType gsd_smartcard_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_SMARTCARD_PLUGIN_H__ */
diff --git a/plugins/smartcard/gsd-smartcard.c b/plugins/smartcard/gsd-smartcard.c
new file mode 100644
index 0000000..22f4e12
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard.c
@@ -0,0 +1,555 @@
+/* gsd-smartcard.c - smartcard object
+ *
+ * Copyright (C) 2006 Ray Strode <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#define GSD_SMARTCARD_ENABLE_INTERNAL_API
+#include "gsd-smartcard.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <cert.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <prerror.h>
+#include <secmod.h>
+#include <secerr.h>
+
+struct _GsdSmartcardPrivate {
+ SECMODModule *module;
+ GsdSmartcardState state;
+
+ CK_SLOT_ID slot_id;
+ int slot_series;
+
+ PK11SlotInfo *slot;
+ char *name;
+
+ CERTCertificate *signing_certificate;
+ CERTCertificate *encryption_certificate;
+};
+
+static void gsd_smartcard_finalize (GObject *object);
+static void gsd_smartcard_class_install_signals (GsdSmartcardClass *card_class);
+static void gsd_smartcard_class_install_properties (GsdSmartcardClass *card_class);
+static void gsd_smartcard_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gsd_smartcard_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gsd_smartcard_set_name (GsdSmartcard *card, const char *name);
+static void gsd_smartcard_set_slot_id (GsdSmartcard *card,
+ int slot_id);
+static void gsd_smartcard_set_slot_series (GsdSmartcard *card,
+ int slot_series);
+static void gsd_smartcard_set_module (GsdSmartcard *card,
+ SECMODModule *module);
+
+static PK11SlotInfo *gsd_smartcard_find_slot_from_id (GsdSmartcard *card,
+ int slot_id);
+
+static PK11SlotInfo *gsd_smartcard_find_slot_from_card_name (GsdSmartcard *card,
+ const char *card_name);
+#ifndef GSD_SMARTCARD_DEFAULT_SLOT_ID
+#define GSD_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1)
+#endif
+
+#ifndef GSD_SMARTCARD_DEFAULT_SLOT_SERIES
+#define GSD_SMARTCARD_DEFAULT_SLOT_SERIES -1
+#endif
+
+enum {
+ PROP_0 = 0,
+ PROP_NAME,
+ PROP_SLOT_ID,
+ PROP_SLOT_SERIES,
+ PROP_MODULE,
+ NUMBER_OF_PROPERTIES
+};
+
+enum {
+ INSERTED,
+ REMOVED,
+ NUMBER_OF_SIGNALS
+};
+
+static guint gsd_smartcard_signals[NUMBER_OF_SIGNALS];
+
+G_DEFINE_TYPE (GsdSmartcard, gsd_smartcard, G_TYPE_OBJECT);
+
+static void
+gsd_smartcard_class_init (GsdSmartcardClass *card_class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (card_class);
+
+ gobject_class->finalize = gsd_smartcard_finalize;
+
+ gsd_smartcard_class_install_signals (card_class);
+ gsd_smartcard_class_install_properties (card_class);
+
+ g_type_class_add_private (card_class,
+ sizeof (GsdSmartcardPrivate));
+}
+
+static void
+gsd_smartcard_class_install_signals (GsdSmartcardClass *card_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (card_class);
+
+ gsd_smartcard_signals[INSERTED] =
+ g_signal_new ("inserted",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdSmartcardClass,
+ inserted),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ gsd_smartcard_signals[REMOVED] =
+ g_signal_new ("removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdSmartcardClass,
+ removed),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gsd_smartcard_class_install_properties (GsdSmartcardClass *card_class)
+{
+ GObjectClass *object_class;
+ GParamSpec *param_spec;
+
+ object_class = G_OBJECT_CLASS (card_class);
+ object_class->set_property = gsd_smartcard_set_property;
+ object_class->get_property = gsd_smartcard_get_property;
+
+ param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"),
+ _("The slot the card is in"),
+ 1, G_MAXULONG,
+ GSD_SMARTCARD_DEFAULT_SLOT_ID,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec);
+
+ param_spec = g_param_spec_int ("slot-series", _("Slot Series"),
+ _("per-slot card identifier"),
+ -1, G_MAXINT,
+ GSD_SMARTCARD_DEFAULT_SLOT_SERIES,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec);
+
+ param_spec = g_param_spec_string ("name", _("name"),
+ _("name"), NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_NAME, param_spec);
+
+ param_spec = g_param_spec_pointer ("module", _("Module"),
+ _("smartcard driver"),
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_MODULE, param_spec);
+}
+
+static void
+gsd_smartcard_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdSmartcard *card = GSD_SMARTCARD (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ gsd_smartcard_set_name (card, g_value_get_string (value));
+ break;
+
+ case PROP_SLOT_ID:
+ gsd_smartcard_set_slot_id (card,
+ g_value_get_ulong (value));
+ break;
+
+ case PROP_SLOT_SERIES:
+ gsd_smartcard_set_slot_series (card,
+ g_value_get_int (value));
+ break;
+
+ case PROP_MODULE:
+ gsd_smartcard_set_module (card,
+ (SECMODModule *)
+ g_value_get_pointer (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+CK_SLOT_ID
+gsd_smartcard_get_slot_id (GsdSmartcard *card)
+{
+ return card->priv->slot_id;
+}
+
+GsdSmartcardState
+gsd_smartcard_get_state (GsdSmartcard *card)
+{
+ return card->priv->state;
+}
+
+char *
+gsd_smartcard_get_name (GsdSmartcard *card)
+{
+ return g_strdup (card->priv->name);
+}
+
+gboolean
+gsd_smartcard_is_login_card (GsdSmartcard *card)
+{
+ const char *login_card_name;
+ login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME");
+
+ if ((login_card_name == NULL) || (card->priv->name == NULL)) {
+ return FALSE;
+ }
+
+ if (strcmp (card->priv->name, login_card_name) == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gsd_smartcard_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdSmartcard *card = GSD_SMARTCARD (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_take_string (value,
+ gsd_smartcard_get_name (card));
+ break;
+
+ case PROP_SLOT_ID:
+ g_value_set_ulong (value,
+ (gulong) gsd_smartcard_get_slot_id (card));
+ break;
+
+ case PROP_SLOT_SERIES:
+ g_value_set_int (value,
+ gsd_smartcard_get_slot_series (card));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gsd_smartcard_set_name (GsdSmartcard *card,
+ const char *name)
+{
+ if (name == NULL) {
+ return;
+ }
+
+ if ((card->priv->name == NULL) ||
+ (strcmp (card->priv->name, name) != 0)) {
+ g_free (card->priv->name);
+ card->priv->name = g_strdup (name);
+
+ if (card->priv->slot == NULL) {
+ card->priv->slot = gsd_smartcard_find_slot_from_card_name (card,
+ card->priv->name);
+
+ if (card->priv->slot != NULL) {
+ int slot_id, slot_series;
+
+ slot_id = PK11_GetSlotID (card->priv->slot);
+ if (slot_id != card->priv->slot_id) {
+ gsd_smartcard_set_slot_id (card, slot_id);
+ }
+
+ slot_series = PK11_GetSlotSeries (card->priv->slot);
+ if (slot_series != card->priv->slot_series) {
+ gsd_smartcard_set_slot_series (card, slot_series);
+ }
+
+ _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED);
+ } else {
+ _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED);
+ }
+ }
+
+ g_object_notify (G_OBJECT (card), "name");
+ }
+}
+
+static void
+gsd_smartcard_set_slot_id (GsdSmartcard *card,
+ int slot_id)
+{
+ if (card->priv->slot_id != slot_id) {
+ card->priv->slot_id = slot_id;
+
+ if (card->priv->slot == NULL) {
+ card->priv->slot = gsd_smartcard_find_slot_from_id (card,
+ card->priv->slot_id);
+
+ if (card->priv->slot != NULL) {
+ const char *card_name;
+
+ card_name = PK11_GetTokenName (card->priv->slot);
+ if ((card->priv->name == NULL) ||
+ ((card_name != NULL) &&
+ (strcmp (card_name, card->priv->name) != 0))) {
+ gsd_smartcard_set_name (card, card_name);
+ }
+
+ _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED);
+ } else {
+ _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED);
+ }
+ }
+
+ g_object_notify (G_OBJECT (card), "slot-id");
+ }
+}
+
+static void
+gsd_smartcard_set_slot_series (GsdSmartcard *card,
+ int slot_series)
+{
+ if (card->priv->slot_series != slot_series) {
+ card->priv->slot_series = slot_series;
+ g_object_notify (G_OBJECT (card), "slot-series");
+ }
+}
+
+static void
+gsd_smartcard_set_module (GsdSmartcard *card,
+ SECMODModule *module)
+{
+ gboolean should_notify;
+
+ if (card->priv->module != module) {
+ should_notify = TRUE;
+ } else {
+ should_notify = FALSE;
+ }
+
+ if (card->priv->module != NULL) {
+ SECMOD_DestroyModule (card->priv->module);
+ card->priv->module = NULL;
+ }
+
+ if (module != NULL) {
+ card->priv->module = SECMOD_ReferenceModule (module);
+ }
+
+ if (should_notify) {
+ g_object_notify (G_OBJECT (card), "module");
+ }
+}
+
+int
+gsd_smartcard_get_slot_series (GsdSmartcard *card)
+{
+ return card->priv->slot_series;
+}
+
+static void
+gsd_smartcard_init (GsdSmartcard *card)
+{
+
+ g_debug ("initializing smartcard ");
+
+ card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card,
+ GSD_TYPE_SMARTCARD,
+ GsdSmartcardPrivate);
+
+ if (card->priv->slot != NULL) {
+ card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot));
+ }
+}
+
+static void gsd_smartcard_finalize (GObject *object)
+{
+ GsdSmartcard *card;
+ GObjectClass *gobject_class;
+
+ card = GSD_SMARTCARD (object);
+
+ g_free (card->priv->name);
+
+ gsd_smartcard_set_module (card, NULL);
+
+ gobject_class = G_OBJECT_CLASS (gsd_smartcard_parent_class);
+
+ gobject_class->finalize (object);
+}
+
+GQuark gsd_smartcard_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0) {
+ error_quark = g_quark_from_static_string ("gsd-smartcard-error-quark");
+ }
+
+ return error_quark;
+}
+
+GsdSmartcard *
+_gsd_smartcard_new (SECMODModule *module,
+ CK_SLOT_ID slot_id,
+ int slot_series)
+{
+ GsdSmartcard *card;
+
+ g_return_val_if_fail (module != NULL, NULL);
+ g_return_val_if_fail (slot_id >= 1, NULL);
+ g_return_val_if_fail (slot_series > 0, NULL);
+ g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL);
+
+ card = GSD_SMARTCARD (g_object_new (GSD_TYPE_SMARTCARD,
+ "module", module,
+ "slot-id", (gulong) slot_id,
+ "slot-series", slot_series,
+ NULL));
+ return card;
+}
+
+GsdSmartcard *
+_gsd_smartcard_new_from_name (SECMODModule *module,
+ const char *name)
+{
+ GsdSmartcard *card;
+
+ g_return_val_if_fail (module != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ card = GSD_SMARTCARD (g_object_new (GSD_TYPE_SMARTCARD,
+ "module", module,
+ "name", name,
+ NULL));
+ return card;
+}
+
+void
+_gsd_smartcard_set_state (GsdSmartcard *card,
+ GsdSmartcardState state)
+{
+ if (card->priv->state != state) {
+ card->priv->state = state;
+
+ if (state == GSD_SMARTCARD_STATE_INSERTED) {
+ g_signal_emit (card, gsd_smartcard_signals[INSERTED], 0);
+ } else if (state == GSD_SMARTCARD_STATE_REMOVED) {
+ g_signal_emit (card, gsd_smartcard_signals[REMOVED], 0);
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+}
+
+/* So we could conceivably make the closure data a pointer to the card
+ * or something similiar and then emit signals when we want passwords,
+ * but it's probably easier to just get the password up front and use
+ * it. So we just take the passed in g_malloc'd (well probably, who knows)
+ * and strdup it using NSPR's memory allocation routines.
+ */
+static char *
+gsd_smartcard_password_handler (PK11SlotInfo *slot,
+ PRBool is_retrying,
+ const char *password)
+{
+ if (is_retrying) {
+ return NULL;
+ }
+
+ return password != NULL? PL_strdup (password): NULL;
+}
+
+gboolean
+gsd_smartcard_unlock (GsdSmartcard *card,
+ const char *password)
+{
+ SECStatus status;
+
+ PK11_SetPasswordFunc ((PK11PasswordFunc) gsd_smartcard_password_handler);
+
+ /* we pass PR_TRUE to load certificates
+ */
+ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password);
+
+ if (status != SECSuccess) {
+ g_debug ("could not unlock card - %d", status);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static PK11SlotInfo *
+gsd_smartcard_find_slot_from_card_name (GsdSmartcard *card,
+ const char *card_name)
+{
+ int i;
+
+ for (i = 0; i < card->priv->module->slotCount; i++) {
+ const char *slot_card_name;
+
+ slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]);
+
+ if ((slot_card_name != NULL) &&
+ (strcmp (slot_card_name, card_name) == 0)) {
+ return card->priv->module->slots[i];
+ }
+ }
+
+ return NULL;
+}
+
+static PK11SlotInfo *
+gsd_smartcard_find_slot_from_id (GsdSmartcard *card,
+ int slot_id)
+{
+ int i;
+
+ for (i = 0; i < card->priv->module->slotCount; i++) {
+ if (PK11_GetSlotID (card->priv->module->slots[i]) == slot_id) {
+ return card->priv->module->slots[i];
+ }
+ }
+
+ return NULL;
+}
diff --git a/plugins/smartcard/gsd-smartcard.h b/plugins/smartcard/gsd-smartcard.h
new file mode 100644
index 0000000..c8c1ea7
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard.h
@@ -0,0 +1,98 @@
+/* securitycard.h - api for reading and writing data to a security card
+ *
+ * Copyright (C) 2006 Ray Strode
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef GSD_SMARTCARD_H
+#define GSD_SMARTCARD_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <secmod.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define GSD_TYPE_SMARTCARD (gsd_smartcard_get_type ())
+#define GSD_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_SMARTCARD, GsdSmartcard))
+#define GSD_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_SMARTCARD, GsdSmartcardClass))
+#define GSD_IS_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_SMARTCARD))
+#define GSD_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_SMARTCARD))
+#define GSD_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_SMARTCARD, GsdSmartcardClass))
+#define GSD_SMARTCARD_ERROR (gsd_smartcard_error_quark ())
+typedef struct _GsdSmartcardClass GsdSmartcardClass;
+typedef struct _GsdSmartcard GsdSmartcard;
+typedef struct _GsdSmartcardPrivate GsdSmartcardPrivate;
+typedef enum _GsdSmartcardError GsdSmartcardError;
+typedef enum _GsdSmartcardState GsdSmartcardState;
+
+typedef struct _GsdSmartcardRequest GsdSmartcardRequest;
+
+struct _GsdSmartcard {
+ GObject parent;
+
+ /*< private > */
+ GsdSmartcardPrivate *priv;
+};
+
+struct _GsdSmartcardClass {
+ GObjectClass parent_class;
+
+ void (* inserted) (GsdSmartcard *card);
+ void (* removed) (GsdSmartcard *card);
+};
+
+enum _GsdSmartcardError {
+ GSD_SMARTCARD_ERROR_GENERIC = 0,
+};
+
+enum _GsdSmartcardState {
+ GSD_SMARTCARD_STATE_INSERTED = 0,
+ GSD_SMARTCARD_STATE_REMOVED,
+};
+
+GType gsd_smartcard_get_type (void) G_GNUC_CONST;
+GQuark gsd_smartcard_error_quark (void) G_GNUC_CONST;
+
+CK_SLOT_ID gsd_smartcard_get_slot_id (GsdSmartcard *card);
+gint gsd_smartcard_get_slot_series (GsdSmartcard *card);
+GsdSmartcardState gsd_smartcard_get_state (GsdSmartcard *card);
+
+char *gsd_smartcard_get_name (GsdSmartcard *card);
+gboolean gsd_smartcard_is_login_card (GsdSmartcard *card);
+
+gboolean gsd_smartcard_unlock (GsdSmartcard *card,
+ const char *password);
+
+/* don't under any circumstances call these functions */
+#ifdef GSD_SMARTCARD_ENABLE_INTERNAL_API
+
+GsdSmartcard *_gsd_smartcard_new (SECMODModule *module,
+ CK_SLOT_ID slot_id,
+ gint slot_series);
+GsdSmartcard *_gsd_smartcard_new_from_name (SECMODModule *module,
+ const char *name);
+
+void _gsd_smartcard_set_state (GsdSmartcard *card,
+ GsdSmartcardState state);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GSD_SMARTCARD_H */
diff --git a/plugins/smartcard/smartcard.mate-settings-plugin.in b/plugins/smartcard/smartcard.mate-settings-plugin.in
new file mode 100644
index 0000000..dd75784
--- /dev/null
+++ b/plugins/smartcard/smartcard.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=smartcard
+IAge=0
+_Name=Smartcard
+_Description=Smartcard plugin
+Authors=Ray Strode
+Copyright=Copyright © 2010 Red Hat, Inc.
+Website=
diff --git a/plugins/sound/Makefile.am b/plugins/sound/Makefile.am
new file mode 100644
index 0000000..7caf2ac
--- /dev/null
+++ b/plugins/sound/Makefile.am
@@ -0,0 +1,42 @@
+plugin_LTLIBRARIES = \
+ libsound.la
+
+libsound_la_SOURCES = \
+ gsd-sound-plugin.h \
+ gsd-sound-plugin.c \
+ gsd-sound-manager.h \
+ gsd-sound-manager.c
+
+libsound_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libsound_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(MATE_CFLAGS) \
+ $(PULSE_CFLAGS) \
+ $(AM_CFLAGS)
+
+libsound_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libsound_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(PULSE_LIBS)
+
+plugin_in_files = \
+ sound.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files)
+
+CLEANFILES = \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/sound/Makefile.in b/plugins/sound/Makefile.in
new file mode 100644
index 0000000..1656268
--- /dev/null
+++ b/plugins/sound/Makefile.in
@@ -0,0 +1,669 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/sound
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libsound_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libsound_la_OBJECTS = libsound_la-gsd-sound-plugin.lo \
+ libsound_la-gsd-sound-manager.lo
+libsound_la_OBJECTS = $(am_libsound_la_OBJECTS)
+libsound_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libsound_la_CFLAGS) \
+ $(CFLAGS) $(libsound_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libsound_la_SOURCES)
+DIST_SOURCES = $(libsound_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = \
+ libsound.la
+
+libsound_la_SOURCES = \
+ gsd-sound-plugin.h \
+ gsd-sound-plugin.c \
+ gsd-sound-manager.h \
+ gsd-sound-manager.c
+
+libsound_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libsound_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(MATE_CFLAGS) \
+ $(PULSE_CFLAGS) \
+ $(AM_CFLAGS)
+
+libsound_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libsound_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(PULSE_LIBS)
+
+plugin_in_files = \
+ sound.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files)
+
+CLEANFILES = \
+ $(plugin_DATA)
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/sound/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/sound/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libsound.la: $(libsound_la_OBJECTS) $(libsound_la_DEPENDENCIES)
+ $(libsound_la_LINK) -rpath $(plugindir) $(libsound_la_OBJECTS) $(libsound_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsound_la-gsd-sound-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsound_la-gsd-sound-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libsound_la-gsd-sound-plugin.lo: gsd-sound-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsound_la_CPPFLAGS) $(CPPFLAGS) $(libsound_la_CFLAGS) $(CFLAGS) -MT libsound_la-gsd-sound-plugin.lo -MD -MP -MF $(DEPDIR)/libsound_la-gsd-sound-plugin.Tpo -c -o libsound_la-gsd-sound-plugin.lo `test -f 'gsd-sound-plugin.c' || echo '$(srcdir)/'`gsd-sound-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libsound_la-gsd-sound-plugin.Tpo $(DEPDIR)/libsound_la-gsd-sound-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-sound-plugin.c' object='libsound_la-gsd-sound-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsound_la_CPPFLAGS) $(CPPFLAGS) $(libsound_la_CFLAGS) $(CFLAGS) -c -o libsound_la-gsd-sound-plugin.lo `test -f 'gsd-sound-plugin.c' || echo '$(srcdir)/'`gsd-sound-plugin.c
+
+libsound_la-gsd-sound-manager.lo: gsd-sound-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsound_la_CPPFLAGS) $(CPPFLAGS) $(libsound_la_CFLAGS) $(CFLAGS) -MT libsound_la-gsd-sound-manager.lo -MD -MP -MF $(DEPDIR)/libsound_la-gsd-sound-manager.Tpo -c -o libsound_la-gsd-sound-manager.lo `test -f 'gsd-sound-manager.c' || echo '$(srcdir)/'`gsd-sound-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libsound_la-gsd-sound-manager.Tpo $(DEPDIR)/libsound_la-gsd-sound-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-sound-manager.c' object='libsound_la-gsd-sound-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsound_la_CPPFLAGS) $(CPPFLAGS) $(libsound_la_CFLAGS) $(CFLAGS) -c -o libsound_la-gsd-sound-manager.lo `test -f 'gsd-sound-manager.c' || echo '$(srcdir)/'`gsd-sound-manager.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/sound/gsd-sound-manager.c b/plugins/sound/gsd-sound-manager.c
new file mode 100644
index 0000000..4b32130
--- /dev/null
+++ b/plugins/sound/gsd-sound-manager.c
@@ -0,0 +1,433 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Lennart Poettering <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <mateconf/mateconf-client.h>
+#include <gtk/gtk.h>
+
+#ifdef HAVE_PULSE
+#include <pulse/pulseaudio.h>
+#endif
+
+#include "gsd-sound-manager.h"
+#include "mate-settings-profile.h"
+
+#define GSD_SOUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerPrivate))
+
+struct GsdSoundManagerPrivate
+{
+ guint mateconf_notify;
+ GList* monitors;
+ guint timeout;
+};
+
+#define MATECONF_SOUND_DIR "/desktop/mate/sound"
+
+static void gsd_sound_manager_class_init (GsdSoundManagerClass *klass);
+static void gsd_sound_manager_init (GsdSoundManager *sound_manager);
+static void gsd_sound_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdSoundManager, gsd_sound_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+#ifdef HAVE_PULSE
+
+static void
+sample_info_cb (pa_context *c, const pa_sample_info *i, int eol, void *userdata)
+{
+ pa_operation *o;
+
+ if (!i)
+ return;
+
+ g_debug ("Found sample %s", i->name);
+
+ /* We only flush those samples which have an XDG sound name
+ * attached, because only those originate from themeing */
+ if (!(pa_proplist_gets (i->proplist, PA_PROP_EVENT_ID)))
+ return;
+
+ g_debug ("Dropping sample %s from cache", i->name);
+
+ if (!(o = pa_context_remove_sample (c, i->name, NULL, NULL))) {
+ g_debug ("pa_context_remove_sample (): %s", pa_strerror (pa_context_errno (c)));
+ return;
+ }
+
+ pa_operation_unref (o);
+
+ /* We won't wait until the operation is actually executed to
+ * speed things up a bit.*/
+}
+
+static void
+flush_cache (void)
+{
+ pa_mainloop *ml = NULL;
+ pa_context *c = NULL;
+ pa_proplist *pl = NULL;
+ pa_operation *o = NULL;
+
+ g_debug ("Flushing sample cache");
+
+ if (!(ml = pa_mainloop_new ())) {
+ g_debug ("Failed to allocate pa_mainloop");
+ goto fail;
+ }
+
+ if (!(pl = pa_proplist_new ())) {
+ g_debug ("Failed to allocate pa_proplist");
+ goto fail;
+ }
+
+ pa_proplist_sets (pl, PA_PROP_APPLICATION_NAME, PACKAGE_NAME);
+ pa_proplist_sets (pl, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
+ pa_proplist_sets (pl, PA_PROP_APPLICATION_ID, "org.mate.SettingsDaemon");
+
+ if (!(c = pa_context_new_with_proplist (pa_mainloop_get_api (ml), PACKAGE_NAME, pl))) {
+ g_debug ("Failed to allocate pa_context");
+ goto fail;
+ }
+
+ pa_proplist_free (pl);
+ pl = NULL;
+
+ if (pa_context_connect (c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
+ g_debug ("pa_context_connect(): %s", pa_strerror (pa_context_errno (c)));
+ goto fail;
+ }
+
+ /* Wait until the connection is established */
+ while (pa_context_get_state (c) != PA_CONTEXT_READY) {
+
+ if (!PA_CONTEXT_IS_GOOD (pa_context_get_state (c))) {
+ g_debug ("Connection failed: %s", pa_strerror (pa_context_errno (c)));
+ goto fail;
+ }
+
+ if (pa_mainloop_iterate (ml, TRUE, NULL) < 0) {
+ g_debug ("pa_mainloop_iterate() failed");
+ goto fail;
+ }
+ }
+
+ /* Enumerate all cached samples */
+ if (!(o = pa_context_get_sample_info_list (c, sample_info_cb, NULL))) {
+ g_debug ("pa_context_get_sample_info_list(): %s", pa_strerror (pa_context_errno (c)));
+ goto fail;
+ }
+
+ /* Wait until our operation is finished and there's nothing
+ * more queued to send to the server */
+ while (pa_operation_get_state (o) == PA_OPERATION_RUNNING || pa_context_is_pending (c)) {
+
+ if (!PA_CONTEXT_IS_GOOD (pa_context_get_state (c))) {
+ g_debug ("Connection failed: %s", pa_strerror (pa_context_errno (c)));
+ goto fail;
+ }
+
+ if (pa_mainloop_iterate (ml, TRUE, NULL) < 0) {
+ g_debug ("pa_mainloop_iterate() failed");
+ goto fail;
+ }
+ }
+
+ g_debug ("Sample cache flushed");
+
+fail:
+ if (o) {
+ pa_operation_cancel (o);
+ pa_operation_unref (o);
+ }
+
+ if (c) {
+ pa_context_disconnect (c);
+ pa_context_unref (c);
+ }
+
+ if (pl)
+ pa_proplist_free (pl);
+
+ if (ml)
+ pa_mainloop_free (ml);
+}
+
+static gboolean
+flush_cb (GsdSoundManager *manager)
+{
+ flush_cache ();
+ manager->priv->timeout = 0;
+ return FALSE;
+}
+
+static void
+trigger_flush (GsdSoundManager *manager)
+{
+
+ if (manager->priv->timeout)
+ g_source_remove (manager->priv->timeout);
+
+ /* We delay the flushing a bit so that we can coalesce
+ * multiple changes into a single cache flush */
+ manager->priv->timeout = g_timeout_add (500, (GSourceFunc) flush_cb, manager);
+}
+
+static void
+mateconf_client_notify_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdSoundManager *manager)
+{
+ trigger_flush (manager);
+}
+
+static gboolean
+register_config_callback (GsdSoundManager *manager, GError **error)
+{
+ MateConfClient *client;
+ gboolean succ;
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_add_dir (client, MATECONF_SOUND_DIR, MATECONF_CLIENT_PRELOAD_NONE, error);
+ succ = !error || !*error;
+
+ if (!error) {
+ manager->priv->mateconf_notify = mateconf_client_notify_add (client, MATECONF_SOUND_DIR, (MateConfClientNotifyFunc) mateconf_client_notify_cb, manager, NULL, error);
+ succ = !error || !*error;
+ }
+
+ g_object_unref (client);
+
+ return succ;
+}
+
+static void
+file_monitor_changed_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ GsdSoundManager *manager)
+{
+ g_debug ("Theme dir changed");
+ trigger_flush (manager);
+}
+
+static gboolean
+register_directory_callback (GsdSoundManager *manager,
+ const char *path,
+ GError **error)
+{
+ GFile *f;
+ GFileMonitor *m;
+ gboolean succ = FALSE;
+
+ g_debug ("Registering directory monitor for %s", path);
+
+ f = g_file_new_for_path (path);
+
+ m = g_file_monitor_directory (f, 0, NULL, error);
+
+ if (m != NULL) {
+ g_signal_connect (m, "changed", G_CALLBACK (file_monitor_changed_cb), manager);
+
+ manager->priv->monitors = g_list_prepend (manager->priv->monitors, m);
+
+ succ = TRUE;
+ }
+
+ g_object_unref (f);
+
+ return succ;
+}
+
+#endif
+
+gboolean
+gsd_sound_manager_start (GsdSoundManager *manager,
+ GError **error)
+{
+
+#ifdef HAVE_PULSE
+ char *p, **ps, **k;
+ const char *env, *dd;
+#endif
+
+ g_debug ("Starting sound manager");
+ mate_settings_profile_start (NULL);
+
+#ifdef HAVE_PULSE
+
+ /* We listen for change of the selected theme ... */
+ register_config_callback (manager, NULL);
+
+ /* ... and we listen to changes of the theme base directories
+ * in $HOME ...*/
+
+ if ((env = g_getenv ("XDG_DATA_HOME")) && *env == '/')
+ p = g_build_filename (env, "sounds", NULL);
+ else if (((env = g_getenv ("HOME")) && *env == '/') || (env = g_get_home_dir ()))
+ p = g_build_filename (env, ".local", "share", "sounds", NULL);
+ else
+ p = NULL;
+
+ if (p) {
+ register_directory_callback (manager, p, NULL);
+ g_free (p);
+ }
+
+ /* ... and globally. */
+ if (!(dd = g_getenv ("XDG_DATA_DIRS")) || *dd == 0)
+ dd = "/usr/local/share:/usr/share";
+
+ ps = g_strsplit (dd, ":", 0);
+
+ for (k = ps; *k; ++k)
+ register_directory_callback (manager, *k, NULL);
+
+ g_strfreev (ps);
+#endif
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_sound_manager_stop (GsdSoundManager *manager)
+{
+ g_debug ("Stopping sound manager");
+
+#ifdef HAVE_PULSE
+ if (manager->priv->mateconf_notify != 0) {
+ MateConfClient *client = mateconf_client_get_default ();
+
+ mateconf_client_remove_dir (client, MATECONF_SOUND_DIR, NULL);
+
+ mateconf_client_notify_remove (client, manager->priv->mateconf_notify);
+ manager->priv->mateconf_notify = 0;
+
+ g_object_unref (client);
+ }
+
+ if (manager->priv->timeout) {
+ g_source_remove (manager->priv->timeout);
+ manager->priv->timeout = 0;
+ }
+
+ while (manager->priv->monitors) {
+ g_file_monitor_cancel (G_FILE_MONITOR (manager->priv->monitors->data));
+ g_object_unref (manager->priv->monitors->data);
+ manager->priv->monitors = g_list_delete_link (manager->priv->monitors, manager->priv->monitors);
+ }
+#endif
+}
+
+static GObject *
+gsd_sound_manager_constructor (
+ GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdSoundManager *m;
+ GsdSoundManagerClass *klass;
+
+ klass = GSD_SOUND_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_SOUND_MANAGER));
+
+ m = GSD_SOUND_MANAGER (G_OBJECT_CLASS (gsd_sound_manager_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (m);
+}
+
+static void
+gsd_sound_manager_dispose (GObject *object)
+{
+ GsdSoundManager *manager;
+
+ manager = GSD_SOUND_MANAGER (object);
+
+ gsd_sound_manager_stop (manager);
+
+ G_OBJECT_CLASS (gsd_sound_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_sound_manager_class_init (GsdSoundManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = gsd_sound_manager_constructor;
+ object_class->dispose = gsd_sound_manager_dispose;
+ object_class->finalize = gsd_sound_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdSoundManagerPrivate));
+}
+
+static void
+gsd_sound_manager_init (GsdSoundManager *manager)
+{
+ manager->priv = GSD_SOUND_MANAGER_GET_PRIVATE (manager);
+}
+
+static void
+gsd_sound_manager_finalize (GObject *object)
+{
+ GsdSoundManager *sound_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_SOUND_MANAGER (object));
+
+ sound_manager = GSD_SOUND_MANAGER (object);
+
+ g_return_if_fail (sound_manager->priv);
+
+ G_OBJECT_CLASS (gsd_sound_manager_parent_class)->finalize (object);
+}
+
+GsdSoundManager *
+gsd_sound_manager_new (void)
+{
+ if (manager_object) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_SOUND_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object);
+ }
+
+ return GSD_SOUND_MANAGER (manager_object);
+}
diff --git a/plugins/sound/gsd-sound-manager.h b/plugins/sound/gsd-sound-manager.h
new file mode 100644
index 0000000..e640f09
--- /dev/null
+++ b/plugins/sound/gsd-sound-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Lennart Poettering <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_SOUND_MANAGER_H
+#define __GSD_SOUND_MANAGER_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_SOUND_MANAGER (gsd_sound_manager_get_type ())
+#define GSD_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManager))
+#define GSD_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerClass))
+#define GSD_IS_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SOUND_MANAGER))
+#define GSD_IS_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SOUND_MANAGER))
+#define GSD_SOUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerClass))
+
+typedef struct GsdSoundManagerPrivate GsdSoundManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdSoundManagerPrivate *priv;
+} GsdSoundManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdSoundManagerClass;
+
+GType gsd_sound_manager_get_type (void) G_GNUC_CONST;
+
+GsdSoundManager *gsd_sound_manager_new (void);
+gboolean gsd_sound_manager_start (GsdSoundManager *manager, GError **error);
+void gsd_sound_manager_stop (GsdSoundManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_SOUND_MANAGER_H */
diff --git a/plugins/sound/gsd-sound-plugin.c b/plugins/sound/gsd-sound-plugin.c
new file mode 100644
index 0000000..88168bf
--- /dev/null
+++ b/plugins/sound/gsd-sound-plugin.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Lennart Poettering <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-sound-plugin.h"
+#include "gsd-sound-manager.h"
+
+struct GsdSoundPluginPrivate {
+ GsdSoundManager *manager;
+};
+
+#define GSD_SOUND_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_SOUND_PLUGIN, GsdSoundPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdSoundPlugin, gsd_sound_plugin)
+
+static void
+gsd_sound_plugin_init (GsdSoundPlugin *plugin)
+{
+ plugin->priv = GSD_SOUND_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdSoundPlugin initializing");
+
+ plugin->priv->manager = gsd_sound_manager_new ();
+}
+
+static void
+gsd_sound_plugin_finalize (GObject *object)
+{
+ GsdSoundPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_SOUND_PLUGIN (object));
+
+ g_debug ("GsdSoundPlugin finalizing");
+
+ plugin = GSD_SOUND_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL)
+ g_object_unref (plugin->priv->manager);
+
+ G_OBJECT_CLASS (gsd_sound_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ GError *error = NULL;
+
+ g_debug ("Activating sound plugin");
+
+ if (!gsd_sound_manager_start (GSD_SOUND_PLUGIN (plugin)->priv->manager, &error)) {
+ g_warning ("Unable to start sound manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating sound plugin");
+ gsd_sound_manager_stop (GSD_SOUND_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_sound_plugin_class_init (GsdSoundPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_sound_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdSoundPluginPrivate));
+}
diff --git a/plugins/sound/gsd-sound-plugin.h b/plugins/sound/gsd-sound-plugin.h
new file mode 100644
index 0000000..660e159
--- /dev/null
+++ b/plugins/sound/gsd-sound-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Lennart Poettering <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_SOUND_PLUGIN_H__
+#define __GSD_SOUND_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_SOUND_PLUGIN (gsd_sound_plugin_get_type ())
+#define GSD_SOUND_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SOUND_PLUGIN, GsdSoundPlugin))
+#define GSD_SOUND_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SOUND_PLUGIN, GsdSoundPluginClass))
+#define GSD_IS_SOUND_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SOUND_PLUGIN))
+#define GSD_IS_SOUND_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SOUND_PLUGIN))
+#define GSD_SOUND_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SOUND_PLUGIN, GsdSoundPluginClass))
+
+typedef struct GsdSoundPluginPrivate GsdSoundPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdSoundPluginPrivate *priv;
+} GsdSoundPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdSoundPluginClass;
+
+GType gsd_sound_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_SOUND_PLUGIN_H__ */
diff --git a/plugins/sound/sound.mate-settings-plugin.in b/plugins/sound/sound.mate-settings-plugin.in
new file mode 100644
index 0000000..fb7e57b
--- /dev/null
+++ b/plugins/sound/sound.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=sound
+IAge=0
+_Name=Sound
+_Description=Sound Sample Cache plugin
+Authors=Lennart Poettering
+Copyright=Copyright © 2008
+Website=
diff --git a/plugins/typing-break/Makefile.am b/plugins/typing-break/Makefile.am
new file mode 100644
index 0000000..0648007
--- /dev/null
+++ b/plugins/typing-break/Makefile.am
@@ -0,0 +1,49 @@
+NULL =
+
+plugin_LTLIBRARIES = \
+ libtyping-break.la \
+ $(NULL)
+
+libtyping_break_la_SOURCES = \
+ gsd-typing-break-plugin.h \
+ gsd-typing-break-plugin.c \
+ gsd-typing-break-manager.h \
+ gsd-typing-break-manager.c \
+ $(NULL)
+
+libtyping_break_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libtyping_break_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libtyping_break_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libtyping_break_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ typing-break.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/typing-break/Makefile.in b/plugins/typing-break/Makefile.in
new file mode 100644
index 0000000..8fb38dc
--- /dev/null
+++ b/plugins/typing-break/Makefile.in
@@ -0,0 +1,680 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/typing-break
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libtyping_break_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libtyping_break_la_OBJECTS = \
+ libtyping_break_la-gsd-typing-break-plugin.lo \
+ libtyping_break_la-gsd-typing-break-manager.lo \
+ $(am__objects_1)
+libtyping_break_la_OBJECTS = $(am_libtyping_break_la_OBJECTS)
+libtyping_break_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libtyping_break_la_CFLAGS) $(CFLAGS) \
+ $(libtyping_break_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libtyping_break_la_SOURCES)
+DIST_SOURCES = $(libtyping_break_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+plugin_LTLIBRARIES = \
+ libtyping-break.la \
+ $(NULL)
+
+libtyping_break_la_SOURCES = \
+ gsd-typing-break-plugin.h \
+ gsd-typing-break-plugin.c \
+ gsd-typing-break-manager.h \
+ gsd-typing-break-manager.c \
+ $(NULL)
+
+libtyping_break_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libtyping_break_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libtyping_break_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libtyping_break_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ typing-break.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/typing-break/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/typing-break/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libtyping-break.la: $(libtyping_break_la_OBJECTS) $(libtyping_break_la_DEPENDENCIES)
+ $(libtyping_break_la_LINK) -rpath $(plugindir) $(libtyping_break_la_OBJECTS) $(libtyping_break_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtyping_break_la-gsd-typing-break-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtyping_break_la-gsd-typing-break-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libtyping_break_la-gsd-typing-break-plugin.lo: gsd-typing-break-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtyping_break_la_CPPFLAGS) $(CPPFLAGS) $(libtyping_break_la_CFLAGS) $(CFLAGS) -MT libtyping_break_la-gsd-typing-break-plugin.lo -MD -MP -MF $(DEPDIR)/libtyping_break_la-gsd-typing-break-plugin.Tpo -c -o libtyping_break_la-gsd-typing-break-plugin.lo `test -f 'gsd-typing-break-plugin.c' || echo '$(srcdir)/'`gsd-typing-break-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libtyping_break_la-gsd-typing-break-plugin.Tpo $(DEPDIR)/libtyping_break_la-gsd-typing-break-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-typing-break-plugin.c' object='libtyping_break_la-gsd-typing-break-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtyping_break_la_CPPFLAGS) $(CPPFLAGS) $(libtyping_break_la_CFLAGS) $(CFLAGS) -c -o libtyping_break_la-gsd-typing-break-plugin.lo `test -f 'gsd-typing-break-plugin.c' || echo '$(srcdir)/'`gsd-typing-break-plugin.c
+
+libtyping_break_la-gsd-typing-break-manager.lo: gsd-typing-break-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtyping_break_la_CPPFLAGS) $(CPPFLAGS) $(libtyping_break_la_CFLAGS) $(CFLAGS) -MT libtyping_break_la-gsd-typing-break-manager.lo -MD -MP -MF $(DEPDIR)/libtyping_break_la-gsd-typing-break-manager.Tpo -c -o libtyping_break_la-gsd-typing-break-manager.lo `test -f 'gsd-typing-break-manager.c' || echo '$(srcdir)/'`gsd-typing-break-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libtyping_break_la-gsd-typing-break-manager.Tpo $(DEPDIR)/libtyping_break_la-gsd-typing-break-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-typing-break-manager.c' object='libtyping_break_la-gsd-typing-break-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtyping_break_la_CPPFLAGS) $(CPPFLAGS) $(libtyping_break_la_CFLAGS) $(CFLAGS) -c -o libtyping_break_la-gsd-typing-break-manager.lo `test -f 'gsd-typing-break-manager.c' || echo '$(srcdir)/'`gsd-typing-break-manager.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/typing-break/gsd-typing-break-manager.c b/plugins/typing-break/gsd-typing-break-manager.c
new file mode 100644
index 0000000..d157964
--- /dev/null
+++ b/plugins/typing-break/gsd-typing-break-manager.c
@@ -0,0 +1,339 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-typing-break-manager.h"
+
+#define GSD_TYPING_BREAK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_TYPING_BREAK_MANAGER, GsdTypingBreakManagerPrivate))
+
+#define MATECONF_BREAK_DIR "/desktop/mate/typing_break"
+
+struct GsdTypingBreakManagerPrivate
+{
+ GPid typing_monitor_pid;
+ guint typing_monitor_idle_id;
+ guint child_watch_id;
+ guint setup_id;
+ guint notify;
+};
+
+static void gsd_typing_break_manager_class_init (GsdTypingBreakManagerClass *klass);
+static void gsd_typing_break_manager_init (GsdTypingBreakManager *typing_break_manager);
+static void gsd_typing_break_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdTypingBreakManager, gsd_typing_break_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static gboolean
+typing_break_timeout (GsdTypingBreakManager *manager)
+{
+ if (manager->priv->typing_monitor_pid > 0) {
+ kill (manager->priv->typing_monitor_pid, SIGKILL);
+ }
+
+ manager->priv->typing_monitor_idle_id = 0;
+
+ return FALSE;
+}
+
+static void
+child_watch (GPid pid,
+ int status,
+ GsdTypingBreakManager *manager)
+{
+ if (pid == manager->priv->typing_monitor_pid) {
+ manager->priv->typing_monitor_pid = 0;
+ g_spawn_close_pid (pid);
+ }
+}
+
+static void
+setup_typing_break (GsdTypingBreakManager *manager,
+ gboolean enabled)
+{
+ mate_settings_profile_start (NULL);
+
+ if (! enabled) {
+ if (manager->priv->typing_monitor_pid != 0) {
+ manager->priv->typing_monitor_idle_id = g_timeout_add_seconds (3, (GSourceFunc) typing_break_timeout, manager);
+ }
+ return;
+ }
+
+ if (manager->priv->typing_monitor_idle_id != 0) {
+ g_source_remove (manager->priv->typing_monitor_idle_id);
+ manager->priv->typing_monitor_idle_id = 0;
+ }
+
+ if (manager->priv->typing_monitor_pid == 0) {
+ GError *error;
+ char *argv[] = { "mate-typing-monitor", "-n", NULL };
+ gboolean res;
+
+ error = NULL;
+ res = g_spawn_async ("/",
+ argv,
+ NULL,
+ G_SPAWN_STDOUT_TO_DEV_NULL
+ | G_SPAWN_STDERR_TO_DEV_NULL
+ | G_SPAWN_SEARCH_PATH
+ | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL,
+ NULL,
+ &manager->priv->typing_monitor_pid,
+ &error);
+ if (! res) {
+ /* FIXME: put up a warning */
+ g_warning ("failed: %s\n", error->message);
+ g_error_free (error);
+ manager->priv->typing_monitor_pid = 0;
+ return;
+ }
+
+ manager->priv->child_watch_id = g_child_watch_add (manager->priv->typing_monitor_pid,
+ (GChildWatchFunc)child_watch,
+ manager);
+ }
+
+ mate_settings_profile_end (NULL);
+}
+
+static void
+typing_break_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdTypingBreakManager *manager)
+{
+ if (! strcmp (entry->key, "/desktop/mate/typing_break/enabled")) {
+ if (entry->value->type == MATECONF_VALUE_BOOL) {
+ setup_typing_break (manager, mateconf_value_get_bool (entry->value));
+ }
+ }
+}
+
+static gboolean
+really_setup_typing_break (GsdTypingBreakManager *manager)
+{
+ setup_typing_break (manager, TRUE);
+ manager->priv->setup_id = 0;
+ return FALSE;
+}
+
+gboolean
+gsd_typing_break_manager_start (GsdTypingBreakManager *manager,
+ GError **error)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ g_debug ("Starting typing_break manager");
+ mate_settings_profile_start (NULL);
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_add_dir (client, MATECONF_BREAK_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ manager->priv->notify =
+ mateconf_client_notify_add (client,
+ MATECONF_BREAK_DIR,
+ (MateConfClientNotifyFunc) typing_break_callback, manager,
+ NULL, NULL);
+
+ enabled = mateconf_client_get_bool (client, MATECONF_BREAK_DIR "/enabled", NULL);
+ g_object_unref (client);
+ if (enabled) {
+ manager->priv->setup_id =
+ g_timeout_add_seconds (3,
+ (GSourceFunc) really_setup_typing_break,
+ manager);
+ }
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_typing_break_manager_stop (GsdTypingBreakManager *manager)
+{
+ GsdTypingBreakManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping typing_break manager");
+
+ if (p->setup_id != 0) {
+ g_source_remove (p->setup_id);
+ p->setup_id = 0;
+ }
+
+ if (p->child_watch_id != 0) {
+ g_source_remove (p->child_watch_id);
+ p->child_watch_id = 0;
+ }
+
+ if (p->typing_monitor_idle_id != 0) {
+ g_source_remove (p->typing_monitor_idle_id);
+ p->typing_monitor_idle_id = 0;
+ }
+
+ if (p->typing_monitor_pid > 0) {
+ kill (p->typing_monitor_pid, SIGKILL);
+ g_spawn_close_pid (p->typing_monitor_pid);
+ p->typing_monitor_pid = 0;
+ }
+
+ if (p->notify != 0) {
+ MateConfClient *client = mateconf_client_get_default ();
+ mateconf_client_remove_dir (client, MATECONF_BREAK_DIR, NULL);
+ mateconf_client_notify_remove (client, p->notify);
+ g_object_unref (client);
+ p->notify = 0;
+ }
+}
+
+static void
+gsd_typing_break_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdTypingBreakManager *self;
+
+ self = GSD_TYPING_BREAK_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_typing_break_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdTypingBreakManager *self;
+
+ self = GSD_TYPING_BREAK_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_typing_break_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdTypingBreakManager *typing_break_manager;
+ GsdTypingBreakManagerClass *klass;
+
+ klass = GSD_TYPING_BREAK_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_TYPING_BREAK_MANAGER));
+
+ typing_break_manager = GSD_TYPING_BREAK_MANAGER (G_OBJECT_CLASS (gsd_typing_break_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (typing_break_manager);
+}
+
+static void
+gsd_typing_break_manager_dispose (GObject *object)
+{
+ GsdTypingBreakManager *typing_break_manager;
+
+ typing_break_manager = GSD_TYPING_BREAK_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_typing_break_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_typing_break_manager_class_init (GsdTypingBreakManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_typing_break_manager_get_property;
+ object_class->set_property = gsd_typing_break_manager_set_property;
+ object_class->constructor = gsd_typing_break_manager_constructor;
+ object_class->dispose = gsd_typing_break_manager_dispose;
+ object_class->finalize = gsd_typing_break_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdTypingBreakManagerPrivate));
+}
+
+static void
+gsd_typing_break_manager_init (GsdTypingBreakManager *manager)
+{
+ manager->priv = GSD_TYPING_BREAK_MANAGER_GET_PRIVATE (manager);
+
+}
+
+static void
+gsd_typing_break_manager_finalize (GObject *object)
+{
+ GsdTypingBreakManager *typing_break_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_TYPING_BREAK_MANAGER (object));
+
+ typing_break_manager = GSD_TYPING_BREAK_MANAGER (object);
+
+ g_return_if_fail (typing_break_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_typing_break_manager_parent_class)->finalize (object);
+}
+
+GsdTypingBreakManager *
+gsd_typing_break_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_TYPING_BREAK_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_TYPING_BREAK_MANAGER (manager_object);
+}
diff --git a/plugins/typing-break/gsd-typing-break-manager.h b/plugins/typing-break/gsd-typing-break-manager.h
new file mode 100644
index 0000000..e4ac24d
--- /dev/null
+++ b/plugins/typing-break/gsd-typing-break-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_TYPING_BREAK_MANAGER_H
+#define __GSD_TYPING_BREAK_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_TYPING_BREAK_MANAGER (gsd_typing_break_manager_get_type ())
+#define GSD_TYPING_BREAK_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_TYPING_BREAK_MANAGER, GsdTypingBreakManager))
+#define GSD_TYPING_BREAK_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_TYPING_BREAK_MANAGER, GsdTypingBreakManagerClass))
+#define GSD_IS_TYPING_BREAK_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_TYPING_BREAK_MANAGER))
+#define GSD_IS_TYPING_BREAK_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_TYPING_BREAK_MANAGER))
+#define GSD_TYPING_BREAK_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_TYPING_BREAK_MANAGER, GsdTypingBreakManagerClass))
+
+typedef struct GsdTypingBreakManagerPrivate GsdTypingBreakManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdTypingBreakManagerPrivate *priv;
+} GsdTypingBreakManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdTypingBreakManagerClass;
+
+GType gsd_typing_break_manager_get_type (void);
+
+GsdTypingBreakManager * gsd_typing_break_manager_new (void);
+gboolean gsd_typing_break_manager_start (GsdTypingBreakManager *manager,
+ GError **error);
+void gsd_typing_break_manager_stop (GsdTypingBreakManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_TYPING_BREAK_MANAGER_H */
diff --git a/plugins/typing-break/gsd-typing-break-plugin.c b/plugins/typing-break/gsd-typing-break-plugin.c
new file mode 100644
index 0000000..0f0535d
--- /dev/null
+++ b/plugins/typing-break/gsd-typing-break-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-typing-break-plugin.h"
+#include "gsd-typing-break-manager.h"
+
+struct GsdTypingBreakPluginPrivate {
+ GsdTypingBreakManager *manager;
+};
+
+#define GSD_TYPING_BREAK_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_TYPING_BREAK_PLUGIN, GsdTypingBreakPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdTypingBreakPlugin, gsd_typing_break_plugin)
+
+static void
+gsd_typing_break_plugin_init (GsdTypingBreakPlugin *plugin)
+{
+ plugin->priv = GSD_TYPING_BREAK_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdTypingBreakPlugin initializing");
+
+ plugin->priv->manager = gsd_typing_break_manager_new ();
+}
+
+static void
+gsd_typing_break_plugin_finalize (GObject *object)
+{
+ GsdTypingBreakPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_TYPING_BREAK_PLUGIN (object));
+
+ g_debug ("GsdTypingBreakPlugin finalizing");
+
+ plugin = GSD_TYPING_BREAK_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_typing_break_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating typing_break plugin");
+
+ error = NULL;
+ res = gsd_typing_break_manager_start (GSD_TYPING_BREAK_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start typing_break manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating typing_break plugin");
+ gsd_typing_break_manager_stop (GSD_TYPING_BREAK_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_typing_break_plugin_class_init (GsdTypingBreakPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_typing_break_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdTypingBreakPluginPrivate));
+}
diff --git a/plugins/typing-break/gsd-typing-break-plugin.h b/plugins/typing-break/gsd-typing-break-plugin.h
new file mode 100644
index 0000000..b7bbf16
--- /dev/null
+++ b/plugins/typing-break/gsd-typing-break-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_TYPING_BREAK_PLUGIN_H__
+#define __GSD_TYPING_BREAK_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_TYPING_BREAK_PLUGIN (gsd_typing_break_plugin_get_type ())
+#define GSD_TYPING_BREAK_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_TYPING_BREAK_PLUGIN, GsdTypingBreakPlugin))
+#define GSD_TYPING_BREAK_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_TYPING_BREAK_PLUGIN, GsdTypingBreakPluginClass))
+#define GSD_IS_TYPING_BREAK_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_TYPING_BREAK_PLUGIN))
+#define GSD_IS_TYPING_BREAK_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_TYPING_BREAK_PLUGIN))
+#define GSD_TYPING_BREAK_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_TYPING_BREAK_PLUGIN, GsdTypingBreakPluginClass))
+
+typedef struct GsdTypingBreakPluginPrivate GsdTypingBreakPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdTypingBreakPluginPrivate *priv;
+} GsdTypingBreakPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdTypingBreakPluginClass;
+
+GType gsd_typing_break_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_TYPING_BREAK_PLUGIN_H__ */
diff --git a/plugins/typing-break/typing-break.mate-settings-plugin.in b/plugins/typing-break/typing-break.mate-settings-plugin.in
new file mode 100644
index 0000000..22b722f
--- /dev/null
+++ b/plugins/typing-break/typing-break.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=typing-break
+IAge=0
+_Name=Typing Break
+_Description=Typing break plugin
+Authors=
+Copyright=Copyright © 2007
+Website=
diff --git a/plugins/xrandr/Makefile.am b/plugins/xrandr/Makefile.am
new file mode 100644
index 0000000..b7d8684
--- /dev/null
+++ b/plugins/xrandr/Makefile.am
@@ -0,0 +1,76 @@
+icondir = $(datadir)/icons/mate
+context = apps
+
+BUILT_SOURCES = \
+ gsd-xrandr-manager-glue.h
+
+ICON_FILES = \
+ gsd-xrandr-16.png \
+ gsd-xrandr-22.png \
+ gsd-xrandr-24.png \
+ gsd-xrandr-32.png \
+ gsd-xrandr.svg
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/mate-settings-daemon/xrandr
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/16x16/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/22x22/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/24x24/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/32x32/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/scalable/$(context)
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-16.png $(DESTDIR)$(icondir)/16x16/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-22.png $(DESTDIR)$(icondir)/22x22/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-24.png $(DESTDIR)$(icondir)/24x24/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-32.png $(DESTDIR)$(icondir)/32x32/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr.svg $(DESTDIR)$(icondir)/scalable/$(context)/gsd-xrandr.svg
+
+uninstall-local:
+ rm -f $(DESTDIR)$(icondir)/16x16/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/22x22/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/24x24/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/32x32/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/scalable/$(context)/gsd-xrandr.svg
+
+plugin_LTLIBRARIES = \
+ libxrandr.la
+
+gsd-xrandr-manager-glue.h: gsd-xrandr-manager.xml Makefile
+ dbus-binding-tool --prefix=gsd_xrandr_manager --mode=glib-server $< > xgen-$(@F) \
+ && ( cmp -s xgen-$(@F) $@ || cp xgen-$(@F) $@ ) \
+ && rm -f xgen-$(@F)
+
+libxrandr_la_SOURCES = \
+ $(BUILT_SOURCES) \
+ gsd-xrandr-plugin.h \
+ gsd-xrandr-plugin.c \
+ gsd-xrandr-manager.h \
+ gsd-xrandr-manager.c
+
+libxrandr_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DBINDIR=\"$(bindir)\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libxrandr_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(LIBMATENOTIFY_CFLAGS) \
+ $(AM_CFLAGS)
+
+libxrandr_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libxrandr_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(LIBMATENOTIFY_LIBS)
+
+plugin_in_files = \
+ xrandr.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = $(plugin_in_files) $(ICON_FILES) gsd-xrandr-manager.xml
+CLEANFILES = $(plugin_DATA) $(BUILT_SOURCES)
+DISTCLEANFILES = $(plugin_DATA)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/xrandr/Makefile.in b/plugins/xrandr/Makefile.in
new file mode 100644
index 0000000..ba8edc4
--- /dev/null
+++ b/plugins/xrandr/Makefile.in
@@ -0,0 +1,711 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/xrandr
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libxrandr_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libxrandr_la_OBJECTS = $(am__objects_1) \
+ libxrandr_la-gsd-xrandr-plugin.lo \
+ libxrandr_la-gsd-xrandr-manager.lo
+libxrandr_la_OBJECTS = $(am_libxrandr_la_OBJECTS)
+libxrandr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libxrandr_la_CFLAGS) \
+ $(CFLAGS) $(libxrandr_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libxrandr_la_SOURCES)
+DIST_SOURCES = $(libxrandr_la_SOURCES)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+icondir = $(datadir)/icons/mate
+context = apps
+BUILT_SOURCES = \
+ gsd-xrandr-manager-glue.h
+
+ICON_FILES = \
+ gsd-xrandr-16.png \
+ gsd-xrandr-22.png \
+ gsd-xrandr-24.png \
+ gsd-xrandr-32.png \
+ gsd-xrandr.svg
+
+plugin_LTLIBRARIES = \
+ libxrandr.la
+
+libxrandr_la_SOURCES = \
+ $(BUILT_SOURCES) \
+ gsd-xrandr-plugin.h \
+ gsd-xrandr-plugin.c \
+ gsd-xrandr-manager.h \
+ gsd-xrandr-manager.c
+
+libxrandr_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DBINDIR=\"$(bindir)\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libxrandr_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(LIBMATENOTIFY_CFLAGS) \
+ $(AM_CFLAGS)
+
+libxrandr_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS)
+
+libxrandr_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(LIBMATENOTIFY_LIBS)
+
+plugin_in_files = \
+ xrandr.mate-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = $(plugin_in_files) $(ICON_FILES) gsd-xrandr-manager.xml
+CLEANFILES = $(plugin_DATA) $(BUILT_SOURCES)
+DISTCLEANFILES = $(plugin_DATA)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/xrandr/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/xrandr/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libxrandr.la: $(libxrandr_la_OBJECTS) $(libxrandr_la_DEPENDENCIES)
+ $(libxrandr_la_LINK) -rpath $(plugindir) $(libxrandr_la_OBJECTS) $(libxrandr_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxrandr_la-gsd-xrandr-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxrandr_la-gsd-xrandr-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libxrandr_la-gsd-xrandr-plugin.lo: gsd-xrandr-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrandr_la_CPPFLAGS) $(CPPFLAGS) $(libxrandr_la_CFLAGS) $(CFLAGS) -MT libxrandr_la-gsd-xrandr-plugin.lo -MD -MP -MF $(DEPDIR)/libxrandr_la-gsd-xrandr-plugin.Tpo -c -o libxrandr_la-gsd-xrandr-plugin.lo `test -f 'gsd-xrandr-plugin.c' || echo '$(srcdir)/'`gsd-xrandr-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxrandr_la-gsd-xrandr-plugin.Tpo $(DEPDIR)/libxrandr_la-gsd-xrandr-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xrandr-plugin.c' object='libxrandr_la-gsd-xrandr-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrandr_la_CPPFLAGS) $(CPPFLAGS) $(libxrandr_la_CFLAGS) $(CFLAGS) -c -o libxrandr_la-gsd-xrandr-plugin.lo `test -f 'gsd-xrandr-plugin.c' || echo '$(srcdir)/'`gsd-xrandr-plugin.c
+
+libxrandr_la-gsd-xrandr-manager.lo: gsd-xrandr-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrandr_la_CPPFLAGS) $(CPPFLAGS) $(libxrandr_la_CFLAGS) $(CFLAGS) -MT libxrandr_la-gsd-xrandr-manager.lo -MD -MP -MF $(DEPDIR)/libxrandr_la-gsd-xrandr-manager.Tpo -c -o libxrandr_la-gsd-xrandr-manager.lo `test -f 'gsd-xrandr-manager.c' || echo '$(srcdir)/'`gsd-xrandr-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxrandr_la-gsd-xrandr-manager.Tpo $(DEPDIR)/libxrandr_la-gsd-xrandr-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xrandr-manager.c' object='libxrandr_la-gsd-xrandr-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrandr_la_CPPFLAGS) $(CPPFLAGS) $(libxrandr_la_CFLAGS) $(CFLAGS) -c -o libxrandr_la-gsd-xrandr-manager.lo `test -f 'gsd-xrandr-manager.c' || echo '$(srcdir)/'`gsd-xrandr-manager.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-pluginDATA \
+ install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-local uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginDATA install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-local uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/mate-settings-daemon/xrandr
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/16x16/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/22x22/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/24x24/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/32x32/$(context)
+ $(mkinstalldirs) $(DESTDIR)$(icondir)/scalable/$(context)
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-16.png $(DESTDIR)$(icondir)/16x16/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-22.png $(DESTDIR)$(icondir)/22x22/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-24.png $(DESTDIR)$(icondir)/24x24/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr-32.png $(DESTDIR)$(icondir)/32x32/$(context)/gsd-xrandr.png
+ $(INSTALL_DATA) $(srcdir)/gsd-xrandr.svg $(DESTDIR)$(icondir)/scalable/$(context)/gsd-xrandr.svg
+
+uninstall-local:
+ rm -f $(DESTDIR)$(icondir)/16x16/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/22x22/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/24x24/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/32x32/$(context)/gsd-xrandr.png
+ rm -f $(DESTDIR)$(icondir)/scalable/$(context)/gsd-xrandr.svg
+
+gsd-xrandr-manager-glue.h: gsd-xrandr-manager.xml Makefile
+ dbus-binding-tool --prefix=gsd_xrandr_manager --mode=glib-server $< > xgen-$(@F) \
+ && ( cmp -s xgen-$(@F) $@ || cp xgen-$(@F) $@ ) \
+ && rm -f xgen-$(@F)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/xrandr/gsd-xrandr-16.png b/plugins/xrandr/gsd-xrandr-16.png
new file mode 100644
index 0000000..f996ddf
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-16.png
Binary files differ
diff --git a/plugins/xrandr/gsd-xrandr-22.png b/plugins/xrandr/gsd-xrandr-22.png
new file mode 100644
index 0000000..cc47eec
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-22.png
Binary files differ
diff --git a/plugins/xrandr/gsd-xrandr-24.png b/plugins/xrandr/gsd-xrandr-24.png
new file mode 100644
index 0000000..49b4e12
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-24.png
Binary files differ
diff --git a/plugins/xrandr/gsd-xrandr-32.png b/plugins/xrandr/gsd-xrandr-32.png
new file mode 100644
index 0000000..95de3ea
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-32.png
Binary files differ
diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
new file mode 100644
index 0000000..b8d9c66
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -0,0 +1,2584 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ * Copyright (C) 2007, 2008 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+#include <dbus/dbus-glib.h>
+
+#define MATE_DESKTOP_USE_UNSTABLE_API
+
+#include <libmateui/mate-rr-config.h>
+#include <libmateui/mate-rr.h>
+#include <libmateui/mate-rr-labeler.h>
+
+#ifdef HAVE_LIBMATENOTIFY
+#include <libmatenotify/notify.h>
+#endif
+
+#include "mate-settings-profile.h"
+#include "gsd-xrandr-manager.h"
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
+#define GSD_XRANDR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManagerPrivate))
+
+#define CONF_DIR "/apps/mate_settings_daemon/xrandr"
+#define CONF_KEY_SHOW_NOTIFICATION_ICON (CONF_DIR "/show_notification_icon")
+#define CONF_KEY_TURN_ON_EXTERNAL_MONITORS_AT_STARTUP (CONF_DIR "/turn_on_external_monitors_at_startup")
+#define CONF_KEY_TURN_ON_LAPTOP_MONITOR_AT_STARTUP (CONF_DIR "/turn_on_laptop_monitor_at_startup")
+#define CONF_KEY_DEFAULT_CONFIGURATION_FILE (CONF_DIR "/default_configuration_file")
+
+#define VIDEO_KEYSYM "XF86Display"
+#define ROTATE_KEYSYM "XF86RotateWindows"
+
+/* Number of seconds that the confirmation dialog will last before it resets the
+ * RANDR configuration to its old state.
+ */
+#define CONFIRMATION_DIALOG_SECONDS 30
+
+/* name of the icon files (gsd-xrandr.svg, etc.) */
+#define GSD_XRANDR_ICON_NAME "gsd-xrandr"
+
+/* executable of the control center's display configuration capplet */
+#define GSD_XRANDR_DISPLAY_CAPPLET "mate-control-center display"
+
+#define GSD_DBUS_PATH "/org/mate/SettingsDaemon"
+#define GSD_DBUS_NAME "org.mate.SettingsDaemon"
+#define GSD_XRANDR_DBUS_PATH GSD_DBUS_PATH "/XRANDR"
+#define GSD_XRANDR_DBUS_NAME GSD_DBUS_NAME ".XRANDR"
+
+struct GsdXrandrManagerPrivate
+{
+ DBusGConnection *dbus_connection;
+
+ /* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */
+ guint switch_video_mode_keycode;
+
+ /* Key code of the XF86RotateWindows key (present on some tablets) */
+ guint rotate_windows_keycode;
+
+ MateRRScreen *rw_screen;
+ gboolean running;
+
+ GtkStatusIcon *status_icon;
+ GtkWidget *popup_menu;
+ MateRRConfig *configuration;
+ MateRRLabeler *labeler;
+ MateConfClient *client;
+ int notify_id;
+
+ /* fn-F7 status */
+ int current_fn_f7_config; /* -1 if no configs */
+ MateRRConfig **fn_f7_configs; /* NULL terminated, NULL if there are no configs */
+
+ /* Last time at which we got a "screen got reconfigured" event; see on_randr_event() */
+ guint32 last_config_timestamp;
+};
+
+static const MateRRRotation possible_rotations[] = {
+ MATE_RR_ROTATION_0,
+ MATE_RR_ROTATION_90,
+ MATE_RR_ROTATION_180,
+ MATE_RR_ROTATION_270
+ /* We don't allow REFLECT_X or REFLECT_Y for now, as mate-display-properties doesn't allow them, either */
+};
+
+static void gsd_xrandr_manager_class_init (GsdXrandrManagerClass *klass);
+static void gsd_xrandr_manager_init (GsdXrandrManager *xrandr_manager);
+static void gsd_xrandr_manager_finalize (GObject *object);
+
+static void error_message (GsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text);
+
+static void status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timestamp);
+static void run_display_capplet (GtkWidget *widget);
+static void get_allowed_rotations_for_output (MateRRConfig *config,
+ MateRRScreen *rr_screen,
+ MateOutputInfo *output,
+ int *out_num_rotations,
+ MateRRRotation *out_rotations);
+
+G_DEFINE_TYPE (GsdXrandrManager, gsd_xrandr_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static FILE *log_file;
+
+static void
+log_open (void)
+{
+ char *toggle_filename;
+ char *log_filename;
+ struct stat st;
+
+ if (log_file)
+ return;
+
+ toggle_filename = g_build_filename (g_get_home_dir (), "gsd-debug-randr", NULL);
+ log_filename = g_build_filename (g_get_home_dir (), "gsd-debug-randr.log", NULL);
+
+ if (stat (toggle_filename, &st) != 0)
+ goto out;
+
+ log_file = fopen (log_filename, "a");
+
+ if (log_file && ftell (log_file) == 0)
+ fprintf (log_file, "To keep this log from being created, please rm ~/gsd-debug-randr\n");
+
+out:
+ g_free (toggle_filename);
+ g_free (log_filename);
+}
+
+static void
+log_close (void)
+{
+ if (log_file) {
+ fclose (log_file);
+ log_file = NULL;
+ }
+}
+
+static void
+log_msg (const char *format, ...)
+{
+ if (log_file) {
+ va_list args;
+
+ va_start (args, format);
+ vfprintf (log_file, format, args);
+ va_end (args);
+ }
+}
+
+static void
+log_output (MateOutputInfo *output)
+{
+ log_msg (" %s: ", output->name ? output->name : "unknown");
+
+ if (output->connected) {
+ if (output->on) {
+ log_msg ("%dx%d@%d +%d+%d",
+ output->width,
+ output->height,
+ output->rate,
+ output->x,
+ output->y);
+ } else
+ log_msg ("off");
+ } else
+ log_msg ("disconnected");
+
+ if (output->display_name)
+ log_msg (" (%s)", output->display_name);
+
+ if (output->primary)
+ log_msg (" (primary output)");
+
+ log_msg ("\n");
+}
+
+static void
+log_configuration (MateRRConfig *config)
+{
+ int i;
+
+ log_msg (" cloned: %s\n", config->clone ? "yes" : "no");
+
+ for (i = 0; config->outputs[i] != NULL; i++)
+ log_output (config->outputs[i]);
+
+ if (i == 0)
+ log_msg (" no outputs!\n");
+}
+
+static char
+timestamp_relationship (guint32 a, guint32 b)
+{
+ if (a < b)
+ return '<';
+ else if (a > b)
+ return '>';
+ else
+ return '=';
+}
+
+static void
+log_screen (MateRRScreen *screen)
+{
+ MateRRConfig *config;
+ int min_w, min_h, max_w, max_h;
+ guint32 change_timestamp, config_timestamp;
+
+ if (!log_file)
+ return;
+
+ config = mate_rr_config_new_current (screen);
+
+ mate_rr_screen_get_ranges (screen, &min_w, &max_w, &min_h, &max_h);
+ mate_rr_screen_get_timestamps (screen, &change_timestamp, &config_timestamp);
+
+ log_msg (" Screen min(%d, %d), max(%d, %d), change=%u %c config=%u\n",
+ min_w, min_h,
+ max_w, max_h,
+ change_timestamp,
+ timestamp_relationship (change_timestamp, config_timestamp),
+ config_timestamp);
+
+ log_configuration (config);
+ mate_rr_config_free (config);
+}
+
+static void
+log_configurations (MateRRConfig **configs)
+{
+ int i;
+
+ if (!configs) {
+ log_msg (" No configurations\n");
+ return;
+ }
+
+ for (i = 0; configs[i]; i++) {
+ log_msg (" Configuration %d\n", i);
+ log_configuration (configs[i]);
+ }
+}
+
+static void
+show_timestamps_dialog (GsdXrandrManager *manager, const char *msg)
+{
+#if 1
+ return;
+#else
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ GtkWidget *dialog;
+ guint32 change_timestamp, config_timestamp;
+ static int serial;
+
+ mate_rr_screen_get_timestamps (priv->rw_screen, &change_timestamp, &config_timestamp);
+
+ dialog = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "RANDR timestamps (%d):\n%s\nchange: %u\nconfig: %u",
+ serial++,
+ msg,
+ change_timestamp,
+ config_timestamp);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (dialog);
+#endif
+}
+
+/* This function centralizes the use of mate_rr_config_apply_from_filename_with_time().
+ *
+ * Optionally filters out MATE_RR_ERROR_NO_MATCHING_CONFIG from
+ * mate_rr_config_apply_from_filename_with_time(), since that is not usually an error.
+ */
+static gboolean
+apply_configuration_from_filename (GsdXrandrManager *manager,
+ const char *filename,
+ gboolean no_matching_config_is_an_error,
+ guint32 timestamp,
+ GError **error)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ GError *my_error;
+ gboolean success;
+ char *str;
+
+ str = g_strdup_printf ("Applying %s with timestamp %d", filename, timestamp);
+ show_timestamps_dialog (manager, str);
+ g_free (str);
+
+ my_error = NULL;
+ success = mate_rr_config_apply_from_filename_with_time (priv->rw_screen, filename, timestamp, &my_error);
+ if (success)
+ return TRUE;
+
+ if (g_error_matches (my_error, MATE_RR_ERROR, MATE_RR_ERROR_NO_MATCHING_CONFIG)) {
+ if (no_matching_config_is_an_error)
+ goto fail;
+
+ /* This is not an error; the user probably changed his monitors
+ * and so they don't match any of the stored configurations.
+ */
+ g_error_free (my_error);
+ return TRUE;
+ }
+
+fail:
+ g_propagate_error (error, my_error);
+ return FALSE;
+}
+
+/* This function centralizes the use of mate_rr_config_apply_with_time().
+ *
+ * Applies a configuration and displays an error message if an error happens.
+ * We just return whether setting the configuration succeeded.
+ */
+static gboolean
+apply_configuration_and_display_error (GsdXrandrManager *manager, MateRRConfig *config, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = manager->priv;
+ GError *error;
+ gboolean success;
+
+ error = NULL;
+ success = mate_rr_config_apply_with_time (config, priv->rw_screen, timestamp, &error);
+ if (!success) {
+ log_msg ("Could not switch to the following configuration (timestamp %u): %s\n", timestamp, error->message);
+ log_configuration (config);
+ error_message (manager, _("Could not switch the monitor configuration"), error, NULL);
+ g_error_free (error);
+ }
+
+ return success;
+}
+
+static void
+restore_backup_configuration_without_messages (const char *backup_filename, const char *intended_filename)
+{
+ backup_filename = mate_rr_config_get_backup_filename ();
+ rename (backup_filename, intended_filename);
+}
+
+static void
+restore_backup_configuration (GsdXrandrManager *manager, const char *backup_filename, const char *intended_filename, guint32 timestamp)
+{
+ int saved_errno;
+
+ if (rename (backup_filename, intended_filename) == 0) {
+ GError *error;
+
+ error = NULL;
+ if (!apply_configuration_from_filename (manager, intended_filename, FALSE, timestamp, &error)) {
+ error_message (manager, _("Could not restore the display's configuration"), error, NULL);
+
+ if (error)
+ g_error_free (error);
+ }
+
+ return;
+ }
+
+ saved_errno = errno;
+
+ /* ENOENT means the original file didn't exist. That is *not* an error;
+ * the backup was not created because there wasn't even an original
+ * monitors.xml (such as on a first-time login). Note that *here* there
+ * is a "didn't work" monitors.xml, so we must delete that one.
+ */
+ if (saved_errno == ENOENT)
+ unlink (intended_filename);
+ else {
+ char *msg;
+
+ msg = g_strdup_printf ("Could not rename %s to %s: %s",
+ backup_filename, intended_filename,
+ g_strerror (saved_errno));
+ error_message (manager,
+ _("Could not restore the display's configuration from a backup"),
+ NULL,
+ msg);
+ g_free (msg);
+ }
+
+ unlink (backup_filename);
+}
+
+typedef struct {
+ GsdXrandrManager *manager;
+ GtkWidget *dialog;
+
+ int countdown;
+ int response_id;
+} TimeoutDialog;
+
+static void
+print_countdown_text (TimeoutDialog *timeout)
+{
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (timeout->dialog),
+ ngettext ("The display will be reset to its previous configuration in %d second",
+ "The display will be reset to its previous configuration in %d seconds",
+ timeout->countdown),
+ timeout->countdown);
+}
+
+static gboolean
+timeout_cb (gpointer data)
+{
+ TimeoutDialog *timeout = data;
+
+ timeout->countdown--;
+
+ if (timeout->countdown == 0) {
+ timeout->response_id = GTK_RESPONSE_CANCEL;
+ gtk_main_quit ();
+ } else {
+ print_countdown_text (timeout);
+ }
+
+ return TRUE;
+}
+
+static void
+timeout_response_cb (GtkDialog *dialog, int response_id, gpointer data)
+{
+ TimeoutDialog *timeout = data;
+
+ if (response_id == GTK_RESPONSE_DELETE_EVENT) {
+ /* The user closed the dialog or pressed ESC, revert */
+ timeout->response_id = GTK_RESPONSE_CANCEL;
+ } else
+ timeout->response_id = response_id;
+
+ gtk_main_quit ();
+}
+
+static gboolean
+user_says_things_are_ok (GsdXrandrManager *manager, GdkWindow *parent_window)
+{
+ TimeoutDialog timeout;
+ guint timeout_id;
+
+ timeout.manager = manager;
+
+ timeout.dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Does the display look OK?"));
+
+ timeout.countdown = CONFIRMATION_DIALOG_SECONDS;
+
+ print_countdown_text (&timeout);
+
+ gtk_dialog_add_button (GTK_DIALOG (timeout.dialog), _("_Restore Previous Configuration"), GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (timeout.dialog), _("_Keep This Configuration"), GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (timeout.dialog), GTK_RESPONSE_ACCEPT); /* ah, the optimism */
+
+ g_signal_connect (timeout.dialog, "response",
+ G_CALLBACK (timeout_response_cb),
+ &timeout);
+
+ gtk_widget_realize (timeout.dialog);
+
+ if (parent_window)
+ gdk_window_set_transient_for (gtk_widget_get_window (timeout.dialog), parent_window);
+
+ gtk_widget_show_all (timeout.dialog);
+ /* We don't use g_timeout_add_seconds() since we actually care that the user sees "real" second ticks in the dialog */
+ timeout_id = g_timeout_add (1000,
+ timeout_cb,
+ &timeout);
+ gtk_main ();
+
+ gtk_widget_destroy (timeout.dialog);
+ g_source_remove (timeout_id);
+
+ if (timeout.response_id == GTK_RESPONSE_ACCEPT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+struct confirmation {
+ GsdXrandrManager *manager;
+ GdkWindow *parent_window;
+ guint32 timestamp;
+};
+
+static gboolean
+confirm_with_user_idle_cb (gpointer data)
+{
+ struct confirmation *confirmation = data;
+ char *backup_filename;
+ char *intended_filename;
+
+ backup_filename = mate_rr_config_get_backup_filename ();
+ intended_filename = mate_rr_config_get_intended_filename ();
+
+ if (user_says_things_are_ok (confirmation->manager, confirmation->parent_window))
+ unlink (backup_filename);
+ else
+ restore_backup_configuration (confirmation->manager, backup_filename, intended_filename, confirmation->timestamp);
+
+ g_free (confirmation);
+
+ return FALSE;
+}
+
+static void
+queue_confirmation_by_user (GsdXrandrManager *manager, GdkWindow *parent_window, guint32 timestamp)
+{
+ struct confirmation *confirmation;
+
+ confirmation = g_new (struct confirmation, 1);
+ confirmation->manager = manager;
+ confirmation->parent_window = parent_window;
+ confirmation->timestamp = timestamp;
+
+ g_idle_add (confirm_with_user_idle_cb, confirmation);
+}
+
+static gboolean
+try_to_apply_intended_configuration (GsdXrandrManager *manager, GdkWindow *parent_window, guint32 timestamp, GError **error)
+{
+ char *backup_filename;
+ char *intended_filename;
+ gboolean result;
+
+ /* Try to apply the intended configuration */
+
+ backup_filename = mate_rr_config_get_backup_filename ();
+ intended_filename = mate_rr_config_get_intended_filename ();
+
+ result = apply_configuration_from_filename (manager, intended_filename, FALSE, timestamp, error);
+ if (!result) {
+ error_message (manager, _("The selected configuration for displays could not be applied"), error ? *error : NULL, NULL);
+ restore_backup_configuration_without_messages (backup_filename, intended_filename);
+ goto out;
+ } else {
+ /* We need to return as quickly as possible, so instead of
+ * confirming with the user right here, we do it in an idle
+ * handler. The caller only expects a status for "could you
+ * change the RANDR configuration?", not "is the user OK with it
+ * as well?".
+ */
+ queue_confirmation_by_user (manager, parent_window, timestamp);
+ }
+
+out:
+ g_free (backup_filename);
+ g_free (intended_filename);
+
+ return result;
+}
+
+/* DBus method for org.mate.SettingsDaemon.XRANDR ApplyConfiguration; see gsd-xrandr-manager.xml for the interface definition */
+static gboolean
+gsd_xrandr_manager_apply_configuration (GsdXrandrManager *manager,
+ GError **error)
+{
+ return try_to_apply_intended_configuration (manager, NULL, GDK_CURRENT_TIME, error);
+}
+
+/* DBus method for org.mate.SettingsDaemon.XRANDR_2 ApplyConfiguration; see gsd-xrandr-manager.xml for the interface definition */
+static gboolean
+gsd_xrandr_manager_2_apply_configuration (GsdXrandrManager *manager,
+ gint64 parent_window_id,
+ gint64 timestamp,
+ GError **error)
+{
+ GdkWindow *parent_window;
+ gboolean result;
+
+ if (parent_window_id != 0)
+ parent_window = gdk_window_foreign_new_for_display (gdk_display_get_default (), (GdkNativeWindow) parent_window_id);
+ else
+ parent_window = NULL;
+
+ result = try_to_apply_intended_configuration (manager, parent_window, (guint32) timestamp, error);
+
+ if (parent_window)
+ g_object_unref (parent_window);
+
+ return result;
+}
+
+/* We include this after the definition of gsd_xrandr_manager_apply_configuration() so the prototype will already exist */
+#include "gsd-xrandr-manager-glue.h"
+
+static gboolean
+is_laptop (MateRRScreen *screen, MateOutputInfo *output)
+{
+ MateRROutput *rr_output;
+
+ rr_output = mate_rr_screen_get_output_by_name (screen, output->name);
+ return mate_rr_output_is_laptop (rr_output);
+}
+
+static gboolean
+get_clone_size (MateRRScreen *screen, int *width, int *height)
+{
+ MateRRMode **modes = mate_rr_screen_list_clone_modes (screen);
+ int best_w, best_h;
+ int i;
+
+ best_w = 0;
+ best_h = 0;
+
+ for (i = 0; modes[i] != NULL; ++i) {
+ MateRRMode *mode = modes[i];
+ int w, h;
+
+ w = mate_rr_mode_get_width (mode);
+ h = mate_rr_mode_get_height (mode);
+
+ if (w * h > best_w * best_h) {
+ best_w = w;
+ best_h = h;
+ }
+ }
+
+ if (best_w > 0 && best_h > 0) {
+ if (width)
+ *width = best_w;
+ if (height)
+ *height = best_h;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+print_output (MateOutputInfo *info)
+{
+ g_print (" Output: %s attached to %s\n", info->display_name, info->name);
+ g_print (" status: %s\n", info->on ? "on" : "off");
+ g_print (" width: %d\n", info->width);
+ g_print (" height: %d\n", info->height);
+ g_print (" rate: %d\n", info->rate);
+ g_print (" position: %d %d\n", info->x, info->y);
+}
+
+static void
+print_configuration (MateRRConfig *config, const char *header)
+{
+ int i;
+
+ g_print ("=== %s Configuration ===\n", header);
+ if (!config) {
+ g_print (" none\n");
+ return;
+ }
+
+ for (i = 0; config->outputs[i] != NULL; ++i)
+ print_output (config->outputs[i]);
+}
+
+static gboolean
+config_is_all_off (MateRRConfig *config)
+{
+ int j;
+
+ for (j = 0; config->outputs[j] != NULL; ++j) {
+ if (config->outputs[j]->on) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static MateRRConfig *
+make_clone_setup (MateRRScreen *screen)
+{
+ MateRRConfig *result;
+ int width, height;
+ int i;
+
+ if (!get_clone_size (screen, &width, &height))
+ return NULL;
+
+ result = mate_rr_config_new_current (screen);
+
+ for (i = 0; result->outputs[i] != NULL; ++i) {
+ MateOutputInfo *info = result->outputs[i];
+
+ info->on = FALSE;
+ if (info->connected) {
+ MateRROutput *output =
+ mate_rr_screen_get_output_by_name (screen, info->name);
+ MateRRMode **modes = mate_rr_output_list_modes (output);
+ int j;
+ int best_rate = 0;
+
+ for (j = 0; modes[j] != NULL; ++j) {
+ MateRRMode *mode = modes[j];
+ int w, h;
+
+ w = mate_rr_mode_get_width (mode);
+ h = mate_rr_mode_get_height (mode);
+
+ if (w == width && h == height) {
+ int r = mate_rr_mode_get_freq (mode);
+ if (r > best_rate)
+ best_rate = r;
+ }
+ }
+
+ if (best_rate > 0) {
+ info->on = TRUE;
+ info->width = width;
+ info->height = height;
+ info->rate = best_rate;
+ info->rotation = MATE_RR_ROTATION_0;
+ info->x = 0;
+ info->y = 0;
+ }
+ }
+ }
+
+ if (config_is_all_off (result)) {
+ mate_rr_config_free (result);
+ result = NULL;
+ }
+
+ print_configuration (result, "clone setup");
+
+ return result;
+}
+
+static MateRRMode *
+find_best_mode (MateRROutput *output)
+{
+ MateRRMode *preferred;
+ MateRRMode **modes;
+ int best_size;
+ int best_width, best_height, best_rate;
+ int i;
+ MateRRMode *best_mode;
+
+ preferred = mate_rr_output_get_preferred_mode (output);
+ if (preferred)
+ return preferred;
+
+ modes = mate_rr_output_list_modes (output);
+ if (!modes)
+ return NULL;
+
+ best_size = best_width = best_height = best_rate = 0;
+ best_mode = NULL;
+
+ for (i = 0; modes[i] != NULL; i++) {
+ int w, h, r;
+ int size;
+
+ w = mate_rr_mode_get_width (modes[i]);
+ h = mate_rr_mode_get_height (modes[i]);
+ r = mate_rr_mode_get_freq (modes[i]);
+
+ size = w * h;
+
+ if (size > best_size) {
+ best_size = size;
+ best_width = w;
+ best_height = h;
+ best_rate = r;
+ best_mode = modes[i];
+ } else if (size == best_size) {
+ if (r > best_rate) {
+ best_rate = r;
+ best_mode = modes[i];
+ }
+ }
+ }
+
+ return best_mode;
+}
+
+static gboolean
+turn_on (MateRRScreen *screen,
+ MateOutputInfo *info,
+ int x, int y)
+{
+ MateRROutput *output = mate_rr_screen_get_output_by_name (screen, info->name);
+ MateRRMode *mode = find_best_mode (output);
+
+ if (mode) {
+ info->on = TRUE;
+ info->x = x;
+ info->y = y;
+ info->width = mate_rr_mode_get_width (mode);
+ info->height = mate_rr_mode_get_height (mode);
+ info->rotation = MATE_RR_ROTATION_0;
+ info->rate = mate_rr_mode_get_freq (mode);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static MateRRConfig *
+make_laptop_setup (MateRRScreen *screen)
+{
+ /* Turn on the laptop, disable everything else */
+ MateRRConfig *result = mate_rr_config_new_current (screen);
+ int i;
+
+ for (i = 0; result->outputs[i] != NULL; ++i) {
+ MateOutputInfo *info = result->outputs[i];
+
+ if (is_laptop (screen, info)) {
+ if (!turn_on (screen, info, 0, 0)) {
+ mate_rr_config_free (result);
+ result = NULL;
+ break;
+ }
+ }
+ else {
+ info->on = FALSE;
+ }
+ }
+
+ if (config_is_all_off (result)) {
+ mate_rr_config_free (result);
+ result = NULL;
+ }
+
+ print_configuration (result, "Laptop setup");
+
+ /* FIXME - Maybe we should return NULL if there is more than
+ * one connected "laptop" screen?
+ */
+ return result;
+
+}
+
+static int
+turn_on_and_get_rightmost_offset (MateRRScreen *screen, MateOutputInfo *info, int x)
+{
+ if (turn_on (screen, info, x, 0))
+ x += info->width;
+
+ return x;
+}
+
+static MateRRConfig *
+make_xinerama_setup (MateRRScreen *screen)
+{
+ /* Turn on everything that has a preferred mode, and
+ * position it from left to right
+ */
+ MateRRConfig *result = mate_rr_config_new_current (screen);
+ int i;
+ int x;
+
+ x = 0;
+ for (i = 0; result->outputs[i] != NULL; ++i) {
+ MateOutputInfo *info = result->outputs[i];
+
+ if (is_laptop (screen, info))
+ x = turn_on_and_get_rightmost_offset (screen, info, x);
+ }
+
+ for (i = 0; result->outputs[i] != NULL; ++i) {
+ MateOutputInfo *info = result->outputs[i];
+
+ if (info->connected && !is_laptop (screen, info))
+ x = turn_on_and_get_rightmost_offset (screen, info, x);
+ }
+
+ if (config_is_all_off (result)) {
+ mate_rr_config_free (result);
+ result = NULL;
+ }
+
+ print_configuration (result, "xinerama setup");
+
+ return result;
+}
+
+static MateRRConfig *
+make_other_setup (MateRRScreen *screen)
+{
+ /* Turn off all laptops, and make all external monitors clone
+ * from (0, 0)
+ */
+
+ MateRRConfig *result = mate_rr_config_new_current (screen);
+ int i;
+
+ for (i = 0; result->outputs[i] != NULL; ++i) {
+ MateOutputInfo *info = result->outputs[i];
+
+ if (is_laptop (screen, info)) {
+ info->on = FALSE;
+ }
+ else {
+ if (info->connected)
+ turn_on (screen, info, 0, 0);
+ }
+ }
+
+ if (config_is_all_off (result)) {
+ mate_rr_config_free (result);
+ result = NULL;
+ }
+
+ print_configuration (result, "other setup");
+
+ return result;
+}
+
+static GPtrArray *
+sanitize (GsdXrandrManager *manager, GPtrArray *array)
+{
+ int i;
+ GPtrArray *new;
+
+ g_debug ("before sanitizing");
+
+ for (i = 0; i < array->len; ++i) {
+ if (array->pdata[i]) {
+ print_configuration (array->pdata[i], "before");
+ }
+ }
+
+
+ /* Remove configurations that are duplicates of
+ * configurations earlier in the cycle
+ */
+ for (i = 0; i < array->len; i++) {
+ int j;
+
+ for (j = i + 1; j < array->len; j++) {
+ MateRRConfig *this = array->pdata[j];
+ MateRRConfig *other = array->pdata[i];
+
+ if (this && other && mate_rr_config_equal (this, other)) {
+ g_debug ("removing duplicate configuration");
+ mate_rr_config_free (this);
+ array->pdata[j] = NULL;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < array->len; ++i) {
+ MateRRConfig *config = array->pdata[i];
+
+ if (config && config_is_all_off (config)) {
+ g_debug ("removing configuration as all outputs are off");
+ mate_rr_config_free (array->pdata[i]);
+ array->pdata[i] = NULL;
+ }
+ }
+
+ /* Do a final sanitization pass. This will remove configurations that
+ * don't fit in the framebuffer's Virtual size.
+ */
+
+ for (i = 0; i < array->len; i++) {
+ MateRRConfig *config = array->pdata[i];
+
+ if (config) {
+ GError *error;
+
+ error = NULL;
+ if (!mate_rr_config_applicable (config, manager->priv->rw_screen, &error)) { /* NULL-GError */
+ g_debug ("removing configuration which is not applicable because %s", error->message);
+ g_error_free (error);
+
+ mate_rr_config_free (config);
+ array->pdata[i] = NULL;
+ }
+ }
+ }
+
+ /* Remove NULL configurations */
+ new = g_ptr_array_new ();
+
+ for (i = 0; i < array->len; ++i) {
+ if (array->pdata[i]) {
+ g_ptr_array_add (new, array->pdata[i]);
+ print_configuration (array->pdata[i], "Final");
+ }
+ }
+
+ if (new->len > 0) {
+ g_ptr_array_add (new, NULL);
+ } else {
+ g_ptr_array_free (new, TRUE);
+ new = NULL;
+ }
+
+ g_ptr_array_free (array, TRUE);
+
+ return new;
+}
+
+static void
+generate_fn_f7_configs (GsdXrandrManager *mgr)
+{
+ GPtrArray *array = g_ptr_array_new ();
+ MateRRScreen *screen = mgr->priv->rw_screen;
+
+ g_debug ("Generating configurations");
+
+ /* Free any existing list of configurations */
+ if (mgr->priv->fn_f7_configs) {
+ int i;
+
+ for (i = 0; mgr->priv->fn_f7_configs[i] != NULL; ++i)
+ mate_rr_config_free (mgr->priv->fn_f7_configs[i]);
+ g_free (mgr->priv->fn_f7_configs);
+
+ mgr->priv->fn_f7_configs = NULL;
+ mgr->priv->current_fn_f7_config = -1;
+ }
+
+ g_ptr_array_add (array, mate_rr_config_new_current (screen));
+ g_ptr_array_add (array, make_clone_setup (screen));
+ g_ptr_array_add (array, make_xinerama_setup (screen));
+ g_ptr_array_add (array, make_laptop_setup (screen));
+ g_ptr_array_add (array, make_other_setup (screen));
+
+ array = sanitize (mgr, array);
+
+ if (array) {
+ mgr->priv->fn_f7_configs = (MateRRConfig **)g_ptr_array_free (array, FALSE);
+ mgr->priv->current_fn_f7_config = 0;
+ }
+}
+
+static void
+error_message (GsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text)
+{
+#ifdef HAVE_LIBMATENOTIFY
+ GsdXrandrManagerPrivate *priv = mgr->priv;
+ NotifyNotification *notification;
+
+ g_assert (error_to_display == NULL || secondary_text == NULL);
+
+ if (priv->status_icon)
+ notification = notify_notification_new_with_status_icon (primary_text,
+ error_to_display ? error_to_display->message : secondary_text,
+ GSD_XRANDR_ICON_NAME,
+ priv->status_icon);
+ else
+ notification = notify_notification_new (primary_text,
+ error_to_display ? error_to_display->message : secondary_text,
+ GSD_XRANDR_ICON_NAME,
+ NULL);
+
+ notify_notification_show (notification, NULL); /* NULL-GError */
+#else
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ "%s", primary_text);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
+ error_to_display ? error_to_display->message : secondary_text);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+#endif /* HAVE_LIBMATENOTIFY */
+}
+
+static void
+handle_fn_f7 (GsdXrandrManager *mgr, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = mgr->priv;
+ MateRRScreen *screen = priv->rw_screen;
+ MateRRConfig *current;
+ GError *error;
+
+ /* Theory of fn-F7 operation
+ *
+ * We maintain a datastructure "fn_f7_status", that contains
+ * a list of MateRRConfig's. Each of the MateRRConfigs has a
+ * mode (or "off") for each connected output.
+ *
+ * When the user hits fn-F7, we cycle to the next MateRRConfig
+ * in the data structure. If the data structure does not exist, it
+ * is generated. If the configs in the data structure do not match
+ * the current hardware reality, it is regenerated.
+ *
+ */
+ g_debug ("Handling fn-f7");
+
+ log_open ();
+ log_msg ("Handling XF86Display hotkey - timestamp %u\n", timestamp);
+
+ error = NULL;
+ if (!mate_rr_screen_refresh (screen, &error) && error) {
+ char *str;
+
+ str = g_strdup_printf (_("Could not refresh the screen information: %s"), error->message);
+ g_error_free (error);
+
+ log_msg ("%s\n", str);
+ error_message (mgr, str, NULL, _("Trying to switch the monitor configuration anyway."));
+ g_free (str);
+ }
+
+ if (!priv->fn_f7_configs) {
+ log_msg ("Generating stock configurations:\n");
+ generate_fn_f7_configs (mgr);
+ log_configurations (priv->fn_f7_configs);
+ }
+
+ current = mate_rr_config_new_current (screen);
+
+ if (priv->fn_f7_configs &&
+ (!mate_rr_config_match (current, priv->fn_f7_configs[0]) ||
+ !mate_rr_config_equal (current, priv->fn_f7_configs[mgr->priv->current_fn_f7_config]))) {
+ /* Our view of the world is incorrect, so regenerate the
+ * configurations
+ */
+ generate_fn_f7_configs (mgr);
+ log_msg ("Regenerated stock configurations:\n");
+ log_configurations (priv->fn_f7_configs);
+ }
+
+ mate_rr_config_free (current);
+
+ if (priv->fn_f7_configs) {
+ guint32 server_timestamp;
+ gboolean success;
+
+ mgr->priv->current_fn_f7_config++;
+
+ if (priv->fn_f7_configs[mgr->priv->current_fn_f7_config] == NULL)
+ mgr->priv->current_fn_f7_config = 0;
+
+ g_debug ("cycling to next configuration (%d)", mgr->priv->current_fn_f7_config);
+
+ print_configuration (priv->fn_f7_configs[mgr->priv->current_fn_f7_config], "new config");
+
+ g_debug ("applying");
+
+ /* See https://bugzilla.gnome.org/show_bug.cgi?id=610482
+ *
+ * Sometimes we'll get two rapid XF86Display keypress events,
+ * but their timestamps will be out of order with respect to the
+ * RANDR timestamps. This *may* be due to stupid BIOSes sending
+ * out display-switch keystrokes "to make Windows work".
+ *
+ * The X server will error out if the timestamp provided is
+ * older than a previous change configuration timestamp. We
+ * assume here that we do want this event to go through still,
+ * since kernel timestamps may be skewed wrt the X server.
+ */
+ mate_rr_screen_get_timestamps (screen, NULL, &server_timestamp);
+ if (timestamp < server_timestamp)
+ timestamp = server_timestamp;
+
+ success = apply_configuration_and_display_error (mgr, priv->fn_f7_configs[mgr->priv->current_fn_f7_config], timestamp);
+
+ if (success) {
+ log_msg ("Successfully switched to configuration (timestamp %u):\n", timestamp);
+ log_configuration (priv->fn_f7_configs[mgr->priv->current_fn_f7_config]);
+ }
+ }
+ else {
+ g_debug ("no configurations generated");
+ }
+
+ log_close ();
+
+ g_debug ("done handling fn-f7");
+}
+
+static MateOutputInfo *
+get_laptop_output_info (MateRRScreen *screen, MateRRConfig *config)
+{
+ int i;
+
+ for (i = 0; config->outputs[i] != NULL; i++) {
+ MateOutputInfo *info;
+
+ info = config->outputs[i];
+ if (is_laptop (screen, info))
+ return info;
+ }
+
+ return NULL;
+
+}
+
+static MateRRRotation
+get_next_rotation (MateRRRotation allowed_rotations, MateRRRotation current_rotation)
+{
+ int i;
+ int current_index;
+
+ /* First, find the index of the current rotation */
+
+ current_index = -1;
+
+ for (i = 0; i < G_N_ELEMENTS (possible_rotations); i++) {
+ MateRRRotation r;
+
+ r = possible_rotations[i];
+ if (r == current_rotation) {
+ current_index = i;
+ break;
+ }
+ }
+
+ if (current_index == -1) {
+ /* Huh, the current_rotation was not one of the supported rotations. Bail out. */
+ return current_rotation;
+ }
+
+ /* Then, find the next rotation that is allowed */
+
+ i = (current_index + 1) % G_N_ELEMENTS (possible_rotations);
+
+ while (1) {
+ MateRRRotation r;
+
+ r = possible_rotations[i];
+ if (r == current_rotation) {
+ /* We wrapped around and no other rotation is suported. Bummer. */
+ return current_rotation;
+ } else if (r & allowed_rotations)
+ return r;
+
+ i = (i + 1) % G_N_ELEMENTS (possible_rotations);
+ }
+}
+
+/* We use this when the XF86RotateWindows key is pressed. That key is present
+ * on some tablet PCs; they use it so that the user can rotate the tablet
+ * easily.
+ */
+static void
+handle_rotate_windows (GsdXrandrManager *mgr, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = mgr->priv;
+ MateRRScreen *screen = priv->rw_screen;
+ MateRRConfig *current;
+ MateOutputInfo *rotatable_output_info;
+ int num_allowed_rotations;
+ MateRRRotation allowed_rotations;
+ MateRRRotation next_rotation;
+
+ g_debug ("Handling XF86RotateWindows");
+
+ /* Which output? */
+
+ current = mate_rr_config_new_current (screen);
+
+ rotatable_output_info = get_laptop_output_info (screen, current);
+ if (rotatable_output_info == NULL) {
+ g_debug ("No laptop outputs found to rotate; XF86RotateWindows key will do nothing");
+ goto out;
+ }
+
+ /* Which rotation? */
+
+ get_allowed_rotations_for_output (current, priv->rw_screen, rotatable_output_info, &num_allowed_rotations, &allowed_rotations);
+ next_rotation = get_next_rotation (allowed_rotations, rotatable_output_info->rotation);
+
+ if (next_rotation == rotatable_output_info->rotation) {
+ g_debug ("No rotations are supported other than the current one; XF86RotateWindows key will do nothing");
+ goto out;
+ }
+
+ /* Rotate */
+
+ rotatable_output_info->rotation = next_rotation;
+
+ apply_configuration_and_display_error (mgr, current, timestamp);
+
+out:
+ mate_rr_config_free (current);
+}
+
+static GdkFilterReturn
+event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ GsdXrandrManager *manager = data;
+ XEvent *xev = (XEvent *) xevent;
+
+ if (!manager->priv->running)
+ return GDK_FILTER_CONTINUE;
+
+ /* verify we have a key event */
+ if (xev->xany.type != KeyPress && xev->xany.type != KeyRelease)
+ return GDK_FILTER_CONTINUE;
+
+ if (xev->xany.type == KeyPress) {
+ if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode)
+ handle_fn_f7 (manager, xev->xkey.time);
+ else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode)
+ handle_rotate_windows (manager, xev->xkey.time);
+
+ return GDK_FILTER_CONTINUE;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+refresh_tray_icon_menu_if_active (GsdXrandrManager *manager, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = manager->priv;
+
+ if (priv->popup_menu) {
+ gtk_menu_shell_cancel (GTK_MENU_SHELL (priv->popup_menu)); /* status_icon_popup_menu_selection_done_cb() will free everything */
+ status_icon_popup_menu (manager, 0, timestamp);
+ }
+}
+
+static void
+auto_configure_outputs (GsdXrandrManager *manager, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = manager->priv;
+ MateRRConfig *config;
+ int i;
+ GList *just_turned_on;
+ GList *l;
+ int x;
+ GError *error;
+ gboolean applicable;
+
+ config = mate_rr_config_new_current (priv->rw_screen);
+
+ /* For outputs that are connected and on (i.e. they have a CRTC assigned
+ * to them, so they are getting a signal), we leave them as they are
+ * with their current modes.
+ *
+ * For other outputs, we will turn on connected-but-off outputs and turn
+ * off disconnected-but-on outputs.
+ *
+ * FIXME: If an output remained connected+on, it would be nice to ensure
+ * that the output's CRTCs still has a reasonable mode (think of
+ * changing one monitor for another with different capabilities).
+ */
+
+ just_turned_on = NULL;
+
+ for (i = 0; config->outputs[i] != NULL; i++) {
+ MateOutputInfo *output = config->outputs[i];
+
+ if (output->connected && !output->on) {
+ output->on = TRUE;
+ output->rotation = MATE_RR_ROTATION_0;
+ just_turned_on = g_list_prepend (just_turned_on, GINT_TO_POINTER (i));
+ } else if (!output->connected && output->on)
+ output->on = FALSE;
+ }
+
+ /* Now, lay out the outputs from left to right. Put first the outputs
+ * which remained on; put last the outputs that were newly turned on.
+ */
+
+ x = 0;
+
+ /* First, outputs that remained on */
+
+ for (i = 0; config->outputs[i] != NULL; i++) {
+ MateOutputInfo *output = config->outputs[i];
+
+ if (g_list_find (just_turned_on, GINT_TO_POINTER (i)))
+ continue;
+
+ if (output->on) {
+ g_assert (output->connected);
+
+ output->x = x;
+ output->y = 0;
+
+ x += output->width;
+ }
+ }
+
+ /* Second, outputs that were newly-turned on */
+
+ for (l = just_turned_on; l; l = l->next) {
+ MateOutputInfo *output;
+
+ i = GPOINTER_TO_INT (l->data);
+ output = config->outputs[i];
+
+ g_assert (output->on && output->connected);
+
+ output->x = x;
+ output->y = 0;
+
+ /* since the output was off, use its preferred width/height (it doesn't have a real width/height yet) */
+ output->width = output->pref_width;
+ output->height = output->pref_height;
+
+ x += output->width;
+ }
+
+ /* Check if we have a large enough framebuffer size. If not, turn off
+ * outputs from right to left until we reach a usable size.
+ */
+
+ just_turned_on = g_list_reverse (just_turned_on); /* now the outputs here are from right to left */
+
+ l = just_turned_on;
+ while (1) {
+ MateOutputInfo *output;
+ gboolean is_bounds_error;
+
+ error = NULL;
+ applicable = mate_rr_config_applicable (config, priv->rw_screen, &error);
+
+ if (applicable)
+ break;
+
+ is_bounds_error = g_error_matches (error, MATE_RR_ERROR, MATE_RR_ERROR_BOUNDS_ERROR);
+ g_error_free (error);
+
+ if (!is_bounds_error)
+ break;
+
+ if (l) {
+ i = GPOINTER_TO_INT (l->data);
+ l = l->next;
+
+ output = config->outputs[i];
+ output->on = FALSE;
+ } else
+ break;
+ }
+
+ /* Apply the configuration! */
+
+ if (applicable)
+ apply_configuration_and_display_error (manager, config, timestamp);
+
+ g_list_free (just_turned_on);
+ mate_rr_config_free (config);
+
+ /* Finally, even though we did a best-effort job in sanitizing the
+ * outputs, we don't know the physical layout of the monitors. We'll
+ * start the display capplet so that the user can tweak things to his
+ * liking.
+ */
+
+#if 0
+ /* FIXME: This is disabled for now. The capplet is not a single-instance application.
+ * If you do this:
+ *
+ * 1. Start the display capplet
+ *
+ * 2. Plug an extra monitor
+ *
+ * 3. Hit the "Detect displays" button
+ *
+ * Then we will get a RANDR event because X re-probes the outputs. We don't want to
+ * start up a second display capplet right there!
+ */
+
+ run_display_capplet (NULL);
+#endif
+}
+
+static void
+apply_color_profiles (void)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* run the mate-color-manager apply program */
+ ret = g_spawn_command_line_async (BINDIR "/gcm-apply", &error);
+ if (!ret) {
+ /* only print the warning if the binary is installed */
+ if (error->code != G_SPAWN_ERROR_NOENT) {
+ g_warning ("failed to apply color profiles: %s", error->message);
+ }
+ g_error_free (error);
+ }
+}
+
+static void
+on_randr_event (MateRRScreen *screen, gpointer data)
+{
+ GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+ GsdXrandrManagerPrivate *priv = manager->priv;
+ guint32 change_timestamp, config_timestamp;
+
+ if (!priv->running)
+ return;
+
+ mate_rr_screen_get_timestamps (screen, &change_timestamp, &config_timestamp);
+
+ log_open ();
+ log_msg ("Got RANDR event with timestamps change=%u %c config=%u\n",
+ change_timestamp,
+ timestamp_relationship (change_timestamp, config_timestamp),
+ config_timestamp);
+
+ if (change_timestamp >= config_timestamp) {
+ /* The event is due to an explicit configuration change.
+ *
+ * If the change was performed by us, then we need to do nothing.
+ *
+ * If the change was done by some other X client, we don't need
+ * to do anything, either; the screen is already configured.
+ */
+ show_timestamps_dialog (manager, "ignoring since change > config");
+ log_msg (" Ignoring event since change >= config\n");
+ } else {
+ /* Here, config_timestamp > change_timestamp. This means that
+ * the screen got reconfigured because of hotplug/unplug; the X
+ * server is just notifying us, and we need to configure the
+ * outputs in a sane way.
+ */
+
+ char *intended_filename;
+ GError *error;
+ gboolean success;
+
+ show_timestamps_dialog (manager, "need to deal with reconfiguration, as config > change");
+
+ intended_filename = mate_rr_config_get_intended_filename ();
+
+ error = NULL;
+ success = apply_configuration_from_filename (manager, intended_filename, TRUE, config_timestamp, &error);
+ g_free (intended_filename);
+
+ if (!success) {
+ /* We don't bother checking the error type.
+ *
+ * Both G_FILE_ERROR_NOENT and
+ * MATE_RR_ERROR_NO_MATCHING_CONFIG would mean, "there
+ * was no configuration to apply, or none that matched
+ * the current outputs", and in that case we need to run
+ * our fallback.
+ *
+ * Any other error means "we couldn't do the smart thing
+ * of using a previously- saved configuration, anyway,
+ * for some other reason. In that case, we also need to
+ * run our fallback to avoid leaving the user with a
+ * bogus configuration.
+ */
+
+ if (error)
+ g_error_free (error);
+
+ if (config_timestamp != priv->last_config_timestamp) {
+ priv->last_config_timestamp = config_timestamp;
+ auto_configure_outputs (manager, config_timestamp);
+ log_msg (" Automatically configured outputs to deal with event\n");
+ } else
+ log_msg (" Ignored event as old and new config timestamps are the same\n");
+ } else
+ log_msg ("Applied stored configuration to deal with event\n");
+ }
+
+ /* poke mate-color-manager */
+ apply_color_profiles ();
+
+ refresh_tray_icon_menu_if_active (manager, MAX (change_timestamp, config_timestamp));
+
+ log_close ();
+}
+
+static void
+run_display_capplet (GtkWidget *widget)
+{
+ GdkScreen *screen;
+ GError *error;
+
+ if (widget)
+ screen = gtk_widget_get_screen (widget);
+ else
+ screen = gdk_screen_get_default ();
+
+ error = NULL;
+ if (!gdk_spawn_command_line_on_screen (screen, GSD_XRANDR_DISPLAY_CAPPLET, &error)) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "<span weight=\"bold\" size=\"larger\">"
+ "Display configuration could not be run"
+ "</span>\n\n"
+ "%s", error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ g_error_free (error);
+ }
+}
+
+static void
+popup_menu_configure_display_cb (GtkMenuItem *item, gpointer data)
+{
+ run_display_capplet (GTK_WIDGET (item));
+}
+
+static void
+status_icon_popup_menu_selection_done_cb (GtkMenuShell *menu_shell, gpointer data)
+{
+ GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+
+ gtk_widget_destroy (priv->popup_menu);
+ priv->popup_menu = NULL;
+
+ mate_rr_labeler_hide (priv->labeler);
+ g_object_unref (priv->labeler);
+ priv->labeler = NULL;
+
+ mate_rr_config_free (priv->configuration);
+ priv->configuration = NULL;
+}
+
+#define OUTPUT_TITLE_ITEM_BORDER 2
+#define OUTPUT_TITLE_ITEM_PADDING 4
+
+/* This is an expose-event hander for the title label for each MateRROutput.
+ * We want each title to have a colored background, so we paint that background, then
+ * return FALSE to let GtkLabel expose itself (i.e. paint the label's text), and then
+ * we have a signal_connect_after handler as well. See the comments below
+ * to see why that "after" handler is needed.
+ */
+static gboolean
+output_title_label_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ MateOutputInfo *output;
+ GdkColor color;
+ cairo_t *cr;
+ GtkAllocation allocation;
+
+ g_assert (GTK_IS_LABEL (widget));
+
+ output = g_object_get_data (G_OBJECT (widget), "output");
+ g_assert (output != NULL);
+
+ g_assert (priv->labeler != NULL);
+
+ /* Draw a black rectangular border, filled with the color that corresponds to this output */
+
+ mate_rr_labeler_get_color_for_output (priv->labeler, output, &color);
+
+ cr = gdk_cairo_create (gtk_widget_get_window (widget));
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_set_line_width (cr, OUTPUT_TITLE_ITEM_BORDER);
+ gtk_widget_get_allocation (widget, &allocation);
+ cairo_rectangle (cr,
+ allocation.x + OUTPUT_TITLE_ITEM_BORDER / 2.0,
+ allocation.y + OUTPUT_TITLE_ITEM_BORDER / 2.0,
+ allocation.width - OUTPUT_TITLE_ITEM_BORDER,
+ allocation.height - OUTPUT_TITLE_ITEM_BORDER);
+ cairo_stroke (cr);
+
+ gdk_cairo_set_source_color (cr, &color);
+ cairo_rectangle (cr,
+ allocation.x + OUTPUT_TITLE_ITEM_BORDER,
+ allocation.y + OUTPUT_TITLE_ITEM_BORDER,
+ allocation.width - 2 * OUTPUT_TITLE_ITEM_BORDER,
+ allocation.height - 2 * OUTPUT_TITLE_ITEM_BORDER);
+
+ cairo_fill (cr);
+
+ /* We want the label to always show up as if it were sensitive
+ * ("style->fg[GTK_STATE_NORMAL]"), even though the label is insensitive
+ * due to being inside an insensitive menu item. So, here we have a
+ * HACK in which we frob the label's state directly. GtkLabel's expose
+ * handler will be run after this function, so it will think that the
+ * label is in GTK_STATE_NORMAL. We reset the label's state back to
+ * insensitive in output_title_label_after_expose_event_cb().
+ *
+ * Yay for fucking with GTK+'s internals.
+ */
+
+ gtk_widget_set_state (widget, GTK_STATE_NORMAL);
+
+ return FALSE;
+}
+
+/* See the comment in output_title_event_box_expose_event_cb() about this funny label widget */
+static gboolean
+output_title_label_after_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ g_assert (GTK_IS_LABEL (widget));
+ gtk_widget_set_state (widget, GTK_STATE_INSENSITIVE);
+
+ return FALSE;
+}
+
+static void
+title_item_size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer data)
+{
+ /* When GtkMenu does size_request on its items, it asks them for their "toggle size",
+ * which will be non-zero when there are check/radio items. GtkMenu remembers
+ * the largest of those sizes. During the size_allocate pass, GtkMenu calls
+ * gtk_menu_item_toggle_size_allocate() with that value, to tell the menu item
+ * that it should later paint its child a bit to the right of its edge.
+ *
+ * However, we want the "title" menu items for each RANDR output to span the *whole*
+ * allocation of the menu item, not just the "allocation minus toggle" area.
+ *
+ * So, we let the menu item size_allocate itself as usual, but this
+ * callback gets run afterward. Here we hack a toggle size of 0 into
+ * the menu item, and size_allocate it by hand *again*. We also need to
+ * avoid recursing into this function.
+ */
+
+ g_assert (GTK_IS_MENU_ITEM (widget));
+
+ gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (widget), 0);
+
+ g_signal_handlers_block_by_func (widget, title_item_size_allocate_cb, NULL);
+
+ /* Sigh. There is no way to turn on GTK_ALLOC_NEEDED outside of GTK+
+ * itself; also, since calling size_allocate on a widget with the same
+ * allcation is a no-op, we need to allocate with a "different" size
+ * first.
+ */
+
+ allocation->width++;
+ gtk_widget_size_allocate (widget, allocation);
+
+ allocation->width--;
+ gtk_widget_size_allocate (widget, allocation);
+
+ g_signal_handlers_unblock_by_func (widget, title_item_size_allocate_cb, NULL);
+}
+
+static GtkWidget *
+make_menu_item_for_output_title (GsdXrandrManager *manager, MateOutputInfo *output)
+{
+ GtkWidget *item;
+ GtkWidget *label;
+ char *str;
+ GdkColor black = { 0, 0, 0, 0 };
+
+ item = gtk_menu_item_new ();
+
+ g_signal_connect (item, "size-allocate",
+ G_CALLBACK (title_item_size_allocate_cb), NULL);
+
+ str = g_markup_printf_escaped ("<b>%s</b>", output->display_name);
+ label = gtk_label_new (NULL);
+ gtk_label_set_markup (GTK_LABEL (label), str);
+ g_free (str);
+
+ /* Make the label explicitly black. We don't want it to follow the
+ * theme's colors, since the label is always shown against a light
+ * pastel background. See bgo#556050
+ */
+ gtk_widget_modify_fg (label, gtk_widget_get_state (label), &black);
+
+ /* Add padding around the label to fit the box that we'll draw for color-coding */
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (label),
+ OUTPUT_TITLE_ITEM_BORDER + OUTPUT_TITLE_ITEM_PADDING,
+ OUTPUT_TITLE_ITEM_BORDER + OUTPUT_TITLE_ITEM_PADDING);
+
+ gtk_container_add (GTK_CONTAINER (item), label);
+
+ /* We want to paint a colored box as the background of the label, so we connect
+ * to its expose-event signal. See the comment in *** to see why need to connect
+ * to the label both 'before' and 'after'.
+ */
+ g_signal_connect (label, "expose-event",
+ G_CALLBACK (output_title_label_expose_event_cb), manager);
+ g_signal_connect_after (label, "expose-event",
+ G_CALLBACK (output_title_label_after_expose_event_cb), manager);
+
+ g_object_set_data (G_OBJECT (label), "output", output);
+
+ gtk_widget_set_sensitive (item, FALSE); /* the title is not selectable */
+ gtk_widget_show_all (item);
+
+ return item;
+}
+
+static void
+get_allowed_rotations_for_output (MateRRConfig *config,
+ MateRRScreen *rr_screen,
+ MateOutputInfo *output,
+ int *out_num_rotations,
+ MateRRRotation *out_rotations)
+{
+ MateRRRotation current_rotation;
+ int i;
+
+ *out_num_rotations = 0;
+ *out_rotations = 0;
+
+ current_rotation = output->rotation;
+
+ /* Yay for brute force */
+
+ for (i = 0; i < G_N_ELEMENTS (possible_rotations); i++) {
+ MateRRRotation rotation_to_test;
+
+ rotation_to_test = possible_rotations[i];
+
+ output->rotation = rotation_to_test;
+
+ if (mate_rr_config_applicable (config, rr_screen, NULL)) { /* NULL-GError */
+ (*out_num_rotations)++;
+ (*out_rotations) |= rotation_to_test;
+ }
+ }
+
+ output->rotation = current_rotation;
+
+ if (*out_num_rotations == 0 || *out_rotations == 0) {
+ g_warning ("Huh, output %p says it doesn't support any rotations, and yet it has a current rotation?", output);
+ *out_num_rotations = 1;
+ *out_rotations = output->rotation;
+ }
+}
+
+static void
+add_unsupported_rotation_item (GsdXrandrManager *manager)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ GtkWidget *item;
+ GtkWidget *label;
+ gchar *markup;
+
+ item = gtk_menu_item_new ();
+
+ label = gtk_label_new (NULL);
+ markup = g_strdup_printf ("<i>%s</i>", _("Rotation not supported"));
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ g_free (markup);
+ gtk_container_add (GTK_CONTAINER (item), label);
+
+ gtk_widget_show_all (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
+}
+
+static void
+ensure_current_configuration_is_saved (void)
+{
+ MateRRScreen *rr_screen;
+ MateRRConfig *rr_config;
+
+ /* Normally, mate_rr_config_save() creates a backup file based on the
+ * old monitors.xml. However, if *that* file didn't exist, there is
+ * nothing from which to create a backup. So, here we'll save the
+ * current/unchanged configuration and then let our caller call
+ * mate_rr_config_save() again with the new/changed configuration, so
+ * that there *will* be a backup file in the end.
+ */
+
+ rr_screen = mate_rr_screen_new (gdk_screen_get_default (), NULL, NULL, NULL); /* NULL-GError */
+ if (!rr_screen)
+ return;
+
+ rr_config = mate_rr_config_new_current (rr_screen);
+ mate_rr_config_save (rr_config, NULL); /* NULL-GError */
+
+ mate_rr_config_free (rr_config);
+ mate_rr_screen_destroy (rr_screen);
+}
+
+static void
+output_rotation_item_activate_cb (GtkCheckMenuItem *item, gpointer data)
+{
+ GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ MateOutputInfo *output;
+ MateRRRotation rotation;
+ GError *error;
+
+ /* Not interested in deselected items */
+ if (!gtk_check_menu_item_get_active (item))
+ return;
+
+ ensure_current_configuration_is_saved ();
+
+ output = g_object_get_data (G_OBJECT (item), "output");
+ rotation = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "rotation"));
+
+ output->rotation = rotation;
+
+ error = NULL;
+ if (!mate_rr_config_save (priv->configuration, &error)) {
+ error_message (manager, _("Could not save monitor configuration"), error, NULL);
+ if (error)
+ g_error_free (error);
+
+ return;
+ }
+
+ try_to_apply_intended_configuration (manager, NULL, gtk_get_current_event_time (), NULL); /* NULL-GError */
+}
+
+static void
+add_items_for_rotations (GsdXrandrManager *manager, MateOutputInfo *output, MateRRRotation allowed_rotations)
+{
+ typedef struct {
+ MateRRRotation rotation;
+ const char * name;
+ } RotationInfo;
+ static const RotationInfo rotations[] = {
+ { MATE_RR_ROTATION_0, N_("Normal") },
+ { MATE_RR_ROTATION_90, N_("Left") },
+ { MATE_RR_ROTATION_270, N_("Right") },
+ { MATE_RR_ROTATION_180, N_("Upside Down") },
+ /* We don't allow REFLECT_X or REFLECT_Y for now, as mate-display-properties doesn't allow them, either */
+ };
+
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ int i;
+ GSList *group;
+ GtkWidget *active_item;
+ gulong active_item_activate_id;
+
+ group = NULL;
+ active_item = NULL;
+ active_item_activate_id = 0;
+
+ for (i = 0; i < G_N_ELEMENTS (rotations); i++) {
+ MateRRRotation rot;
+ GtkWidget *item;
+ gulong activate_id;
+
+ rot = rotations[i].rotation;
+
+ if ((allowed_rotations & rot) == 0) {
+ /* don't display items for rotations which are
+ * unavailable. Their availability is not under the
+ * user's control, anyway.
+ */
+ continue;
+ }
+
+ item = gtk_radio_menu_item_new_with_label (group, _(rotations[i].name));
+ gtk_widget_show_all (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
+
+ g_object_set_data (G_OBJECT (item), "output", output);
+ g_object_set_data (G_OBJECT (item), "rotation", GINT_TO_POINTER (rot));
+
+ activate_id = g_signal_connect (item, "activate",
+ G_CALLBACK (output_rotation_item_activate_cb), manager);
+
+ group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
+
+ if (rot == output->rotation) {
+ active_item = item;
+ active_item_activate_id = activate_id;
+ }
+ }
+
+ if (active_item) {
+ /* Block the signal temporarily so our callback won't be called;
+ * we are just setting up the UI.
+ */
+ g_signal_handler_block (active_item, active_item_activate_id);
+
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (active_item), TRUE);
+
+ g_signal_handler_unblock (active_item, active_item_activate_id);
+ }
+
+}
+
+static void
+add_rotation_items_for_output (GsdXrandrManager *manager, MateOutputInfo *output)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ int num_rotations;
+ MateRRRotation rotations;
+
+ get_allowed_rotations_for_output (priv->configuration, priv->rw_screen, output, &num_rotations, &rotations);
+
+ if (num_rotations == 1)
+ add_unsupported_rotation_item (manager);
+ else
+ add_items_for_rotations (manager, output, rotations);
+}
+
+static void
+add_menu_items_for_output (GsdXrandrManager *manager, MateOutputInfo *output)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ GtkWidget *item;
+
+ item = make_menu_item_for_output_title (manager, output);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
+
+ add_rotation_items_for_output (manager, output);
+}
+
+static void
+add_menu_items_for_outputs (GsdXrandrManager *manager)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ int i;
+
+ for (i = 0; priv->configuration->outputs[i] != NULL; i++) {
+ if (priv->configuration->outputs[i]->connected)
+ add_menu_items_for_output (manager, priv->configuration->outputs[i]);
+ }
+}
+
+static void
+status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timestamp)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ GtkWidget *item;
+
+ g_assert (priv->configuration == NULL);
+ priv->configuration = mate_rr_config_new_current (priv->rw_screen);
+
+ g_assert (priv->labeler == NULL);
+ priv->labeler = mate_rr_labeler_new (priv->configuration);
+
+ g_assert (priv->popup_menu == NULL);
+ priv->popup_menu = gtk_menu_new ();
+
+ add_menu_items_for_outputs (manager);
+
+ item = gtk_separator_menu_item_new ();
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Configure Display Settings…"));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (popup_menu_configure_display_cb), manager);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
+
+ g_signal_connect (priv->popup_menu, "selection-done",
+ G_CALLBACK (status_icon_popup_menu_selection_done_cb), manager);
+
+ gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
+ gtk_status_icon_position_menu,
+ priv->status_icon, button, timestamp);
+}
+
+static void
+status_icon_activate_cb (GtkStatusIcon *status_icon, gpointer data)
+{
+ GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+
+ /* Suck; we don't get a proper button/timestamp */
+ status_icon_popup_menu (manager, 0, gtk_get_current_event_time ());
+}
+
+static void
+status_icon_popup_menu_cb (GtkStatusIcon *status_icon, guint button, guint32 timestamp, gpointer data)
+{
+ GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+
+ status_icon_popup_menu (manager, button, timestamp);
+}
+
+static void
+status_icon_start (GsdXrandrManager *manager)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+
+ /* Ideally, we should detect if we are on a tablet and only display
+ * the icon in that case.
+ */
+ if (!priv->status_icon) {
+ priv->status_icon = gtk_status_icon_new_from_icon_name (GSD_XRANDR_ICON_NAME);
+ gtk_status_icon_set_tooltip_text (priv->status_icon, _("Configure display settings"));
+
+ g_signal_connect (priv->status_icon, "activate",
+ G_CALLBACK (status_icon_activate_cb), manager);
+ g_signal_connect (priv->status_icon, "popup-menu",
+ G_CALLBACK (status_icon_popup_menu_cb), manager);
+ }
+}
+
+static void
+status_icon_stop (GsdXrandrManager *manager)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+
+ if (priv->status_icon) {
+ g_signal_handlers_disconnect_by_func (
+ priv->status_icon, G_CALLBACK (status_icon_activate_cb), manager);
+ g_signal_handlers_disconnect_by_func (
+ priv->status_icon, G_CALLBACK (status_icon_popup_menu_cb), manager);
+
+ /* hide the icon before unreffing it; otherwise we will leak
+ whitespace in the notification area due to a bug in there */
+ gtk_status_icon_set_visible (priv->status_icon, FALSE);
+ g_object_unref (priv->status_icon);
+ priv->status_icon = NULL;
+ }
+}
+
+static void
+start_or_stop_icon (GsdXrandrManager *manager)
+{
+ if (mateconf_client_get_bool (manager->priv->client, CONF_KEY_SHOW_NOTIFICATION_ICON, NULL)) {
+ status_icon_start (manager);
+ }
+ else {
+ status_icon_stop (manager);
+ }
+}
+
+static void
+on_config_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GsdXrandrManager *manager)
+{
+ if (strcmp (entry->key, CONF_KEY_SHOW_NOTIFICATION_ICON) == 0)
+ start_or_stop_icon (manager);
+}
+
+static gboolean
+apply_intended_configuration (GsdXrandrManager *manager, const char *intended_filename, guint32 timestamp)
+{
+ GError *my_error;
+ gboolean result;
+
+ my_error = NULL;
+ result = apply_configuration_from_filename (manager, intended_filename, FALSE, timestamp, &my_error);
+ if (!result) {
+ if (my_error) {
+ if (!g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ error_message (manager, _("Could not apply the stored configuration for monitors"), my_error, NULL);
+
+ g_error_free (my_error);
+ }
+ }
+
+ return result;
+}
+
+static void
+apply_default_boot_configuration (GsdXrandrManager *mgr, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = mgr->priv;
+ MateRRScreen *screen = priv->rw_screen;
+ MateRRConfig *config;
+ gboolean turn_on_external, turn_on_laptop;
+
+ turn_on_external =
+ mateconf_client_get_bool (mgr->priv->client, CONF_KEY_TURN_ON_EXTERNAL_MONITORS_AT_STARTUP, NULL);
+ turn_on_laptop =
+ mateconf_client_get_bool (mgr->priv->client, CONF_KEY_TURN_ON_LAPTOP_MONITOR_AT_STARTUP, NULL);
+
+ if (turn_on_external && turn_on_laptop)
+ config = make_clone_setup (screen);
+ else if (!turn_on_external && turn_on_laptop)
+ config = make_laptop_setup (screen);
+ else if (turn_on_external && !turn_on_laptop)
+ config = make_other_setup (screen);
+ else
+ config = make_laptop_setup (screen);
+
+ if (config) {
+ apply_configuration_and_display_error (mgr, config, timestamp);
+ mate_rr_config_free (config);
+ }
+}
+
+static gboolean
+apply_stored_configuration_at_startup (GsdXrandrManager *manager, guint32 timestamp)
+{
+ GError *my_error;
+ gboolean success;
+ char *backup_filename;
+ char *intended_filename;
+
+ backup_filename = mate_rr_config_get_backup_filename ();
+ intended_filename = mate_rr_config_get_intended_filename ();
+
+ /* 1. See if there was a "saved" configuration. If there is one, it means
+ * that the user had selected to change the display configuration, but the
+ * machine crashed. In that case, we'll apply *that* configuration and save it on top of the
+ * "intended" one.
+ */
+
+ my_error = NULL;
+
+ success = apply_configuration_from_filename (manager, backup_filename, FALSE, timestamp, &my_error);
+ if (success) {
+ /* The backup configuration existed, and could be applied
+ * successfully, so we must restore it on top of the
+ * failed/intended one.
+ */
+ restore_backup_configuration (manager, backup_filename, intended_filename, timestamp);
+ goto out;
+ }
+
+ if (!g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
+ /* Epic fail: there (probably) was a backup configuration, but
+ * we could not apply it. The only thing we can do is delete
+ * the backup configuration. Let's hope that the user doesn't
+ * get left with an unusable display...
+ */
+
+ unlink (backup_filename);
+ goto out;
+ }
+
+ /* 2. There was no backup configuration! This means we are
+ * good. Apply the intended configuration instead.
+ */
+
+ success = apply_intended_configuration (manager, intended_filename, timestamp);
+
+out:
+
+ if (my_error)
+ g_error_free (my_error);
+
+ g_free (backup_filename);
+ g_free (intended_filename);
+
+ return success;
+}
+
+static gboolean
+apply_default_configuration_from_file (GsdXrandrManager *manager, guint32 timestamp)
+{
+ GsdXrandrManagerPrivate *priv = manager->priv;
+ char *default_config_filename;
+ gboolean result;
+
+ default_config_filename = mateconf_client_get_string (priv->client, CONF_KEY_DEFAULT_CONFIGURATION_FILE, NULL);
+ if (!default_config_filename)
+ return FALSE;
+
+ result = apply_configuration_from_filename (manager, default_config_filename, TRUE, timestamp, NULL);
+
+ g_free (default_config_filename);
+ return result;
+}
+
+gboolean
+gsd_xrandr_manager_start (GsdXrandrManager *manager,
+ GError **error)
+{
+ g_debug ("Starting xrandr manager");
+ mate_settings_profile_start (NULL);
+
+ log_open ();
+ log_msg ("------------------------------------------------------------\nSTARTING XRANDR PLUGIN\n");
+
+ manager->priv->rw_screen = mate_rr_screen_new (
+ gdk_screen_get_default (), on_randr_event, manager, error);
+
+ if (manager->priv->rw_screen == NULL) {
+ log_msg ("Could not initialize the RANDR plugin%s%s\n",
+ (error && *error) ? ": " : "",
+ (error && *error) ? (*error)->message : "");
+ log_close ();
+ return FALSE;
+ }
+
+ log_msg ("State of screen at startup:\n");
+ log_screen (manager->priv->rw_screen);
+
+ manager->priv->running = TRUE;
+ manager->priv->client = mateconf_client_get_default ();
+
+ g_assert (manager->priv->notify_id == 0);
+
+ mateconf_client_add_dir (manager->priv->client, CONF_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ manager->priv->notify_id =
+ mateconf_client_notify_add (
+ manager->priv->client, CONF_DIR,
+ (MateConfClientNotifyFunc)on_config_changed,
+ manager, NULL, NULL);
+
+ if (manager->priv->switch_video_mode_keycode) {
+ gdk_error_trap_push ();
+
+ XGrabKey (gdk_x11_get_default_xdisplay(),
+ manager->priv->switch_video_mode_keycode, AnyModifier,
+ gdk_x11_get_default_root_xwindow(),
+ True, GrabModeAsync, GrabModeAsync);
+
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ }
+
+ if (manager->priv->rotate_windows_keycode) {
+ gdk_error_trap_push ();
+
+ XGrabKey (gdk_x11_get_default_xdisplay(),
+ manager->priv->rotate_windows_keycode, AnyModifier,
+ gdk_x11_get_default_root_xwindow(),
+ True, GrabModeAsync, GrabModeAsync);
+
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ }
+
+ show_timestamps_dialog (manager, "Startup");
+ if (!apply_stored_configuration_at_startup (manager, GDK_CURRENT_TIME)) /* we don't have a real timestamp at startup anyway */
+ if (!apply_default_configuration_from_file (manager, GDK_CURRENT_TIME))
+ apply_default_boot_configuration (manager, GDK_CURRENT_TIME);
+
+ log_msg ("State of screen after initial configuration:\n");
+ log_screen (manager->priv->rw_screen);
+
+ gdk_window_add_filter (gdk_get_default_root_window(),
+ (GdkFilterFunc)event_filter,
+ manager);
+
+ start_or_stop_icon (manager);
+
+ log_close ();
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_xrandr_manager_stop (GsdXrandrManager *manager)
+{
+ g_debug ("Stopping xrandr manager");
+
+ manager->priv->running = FALSE;
+
+ if (manager->priv->switch_video_mode_keycode) {
+ gdk_error_trap_push ();
+
+ XUngrabKey (gdk_x11_get_default_xdisplay(),
+ manager->priv->switch_video_mode_keycode, AnyModifier,
+ gdk_x11_get_default_root_xwindow());
+
+ gdk_error_trap_pop ();
+ }
+
+ if (manager->priv->rotate_windows_keycode) {
+ gdk_error_trap_push ();
+
+ XUngrabKey (gdk_x11_get_default_xdisplay(),
+ manager->priv->rotate_windows_keycode, AnyModifier,
+ gdk_x11_get_default_root_xwindow());
+
+ gdk_error_trap_pop ();
+ }
+
+ gdk_window_remove_filter (gdk_get_default_root_window (),
+ (GdkFilterFunc) event_filter,
+ manager);
+
+ if (manager->priv->notify_id != 0) {
+ mateconf_client_remove_dir (manager->priv->client,
+ CONF_DIR, NULL);
+ mateconf_client_notify_remove (manager->priv->client,
+ manager->priv->notify_id);
+ manager->priv->notify_id = 0;
+ }
+
+ if (manager->priv->client != NULL) {
+ g_object_unref (manager->priv->client);
+ manager->priv->client = NULL;
+ }
+
+ if (manager->priv->rw_screen != NULL) {
+ mate_rr_screen_destroy (manager->priv->rw_screen);
+ manager->priv->rw_screen = NULL;
+ }
+
+ if (manager->priv->dbus_connection != NULL) {
+ dbus_g_connection_unref (manager->priv->dbus_connection);
+ manager->priv->dbus_connection = NULL;
+ }
+
+ status_icon_stop (manager);
+
+ log_open ();
+ log_msg ("STOPPING XRANDR PLUGIN\n------------------------------------------------------------\n");
+ log_close ();
+}
+
+static void
+gsd_xrandr_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdXrandrManager *self;
+
+ self = GSD_XRANDR_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_xrandr_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdXrandrManager *self;
+
+ self = GSD_XRANDR_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_xrandr_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdXrandrManager *xrandr_manager;
+ GsdXrandrManagerClass *klass;
+
+ klass = GSD_XRANDR_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_XRANDR_MANAGER));
+
+ xrandr_manager = GSD_XRANDR_MANAGER (G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (xrandr_manager);
+}
+
+static void
+gsd_xrandr_manager_dispose (GObject *object)
+{
+ GsdXrandrManager *xrandr_manager;
+
+ xrandr_manager = GSD_XRANDR_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_xrandr_manager_class_init (GsdXrandrManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_xrandr_manager_get_property;
+ object_class->set_property = gsd_xrandr_manager_set_property;
+ object_class->constructor = gsd_xrandr_manager_constructor;
+ object_class->dispose = gsd_xrandr_manager_dispose;
+ object_class->finalize = gsd_xrandr_manager_finalize;
+
+ dbus_g_object_type_install_info (GSD_TYPE_XRANDR_MANAGER, &dbus_glib_gsd_xrandr_manager_object_info);
+
+ g_type_class_add_private (klass, sizeof (GsdXrandrManagerPrivate));
+}
+
+static guint
+get_keycode_for_keysym_name (const char *name)
+{
+ Display *dpy;
+ guint keyval;
+
+ dpy = gdk_x11_get_default_xdisplay ();
+
+ keyval = gdk_keyval_from_name (name);
+ return XKeysymToKeycode (dpy, keyval);
+}
+
+static void
+gsd_xrandr_manager_init (GsdXrandrManager *manager)
+{
+ manager->priv = GSD_XRANDR_MANAGER_GET_PRIVATE (manager);
+
+ manager->priv->switch_video_mode_keycode = get_keycode_for_keysym_name (VIDEO_KEYSYM);
+ manager->priv->rotate_windows_keycode = get_keycode_for_keysym_name (ROTATE_KEYSYM);
+
+ manager->priv->current_fn_f7_config = -1;
+ manager->priv->fn_f7_configs = NULL;
+}
+
+static void
+gsd_xrandr_manager_finalize (GObject *object)
+{
+ GsdXrandrManager *xrandr_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_XRANDR_MANAGER (object));
+
+ xrandr_manager = GSD_XRANDR_MANAGER (object);
+
+ g_return_if_fail (xrandr_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->finalize (object);
+}
+
+static gboolean
+register_manager_dbus (GsdXrandrManager *manager)
+{
+ GError *error = NULL;
+
+ manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (manager->priv->dbus_connection == NULL) {
+ if (error != NULL) {
+ g_warning ("Error getting session bus: %s", error->message);
+ g_error_free (error);
+ }
+ return FALSE;
+ }
+
+ /* Hmm, should we do this in gsd_xrandr_manager_start()? */
+ dbus_g_connection_register_g_object (manager->priv->dbus_connection, GSD_XRANDR_DBUS_PATH, G_OBJECT (manager));
+
+ return TRUE;
+}
+
+GsdXrandrManager *
+gsd_xrandr_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_XRANDR_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+
+ if (!register_manager_dbus (manager_object)) {
+ g_object_unref (manager_object);
+ return NULL;
+ }
+ }
+
+ return GSD_XRANDR_MANAGER (manager_object);
+}
diff --git a/plugins/xrandr/gsd-xrandr-manager.h b/plugins/xrandr/gsd-xrandr-manager.h
new file mode 100644
index 0000000..c404bfe
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_XRANDR_MANAGER_H
+#define __GSD_XRANDR_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_XRANDR_MANAGER (gsd_xrandr_manager_get_type ())
+#define GSD_XRANDR_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManager))
+#define GSD_XRANDR_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManagerClass))
+#define GSD_IS_XRANDR_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_XRANDR_MANAGER))
+#define GSD_IS_XRANDR_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_XRANDR_MANAGER))
+#define GSD_XRANDR_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManagerClass))
+
+typedef struct GsdXrandrManagerPrivate GsdXrandrManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdXrandrManagerPrivate *priv;
+} GsdXrandrManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdXrandrManagerClass;
+
+GType gsd_xrandr_manager_get_type (void);
+
+GsdXrandrManager * gsd_xrandr_manager_new (void);
+gboolean gsd_xrandr_manager_start (GsdXrandrManager *manager,
+ GError **error);
+void gsd_xrandr_manager_stop (GsdXrandrManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_XRANDR_MANAGER_H */
diff --git a/plugins/xrandr/gsd-xrandr-manager.xml b/plugins/xrandr/gsd-xrandr-manager.xml
new file mode 100644
index 0000000..e8dde7c
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-manager.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.mate.SettingsDaemon.XRANDR">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="gsd_xrandr_manager"/>
+ <method name="ApplyConfiguration">
+ <!-- This method is implemented, but deprecated in favor of the
+ same method in the XRANDR-2 interface defined below. -->
+ </method>
+ </interface>
+
+ <interface name="org.mate.SettingsDaemon.XRANDR_2">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="gsd_xrandr_manager_2"/>
+ <method name="ApplyConfiguration">
+ <!-- transient-parent window for the confirmation dialog; use 0
+ for no parent -->
+ <arg name="parent_window_id" type="x" direction="in"/>
+
+ <!-- Timestamp used to present the confirmation dialog and (in
+ the future) for the RANDR calls themselves -->
+ <arg name="timestamp" type="x" direction="in"/>
+ </method>
+ </interface>
+</node>
diff --git a/plugins/xrandr/gsd-xrandr-plugin.c b/plugins/xrandr/gsd-xrandr-plugin.c
new file mode 100644
index 0000000..e765124
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-xrandr-plugin.h"
+#include "gsd-xrandr-manager.h"
+
+struct GsdXrandrPluginPrivate {
+ GsdXrandrManager *manager;
+};
+
+#define GSD_XRANDR_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_XRANDR_PLUGIN, GsdXrandrPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdXrandrPlugin, gsd_xrandr_plugin)
+
+static void
+gsd_xrandr_plugin_init (GsdXrandrPlugin *plugin)
+{
+ plugin->priv = GSD_XRANDR_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdXrandrPlugin initializing");
+
+ plugin->priv->manager = gsd_xrandr_manager_new ();
+}
+
+static void
+gsd_xrandr_plugin_finalize (GObject *object)
+{
+ GsdXrandrPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_XRANDR_PLUGIN (object));
+
+ g_debug ("GsdXrandrPlugin finalizing");
+
+ plugin = GSD_XRANDR_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_xrandr_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating xrandr plugin");
+
+ error = NULL;
+ res = gsd_xrandr_manager_start (GSD_XRANDR_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start xrandr manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating xrandr plugin");
+ gsd_xrandr_manager_stop (GSD_XRANDR_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_xrandr_plugin_class_init (GsdXrandrPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_xrandr_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdXrandrPluginPrivate));
+}
diff --git a/plugins/xrandr/gsd-xrandr-plugin.h b/plugins/xrandr/gsd-xrandr-plugin.h
new file mode 100644
index 0000000..18bb79a
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_XRANDR_PLUGIN_H__
+#define __GSD_XRANDR_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_XRANDR_PLUGIN (gsd_xrandr_plugin_get_type ())
+#define GSD_XRANDR_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_XRANDR_PLUGIN, GsdXrandrPlugin))
+#define GSD_XRANDR_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_XRANDR_PLUGIN, GsdXrandrPluginClass))
+#define GSD_IS_XRANDR_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_XRANDR_PLUGIN))
+#define GSD_IS_XRANDR_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_XRANDR_PLUGIN))
+#define GSD_XRANDR_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_XRANDR_PLUGIN, GsdXrandrPluginClass))
+
+typedef struct GsdXrandrPluginPrivate GsdXrandrPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdXrandrPluginPrivate *priv;
+} GsdXrandrPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdXrandrPluginClass;
+
+GType gsd_xrandr_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_XRANDR_PLUGIN_H__ */
diff --git a/plugins/xrandr/gsd-xrandr.svg b/plugins/xrandr/gsd-xrandr.svg
new file mode 100644
index 0000000..0679b6b
--- /dev/null
+++ b/plugins/xrandr/gsd-xrandr.svg
@@ -0,0 +1,470 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48.000000px"
+ height="48.000000px"
+ id="svg3304"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/control-center/scalable"
+ sodipodi:docname="change-resolution.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs3306">
+ <linearGradient
+ id="linearGradient2804">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop2806" />
+ <stop
+ id="stop2812"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop2808" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2804"
+ id="linearGradient2831"
+ gradientUnits="userSpaceOnUse"
+ x1="21.875"
+ y1="48.000977"
+ x2="21.875"
+ y2="40" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2781"
+ id="radialGradient2829"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.8,36,8.8)"
+ cx="1"
+ cy="44"
+ fx="1"
+ fy="44"
+ r="5" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2781">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop2783" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop2785" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2781"
+ id="radialGradient2827"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
+ cx="1"
+ cy="44"
+ fx="1"
+ fy="44"
+ r="5" />
+ <linearGradient
+ id="linearGradient5137">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop5139" />
+ <stop
+ style="stop-color:#e6e6e3;stop-opacity:1;"
+ offset="1"
+ id="stop5141" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient6240">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop6242" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop6244" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient11400">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop11402" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop11404" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11400"
+ id="linearGradient11406"
+ x1="23.154902"
+ y1="34.572548"
+ x2="23.529411"
+ y2="40.219608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,0.7954955)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5137"
+ id="linearGradient5147"
+ gradientUnits="userSpaceOnUse"
+ x1="17.247635"
+ y1="6.3760414"
+ x2="39.904388"
+ y2="38.876041"
+ gradientTransform="translate(0,0.7954955)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5137"
+ id="linearGradient5223"
+ gradientUnits="userSpaceOnUse"
+ x1="31.743324"
+ y1="37.842293"
+ x2="31.86105"
+ y2="43.82579"
+ gradientTransform="translate(0,0.7954955)" />
+ <linearGradient
+ id="linearGradient7025"
+ inkscape:collect="always">
+ <stop
+ id="stop7027"
+ offset="0"
+ style="stop-color:#e6ce46;stop-opacity:1" />
+ <stop
+ id="stop7029"
+ offset="1"
+ style="stop-color:#d6ba1c;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient22122"
+ inkscape:collect="always">
+ <stop
+ id="stop22124"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop22126"
+ offset="1"
+ style="stop-color:black;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient22140">
+ <stop
+ id="stop22142"
+ offset="0"
+ style="stop-color:black;stop-opacity:0;" />
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0.5"
+ id="stop22148" />
+ <stop
+ id="stop22144"
+ offset="1"
+ style="stop-color:black;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22122"
+ id="radialGradient4770"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1.000001,1.142856,0,-41.10259,45.50001)"
+ cx="7"
+ cy="39.464806"
+ fx="7"
+ fy="39.464806"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22122"
+ id="radialGradient4772"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1.000001,1.142856,0,-89.10259,-31.49999)"
+ cx="7"
+ cy="39.464806"
+ fx="7"
+ fy="39.464806"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22140"
+ id="linearGradient4774"
+ gradientUnits="userSpaceOnUse"
+ x1="18.142136"
+ y1="35"
+ x2="18.142136"
+ y2="42.040661" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7025"
+ id="linearGradient4776"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(53,1.428571)"
+ x1="13.630114"
+ y1="28.5"
+ x2="25.208096"
+ y2="41.180992" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6240"
+ id="linearGradient4778"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(7.843e-3,0.7954955)"
+ x1="20.156862"
+ y1="5.0996137"
+ x2="20.156862"
+ y2="26.039215" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#849193"
+ borderopacity="1.0000000"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="39.697787"
+ inkscape:cy="26.598514"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ showborder="true"
+ inkscape:window-width="923"
+ inkscape:window-height="937"
+ inkscape:window-x="2004"
+ inkscape:window-y="169"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:grid-points="true" />
+ <metadata
+ id="metadata3309">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Change Resolution</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>display</rdf:li>
+ <rdf:li>resolution</rdf:li>
+ <rdf:li>video</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Andreas Nilsson
+Luca Ferretti &lt;[email protected]&gt;</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ <dc:date></dc:date>
+ <dc:source>http://www.gnome.org</dc:source>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/SourceCode" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ id="g2822"
+ style="opacity:0.3"
+ transform="matrix(0.9308511,0,0,1.037397,1.6941489,-1.795056)">
+ <rect
+ transform="scale(-1,-1)"
+ y="-48"
+ x="-11"
+ height="8"
+ width="10"
+ id="rect1892"
+ style="opacity:1;color:#000000;fill:url(#radialGradient2827);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ y="40"
+ x="38"
+ height="8"
+ width="10"
+ id="rect2789"
+ style="opacity:1;color:#000000;fill:url(#radialGradient2829);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ y="40"
+ x="11"
+ height="8"
+ width="27"
+ id="rect2793"
+ style="opacity:1;color:#000000;fill:url(#linearGradient2831);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <rect
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect4784"
+ width="48"
+ height="48"
+ x="0"
+ y="0.79549509" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient5223);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 14.375479,36.328843 C 14.375479,36.328843 15.592355,41.263443 10.51915,41.309767 C 8.0888743,41.331672 8.5866723,45.344918 8.5866723,45.344918 L 39.433139,45.313545 C 39.433139,45.313545 39.851577,41.418182 37.410922,41.372513 C 32.423455,41.280374 33.600393,36.266098 33.600393,36.266098 L 14.375479,36.328843 z "
+ id="path9222"
+ sodipodi:nodetypes="csccscc" />
+ <path
+ style="fill:url(#linearGradient5147);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+ d="M 4.8886262,4.2739318 L 43.01746,4.2739318 C 45.042579,4.2739318 46.518438,5.7015863 46.518438,7.9000726 L 46.529388,34.103908 C 46.529388,35.795975 46.001041,36.319137 44.494732,36.319137 L 3.5320635,36.300202 C 2.3527922,36.271409 1.513468,35.805541 1.4976345,34.280899 L 1.5128113,7.7123281 C 1.5128113,5.9385022 3.0522187,4.2739318 4.8886262,4.2739318 z "
+ id="rect5040"
+ sodipodi:nodetypes="ccccccccc" />
+ <rect
+ style="fill:#555753;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect9208"
+ width="37.00032"
+ height="22.996691"
+ x="5.5059438"
+ y="8.2973185" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.875"
+ inkscape:original="M 4.875 4.28125 C 3.0385925 4.28125 1.5 5.9449242 1.5 7.71875 L 1.5 34.28125 C 1.5158335 35.805892 2.3519787 36.283708 3.53125 36.3125 L 44.5 36.3125 C 46.006309 36.3125 46.53125 35.785816 46.53125 34.09375 L 46.53125 7.90625 C 46.53125 5.7077637 45.056369 4.2812498 43.03125 4.28125 L 4.875 4.28125 z "
+ xlink:href="#rect5040"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+ id="path5145"
+ inkscape:href="#rect5040"
+ d="M 4.875,5.0625 C 3.5670573,5.0625 2.375,6.3571498 2.375,7.625 L 2.375,34.1875 C 2.3812657,34.79084 2.515801,34.970853 2.65625,35.09375 C 2.796699,35.216647 3.0858905,35.332113 3.5625,35.34375 L 44.5,35.34375 C 45.151173,35.34375 45.356981,35.24273 45.4375,35.15625 C 45.518019,35.06977 45.65625,34.755549 45.65625,34 L 45.65625,7.8125 C 45.65625,6.0053499 44.645463,5.0624999 43.03125,5.0625 L 4.875,5.0625 z " />
+ <path
+ style="opacity:0.6;fill:url(#linearGradient11406);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 13.992156,36.834708 C 14.075817,39.007257 13.708803,39.746151 12.358532,40.509939 L 35.973934,41.807257 C 35.024915,40.638629 33.644523,38.873923 34.020993,36.819022 L 13.992156,36.834708 z "
+ id="path10672"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#8d8d8f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.43902438"
+ d="M 9.9921262,42.291555 C 16.698819,42.293524 37.78891,42.291555 37.78891,42.291555"
+ id="path6575"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path8029"
+ d="M 9.647928,43.299429 C 16.354621,43.301398 38.367789,43.299429 38.367789,43.299429"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ style="opacity:0.4;fill:url(#linearGradient4778);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 6.031372,8.8268676 L 6.031372,26.834708 C 22.475817,25.480459 28.630065,16.722289 41.999999,15.807256 L 42,8.7954956 L 6.031372,8.8268676 z "
+ id="path4073"
+ sodipodi:nodetypes="ccccc" />
+ <g
+ id="g4754"
+ transform="translate(-46.77135,-7.3370294)">
+ <g
+ transform="matrix(0.916667,0,0,0.714282,49.771334,11.132681)"
+ style="opacity:0.3"
+ id="g22150">
+ <rect
+ style="opacity:1;fill:url(#radialGradient4770);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+ id="rect22120"
+ width="4"
+ height="7"
+ x="0"
+ y="35" />
+ <rect
+ style="opacity:1;fill:url(#radialGradient4772);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+ id="rect22134"
+ width="4"
+ height="7"
+ x="-48"
+ y="-42"
+ transform="scale(-1,-1)" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient4774);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+ id="rect22138"
+ width="40"
+ height="7"
+ x="4"
+ y="35" />
+ </g>
+ <g
+ id="g4743">
+ <g
+ id="g10824"
+ transform="translate(-5.228666,-6.29601)">
+ <path
+ id="path4319"
+ d="M 57.5,14.928571 L 57.5,44.928571 L 96.5,44.928571 L 57.5,14.928571 z M 63.5,27.928571 L 78.5,38.928571 L 63.5,38.928571 L 63.5,27.928571 z "
+ style="fill:url(#linearGradient4776);fill-opacity:1;fill-rule:evenodd;stroke:#a38503;stroke-width:1.00000024px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4326"
+ d="M 61.5,44.928571 L 61.5,41.928571"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a38503;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4328"
+ d="M 67.5,44.928571 L 67.5,41.928571"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a38503;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4330"
+ d="M 73.5,44.928571 L 73.5,41.964285"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a38503;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4332"
+ d="M 79.5,44.928571 L 79.5,41.928571"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a38503;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4334"
+ d="M 85.5,44.928571 L 85.5,41.928571"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a38503;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path6126"
+ d="M 58.500002,16.928575 L 58.500002,43.928586 L 93.500014,43.928586 L 58.500002,16.928575 z "
+ style="opacity:0.4;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ style="opacity:0.4;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 9.5017474,38.542446 L 9.4575532,24.532894 L 28.541592,38.563262 L 9.5017474,38.542446 z "
+ id="path12221"
+ sodipodi:nodetypes="cccc"
+ transform="translate(47.771334,-4.867439)" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/plugins/xrandr/xrandr.mate-settings-plugin.in b/plugins/xrandr/xrandr.mate-settings-plugin.in
new file mode 100644
index 0000000..a07305c
--- /dev/null
+++ b/plugins/xrandr/xrandr.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=xrandr
+IAge=0
+_Name=XRandR
+_Description=Set up screen size and rotation settings
+Authors=Various
+Copyright=Copyright © 2007 Novell
+Website=
diff --git a/plugins/xrdb/Makefile.am b/plugins/xrdb/Makefile.am
new file mode 100644
index 0000000..1b8e82b
--- /dev/null
+++ b/plugins/xrdb/Makefile.am
@@ -0,0 +1,54 @@
+NULL =
+
+SUBDIRS = \
+ data \
+ $(NULL)
+
+plugin_LTLIBRARIES = \
+ libxrdb.la \
+ $(NULL)
+
+libxrdb_la_SOURCES = \
+ gsd-xrdb-plugin.h \
+ gsd-xrdb-plugin.c \
+ gsd-xrdb-manager.h \
+ gsd-xrdb-manager.c \
+ $(NULL)
+
+libxrdb_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DDATADIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libxrdb_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libxrdb_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libxrdb_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ xrdb.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/xrdb/Makefile.in b/plugins/xrdb/Makefile.in
new file mode 100644
index 0000000..56338b6
--- /dev/null
+++ b/plugins/xrdb/Makefile.in
@@ -0,0 +1,834 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/xrdb
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libxrdb_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libxrdb_la_OBJECTS = libxrdb_la-gsd-xrdb-plugin.lo \
+ libxrdb_la-gsd-xrdb-manager.lo $(am__objects_1)
+libxrdb_la_OBJECTS = $(am_libxrdb_la_OBJECTS)
+libxrdb_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libxrdb_la_CFLAGS) \
+ $(CFLAGS) $(libxrdb_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libxrdb_la_SOURCES)
+DIST_SOURCES = $(libxrdb_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+DATA = $(plugin_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+SUBDIRS = \
+ data \
+ $(NULL)
+
+plugin_LTLIBRARIES = \
+ libxrdb.la \
+ $(NULL)
+
+libxrdb_la_SOURCES = \
+ gsd-xrdb-plugin.h \
+ gsd-xrdb-plugin.c \
+ gsd-xrdb-manager.h \
+ gsd-xrdb-manager.c \
+ $(NULL)
+
+libxrdb_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DDATADIR=\""$(pkgdatadir)"\" \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libxrdb_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libxrdb_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libxrdb_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+plugin_in_files = \
+ xrdb.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/xrdb/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/xrdb/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libxrdb.la: $(libxrdb_la_OBJECTS) $(libxrdb_la_DEPENDENCIES)
+ $(libxrdb_la_LINK) -rpath $(plugindir) $(libxrdb_la_OBJECTS) $(libxrdb_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxrdb_la-gsd-xrdb-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxrdb_la-gsd-xrdb-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libxrdb_la-gsd-xrdb-plugin.lo: gsd-xrdb-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrdb_la_CPPFLAGS) $(CPPFLAGS) $(libxrdb_la_CFLAGS) $(CFLAGS) -MT libxrdb_la-gsd-xrdb-plugin.lo -MD -MP -MF $(DEPDIR)/libxrdb_la-gsd-xrdb-plugin.Tpo -c -o libxrdb_la-gsd-xrdb-plugin.lo `test -f 'gsd-xrdb-plugin.c' || echo '$(srcdir)/'`gsd-xrdb-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxrdb_la-gsd-xrdb-plugin.Tpo $(DEPDIR)/libxrdb_la-gsd-xrdb-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xrdb-plugin.c' object='libxrdb_la-gsd-xrdb-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrdb_la_CPPFLAGS) $(CPPFLAGS) $(libxrdb_la_CFLAGS) $(CFLAGS) -c -o libxrdb_la-gsd-xrdb-plugin.lo `test -f 'gsd-xrdb-plugin.c' || echo '$(srcdir)/'`gsd-xrdb-plugin.c
+
+libxrdb_la-gsd-xrdb-manager.lo: gsd-xrdb-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrdb_la_CPPFLAGS) $(CPPFLAGS) $(libxrdb_la_CFLAGS) $(CFLAGS) -MT libxrdb_la-gsd-xrdb-manager.lo -MD -MP -MF $(DEPDIR)/libxrdb_la-gsd-xrdb-manager.Tpo -c -o libxrdb_la-gsd-xrdb-manager.lo `test -f 'gsd-xrdb-manager.c' || echo '$(srcdir)/'`gsd-xrdb-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxrdb_la-gsd-xrdb-manager.Tpo $(DEPDIR)/libxrdb_la-gsd-xrdb-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xrdb-manager.c' object='libxrdb_la-gsd-xrdb-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxrdb_la_CPPFLAGS) $(CPPFLAGS) $(libxrdb_la_CFLAGS) $(CFLAGS) -c -o libxrdb_la-gsd-xrdb-manager.lo `test -f 'gsd-xrdb-manager.c' || echo '$(srcdir)/'`gsd-xrdb-manager.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-pluginLTLIBRARIES ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-pluginDATA \
+ uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/xrdb/data/Editres.ad b/plugins/xrdb/data/Editres.ad
new file mode 100644
index 0000000..d33d499
--- /dev/null
+++ b/plugins/xrdb/data/Editres.ad
@@ -0,0 +1,5 @@
+Editres*Tree.Background: WINDOW_BACKGROUND
+Editres*Tree.Foreground: WINDOW_FOREGROUND
+Editres*Tree.Toggle.Foreground: FOREGROUND
+Editres*Tree.Toggle.Background: BACKGROUND
+Editres*Panner.Background: BACKGROUND
diff --git a/plugins/xrdb/data/Emacs.ad b/plugins/xrdb/data/Emacs.ad
new file mode 100644
index 0000000..d40be72
--- /dev/null
+++ b/plugins/xrdb/data/Emacs.ad
@@ -0,0 +1,21 @@
+Emacs.default.attributeForeground: WINDOW_FOREGROUND
+Emacs.default.attributeBackground: WINDOW_BACKGROUND
+
+Emacs*Foreground: WINDOW_FOREGROUND
+Emacs*Background: WINDOW_BACKGROUND
+Emacs*menubar*foreground: FOREGROUND
+Emacs*menubar*background: BACKGROUND
+Emacs*popup*Foreground: FOREGROUND
+Emacs*popup*Background: BACKGROUND
+Emacs*Dialog*foreground: FOREGROUND
+Emacs*Dialog*background: BACKGROUND
+Emacs*XlwScrollBar.Foreground: FOREGROUND
+Emacs*XlwScrollBar.Background: BACKGROUND
+Emacs*topToolBarShadowColor: BACKGROUND
+Emacs*bottomToolBarShadowColor: BACKGROUND
+Emacs*backgroundToolBarColor: BACKGROUND
+Emacs.scroll-bar.attributeBackground: BACKGROUND
+Emacs.scroll-bar.attributeForeground: FOREGROUND
+Emacs.mode-line.attributeForeground: FOREGROUND
+Emacs.tool-bar.attributeBackground: BACKGROUND
+Emacs.tool-bar.attributeForeground: FOREGROUND
diff --git a/plugins/xrdb/data/General.ad b/plugins/xrdb/data/General.ad
new file mode 100644
index 0000000..d398d41
--- /dev/null
+++ b/plugins/xrdb/data/General.ad
@@ -0,0 +1,2 @@
+*background: BACKGROUND
+*foreground: FOREGROUND
diff --git a/plugins/xrdb/data/Makefile.am b/plugins/xrdb/data/Makefile.am
new file mode 100644
index 0000000..e133b9b
--- /dev/null
+++ b/plugins/xrdb/data/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+xrdbdir = $(pkgdatadir)/xrdb
+xrdb_DATA = \
+ General.ad \
+ Editres.ad \
+ Emacs.ad \
+ Motif.ad \
+ Tk.ad \
+ Xaw.ad \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(xrdb_DATA) \
+ $(NULL)
diff --git a/plugins/xrdb/data/Makefile.in b/plugins/xrdb/data/Makefile.in
new file mode 100644
index 0000000..9ef37f5
--- /dev/null
+++ b/plugins/xrdb/data/Makefile.in
@@ -0,0 +1,483 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/xrdb/data
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(xrdbdir)"
+DATA = $(xrdb_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+xrdbdir = $(pkgdatadir)/xrdb
+xrdb_DATA = \
+ General.ad \
+ Editres.ad \
+ Emacs.ad \
+ Motif.ad \
+ Tk.ad \
+ Xaw.ad \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(xrdb_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/xrdb/data/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/xrdb/data/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-xrdbDATA: $(xrdb_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(xrdbdir)" || $(MKDIR_P) "$(DESTDIR)$(xrdbdir)"
+ @list='$(xrdb_DATA)'; test -n "$(xrdbdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(xrdbdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(xrdbdir)" || exit $$?; \
+ done
+
+uninstall-xrdbDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(xrdb_DATA)'; test -n "$(xrdbdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(xrdbdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(xrdbdir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(xrdbdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-xrdbDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-xrdbDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ install-xrdbDATA installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ uninstall uninstall-am uninstall-xrdbDATA
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/xrdb/data/Motif.ad b/plugins/xrdb/data/Motif.ad
new file mode 100644
index 0000000..af36763
--- /dev/null
+++ b/plugins/xrdb/data/Motif.ad
@@ -0,0 +1,74 @@
+*XmScrollBar.background: BACKGROUND
+*XmScrollBar.foreground: FOREGROUND
+
+*XmSash.background: BACKGROUND
+*XmSash.foreground: FOREGROUND
+
+*XmLabel.background: BACKGROUND
+*XmLabel.foreground: FOREGROUND
+*XmLabelGadget.background: BACKGROUND
+*XmLabelGadget.foreground: FOREGROUND
+
+*XmCascadeButton.background: BACKGROUND
+*XmCascadeButton.foreground: FOREGROUND
+*XmCascadeButtonGadget.background: BACKGROUND
+*XmCascadeButtonGadget.foreground: FOREGROUND
+
+*XmToggleButton.background: BACKGROUND
+*XmToggleButton.foreground: FOREGROUND
+*XmToggleButtonGadget.background: BACKGROUND
+*XmToggleButtonGadget.foreground: FOREGROUND
+
+*XmPushButton.background: BACKGROUND
+*XmPushButton.foreground: FOREGROUND
+*XmPushButtonGadget.background: BACKGROUND
+*XmPushButtonGadget.foreground: FOREGROUND
+
+*XmSeparator.background: BACKGROUND
+*XmSeparator.foreground: FOREGROUND
+*XmSeparatorGadget.background: BACKGROUND
+*XmSeparatorGadget.foreground: FOREGROUND
+
+*XmTearOffButton.background: BACKGROUND
+*XmTearOffButton.foreground: FOREGROUND
+*XmTearOffButtonGadget.background: BACKGROUND
+*XmTearOffButtonGadget.foreground: FOREGROUND
+
+*XmMenuShell.background: BACKGROUND
+*XmMenuShell.foreground: FOREGROUND
+
+*XmDialogShell.background: BACKGROUND
+*XmDialogShell.foreground: FOREGROUND
+
+*XmFileSelectionBox.background: BACKGROUND
+*XmFileSelectionBox.foreground: FOREGROUND
+
+*XmSelectionBox.background: BACKGROUND
+*XmSelectionBox.foreground: FOREGROUND
+
+*XmMessageBox.background: BACKGROUND
+*XmMessageBox.foreground: FOREGROUND
+
+*XmRowColumn.background: BACKGROUND
+*XmRowColumn.foreground: FOREGROUND
+
+*XmFrame.background: BACKGROUND
+*XmFrame.foreground: FOREGROUND
+
+*XmForm.background: BACKGROUND
+*XmForm.foreground: FOREGROUND
+
+*XmScrolledWindow.background: BACKGROUND
+*XmScrolledWindow.foreground: FOREGROUND
+
+*XmPanedWindow.background: BACKGROUND
+*XmPanedWindow.foreground: FOREGROUND
+
+*XmText.background: WINDOW_BACKGROUND
+*XmText.foreground: WINDOW_FOREGROUND
+
+*XmTextField.background: WINDOW_BACKGROUND
+*XmTextField.foreground: WINDOW_FOREGROUND
+
+*XmList.background: WINDOW_BACKGROUND
+*XmList.foreground: WINDOW_FOREGROUND
diff --git a/plugins/xrdb/data/Tk.ad b/plugins/xrdb/data/Tk.ad
new file mode 100644
index 0000000..d49ec38
--- /dev/null
+++ b/plugins/xrdb/data/Tk.ad
@@ -0,0 +1,102 @@
+*Toplevel.background: BACKGROUND
+*Toplevel.foreground: FOREGROUND
+*Toplevel.highlightBackground: BACKGROUND
+*Toplevel.highlightColor: FOREGROUND
+*Toplevel.activeBackground: BACKGROUND
+*Toplevel.activeForeground: FOREGROUND
+
+*Button.background: BACKGROUND
+*Button.foreground: FOREGROUND
+*Button.highlightBackground: BACKGROUND
+*Button.highlightColor: FOREGROUND
+*Button.activeBackground: HIGHLIGHT
+*Button.activeForeground: FOREGROUND
+
+*Menubutton.background: BACKGROUND
+*Menubutton.foreground: FOREGROUND
+*Menubutton.highlightBackground: BACKGROUND
+*Menubutton.highlightColor: FOREGROUND
+*Menubutton.activeBackground: ACTIVE_BACKGROUND
+*Menubutton.activeForeground: ACTIVE_FOREGROUND
+
+*Checkbutton.background: BACKGROUND
+*Checkbutton.foreground: FOREGROUND
+*Checkbutton.highlightBackground: BACKGROUND
+*Checkbutton.highlightColor: FOREGROUND
+*Checkbutton.activeBackground: HIGHLIGHT
+*Checkbutton.activeForeground: FOREGROUND
+
+*Radiobutton.background: BACKGROUND
+*Radiobutton.foreground: FOREGROUND
+*Radiobutton.highlightBackground: BACKGROUND
+*Radiobutton.highlightColor: FOREGROUND
+*Radiobutton.activeBackground: HIGHLIGHT
+*Radiobutton.activeForeground: FOREGROUND
+
+*Label.background: BACKGROUND
+*Label.foreground: FOREGROUND
+*Label.highlightBackground: BACKGROUND
+*Label.highlightColor: FOREGROUND
+
+*Menu.background: BACKGROUND
+*Menu.foreground: FOREGROUND
+*Menu.activeBackground: ACTIVE_BACKGROUND
+*Menu.activeForeground: ACTIVE_FOREGROUND
+
+*Frame.background: BACKGROUND
+*Frame.foreground: FOREGROUND
+
+*Labelframe.background: BACKGROUND
+*Labelframe.foreground: FOREGROUND
+*Labelframe.highlightColor: FOREGROUND
+
+*Scrollbar.background: BACKGROUND
+*Scrollbar.highlightBackground: BACKGROUND
+*Scrollbar.highlightColor: FOREGROUND
+*Scrollbar.activeBackground: HIGHLIGHT
+!*Scrollbar.troughColor: LOWLIGHT
+!*Scrollbar.troughColor: BACKGROUND
+
+*Scale.background: BACKGROUND
+*Scale.foreground: FOREGROUND
+*Scale.highlightBackground: BACKGROUND
+*Scale.highlightColor: FOREGROUND
+*Scale.activeBackground: BACKGROUND
+*Scale.activeForeground: FOREGROUND
+!*Scale.troughColor: LOWLIGHT
+
+*Entry.background: WINDOW_BACKGROUND
+*Entry.foreground: WINDOW_FOREGROUND
+*Entry.highlightBackground: WINDOW_BACKGROUND
+*Entry.highlightColor: WINDOW_FOREGROUND
+*Entry.activeBackground: WINDOW_BACKGROUND
+*Entry.activeForeground: WINDOW_FOREGROUND
+*Entry.selectBackground: SELECT_BACKGROUND
+*Entry.selectForeground: SELECT_FOREGROUND
+
+*Text.background: WINDOW_BACKGROUND
+*Text.foreground: WINDOW_FOREGROUND
+*Text.highlightBackground: WINDOW_BACKGROUND
+*Text.highlightColor: WINDOW_FOREGROUND
+*Text.activeBackground: WINDOW_BACKGROUND
+*Text.activeForeground: WINDOW_FOREGROUND
+*Text.selectBackground: SELECT_BACKGROUND
+*Text.selectForeground: SELECT_FOREGROUND
+
+*Listbox.background: WINDOW_BACKGROUND
+*Listbox.foreground: WINDOW_FOREGROUND
+*Listbox.highlightBackground: WINDOW_BACKGROUND
+*Listbox.highlightColor: WINDOW_FOREGROUND
+*Listbox.activeBackground: WINDOW_BACKGROUND
+*Listbox.activeForeground: WINDOW_FOREGROUND
+*Listbox.selectBackground: SELECT_BACKGROUND
+*Listbox.selectForeground: SELECT_FOREGROUND
+
+*Canvas.background: WINDOW_BACKGROUND
+*Canvas.foreground: WINDOW_FOREGROUND
+*Canvas.highlightBackground: WINDOW_BACKGROUND
+*Canvas.highlightColor: WINDOW_FOREGROUND
+*Canvas.activeBackground: WINDOW_BACKGROUND
+*Canvas.activeForeground: WINDOW_FOREGROUND
+*Canvas.selectbackground: SELECT_BACKGROUND
+*Canvas.selectforeground: SELECT_FOREGROUND
diff --git a/plugins/xrdb/data/Xaw.ad b/plugins/xrdb/data/Xaw.ad
new file mode 100644
index 0000000..d44dc51
--- /dev/null
+++ b/plugins/xrdb/data/Xaw.ad
@@ -0,0 +1,25 @@
+*MenuButton.background: BACKGROUND
+*Command.background: BACKGROUND
+*Toggle.background: BACKGROUND
+*Label.background: BACKGROUND
+*Scrollbar*background: BACKGROUND
+*SimpleMenu*background: BACKGROUND
+*Box.background: BACKGROUND
+*Form.background: BACKGROUND
+*Dialog.background: BACKGROUND
+*Text.background: WINDOW_BACKGROUND
+*List.background: WINDOW_BACKGROUND
+
+*MenuButton.foreground: FOREGROUND
+*Command.foreground: FOREGROUND
+*Toggle.foreground: FOREGROUND
+*Label.foreground: FOREGROUND
+*Scrollbar.foreground: FOREGROUND
+*SimpleMenu*foreground: FOREGROUND
+*Box.foreground: FOREGROUND
+*Form.foreground: FOREGROUND
+*Dialog.foreground: FOREGROUND
+*Text.foreground: WINDOW_FOREGROUND
+*List.foreground: WINDOW_FOREGROUND
+
+*ScrollbarBackground: BACKGROUND
diff --git a/plugins/xrdb/gsd-xrdb-manager.c b/plugins/xrdb/gsd-xrdb-manager.c
new file mode 100644
index 0000000..47eed1d
--- /dev/null
+++ b/plugins/xrdb/gsd-xrdb-manager.c
@@ -0,0 +1,638 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2003 Ross Burton <[email protected]>
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-xrdb-manager.h"
+
+#define GSD_XRDB_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_XRDB_MANAGER, GsdXrdbManagerPrivate))
+
+#define SYSTEM_AD_DIR DATADIR "/xrdb"
+#define GENERAL_AD SYSTEM_AD_DIR "/General.ad"
+#define USER_AD_DIR ".mate2/xrdb"
+#define USER_X_RESOURCES ".Xresources"
+#define USER_X_DEFAULTS ".Xdefaults"
+
+#define GTK_THEME_KEY "/desktop/mate/interface/gtk_theme"
+
+struct GsdXrdbManagerPrivate
+{
+ GtkWidget *widget;
+};
+
+static void gsd_xrdb_manager_class_init (GsdXrdbManagerClass *klass);
+static void gsd_xrdb_manager_init (GsdXrdbManager *xrdb_manager);
+static void gsd_xrdb_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (GsdXrdbManager, gsd_xrdb_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+static void
+
+append_color_define (GString *string,
+ const char *name,
+ const GdkColor *color)
+{
+ g_return_if_fail (string != NULL);
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (color != NULL);
+
+ g_string_append_printf (string,
+ "#define %s #%2.2hx%2.2hx%2.2hx\n",
+ name,
+ color->red>>8,
+ color->green>>8,
+ color->blue>>8);
+}
+
+static GdkColor*
+color_shade (GdkColor *a,
+ gdouble shade,
+ GdkColor *b)
+{
+ guint16 red, green, blue;
+
+ red = CLAMP ((a->red) * shade, 0, 0xFFFF);
+ green = CLAMP ((a->green) * shade, 0, 0xFFFF);
+ blue = CLAMP ((a->blue) * shade, 0, 0xFFFF);
+
+ b->red = red;
+ b->green = green;
+ b->blue = blue;
+
+ return b;
+}
+
+static void
+append_theme_colors (GtkStyle *style,
+ GString *string)
+{
+ GdkColor tmp;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (string != NULL);
+
+ append_color_define (string,
+ "BACKGROUND",
+ &style->bg[GTK_STATE_NORMAL]);
+ append_color_define (string,
+ "FOREGROUND",
+ &style->fg[GTK_STATE_NORMAL]);
+ append_color_define (string,
+ "SELECT_BACKGROUND",
+ &style->bg[GTK_STATE_SELECTED]);
+ append_color_define (string,
+ "SELECT_FOREGROUND",
+ &style->text[GTK_STATE_SELECTED]);
+ append_color_define (string,
+ "WINDOW_BACKGROUND",
+ &style->base[GTK_STATE_NORMAL]);
+ append_color_define (string,
+ "WINDOW_FOREGROUND",
+ &style->text[GTK_STATE_NORMAL]);
+ append_color_define (string,
+ "INACTIVE_BACKGROUND",
+ &style->bg[GTK_STATE_INSENSITIVE]);
+ append_color_define (string,
+ "INACTIVE_FOREGROUND",
+ &style->text[GTK_STATE_INSENSITIVE]);
+ append_color_define (string,
+ "ACTIVE_BACKGROUND",
+ &style->bg[GTK_STATE_SELECTED]);
+ append_color_define (string,
+ "ACTIVE_FOREGROUND",
+ &style->text[GTK_STATE_SELECTED]);
+
+ append_color_define (string,
+ "HIGHLIGHT",
+ color_shade (&style->bg[GTK_STATE_NORMAL], 1.2, &tmp));
+ append_color_define (string,
+ "LOWLIGHT",
+ color_shade (&style->bg[GTK_STATE_NORMAL], 2.0/3.0, &tmp));
+ return;
+}
+
+/**
+ * Scan a single directory for .ad files, and return them all in a
+ * GSList*
+ */
+static GSList*
+scan_ad_directory (const char *path,
+ GError **error)
+{
+ GSList *list;
+ GDir *dir;
+ const char *entry;
+ GError *local_error;
+
+ list = NULL;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ local_error = NULL;
+ dir = g_dir_open (path, 0, &local_error);
+ if (local_error != NULL) {
+ g_propagate_error (error, local_error);
+ return NULL;
+ }
+
+ while ((entry = g_dir_read_name (dir)) != NULL) {
+ if (g_str_has_suffix (entry, ".ad")) {
+ list = g_slist_prepend (list, g_strdup_printf ("%s/%s", path, entry));
+ }
+ }
+
+ g_dir_close (dir);
+
+ /* TODO: sort still? */
+ return g_slist_sort (list, (GCompareFunc)strcmp);
+}
+
+/**
+ * Compare two file names on their base names.
+ */
+static gint
+compare_basenames (gconstpointer a,
+ gconstpointer b)
+{
+ char *base_a;
+ char *base_b;
+ int res;
+
+ base_a = g_path_get_basename (a);
+ base_b = g_path_get_basename (b);
+ res = strcmp (base_a, base_b);
+ g_free (base_a);
+ g_free (base_b);
+
+ return res;
+}
+
+/**
+ * Scan the user and system paths, and return a list of strings in the
+ * right order for processing.
+ */
+static GSList*
+scan_for_files (GsdXrdbManager *manager,
+ GError **error)
+{
+ const char *home_dir;
+ GSList *user_list;
+ GSList *system_list;
+ GSList *list;
+ GSList *p;
+ GError *local_error;
+
+ list = NULL;
+ user_list = NULL;
+ system_list = NULL;
+
+ local_error = NULL;
+ system_list = scan_ad_directory (SYSTEM_AD_DIR, &local_error);
+ if (local_error != NULL) {
+ g_propagate_error (error, local_error);
+ return NULL;
+ }
+
+ home_dir = g_get_home_dir ();
+ if (home_dir != NULL) {
+ char *user_ad;
+
+ user_ad = g_build_filename (home_dir, USER_AD_DIR, NULL);
+
+ if (g_file_test (user_ad, G_FILE_TEST_IS_DIR)) {
+
+ local_error = NULL;
+ user_list = scan_ad_directory (user_ad, &local_error);
+ if (local_error != NULL) {
+ g_propagate_error (error, local_error);
+
+ g_slist_foreach (system_list, (GFunc)g_free, NULL);
+ g_slist_free (system_list);
+ g_free (user_ad);
+ return NULL;
+ }
+ }
+
+ g_free (user_ad);
+
+ } else {
+ g_warning (_("Cannot determine user's home directory"));
+ }
+
+ /* An alternative approach would be to strdup() the strings
+ and free the entire contents of these lists, but that is a
+ little inefficient for my liking - RB */
+ for (p = system_list; p != NULL; p = g_slist_next (p)) {
+ if (strcmp (p->data, GENERAL_AD) == 0) {
+ /* We ignore this, free the data now */
+ g_free (p->data);
+ continue;
+ }
+ if (g_slist_find_custom (user_list, p->data, compare_basenames)) {
+ /* Ditto */
+ g_free (p->data);
+ continue;
+ }
+ list = g_slist_prepend (list, p->data);
+ }
+ g_slist_free (system_list);
+
+ for (p = user_list; p != NULL; p = g_slist_next (p)) {
+ list = g_slist_prepend (list, p->data);
+ }
+ g_slist_free (user_list);
+
+ /* Reverse the order so it is the correct way */
+ list = g_slist_reverse (list);
+
+ /* Add the initial file */
+ list = g_slist_prepend (list, g_strdup (GENERAL_AD));
+
+ return list;
+}
+
+/**
+ * Append the contents of a file onto the end of a GString
+ */
+static void
+append_file (const char *file,
+ GString *string,
+ GError **error)
+{
+ char *contents;
+
+ g_return_if_fail (string != NULL);
+ g_return_if_fail (file != NULL);
+
+ if (g_file_get_contents (file, &contents, NULL, error)) {
+ g_string_append (string, contents);
+ g_free (contents);
+ }
+}
+
+/**
+ * Append an X resources file, such as .Xresources, or .Xdefaults
+ */
+static void
+append_xresource_file (const char *filename,
+ GString *string,
+ GError **error)
+{
+ const char *home_path;
+ char *xresources;
+
+ g_return_if_fail (string != NULL);
+
+ home_path = g_get_home_dir ();
+ if (home_path == NULL) {
+ g_warning (_("Cannot determine user's home directory"));
+ return;
+ }
+
+ xresources = g_build_filename (home_path, filename, NULL);
+ if (g_file_test (xresources, G_FILE_TEST_EXISTS)) {
+ GError *local_error;
+
+ local_error = NULL;
+
+ append_file (xresources, string, &local_error);
+ if (local_error != NULL) {
+ g_warning ("%s", local_error->message);
+ g_propagate_error (error, local_error);
+ }
+ }
+ g_free (xresources);
+}
+
+static gboolean
+write_all (int fd,
+ const char *buf,
+ gsize to_write)
+{
+ while (to_write > 0) {
+ gssize count = write (fd, buf, to_write);
+ if (count < 0) {
+ if (errno != EINTR)
+ return FALSE;
+ } else {
+ to_write -= count;
+ buf += count;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+child_watch_cb (GPid pid,
+ int status,
+ gpointer user_data)
+{
+ char *command = user_data;
+
+ if (!WIFEXITED (status) || WEXITSTATUS (status)) {
+ g_warning ("Command %s failed", command);
+ }
+}
+
+static void
+spawn_with_input (const char *command,
+ const char *input)
+{
+ char **argv;
+ int child_pid;
+ int inpipe;
+ GError *error;
+ gboolean res;
+
+ argv = NULL;
+ res = g_shell_parse_argv (command, NULL, &argv, NULL);
+ if (! res) {
+ g_warning ("Unable to parse command: %s", command);
+ return;
+ }
+
+ error = NULL;
+ res = g_spawn_async_with_pipes (NULL,
+ argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL,
+ NULL,
+ &child_pid,
+ &inpipe,
+ NULL,
+ NULL,
+ &error);
+ g_strfreev (argv);
+
+ if (! res) {
+ g_warning ("Could not execute %s: %s", command, error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ if (input != NULL) {
+ if (! write_all (inpipe, input, strlen (input))) {
+ g_warning ("Could not write input to %s", command);
+ }
+
+ close (inpipe);
+ }
+
+ g_child_watch_add (child_pid, (GChildWatchFunc) child_watch_cb, (gpointer)command);
+}
+
+static void
+apply_settings (GsdXrdbManager *manager,
+ GtkStyle *style)
+{
+ const char *command;
+ GString *string;
+ GSList *list;
+ GSList *p;
+ GError *error;
+
+ mate_settings_profile_start (NULL);
+
+ command = "xrdb -merge -quiet";
+
+ string = g_string_sized_new (256);
+ append_theme_colors (style, string);
+
+ error = NULL;
+ list = scan_for_files (manager, &error);
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ for (p = list; p != NULL; p = p->next) {
+ error = NULL;
+ append_file (p->data, string, &error);
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ g_slist_foreach (list, (GFunc)g_free, NULL);
+ g_slist_free (list);
+
+ error = NULL;
+ append_xresource_file (USER_X_RESOURCES, string, &error);
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ error = NULL;
+ append_xresource_file (USER_X_DEFAULTS, string, &error);
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ spawn_with_input (command, string->str);
+ g_string_free (string, TRUE);
+
+ mate_settings_profile_end (NULL);
+
+ return;
+}
+
+static void
+theme_changed (GtkSettings *settings,
+ GParamSpec *pspec,
+ GsdXrdbManager *manager)
+{
+ apply_settings (manager, gtk_widget_get_style (manager->priv->widget));
+}
+
+gboolean
+gsd_xrdb_manager_start (GsdXrdbManager *manager,
+ GError **error)
+{
+ mate_settings_profile_start (NULL);
+
+ /* the initialization is done here otherwise
+ mate_settings_xsettings_load would generate
+ false hit as gtk-theme-name is set to Default in
+ mate_settings_xsettings_init */
+ g_signal_connect (gtk_settings_get_default (),
+ "notify::gtk-theme-name",
+ G_CALLBACK (theme_changed),
+ manager);
+
+ manager->priv->widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_ensure_style (manager->priv->widget);
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+gsd_xrdb_manager_stop (GsdXrdbManager *manager)
+{
+ GsdXrdbManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping xrdb manager");
+
+ g_signal_handlers_disconnect_by_func (gtk_settings_get_default (),
+ theme_changed,
+ manager);
+
+ if (p->widget != NULL) {
+ gtk_widget_destroy (p->widget);
+ p->widget = NULL;
+ }
+}
+
+static void
+gsd_xrdb_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdXrdbManager *self;
+
+ self = GSD_XRDB_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_xrdb_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdXrdbManager *self;
+
+ self = GSD_XRDB_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gsd_xrdb_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GsdXrdbManager *xrdb_manager;
+ GsdXrdbManagerClass *klass;
+
+ klass = GSD_XRDB_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_XRDB_MANAGER));
+
+ xrdb_manager = GSD_XRDB_MANAGER (G_OBJECT_CLASS (gsd_xrdb_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (xrdb_manager);
+}
+
+static void
+gsd_xrdb_manager_dispose (GObject *object)
+{
+ GsdXrdbManager *xrdb_manager;
+
+ xrdb_manager = GSD_XRDB_MANAGER (object);
+
+ G_OBJECT_CLASS (gsd_xrdb_manager_parent_class)->dispose (object);
+}
+
+static void
+gsd_xrdb_manager_class_init (GsdXrdbManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gsd_xrdb_manager_get_property;
+ object_class->set_property = gsd_xrdb_manager_set_property;
+ object_class->constructor = gsd_xrdb_manager_constructor;
+ object_class->dispose = gsd_xrdb_manager_dispose;
+ object_class->finalize = gsd_xrdb_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdXrdbManagerPrivate));
+}
+
+static void
+gsd_xrdb_manager_init (GsdXrdbManager *manager)
+{
+ manager->priv = GSD_XRDB_MANAGER_GET_PRIVATE (manager);
+
+}
+
+static void
+gsd_xrdb_manager_finalize (GObject *object)
+{
+ GsdXrdbManager *xrdb_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_XRDB_MANAGER (object));
+
+ xrdb_manager = GSD_XRDB_MANAGER (object);
+
+ g_return_if_fail (xrdb_manager->priv != NULL);
+
+ G_OBJECT_CLASS (gsd_xrdb_manager_parent_class)->finalize (object);
+}
+
+GsdXrdbManager *
+gsd_xrdb_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (GSD_TYPE_XRDB_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return GSD_XRDB_MANAGER (manager_object);
+}
diff --git a/plugins/xrdb/gsd-xrdb-manager.h b/plugins/xrdb/gsd-xrdb-manager.h
new file mode 100644
index 0000000..4588e69
--- /dev/null
+++ b/plugins/xrdb/gsd-xrdb-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_XRDB_MANAGER_H
+#define __GSD_XRDB_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_XRDB_MANAGER (gsd_xrdb_manager_get_type ())
+#define GSD_XRDB_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_XRDB_MANAGER, GsdXrdbManager))
+#define GSD_XRDB_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_XRDB_MANAGER, GsdXrdbManagerClass))
+#define GSD_IS_XRDB_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_XRDB_MANAGER))
+#define GSD_IS_XRDB_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_XRDB_MANAGER))
+#define GSD_XRDB_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_XRDB_MANAGER, GsdXrdbManagerClass))
+
+typedef struct GsdXrdbManagerPrivate GsdXrdbManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdXrdbManagerPrivate *priv;
+} GsdXrdbManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdXrdbManagerClass;
+
+GType gsd_xrdb_manager_get_type (void);
+
+GsdXrdbManager * gsd_xrdb_manager_new (void);
+gboolean gsd_xrdb_manager_start (GsdXrdbManager *manager,
+ GError **error);
+void gsd_xrdb_manager_stop (GsdXrdbManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_XRDB_MANAGER_H */
diff --git a/plugins/xrdb/gsd-xrdb-plugin.c b/plugins/xrdb/gsd-xrdb-plugin.c
new file mode 100644
index 0000000..870eb56
--- /dev/null
+++ b/plugins/xrdb/gsd-xrdb-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-xrdb-plugin.h"
+#include "gsd-xrdb-manager.h"
+
+struct GsdXrdbPluginPrivate {
+ GsdXrdbManager *manager;
+};
+
+#define GSD_XRDB_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_XRDB_PLUGIN, GsdXrdbPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (GsdXrdbPlugin, gsd_xrdb_plugin)
+
+static void
+gsd_xrdb_plugin_init (GsdXrdbPlugin *plugin)
+{
+ plugin->priv = GSD_XRDB_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("GsdXrdbPlugin initializing");
+
+ plugin->priv->manager = gsd_xrdb_manager_new ();
+}
+
+static void
+gsd_xrdb_plugin_finalize (GObject *object)
+{
+ GsdXrdbPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GSD_IS_XRDB_PLUGIN (object));
+
+ g_debug ("GsdXrdbPlugin finalizing");
+
+ plugin = GSD_XRDB_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (gsd_xrdb_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating xrdb plugin");
+
+ error = NULL;
+ res = gsd_xrdb_manager_start (GSD_XRDB_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start xrdb manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating xrdb plugin");
+ gsd_xrdb_manager_stop (GSD_XRDB_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+gsd_xrdb_plugin_class_init (GsdXrdbPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gsd_xrdb_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (GsdXrdbPluginPrivate));
+}
diff --git a/plugins/xrdb/gsd-xrdb-plugin.h b/plugins/xrdb/gsd-xrdb-plugin.h
new file mode 100644
index 0000000..9baa26a
--- /dev/null
+++ b/plugins/xrdb/gsd-xrdb-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_XRDB_PLUGIN_H__
+#define __GSD_XRDB_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GSD_TYPE_XRDB_PLUGIN (gsd_xrdb_plugin_get_type ())
+#define GSD_XRDB_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_XRDB_PLUGIN, GsdXrdbPlugin))
+#define GSD_XRDB_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_XRDB_PLUGIN, GsdXrdbPluginClass))
+#define GSD_IS_XRDB_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_XRDB_PLUGIN))
+#define GSD_IS_XRDB_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_XRDB_PLUGIN))
+#define GSD_XRDB_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_XRDB_PLUGIN, GsdXrdbPluginClass))
+
+typedef struct GsdXrdbPluginPrivate GsdXrdbPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ GsdXrdbPluginPrivate *priv;
+} GsdXrdbPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} GsdXrdbPluginClass;
+
+GType gsd_xrdb_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSD_XRDB_PLUGIN_H__ */
diff --git a/plugins/xrdb/xrdb.mate-settings-plugin.in b/plugins/xrdb/xrdb.mate-settings-plugin.in
new file mode 100644
index 0000000..e21a4c2
--- /dev/null
+++ b/plugins/xrdb/xrdb.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=xrdb
+IAge=0
+_Name=X Resource Database
+_Description=Manage the X resource database
+Authors=Ross Burton
+Copyright=Copyright © 2007 Ross Burton
+Website=
diff --git a/plugins/xsettings/Makefile.am b/plugins/xsettings/Makefile.am
new file mode 100644
index 0000000..8b861b9
--- /dev/null
+++ b/plugins/xsettings/Makefile.am
@@ -0,0 +1,65 @@
+NULL =
+
+plugin_LTLIBRARIES = \
+ libxsettings.la \
+ $(NULL)
+
+libxsettings_la_SOURCES = \
+ gsd-xsettings-plugin.h \
+ gsd-xsettings-plugin.c \
+ gsd-xsettings-manager.h \
+ gsd-xsettings-manager.c \
+ xsettings-common.h \
+ xsettings-common.c \
+ xsettings-manager.h \
+ xsettings-manager.c \
+ $(NULL)
+
+libxsettings_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libxsettings_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libxsettings_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libxsettings_la_LIBADD = \
+ $(SETTINGS_PLUGIN_LIBS) \
+ $(NULL)
+
+if HAVE_FONTCONFIG
+libxsettings_la_SOURCES += \
+ fontconfig-monitor.h \
+ fontconfig-monitor.c \
+ $(NULL)
+libxsettings_la_CFLAGS += \
+ $(FONTCONFIG_CFLAGS)
+libxsettings_la_LIBADD += \
+ $(FONTCONFIG_LIBS)
+endif
+
+
+plugin_in_files = \
+ xsettings.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/xsettings/Makefile.in b/plugins/xsettings/Makefile.in
new file mode 100644
index 0000000..4f5f8ed
--- /dev/null
+++ b/plugins/xsettings/Makefile.in
@@ -0,0 +1,718 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_FONTCONFIG_TRUE@am__append_1 = \
+@HAVE_FONTCONFIG_TRUE@ fontconfig-monitor.h \
+@HAVE_FONTCONFIG_TRUE@ fontconfig-monitor.c \
+@HAVE_FONTCONFIG_TRUE@ $(NULL)
+
+@HAVE_FONTCONFIG_TRUE@am__append_2 = \
+@HAVE_FONTCONFIG_TRUE@ $(FONTCONFIG_CFLAGS)
+
+@HAVE_FONTCONFIG_TRUE@am__append_3 = \
+@HAVE_FONTCONFIG_TRUE@ $(FONTCONFIG_LIBS)
+
+subdir = plugins/xsettings
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@HAVE_FONTCONFIG_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+libxsettings_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+am__libxsettings_la_SOURCES_DIST = gsd-xsettings-plugin.h \
+ gsd-xsettings-plugin.c gsd-xsettings-manager.h \
+ gsd-xsettings-manager.c xsettings-common.h xsettings-common.c \
+ xsettings-manager.h xsettings-manager.c fontconfig-monitor.h \
+ fontconfig-monitor.c
+am__objects_1 =
+@HAVE_FONTCONFIG_TRUE@am__objects_2 = \
+@HAVE_FONTCONFIG_TRUE@ libxsettings_la-fontconfig-monitor.lo \
+@HAVE_FONTCONFIG_TRUE@ $(am__objects_1)
+am_libxsettings_la_OBJECTS = libxsettings_la-gsd-xsettings-plugin.lo \
+ libxsettings_la-gsd-xsettings-manager.lo \
+ libxsettings_la-xsettings-common.lo \
+ libxsettings_la-xsettings-manager.lo $(am__objects_1) \
+ $(am__objects_2)
+libxsettings_la_OBJECTS = $(am_libxsettings_la_OBJECTS)
+libxsettings_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libxsettings_la_CFLAGS) \
+ $(CFLAGS) $(libxsettings_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libxsettings_la_SOURCES)
+DIST_SOURCES = $(am__libxsettings_la_SOURCES_DIST)
+DATA = $(plugin_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@
+GIOUNIX_LIBS = @GIOUNIX_LIBS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSD_INTLTOOL_PLUGIN_RULE = @GSD_INTLTOOL_PLUGIN_RULE@
+GSD_PLUGIN_LDFLAGS = @GSD_PLUGIN_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEXECDIR = @LIBEXECDIR@
+LIBMATEKBDUI_CFLAGS = @LIBMATEKBDUI_CFLAGS@
+LIBMATEKBDUI_LIBS = @LIBMATEKBDUI_LIBS@
+LIBMATENOTIFY_CFLAGS = @LIBMATENOTIFY_CFLAGS@
+LIBMATENOTIFY_LIBS = @LIBMATENOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATE_KEYBINDINGS_KEYSDIR = @MATE_KEYBINDINGS_KEYSDIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_DATABASE = @NSS_DATABASE@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SETTINGS_DAEMON_CFLAGS = @SETTINGS_DAEMON_CFLAGS@
+SETTINGS_DAEMON_LIBS = @SETTINGS_DAEMON_LIBS@
+SETTINGS_PLUGIN_CFLAGS = @SETTINGS_PLUGIN_CFLAGS@
+SETTINGS_PLUGIN_LIBS = @SETTINGS_PLUGIN_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XGETTEXT = @XGETTEXT@
+XINPUT_LIBS = @XINPUT_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+plugin_LTLIBRARIES = \
+ libxsettings.la \
+ $(NULL)
+
+libxsettings_la_SOURCES = gsd-xsettings-plugin.h \
+ gsd-xsettings-plugin.c gsd-xsettings-manager.h \
+ gsd-xsettings-manager.c xsettings-common.h xsettings-common.c \
+ xsettings-manager.h xsettings-manager.c $(NULL) \
+ $(am__append_1)
+libxsettings_la_CPPFLAGS = \
+ -I$(top_srcdir)/mate-settings-daemon \
+ -DMATE_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libxsettings_la_CFLAGS = $(SETTINGS_PLUGIN_CFLAGS) $(AM_CFLAGS) \
+ $(am__append_2)
+libxsettings_la_LDFLAGS = \
+ $(GSD_PLUGIN_LDFLAGS) \
+ $(NULL)
+
+libxsettings_la_LIBADD = $(SETTINGS_PLUGIN_LIBS) $(NULL) \
+ $(am__append_3)
+plugin_in_files = \
+ xsettings.mate-settings-plugin.in \
+ $(NULL)
+
+plugin_DATA = $(plugin_in_files:.mate-settings-plugin.in=.mate-settings-plugin)
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(plugin_DATA) \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/xsettings/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/xsettings/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libxsettings.la: $(libxsettings_la_OBJECTS) $(libxsettings_la_DEPENDENCIES)
+ $(libxsettings_la_LINK) -rpath $(plugindir) $(libxsettings_la_OBJECTS) $(libxsettings_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxsettings_la-fontconfig-monitor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxsettings_la-gsd-xsettings-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxsettings_la-gsd-xsettings-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxsettings_la-xsettings-common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxsettings_la-xsettings-manager.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libxsettings_la-gsd-xsettings-plugin.lo: gsd-xsettings-plugin.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -MT libxsettings_la-gsd-xsettings-plugin.lo -MD -MP -MF $(DEPDIR)/libxsettings_la-gsd-xsettings-plugin.Tpo -c -o libxsettings_la-gsd-xsettings-plugin.lo `test -f 'gsd-xsettings-plugin.c' || echo '$(srcdir)/'`gsd-xsettings-plugin.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxsettings_la-gsd-xsettings-plugin.Tpo $(DEPDIR)/libxsettings_la-gsd-xsettings-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xsettings-plugin.c' object='libxsettings_la-gsd-xsettings-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -c -o libxsettings_la-gsd-xsettings-plugin.lo `test -f 'gsd-xsettings-plugin.c' || echo '$(srcdir)/'`gsd-xsettings-plugin.c
+
+libxsettings_la-gsd-xsettings-manager.lo: gsd-xsettings-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -MT libxsettings_la-gsd-xsettings-manager.lo -MD -MP -MF $(DEPDIR)/libxsettings_la-gsd-xsettings-manager.Tpo -c -o libxsettings_la-gsd-xsettings-manager.lo `test -f 'gsd-xsettings-manager.c' || echo '$(srcdir)/'`gsd-xsettings-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxsettings_la-gsd-xsettings-manager.Tpo $(DEPDIR)/libxsettings_la-gsd-xsettings-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsd-xsettings-manager.c' object='libxsettings_la-gsd-xsettings-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -c -o libxsettings_la-gsd-xsettings-manager.lo `test -f 'gsd-xsettings-manager.c' || echo '$(srcdir)/'`gsd-xsettings-manager.c
+
+libxsettings_la-xsettings-common.lo: xsettings-common.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -MT libxsettings_la-xsettings-common.lo -MD -MP -MF $(DEPDIR)/libxsettings_la-xsettings-common.Tpo -c -o libxsettings_la-xsettings-common.lo `test -f 'xsettings-common.c' || echo '$(srcdir)/'`xsettings-common.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxsettings_la-xsettings-common.Tpo $(DEPDIR)/libxsettings_la-xsettings-common.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xsettings-common.c' object='libxsettings_la-xsettings-common.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -c -o libxsettings_la-xsettings-common.lo `test -f 'xsettings-common.c' || echo '$(srcdir)/'`xsettings-common.c
+
+libxsettings_la-xsettings-manager.lo: xsettings-manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -MT libxsettings_la-xsettings-manager.lo -MD -MP -MF $(DEPDIR)/libxsettings_la-xsettings-manager.Tpo -c -o libxsettings_la-xsettings-manager.lo `test -f 'xsettings-manager.c' || echo '$(srcdir)/'`xsettings-manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxsettings_la-xsettings-manager.Tpo $(DEPDIR)/libxsettings_la-xsettings-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xsettings-manager.c' object='libxsettings_la-xsettings-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -c -o libxsettings_la-xsettings-manager.lo `test -f 'xsettings-manager.c' || echo '$(srcdir)/'`xsettings-manager.c
+
+libxsettings_la-fontconfig-monitor.lo: fontconfig-monitor.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -MT libxsettings_la-fontconfig-monitor.lo -MD -MP -MF $(DEPDIR)/libxsettings_la-fontconfig-monitor.Tpo -c -o libxsettings_la-fontconfig-monitor.lo `test -f 'fontconfig-monitor.c' || echo '$(srcdir)/'`fontconfig-monitor.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxsettings_la-fontconfig-monitor.Tpo $(DEPDIR)/libxsettings_la-fontconfig-monitor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fontconfig-monitor.c' object='libxsettings_la-fontconfig-monitor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxsettings_la_CPPFLAGS) $(CPPFLAGS) $(libxsettings_la_CFLAGS) $(CFLAGS) -c -o libxsettings_la-fontconfig-monitor.lo `test -f 'fontconfig-monitor.c' || echo '$(srcdir)/'`fontconfig-monitor.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pluginDATA: $(plugin_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugindir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(plugindir)" || exit $$?; \
+ done
+
+uninstall-pluginDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_DATA)'; test -n "$(plugindir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(plugindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(plugindir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginDATA \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginDATA uninstall-pluginLTLIBRARIES
+
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/xsettings/fontconfig-monitor.c b/plugins/xsettings/fontconfig-monitor.c
new file mode 100644
index 0000000..bfb15ed
--- /dev/null
+++ b/plugins/xsettings/fontconfig-monitor.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Behdad Esfahbod, Red Hat, Inc.
+ */
+
+#include "fontconfig-monitor.h"
+
+#include <gio/gio.h>
+#include <fontconfig/fontconfig.h>
+
+#define TIMEOUT_SECONDS 2
+
+static void
+stuff_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer handle);
+
+void
+fontconfig_cache_init (void)
+{
+ FcInit ();
+}
+
+gboolean
+fontconfig_cache_update (void)
+{
+ return !FcConfigUptoDate (NULL) && FcInitReinitialize ();
+}
+
+static void
+monitor_files (GPtrArray *monitors,
+ FcStrList *list,
+ gpointer data)
+{
+ const char *str;
+
+ while ((str = (const char *) FcStrListNext (list))) {
+ GFile *file;
+ GFileMonitor *monitor;
+
+ file = g_file_new_for_path (str);
+
+ monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);
+
+ g_object_unref (file);
+
+ if (!monitor)
+ continue;
+
+ g_signal_connect (monitor, "changed", G_CALLBACK (stuff_changed), data);
+
+ g_ptr_array_add (monitors, monitor);
+ }
+
+ FcStrListDone (list);
+}
+
+
+struct _fontconfig_monitor_handle {
+ GPtrArray *monitors;
+
+ guint timeout;
+
+ GFunc notify_callback;
+ gpointer notify_data;
+};
+
+static GPtrArray *
+monitors_create (gpointer data)
+{
+ GPtrArray *monitors = g_ptr_array_new ();
+
+ monitor_files (monitors, FcConfigGetConfigFiles (NULL), data);
+ monitor_files (monitors, FcConfigGetFontDirs (NULL) , data);
+
+ return monitors;
+}
+
+static void
+monitors_free (GPtrArray *monitors)
+{
+ if (!monitors)
+ return;
+
+ g_ptr_array_foreach (monitors, (GFunc) g_object_unref, NULL);
+ g_ptr_array_free (monitors, TRUE);
+}
+
+static gboolean
+update (gpointer data)
+{
+ fontconfig_monitor_handle_t *handle = data;
+ gboolean notify = FALSE;
+
+ handle->timeout = 0;
+
+ if (fontconfig_cache_update ()) {
+ notify = TRUE;
+ monitors_free (handle->monitors);
+ handle->monitors = monitors_create (data);
+ }
+
+ /* we finish modifying handle before calling the notify callback,
+ * allowing the callback to free the monitor if it decides to. */
+
+ if (notify && handle->notify_callback)
+ handle->notify_callback (data, handle->notify_data);
+
+ return FALSE;
+}
+
+static void
+stuff_changed (GFileMonitor *monitor G_GNUC_UNUSED,
+ GFile *file G_GNUC_UNUSED,
+ GFile *other_file G_GNUC_UNUSED,
+ GFileMonitorEvent event_type G_GNUC_UNUSED,
+ gpointer data)
+{
+ fontconfig_monitor_handle_t *handle = data;
+
+ /* wait for quiescence */
+ if (handle->timeout)
+ g_source_remove (handle->timeout);
+
+ handle->timeout = g_timeout_add_seconds (TIMEOUT_SECONDS, update, data);
+}
+
+
+fontconfig_monitor_handle_t *
+fontconfig_monitor_start (GFunc notify_callback,
+ gpointer notify_data)
+{
+ fontconfig_monitor_handle_t *handle = g_slice_new0 (fontconfig_monitor_handle_t);
+
+ handle->notify_callback = notify_callback;
+ handle->notify_data = notify_data;
+ handle->monitors = monitors_create (handle);
+
+ return handle;
+}
+
+void
+fontconfig_monitor_stop (fontconfig_monitor_handle_t *handle)
+{
+ if (handle->timeout)
+ g_source_remove (handle->timeout);
+ handle->timeout = 0;
+
+ monitors_free (handle->monitors);
+ handle->monitors = NULL;
+}
+
+#ifdef FONTCONFIG_MONITOR_TEST
+static void
+yay (void)
+{
+ g_message ("yay");
+}
+
+int
+main (void)
+{
+ GMainLoop *loop;
+
+ g_type_init ();
+
+ fontconfig_monitor_start ((GFunc) yay, NULL);
+
+ loop = g_main_loop_new (NULL, TRUE);
+ g_main_loop_run (loop);
+
+ return 0;
+}
+#endif
diff --git a/plugins/xsettings/fontconfig-monitor.h b/plugins/xsettings/fontconfig-monitor.h
new file mode 100644
index 0000000..71256e4
--- /dev/null
+++ b/plugins/xsettings/fontconfig-monitor.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Behdad Esfahbod, Red Hat, Inc.
+ */
+#ifndef __FONTCONFIG_MONITOR_H
+#define __FONTCONFIG_MONITOR_H
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fontconfig_cache_init (void);
+gboolean fontconfig_cache_update (void);
+
+typedef struct _fontconfig_monitor_handle fontconfig_monitor_handle_t;
+
+fontconfig_monitor_handle_t *
+fontconfig_monitor_start (GFunc notify_callback,
+ gpointer notify_data);
+void fontconfig_monitor_stop (fontconfig_monitor_handle_t *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FONTCONFIG_MONITOR_H */
diff --git a/plugins/xsettings/gsd-xsettings-manager.c b/plugins/xsettings/gsd-xsettings-manager.c
new file mode 100644
index 0000000..e7b4f9a
--- /dev/null
+++ b/plugins/xsettings/gsd-xsettings-manager.c
@@ -0,0 +1,1040 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Rodrigo Moya
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include <X11/Xatom.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf.h>
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-profile.h"
+#include "gsd-xsettings-manager.h"
+#include "xsettings-manager.h"
+#ifdef HAVE_FONTCONFIG
+#include "fontconfig-monitor.h"
+#endif /* HAVE_FONTCONFIG */
+
+#define MATE_XSETTINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MATE_TYPE_XSETTINGS_MANAGER, MateXSettingsManagerPrivate))
+
+#define MOUSE_SETTINGS_DIR "/desktop/mate/peripherals/mouse"
+#define GTK_SETTINGS_DIR "/desktop/gtk"
+#define INTERFACE_SETTINGS_DIR "/desktop/mate/interface"
+#define SOUND_SETTINGS_DIR "/desktop/mate/sound"
+#define GTK_MODULES_DIR "/apps/mate_settings_daemon/gtk-modules"
+
+#ifdef HAVE_FONTCONFIG
+#define FONT_RENDER_DIR "/desktop/mate/font_rendering"
+#define FONT_ANTIALIASING_KEY FONT_RENDER_DIR "/antialiasing"
+#define FONT_HINTING_KEY FONT_RENDER_DIR "/hinting"
+#define FONT_RGBA_ORDER_KEY FONT_RENDER_DIR "/rgba_order"
+#define FONT_DPI_KEY FONT_RENDER_DIR "/dpi"
+
+/* X servers sometimes lie about the screen's physical dimensions, so we cannot
+ * compute an accurate DPI value. When this happens, the user gets fonts that
+ * are too huge or too tiny. So, we see what the server returns: if it reports
+ * something outside of the range [DPI_LOW_REASONABLE_VALUE,
+ * DPI_HIGH_REASONABLE_VALUE], then we assume that it is lying and we use
+ * DPI_FALLBACK instead.
+ *
+ * See get_dpi_from_mateconf_or_server() below, and also
+ * https://bugzilla.novell.com/show_bug.cgi?id=217790
+ */
+#define DPI_FALLBACK 96
+#define DPI_LOW_REASONABLE_VALUE 50
+#define DPI_HIGH_REASONABLE_VALUE 500
+
+#endif /* HAVE_FONTCONFIG */
+
+typedef struct _TranslationEntry TranslationEntry;
+typedef void (* TranslationFunc) (MateXSettingsManager *manager,
+ TranslationEntry *trans,
+ MateConfValue *value);
+
+struct _TranslationEntry {
+ const char *mateconf_key;
+ const char *xsetting_name;
+
+ MateConfValueType mateconf_type;
+ TranslationFunc translate;
+};
+
+struct MateXSettingsManagerPrivate
+{
+ XSettingsManager **managers;
+ guint notify[6];
+#ifdef HAVE_FONTCONFIG
+ fontconfig_monitor_handle_t *fontconfig_handle;
+#endif /* HAVE_FONTCONFIG */
+};
+
+#define GSD_XSETTINGS_ERROR gsd_xsettings_error_quark ()
+
+enum {
+ GSD_XSETTINGS_ERROR_INIT
+};
+
+static void mate_xsettings_manager_class_init (MateXSettingsManagerClass *klass);
+static void mate_xsettings_manager_init (MateXSettingsManager *xsettings_manager);
+static void mate_xsettings_manager_finalize (GObject *object);
+
+G_DEFINE_TYPE (MateXSettingsManager, mate_xsettings_manager, G_TYPE_OBJECT)
+
+static gpointer manager_object = NULL;
+
+static GQuark
+gsd_xsettings_error_quark (void)
+{
+ return g_quark_from_static_string ("gsd-xsettings-error-quark");
+}
+
+static void
+translate_bool_int (MateXSettingsManager *manager,
+ TranslationEntry *trans,
+ MateConfValue *value)
+{
+ int i;
+
+ g_assert (value->type == trans->mateconf_type);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_int (manager->priv->managers [i], trans->xsetting_name,
+ mateconf_value_get_bool (value));
+ }
+}
+
+static void
+translate_int_int (MateXSettingsManager *manager,
+ TranslationEntry *trans,
+ MateConfValue *value)
+{
+ int i;
+
+ g_assert (value->type == trans->mateconf_type);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_int (manager->priv->managers [i], trans->xsetting_name,
+ mateconf_value_get_int (value));
+ }
+}
+
+static void
+translate_string_string (MateXSettingsManager *manager,
+ TranslationEntry *trans,
+ MateConfValue *value)
+{
+ int i;
+
+ g_assert (value->type == trans->mateconf_type);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_string (manager->priv->managers [i],
+ trans->xsetting_name,
+ mateconf_value_get_string (value));
+ }
+}
+
+static void
+translate_string_string_toolbar (MateXSettingsManager *manager,
+ TranslationEntry *trans,
+ MateConfValue *value)
+{
+ int i;
+ const char *tmp;
+
+ g_assert (value->type == trans->mateconf_type);
+
+ /* This is kind of a workaround since MATE expects the key value to be
+ * "both_horiz" and gtk+ wants the XSetting to be "both-horiz".
+ */
+ tmp = mateconf_value_get_string (value);
+ if (tmp && strcmp (tmp, "both_horiz") == 0) {
+ tmp = "both-horiz";
+ }
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_string (manager->priv->managers [i],
+ trans->xsetting_name,
+ tmp);
+ }
+}
+
+static TranslationEntry translations [] = {
+ { "/desktop/mate/peripherals/mouse/double_click", "Net/DoubleClickTime", MATECONF_VALUE_INT, translate_int_int },
+ { "/desktop/mate/peripherals/mouse/drag_threshold", "Net/DndDragThreshold", MATECONF_VALUE_INT, translate_int_int },
+ { "/desktop/mate/gtk-color-palette", "Gtk/ColorPalette", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/font_name", "Gtk/FontName", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/gtk_key_theme", "Gtk/KeyThemeName", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/toolbar_style", "Gtk/ToolbarStyle", MATECONF_VALUE_STRING, translate_string_string_toolbar },
+ { "/desktop/mate/interface/toolbar_icons_size", "Gtk/ToolbarIconSize", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/can_change_accels", "Gtk/CanChangeAccels", MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/interface/cursor_blink", "Net/CursorBlink", MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/interface/cursor_blink_time", "Net/CursorBlinkTime", MATECONF_VALUE_INT, translate_int_int },
+ { "/desktop/mate/interface/gtk_theme", "Net/ThemeName", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/gtk_color_scheme", "Gtk/ColorScheme", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/gtk-im-preedit-style", "Gtk/IMPreeditStyle", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/gtk-im-status-style", "Gtk/IMStatusStyle", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/gtk-im-module", "Gtk/IMModule", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/icon_theme", "Net/IconThemeName", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/file_chooser_backend", "Gtk/FileChooserBackend", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/interface/menus_have_icons", "Gtk/MenuImages", MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/interface/buttons_have_icons", "Gtk/ButtonImages", MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/interface/menubar_accel", "Gtk/MenuBarAccel", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/peripherals/mouse/cursor_theme", "Gtk/CursorThemeName", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/peripherals/mouse/cursor_size", "Gtk/CursorThemeSize", MATECONF_VALUE_INT, translate_int_int },
+ { "/desktop/mate/interface/show_input_method_menu", "Gtk/ShowInputMethodMenu", MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/interface/show_unicode_menu", "Gtk/ShowUnicodeMenu", MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/sound/theme_name", "Net/SoundThemeName", MATECONF_VALUE_STRING, translate_string_string },
+ { "/desktop/mate/sound/event_sounds", "Net/EnableEventSounds" , MATECONF_VALUE_BOOL, translate_bool_int },
+ { "/desktop/mate/sound/input_feedback_sounds", "Net/EnableInputFeedbackSounds", MATECONF_VALUE_BOOL, translate_bool_int }
+};
+
+#ifdef HAVE_FONTCONFIG
+static double
+dpi_from_pixels_and_mm (int pixels,
+ int mm)
+{
+ double dpi;
+
+ if (mm >= 1)
+ dpi = pixels / (mm / 25.4);
+ else
+ dpi = 0;
+
+ return dpi;
+}
+
+static double
+get_dpi_from_x_server (void)
+{
+ GdkScreen *screen;
+ double dpi;
+
+ screen = gdk_screen_get_default ();
+ if (screen != NULL) {
+ double width_dpi, height_dpi;
+
+ width_dpi = dpi_from_pixels_and_mm (gdk_screen_get_width (screen), gdk_screen_get_width_mm (screen));
+ height_dpi = dpi_from_pixels_and_mm (gdk_screen_get_height (screen), gdk_screen_get_height_mm (screen));
+
+ if (width_dpi < DPI_LOW_REASONABLE_VALUE || width_dpi > DPI_HIGH_REASONABLE_VALUE
+ || height_dpi < DPI_LOW_REASONABLE_VALUE || height_dpi > DPI_HIGH_REASONABLE_VALUE) {
+ dpi = DPI_FALLBACK;
+ } else {
+ dpi = (width_dpi + height_dpi) / 2.0;
+ }
+ } else {
+ /* Huh!? No screen? */
+
+ dpi = DPI_FALLBACK;
+ }
+
+ return dpi;
+}
+
+static double
+get_dpi_from_mateconf_or_x_server (MateConfClient *client)
+{
+ MateConfValue *value;
+ double dpi;
+
+ value = mateconf_client_get_without_default (client, FONT_DPI_KEY, NULL);
+
+ /* If the user has ever set the DPI preference in MateConf, we use that.
+ * Otherwise, we see if the X server reports a reasonable DPI value: some X
+ * servers report completely bogus values, and the user gets huge or tiny
+ * fonts which are unusable.
+ */
+
+ if (value != NULL) {
+ dpi = mateconf_value_get_float (value);
+ mateconf_value_free (value);
+ } else {
+ dpi = get_dpi_from_x_server ();
+ }
+
+ return dpi;
+}
+
+typedef struct
+{
+ gboolean antialias;
+ gboolean hinting;
+ int dpi;
+ const char *rgba;
+ const char *hintstyle;
+} MateXftSettings;
+
+static const char *rgba_types[] = { "rgb", "bgr", "vbgr", "vrgb" };
+
+/* Read MateConf settings and determine the appropriate Xft settings based on them
+ * This probably could be done a bit more cleanly with mateconf_string_to_enum
+ */
+static void
+xft_settings_get (MateConfClient *client,
+ MateXftSettings *settings)
+{
+ char *antialiasing;
+ char *hinting;
+ char *rgba_order;
+ double dpi;
+
+ antialiasing = mateconf_client_get_string (client, FONT_ANTIALIASING_KEY, NULL);
+ hinting = mateconf_client_get_string (client, FONT_HINTING_KEY, NULL);
+ rgba_order = mateconf_client_get_string (client, FONT_RGBA_ORDER_KEY, NULL);
+ dpi = get_dpi_from_mateconf_or_x_server (client);
+
+ settings->antialias = TRUE;
+ settings->hinting = TRUE;
+ settings->hintstyle = "hintfull";
+ settings->dpi = dpi * 1024; /* Xft wants 1/1024ths of an inch */
+ settings->rgba = "rgb";
+
+ if (rgba_order) {
+ int i;
+ gboolean found = FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (rgba_types) && !found; i++) {
+ if (strcmp (rgba_order, rgba_types[i]) == 0) {
+ settings->rgba = rgba_types[i];
+ found = TRUE;
+ }
+ }
+
+ if (!found) {
+ g_warning ("Invalid value for " FONT_RGBA_ORDER_KEY ": '%s'",
+ rgba_order);
+ }
+ }
+
+ if (hinting) {
+ if (strcmp (hinting, "none") == 0) {
+ settings->hinting = 0;
+ settings->hintstyle = "hintnone";
+ } else if (strcmp (hinting, "slight") == 0) {
+ settings->hinting = 1;
+ settings->hintstyle = "hintslight";
+ } else if (strcmp (hinting, "medium") == 0) {
+ settings->hinting = 1;
+ settings->hintstyle = "hintmedium";
+ } else if (strcmp (hinting, "full") == 0) {
+ settings->hinting = 1;
+ settings->hintstyle = "hintfull";
+ } else {
+ g_warning ("Invalid value for " FONT_HINTING_KEY ": '%s'",
+ hinting);
+ }
+ }
+
+ if (antialiasing) {
+ gboolean use_rgba = FALSE;
+
+ if (strcmp (antialiasing, "none") == 0) {
+ settings->antialias = 0;
+ } else if (strcmp (antialiasing, "grayscale") == 0) {
+ settings->antialias = 1;
+ } else if (strcmp (antialiasing, "rgba") == 0) {
+ settings->antialias = 1;
+ use_rgba = TRUE;
+ } else {
+ g_warning ("Invalid value for " FONT_ANTIALIASING_KEY " : '%s'",
+ antialiasing);
+ }
+
+ if (!use_rgba) {
+ settings->rgba = "none";
+ }
+ }
+
+ g_free (rgba_order);
+ g_free (hinting);
+ g_free (antialiasing);
+}
+
+static void
+xft_settings_set_xsettings (MateXSettingsManager *manager,
+ MateXftSettings *settings)
+{
+ int i;
+
+ mate_settings_profile_start (NULL);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_int (manager->priv->managers [i], "Xft/Antialias", settings->antialias);
+ xsettings_manager_set_int (manager->priv->managers [i], "Xft/Hinting", settings->hinting);
+ xsettings_manager_set_string (manager->priv->managers [i], "Xft/HintStyle", settings->hintstyle);
+ xsettings_manager_set_int (manager->priv->managers [i], "Xft/DPI", settings->dpi);
+ xsettings_manager_set_string (manager->priv->managers [i], "Xft/RGBA", settings->rgba);
+ }
+ mate_settings_profile_end (NULL);
+}
+
+static void
+update_property (GString *props, const gchar* key, const gchar* value)
+{
+ gchar* needle;
+ size_t needle_len;
+ gchar* found = NULL;
+
+ /* update an existing property */
+ needle = g_strconcat (key, ":", NULL);
+ needle_len = strlen (needle);
+ if (g_str_has_prefix (props->str, needle))
+ found = props->str;
+ else
+ found = strstr (props->str, needle);
+
+ if (found) {
+ size_t value_index;
+ gchar* end;
+
+ end = strchr (found, '\n');
+ value_index = (found - props->str) + needle_len + 1;
+ g_string_erase (props, value_index, end ? (end - found - needle_len) : -1);
+ g_string_insert (props, value_index, "\n");
+ g_string_insert (props, value_index, value);
+ } else {
+ g_string_append_printf (props, "%s:\t%s\n", key, value);
+ }
+}
+
+static void
+xft_settings_set_xresources (MateXftSettings *settings)
+{
+ GString *add_string;
+ char dpibuf[G_ASCII_DTOSTR_BUF_SIZE];
+ Display *dpy;
+
+ mate_settings_profile_start (NULL);
+
+ /* get existing properties */
+ dpy = XOpenDisplay (NULL);
+ g_return_if_fail (dpy != NULL);
+ add_string = g_string_new (XResourceManagerString (dpy));
+
+ g_debug("xft_settings_set_xresources: orig res '%s'", add_string->str);
+
+ update_property (add_string, "Xft.dpi",
+ g_ascii_dtostr (dpibuf, sizeof (dpibuf), (double) settings->dpi / 1024.0));
+ update_property (add_string, "Xft.antialias",
+ settings->antialias ? "1" : "0");
+ update_property (add_string, "Xft.hinting",
+ settings->hinting ? "1" : "0");
+ update_property (add_string, "Xft.hintstyle",
+ settings->hintstyle);
+ update_property (add_string, "Xft.rgba",
+ settings->rgba);
+
+ g_debug("xft_settings_set_xresources: new res '%s'", add_string->str);
+
+ /* Set the new X property */
+ XChangeProperty(dpy, RootWindow (dpy, 0),
+ XA_RESOURCE_MANAGER, XA_STRING, 8, PropModeReplace, add_string->str, add_string->len);
+ XCloseDisplay (dpy);
+
+ g_string_free (add_string, TRUE);
+
+ mate_settings_profile_end (NULL);
+}
+
+/* We mirror the Xft properties both through XSETTINGS and through
+ * X resources
+ */
+static void
+update_xft_settings (MateXSettingsManager *manager,
+ MateConfClient *client)
+{
+ MateXftSettings settings;
+
+ mate_settings_profile_start (NULL);
+
+ xft_settings_get (client, &settings);
+ xft_settings_set_xsettings (manager, &settings);
+ xft_settings_set_xresources (&settings);
+
+ mate_settings_profile_end (NULL);
+}
+
+static void
+xft_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ MateXSettingsManager *manager)
+{
+ int i;
+
+ update_xft_settings (manager, client);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_notify (manager->priv->managers [i]);
+ }
+}
+
+static void
+fontconfig_callback (fontconfig_monitor_handle_t *handle,
+ MateXSettingsManager *manager)
+{
+ int i;
+ int timestamp = time (NULL);
+
+ mate_settings_profile_start (NULL);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_int (manager->priv->managers [i], "Fontconfig/Timestamp", timestamp);
+ xsettings_manager_notify (manager->priv->managers [i]);
+ }
+ mate_settings_profile_end (NULL);
+}
+
+static gboolean
+start_fontconfig_monitor_idle_cb (MateXSettingsManager *manager)
+{
+ mate_settings_profile_start (NULL);
+
+ manager->priv->fontconfig_handle = fontconfig_monitor_start ((GFunc) fontconfig_callback, manager);
+
+ mate_settings_profile_end (NULL);
+
+ return FALSE;
+}
+
+static void
+start_fontconfig_monitor (MateXSettingsManager *manager)
+{
+ mate_settings_profile_start (NULL);
+
+ fontconfig_cache_init ();
+
+ g_idle_add ((GSourceFunc) start_fontconfig_monitor_idle_cb, manager);
+
+ mate_settings_profile_end (NULL);
+}
+
+static void
+stop_fontconfig_monitor (MateXSettingsManager *manager)
+{
+ if (manager->priv->fontconfig_handle) {
+ fontconfig_monitor_stop (manager->priv->fontconfig_handle);
+ manager->priv->fontconfig_handle = NULL;
+ }
+}
+#endif /* HAVE_FONTCONFIG */
+
+static const char *
+type_to_string (MateConfValueType type)
+{
+ switch (type) {
+ case MATECONF_VALUE_INT:
+ return "int";
+ case MATECONF_VALUE_STRING:
+ return "string";
+ case MATECONF_VALUE_FLOAT:
+ return "float";
+ case MATECONF_VALUE_BOOL:
+ return "bool";
+ case MATECONF_VALUE_SCHEMA:
+ return "schema";
+ case MATECONF_VALUE_LIST:
+ return "list";
+ case MATECONF_VALUE_PAIR:
+ return "pair";
+ case MATECONF_VALUE_INVALID:
+ return "*invalid*";
+ default:
+ g_assert_not_reached();
+ return NULL; /* for warnings */
+ }
+}
+
+static void
+process_value (MateXSettingsManager *manager,
+ TranslationEntry *trans,
+ MateConfValue *val)
+{
+ if (val == NULL) {
+ int i;
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_delete_setting (manager->priv->managers [i], trans->xsetting_name);
+ }
+ } else {
+ if (val->type == trans->mateconf_type) {
+ (* trans->translate) (manager, trans, val);
+ } else {
+ g_warning (_("MateConf key %s set to type %s but its expected type was %s\n"),
+ trans->mateconf_key,
+ type_to_string (val->type),
+ type_to_string (trans->mateconf_type));
+ }
+ }
+}
+
+static TranslationEntry *
+find_translation_entry (const char *mateconf_key)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (translations); ++i) {
+ if (strcmp (translations[i].mateconf_key, mateconf_key) == 0) {
+ return &translations[i];
+ }
+ }
+
+ return NULL;
+}
+
+static void
+xsettings_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ MateXSettingsManager *manager)
+{
+ TranslationEntry *trans;
+ int i;
+
+ trans = find_translation_entry (entry->key);
+ if (trans == NULL) {
+ return;
+ }
+
+ process_value (manager, trans, entry->value);
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_set_string (manager->priv->managers [i],
+ "Net/FallbackIconTheme",
+ "mate");
+ }
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_notify (manager->priv->managers [i]);
+ }
+}
+
+static gchar *
+get_gtk_modules (MateConfClient *client)
+{
+ GSList *entries, *l;
+ GString *mods = g_string_new (NULL);
+
+ entries = mateconf_client_all_entries (client, GTK_MODULES_DIR, NULL);
+
+ for (l = entries; l != NULL; l = g_slist_next (l)) {
+ MateConfEntry *e = l->data;
+ MateConfValue *v = mateconf_entry_get_value (e);
+
+ if (v != NULL) {
+ gboolean enabled = FALSE;
+ const gchar *key;
+
+ switch (v->type) {
+ case MATECONF_VALUE_BOOL:
+ /* simple enabled/disabled */
+ enabled = mateconf_value_get_bool (v);
+ break;
+
+ /* due to limitations in MateConf (or the client libraries,
+ * anyway), it is currently impossible to monitor
+ * arbitrary keys for changes, so these won't update at
+ * runtime */
+ case MATECONF_VALUE_STRING:
+ /* linked to another MateConf key of type bool */
+ key = mateconf_value_get_string (v);
+ if (key != NULL && mateconf_valid_key (key, NULL)) {
+ enabled = mateconf_client_get_bool (client, key, NULL);
+ }
+ break;
+
+ default:
+ g_warning ("MateConf entry %s has invalid type %s",
+ mateconf_entry_get_key (e), type_to_string (v->type));
+ }
+
+ if (enabled) {
+ const gchar *name;
+ name = strrchr (mateconf_entry_get_key (e), '/') + 1;
+
+ if (mods->len > 0) {
+ g_string_append_c (mods, ':');
+ }
+ g_string_append (mods, name);
+ }
+ }
+
+ mateconf_entry_free (e);
+ }
+
+ g_slist_free (entries);
+
+ return g_string_free (mods, mods->len == 0);
+}
+
+static void
+gtk_modules_callback (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ MateXSettingsManager *manager)
+{
+ gchar *modules = get_gtk_modules (client);
+ int i;
+
+ if (modules == NULL) {
+ for (i = 0; manager->priv->managers [i]; ++i) {
+ xsettings_manager_delete_setting (manager->priv->managers [i], "Gtk/Modules");
+ }
+ } else {
+ g_debug ("Setting GTK modules '%s'", modules);
+ for (i = 0; manager->priv->managers [i]; ++i) {
+ xsettings_manager_set_string (manager->priv->managers [i],
+ "Gtk/Modules",
+ modules);
+ }
+ g_free (modules);
+ }
+
+ for (i = 0; manager->priv->managers [i]; ++i) {
+ xsettings_manager_notify (manager->priv->managers [i]);
+ }
+}
+
+static guint
+register_config_callback (MateXSettingsManager *manager,
+ MateConfClient *client,
+ const char *path,
+ MateConfClientNotifyFunc func)
+{
+ return mateconf_client_notify_add (client, path, func, manager, NULL, NULL);
+}
+
+static void
+terminate_cb (void *data)
+{
+ gboolean *terminated = data;
+
+ if (*terminated) {
+ return;
+ }
+
+ *terminated = TRUE;
+
+ gtk_main_quit ();
+}
+
+static gboolean
+setup_xsettings_managers (MateXSettingsManager *manager)
+{
+ GdkDisplay *display;
+ int i;
+ int n_screens;
+ gboolean res;
+ gboolean terminated;
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+
+ res = xsettings_manager_check_running (gdk_x11_display_get_xdisplay (display),
+ gdk_screen_get_number (gdk_screen_get_default ()));
+ if (res) {
+ g_warning ("You can only run one xsettings manager at a time; exiting");
+ return FALSE;
+ }
+
+ manager->priv->managers = g_new0 (XSettingsManager *, n_screens + 1);
+
+ terminated = FALSE;
+ for (i = 0; i < n_screens; i++) {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (display, i);
+
+ manager->priv->managers [i] = xsettings_manager_new (gdk_x11_display_get_xdisplay (display),
+ gdk_screen_get_number (screen),
+ terminate_cb,
+ &terminated);
+ if (! manager->priv->managers [i]) {
+ g_warning ("Could not create xsettings manager for screen %d!", i);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+mate_xsettings_manager_start (MateXSettingsManager *manager,
+ GError **error)
+{
+ MateConfClient *client;
+ int i;
+
+ g_debug ("Starting xsettings manager");
+ mate_settings_profile_start (NULL);
+
+ if (!setup_xsettings_managers (manager)) {
+ g_set_error (error, GSD_XSETTINGS_ERROR,
+ GSD_XSETTINGS_ERROR_INIT,
+ "Could not initialize xsettings manager.");
+ return FALSE;
+ }
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_add_dir (client, MOUSE_SETTINGS_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ mateconf_client_add_dir (client, GTK_SETTINGS_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ mateconf_client_add_dir (client, INTERFACE_SETTINGS_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ mateconf_client_add_dir (client, SOUND_SETTINGS_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ mateconf_client_add_dir (client, GTK_MODULES_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ mateconf_client_add_dir (client, FONT_RENDER_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (translations); i++) {
+ MateConfValue *val;
+ GError *err;
+
+ err = NULL;
+ val = mateconf_client_get (client,
+ translations[i].mateconf_key,
+ &err);
+
+ if (err != NULL) {
+ g_warning ("Error getting value for %s: %s",
+ translations[i].mateconf_key,
+ err->message);
+ g_error_free (err);
+ } else {
+ process_value (manager, &translations[i], val);
+ if (val != NULL) {
+ mateconf_value_free (val);
+ }
+ }
+ }
+
+ manager->priv->notify[0] =
+ register_config_callback (manager, client,
+ MOUSE_SETTINGS_DIR,
+ (MateConfClientNotifyFunc) xsettings_callback);
+ manager->priv->notify[1] =
+ register_config_callback (manager, client,
+ GTK_SETTINGS_DIR,
+ (MateConfClientNotifyFunc) xsettings_callback);
+ manager->priv->notify[2] =
+ register_config_callback (manager, client,
+ INTERFACE_SETTINGS_DIR,
+ (MateConfClientNotifyFunc) xsettings_callback);
+ manager->priv->notify[3] =
+ register_config_callback (manager, client,
+ SOUND_SETTINGS_DIR,
+ (MateConfClientNotifyFunc) xsettings_callback);
+
+ manager->priv->notify[4] =
+ register_config_callback (manager, client,
+ GTK_MODULES_DIR,
+ (MateConfClientNotifyFunc) gtk_modules_callback);
+ gtk_modules_callback (client, 0, NULL, manager);
+
+#ifdef HAVE_FONTCONFIG
+ manager->priv->notify[5] =
+ register_config_callback (manager, client,
+ FONT_RENDER_DIR,
+ (MateConfClientNotifyFunc) xft_callback);
+ update_xft_settings (manager, client);
+
+ start_fontconfig_monitor (manager);
+#endif /* HAVE_FONTCONFIG */
+
+ g_object_unref (client);
+
+ for (i = 0; manager->priv->managers [i]; i++)
+ xsettings_manager_set_string (manager->priv->managers [i],
+ "Net/FallbackIconTheme",
+ "mate");
+
+ for (i = 0; manager->priv->managers [i]; i++) {
+ xsettings_manager_notify (manager->priv->managers [i]);
+ }
+
+
+ mate_settings_profile_end (NULL);
+
+ return TRUE;
+}
+
+void
+mate_xsettings_manager_stop (MateXSettingsManager *manager)
+{
+ MateXSettingsManagerPrivate *p = manager->priv;
+ MateConfClient *client;
+ int i;
+
+ g_debug ("Stopping xsettings manager");
+
+ if (p->managers != NULL) {
+ for (i = 0; p->managers [i]; ++i)
+ xsettings_manager_destroy (p->managers [i]);
+
+ g_free (p->managers);
+ p->managers = NULL;
+ }
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_remove_dir (client, MOUSE_SETTINGS_DIR, NULL);
+ mateconf_client_remove_dir (client, GTK_SETTINGS_DIR, NULL);
+ mateconf_client_remove_dir (client, INTERFACE_SETTINGS_DIR, NULL);
+ mateconf_client_remove_dir (client, SOUND_SETTINGS_DIR, NULL);
+ mateconf_client_remove_dir (client, GTK_MODULES_DIR, NULL);
+#ifdef HAVE_FONTCONFIG
+ mateconf_client_remove_dir (client, FONT_RENDER_DIR, NULL);
+
+ stop_fontconfig_monitor (manager);
+#endif /* HAVE_FONTCONFIG */
+
+ for (i = 0; i < G_N_ELEMENTS (p->notify); ++i) {
+ if (p->notify[i] != 0) {
+ mateconf_client_notify_remove (client, p->notify[i]);
+ p->notify[i] = 0;
+ }
+ }
+
+ g_object_unref (client);
+}
+
+static void
+mate_xsettings_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MateXSettingsManager *self;
+
+ self = MATE_XSETTINGS_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+mate_xsettings_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MateXSettingsManager *self;
+
+ self = MATE_XSETTINGS_MANAGER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+mate_xsettings_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ MateXSettingsManager *xsettings_manager;
+ MateXSettingsManagerClass *klass;
+
+ klass = MATE_XSETTINGS_MANAGER_CLASS (g_type_class_peek (MATE_TYPE_XSETTINGS_MANAGER));
+
+ xsettings_manager = MATE_XSETTINGS_MANAGER (G_OBJECT_CLASS (mate_xsettings_manager_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (xsettings_manager);
+}
+
+static void
+mate_xsettings_manager_dispose (GObject *object)
+{
+ MateXSettingsManager *xsettings_manager;
+
+ xsettings_manager = MATE_XSETTINGS_MANAGER (object);
+
+ G_OBJECT_CLASS (mate_xsettings_manager_parent_class)->dispose (object);
+}
+
+static void
+mate_xsettings_manager_class_init (MateXSettingsManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = mate_xsettings_manager_get_property;
+ object_class->set_property = mate_xsettings_manager_set_property;
+ object_class->constructor = mate_xsettings_manager_constructor;
+ object_class->dispose = mate_xsettings_manager_dispose;
+ object_class->finalize = mate_xsettings_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (MateXSettingsManagerPrivate));
+}
+
+static void
+mate_xsettings_manager_init (MateXSettingsManager *manager)
+{
+ manager->priv = MATE_XSETTINGS_MANAGER_GET_PRIVATE (manager);
+}
+
+static void
+mate_xsettings_manager_finalize (GObject *object)
+{
+ MateXSettingsManager *xsettings_manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (MATE_IS_XSETTINGS_MANAGER (object));
+
+ xsettings_manager = MATE_XSETTINGS_MANAGER (object);
+
+ g_return_if_fail (xsettings_manager->priv != NULL);
+
+ G_OBJECT_CLASS (mate_xsettings_manager_parent_class)->finalize (object);
+}
+
+MateXSettingsManager *
+mate_xsettings_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ manager_object = g_object_new (MATE_TYPE_XSETTINGS_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ }
+
+ return MATE_XSETTINGS_MANAGER (manager_object);
+}
diff --git a/plugins/xsettings/gsd-xsettings-manager.h b/plugins/xsettings/gsd-xsettings-manager.h
new file mode 100644
index 0000000..b97afbf
--- /dev/null
+++ b/plugins/xsettings/gsd-xsettings-manager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __MATE_XSETTINGS_MANAGER_H
+#define __MATE_XSETTINGS_MANAGER_H
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MATE_TYPE_XSETTINGS_MANAGER (mate_xsettings_manager_get_type ())
+#define MATE_XSETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_TYPE_XSETTINGS_MANAGER, MateXSettingsManager))
+#define MATE_XSETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MATE_TYPE_XSETTINGS_MANAGER, MateXSettingsManagerClass))
+#define MATE_IS_XSETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_TYPE_XSETTINGS_MANAGER))
+#define MATE_IS_XSETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MATE_TYPE_XSETTINGS_MANAGER))
+#define MATE_XSETTINGS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_TYPE_XSETTINGS_MANAGER, MateXSettingsManagerClass))
+
+typedef struct MateXSettingsManagerPrivate MateXSettingsManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ MateXSettingsManagerPrivate *priv;
+} MateXSettingsManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} MateXSettingsManagerClass;
+
+GType mate_xsettings_manager_get_type (void);
+
+MateXSettingsManager * mate_xsettings_manager_new (void);
+gboolean mate_xsettings_manager_start (MateXSettingsManager *manager,
+ GError **error);
+void mate_xsettings_manager_stop (MateXSettingsManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_XSETTINGS_MANAGER_H */
diff --git a/plugins/xsettings/gsd-xsettings-plugin.c b/plugins/xsettings/gsd-xsettings-plugin.c
new file mode 100644
index 0000000..2280589
--- /dev/null
+++ b/plugins/xsettings/gsd-xsettings-plugin.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+#include "gsd-xsettings-plugin.h"
+#include "gsd-xsettings-manager.h"
+
+struct MateXSettingsPluginPrivate {
+ MateXSettingsManager *manager;
+};
+
+#define MATE_XSETTINGS_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), MATE_TYPE_XSETTINGS_PLUGIN, MateXSettingsPluginPrivate))
+
+MATE_SETTINGS_PLUGIN_REGISTER (MateXSettingsPlugin, mate_xsettings_plugin)
+
+static void
+mate_xsettings_plugin_init (MateXSettingsPlugin *plugin)
+{
+ plugin->priv = MATE_XSETTINGS_PLUGIN_GET_PRIVATE (plugin);
+
+ g_debug ("MateXSettingsPlugin initializing");
+
+ plugin->priv->manager = mate_xsettings_manager_new ();
+}
+
+static void
+mate_xsettings_plugin_finalize (GObject *object)
+{
+ MateXSettingsPlugin *plugin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (MATE_IS_XSETTINGS_PLUGIN (object));
+
+ g_debug ("MateXSettingsPlugin finalizing");
+
+ plugin = MATE_XSETTINGS_PLUGIN (object);
+
+ g_return_if_fail (plugin->priv != NULL);
+
+ if (plugin->priv->manager != NULL) {
+ g_object_unref (plugin->priv->manager);
+ }
+
+ G_OBJECT_CLASS (mate_xsettings_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (MateSettingsPlugin *plugin)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("Activating xsettings plugin");
+
+ error = NULL;
+ res = mate_xsettings_manager_start (MATE_XSETTINGS_PLUGIN (plugin)->priv->manager, &error);
+ if (! res) {
+ g_warning ("Unable to start xsettings manager: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+impl_deactivate (MateSettingsPlugin *plugin)
+{
+ g_debug ("Deactivating xsettings plugin");
+ mate_xsettings_manager_stop (MATE_XSETTINGS_PLUGIN (plugin)->priv->manager);
+}
+
+static void
+mate_xsettings_plugin_class_init (MateXSettingsPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = mate_xsettings_plugin_finalize;
+
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+
+ g_type_class_add_private (klass, sizeof (MateXSettingsPluginPrivate));
+}
diff --git a/plugins/xsettings/gsd-xsettings-plugin.h b/plugins/xsettings/gsd-xsettings-plugin.h
new file mode 100644
index 0000000..88c8331
--- /dev/null
+++ b/plugins/xsettings/gsd-xsettings-plugin.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __MATE_XSETTINGS_PLUGIN_H__
+#define __MATE_XSETTINGS_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include "mate-settings-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MATE_TYPE_XSETTINGS_PLUGIN (mate_xsettings_plugin_get_type ())
+#define MATE_XSETTINGS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_TYPE_XSETTINGS_PLUGIN, MateXSettingsPlugin))
+#define MATE_XSETTINGS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MATE_TYPE_XSETTINGS_PLUGIN, MateXSettingsPluginClass))
+#define MATE_IS_XSETTINGS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_TYPE_XSETTINGS_PLUGIN))
+#define MATE_IS_XSETTINGS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MATE_TYPE_XSETTINGS_PLUGIN))
+#define MATE_XSETTINGS_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_TYPE_XSETTINGS_PLUGIN, MateXSettingsPluginClass))
+
+typedef struct MateXSettingsPluginPrivate MateXSettingsPluginPrivate;
+
+typedef struct
+{
+ MateSettingsPlugin parent;
+ MateXSettingsPluginPrivate *priv;
+} MateXSettingsPlugin;
+
+typedef struct
+{
+ MateSettingsPluginClass parent_class;
+} MateXSettingsPluginClass;
+
+GType mate_xsettings_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_XSETTINGS_PLUGIN_H__ */
diff --git a/plugins/xsettings/xsettings-common.c b/plugins/xsettings/xsettings-common.c
new file mode 100644
index 0000000..992175a
--- /dev/null
+++ b/plugins/xsettings/xsettings-common.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include "string.h"
+#include "stdlib.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h> /* For CARD32 */
+
+#include "xsettings-common.h"
+
+XSettingsSetting *
+xsettings_setting_copy (XSettingsSetting *setting)
+{
+ XSettingsSetting *result;
+ size_t str_len;
+
+ result = malloc (sizeof *result);
+ if (!result)
+ return NULL;
+
+ str_len = strlen (setting->name);
+ result->name = malloc (str_len + 1);
+ if (!result->name)
+ goto err;
+
+ memcpy (result->name, setting->name, str_len + 1);
+
+ result->type = setting->type;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ result->data.v_int = setting->data.v_int;
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ result->data.v_color = setting->data.v_color;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ str_len = strlen (setting->data.v_string);
+ result->data.v_string = malloc (str_len + 1);
+ if (!result->data.v_string)
+ goto err;
+
+ memcpy (result->data.v_string, setting->data.v_string, str_len + 1);
+ break;
+ }
+
+ result->last_change_serial = setting->last_change_serial;
+
+ return result;
+
+ err:
+ if (result->name)
+ free (result->name);
+ free (result);
+
+ return NULL;
+}
+
+XSettingsList *
+xsettings_list_copy (XSettingsList *list)
+{
+ XSettingsList *new = NULL;
+ XSettingsList *old_iter = list;
+ XSettingsList *new_iter = NULL;
+
+ while (old_iter)
+ {
+ XSettingsList *new_node;
+
+ new_node = malloc (sizeof *new_node);
+ if (!new_node)
+ goto error;
+
+ new_node->setting = xsettings_setting_copy (old_iter->setting);
+ if (!new_node->setting)
+ {
+ free (new_node);
+ goto error;
+ }
+
+ if (new_iter)
+ new_iter->next = new_node;
+ else
+ new = new_node;
+
+ new_iter = new_node;
+
+ old_iter = old_iter->next;
+ }
+
+ return new;
+
+ error:
+ xsettings_list_free (new);
+ return NULL;
+}
+
+int
+xsettings_setting_equal (XSettingsSetting *setting_a,
+ XSettingsSetting *setting_b)
+{
+ if (setting_a->type != setting_b->type)
+ return 0;
+
+ if (strcmp (setting_a->name, setting_b->name) != 0)
+ return 0;
+
+ switch (setting_a->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ return setting_a->data.v_int == setting_b->data.v_int;
+ case XSETTINGS_TYPE_COLOR:
+ return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
+ setting_a->data.v_color.green == setting_b->data.v_color.green &&
+ setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
+ setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
+ case XSETTINGS_TYPE_STRING:
+ return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0;
+ }
+
+ return 0;
+}
+
+void
+xsettings_setting_free (XSettingsSetting *setting)
+{
+ if (setting->type == XSETTINGS_TYPE_STRING)
+ free (setting->data.v_string);
+
+ if (setting->name)
+ free (setting->name);
+
+ free (setting);
+}
+
+void
+xsettings_list_free (XSettingsList *list)
+{
+ while (list)
+ {
+ XSettingsList *next = list->next;
+
+ xsettings_setting_free (list->setting);
+ free (list);
+
+ list = next;
+ }
+}
+
+XSettingsResult
+xsettings_list_insert (XSettingsList **list,
+ XSettingsSetting *setting)
+{
+ XSettingsList *node;
+ XSettingsList *iter;
+ XSettingsList *last = NULL;
+
+ node = malloc (sizeof *node);
+ if (!node)
+ return XSETTINGS_NO_MEM;
+ node->setting = setting;
+
+ iter = *list;
+ while (iter)
+ {
+ int cmp = strcmp (setting->name, iter->setting->name);
+
+ if (cmp < 0)
+ break;
+ else if (cmp == 0)
+ {
+ free (node);
+ return XSETTINGS_DUPLICATE_ENTRY;
+ }
+
+ last = iter;
+ iter = iter->next;
+ }
+
+ if (last)
+ last->next = node;
+ else
+ *list = node;
+
+ node->next = iter;
+
+ return XSETTINGS_SUCCESS;
+}
+
+XSettingsResult
+xsettings_list_delete (XSettingsList **list,
+ const char *name)
+{
+ XSettingsList *iter;
+ XSettingsList *last = NULL;
+
+ iter = *list;
+ while (iter)
+ {
+ if (strcmp (name, iter->setting->name) == 0)
+ {
+ if (last)
+ last->next = iter->next;
+ else
+ *list = iter->next;
+
+ xsettings_setting_free (iter->setting);
+ free (iter);
+
+ return XSETTINGS_SUCCESS;
+ }
+
+ last = iter;
+ iter = iter->next;
+ }
+
+ return XSETTINGS_FAILED;
+}
+
+XSettingsSetting *
+xsettings_list_lookup (XSettingsList *list,
+ const char *name)
+{
+ XSettingsList *iter;
+
+ iter = list;
+ while (iter)
+ {
+ if (strcmp (name, iter->setting->name) == 0)
+ return iter->setting;
+
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+char
+xsettings_byte_order (void)
+{
+ CARD32 myint = 0x01020304;
+ return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
+}
diff --git a/plugins/xsettings/xsettings-common.h b/plugins/xsettings/xsettings-common.h
new file mode 100644
index 0000000..e3af4a6
--- /dev/null
+++ b/plugins/xsettings/xsettings-common.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef XSETTINGS_COMMON_H
+#define XSETTINGS_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _XSettingsBuffer XSettingsBuffer;
+typedef struct _XSettingsColor XSettingsColor;
+typedef struct _XSettingsList XSettingsList;
+typedef struct _XSettingsSetting XSettingsSetting;
+
+/* Types of settings possible. Enum values correspond to
+ * protocol values.
+ */
+typedef enum
+{
+ XSETTINGS_TYPE_INT = 0,
+ XSETTINGS_TYPE_STRING = 1,
+ XSETTINGS_TYPE_COLOR = 2
+} XSettingsType;
+
+typedef enum
+{
+ XSETTINGS_SUCCESS,
+ XSETTINGS_NO_MEM,
+ XSETTINGS_ACCESS,
+ XSETTINGS_FAILED,
+ XSETTINGS_NO_ENTRY,
+ XSETTINGS_DUPLICATE_ENTRY
+} XSettingsResult;
+
+struct _XSettingsBuffer
+{
+ char byte_order;
+ size_t len;
+ unsigned char *data;
+ unsigned char *pos;
+};
+
+struct _XSettingsColor
+{
+ unsigned short red, green, blue, alpha;
+};
+
+struct _XSettingsList
+{
+ XSettingsSetting *setting;
+ XSettingsList *next;
+};
+
+struct _XSettingsSetting
+{
+ char *name;
+ XSettingsType type;
+
+ union {
+ int v_int;
+ char *v_string;
+ XSettingsColor v_color;
+ } data;
+
+ unsigned long last_change_serial;
+};
+
+XSettingsSetting *xsettings_setting_copy (XSettingsSetting *setting);
+void xsettings_setting_free (XSettingsSetting *setting);
+int xsettings_setting_equal (XSettingsSetting *setting_a,
+ XSettingsSetting *setting_b);
+
+void xsettings_list_free (XSettingsList *list);
+XSettingsList *xsettings_list_copy (XSettingsList *list);
+XSettingsResult xsettings_list_insert (XSettingsList **list,
+ XSettingsSetting *setting);
+XSettingsSetting *xsettings_list_lookup (XSettingsList *list,
+ const char *name);
+XSettingsResult xsettings_list_delete (XSettingsList **list,
+ const char *name);
+
+char xsettings_byte_order (void);
+
+#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XSETTINGS_COMMON_H */
diff --git a/plugins/xsettings/xsettings-manager.c b/plugins/xsettings/xsettings-manager.c
new file mode 100644
index 0000000..6578ce1
--- /dev/null
+++ b/plugins/xsettings/xsettings-manager.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xmd.h> /* For CARD16 */
+
+#include "xsettings-manager.h"
+
+struct _XSettingsManager
+{
+ Display *display;
+ int screen;
+
+ Window window;
+ Atom manager_atom;
+ Atom selection_atom;
+ Atom xsettings_atom;
+
+ XSettingsTerminateFunc terminate;
+ void *cb_data;
+
+ XSettingsList *settings;
+ unsigned long serial;
+};
+
+static XSettingsList *settings;
+
+typedef struct
+{
+ Window window;
+ Atom timestamp_prop_atom;
+} TimeStampInfo;
+
+static Bool
+timestamp_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ TimeStampInfo *info = (TimeStampInfo *)arg;
+
+ if (xevent->type == PropertyNotify &&
+ xevent->xproperty.window == info->window &&
+ xevent->xproperty.atom == info->timestamp_prop_atom)
+ return True;
+
+ return False;
+}
+
+/**
+ * get_server_time:
+ * @display: display from which to get the time
+ * @window: a #Window, used for communication with the server.
+ * The window must have PropertyChangeMask in its
+ * events mask or a hang will result.
+ *
+ * Routine to get the current X server time stamp.
+ *
+ * Return value: the time stamp.
+ **/
+static Time
+get_server_time (Display *display,
+ Window window)
+{
+ unsigned char c = 'a';
+ XEvent xevent;
+ TimeStampInfo info;
+
+ info.timestamp_prop_atom = XInternAtom (display, "_TIMESTAMP_PROP", False);
+ info.window = window;
+
+ XChangeProperty (display, window,
+ info.timestamp_prop_atom, info.timestamp_prop_atom,
+ 8, PropModeReplace, &c, 1);
+
+ XIfEvent (display, &xevent,
+ timestamp_predicate, (XPointer)&info);
+
+ return xevent.xproperty.time;
+}
+
+Bool
+xsettings_manager_check_running (Display *display,
+ int screen)
+{
+ char buffer[256];
+ Atom selection_atom;
+
+ sprintf(buffer, "_XSETTINGS_S%d", screen);
+ selection_atom = XInternAtom (display, buffer, False);
+
+ if (XGetSelectionOwner (display, selection_atom))
+ return True;
+ else
+ return False;
+}
+
+XSettingsManager *
+xsettings_manager_new (Display *display,
+ int screen,
+ XSettingsTerminateFunc terminate,
+ void *cb_data)
+{
+ XSettingsManager *manager;
+ Time timestamp;
+ XClientMessageEvent xev;
+
+ char buffer[256];
+
+ manager = malloc (sizeof *manager);
+ if (!manager)
+ return NULL;
+
+ manager->display = display;
+ manager->screen = screen;
+
+ sprintf(buffer, "_XSETTINGS_S%d", screen);
+ manager->selection_atom = XInternAtom (display, buffer, False);
+ manager->xsettings_atom = XInternAtom (display, "_XSETTINGS_SETTINGS", False);
+ manager->manager_atom = XInternAtom (display, "MANAGER", False);
+
+ manager->terminate = terminate;
+ manager->cb_data = cb_data;
+
+ manager->settings = NULL;
+ manager->serial = 0;
+
+ manager->window = XCreateSimpleWindow (display,
+ RootWindow (display, screen),
+ 0, 0, 10, 10, 0,
+ WhitePixel (display, screen),
+ WhitePixel (display, screen));
+
+ XSelectInput (display, manager->window, PropertyChangeMask);
+ timestamp = get_server_time (display, manager->window);
+
+ XSetSelectionOwner (display, manager->selection_atom,
+ manager->window, timestamp);
+
+ /* Check to see if we managed to claim the selection. If not,
+ * we treat it as if we got it then immediately lost it
+ */
+
+ if (XGetSelectionOwner (display, manager->selection_atom) ==
+ manager->window)
+ {
+ xev.type = ClientMessage;
+ xev.window = RootWindow (display, screen);
+ xev.message_type = manager->manager_atom;
+ xev.format = 32;
+ xev.data.l[0] = timestamp;
+ xev.data.l[1] = manager->selection_atom;
+ xev.data.l[2] = manager->window;
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (display, RootWindow (display, screen),
+ False, StructureNotifyMask, (XEvent *)&xev);
+ }
+ else
+ {
+ manager->terminate (manager->cb_data);
+ }
+
+ return manager;
+}
+
+void
+xsettings_manager_destroy (XSettingsManager *manager)
+{
+ XDestroyWindow (manager->display, manager->window);
+
+ xsettings_list_free (manager->settings);
+ free (manager);
+}
+
+Window
+xsettings_manager_get_window (XSettingsManager *manager)
+{
+ return manager->window;
+}
+
+Bool
+xsettings_manager_process_event (XSettingsManager *manager,
+ XEvent *xev)
+{
+ if (xev->xany.window == manager->window &&
+ xev->xany.type == SelectionClear &&
+ xev->xselectionclear.selection == manager->selection_atom)
+ {
+ manager->terminate (manager->cb_data);
+ return True;
+ }
+
+ return False;
+}
+
+XSettingsResult
+xsettings_manager_delete_setting (XSettingsManager *manager,
+ const char *name)
+{
+ return xsettings_list_delete (&settings, name);
+}
+
+XSettingsResult
+xsettings_manager_set_setting (XSettingsManager *manager,
+ XSettingsSetting *setting)
+{
+ XSettingsSetting *old_setting = xsettings_list_lookup (settings, setting->name);
+ XSettingsSetting *new_setting;
+ XSettingsResult result;
+
+ if (old_setting)
+ {
+ if (xsettings_setting_equal (old_setting, setting))
+ return XSETTINGS_SUCCESS;
+
+ xsettings_list_delete (&settings, setting->name);
+ }
+
+ new_setting = xsettings_setting_copy (setting);
+ if (!new_setting)
+ return XSETTINGS_NO_MEM;
+
+ new_setting->last_change_serial = manager->serial;
+
+ result = xsettings_list_insert (&settings, new_setting);
+
+ if (result != XSETTINGS_SUCCESS)
+ xsettings_setting_free (new_setting);
+
+ return result;
+}
+
+XSettingsResult
+xsettings_manager_set_int (XSettingsManager *manager,
+ const char *name,
+ int value)
+{
+ XSettingsSetting setting;
+
+ setting.name = (char *)name;
+ setting.type = XSETTINGS_TYPE_INT;
+ setting.data.v_int = value;
+
+ return xsettings_manager_set_setting (manager, &setting);
+}
+
+XSettingsResult
+xsettings_manager_set_string (XSettingsManager *manager,
+ const char *name,
+ const char *value)
+{
+ XSettingsSetting setting;
+
+ setting.name = (char *)name;
+ setting.type = XSETTINGS_TYPE_STRING;
+ setting.data.v_string = (char *)value;
+
+ return xsettings_manager_set_setting (manager, &setting);
+}
+
+XSettingsResult
+xsettings_manager_set_color (XSettingsManager *manager,
+ const char *name,
+ XSettingsColor *value)
+{
+ XSettingsSetting setting;
+
+ setting.name = (char *)name;
+ setting.type = XSETTINGS_TYPE_COLOR;
+ setting.data.v_color = *value;
+
+ return xsettings_manager_set_setting (manager, &setting);
+}
+
+static size_t
+setting_length (XSettingsSetting *setting)
+{
+ size_t length = 8; /* type + pad + name-len + last-change-serial */
+ length += XSETTINGS_PAD (strlen (setting->name), 4);
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ length += 4;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ length += 4 + XSETTINGS_PAD (strlen (setting->data.v_string), 4);
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ length += 8;
+ break;
+ }
+
+ return length;
+}
+
+static void
+setting_store (XSettingsSetting *setting,
+ XSettingsBuffer *buffer)
+{
+ size_t string_len;
+ size_t length;
+
+ *(buffer->pos++) = setting->type;
+ *(buffer->pos++) = 0;
+
+ string_len = strlen (setting->name);
+ *(CARD16 *)(buffer->pos) = string_len;
+ buffer->pos += 2;
+
+ length = XSETTINGS_PAD (string_len, 4);
+ memcpy (buffer->pos, setting->name, string_len);
+ length -= string_len;
+ buffer->pos += string_len;
+
+ while (length > 0)
+ {
+ *(buffer->pos++) = 0;
+ length--;
+ }
+
+ *(CARD32 *)(buffer->pos) = setting->last_change_serial;
+ buffer->pos += 4;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ *(CARD32 *)(buffer->pos) = setting->data.v_int;
+ buffer->pos += 4;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ string_len = strlen (setting->data.v_string);
+ *(CARD32 *)(buffer->pos) = string_len;
+ buffer->pos += 4;
+
+ length = XSETTINGS_PAD (string_len, 4);
+ memcpy (buffer->pos, setting->data.v_string, string_len);
+ length -= string_len;
+ buffer->pos += string_len;
+
+ while (length > 0)
+ {
+ *(buffer->pos++) = 0;
+ length--;
+ }
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ *(CARD16 *)(buffer->pos) = setting->data.v_color.red;
+ *(CARD16 *)(buffer->pos + 2) = setting->data.v_color.green;
+ *(CARD16 *)(buffer->pos + 4) = setting->data.v_color.blue;
+ *(CARD16 *)(buffer->pos + 6) = setting->data.v_color.alpha;
+ buffer->pos += 8;
+ break;
+ }
+}
+
+XSettingsResult
+xsettings_manager_notify (XSettingsManager *manager)
+{
+ XSettingsBuffer buffer;
+ XSettingsList *iter;
+ int n_settings = 0;
+
+ buffer.len = 12; /* byte-order + pad + SERIAL + N_SETTINGS */
+
+ iter = settings;
+ while (iter)
+ {
+ buffer.len += setting_length (iter->setting);
+ n_settings++;
+ iter = iter->next;
+ }
+
+ buffer.data = buffer.pos = malloc (buffer.len);
+ if (!buffer.data)
+ return XSETTINGS_NO_MEM;
+
+ *buffer.pos = xsettings_byte_order ();
+
+ buffer.pos += 4;
+ *(CARD32 *)buffer.pos = manager->serial++;
+ buffer.pos += 4;
+ *(CARD32 *)buffer.pos = n_settings;
+ buffer.pos += 4;
+
+ iter = settings;
+ while (iter)
+ {
+ setting_store (iter->setting, &buffer);
+ iter = iter->next;
+ }
+
+ XChangeProperty (manager->display, manager->window,
+ manager->xsettings_atom, manager->xsettings_atom,
+ 8, PropModeReplace, buffer.data, buffer.len);
+
+ free (buffer.data);
+
+ return XSETTINGS_SUCCESS;
+}
+
diff --git a/plugins/xsettings/xsettings-manager.h b/plugins/xsettings/xsettings-manager.h
new file mode 100644
index 0000000..f309768
--- /dev/null
+++ b/plugins/xsettings/xsettings-manager.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef XSETTINGS_MANAGER_H
+#define XSETTINGS_MANAGER_H
+
+#include <X11/Xlib.h>
+#include "xsettings-common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _XSettingsManager XSettingsManager;
+
+typedef void (*XSettingsTerminateFunc) (void *cb_data);
+
+Bool xsettings_manager_check_running (Display *display,
+ int screen);
+
+XSettingsManager *xsettings_manager_new (Display *display,
+ int screen,
+ XSettingsTerminateFunc terminate,
+ void *cb_data);
+
+void xsettings_manager_destroy (XSettingsManager *manager);
+Window xsettings_manager_get_window (XSettingsManager *manager);
+Bool xsettings_manager_process_event (XSettingsManager *manager,
+ XEvent *xev);
+
+XSettingsResult xsettings_manager_delete_setting (XSettingsManager *manager,
+ const char *name);
+XSettingsResult xsettings_manager_set_setting (XSettingsManager *manager,
+ XSettingsSetting *setting);
+XSettingsResult xsettings_manager_set_int (XSettingsManager *manager,
+ const char *name,
+ int value);
+XSettingsResult xsettings_manager_set_string (XSettingsManager *manager,
+ const char *name,
+ const char *value);
+XSettingsResult xsettings_manager_set_color (XSettingsManager *manager,
+ const char *name,
+ XSettingsColor *value);
+XSettingsResult xsettings_manager_notify (XSettingsManager *manager);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XSETTINGS_MANAGER_H */
diff --git a/plugins/xsettings/xsettings.mate-settings-plugin.in b/plugins/xsettings/xsettings.mate-settings-plugin.in
new file mode 100644
index 0000000..6747dc1
--- /dev/null
+++ b/plugins/xsettings/xsettings.mate-settings-plugin.in
@@ -0,0 +1,8 @@
+[MATE Settings Plugin]
+Module=xsettings
+IAge=0
+_Name=X Settings
+_Description=Manage X Settings
+Authors=William Jon McCann
+Copyright=Copyright © 2007 William Jon McCann
+Website=