summaryrefslogtreecommitdiff
path: root/mate-panel
diff options
context:
space:
mode:
Diffstat (limited to 'mate-panel')
-rw-r--r--mate-panel/Makefile.am290
-rw-r--r--mate-panel/Makefile.in2222
-rw-r--r--mate-panel/applet.c1449
-rw-r--r--mate-panel/applet.h119
-rw-r--r--mate-panel/button-widget.c902
-rw-r--r--mate-panel/button-widget.h60
-rw-r--r--mate-panel/drawer.c806
-rw-r--r--mate-panel/drawer.h52
-rw-r--r--mate-panel/launcher.c1114
-rw-r--r--mate-panel/launcher.h80
-rw-r--r--mate-panel/libegg/Makefile.am25
-rw-r--r--mate-panel/libegg/Makefile.in622
-rw-r--r--mate-panel/libegg/eggdesktopfile.c1510
-rw-r--r--mate-panel/libegg/eggdesktopfile.h164
-rw-r--r--mate-panel/libegg/eggsmclient-private.h57
-rw-r--r--mate-panel/libegg/eggsmclient-xsmp.c1370
-rw-r--r--mate-panel/libegg/eggsmclient.c604
-rw-r--r--mate-panel/libegg/eggsmclient.h121
-rw-r--r--mate-panel/libmate-panel-applet-private/Makefile.am34
-rw-r--r--mate-panel/libmate-panel-applet-private/Makefile.in644
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applet-container.c790
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applet-container.h118
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.c468
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.h65
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applet-mini.c5
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.c604
-rw-r--r--mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.h60
-rw-r--r--mate-panel/libpanel-util/Makefile.am39
-rw-r--r--mate-panel/libpanel-util/Makefile.in647
-rw-r--r--mate-panel/libpanel-util/panel-cleanup.c110
-rw-r--r--mate-panel/libpanel-util/panel-cleanup.h51
-rw-r--r--mate-panel/libpanel-util/panel-dbus-service.c307
-rw-r--r--mate-panel/libpanel-util/panel-dbus-service.h78
-rw-r--r--mate-panel/libpanel-util/panel-error.c96
-rw-r--r--mate-panel/libpanel-util/panel-error.h49
-rw-r--r--mate-panel/libpanel-util/panel-glib.c164
-rw-r--r--mate-panel/libpanel-util/panel-glib.h46
-rw-r--r--mate-panel/libpanel-util/panel-gtk.c83
-rw-r--r--mate-panel/libpanel-util/panel-gtk.h42
-rw-r--r--mate-panel/libpanel-util/panel-icon-chooser.c555
-rw-r--r--mate-panel/libpanel-util/panel-icon-chooser.h79
-rw-r--r--mate-panel/libpanel-util/panel-keyfile.c363
-rw-r--r--mate-panel/libpanel-util/panel-keyfile.h79
-rw-r--r--mate-panel/libpanel-util/panel-launch.c234
-rw-r--r--mate-panel/libpanel-util/panel-launch.h65
-rw-r--r--mate-panel/libpanel-util/panel-list.c212
-rw-r--r--mate-panel/libpanel-util/panel-list.h56
-rw-r--r--mate-panel/libpanel-util/panel-session-manager.c192
-rw-r--r--mate-panel/libpanel-util/panel-session-manager.h75
-rw-r--r--mate-panel/libpanel-util/panel-show.c283
-rw-r--r--mate-panel/libpanel-util/panel-show.h54
-rw-r--r--mate-panel/libpanel-util/panel-xdg.c152
-rw-r--r--mate-panel/libpanel-util/panel-xdg.h43
-rw-r--r--mate-panel/main.c153
-rw-r--r--mate-panel/mate-desktop-item-edit.c225
-rw-r--r--mate-panel/mate-panel-add.in325
-rw-r--r--mate-panel/mate-panel-applet-frame.c1002
-rw-r--r--mate-panel/mate-panel-applet-frame.h146
-rw-r--r--mate-panel/mate-panel-applet-info.c113
-rw-r--r--mate-panel/mate-panel-applet-info.h51
-rw-r--r--mate-panel/mate-panel-applets-manager.c201
-rw-r--r--mate-panel/mate-panel-applets-manager.h94
-rw-r--r--mate-panel/mate-panel.desktop.in.in19
-rw-r--r--mate-panel/mate-panelrc4
-rw-r--r--mate-panel/menu.c1914
-rw-r--r--mate-panel/menu.h80
-rw-r--r--mate-panel/nothing.cP1568
-rw-r--r--mate-panel/nothing.h22
-rw-r--r--mate-panel/panel-a11y.c135
-rw-r--r--mate-panel/panel-a11y.h43
-rw-r--r--mate-panel/panel-action-button.c907
-rw-r--r--mate-panel/panel-action-button.h103
-rw-r--r--mate-panel/panel-action-protocol.c158
-rw-r--r--mate-panel/panel-action-protocol.h40
-rw-r--r--mate-panel/panel-addto.c1428
-rw-r--r--mate-panel/panel-addto.h39
-rw-r--r--mate-panel/panel-background-monitor.c440
-rw-r--r--mate-panel/panel-background-monitor.h60
-rw-r--r--mate-panel/panel-background.c1156
-rw-r--r--mate-panel/panel-background.h133
-rw-r--r--mate-panel/panel-bindings.c303
-rw-r--r--mate-panel/panel-bindings.h42
-rw-r--r--mate-panel/panel-compatibility.c1167
-rw-r--r--mate-panel/panel-compatibility.h48
-rw-r--r--mate-panel/panel-compatibility.schemas546
-rw-r--r--mate-panel/panel-config-global.c153
-rw-r--r--mate-panel/panel-config-global.h47
-rw-r--r--mate-panel/panel-context-menu.c307
-rw-r--r--mate-panel/panel-context-menu.h33
-rw-r--r--mate-panel/panel-default-setup.entries657
-rw-r--r--mate-panel/panel-ditem-editor.c1804
-rw-r--r--mate-panel/panel-ditem-editor.h115
-rw-r--r--mate-panel/panel-enums.h110
-rw-r--r--mate-panel/panel-force-quit.c316
-rw-r--r--mate-panel/panel-force-quit.h41
-rw-r--r--mate-panel/panel-frame.c328
-rw-r--r--mate-panel/panel-frame.h69
-rw-r--r--mate-panel/panel-general.schemas.in127
-rw-r--r--mate-panel/panel-global.schemas.in276
-rw-r--r--mate-panel/panel-globals.h41
-rw-r--r--mate-panel/panel-icon-names.h40
-rw-r--r--mate-panel/panel-lockdown.c442
-rw-r--r--mate-panel/panel-lockdown.h55
-rw-r--r--mate-panel/panel-marshal.list3
-rw-r--r--mate-panel/panel-mateconf.c351
-rw-r--r--mate-panel/panel-mateconf.h76
-rw-r--r--mate-panel/panel-menu-bar.c474
-rw-r--r--mate-panel/panel-menu-bar.h83
-rw-r--r--mate-panel/panel-menu-button.c1194
-rw-r--r--mate-panel/panel-menu-button.h98
-rw-r--r--mate-panel/panel-menu-items.c1618
-rw-r--r--mate-panel/panel-menu-items.h99
-rw-r--r--mate-panel/panel-modules.c86
-rw-r--r--mate-panel/panel-modules.h30
-rw-r--r--mate-panel/panel-multiscreen.c784
-rw-r--r--mate-panel/panel-multiscreen.h58
-rw-r--r--mate-panel/panel-object.schemas.in247
-rw-r--r--mate-panel/panel-profile.c2647
-rw-r--r--mate-panel/panel-profile.h188
-rw-r--r--mate-panel/panel-properties-dialog.c999
-rw-r--r--mate-panel/panel-properties-dialog.h40
-rw-r--r--mate-panel/panel-properties-dialog.ui769
-rw-r--r--mate-panel/panel-recent.c243
-rw-r--r--mate-panel/panel-recent.h41
-rw-r--r--mate-panel/panel-reset.c46
-rw-r--r--mate-panel/panel-reset.h37
-rw-r--r--mate-panel/panel-run-dialog.c2041
-rw-r--r--mate-panel/panel-run-dialog.h41
-rw-r--r--mate-panel/panel-run-dialog.ui270
-rw-r--r--mate-panel/panel-separator.c250
-rw-r--r--mate-panel/panel-separator.h71
-rw-r--r--mate-panel/panel-session.c80
-rw-r--r--mate-panel/panel-session.h39
-rw-r--r--mate-panel/panel-shell.c164
-rw-r--r--mate-panel/panel-shell.h37
-rw-r--r--mate-panel/panel-stock-icons.c141
-rw-r--r--mate-panel/panel-stock-icons.h60
-rw-r--r--mate-panel/panel-struts.c516
-rw-r--r--mate-panel/panel-struts.h56
-rw-r--r--mate-panel/panel-test-applets.c388
-rw-r--r--mate-panel/panel-test-applets.ui203
-rw-r--r--mate-panel/panel-toplevel.c5298
-rw-r--r--mate-panel/panel-toplevel.h179
-rw-r--r--mate-panel/panel-toplevel.schemas.in434
-rw-r--r--mate-panel/panel-types.h19
-rw-r--r--mate-panel/panel-util.c1210
-rw-r--r--mate-panel/panel-util.h72
-rw-r--r--mate-panel/panel-widget.c3010
-rw-r--r--mate-panel/panel-widget.h242
-rw-r--r--mate-panel/panel-xutils.c258
-rw-r--r--mate-panel/panel-xutils.h64
-rw-r--r--mate-panel/panel.c1403
-rw-r--r--mate-panel/panel.h57
-rw-r--r--mate-panel/xstuff.c736
-rw-r--r--mate-panel/xstuff.h39
155 files changed, 63724 insertions, 0 deletions
diff --git a/mate-panel/Makefile.am b/mate-panel/Makefile.am
new file mode 100644
index 00000000..e72925ad
--- /dev/null
+++ b/mate-panel/Makefile.am
@@ -0,0 +1,290 @@
+SUBDIRS = libegg libmate-panel-applet-private libpanel-util
+
+bin_PROGRAMS = \
+ mate-panel \
+ mate-desktop-item-edit \
+ mate-panel-test-applets
+libexec_SCRIPTS = mate-panel-add
+
+AM_CPPFLAGS = \
+ $(PANEL_CFLAGS) \
+ -I. \
+ -I$(srcdir) \
+ -I$(top_builddir)/mate-panel \
+ -I$(top_builddir)/mate-panel/libpanel-util \
+ -DMATELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+ -DBUILDERDIR=\""$(uidir)"\" \
+ -DICONDIR=\""$(datadir)/mate-panel/pixmaps"\" \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+
+panel_sources = \
+ panel-typebuiltins.c \
+ panel-typebuiltins.h \
+ panel-marshal.c \
+ panel-marshal.h \
+ main.c \
+ panel-widget.c \
+ button-widget.c \
+ xstuff.c \
+ panel-session.c \
+ panel-compatibility.c \
+ panel.c \
+ applet.c \
+ drawer.c \
+ panel-config-global.c \
+ panel-util.c \
+ panel-mateconf.c \
+ panel-properties-dialog.c \
+ panel-run-dialog.c \
+ menu.c \
+ panel-context-menu.c \
+ launcher.c \
+ mate-panel-applet-frame.c \
+ mate-panel-applets-manager.c \
+ panel-shell.c \
+ panel-background.c \
+ panel-background-monitor.c \
+ panel-stock-icons.c \
+ panel-action-button.c \
+ panel-menu-bar.c \
+ panel-menu-button.c \
+ panel-menu-items.c \
+ panel-separator.c \
+ panel-recent.c \
+ panel-action-protocol.c \
+ panel-toplevel.c \
+ panel-struts.c \
+ panel-frame.c \
+ panel-xutils.c \
+ panel-multiscreen.c \
+ panel-a11y.c \
+ panel-bindings.c \
+ panel-profile.c \
+ panel-force-quit.c \
+ panel-lockdown.c \
+ panel-addto.c \
+ panel-ditem-editor.c \
+ panel-modules.c \
+ mate-panel-applet-info.c \
+ panel-reset.c
+
+panel_headers = \
+ panel-types.h \
+ panel-widget.h \
+ panel-globals.h \
+ button-widget.h \
+ xstuff.h \
+ panel-session.h \
+ panel-compatibility.h \
+ panel.h \
+ applet.h \
+ drawer.h \
+ panel-util.h \
+ panel-properties-dialog.h \
+ panel-config-global.h \
+ panel-mateconf.h \
+ panel-run-dialog.h \
+ menu.h \
+ panel-context-menu.h \
+ launcher.h \
+ mate-panel-applet-frame.h \
+ mate-panel-applets-manager.h \
+ panel-shell.h \
+ panel-background.h \
+ panel-background-monitor.h \
+ panel-stock-icons.h \
+ panel-action-button.h \
+ panel-menu-bar.h \
+ panel-menu-button.h \
+ panel-menu-items.h \
+ panel-separator.h \
+ panel-recent.h \
+ panel-action-protocol.h \
+ panel-toplevel.h \
+ panel-struts.h \
+ panel-frame.h \
+ panel-xutils.h \
+ panel-multiscreen.h \
+ panel-a11y.h \
+ panel-bindings.h \
+ panel-profile.h \
+ panel-enums.h \
+ panel-force-quit.h \
+ panel-lockdown.h \
+ panel-addto.h \
+ panel-ditem-editor.h \
+ panel-icon-names.h \
+ panel-modules.h \
+ mate-panel-applet-info.h \
+ panel-reset.h
+
+mate_panel_SOURCES = \
+ $(panel_sources) \
+ $(panel_headers)
+
+mate_panel_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(XRANDR_CFLAGS) \
+ -DPANEL_MODULES_DIR=\"$(modulesdir)\" \
+ -DMATEMENU_I_KNOW_THIS_IS_UNSTABLE
+
+mate_panel_LDADD = \
+ $(top_builddir)/mate-panel/libegg/libegg.la \
+ $(top_builddir)/mate-panel/libmate-panel-applet-private/libmate-panel-applet-private.la \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(PANEL_LIBS) \
+ $(XRANDR_LIBS) \
+ $(X_LIBS)
+
+mate_panel_LDFLAGS = -export-dynamic
+
+mate_desktop_item_edit_SOURCES = \
+ mate-desktop-item-edit.c \
+ panel-ditem-editor.c \
+ panel-marshal.c \
+ panel-util.c \
+ xstuff.c
+
+mate_desktop_item_edit_LDADD = \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(PANEL_LIBS)
+
+mate_panel_test_applets_SOURCES = \
+ panel-modules.c \
+ mate-panel-applet-info.c \
+ mate-panel-applets-manager.c \
+ panel-marshal.c \
+ panel-test-applets.c
+
+mate_panel_test_applets_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -DPANEL_MODULES_DIR=\"$(modulesdir)\" \
+ -DMATE_PANEL_APPLETS_DIR=\"$(appletsdir)\"
+
+mate_panel_test_applets_LDADD = \
+ $(top_builddir)/mate-panel/libmate-panel-applet-private/libmate-panel-applet-private-mini.la \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(PANEL_LIBS)
+
+mate_panel_test_applets_LDFLAGS = -export-dynamic
+
+mate-panel-add: mate-panel-add.in Makefile
+ $(AM_V_GEN)sed \
+ -e s!\@PYTHON\@!@PYTHON@! \
+ -e s!\@MATE_PANEL_APPLETS_DIR\@!$(appletsdir)! \
+ < $< > $@
+ $(AM_V_at)chmod a+x $@
+
+panel_enum_headers = \
+ $(top_srcdir)/mate-panel/panel-enums.h \
+ $(top_srcdir)/mate-panel/panel-types.h
+
+panel-marshal.h: panel-marshal.list $(GLIB_GENMARSHAL)
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --header --prefix=panel_marshal > $@
+
+panel-marshal.c: panel-marshal.list $(GLIB_GENMARSHAL)
+ $(AM_V_GEN)echo "#include \"panel-marshal.h\"" > $@ && \
+ $(GLIB_GENMARSHAL) $< --body --prefix=panel_marshal >> $@
+
+panel-typebuiltins.c: @REBUILD@ $(panel_enum_headers)
+ $(AM_V_GEN)glib-mkenums \
+ --fhead "#include <glib-object.h>\n" \
+ --fhead "#include \"panel-typebuiltins.h\"\n\n" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --fprod "\n#include \"@filename@\"\n" \
+ --vhead "static const GEnumValue _@enum_name@_values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n};\n\n" \
+ --vtail "GType\n@enum_name@_get_type (void)\n{\n" \
+ --vtail " static GType type = 0;\n\n" \
+ --vtail " if (!type)\n" \
+ --vtail " type = g_enum_register_static (\"@EnumName@\", _@enum_name@_values);\n\n" \
+ --vtail " return type;\n}\n\n" \
+ $(panel_enum_headers) > $@
+
+panel-typebuiltins.h: @REBUILD@ $(panel_enum_headers)
+ $(AM_V_GEN)glib-mkenums \
+ --fhead "#ifndef __PANEL_TYPEBUILTINS_H__\n" \
+ --fhead "#define __PANEL_TYPEBUILTINS_H__ 1\n\n" \
+ --fhead "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n" \
+ --ftail "#ifdef __cplusplus\n}\n#endif\n\n" \
+ --ftail "#endif /* __PANEL_TYPEBUILTINS_H__ */\n" \
+ --fprod "\n/* --- @filename@ --- */" \
+ --eprod "#define PANEL_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \
+ --eprod "GType @enum_name@_get_type (void);\n" \
+ $(panel_enum_headers) > $@
+
+BUILT_SOURCES = \
+ panel-typebuiltins.c \
+ panel-typebuiltins.h \
+ panel-marshal.c \
+ panel-marshal.h
+
+rcdir = $(datadir)
+rc_DATA = mate-panelrc
+
+uidir = $(datadir)/mate-panel/ui
+ui_DATA = \
+ panel-properties-dialog.ui \
+ panel-run-dialog.ui \
+ panel-test-applets.ui
+
+desktopdir = $(datadir)/applications
+desktop_in_files = mate-panel.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+@INTLTOOL_DESKTOP_RULE@
+
+entriesdir = $(MATECONF_SCHEMA_FILE_DIR)
+entries_DATA = panel-default-setup.entries
+
+schemasdir = $(MATECONF_SCHEMA_FILE_DIR)
+schemas_in_files = \
+ panel-global.schemas.in \
+ panel-general.schemas.in \
+ panel-toplevel.schemas.in \
+ panel-object.schemas.in
+schemas_DATA = panel-compatibility.schemas $(schemas_in_files:.schemas.in=.schemas)
+
+@INTLTOOL_SCHEMAS_RULE@
+
+if MATECONF_SCHEMAS_INSTALL
+install-data-local:
+ if test -z "$(DESTDIR)" ; then \
+ for p in $(schemas_DATA) ; do \
+ MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $(top_builddir)/mate-panel/$$p ; \
+ done ; \
+ $(MATECONFTOOL) --direct --config-source=$(MATECONF_SCHEMA_CONFIG_SOURCE) --load $(srcdir)/panel-default-setup.entries ; \
+ $(MATECONFTOOL) --direct --config-source=$(MATECONF_SCHEMA_CONFIG_SOURCE) --load $(srcdir)/panel-default-setup.entries /apps/panel ; \
+ fi
+uninstall-local:
+ for p in $(schema_DATA) ; do \
+ MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-uninstall-rule $(top_builddir)/applets/ngome-panel/$$p ; \
+ done
+endif
+
+EXTRA_DIST = \
+ $(ui_DATA) \
+ nothing.cP \
+ nothing.h \
+ $(schemas_in_files) \
+ panel-compatibility.schemas \
+ panel-marshal.list \
+ mate-panelrc \
+ $(entries_DATA) \
+ $(desktop_in_files) \
+ mate-panel-add.in
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(schemas_in_files:.schemas.in=.schemas) \
+ $(sys_DATA) \
+ $(desktop_DATA) \
+ mate-panel-add
+
+dist-hook:
+ cd $(distdir) ; rm -f $(CLEANFILES)
+
+-include $(top_srcdir)/git.mk
diff --git a/mate-panel/Makefile.in b/mate-panel/Makefile.in
new file mode 100644
index 00000000..1226b501
--- /dev/null
+++ b/mate-panel/Makefile.in
@@ -0,0 +1,2222 @@
+# 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@
+bin_PROGRAMS = mate-panel$(EXEEXT) mate-desktop-item-edit$(EXEEXT) \
+ mate-panel-test-applets$(EXEEXT)
+subdir = mate-panel
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/mate-panel.desktop.in.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/d-type.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/mate-doc-utils.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 = mate-panel.desktop.in
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \
+ "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(entriesdir)" \
+ "$(DESTDIR)$(rcdir)" "$(DESTDIR)$(schemasdir)" \
+ "$(DESTDIR)$(uidir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_mate_desktop_item_edit_OBJECTS = mate-desktop-item-edit.$(OBJEXT) \
+ panel-ditem-editor.$(OBJEXT) panel-marshal.$(OBJEXT) \
+ panel-util.$(OBJEXT) xstuff.$(OBJEXT)
+mate_desktop_item_edit_OBJECTS = $(am_mate_desktop_item_edit_OBJECTS)
+am__DEPENDENCIES_1 =
+mate_desktop_item_edit_DEPENDENCIES = \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+am__objects_1 = mate_panel-panel-typebuiltins.$(OBJEXT) \
+ mate_panel-panel-marshal.$(OBJEXT) mate_panel-main.$(OBJEXT) \
+ mate_panel-panel-widget.$(OBJEXT) \
+ mate_panel-button-widget.$(OBJEXT) mate_panel-xstuff.$(OBJEXT) \
+ mate_panel-panel-session.$(OBJEXT) \
+ mate_panel-panel-compatibility.$(OBJEXT) \
+ mate_panel-panel.$(OBJEXT) mate_panel-applet.$(OBJEXT) \
+ mate_panel-drawer.$(OBJEXT) \
+ mate_panel-panel-config-global.$(OBJEXT) \
+ mate_panel-panel-util.$(OBJEXT) \
+ mate_panel-panel-mateconf.$(OBJEXT) \
+ mate_panel-panel-properties-dialog.$(OBJEXT) \
+ mate_panel-panel-run-dialog.$(OBJEXT) \
+ mate_panel-menu.$(OBJEXT) \
+ mate_panel-panel-context-menu.$(OBJEXT) \
+ mate_panel-launcher.$(OBJEXT) \
+ mate_panel-mate-panel-applet-frame.$(OBJEXT) \
+ mate_panel-mate-panel-applets-manager.$(OBJEXT) \
+ mate_panel-panel-shell.$(OBJEXT) \
+ mate_panel-panel-background.$(OBJEXT) \
+ mate_panel-panel-background-monitor.$(OBJEXT) \
+ mate_panel-panel-stock-icons.$(OBJEXT) \
+ mate_panel-panel-action-button.$(OBJEXT) \
+ mate_panel-panel-menu-bar.$(OBJEXT) \
+ mate_panel-panel-menu-button.$(OBJEXT) \
+ mate_panel-panel-menu-items.$(OBJEXT) \
+ mate_panel-panel-separator.$(OBJEXT) \
+ mate_panel-panel-recent.$(OBJEXT) \
+ mate_panel-panel-action-protocol.$(OBJEXT) \
+ mate_panel-panel-toplevel.$(OBJEXT) \
+ mate_panel-panel-struts.$(OBJEXT) \
+ mate_panel-panel-frame.$(OBJEXT) \
+ mate_panel-panel-xutils.$(OBJEXT) \
+ mate_panel-panel-multiscreen.$(OBJEXT) \
+ mate_panel-panel-a11y.$(OBJEXT) \
+ mate_panel-panel-bindings.$(OBJEXT) \
+ mate_panel-panel-profile.$(OBJEXT) \
+ mate_panel-panel-force-quit.$(OBJEXT) \
+ mate_panel-panel-lockdown.$(OBJEXT) \
+ mate_panel-panel-addto.$(OBJEXT) \
+ mate_panel-panel-ditem-editor.$(OBJEXT) \
+ mate_panel-panel-modules.$(OBJEXT) \
+ mate_panel-mate-panel-applet-info.$(OBJEXT) \
+ mate_panel-panel-reset.$(OBJEXT)
+am__objects_2 =
+am_mate_panel_OBJECTS = $(am__objects_1) $(am__objects_2)
+mate_panel_OBJECTS = $(am_mate_panel_OBJECTS)
+mate_panel_DEPENDENCIES = $(top_builddir)/mate-panel/libegg/libegg.la \
+ $(top_builddir)/mate-panel/libmate-panel-applet-private/libmate-panel-applet-private.la \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+mate_panel_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mate_panel_LDFLAGS) $(LDFLAGS) -o $@
+am_mate_panel_test_applets_OBJECTS = \
+ mate_panel_test_applets-panel-modules.$(OBJEXT) \
+ mate_panel_test_applets-mate-panel-applet-info.$(OBJEXT) \
+ mate_panel_test_applets-mate-panel-applets-manager.$(OBJEXT) \
+ mate_panel_test_applets-panel-marshal.$(OBJEXT) \
+ mate_panel_test_applets-panel-test-applets.$(OBJEXT)
+mate_panel_test_applets_OBJECTS = \
+ $(am_mate_panel_test_applets_OBJECTS)
+mate_panel_test_applets_DEPENDENCIES = $(top_builddir)/mate-panel/libmate-panel-applet-private/libmate-panel-applet-private-mini.la \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(am__DEPENDENCIES_1)
+mate_panel_test_applets_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mate_panel_test_applets_LDFLAGS) \
+ $(LDFLAGS) -o $@
+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'
+SCRIPTS = $(libexec_SCRIPTS)
+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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(mate_desktop_item_edit_SOURCES) $(mate_panel_SOURCES) \
+ $(mate_panel_test_applets_SOURCES)
+DIST_SOURCES = $(mate_desktop_item_edit_SOURCES) $(mate_panel_SOURCES) \
+ $(mate_panel_test_applets_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 = $(desktop_DATA) $(entries_DATA) $(rc_DATA) $(schemas_DATA) \
+ $(ui_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@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CLOCK_CFLAGS = @CLOCK_CFLAGS@
+CLOCK_EDS_ICONDIR = @CLOCK_EDS_ICONDIR@
+CLOCK_LIBS = @CLOCK_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DISABLE_DEPRECATED_CFLAGS = @DISABLE_DEPRECATED_CFLAGS@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DLLTOOL = @DLLTOOL@
+DOC_USER_FORMATS = @DOC_USER_FORMATS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGG_SMCLIENT_CFLAGS = @EGG_SMCLIENT_CFLAGS@
+EGG_SMCLIENT_LIBS = @EGG_SMCLIENT_LIBS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FISH_CFLAGS = @FISH_CFLAGS@
+FISH_LIBS = @FISH_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_QUERYMODULES = @GIO_QUERYMODULES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+HELP_DIR = @HELP_DIR@
+HTML_DIR = @HTML_DIR@
+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@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBMATE_PANEL_APPLET_CFLAGS = @LIBMATE_PANEL_APPLET_CFLAGS@
+LIBMATE_PANEL_APPLET_LIBS = @LIBMATE_PANEL_APPLET_LIBS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MATE_PANEL_APPLET_LT_VERSION = @LIB_MATE_PANEL_APPLET_LT_VERSION@
+LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION = @LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECOMPONENT_ACT_IDLDIR = @MATECOMPONENT_ACT_IDLDIR@
+MATECOMPONENT_CFLAGS = @MATECOMPONENT_CFLAGS@
+MATECOMPONENT_IDLDIR = @MATECOMPONENT_IDLDIR@
+MATECOMPONENT_LIBS = @MATECOMPONENT_LIBS@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATECORBA_IDL = @MATECORBA_IDL@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NETWORK_MANAGER_CFLAGS = @NETWORK_MANAGER_CFLAGS@
+NETWORK_MANAGER_LIBS = @NETWORK_MANAGER_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NOTIFICATION_AREA_CFLAGS = @NOTIFICATION_AREA_CFLAGS@
+NOTIFICATION_AREA_LIBS = @NOTIFICATION_AREA_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OMF_DIR = @OMF_DIR@
+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@
+PANEL_CFLAGS = @PANEL_CFLAGS@
+PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE = @PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE@
+PANEL_LIBS = @PANEL_LIBS@
+PANEL_MODULE_MATECOMPONENT_CFLAGS = @PANEL_MODULE_MATECOMPONENT_CFLAGS@
+PANEL_MODULE_MATECOMPONENT_LIBS = @PANEL_MODULE_MATECOMPONENT_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+REBUILD = @REBUILD@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TZ_CFLAGS = @TZ_CFLAGS@
+TZ_LIBS = @TZ_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WNCKLET_CFLAGS = @WNCKLET_CFLAGS@
+WNCKLET_LIBS = @WNCKLET_LIBS@
+XGETTEXT = @XGETTEXT@
+XMKMF = @XMKMF@
+XRANDR_CFLAGS = @XRANDR_CFLAGS@
+XRANDR_LIBS = @XRANDR_LIBS@
+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_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@
+appletsdir = @appletsdir@
+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@
+modulesdir = @modulesdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+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@
+SUBDIRS = libegg libmate-panel-applet-private libpanel-util
+libexec_SCRIPTS = mate-panel-add
+AM_CPPFLAGS = \
+ $(PANEL_CFLAGS) \
+ -I. \
+ -I$(srcdir) \
+ -I$(top_builddir)/mate-panel \
+ -I$(top_builddir)/mate-panel/libpanel-util \
+ -DMATELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+ -DBUILDERDIR=\""$(uidir)"\" \
+ -DICONDIR=\""$(datadir)/mate-panel/pixmaps"\" \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+panel_sources = \
+ panel-typebuiltins.c \
+ panel-typebuiltins.h \
+ panel-marshal.c \
+ panel-marshal.h \
+ main.c \
+ panel-widget.c \
+ button-widget.c \
+ xstuff.c \
+ panel-session.c \
+ panel-compatibility.c \
+ panel.c \
+ applet.c \
+ drawer.c \
+ panel-config-global.c \
+ panel-util.c \
+ panel-mateconf.c \
+ panel-properties-dialog.c \
+ panel-run-dialog.c \
+ menu.c \
+ panel-context-menu.c \
+ launcher.c \
+ mate-panel-applet-frame.c \
+ mate-panel-applets-manager.c \
+ panel-shell.c \
+ panel-background.c \
+ panel-background-monitor.c \
+ panel-stock-icons.c \
+ panel-action-button.c \
+ panel-menu-bar.c \
+ panel-menu-button.c \
+ panel-menu-items.c \
+ panel-separator.c \
+ panel-recent.c \
+ panel-action-protocol.c \
+ panel-toplevel.c \
+ panel-struts.c \
+ panel-frame.c \
+ panel-xutils.c \
+ panel-multiscreen.c \
+ panel-a11y.c \
+ panel-bindings.c \
+ panel-profile.c \
+ panel-force-quit.c \
+ panel-lockdown.c \
+ panel-addto.c \
+ panel-ditem-editor.c \
+ panel-modules.c \
+ mate-panel-applet-info.c \
+ panel-reset.c
+
+panel_headers = \
+ panel-types.h \
+ panel-widget.h \
+ panel-globals.h \
+ button-widget.h \
+ xstuff.h \
+ panel-session.h \
+ panel-compatibility.h \
+ panel.h \
+ applet.h \
+ drawer.h \
+ panel-util.h \
+ panel-properties-dialog.h \
+ panel-config-global.h \
+ panel-mateconf.h \
+ panel-run-dialog.h \
+ menu.h \
+ panel-context-menu.h \
+ launcher.h \
+ mate-panel-applet-frame.h \
+ mate-panel-applets-manager.h \
+ panel-shell.h \
+ panel-background.h \
+ panel-background-monitor.h \
+ panel-stock-icons.h \
+ panel-action-button.h \
+ panel-menu-bar.h \
+ panel-menu-button.h \
+ panel-menu-items.h \
+ panel-separator.h \
+ panel-recent.h \
+ panel-action-protocol.h \
+ panel-toplevel.h \
+ panel-struts.h \
+ panel-frame.h \
+ panel-xutils.h \
+ panel-multiscreen.h \
+ panel-a11y.h \
+ panel-bindings.h \
+ panel-profile.h \
+ panel-enums.h \
+ panel-force-quit.h \
+ panel-lockdown.h \
+ panel-addto.h \
+ panel-ditem-editor.h \
+ panel-icon-names.h \
+ panel-modules.h \
+ mate-panel-applet-info.h \
+ panel-reset.h
+
+mate_panel_SOURCES = \
+ $(panel_sources) \
+ $(panel_headers)
+
+mate_panel_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(XRANDR_CFLAGS) \
+ -DPANEL_MODULES_DIR=\"$(modulesdir)\" \
+ -DMATEMENU_I_KNOW_THIS_IS_UNSTABLE
+
+mate_panel_LDADD = \
+ $(top_builddir)/mate-panel/libegg/libegg.la \
+ $(top_builddir)/mate-panel/libmate-panel-applet-private/libmate-panel-applet-private.la \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(PANEL_LIBS) \
+ $(XRANDR_LIBS) \
+ $(X_LIBS)
+
+mate_panel_LDFLAGS = -export-dynamic
+mate_desktop_item_edit_SOURCES = \
+ mate-desktop-item-edit.c \
+ panel-ditem-editor.c \
+ panel-marshal.c \
+ panel-util.c \
+ xstuff.c
+
+mate_desktop_item_edit_LDADD = \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(PANEL_LIBS)
+
+mate_panel_test_applets_SOURCES = \
+ panel-modules.c \
+ mate-panel-applet-info.c \
+ mate-panel-applets-manager.c \
+ panel-marshal.c \
+ panel-test-applets.c
+
+mate_panel_test_applets_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -DPANEL_MODULES_DIR=\"$(modulesdir)\" \
+ -DMATE_PANEL_APPLETS_DIR=\"$(appletsdir)\"
+
+mate_panel_test_applets_LDADD = \
+ $(top_builddir)/mate-panel/libmate-panel-applet-private/libmate-panel-applet-private-mini.la \
+ $(top_builddir)/mate-panel/libpanel-util/libpanel-util.la \
+ $(PANEL_LIBS)
+
+mate_panel_test_applets_LDFLAGS = -export-dynamic
+panel_enum_headers = \
+ $(top_srcdir)/mate-panel/panel-enums.h \
+ $(top_srcdir)/mate-panel/panel-types.h
+
+BUILT_SOURCES = \
+ panel-typebuiltins.c \
+ panel-typebuiltins.h \
+ panel-marshal.c \
+ panel-marshal.h
+
+rcdir = $(datadir)
+rc_DATA = mate-panelrc
+uidir = $(datadir)/mate-panel/ui
+ui_DATA = \
+ panel-properties-dialog.ui \
+ panel-run-dialog.ui \
+ panel-test-applets.ui
+
+desktopdir = $(datadir)/applications
+desktop_in_files = mate-panel.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+entriesdir = $(MATECONF_SCHEMA_FILE_DIR)
+entries_DATA = panel-default-setup.entries
+schemasdir = $(MATECONF_SCHEMA_FILE_DIR)
+schemas_in_files = \
+ panel-global.schemas.in \
+ panel-general.schemas.in \
+ panel-toplevel.schemas.in \
+ panel-object.schemas.in
+
+schemas_DATA = panel-compatibility.schemas $(schemas_in_files:.schemas.in=.schemas)
+EXTRA_DIST = \
+ $(ui_DATA) \
+ nothing.cP \
+ nothing.h \
+ $(schemas_in_files) \
+ panel-compatibility.schemas \
+ panel-marshal.list \
+ mate-panelrc \
+ $(entries_DATA) \
+ $(desktop_in_files) \
+ mate-panel-add.in
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(schemas_in_files:.schemas.in=.schemas) \
+ $(sys_DATA) \
+ $(desktop_DATA) \
+ mate-panel-add
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 mate-panel/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu mate-panel/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+mate-panel.desktop.in: $(top_builddir)/config.status $(srcdir)/mate-panel.desktop.in.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_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
+mate-desktop-item-edit$(EXEEXT): $(mate_desktop_item_edit_OBJECTS) $(mate_desktop_item_edit_DEPENDENCIES)
+ @rm -f mate-desktop-item-edit$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(mate_desktop_item_edit_OBJECTS) $(mate_desktop_item_edit_LDADD) $(LIBS)
+mate-panel$(EXEEXT): $(mate_panel_OBJECTS) $(mate_panel_DEPENDENCIES)
+ @rm -f mate-panel$(EXEEXT)
+ $(AM_V_CCLD)$(mate_panel_LINK) $(mate_panel_OBJECTS) $(mate_panel_LDADD) $(LIBS)
+mate-panel-test-applets$(EXEEXT): $(mate_panel_test_applets_OBJECTS) $(mate_panel_test_applets_DEPENDENCIES)
+ @rm -f mate-panel-test-applets$(EXEEXT)
+ $(AM_V_CCLD)$(mate_panel_test_applets_LINK) $(mate_panel_test_applets_OBJECTS) $(mate_panel_test_applets_LDADD) $(LIBS)
+install-libexecSCRIPTS: $(libexec_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)"
+ @list='$(libexec_SCRIPTS)'; test -n "$(libexecdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e 'h;s|.*|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | 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; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$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_SCRIPT) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-libexecSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libexec_SCRIPTS)'; test -n "$(libexecdir)" || exit 0; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 's,.*/,,;$(transform)'`; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate-desktop-item-edit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-applet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-button-widget.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-drawer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-launcher.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-mate-panel-applet-frame.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-mate-panel-applet-info.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-mate-panel-applets-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-menu.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-a11y.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-action-button.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-action-protocol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-addto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-background-monitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-background.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-bindings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-compatibility.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-config-global.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-context-menu.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-ditem-editor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-force-quit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-frame.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-lockdown.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-marshal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-mateconf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-menu-bar.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-menu-button.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-menu-items.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-modules.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-multiscreen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-profile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-properties-dialog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-recent.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-reset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-run-dialog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-separator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-session.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-shell.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-stock-icons.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-struts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-toplevel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-typebuiltins.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-widget.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel-xutils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-panel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel-xstuff.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel_test_applets-panel-marshal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel_test_applets-panel-modules.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate_panel_test_applets-panel-test-applets.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-ditem-editor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-marshal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstuff.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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 $@ $<
+
+mate_panel-panel-typebuiltins.o: panel-typebuiltins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-typebuiltins.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-typebuiltins.Tpo -c -o mate_panel-panel-typebuiltins.o `test -f 'panel-typebuiltins.c' || echo '$(srcdir)/'`panel-typebuiltins.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-typebuiltins.Tpo $(DEPDIR)/mate_panel-panel-typebuiltins.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-typebuiltins.c' object='mate_panel-panel-typebuiltins.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-typebuiltins.o `test -f 'panel-typebuiltins.c' || echo '$(srcdir)/'`panel-typebuiltins.c
+
+mate_panel-panel-typebuiltins.obj: panel-typebuiltins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-typebuiltins.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-typebuiltins.Tpo -c -o mate_panel-panel-typebuiltins.obj `if test -f 'panel-typebuiltins.c'; then $(CYGPATH_W) 'panel-typebuiltins.c'; else $(CYGPATH_W) '$(srcdir)/panel-typebuiltins.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-typebuiltins.Tpo $(DEPDIR)/mate_panel-panel-typebuiltins.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-typebuiltins.c' object='mate_panel-panel-typebuiltins.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-typebuiltins.obj `if test -f 'panel-typebuiltins.c'; then $(CYGPATH_W) 'panel-typebuiltins.c'; else $(CYGPATH_W) '$(srcdir)/panel-typebuiltins.c'; fi`
+
+mate_panel-panel-marshal.o: panel-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-marshal.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-marshal.Tpo -c -o mate_panel-panel-marshal.o `test -f 'panel-marshal.c' || echo '$(srcdir)/'`panel-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-marshal.Tpo $(DEPDIR)/mate_panel-panel-marshal.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-marshal.c' object='mate_panel-panel-marshal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-marshal.o `test -f 'panel-marshal.c' || echo '$(srcdir)/'`panel-marshal.c
+
+mate_panel-panel-marshal.obj: panel-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-marshal.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-marshal.Tpo -c -o mate_panel-panel-marshal.obj `if test -f 'panel-marshal.c'; then $(CYGPATH_W) 'panel-marshal.c'; else $(CYGPATH_W) '$(srcdir)/panel-marshal.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-marshal.Tpo $(DEPDIR)/mate_panel-panel-marshal.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-marshal.c' object='mate_panel-panel-marshal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-marshal.obj `if test -f 'panel-marshal.c'; then $(CYGPATH_W) 'panel-marshal.c'; else $(CYGPATH_W) '$(srcdir)/panel-marshal.c'; fi`
+
+mate_panel-main.o: main.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-main.o -MD -MP -MF $(DEPDIR)/mate_panel-main.Tpo -c -o mate_panel-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-main.Tpo $(DEPDIR)/mate_panel-main.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='mate_panel-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+
+mate_panel-main.obj: main.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-main.obj -MD -MP -MF $(DEPDIR)/mate_panel-main.Tpo -c -o mate_panel-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-main.Tpo $(DEPDIR)/mate_panel-main.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='mate_panel-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+
+mate_panel-panel-widget.o: panel-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-widget.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-widget.Tpo -c -o mate_panel-panel-widget.o `test -f 'panel-widget.c' || echo '$(srcdir)/'`panel-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-widget.Tpo $(DEPDIR)/mate_panel-panel-widget.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-widget.c' object='mate_panel-panel-widget.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-widget.o `test -f 'panel-widget.c' || echo '$(srcdir)/'`panel-widget.c
+
+mate_panel-panel-widget.obj: panel-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-widget.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-widget.Tpo -c -o mate_panel-panel-widget.obj `if test -f 'panel-widget.c'; then $(CYGPATH_W) 'panel-widget.c'; else $(CYGPATH_W) '$(srcdir)/panel-widget.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-widget.Tpo $(DEPDIR)/mate_panel-panel-widget.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-widget.c' object='mate_panel-panel-widget.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-widget.obj `if test -f 'panel-widget.c'; then $(CYGPATH_W) 'panel-widget.c'; else $(CYGPATH_W) '$(srcdir)/panel-widget.c'; fi`
+
+mate_panel-button-widget.o: button-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-button-widget.o -MD -MP -MF $(DEPDIR)/mate_panel-button-widget.Tpo -c -o mate_panel-button-widget.o `test -f 'button-widget.c' || echo '$(srcdir)/'`button-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-button-widget.Tpo $(DEPDIR)/mate_panel-button-widget.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='button-widget.c' object='mate_panel-button-widget.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-button-widget.o `test -f 'button-widget.c' || echo '$(srcdir)/'`button-widget.c
+
+mate_panel-button-widget.obj: button-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-button-widget.obj -MD -MP -MF $(DEPDIR)/mate_panel-button-widget.Tpo -c -o mate_panel-button-widget.obj `if test -f 'button-widget.c'; then $(CYGPATH_W) 'button-widget.c'; else $(CYGPATH_W) '$(srcdir)/button-widget.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-button-widget.Tpo $(DEPDIR)/mate_panel-button-widget.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='button-widget.c' object='mate_panel-button-widget.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-button-widget.obj `if test -f 'button-widget.c'; then $(CYGPATH_W) 'button-widget.c'; else $(CYGPATH_W) '$(srcdir)/button-widget.c'; fi`
+
+mate_panel-xstuff.o: xstuff.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-xstuff.o -MD -MP -MF $(DEPDIR)/mate_panel-xstuff.Tpo -c -o mate_panel-xstuff.o `test -f 'xstuff.c' || echo '$(srcdir)/'`xstuff.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-xstuff.Tpo $(DEPDIR)/mate_panel-xstuff.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xstuff.c' object='mate_panel-xstuff.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-xstuff.o `test -f 'xstuff.c' || echo '$(srcdir)/'`xstuff.c
+
+mate_panel-xstuff.obj: xstuff.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-xstuff.obj -MD -MP -MF $(DEPDIR)/mate_panel-xstuff.Tpo -c -o mate_panel-xstuff.obj `if test -f 'xstuff.c'; then $(CYGPATH_W) 'xstuff.c'; else $(CYGPATH_W) '$(srcdir)/xstuff.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-xstuff.Tpo $(DEPDIR)/mate_panel-xstuff.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xstuff.c' object='mate_panel-xstuff.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-xstuff.obj `if test -f 'xstuff.c'; then $(CYGPATH_W) 'xstuff.c'; else $(CYGPATH_W) '$(srcdir)/xstuff.c'; fi`
+
+mate_panel-panel-session.o: panel-session.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-session.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-session.Tpo -c -o mate_panel-panel-session.o `test -f 'panel-session.c' || echo '$(srcdir)/'`panel-session.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-session.Tpo $(DEPDIR)/mate_panel-panel-session.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-session.c' object='mate_panel-panel-session.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-session.o `test -f 'panel-session.c' || echo '$(srcdir)/'`panel-session.c
+
+mate_panel-panel-session.obj: panel-session.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-session.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-session.Tpo -c -o mate_panel-panel-session.obj `if test -f 'panel-session.c'; then $(CYGPATH_W) 'panel-session.c'; else $(CYGPATH_W) '$(srcdir)/panel-session.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-session.Tpo $(DEPDIR)/mate_panel-panel-session.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-session.c' object='mate_panel-panel-session.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-session.obj `if test -f 'panel-session.c'; then $(CYGPATH_W) 'panel-session.c'; else $(CYGPATH_W) '$(srcdir)/panel-session.c'; fi`
+
+mate_panel-panel-compatibility.o: panel-compatibility.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-compatibility.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-compatibility.Tpo -c -o mate_panel-panel-compatibility.o `test -f 'panel-compatibility.c' || echo '$(srcdir)/'`panel-compatibility.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-compatibility.Tpo $(DEPDIR)/mate_panel-panel-compatibility.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-compatibility.c' object='mate_panel-panel-compatibility.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-compatibility.o `test -f 'panel-compatibility.c' || echo '$(srcdir)/'`panel-compatibility.c
+
+mate_panel-panel-compatibility.obj: panel-compatibility.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-compatibility.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-compatibility.Tpo -c -o mate_panel-panel-compatibility.obj `if test -f 'panel-compatibility.c'; then $(CYGPATH_W) 'panel-compatibility.c'; else $(CYGPATH_W) '$(srcdir)/panel-compatibility.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-compatibility.Tpo $(DEPDIR)/mate_panel-panel-compatibility.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-compatibility.c' object='mate_panel-panel-compatibility.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-compatibility.obj `if test -f 'panel-compatibility.c'; then $(CYGPATH_W) 'panel-compatibility.c'; else $(CYGPATH_W) '$(srcdir)/panel-compatibility.c'; fi`
+
+mate_panel-panel.o: panel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel.o -MD -MP -MF $(DEPDIR)/mate_panel-panel.Tpo -c -o mate_panel-panel.o `test -f 'panel.c' || echo '$(srcdir)/'`panel.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel.Tpo $(DEPDIR)/mate_panel-panel.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel.c' object='mate_panel-panel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel.o `test -f 'panel.c' || echo '$(srcdir)/'`panel.c
+
+mate_panel-panel.obj: panel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel.Tpo -c -o mate_panel-panel.obj `if test -f 'panel.c'; then $(CYGPATH_W) 'panel.c'; else $(CYGPATH_W) '$(srcdir)/panel.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel.Tpo $(DEPDIR)/mate_panel-panel.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel.c' object='mate_panel-panel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel.obj `if test -f 'panel.c'; then $(CYGPATH_W) 'panel.c'; else $(CYGPATH_W) '$(srcdir)/panel.c'; fi`
+
+mate_panel-applet.o: applet.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-applet.o -MD -MP -MF $(DEPDIR)/mate_panel-applet.Tpo -c -o mate_panel-applet.o `test -f 'applet.c' || echo '$(srcdir)/'`applet.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-applet.Tpo $(DEPDIR)/mate_panel-applet.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='applet.c' object='mate_panel-applet.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-applet.o `test -f 'applet.c' || echo '$(srcdir)/'`applet.c
+
+mate_panel-applet.obj: applet.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-applet.obj -MD -MP -MF $(DEPDIR)/mate_panel-applet.Tpo -c -o mate_panel-applet.obj `if test -f 'applet.c'; then $(CYGPATH_W) 'applet.c'; else $(CYGPATH_W) '$(srcdir)/applet.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-applet.Tpo $(DEPDIR)/mate_panel-applet.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='applet.c' object='mate_panel-applet.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-applet.obj `if test -f 'applet.c'; then $(CYGPATH_W) 'applet.c'; else $(CYGPATH_W) '$(srcdir)/applet.c'; fi`
+
+mate_panel-drawer.o: drawer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-drawer.o -MD -MP -MF $(DEPDIR)/mate_panel-drawer.Tpo -c -o mate_panel-drawer.o `test -f 'drawer.c' || echo '$(srcdir)/'`drawer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-drawer.Tpo $(DEPDIR)/mate_panel-drawer.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drawer.c' object='mate_panel-drawer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-drawer.o `test -f 'drawer.c' || echo '$(srcdir)/'`drawer.c
+
+mate_panel-drawer.obj: drawer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-drawer.obj -MD -MP -MF $(DEPDIR)/mate_panel-drawer.Tpo -c -o mate_panel-drawer.obj `if test -f 'drawer.c'; then $(CYGPATH_W) 'drawer.c'; else $(CYGPATH_W) '$(srcdir)/drawer.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-drawer.Tpo $(DEPDIR)/mate_panel-drawer.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drawer.c' object='mate_panel-drawer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-drawer.obj `if test -f 'drawer.c'; then $(CYGPATH_W) 'drawer.c'; else $(CYGPATH_W) '$(srcdir)/drawer.c'; fi`
+
+mate_panel-panel-config-global.o: panel-config-global.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-config-global.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-config-global.Tpo -c -o mate_panel-panel-config-global.o `test -f 'panel-config-global.c' || echo '$(srcdir)/'`panel-config-global.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-config-global.Tpo $(DEPDIR)/mate_panel-panel-config-global.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-config-global.c' object='mate_panel-panel-config-global.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-config-global.o `test -f 'panel-config-global.c' || echo '$(srcdir)/'`panel-config-global.c
+
+mate_panel-panel-config-global.obj: panel-config-global.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-config-global.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-config-global.Tpo -c -o mate_panel-panel-config-global.obj `if test -f 'panel-config-global.c'; then $(CYGPATH_W) 'panel-config-global.c'; else $(CYGPATH_W) '$(srcdir)/panel-config-global.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-config-global.Tpo $(DEPDIR)/mate_panel-panel-config-global.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-config-global.c' object='mate_panel-panel-config-global.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-config-global.obj `if test -f 'panel-config-global.c'; then $(CYGPATH_W) 'panel-config-global.c'; else $(CYGPATH_W) '$(srcdir)/panel-config-global.c'; fi`
+
+mate_panel-panel-util.o: panel-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-util.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-util.Tpo -c -o mate_panel-panel-util.o `test -f 'panel-util.c' || echo '$(srcdir)/'`panel-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-util.Tpo $(DEPDIR)/mate_panel-panel-util.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-util.c' object='mate_panel-panel-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-util.o `test -f 'panel-util.c' || echo '$(srcdir)/'`panel-util.c
+
+mate_panel-panel-util.obj: panel-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-util.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-util.Tpo -c -o mate_panel-panel-util.obj `if test -f 'panel-util.c'; then $(CYGPATH_W) 'panel-util.c'; else $(CYGPATH_W) '$(srcdir)/panel-util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-util.Tpo $(DEPDIR)/mate_panel-panel-util.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-util.c' object='mate_panel-panel-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-util.obj `if test -f 'panel-util.c'; then $(CYGPATH_W) 'panel-util.c'; else $(CYGPATH_W) '$(srcdir)/panel-util.c'; fi`
+
+mate_panel-panel-mateconf.o: panel-mateconf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-mateconf.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-mateconf.Tpo -c -o mate_panel-panel-mateconf.o `test -f 'panel-mateconf.c' || echo '$(srcdir)/'`panel-mateconf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-mateconf.Tpo $(DEPDIR)/mate_panel-panel-mateconf.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-mateconf.c' object='mate_panel-panel-mateconf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-mateconf.o `test -f 'panel-mateconf.c' || echo '$(srcdir)/'`panel-mateconf.c
+
+mate_panel-panel-mateconf.obj: panel-mateconf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-mateconf.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-mateconf.Tpo -c -o mate_panel-panel-mateconf.obj `if test -f 'panel-mateconf.c'; then $(CYGPATH_W) 'panel-mateconf.c'; else $(CYGPATH_W) '$(srcdir)/panel-mateconf.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-mateconf.Tpo $(DEPDIR)/mate_panel-panel-mateconf.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-mateconf.c' object='mate_panel-panel-mateconf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-mateconf.obj `if test -f 'panel-mateconf.c'; then $(CYGPATH_W) 'panel-mateconf.c'; else $(CYGPATH_W) '$(srcdir)/panel-mateconf.c'; fi`
+
+mate_panel-panel-properties-dialog.o: panel-properties-dialog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-properties-dialog.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-properties-dialog.Tpo -c -o mate_panel-panel-properties-dialog.o `test -f 'panel-properties-dialog.c' || echo '$(srcdir)/'`panel-properties-dialog.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-properties-dialog.Tpo $(DEPDIR)/mate_panel-panel-properties-dialog.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-properties-dialog.c' object='mate_panel-panel-properties-dialog.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-properties-dialog.o `test -f 'panel-properties-dialog.c' || echo '$(srcdir)/'`panel-properties-dialog.c
+
+mate_panel-panel-properties-dialog.obj: panel-properties-dialog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-properties-dialog.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-properties-dialog.Tpo -c -o mate_panel-panel-properties-dialog.obj `if test -f 'panel-properties-dialog.c'; then $(CYGPATH_W) 'panel-properties-dialog.c'; else $(CYGPATH_W) '$(srcdir)/panel-properties-dialog.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-properties-dialog.Tpo $(DEPDIR)/mate_panel-panel-properties-dialog.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-properties-dialog.c' object='mate_panel-panel-properties-dialog.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-properties-dialog.obj `if test -f 'panel-properties-dialog.c'; then $(CYGPATH_W) 'panel-properties-dialog.c'; else $(CYGPATH_W) '$(srcdir)/panel-properties-dialog.c'; fi`
+
+mate_panel-panel-run-dialog.o: panel-run-dialog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-run-dialog.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-run-dialog.Tpo -c -o mate_panel-panel-run-dialog.o `test -f 'panel-run-dialog.c' || echo '$(srcdir)/'`panel-run-dialog.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-run-dialog.Tpo $(DEPDIR)/mate_panel-panel-run-dialog.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-run-dialog.c' object='mate_panel-panel-run-dialog.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-run-dialog.o `test -f 'panel-run-dialog.c' || echo '$(srcdir)/'`panel-run-dialog.c
+
+mate_panel-panel-run-dialog.obj: panel-run-dialog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-run-dialog.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-run-dialog.Tpo -c -o mate_panel-panel-run-dialog.obj `if test -f 'panel-run-dialog.c'; then $(CYGPATH_W) 'panel-run-dialog.c'; else $(CYGPATH_W) '$(srcdir)/panel-run-dialog.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-run-dialog.Tpo $(DEPDIR)/mate_panel-panel-run-dialog.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-run-dialog.c' object='mate_panel-panel-run-dialog.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-run-dialog.obj `if test -f 'panel-run-dialog.c'; then $(CYGPATH_W) 'panel-run-dialog.c'; else $(CYGPATH_W) '$(srcdir)/panel-run-dialog.c'; fi`
+
+mate_panel-menu.o: menu.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-menu.o -MD -MP -MF $(DEPDIR)/mate_panel-menu.Tpo -c -o mate_panel-menu.o `test -f 'menu.c' || echo '$(srcdir)/'`menu.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-menu.Tpo $(DEPDIR)/mate_panel-menu.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='menu.c' object='mate_panel-menu.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-menu.o `test -f 'menu.c' || echo '$(srcdir)/'`menu.c
+
+mate_panel-menu.obj: menu.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-menu.obj -MD -MP -MF $(DEPDIR)/mate_panel-menu.Tpo -c -o mate_panel-menu.obj `if test -f 'menu.c'; then $(CYGPATH_W) 'menu.c'; else $(CYGPATH_W) '$(srcdir)/menu.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-menu.Tpo $(DEPDIR)/mate_panel-menu.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='menu.c' object='mate_panel-menu.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-menu.obj `if test -f 'menu.c'; then $(CYGPATH_W) 'menu.c'; else $(CYGPATH_W) '$(srcdir)/menu.c'; fi`
+
+mate_panel-panel-context-menu.o: panel-context-menu.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-context-menu.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-context-menu.Tpo -c -o mate_panel-panel-context-menu.o `test -f 'panel-context-menu.c' || echo '$(srcdir)/'`panel-context-menu.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-context-menu.Tpo $(DEPDIR)/mate_panel-panel-context-menu.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-context-menu.c' object='mate_panel-panel-context-menu.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-context-menu.o `test -f 'panel-context-menu.c' || echo '$(srcdir)/'`panel-context-menu.c
+
+mate_panel-panel-context-menu.obj: panel-context-menu.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-context-menu.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-context-menu.Tpo -c -o mate_panel-panel-context-menu.obj `if test -f 'panel-context-menu.c'; then $(CYGPATH_W) 'panel-context-menu.c'; else $(CYGPATH_W) '$(srcdir)/panel-context-menu.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-context-menu.Tpo $(DEPDIR)/mate_panel-panel-context-menu.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-context-menu.c' object='mate_panel-panel-context-menu.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-context-menu.obj `if test -f 'panel-context-menu.c'; then $(CYGPATH_W) 'panel-context-menu.c'; else $(CYGPATH_W) '$(srcdir)/panel-context-menu.c'; fi`
+
+mate_panel-launcher.o: launcher.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-launcher.o -MD -MP -MF $(DEPDIR)/mate_panel-launcher.Tpo -c -o mate_panel-launcher.o `test -f 'launcher.c' || echo '$(srcdir)/'`launcher.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-launcher.Tpo $(DEPDIR)/mate_panel-launcher.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='launcher.c' object='mate_panel-launcher.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-launcher.o `test -f 'launcher.c' || echo '$(srcdir)/'`launcher.c
+
+mate_panel-launcher.obj: launcher.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-launcher.obj -MD -MP -MF $(DEPDIR)/mate_panel-launcher.Tpo -c -o mate_panel-launcher.obj `if test -f 'launcher.c'; then $(CYGPATH_W) 'launcher.c'; else $(CYGPATH_W) '$(srcdir)/launcher.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-launcher.Tpo $(DEPDIR)/mate_panel-launcher.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='launcher.c' object='mate_panel-launcher.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-launcher.obj `if test -f 'launcher.c'; then $(CYGPATH_W) 'launcher.c'; else $(CYGPATH_W) '$(srcdir)/launcher.c'; fi`
+
+mate_panel-mate-panel-applet-frame.o: mate-panel-applet-frame.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-mate-panel-applet-frame.o -MD -MP -MF $(DEPDIR)/mate_panel-mate-panel-applet-frame.Tpo -c -o mate_panel-mate-panel-applet-frame.o `test -f 'mate-panel-applet-frame.c' || echo '$(srcdir)/'`mate-panel-applet-frame.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-mate-panel-applet-frame.Tpo $(DEPDIR)/mate_panel-mate-panel-applet-frame.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applet-frame.c' object='mate_panel-mate-panel-applet-frame.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-mate-panel-applet-frame.o `test -f 'mate-panel-applet-frame.c' || echo '$(srcdir)/'`mate-panel-applet-frame.c
+
+mate_panel-mate-panel-applet-frame.obj: mate-panel-applet-frame.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-mate-panel-applet-frame.obj -MD -MP -MF $(DEPDIR)/mate_panel-mate-panel-applet-frame.Tpo -c -o mate_panel-mate-panel-applet-frame.obj `if test -f 'mate-panel-applet-frame.c'; then $(CYGPATH_W) 'mate-panel-applet-frame.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applet-frame.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-mate-panel-applet-frame.Tpo $(DEPDIR)/mate_panel-mate-panel-applet-frame.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applet-frame.c' object='mate_panel-mate-panel-applet-frame.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-mate-panel-applet-frame.obj `if test -f 'mate-panel-applet-frame.c'; then $(CYGPATH_W) 'mate-panel-applet-frame.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applet-frame.c'; fi`
+
+mate_panel-mate-panel-applets-manager.o: mate-panel-applets-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-mate-panel-applets-manager.o -MD -MP -MF $(DEPDIR)/mate_panel-mate-panel-applets-manager.Tpo -c -o mate_panel-mate-panel-applets-manager.o `test -f 'mate-panel-applets-manager.c' || echo '$(srcdir)/'`mate-panel-applets-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-mate-panel-applets-manager.Tpo $(DEPDIR)/mate_panel-mate-panel-applets-manager.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applets-manager.c' object='mate_panel-mate-panel-applets-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-mate-panel-applets-manager.o `test -f 'mate-panel-applets-manager.c' || echo '$(srcdir)/'`mate-panel-applets-manager.c
+
+mate_panel-mate-panel-applets-manager.obj: mate-panel-applets-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-mate-panel-applets-manager.obj -MD -MP -MF $(DEPDIR)/mate_panel-mate-panel-applets-manager.Tpo -c -o mate_panel-mate-panel-applets-manager.obj `if test -f 'mate-panel-applets-manager.c'; then $(CYGPATH_W) 'mate-panel-applets-manager.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applets-manager.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-mate-panel-applets-manager.Tpo $(DEPDIR)/mate_panel-mate-panel-applets-manager.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applets-manager.c' object='mate_panel-mate-panel-applets-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-mate-panel-applets-manager.obj `if test -f 'mate-panel-applets-manager.c'; then $(CYGPATH_W) 'mate-panel-applets-manager.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applets-manager.c'; fi`
+
+mate_panel-panel-shell.o: panel-shell.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-shell.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-shell.Tpo -c -o mate_panel-panel-shell.o `test -f 'panel-shell.c' || echo '$(srcdir)/'`panel-shell.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-shell.Tpo $(DEPDIR)/mate_panel-panel-shell.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-shell.c' object='mate_panel-panel-shell.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-shell.o `test -f 'panel-shell.c' || echo '$(srcdir)/'`panel-shell.c
+
+mate_panel-panel-shell.obj: panel-shell.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-shell.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-shell.Tpo -c -o mate_panel-panel-shell.obj `if test -f 'panel-shell.c'; then $(CYGPATH_W) 'panel-shell.c'; else $(CYGPATH_W) '$(srcdir)/panel-shell.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-shell.Tpo $(DEPDIR)/mate_panel-panel-shell.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-shell.c' object='mate_panel-panel-shell.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-shell.obj `if test -f 'panel-shell.c'; then $(CYGPATH_W) 'panel-shell.c'; else $(CYGPATH_W) '$(srcdir)/panel-shell.c'; fi`
+
+mate_panel-panel-background.o: panel-background.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-background.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-background.Tpo -c -o mate_panel-panel-background.o `test -f 'panel-background.c' || echo '$(srcdir)/'`panel-background.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-background.Tpo $(DEPDIR)/mate_panel-panel-background.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-background.c' object='mate_panel-panel-background.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-background.o `test -f 'panel-background.c' || echo '$(srcdir)/'`panel-background.c
+
+mate_panel-panel-background.obj: panel-background.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-background.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-background.Tpo -c -o mate_panel-panel-background.obj `if test -f 'panel-background.c'; then $(CYGPATH_W) 'panel-background.c'; else $(CYGPATH_W) '$(srcdir)/panel-background.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-background.Tpo $(DEPDIR)/mate_panel-panel-background.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-background.c' object='mate_panel-panel-background.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-background.obj `if test -f 'panel-background.c'; then $(CYGPATH_W) 'panel-background.c'; else $(CYGPATH_W) '$(srcdir)/panel-background.c'; fi`
+
+mate_panel-panel-background-monitor.o: panel-background-monitor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-background-monitor.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-background-monitor.Tpo -c -o mate_panel-panel-background-monitor.o `test -f 'panel-background-monitor.c' || echo '$(srcdir)/'`panel-background-monitor.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-background-monitor.Tpo $(DEPDIR)/mate_panel-panel-background-monitor.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-background-monitor.c' object='mate_panel-panel-background-monitor.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-background-monitor.o `test -f 'panel-background-monitor.c' || echo '$(srcdir)/'`panel-background-monitor.c
+
+mate_panel-panel-background-monitor.obj: panel-background-monitor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-background-monitor.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-background-monitor.Tpo -c -o mate_panel-panel-background-monitor.obj `if test -f 'panel-background-monitor.c'; then $(CYGPATH_W) 'panel-background-monitor.c'; else $(CYGPATH_W) '$(srcdir)/panel-background-monitor.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-background-monitor.Tpo $(DEPDIR)/mate_panel-panel-background-monitor.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-background-monitor.c' object='mate_panel-panel-background-monitor.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-background-monitor.obj `if test -f 'panel-background-monitor.c'; then $(CYGPATH_W) 'panel-background-monitor.c'; else $(CYGPATH_W) '$(srcdir)/panel-background-monitor.c'; fi`
+
+mate_panel-panel-stock-icons.o: panel-stock-icons.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-stock-icons.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-stock-icons.Tpo -c -o mate_panel-panel-stock-icons.o `test -f 'panel-stock-icons.c' || echo '$(srcdir)/'`panel-stock-icons.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-stock-icons.Tpo $(DEPDIR)/mate_panel-panel-stock-icons.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-stock-icons.c' object='mate_panel-panel-stock-icons.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-stock-icons.o `test -f 'panel-stock-icons.c' || echo '$(srcdir)/'`panel-stock-icons.c
+
+mate_panel-panel-stock-icons.obj: panel-stock-icons.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-stock-icons.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-stock-icons.Tpo -c -o mate_panel-panel-stock-icons.obj `if test -f 'panel-stock-icons.c'; then $(CYGPATH_W) 'panel-stock-icons.c'; else $(CYGPATH_W) '$(srcdir)/panel-stock-icons.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-stock-icons.Tpo $(DEPDIR)/mate_panel-panel-stock-icons.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-stock-icons.c' object='mate_panel-panel-stock-icons.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-stock-icons.obj `if test -f 'panel-stock-icons.c'; then $(CYGPATH_W) 'panel-stock-icons.c'; else $(CYGPATH_W) '$(srcdir)/panel-stock-icons.c'; fi`
+
+mate_panel-panel-action-button.o: panel-action-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-action-button.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-action-button.Tpo -c -o mate_panel-panel-action-button.o `test -f 'panel-action-button.c' || echo '$(srcdir)/'`panel-action-button.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-action-button.Tpo $(DEPDIR)/mate_panel-panel-action-button.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-action-button.c' object='mate_panel-panel-action-button.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-action-button.o `test -f 'panel-action-button.c' || echo '$(srcdir)/'`panel-action-button.c
+
+mate_panel-panel-action-button.obj: panel-action-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-action-button.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-action-button.Tpo -c -o mate_panel-panel-action-button.obj `if test -f 'panel-action-button.c'; then $(CYGPATH_W) 'panel-action-button.c'; else $(CYGPATH_W) '$(srcdir)/panel-action-button.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-action-button.Tpo $(DEPDIR)/mate_panel-panel-action-button.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-action-button.c' object='mate_panel-panel-action-button.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-action-button.obj `if test -f 'panel-action-button.c'; then $(CYGPATH_W) 'panel-action-button.c'; else $(CYGPATH_W) '$(srcdir)/panel-action-button.c'; fi`
+
+mate_panel-panel-menu-bar.o: panel-menu-bar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-menu-bar.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-menu-bar.Tpo -c -o mate_panel-panel-menu-bar.o `test -f 'panel-menu-bar.c' || echo '$(srcdir)/'`panel-menu-bar.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-menu-bar.Tpo $(DEPDIR)/mate_panel-panel-menu-bar.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-menu-bar.c' object='mate_panel-panel-menu-bar.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-menu-bar.o `test -f 'panel-menu-bar.c' || echo '$(srcdir)/'`panel-menu-bar.c
+
+mate_panel-panel-menu-bar.obj: panel-menu-bar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-menu-bar.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-menu-bar.Tpo -c -o mate_panel-panel-menu-bar.obj `if test -f 'panel-menu-bar.c'; then $(CYGPATH_W) 'panel-menu-bar.c'; else $(CYGPATH_W) '$(srcdir)/panel-menu-bar.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-menu-bar.Tpo $(DEPDIR)/mate_panel-panel-menu-bar.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-menu-bar.c' object='mate_panel-panel-menu-bar.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-menu-bar.obj `if test -f 'panel-menu-bar.c'; then $(CYGPATH_W) 'panel-menu-bar.c'; else $(CYGPATH_W) '$(srcdir)/panel-menu-bar.c'; fi`
+
+mate_panel-panel-menu-button.o: panel-menu-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-menu-button.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-menu-button.Tpo -c -o mate_panel-panel-menu-button.o `test -f 'panel-menu-button.c' || echo '$(srcdir)/'`panel-menu-button.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-menu-button.Tpo $(DEPDIR)/mate_panel-panel-menu-button.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-menu-button.c' object='mate_panel-panel-menu-button.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-menu-button.o `test -f 'panel-menu-button.c' || echo '$(srcdir)/'`panel-menu-button.c
+
+mate_panel-panel-menu-button.obj: panel-menu-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-menu-button.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-menu-button.Tpo -c -o mate_panel-panel-menu-button.obj `if test -f 'panel-menu-button.c'; then $(CYGPATH_W) 'panel-menu-button.c'; else $(CYGPATH_W) '$(srcdir)/panel-menu-button.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-menu-button.Tpo $(DEPDIR)/mate_panel-panel-menu-button.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-menu-button.c' object='mate_panel-panel-menu-button.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-menu-button.obj `if test -f 'panel-menu-button.c'; then $(CYGPATH_W) 'panel-menu-button.c'; else $(CYGPATH_W) '$(srcdir)/panel-menu-button.c'; fi`
+
+mate_panel-panel-menu-items.o: panel-menu-items.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-menu-items.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-menu-items.Tpo -c -o mate_panel-panel-menu-items.o `test -f 'panel-menu-items.c' || echo '$(srcdir)/'`panel-menu-items.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-menu-items.Tpo $(DEPDIR)/mate_panel-panel-menu-items.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-menu-items.c' object='mate_panel-panel-menu-items.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-menu-items.o `test -f 'panel-menu-items.c' || echo '$(srcdir)/'`panel-menu-items.c
+
+mate_panel-panel-menu-items.obj: panel-menu-items.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-menu-items.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-menu-items.Tpo -c -o mate_panel-panel-menu-items.obj `if test -f 'panel-menu-items.c'; then $(CYGPATH_W) 'panel-menu-items.c'; else $(CYGPATH_W) '$(srcdir)/panel-menu-items.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-menu-items.Tpo $(DEPDIR)/mate_panel-panel-menu-items.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-menu-items.c' object='mate_panel-panel-menu-items.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-menu-items.obj `if test -f 'panel-menu-items.c'; then $(CYGPATH_W) 'panel-menu-items.c'; else $(CYGPATH_W) '$(srcdir)/panel-menu-items.c'; fi`
+
+mate_panel-panel-separator.o: panel-separator.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-separator.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-separator.Tpo -c -o mate_panel-panel-separator.o `test -f 'panel-separator.c' || echo '$(srcdir)/'`panel-separator.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-separator.Tpo $(DEPDIR)/mate_panel-panel-separator.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-separator.c' object='mate_panel-panel-separator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-separator.o `test -f 'panel-separator.c' || echo '$(srcdir)/'`panel-separator.c
+
+mate_panel-panel-separator.obj: panel-separator.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-separator.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-separator.Tpo -c -o mate_panel-panel-separator.obj `if test -f 'panel-separator.c'; then $(CYGPATH_W) 'panel-separator.c'; else $(CYGPATH_W) '$(srcdir)/panel-separator.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-separator.Tpo $(DEPDIR)/mate_panel-panel-separator.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-separator.c' object='mate_panel-panel-separator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-separator.obj `if test -f 'panel-separator.c'; then $(CYGPATH_W) 'panel-separator.c'; else $(CYGPATH_W) '$(srcdir)/panel-separator.c'; fi`
+
+mate_panel-panel-recent.o: panel-recent.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-recent.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-recent.Tpo -c -o mate_panel-panel-recent.o `test -f 'panel-recent.c' || echo '$(srcdir)/'`panel-recent.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-recent.Tpo $(DEPDIR)/mate_panel-panel-recent.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-recent.c' object='mate_panel-panel-recent.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-recent.o `test -f 'panel-recent.c' || echo '$(srcdir)/'`panel-recent.c
+
+mate_panel-panel-recent.obj: panel-recent.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-recent.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-recent.Tpo -c -o mate_panel-panel-recent.obj `if test -f 'panel-recent.c'; then $(CYGPATH_W) 'panel-recent.c'; else $(CYGPATH_W) '$(srcdir)/panel-recent.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-recent.Tpo $(DEPDIR)/mate_panel-panel-recent.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-recent.c' object='mate_panel-panel-recent.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-recent.obj `if test -f 'panel-recent.c'; then $(CYGPATH_W) 'panel-recent.c'; else $(CYGPATH_W) '$(srcdir)/panel-recent.c'; fi`
+
+mate_panel-panel-action-protocol.o: panel-action-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-action-protocol.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-action-protocol.Tpo -c -o mate_panel-panel-action-protocol.o `test -f 'panel-action-protocol.c' || echo '$(srcdir)/'`panel-action-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-action-protocol.Tpo $(DEPDIR)/mate_panel-panel-action-protocol.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-action-protocol.c' object='mate_panel-panel-action-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-action-protocol.o `test -f 'panel-action-protocol.c' || echo '$(srcdir)/'`panel-action-protocol.c
+
+mate_panel-panel-action-protocol.obj: panel-action-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-action-protocol.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-action-protocol.Tpo -c -o mate_panel-panel-action-protocol.obj `if test -f 'panel-action-protocol.c'; then $(CYGPATH_W) 'panel-action-protocol.c'; else $(CYGPATH_W) '$(srcdir)/panel-action-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-action-protocol.Tpo $(DEPDIR)/mate_panel-panel-action-protocol.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-action-protocol.c' object='mate_panel-panel-action-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-action-protocol.obj `if test -f 'panel-action-protocol.c'; then $(CYGPATH_W) 'panel-action-protocol.c'; else $(CYGPATH_W) '$(srcdir)/panel-action-protocol.c'; fi`
+
+mate_panel-panel-toplevel.o: panel-toplevel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-toplevel.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-toplevel.Tpo -c -o mate_panel-panel-toplevel.o `test -f 'panel-toplevel.c' || echo '$(srcdir)/'`panel-toplevel.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-toplevel.Tpo $(DEPDIR)/mate_panel-panel-toplevel.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-toplevel.c' object='mate_panel-panel-toplevel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-toplevel.o `test -f 'panel-toplevel.c' || echo '$(srcdir)/'`panel-toplevel.c
+
+mate_panel-panel-toplevel.obj: panel-toplevel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-toplevel.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-toplevel.Tpo -c -o mate_panel-panel-toplevel.obj `if test -f 'panel-toplevel.c'; then $(CYGPATH_W) 'panel-toplevel.c'; else $(CYGPATH_W) '$(srcdir)/panel-toplevel.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-toplevel.Tpo $(DEPDIR)/mate_panel-panel-toplevel.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-toplevel.c' object='mate_panel-panel-toplevel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-toplevel.obj `if test -f 'panel-toplevel.c'; then $(CYGPATH_W) 'panel-toplevel.c'; else $(CYGPATH_W) '$(srcdir)/panel-toplevel.c'; fi`
+
+mate_panel-panel-struts.o: panel-struts.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-struts.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-struts.Tpo -c -o mate_panel-panel-struts.o `test -f 'panel-struts.c' || echo '$(srcdir)/'`panel-struts.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-struts.Tpo $(DEPDIR)/mate_panel-panel-struts.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-struts.c' object='mate_panel-panel-struts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-struts.o `test -f 'panel-struts.c' || echo '$(srcdir)/'`panel-struts.c
+
+mate_panel-panel-struts.obj: panel-struts.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-struts.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-struts.Tpo -c -o mate_panel-panel-struts.obj `if test -f 'panel-struts.c'; then $(CYGPATH_W) 'panel-struts.c'; else $(CYGPATH_W) '$(srcdir)/panel-struts.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-struts.Tpo $(DEPDIR)/mate_panel-panel-struts.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-struts.c' object='mate_panel-panel-struts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-struts.obj `if test -f 'panel-struts.c'; then $(CYGPATH_W) 'panel-struts.c'; else $(CYGPATH_W) '$(srcdir)/panel-struts.c'; fi`
+
+mate_panel-panel-frame.o: panel-frame.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-frame.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-frame.Tpo -c -o mate_panel-panel-frame.o `test -f 'panel-frame.c' || echo '$(srcdir)/'`panel-frame.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-frame.Tpo $(DEPDIR)/mate_panel-panel-frame.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-frame.c' object='mate_panel-panel-frame.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-frame.o `test -f 'panel-frame.c' || echo '$(srcdir)/'`panel-frame.c
+
+mate_panel-panel-frame.obj: panel-frame.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-frame.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-frame.Tpo -c -o mate_panel-panel-frame.obj `if test -f 'panel-frame.c'; then $(CYGPATH_W) 'panel-frame.c'; else $(CYGPATH_W) '$(srcdir)/panel-frame.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-frame.Tpo $(DEPDIR)/mate_panel-panel-frame.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-frame.c' object='mate_panel-panel-frame.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-frame.obj `if test -f 'panel-frame.c'; then $(CYGPATH_W) 'panel-frame.c'; else $(CYGPATH_W) '$(srcdir)/panel-frame.c'; fi`
+
+mate_panel-panel-xutils.o: panel-xutils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-xutils.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-xutils.Tpo -c -o mate_panel-panel-xutils.o `test -f 'panel-xutils.c' || echo '$(srcdir)/'`panel-xutils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-xutils.Tpo $(DEPDIR)/mate_panel-panel-xutils.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-xutils.c' object='mate_panel-panel-xutils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-xutils.o `test -f 'panel-xutils.c' || echo '$(srcdir)/'`panel-xutils.c
+
+mate_panel-panel-xutils.obj: panel-xutils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-xutils.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-xutils.Tpo -c -o mate_panel-panel-xutils.obj `if test -f 'panel-xutils.c'; then $(CYGPATH_W) 'panel-xutils.c'; else $(CYGPATH_W) '$(srcdir)/panel-xutils.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-xutils.Tpo $(DEPDIR)/mate_panel-panel-xutils.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-xutils.c' object='mate_panel-panel-xutils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-xutils.obj `if test -f 'panel-xutils.c'; then $(CYGPATH_W) 'panel-xutils.c'; else $(CYGPATH_W) '$(srcdir)/panel-xutils.c'; fi`
+
+mate_panel-panel-multiscreen.o: panel-multiscreen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-multiscreen.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-multiscreen.Tpo -c -o mate_panel-panel-multiscreen.o `test -f 'panel-multiscreen.c' || echo '$(srcdir)/'`panel-multiscreen.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-multiscreen.Tpo $(DEPDIR)/mate_panel-panel-multiscreen.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-multiscreen.c' object='mate_panel-panel-multiscreen.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-multiscreen.o `test -f 'panel-multiscreen.c' || echo '$(srcdir)/'`panel-multiscreen.c
+
+mate_panel-panel-multiscreen.obj: panel-multiscreen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-multiscreen.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-multiscreen.Tpo -c -o mate_panel-panel-multiscreen.obj `if test -f 'panel-multiscreen.c'; then $(CYGPATH_W) 'panel-multiscreen.c'; else $(CYGPATH_W) '$(srcdir)/panel-multiscreen.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-multiscreen.Tpo $(DEPDIR)/mate_panel-panel-multiscreen.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-multiscreen.c' object='mate_panel-panel-multiscreen.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-multiscreen.obj `if test -f 'panel-multiscreen.c'; then $(CYGPATH_W) 'panel-multiscreen.c'; else $(CYGPATH_W) '$(srcdir)/panel-multiscreen.c'; fi`
+
+mate_panel-panel-a11y.o: panel-a11y.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-a11y.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-a11y.Tpo -c -o mate_panel-panel-a11y.o `test -f 'panel-a11y.c' || echo '$(srcdir)/'`panel-a11y.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-a11y.Tpo $(DEPDIR)/mate_panel-panel-a11y.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-a11y.c' object='mate_panel-panel-a11y.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-a11y.o `test -f 'panel-a11y.c' || echo '$(srcdir)/'`panel-a11y.c
+
+mate_panel-panel-a11y.obj: panel-a11y.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-a11y.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-a11y.Tpo -c -o mate_panel-panel-a11y.obj `if test -f 'panel-a11y.c'; then $(CYGPATH_W) 'panel-a11y.c'; else $(CYGPATH_W) '$(srcdir)/panel-a11y.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-a11y.Tpo $(DEPDIR)/mate_panel-panel-a11y.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-a11y.c' object='mate_panel-panel-a11y.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-a11y.obj `if test -f 'panel-a11y.c'; then $(CYGPATH_W) 'panel-a11y.c'; else $(CYGPATH_W) '$(srcdir)/panel-a11y.c'; fi`
+
+mate_panel-panel-bindings.o: panel-bindings.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-bindings.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-bindings.Tpo -c -o mate_panel-panel-bindings.o `test -f 'panel-bindings.c' || echo '$(srcdir)/'`panel-bindings.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-bindings.Tpo $(DEPDIR)/mate_panel-panel-bindings.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-bindings.c' object='mate_panel-panel-bindings.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-bindings.o `test -f 'panel-bindings.c' || echo '$(srcdir)/'`panel-bindings.c
+
+mate_panel-panel-bindings.obj: panel-bindings.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-bindings.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-bindings.Tpo -c -o mate_panel-panel-bindings.obj `if test -f 'panel-bindings.c'; then $(CYGPATH_W) 'panel-bindings.c'; else $(CYGPATH_W) '$(srcdir)/panel-bindings.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-bindings.Tpo $(DEPDIR)/mate_panel-panel-bindings.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-bindings.c' object='mate_panel-panel-bindings.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-bindings.obj `if test -f 'panel-bindings.c'; then $(CYGPATH_W) 'panel-bindings.c'; else $(CYGPATH_W) '$(srcdir)/panel-bindings.c'; fi`
+
+mate_panel-panel-profile.o: panel-profile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-profile.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-profile.Tpo -c -o mate_panel-panel-profile.o `test -f 'panel-profile.c' || echo '$(srcdir)/'`panel-profile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-profile.Tpo $(DEPDIR)/mate_panel-panel-profile.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-profile.c' object='mate_panel-panel-profile.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-profile.o `test -f 'panel-profile.c' || echo '$(srcdir)/'`panel-profile.c
+
+mate_panel-panel-profile.obj: panel-profile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-profile.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-profile.Tpo -c -o mate_panel-panel-profile.obj `if test -f 'panel-profile.c'; then $(CYGPATH_W) 'panel-profile.c'; else $(CYGPATH_W) '$(srcdir)/panel-profile.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-profile.Tpo $(DEPDIR)/mate_panel-panel-profile.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-profile.c' object='mate_panel-panel-profile.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-profile.obj `if test -f 'panel-profile.c'; then $(CYGPATH_W) 'panel-profile.c'; else $(CYGPATH_W) '$(srcdir)/panel-profile.c'; fi`
+
+mate_panel-panel-force-quit.o: panel-force-quit.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-force-quit.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-force-quit.Tpo -c -o mate_panel-panel-force-quit.o `test -f 'panel-force-quit.c' || echo '$(srcdir)/'`panel-force-quit.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-force-quit.Tpo $(DEPDIR)/mate_panel-panel-force-quit.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-force-quit.c' object='mate_panel-panel-force-quit.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-force-quit.o `test -f 'panel-force-quit.c' || echo '$(srcdir)/'`panel-force-quit.c
+
+mate_panel-panel-force-quit.obj: panel-force-quit.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-force-quit.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-force-quit.Tpo -c -o mate_panel-panel-force-quit.obj `if test -f 'panel-force-quit.c'; then $(CYGPATH_W) 'panel-force-quit.c'; else $(CYGPATH_W) '$(srcdir)/panel-force-quit.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-force-quit.Tpo $(DEPDIR)/mate_panel-panel-force-quit.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-force-quit.c' object='mate_panel-panel-force-quit.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-force-quit.obj `if test -f 'panel-force-quit.c'; then $(CYGPATH_W) 'panel-force-quit.c'; else $(CYGPATH_W) '$(srcdir)/panel-force-quit.c'; fi`
+
+mate_panel-panel-lockdown.o: panel-lockdown.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-lockdown.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-lockdown.Tpo -c -o mate_panel-panel-lockdown.o `test -f 'panel-lockdown.c' || echo '$(srcdir)/'`panel-lockdown.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-lockdown.Tpo $(DEPDIR)/mate_panel-panel-lockdown.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-lockdown.c' object='mate_panel-panel-lockdown.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-lockdown.o `test -f 'panel-lockdown.c' || echo '$(srcdir)/'`panel-lockdown.c
+
+mate_panel-panel-lockdown.obj: panel-lockdown.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-lockdown.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-lockdown.Tpo -c -o mate_panel-panel-lockdown.obj `if test -f 'panel-lockdown.c'; then $(CYGPATH_W) 'panel-lockdown.c'; else $(CYGPATH_W) '$(srcdir)/panel-lockdown.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-lockdown.Tpo $(DEPDIR)/mate_panel-panel-lockdown.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-lockdown.c' object='mate_panel-panel-lockdown.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-lockdown.obj `if test -f 'panel-lockdown.c'; then $(CYGPATH_W) 'panel-lockdown.c'; else $(CYGPATH_W) '$(srcdir)/panel-lockdown.c'; fi`
+
+mate_panel-panel-addto.o: panel-addto.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-addto.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-addto.Tpo -c -o mate_panel-panel-addto.o `test -f 'panel-addto.c' || echo '$(srcdir)/'`panel-addto.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-addto.Tpo $(DEPDIR)/mate_panel-panel-addto.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-addto.c' object='mate_panel-panel-addto.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-addto.o `test -f 'panel-addto.c' || echo '$(srcdir)/'`panel-addto.c
+
+mate_panel-panel-addto.obj: panel-addto.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-addto.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-addto.Tpo -c -o mate_panel-panel-addto.obj `if test -f 'panel-addto.c'; then $(CYGPATH_W) 'panel-addto.c'; else $(CYGPATH_W) '$(srcdir)/panel-addto.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-addto.Tpo $(DEPDIR)/mate_panel-panel-addto.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-addto.c' object='mate_panel-panel-addto.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-addto.obj `if test -f 'panel-addto.c'; then $(CYGPATH_W) 'panel-addto.c'; else $(CYGPATH_W) '$(srcdir)/panel-addto.c'; fi`
+
+mate_panel-panel-ditem-editor.o: panel-ditem-editor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-ditem-editor.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-ditem-editor.Tpo -c -o mate_panel-panel-ditem-editor.o `test -f 'panel-ditem-editor.c' || echo '$(srcdir)/'`panel-ditem-editor.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-ditem-editor.Tpo $(DEPDIR)/mate_panel-panel-ditem-editor.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-ditem-editor.c' object='mate_panel-panel-ditem-editor.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-ditem-editor.o `test -f 'panel-ditem-editor.c' || echo '$(srcdir)/'`panel-ditem-editor.c
+
+mate_panel-panel-ditem-editor.obj: panel-ditem-editor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-ditem-editor.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-ditem-editor.Tpo -c -o mate_panel-panel-ditem-editor.obj `if test -f 'panel-ditem-editor.c'; then $(CYGPATH_W) 'panel-ditem-editor.c'; else $(CYGPATH_W) '$(srcdir)/panel-ditem-editor.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-ditem-editor.Tpo $(DEPDIR)/mate_panel-panel-ditem-editor.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-ditem-editor.c' object='mate_panel-panel-ditem-editor.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-ditem-editor.obj `if test -f 'panel-ditem-editor.c'; then $(CYGPATH_W) 'panel-ditem-editor.c'; else $(CYGPATH_W) '$(srcdir)/panel-ditem-editor.c'; fi`
+
+mate_panel-panel-modules.o: panel-modules.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-modules.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-modules.Tpo -c -o mate_panel-panel-modules.o `test -f 'panel-modules.c' || echo '$(srcdir)/'`panel-modules.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-modules.Tpo $(DEPDIR)/mate_panel-panel-modules.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-modules.c' object='mate_panel-panel-modules.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-modules.o `test -f 'panel-modules.c' || echo '$(srcdir)/'`panel-modules.c
+
+mate_panel-panel-modules.obj: panel-modules.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-modules.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-modules.Tpo -c -o mate_panel-panel-modules.obj `if test -f 'panel-modules.c'; then $(CYGPATH_W) 'panel-modules.c'; else $(CYGPATH_W) '$(srcdir)/panel-modules.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-modules.Tpo $(DEPDIR)/mate_panel-panel-modules.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-modules.c' object='mate_panel-panel-modules.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-modules.obj `if test -f 'panel-modules.c'; then $(CYGPATH_W) 'panel-modules.c'; else $(CYGPATH_W) '$(srcdir)/panel-modules.c'; fi`
+
+mate_panel-mate-panel-applet-info.o: mate-panel-applet-info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-mate-panel-applet-info.o -MD -MP -MF $(DEPDIR)/mate_panel-mate-panel-applet-info.Tpo -c -o mate_panel-mate-panel-applet-info.o `test -f 'mate-panel-applet-info.c' || echo '$(srcdir)/'`mate-panel-applet-info.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-mate-panel-applet-info.Tpo $(DEPDIR)/mate_panel-mate-panel-applet-info.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applet-info.c' object='mate_panel-mate-panel-applet-info.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-mate-panel-applet-info.o `test -f 'mate-panel-applet-info.c' || echo '$(srcdir)/'`mate-panel-applet-info.c
+
+mate_panel-mate-panel-applet-info.obj: mate-panel-applet-info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-mate-panel-applet-info.obj -MD -MP -MF $(DEPDIR)/mate_panel-mate-panel-applet-info.Tpo -c -o mate_panel-mate-panel-applet-info.obj `if test -f 'mate-panel-applet-info.c'; then $(CYGPATH_W) 'mate-panel-applet-info.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applet-info.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-mate-panel-applet-info.Tpo $(DEPDIR)/mate_panel-mate-panel-applet-info.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applet-info.c' object='mate_panel-mate-panel-applet-info.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-mate-panel-applet-info.obj `if test -f 'mate-panel-applet-info.c'; then $(CYGPATH_W) 'mate-panel-applet-info.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applet-info.c'; fi`
+
+mate_panel-panel-reset.o: panel-reset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-reset.o -MD -MP -MF $(DEPDIR)/mate_panel-panel-reset.Tpo -c -o mate_panel-panel-reset.o `test -f 'panel-reset.c' || echo '$(srcdir)/'`panel-reset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-reset.Tpo $(DEPDIR)/mate_panel-panel-reset.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-reset.c' object='mate_panel-panel-reset.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-reset.o `test -f 'panel-reset.c' || echo '$(srcdir)/'`panel-reset.c
+
+mate_panel-panel-reset.obj: panel-reset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel-panel-reset.obj -MD -MP -MF $(DEPDIR)/mate_panel-panel-reset.Tpo -c -o mate_panel-panel-reset.obj `if test -f 'panel-reset.c'; then $(CYGPATH_W) 'panel-reset.c'; else $(CYGPATH_W) '$(srcdir)/panel-reset.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel-panel-reset.Tpo $(DEPDIR)/mate_panel-panel-reset.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-reset.c' object='mate_panel-panel-reset.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel-panel-reset.obj `if test -f 'panel-reset.c'; then $(CYGPATH_W) 'panel-reset.c'; else $(CYGPATH_W) '$(srcdir)/panel-reset.c'; fi`
+
+mate_panel_test_applets-panel-modules.o: panel-modules.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-panel-modules.o -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-panel-modules.Tpo -c -o mate_panel_test_applets-panel-modules.o `test -f 'panel-modules.c' || echo '$(srcdir)/'`panel-modules.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-panel-modules.Tpo $(DEPDIR)/mate_panel_test_applets-panel-modules.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-modules.c' object='mate_panel_test_applets-panel-modules.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-panel-modules.o `test -f 'panel-modules.c' || echo '$(srcdir)/'`panel-modules.c
+
+mate_panel_test_applets-panel-modules.obj: panel-modules.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-panel-modules.obj -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-panel-modules.Tpo -c -o mate_panel_test_applets-panel-modules.obj `if test -f 'panel-modules.c'; then $(CYGPATH_W) 'panel-modules.c'; else $(CYGPATH_W) '$(srcdir)/panel-modules.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-panel-modules.Tpo $(DEPDIR)/mate_panel_test_applets-panel-modules.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-modules.c' object='mate_panel_test_applets-panel-modules.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-panel-modules.obj `if test -f 'panel-modules.c'; then $(CYGPATH_W) 'panel-modules.c'; else $(CYGPATH_W) '$(srcdir)/panel-modules.c'; fi`
+
+mate_panel_test_applets-mate-panel-applet-info.o: mate-panel-applet-info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-mate-panel-applet-info.o -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Tpo -c -o mate_panel_test_applets-mate-panel-applet-info.o `test -f 'mate-panel-applet-info.c' || echo '$(srcdir)/'`mate-panel-applet-info.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Tpo $(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applet-info.c' object='mate_panel_test_applets-mate-panel-applet-info.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-mate-panel-applet-info.o `test -f 'mate-panel-applet-info.c' || echo '$(srcdir)/'`mate-panel-applet-info.c
+
+mate_panel_test_applets-mate-panel-applet-info.obj: mate-panel-applet-info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-mate-panel-applet-info.obj -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Tpo -c -o mate_panel_test_applets-mate-panel-applet-info.obj `if test -f 'mate-panel-applet-info.c'; then $(CYGPATH_W) 'mate-panel-applet-info.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applet-info.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Tpo $(DEPDIR)/mate_panel_test_applets-mate-panel-applet-info.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applet-info.c' object='mate_panel_test_applets-mate-panel-applet-info.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-mate-panel-applet-info.obj `if test -f 'mate-panel-applet-info.c'; then $(CYGPATH_W) 'mate-panel-applet-info.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applet-info.c'; fi`
+
+mate_panel_test_applets-mate-panel-applets-manager.o: mate-panel-applets-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-mate-panel-applets-manager.o -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Tpo -c -o mate_panel_test_applets-mate-panel-applets-manager.o `test -f 'mate-panel-applets-manager.c' || echo '$(srcdir)/'`mate-panel-applets-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Tpo $(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applets-manager.c' object='mate_panel_test_applets-mate-panel-applets-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-mate-panel-applets-manager.o `test -f 'mate-panel-applets-manager.c' || echo '$(srcdir)/'`mate-panel-applets-manager.c
+
+mate_panel_test_applets-mate-panel-applets-manager.obj: mate-panel-applets-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-mate-panel-applets-manager.obj -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Tpo -c -o mate_panel_test_applets-mate-panel-applets-manager.obj `if test -f 'mate-panel-applets-manager.c'; then $(CYGPATH_W) 'mate-panel-applets-manager.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applets-manager.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Tpo $(DEPDIR)/mate_panel_test_applets-mate-panel-applets-manager.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mate-panel-applets-manager.c' object='mate_panel_test_applets-mate-panel-applets-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-mate-panel-applets-manager.obj `if test -f 'mate-panel-applets-manager.c'; then $(CYGPATH_W) 'mate-panel-applets-manager.c'; else $(CYGPATH_W) '$(srcdir)/mate-panel-applets-manager.c'; fi`
+
+mate_panel_test_applets-panel-marshal.o: panel-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-panel-marshal.o -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-panel-marshal.Tpo -c -o mate_panel_test_applets-panel-marshal.o `test -f 'panel-marshal.c' || echo '$(srcdir)/'`panel-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-panel-marshal.Tpo $(DEPDIR)/mate_panel_test_applets-panel-marshal.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-marshal.c' object='mate_panel_test_applets-panel-marshal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-panel-marshal.o `test -f 'panel-marshal.c' || echo '$(srcdir)/'`panel-marshal.c
+
+mate_panel_test_applets-panel-marshal.obj: panel-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-panel-marshal.obj -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-panel-marshal.Tpo -c -o mate_panel_test_applets-panel-marshal.obj `if test -f 'panel-marshal.c'; then $(CYGPATH_W) 'panel-marshal.c'; else $(CYGPATH_W) '$(srcdir)/panel-marshal.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-panel-marshal.Tpo $(DEPDIR)/mate_panel_test_applets-panel-marshal.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-marshal.c' object='mate_panel_test_applets-panel-marshal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-panel-marshal.obj `if test -f 'panel-marshal.c'; then $(CYGPATH_W) 'panel-marshal.c'; else $(CYGPATH_W) '$(srcdir)/panel-marshal.c'; fi`
+
+mate_panel_test_applets-panel-test-applets.o: panel-test-applets.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-panel-test-applets.o -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-panel-test-applets.Tpo -c -o mate_panel_test_applets-panel-test-applets.o `test -f 'panel-test-applets.c' || echo '$(srcdir)/'`panel-test-applets.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-panel-test-applets.Tpo $(DEPDIR)/mate_panel_test_applets-panel-test-applets.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-test-applets.c' object='mate_panel_test_applets-panel-test-applets.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-panel-test-applets.o `test -f 'panel-test-applets.c' || echo '$(srcdir)/'`panel-test-applets.c
+
+mate_panel_test_applets-panel-test-applets.obj: panel-test-applets.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mate_panel_test_applets-panel-test-applets.obj -MD -MP -MF $(DEPDIR)/mate_panel_test_applets-panel-test-applets.Tpo -c -o mate_panel_test_applets-panel-test-applets.obj `if test -f 'panel-test-applets.c'; then $(CYGPATH_W) 'panel-test-applets.c'; else $(CYGPATH_W) '$(srcdir)/panel-test-applets.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mate_panel_test_applets-panel-test-applets.Tpo $(DEPDIR)/mate_panel_test_applets-panel-test-applets.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='panel-test-applets.c' object='mate_panel_test_applets-panel-test-applets.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mate_panel_test_applets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mate_panel_test_applets-panel-test-applets.obj `if test -f 'panel-test-applets.c'; then $(CYGPATH_W) 'panel-test-applets.c'; else $(CYGPATH_W) '$(srcdir)/panel-test-applets.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-desktopDATA: $(desktop_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(desktopdir)"
+ @list='$(desktop_DATA)'; test -n "$(desktopdir)" || 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)$(desktopdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(desktopdir)" || exit $$?; \
+ done
+
+uninstall-desktopDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(desktopdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(desktopdir)" && rm -f $$files
+install-entriesDATA: $(entries_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(entriesdir)" || $(MKDIR_P) "$(DESTDIR)$(entriesdir)"
+ @list='$(entries_DATA)'; test -n "$(entriesdir)" || 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)$(entriesdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(entriesdir)" || exit $$?; \
+ done
+
+uninstall-entriesDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(entries_DATA)'; test -n "$(entriesdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(entriesdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(entriesdir)" && rm -f $$files
+install-rcDATA: $(rc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(rcdir)" || $(MKDIR_P) "$(DESTDIR)$(rcdir)"
+ @list='$(rc_DATA)'; test -n "$(rcdir)" || 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)$(rcdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(rcdir)" || exit $$?; \
+ done
+
+uninstall-rcDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(rc_DATA)'; test -n "$(rcdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(rcdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(rcdir)" && rm -f $$files
+install-schemasDATA: $(schemas_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(schemasdir)" || $(MKDIR_P) "$(DESTDIR)$(schemasdir)"
+ @list='$(schemas_DATA)'; test -n "$(schemasdir)" || 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)$(schemasdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(schemasdir)" || exit $$?; \
+ done
+
+uninstall-schemasDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(schemas_DATA)'; test -n "$(schemasdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(schemasdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(schemasdir)" && 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
+
+# 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
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(entriesdir)" "$(DESTDIR)$(rcdir)" "$(DESTDIR)$(schemasdir)" "$(DESTDIR)$(uidir)"; 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)
+
+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)
+@MATECONF_SCHEMAS_INSTALL_FALSE@uninstall-local:
+@MATECONF_SCHEMAS_INSTALL_FALSE@install-data-local:
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool 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-desktopDATA \
+ install-entriesDATA install-rcDATA install-schemasDATA \
+ install-uiDATA
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libexecSCRIPTS
+
+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-binPROGRAMS uninstall-desktopDATA \
+ uninstall-entriesDATA uninstall-libexecSCRIPTS uninstall-local \
+ uninstall-rcDATA uninstall-schemasDATA uninstall-uiDATA
+
+.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-binPROGRAMS \
+ clean-generic clean-libtool ctags ctags-recursive dist-hook \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-data-local \
+ install-desktopDATA install-dvi install-dvi-am \
+ install-entriesDATA install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libexecSCRIPTS install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-rcDATA install-schemasDATA \
+ install-strip install-uiDATA 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-binPROGRAMS uninstall-desktopDATA \
+ uninstall-entriesDATA uninstall-libexecSCRIPTS uninstall-local \
+ uninstall-rcDATA uninstall-schemasDATA uninstall-uiDATA
+
+
+mate-panel-add: mate-panel-add.in Makefile
+ $(AM_V_GEN)sed \
+ -e s!\@PYTHON\@!@PYTHON@! \
+ -e s!\@MATE_PANEL_APPLETS_DIR\@!$(appletsdir)! \
+ < $< > $@
+ $(AM_V_at)chmod a+x $@
+
+panel-marshal.h: panel-marshal.list $(GLIB_GENMARSHAL)
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --header --prefix=panel_marshal > $@
+
+panel-marshal.c: panel-marshal.list $(GLIB_GENMARSHAL)
+ $(AM_V_GEN)echo "#include \"panel-marshal.h\"" > $@ && \
+ $(GLIB_GENMARSHAL) $< --body --prefix=panel_marshal >> $@
+
+panel-typebuiltins.c: @REBUILD@ $(panel_enum_headers)
+ $(AM_V_GEN)glib-mkenums \
+ --fhead "#include <glib-object.h>\n" \
+ --fhead "#include \"panel-typebuiltins.h\"\n\n" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --fprod "\n#include \"@filename@\"\n" \
+ --vhead "static const GEnumValue _@enum_name@_values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n};\n\n" \
+ --vtail "GType\n@enum_name@_get_type (void)\n{\n" \
+ --vtail " static GType type = 0;\n\n" \
+ --vtail " if (!type)\n" \
+ --vtail " type = g_enum_register_static (\"@EnumName@\", _@enum_name@_values);\n\n" \
+ --vtail " return type;\n}\n\n" \
+ $(panel_enum_headers) > $@
+
+panel-typebuiltins.h: @REBUILD@ $(panel_enum_headers)
+ $(AM_V_GEN)glib-mkenums \
+ --fhead "#ifndef __PANEL_TYPEBUILTINS_H__\n" \
+ --fhead "#define __PANEL_TYPEBUILTINS_H__ 1\n\n" \
+ --fhead "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n" \
+ --ftail "#ifdef __cplusplus\n}\n#endif\n\n" \
+ --ftail "#endif /* __PANEL_TYPEBUILTINS_H__ */\n" \
+ --fprod "\n/* --- @filename@ --- */" \
+ --eprod "#define PANEL_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \
+ --eprod "GType @enum_name@_get_type (void);\n" \
+ $(panel_enum_headers) > $@
+
+@INTLTOOL_DESKTOP_RULE@
+
+@INTLTOOL_SCHEMAS_RULE@
+
+@MATECONF_SCHEMAS_INSTALL_TRUE@install-data-local:
+@MATECONF_SCHEMAS_INSTALL_TRUE@ if test -z "$(DESTDIR)" ; then \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ for p in $(schemas_DATA) ; do \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $(top_builddir)/mate-panel/$$p ; \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ done ; \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ $(MATECONFTOOL) --direct --config-source=$(MATECONF_SCHEMA_CONFIG_SOURCE) --load $(srcdir)/panel-default-setup.entries ; \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ $(MATECONFTOOL) --direct --config-source=$(MATECONF_SCHEMA_CONFIG_SOURCE) --load $(srcdir)/panel-default-setup.entries /apps/panel ; \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ fi
+@MATECONF_SCHEMAS_INSTALL_TRUE@uninstall-local:
+@MATECONF_SCHEMAS_INSTALL_TRUE@ for p in $(schema_DATA) ; do \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-uninstall-rule $(top_builddir)/applets/ngome-panel/$$p ; \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ done
+
+dist-hook:
+ cd $(distdir) ; rm -f $(CLEANFILES)
+
+-include $(top_srcdir)/git.mk
+
+# 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/mate-panel/applet.c b/mate-panel/applet.c
new file mode 100644
index 00000000..e20e1faa
--- /dev/null
+++ b/mate-panel/applet.c
@@ -0,0 +1,1449 @@
+/* Mate panel: general applet functionality
+ * (C) 1997 the Free Software Foundation
+ *
+ * Authors: George Lebl
+ * Federico Mena
+ * Miguel de Icaza
+ */
+
+#include <config.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+
+#include <libpanel-util/panel-show.h>
+
+#include "button-widget.h"
+#include "drawer.h"
+#include "launcher.h"
+#include "panel-addto.h"
+#include "panel-mateconf.h"
+#include "panel-config-global.h"
+#include "mate-panel-applet-frame.h"
+#include "panel-action-button.h"
+#include "panel-menu-bar.h"
+#include "panel-separator.h"
+#include "panel-compatibility.h"
+#include "panel-toplevel.h"
+#include "panel-util.h"
+#include "panel-profile.h"
+#include "panel-menu-button.h"
+#include "panel-globals.h"
+#include "panel-properties-dialog.h"
+#include "panel-lockdown.h"
+
+#define SMALL_ICON_SIZE 20
+
+static GSList *registered_applets = NULL;
+static GSList *queued_position_saves = NULL;
+static guint queued_position_source = 0;
+
+
+static inline PanelWidget *
+mate_panel_applet_get_panel_widget (AppletInfo *info)
+{
+ return PANEL_WIDGET (gtk_widget_get_parent (info->widget));
+}
+
+static void
+mate_panel_applet_set_dnd_enabled (AppletInfo *info,
+ gboolean dnd_enabled)
+{
+ switch (info->type) {
+ case PANEL_OBJECT_DRAWER:
+ panel_drawer_set_dnd_enabled (info->data, dnd_enabled);
+ break;
+ case PANEL_OBJECT_MENU:
+ panel_menu_button_set_dnd_enabled (PANEL_MENU_BUTTON (info->widget),
+ dnd_enabled);
+ break;
+ case PANEL_OBJECT_LAUNCHER:
+ panel_launcher_set_dnd_enabled (info->data, dnd_enabled);
+ break;
+ case PANEL_OBJECT_APPLET:
+ break;
+ case PANEL_OBJECT_LOGOUT:
+ case PANEL_OBJECT_LOCK:
+ case PANEL_OBJECT_ACTION:
+ panel_action_button_set_dnd_enabled (PANEL_ACTION_BUTTON (info->widget),
+ dnd_enabled);
+ break;
+ case PANEL_OBJECT_MENU_BAR:
+ case PANEL_OBJECT_SEPARATOR:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+}
+
+gboolean
+mate_panel_applet_toggle_locked (AppletInfo *info)
+{
+ PanelWidget *panel_widget;
+ gboolean locked;
+
+ panel_widget = mate_panel_applet_get_panel_widget (info);
+
+ locked = panel_widget_toggle_applet_locked (panel_widget, info->widget);
+
+ mate_panel_applet_save_position (info, info->id, TRUE);
+ mate_panel_applet_set_dnd_enabled (info, !locked);
+
+ return locked;
+}
+
+static void
+mate_panel_applet_lock (GtkCheckMenuItem *menuitem,
+ AppletInfo *info)
+{
+ gboolean locked;
+
+ locked = mate_panel_applet_toggle_locked (info);
+
+ gtk_check_menu_item_set_active (menuitem, locked);
+
+ if (info->move_item)
+ gtk_widget_set_sensitive (info->move_item, !locked);
+}
+
+static void
+move_applet_callback (GtkWidget *widget, AppletInfo *info)
+{
+ GtkWidget *parent;
+ PanelWidget *panel;
+
+ g_return_if_fail (info != NULL);
+ g_return_if_fail (info->widget != NULL);
+
+ parent = gtk_widget_get_parent (info->widget);
+
+ g_return_if_fail (parent != NULL);
+ g_return_if_fail (PANEL_IS_WIDGET (parent));
+
+ panel = PANEL_WIDGET (parent);
+
+ panel_widget_applet_drag_start (panel, info->widget,
+ PW_DRAG_OFF_CENTER,
+ GDK_CURRENT_TIME);
+}
+
+/* permanently remove an applet - all non-permanent
+ * cleanups should go in mate_panel_applet_destroy()
+ */
+void
+mate_panel_applet_clean (AppletInfo *info)
+{
+ g_return_if_fail (info != NULL);
+
+ if (info->type == PANEL_OBJECT_LAUNCHER)
+ panel_launcher_delete (info->data);
+
+ if (info->widget) {
+ GtkWidget *widget = info->widget;
+
+ info->widget = NULL;
+ gtk_widget_destroy (widget);
+ }
+}
+
+static void
+mate_panel_applet_recreate_menu (AppletInfo *info)
+{
+ GList *l;
+
+ if (!info->menu)
+ return;
+
+ for (l = info->user_menu; l; l = l->next) {
+ AppletUserMenu *menu = l->data;
+
+ menu->menuitem =NULL;
+ menu->submenu =NULL;
+ }
+
+ g_object_unref (info->menu);
+ info->menu = mate_panel_applet_create_menu (info);
+}
+
+static void
+mate_panel_applet_locked_change_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GtkWidget *applet)
+{
+ MateConfValue *value;
+ gboolean locked;
+ gboolean applet_locked;
+ AppletInfo *info;
+ PanelWidget *panel_widget;
+
+ g_assert (applet != NULL);
+
+ info = (AppletInfo *) g_object_get_data (G_OBJECT (applet),
+ "applet_info");
+ if (info == NULL)
+ return;
+
+ value = mateconf_entry_get_value (entry);
+ if (value == NULL || value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ locked = mateconf_value_get_bool (value);
+
+ panel_widget = mate_panel_applet_get_panel_widget (info);
+ applet_locked = panel_widget_get_applet_locked (panel_widget,
+ info->widget);
+
+ if ((locked && applet_locked) || !(locked || applet_locked))
+ return;
+
+ mate_panel_applet_toggle_locked (info);
+
+ if (info->type == PANEL_OBJECT_APPLET)
+ mate_panel_applet_frame_sync_menu_state (MATE_PANEL_APPLET_FRAME (info->widget));
+ else
+ mate_panel_applet_recreate_menu (info);
+}
+
+static void
+applet_remove_callback (GtkWidget *widget,
+ AppletInfo *info)
+{
+
+ if (info->type == PANEL_OBJECT_DRAWER)
+ drawer_query_deletion (info->data);
+ else
+ panel_profile_delete_object (info);
+}
+
+static inline GdkScreen *
+applet_user_menu_get_screen (AppletUserMenu *menu)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = mate_panel_applet_get_panel_widget (menu->info);
+
+ return gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel));
+}
+
+static void
+applet_callback_callback (GtkWidget *widget,
+ AppletUserMenu *menu)
+{
+ GdkScreen *screen;
+
+ g_return_if_fail (menu->info != NULL);
+
+ screen = applet_user_menu_get_screen (menu);
+
+ switch (menu->info->type) {
+ case PANEL_OBJECT_LAUNCHER:
+ if (!strcmp (menu->name, "launch"))
+ launcher_launch (menu->info->data, widget);
+ else if (!strcmp (menu->name, "properties"))
+ launcher_properties (menu->info->data);
+ break;
+ case PANEL_OBJECT_DRAWER:
+ if (strcmp (menu->name, "add") == 0) {
+ Drawer *drawer = menu->info->data;
+
+ panel_addto_present (GTK_MENU_ITEM (widget),
+ panel_toplevel_get_panel_widget (drawer->toplevel));
+ } else if (strcmp (menu->name, "properties") == 0) {
+ Drawer *drawer = menu->info->data;
+
+ panel_properties_dialog_present (drawer->toplevel);
+ } else if (strcmp (menu->name, "help") == 0) {
+ panel_show_help (screen,
+ "user-guide", "gospanel-18", NULL);
+ }
+ break;
+ case PANEL_OBJECT_MENU:
+ panel_menu_button_invoke_menu (
+ PANEL_MENU_BUTTON (menu->info->widget), menu->name);
+ break;
+ case PANEL_OBJECT_ACTION:
+ case PANEL_OBJECT_LOGOUT:
+ case PANEL_OBJECT_LOCK:
+ panel_action_button_invoke_menu (
+ PANEL_ACTION_BUTTON (menu->info->widget), menu->name);
+ break;
+ case PANEL_OBJECT_MENU_BAR:
+ panel_menu_bar_invoke_menu (
+ PANEL_MENU_BAR (menu->info->widget), menu->name);
+ break;
+
+ case PANEL_OBJECT_APPLET:
+ /*
+ * Applet's menu's are handled differently
+ */
+ break;
+ case PANEL_OBJECT_SEPARATOR:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+applet_menu_show (GtkWidget *w,
+ AppletInfo *info)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = mate_panel_applet_get_panel_widget (info);
+
+ panel_toplevel_push_autohide_disabler (panel_widget->toplevel);
+}
+
+
+static void
+applet_menu_deactivate (GtkWidget *w,
+ AppletInfo *info)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = mate_panel_applet_get_panel_widget (info);
+
+ panel_toplevel_pop_autohide_disabler (panel_widget->toplevel);
+}
+
+AppletUserMenu *
+mate_panel_applet_get_callback (GList *user_menu,
+ const char *name)
+{
+ GList *l;
+
+ for (l = user_menu; l; l = l->next) {
+ AppletUserMenu *menu = l->data;
+
+ if (strcmp (menu->name, name) == 0)
+ return menu;
+ }
+
+ return NULL;
+}
+
+void
+mate_panel_applet_add_callback (AppletInfo *info,
+ const char *callback_name,
+ const char *stock_item,
+ const char *menuitem_text,
+ CallbackEnabledFunc is_enabled_func)
+{
+ AppletUserMenu *menu;
+
+ g_return_if_fail (info != NULL);
+ g_return_if_fail (mate_panel_applet_get_callback (info->user_menu,
+ callback_name) == NULL);
+
+ menu = g_new0 (AppletUserMenu, 1);
+ menu->name = g_strdup (callback_name);
+ menu->stock_item = g_strdup (stock_item);
+ menu->text = g_strdup (menuitem_text);
+ menu->is_enabled_func = is_enabled_func;
+ menu->sensitive = TRUE;
+ menu->info = info;
+ menu->menuitem = NULL;
+ menu->submenu = NULL;
+
+ info->user_menu = g_list_append (info->user_menu, menu);
+
+ mate_panel_applet_recreate_menu (info);
+}
+
+static void
+setup_an_item (AppletUserMenu *menu,
+ GtkWidget *submenu,
+ int is_submenu)
+{
+ GtkWidget *image = NULL;
+
+ menu->menuitem = gtk_image_menu_item_new_with_mnemonic (menu->text);
+ if (menu->stock_item && menu->stock_item [0]) {
+ image = gtk_image_new_from_stock (menu->stock_item,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->menuitem),
+ image);
+ }
+ gtk_widget_show (menu->menuitem);
+
+ g_signal_connect (G_OBJECT (menu->menuitem), "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &menu->menuitem);
+
+ if(submenu)
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menu->menuitem);
+
+ /*if an item not a submenu*/
+ if (!is_submenu) {
+ g_signal_connect (menu->menuitem, "activate",
+ G_CALLBACK (applet_callback_callback),
+ menu);
+ g_signal_connect (submenu, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &menu->submenu);
+ /* if the item is a submenu and doesn't have it's menu
+ created yet*/
+ } else if (!menu->submenu) {
+ menu->submenu = gtk_menu_new ();
+ }
+
+ if(menu->submenu) {
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu->menuitem),
+ menu->submenu);
+ g_signal_connect (G_OBJECT (menu->submenu), "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &menu->submenu);
+ }
+
+ gtk_widget_set_sensitive(menu->menuitem,menu->sensitive);
+}
+
+static void
+add_to_submenus (AppletInfo *info,
+ const char *path,
+ const char *name,
+ AppletUserMenu *menu,
+ GtkWidget *submenu,
+ GList *user_menu)
+{
+ char *n = g_strdup (name);
+ char *p = strchr (n, '/');
+ char *t;
+ AppletUserMenu *s_menu;
+
+ /*this is the last one*/
+ if (p == NULL) {
+ g_free (n);
+ setup_an_item (menu, submenu, FALSE);
+ return;
+ }
+
+ /*this is the last one and we are a submenu, we have already been
+ set up*/
+ if(p==(n + strlen(n) - 1)) {
+ g_free(n);
+ return;
+ }
+
+ *p = '\0';
+ p++;
+
+ t = g_strconcat (path, n, "/", NULL);
+ s_menu = mate_panel_applet_get_callback (user_menu, t);
+ /*the user did not give us this sub menu, whoops, will create an empty
+ one then*/
+ if (s_menu == NULL) {
+ s_menu = g_new0 (AppletUserMenu,1);
+ s_menu->name = g_strdup (t);
+ s_menu->stock_item = NULL;
+ s_menu->text = g_strdup (_("???"));
+ s_menu->sensitive = TRUE;
+ s_menu->info = info;
+ s_menu->menuitem = NULL;
+ s_menu->submenu = NULL;
+ info->user_menu = g_list_append (info->user_menu,s_menu);
+ user_menu = info->user_menu;
+ }
+
+ if (s_menu->submenu == NULL) {
+ s_menu->submenu = gtk_menu_new ();
+ /*a more elegant way to do this should be done
+ when I don't want to go to sleep */
+ if (s_menu->menuitem != NULL) {
+ gtk_widget_destroy (s_menu->menuitem);
+ s_menu->menuitem = NULL;
+ }
+ }
+ if (s_menu->menuitem == NULL)
+ setup_an_item (s_menu, submenu, TRUE);
+
+ add_to_submenus (info, t, p, menu, s_menu->submenu, user_menu);
+
+ g_free(t);
+ g_free(n);
+}
+
+GtkWidget *
+mate_panel_applet_create_menu (AppletInfo *info)
+{
+ GtkWidget *menu;
+ GtkWidget *menuitem;
+ GList *l;
+ PanelWidget *panel_widget;
+ gboolean added_anything = FALSE;
+
+ panel_widget = mate_panel_applet_get_panel_widget (info);
+
+ menu = g_object_ref_sink (gtk_menu_new ());
+
+ /* connect the show & deactivate signal, so that we can "disallow" and
+ * "re-allow" autohide when the menu is shown/deactivated.
+ */
+ g_signal_connect (menu, "show",
+ G_CALLBACK (applet_menu_show), info);
+ g_signal_connect (menu, "deactivate",
+ G_CALLBACK (applet_menu_deactivate), info);
+
+ for (l = info->user_menu; l; l = l->next) {
+ AppletUserMenu *user_menu = l->data;
+
+ if (user_menu->is_enabled_func && !user_menu->is_enabled_func ())
+ continue;
+
+ add_to_submenus (info, "", user_menu->name, user_menu,
+ menu, info->user_menu);
+
+ added_anything = TRUE;
+ }
+
+ if (!panel_lockdown_get_locked_down ()) {
+ GtkWidget *image;
+ gboolean locked;
+ gboolean lockable;
+ gboolean movable;
+ gboolean removable;
+
+ lockable = mate_panel_applet_lockable (info);
+ movable = mate_panel_applet_can_freely_move (info);
+ removable = panel_profile_id_lists_are_writable ();
+
+ locked = panel_widget_get_applet_locked (panel_widget, info->widget);
+
+ if (added_anything) {
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show (menuitem);
+ }
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Remove From Panel"));
+ image = gtk_image_new_from_stock (GTK_STOCK_REMOVE,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
+ image);
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (applet_remove_callback), info);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_set_sensitive (menuitem, (!locked || lockable) && removable);
+
+ menuitem = gtk_menu_item_new_with_mnemonic (_("_Move"));
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (move_applet_callback), info);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_set_sensitive (menuitem, !locked && movable);
+
+ g_assert (info->move_item == NULL);
+
+ info->move_item = menuitem;
+ g_object_add_weak_pointer (G_OBJECT (menuitem),
+ (gpointer *) &info->move_item);
+
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_check_menu_item_new_with_mnemonic (_("Loc_k To Panel"));
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
+ locked);
+ g_signal_connect (menuitem, "toggled",
+ G_CALLBACK (mate_panel_applet_lock), info);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_set_sensitive (menuitem, lockable);
+
+ added_anything = TRUE;
+ }
+
+ if ( ! added_anything) {
+ g_object_unref (menu);
+ return NULL;
+ }
+
+ return menu;
+}
+
+void
+mate_panel_applet_menu_set_recurse (GtkMenu *menu,
+ const gchar *key,
+ gpointer data)
+{
+ GList *children;
+ GList *l;
+
+ g_object_set_data (G_OBJECT (menu), key, data);
+
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+
+ for (l = children; l; l = l->next) {
+ GtkWidget *submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (l->data));
+
+ if (submenu)
+ mate_panel_applet_menu_set_recurse (
+ GTK_MENU (submenu), key, data);
+ }
+
+ g_list_free (children);
+}
+
+void
+mate_panel_applet_position_menu (GtkMenu *menu,
+ int *x,
+ int *y,
+ gboolean *push_in,
+ GtkWidget *applet)
+{
+ GtkAllocation allocation;
+ GtkRequisition requisition;
+ GdkScreen *screen;
+ GtkWidget *parent;
+ int menu_x = 0;
+ int menu_y = 0;
+ int pointer_x;
+ int pointer_y;
+
+ parent = gtk_widget_get_parent (applet);
+
+ g_return_if_fail (PANEL_IS_WIDGET (parent));
+
+ screen = gtk_widget_get_screen (applet);
+
+ gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
+
+ gdk_window_get_origin (gtk_widget_get_window (applet), &menu_x, &menu_y);
+ gtk_widget_get_pointer (applet, &pointer_x, &pointer_y);
+
+ gtk_widget_get_allocation (applet, &allocation);
+
+ if (!gtk_widget_get_has_window (applet)) {
+ menu_x += allocation.x;
+ menu_y += allocation.y;
+ }
+
+ if (PANEL_WIDGET (parent)->orient == GTK_ORIENTATION_HORIZONTAL) {
+ if (gtk_widget_get_direction (GTK_WIDGET (menu)) != GTK_TEXT_DIR_RTL) {
+ if (pointer_x < allocation.width &&
+ requisition.width < pointer_x)
+ menu_x += MIN (pointer_x,
+ allocation.width - requisition.width);
+ } else {
+ menu_x += allocation.width - requisition.width;
+ if (pointer_x > 0 && pointer_x < allocation.width &&
+ pointer_x < allocation.width - requisition.width) {
+ menu_x -= MIN (allocation.width - pointer_x,
+ allocation.width - requisition.width);
+ }
+ }
+ menu_x = MIN (menu_x, gdk_screen_get_width (screen) - requisition.width);
+
+ if (menu_y > gdk_screen_get_height (screen) / 2)
+ menu_y -= requisition.height;
+ else
+ menu_y += allocation.height;
+ } else {
+ if (pointer_y < allocation.height &&
+ requisition.height < pointer_y)
+ menu_y += MIN (pointer_y, allocation.height - requisition.height);
+ menu_y = MIN (menu_y, gdk_screen_get_height (screen) - requisition.height);
+
+ if (menu_x > gdk_screen_get_width (screen) / 2)
+ menu_x -= requisition.width;
+ else
+ menu_x += allocation.width;
+ }
+
+ *x = menu_x;
+ *y = menu_y;
+ *push_in = TRUE;
+}
+
+static void
+applet_show_menu (AppletInfo *info,
+ GdkEventButton *event)
+{
+ PanelWidget *panel_widget;
+
+ g_return_if_fail (info != NULL);
+
+ panel_widget = mate_panel_applet_get_panel_widget (info);
+
+ if (info->menu == NULL)
+ info->menu = mate_panel_applet_create_menu (info);
+
+ if (info->menu == NULL)
+ return;
+
+ mate_panel_applet_menu_set_recurse (GTK_MENU (info->menu),
+ "menu_panel",
+ panel_widget);
+
+ gtk_menu_set_screen (GTK_MENU (info->menu),
+ gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel)));
+
+ if (!gtk_widget_get_realized (info->menu))
+ gtk_widget_show (info->menu);
+
+ gtk_menu_popup (GTK_MENU (info->menu),
+ NULL,
+ NULL,
+ (GtkMenuPositionFunc) mate_panel_applet_position_menu,
+ info->widget,
+ event->button,
+ event->time);
+}
+
+static gboolean
+applet_do_popup_menu (GtkWidget *widget,
+ GdkEventButton *event,
+ AppletInfo *info)
+{
+ if (mate_panel_applet_is_in_drag ())
+ return FALSE;
+
+ if (info->type == PANEL_OBJECT_APPLET)
+ return FALSE;
+
+ applet_show_menu (info, event);
+
+ return TRUE;
+}
+
+static gboolean
+applet_popup_menu (GtkWidget *widget,
+ AppletInfo *info)
+{
+ GdkEventButton event;
+
+ event.button = 3;
+ event.time = GDK_CURRENT_TIME;
+
+ return applet_do_popup_menu (widget, &event, info);
+}
+
+static gboolean
+applet_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ AppletInfo *info)
+{
+ if (event->button == 3)
+ return applet_do_popup_menu (widget, event, info);
+
+ return FALSE;
+}
+
+static void
+mate_panel_applet_destroy (GtkWidget *widget,
+ AppletInfo *info)
+{
+ GList *l;
+
+ g_return_if_fail (info != NULL);
+
+ info->widget = NULL;
+
+ registered_applets = g_slist_remove (registered_applets, info);
+
+ queued_position_saves =
+ g_slist_remove (queued_position_saves, info);
+
+ if (info->type == PANEL_OBJECT_DRAWER) {
+ Drawer *drawer = info->data;
+
+ if (drawer->toplevel) {
+ PanelWidget *panel_widget;
+
+ panel_widget = panel_toplevel_get_panel_widget (
+ drawer->toplevel);
+ panel_widget->master_widget = NULL;
+
+ gtk_widget_destroy (GTK_WIDGET (drawer->toplevel));
+ drawer->toplevel = NULL;
+ }
+ }
+
+ if (info->type != PANEL_OBJECT_APPLET)
+ panel_lockdown_notify_remove (G_CALLBACK (mate_panel_applet_recreate_menu),
+ info);
+
+ if (info->menu)
+ g_object_unref (info->menu);
+ info->menu = NULL;
+
+ if (info->data_destroy)
+ info->data_destroy (info->data);
+ info->data = NULL;
+
+ for (l = info->user_menu; l != NULL; l = l->next) {
+ AppletUserMenu *umenu = l->data;
+
+ g_free (umenu->name);
+ g_free (umenu->stock_item);
+ g_free (umenu->text);
+
+ g_free (umenu);
+ }
+
+ g_list_free (info->user_menu);
+ info->user_menu = NULL;
+
+ g_free (info->id);
+ info->id = NULL;
+
+ g_free (info);
+}
+
+typedef struct {
+ char *id;
+ PanelObjectType type;
+ char *toplevel_id;
+ int position;
+ guint right_stick : 1;
+ guint locked : 1;
+} MatePanelAppletToLoad;
+
+/* Each time those lists get both empty,
+ * mate_panel_applet_queue_initial_unhide_toplevels() should be called */
+static GSList *mate_panel_applets_to_load = NULL;
+static GSList *mate_panel_applets_loading = NULL;
+/* We have a timeout to always unhide toplevels after a delay, in case of some
+ * blocking applet */
+#define UNHIDE_TOPLEVELS_TIMEOUT_SECONDS 5
+static guint mate_panel_applet_unhide_toplevels_timeout = 0;
+
+static gboolean mate_panel_applet_have_load_idle = FALSE;
+
+static void
+free_applet_to_load (MatePanelAppletToLoad *applet)
+{
+ g_free (applet->id);
+ applet->id = NULL;
+
+ g_free (applet->toplevel_id);
+ applet->toplevel_id = NULL;
+
+ g_free (applet);
+}
+
+gboolean
+mate_panel_applet_on_load_queue (const char *id)
+{
+ GSList *li;
+ for (li = mate_panel_applets_to_load; li != NULL; li = li->next) {
+ MatePanelAppletToLoad *applet = li->data;
+ if (strcmp (applet->id, id) == 0)
+ return TRUE;
+ }
+ for (li = mate_panel_applets_loading; li != NULL; li = li->next) {
+ MatePanelAppletToLoad *applet = li->data;
+ if (strcmp (applet->id, id) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* This doesn't do anything if the initial unhide already happened */
+static gboolean
+mate_panel_applet_queue_initial_unhide_toplevels (gpointer user_data)
+{
+ GSList *l;
+
+ if (mate_panel_applet_unhide_toplevels_timeout != 0) {
+ g_source_remove (mate_panel_applet_unhide_toplevels_timeout);
+ mate_panel_applet_unhide_toplevels_timeout = 0;
+ }
+
+ for (l = panel_toplevel_list_toplevels (); l != NULL; l = l->next)
+ panel_toplevel_queue_initial_unhide ((PanelToplevel *) l->data);
+
+ return FALSE;
+}
+
+void
+mate_panel_applet_stop_loading (const char *id)
+{
+ MatePanelAppletToLoad *applet;
+ GSList *l;
+
+ for (l = mate_panel_applets_loading; l; l = l->next) {
+ applet = l->data;
+
+ if (strcmp (applet->id, id) == 0)
+ break;
+ }
+
+ /* this can happen if we reload an applet after it crashed,
+ * for example */
+ if (l != NULL) {
+ mate_panel_applets_loading = g_slist_delete_link (mate_panel_applets_loading, l);
+ free_applet_to_load (applet);
+ }
+
+ if (mate_panel_applets_loading == NULL && mate_panel_applets_to_load == NULL)
+ mate_panel_applet_queue_initial_unhide_toplevels (NULL);
+}
+
+static gboolean
+mate_panel_applet_load_idle_handler (gpointer dummy)
+{
+ PanelObjectType applet_type;
+ MatePanelAppletToLoad *applet = NULL;
+ PanelToplevel *toplevel = NULL;
+ PanelWidget *panel_widget;
+ GSList *l;
+
+ if (!mate_panel_applets_to_load) {
+ mate_panel_applet_have_load_idle = FALSE;
+ return FALSE;
+ }
+
+ for (l = mate_panel_applets_to_load; l; l = l->next) {
+ applet = l->data;
+
+ toplevel = panel_profile_get_toplevel_by_id (applet->toplevel_id);
+ if (toplevel)
+ break;
+ }
+
+ if (!l) {
+ /* All the remaining applets don't have a panel */
+ for (l = mate_panel_applets_to_load; l; l = l->next)
+ free_applet_to_load (l->data);
+ g_slist_free (mate_panel_applets_to_load);
+ mate_panel_applets_to_load = NULL;
+ mate_panel_applet_have_load_idle = FALSE;
+
+ if (mate_panel_applets_loading == NULL) {
+ /* unhide any potential initially hidden toplevel */
+ mate_panel_applet_queue_initial_unhide_toplevels (NULL);
+ }
+
+ return FALSE;
+ }
+
+ mate_panel_applets_to_load = g_slist_delete_link (mate_panel_applets_to_load, l);
+ mate_panel_applets_loading = g_slist_append (mate_panel_applets_loading, applet);
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+
+ if (applet->right_stick) {
+ if (!panel_widget->packed)
+ applet->position = panel_widget->size - applet->position;
+ else
+ applet->position = -1;
+ }
+
+ /* We load applets asynchronously, so we specifically don't call
+ * mate_panel_applet_stop_loading() for this type. However, in case of
+ * failure during the load, we might call mate_panel_applet_stop_loading()
+ * synchronously, which will make us lose the content of the applet
+ * variable. So we save the type to be sure we always ignore the
+ * applets. */
+ applet_type = applet->type;
+
+ switch (applet_type) {
+ case PANEL_OBJECT_APPLET:
+ mate_panel_applet_frame_load_from_mateconf (
+ panel_widget,
+ applet->locked,
+ applet->position,
+ applet->id);
+ break;
+ case PANEL_OBJECT_DRAWER:
+ drawer_load_from_mateconf (panel_widget,
+ applet->locked,
+ applet->position,
+ applet->id);
+ break;
+ case PANEL_OBJECT_MENU:
+ panel_menu_button_load_from_mateconf (panel_widget,
+ applet->locked,
+ applet->position,
+ TRUE,
+ applet->id);
+ break;
+ case PANEL_OBJECT_LAUNCHER:
+ launcher_load_from_mateconf (panel_widget,
+ applet->locked,
+ applet->position,
+ applet->id);
+ break;
+ case PANEL_OBJECT_LOGOUT:
+ case PANEL_OBJECT_LOCK:
+ panel_action_button_load_compatible (
+ applet->type,
+ panel_widget,
+ applet->locked,
+ applet->position,
+ TRUE,
+ applet->id);
+ break;
+ case PANEL_OBJECT_ACTION:
+ panel_action_button_load_from_mateconf (
+ panel_widget,
+ applet->locked,
+ applet->position,
+ TRUE,
+ applet->id);
+ break;
+ case PANEL_OBJECT_MENU_BAR:
+ panel_menu_bar_load_from_mateconf (
+ panel_widget,
+ applet->locked,
+ applet->position,
+ TRUE,
+ applet->id);
+ break;
+ case PANEL_OBJECT_SEPARATOR:
+ panel_separator_load_from_mateconf (panel_widget,
+ applet->locked,
+ applet->position,
+ applet->id);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ /* Only the real applets will do a late stop_loading */
+ if (applet_type != PANEL_OBJECT_APPLET)
+ mate_panel_applet_stop_loading (applet->id);
+
+ return TRUE;
+}
+
+void
+mate_panel_applet_queue_applet_to_load (const char *id,
+ PanelObjectType type,
+ const char *toplevel_id,
+ int position,
+ gboolean right_stick,
+ gboolean locked)
+{
+ MatePanelAppletToLoad *applet;
+
+ if (!toplevel_id) {
+ g_warning ("No toplevel on which to load object '%s'\n", id);
+ return;
+ }
+
+ applet = g_new0 (MatePanelAppletToLoad, 1);
+
+ applet->id = g_strdup (id);
+ applet->type = type;
+ applet->toplevel_id = g_strdup (toplevel_id);
+ applet->position = position;
+ applet->right_stick = right_stick != FALSE;
+ applet->locked = locked != FALSE;
+
+ mate_panel_applets_to_load = g_slist_prepend (mate_panel_applets_to_load, applet);
+}
+
+static int
+mate_panel_applet_compare (const MatePanelAppletToLoad *a,
+ const MatePanelAppletToLoad *b)
+{
+ int c;
+
+ if ((c = strcmp (a->toplevel_id, b->toplevel_id)))
+ return c;
+ else if (a->right_stick != b->right_stick)
+ return b->right_stick ? -1 : 1;
+ else
+ return a->position - b->position;
+}
+
+void
+mate_panel_applet_load_queued_applets (gboolean initial_load)
+{
+ if (!mate_panel_applets_to_load) {
+ mate_panel_applet_queue_initial_unhide_toplevels (NULL);
+ return;
+ }
+
+ if (mate_panel_applets_to_load && mate_panel_applet_unhide_toplevels_timeout == 0) {
+ /* Install a timeout to make sure we don't block the
+ * unhiding because of an applet that doesn't load */
+ mate_panel_applet_unhide_toplevels_timeout =
+ g_timeout_add_seconds (UNHIDE_TOPLEVELS_TIMEOUT_SECONDS,
+ mate_panel_applet_queue_initial_unhide_toplevels,
+ NULL);
+ }
+
+ mate_panel_applets_to_load = g_slist_sort (mate_panel_applets_to_load,
+ (GCompareFunc) mate_panel_applet_compare);
+
+ if ( ! mate_panel_applet_have_load_idle) {
+ /* on panel startup, we don't care about redraws of the
+ * toplevels since they are hidden, so we give a higher
+ * priority to loading of applets */
+ if (initial_load)
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+ mate_panel_applet_load_idle_handler,
+ NULL, NULL);
+ else
+ g_idle_add (mate_panel_applet_load_idle_handler, NULL);
+
+ mate_panel_applet_have_load_idle = TRUE;
+ }
+}
+
+static const char* mate_panel_applet_get_toplevel_id(AppletInfo* applet)
+{
+ PanelWidget* panel_widget;
+
+ g_return_val_if_fail(applet != NULL, NULL);
+ g_return_val_if_fail(GTK_IS_WIDGET(applet->widget), NULL);
+
+ panel_widget = mate_panel_applet_get_panel_widget(applet);
+
+ if (!panel_widget)
+ {
+ return NULL;
+ }
+
+ return panel_profile_get_toplevel_id(panel_widget->toplevel);
+}
+
+static gboolean
+mate_panel_applet_position_save_timeout (gpointer dummy)
+{
+ GSList *l;
+
+ queued_position_source = 0;
+
+ for (l = queued_position_saves; l; l = l->next) {
+ AppletInfo *info = l->data;
+
+ mate_panel_applet_save_position (info, info->id, TRUE);
+ }
+
+ g_slist_free (queued_position_saves);
+ queued_position_saves = NULL;
+
+ return FALSE;
+}
+
+void
+mate_panel_applet_save_position (AppletInfo *applet_info,
+ const char *id,
+ gboolean immediate)
+{
+ PanelMateConfKeyType key_type;
+ MateConfClient *client;
+ PanelWidget *panel_widget;
+ const char *key;
+ const char *toplevel_id;
+ char *old_toplevel_id;
+ gboolean right_stick;
+ gboolean locked;
+ int position;
+
+ g_return_if_fail (applet_info != NULL);
+
+ if (!immediate) {
+ if (!queued_position_source)
+ queued_position_source =
+ g_timeout_add_seconds (1,
+ (GSourceFunc) mate_panel_applet_position_save_timeout,
+ NULL);
+
+ if (!g_slist_find (queued_position_saves, applet_info))
+ queued_position_saves =
+ g_slist_prepend (queued_position_saves, applet_info);
+
+ return;
+ }
+
+ if (!(toplevel_id = mate_panel_applet_get_toplevel_id (applet_info)))
+ return;
+
+ client = panel_mateconf_get_client ();
+
+ key_type = applet_info->type == PANEL_OBJECT_APPLET ? PANEL_MATECONF_APPLETS : PANEL_MATECONF_OBJECTS;
+
+ panel_widget = mate_panel_applet_get_panel_widget (applet_info);
+
+ /* FIXME: Instead of getting keys, comparing and setting, there
+ should be a dirty flag */
+
+ key = panel_mateconf_full_key (key_type, id, "toplevel_id");
+ old_toplevel_id = mateconf_client_get_string (client, key, NULL);
+ if (old_toplevel_id == NULL || strcmp (old_toplevel_id, toplevel_id) != 0)
+ mateconf_client_set_string (client, key, toplevel_id, NULL);
+ g_free (old_toplevel_id);
+
+ /* Note: changing some properties of the panel that may not be locked down
+ (e.g. background) can change the state of the "panel_right_stick" and
+ "position" properties of an applet that may in fact be locked down.
+ So check if these are writable before attempting to write them */
+
+ right_stick = panel_is_applet_right_stick (applet_info->widget) ? 1 : 0;
+ key = panel_mateconf_full_key (
+ key_type, id, "panel_right_stick");
+ if (mateconf_client_key_is_writable (client, key, NULL) &&
+ (mateconf_client_get_bool (client, key, NULL) ? 1 : 0) != right_stick)
+ mateconf_client_set_bool (client, key, right_stick, NULL);
+
+ position = mate_panel_applet_get_position (applet_info);
+ if (right_stick && !panel_widget->packed)
+ position = panel_widget->size - position;
+
+ key = panel_mateconf_full_key (key_type, id, "position");
+ if (mateconf_client_key_is_writable (client, key, NULL) &&
+ mateconf_client_get_int (client, key, NULL) != position)
+ mateconf_client_set_int (client, key, position, NULL);
+
+ locked = panel_widget_get_applet_locked (panel_widget, applet_info->widget) ? 1 : 0;
+ key = panel_mateconf_full_key (key_type, id, "locked");
+ if (mateconf_client_get_bool (client, key, NULL) ? 1 : 0 != locked)
+ mateconf_client_set_bool (client, key, locked, NULL);
+}
+
+const char *
+mate_panel_applet_get_id (AppletInfo *info)
+{
+ if (!info)
+ return NULL;
+
+ return info->id;
+}
+
+const char *
+mate_panel_applet_get_id_by_widget (GtkWidget *applet_widget)
+{
+ GSList *l;
+
+ if (!applet_widget)
+ return NULL;
+
+ for (l = registered_applets; l; l = l->next) {
+ AppletInfo *info = l->data;
+
+ if (info->widget == applet_widget)
+ return info->id;
+ }
+
+ return NULL;
+}
+
+AppletInfo *
+mate_panel_applet_get_by_id (const char *id)
+{
+ GSList *l;
+
+ for (l = registered_applets; l; l = l->next) {
+ AppletInfo *info = l->data;
+
+ if (!strcmp (info->id, id))
+ return info;
+ }
+
+ return NULL;
+}
+
+GSList *
+mate_panel_applet_list_applets (void)
+{
+ return registered_applets;
+}
+
+AppletInfo *
+mate_panel_applet_get_by_type (PanelObjectType object_type, GdkScreen *screen)
+{
+ GSList *l;
+
+ for (l = registered_applets; l; l = l->next) {
+ AppletInfo *info = l->data;
+
+ if (info->type == object_type) {
+ if (screen) {
+ if (screen == gtk_widget_get_screen (info->widget))
+ return info;
+ } else
+ return info;
+ }
+ }
+
+ return NULL;
+}
+
+AppletInfo *
+mate_panel_applet_register (GtkWidget *applet,
+ gpointer data,
+ GDestroyNotify data_destroy,
+ PanelWidget *panel,
+ gboolean locked,
+ gint pos,
+ gboolean exactpos,
+ PanelObjectType type,
+ const char *id)
+{
+ AppletInfo *info;
+ const char *key;
+
+ g_return_val_if_fail (applet != NULL && panel != NULL, NULL);
+
+ if (gtk_widget_get_has_window (applet))
+ gtk_widget_set_events (applet, (gtk_widget_get_events (applet) |
+ APPLET_EVENT_MASK) &
+ ~( GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK));
+
+ info = g_new0 (AppletInfo, 1);
+ info->type = type;
+ info->widget = applet;
+ info->menu = NULL;
+ info->data = data;
+ info->data_destroy = data_destroy;
+ info->user_menu = NULL;
+ info->move_item = NULL;
+ info->id = g_strdup (id);
+
+ g_object_set_data (G_OBJECT (applet), "applet_info", info);
+
+ if (type != PANEL_OBJECT_APPLET)
+ panel_lockdown_notify_add (G_CALLBACK (mate_panel_applet_recreate_menu),
+ info);
+
+ key = panel_mateconf_full_key ((type == PANEL_OBJECT_APPLET) ?
+ PANEL_MATECONF_APPLETS : PANEL_MATECONF_OBJECTS,
+ id, "locked");
+ panel_mateconf_notify_add_while_alive (key,
+ (MateConfClientNotifyFunc) mate_panel_applet_locked_change_notify,
+ G_OBJECT (applet));
+
+ if (type == PANEL_OBJECT_DRAWER) {
+ Drawer *drawer = data;
+ PanelWidget *assoc_panel;
+
+ assoc_panel = panel_toplevel_get_panel_widget (drawer->toplevel);
+
+ g_object_set_data (G_OBJECT (applet),
+ MATE_PANEL_APPLET_ASSOC_PANEL_KEY, assoc_panel);
+ assoc_panel->master_widget = applet;
+ g_object_add_weak_pointer (
+ G_OBJECT (applet), (gpointer *) &assoc_panel->master_widget);
+ }
+
+ g_object_set_data (G_OBJECT (applet),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS, NULL);
+
+ registered_applets = g_slist_append (registered_applets, info);
+
+ if (panel_widget_add (panel, applet, locked, pos, exactpos) == -1 &&
+ panel_widget_add (panel, applet, locked, 0, TRUE) == -1) {
+ GSList *l;
+
+ for (l = panels; l; l = l->next) {
+ panel = PANEL_WIDGET (l->data);
+
+ if (panel_widget_add (panel, applet, locked, 0, TRUE) != -1)
+ break;
+ }
+
+ if (!l) {
+ g_warning (_("Cannot find an empty spot"));
+ panel_profile_delete_object (info);
+ return NULL;
+ }
+ }
+
+ if (BUTTON_IS_WIDGET (applet) ||
+ gtk_widget_get_has_window (applet)) {
+ g_signal_connect (applet, "button_press_event",
+ G_CALLBACK (applet_button_press),
+ info);
+
+ g_signal_connect (applet, "popup_menu",
+ G_CALLBACK (applet_popup_menu),
+ info);
+ }
+
+ g_signal_connect (applet, "destroy",
+ G_CALLBACK (mate_panel_applet_destroy),
+ info);
+
+ mate_panel_applet_set_dnd_enabled (info, !locked);
+
+ gtk_widget_show_all (applet);
+
+ orientation_change (info, panel);
+ size_change (info, panel);
+ back_change (info, panel);
+
+ if (type != PANEL_OBJECT_APPLET)
+ gtk_widget_grab_focus (applet);
+ else
+ gtk_widget_child_focus (applet, GTK_DIR_TAB_FORWARD);
+
+ return info;
+}
+
+int
+mate_panel_applet_get_position (AppletInfo *applet)
+{
+ AppletData *applet_data;
+
+ g_return_val_if_fail (applet != NULL, 0);
+ g_return_val_if_fail (G_IS_OBJECT (applet->widget), 0);
+
+ applet_data = g_object_get_data (G_OBJECT (applet->widget), MATE_PANEL_APPLET_DATA);
+
+ return applet_data->pos;
+}
+
+gboolean
+mate_panel_applet_can_freely_move (AppletInfo *applet)
+{
+ MateConfClient *client;
+ PanelMateConfKeyType key_type;
+ const char *key;
+
+ if (panel_lockdown_get_locked_down ())
+ return FALSE;
+
+ client = panel_mateconf_get_client ();
+
+ key_type = (applet->type == PANEL_OBJECT_APPLET) ? PANEL_MATECONF_APPLETS : PANEL_MATECONF_OBJECTS;
+
+ key = panel_mateconf_full_key (key_type, applet->id, "position");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ key = panel_mateconf_full_key (key_type, applet->id, "toplevel_id");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ key = panel_mateconf_full_key (key_type, applet->id, "panel_right_stick");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+mate_panel_applet_lockable (AppletInfo *applet)
+{
+ MateConfClient *client;
+ PanelMateConfKeyType key_type;
+ const char *key;
+
+ if (panel_lockdown_get_locked_down ())
+ return FALSE;
+
+ client = panel_mateconf_get_client ();
+
+ key_type = (applet->type == PANEL_OBJECT_APPLET) ? PANEL_MATECONF_APPLETS : PANEL_MATECONF_OBJECTS;
+
+ key = panel_mateconf_full_key (key_type, applet->id, "locked");
+
+ return mateconf_client_key_is_writable (client, key, NULL);
+}
diff --git a/mate-panel/applet.h b/mate-panel/applet.h
new file mode 100644
index 00000000..531e7e20
--- /dev/null
+++ b/mate-panel/applet.h
@@ -0,0 +1,119 @@
+#ifndef APPLET_H
+#define APPLET_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include "panel-widget.h"
+#include "panel-mateconf.h"
+#include "panel-enums.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define APPLET_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \
+ GDK_BUTTON_RELEASE_MASK | \
+ GDK_POINTER_MOTION_MASK | \
+ GDK_POINTER_MOTION_HINT_MASK)
+typedef struct {
+ PanelObjectType type;
+ GtkWidget *widget;
+
+ GtkWidget *menu;
+ GtkWidget *move_item;
+ GList *user_menu;
+
+ gpointer data;
+ GDestroyNotify data_destroy;
+
+ char *id;
+} AppletInfo;
+
+typedef gboolean (* CallbackEnabledFunc) (void);
+
+typedef struct {
+ char *name;
+ char *stock_item;
+ char *text;
+
+ CallbackEnabledFunc is_enabled_func;
+
+ int sensitive;
+ AppletInfo *info;
+
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+} AppletUserMenu;
+
+AppletInfo *mate_panel_applet_register (GtkWidget *applet,
+ gpointer data,
+ GDestroyNotify data_destroy,
+ PanelWidget *panel,
+ gboolean locked,
+ gint pos,
+ gboolean exactpos,
+ PanelObjectType type,
+ const char *id);
+void mate_panel_applet_stop_loading (const char *id);
+
+const char *mate_panel_applet_get_id (AppletInfo *info);
+const char *mate_panel_applet_get_id_by_widget (GtkWidget *widget);
+AppletInfo *mate_panel_applet_get_by_id (const char *id);
+AppletInfo *mate_panel_applet_get_by_type (PanelObjectType object_type, GdkScreen *screen);
+
+GSList *mate_panel_applet_list_applets (void);
+
+void mate_panel_applet_clean (AppletInfo *info);
+
+void mate_panel_applet_queue_applet_to_load (const char *id,
+ PanelObjectType type,
+ const char *toplevel_id,
+ int position,
+ gboolean right_stick,
+ gboolean locked);
+void mate_panel_applet_load_queued_applets (gboolean initial_load);
+gboolean mate_panel_applet_on_load_queue (const char *id);
+
+
+void mate_panel_applet_add_callback (AppletInfo *info,
+ const gchar *callback_name,
+ const gchar *stock_item,
+ const gchar *menuitem_text,
+ CallbackEnabledFunc is_enabled_func);
+
+AppletUserMenu *mate_panel_applet_get_callback (GList *user_menu,
+ const gchar *name);
+
+
+void mate_panel_applet_save_position (AppletInfo *applet_info,
+ const char *id,
+ gboolean immediate);
+
+int mate_panel_applet_get_position (AppletInfo *applet);
+
+/* True if all the keys relevant to moving are writable
+ (position, toplevel_id, panel_right_stick) */
+gboolean mate_panel_applet_can_freely_move (AppletInfo *applet);
+
+/* True if the locked flag is writable */
+gboolean mate_panel_applet_lockable (AppletInfo *applet);
+
+GtkWidget *mate_panel_applet_create_menu (AppletInfo *info);
+
+void mate_panel_applet_menu_set_recurse (GtkMenu *menu,
+ const gchar *key,
+ gpointer data);
+
+gboolean mate_panel_applet_toggle_locked (AppletInfo *info);
+
+void mate_panel_applet_position_menu (GtkMenu *menu,
+ int *x,
+ int *y,
+ gboolean *push_in,
+ GtkWidget *applet);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mate-panel/button-widget.c b/mate-panel/button-widget.c
new file mode 100644
index 00000000..6f2fd6b8
--- /dev/null
+++ b/mate-panel/button-widget.c
@@ -0,0 +1,902 @@
+#include <config.h>
+#include <math.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "button-widget.h"
+#include "panel-widget.h"
+#include "panel-types.h"
+#include "panel-util.h"
+#include "panel-config-global.h"
+#include "panel-marshal.h"
+#include "panel-typebuiltins.h"
+#include "panel-globals.h"
+
+#define BUTTON_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUTTON_TYPE_WIDGET, ButtonWidgetPrivate))
+
+struct _ButtonWidgetPrivate {
+ GtkIconTheme *icon_theme;
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *pixbuf_hc;
+
+ char *filename;
+
+ PanelOrientation orientation;
+
+ int size;
+
+ guint activatable : 1;
+ guint ignore_leave : 1;
+ guint arrow : 1;
+ guint dnd_highlight : 1;
+};
+
+static void button_widget_icon_theme_changed (ButtonWidget *button);
+static void button_widget_reload_pixbuf (ButtonWidget *button);
+
+enum {
+ PROP_0,
+ PROP_ACTIVATABLE,
+ PROP_IGNORE_LEAVE,
+ PROP_HAS_ARROW,
+ PROP_DND_HIGHLIGHT,
+ PROP_ORIENTATION,
+ PROP_ICON_NAME
+};
+
+#define BUTTON_WIDGET_DISPLACEMENT 2
+
+G_DEFINE_TYPE (ButtonWidget, button_widget, GTK_TYPE_BUTTON)
+
+/* colorshift a pixbuf */
+static void
+do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift)
+{
+ gint i, j;
+ gint width, height, has_alpha, srcrowstride, destrowstride;
+ guchar *target_pixels;
+ guchar *original_pixels;
+ guchar *pixsrc;
+ guchar *pixdest;
+ int val;
+ guchar r,g,b;
+
+ has_alpha = gdk_pixbuf_get_has_alpha (src);
+ width = gdk_pixbuf_get_width (src);
+ height = gdk_pixbuf_get_height (src);
+ srcrowstride = gdk_pixbuf_get_rowstride (src);
+ destrowstride = gdk_pixbuf_get_rowstride (dest);
+ target_pixels = gdk_pixbuf_get_pixels (dest);
+ original_pixels = gdk_pixbuf_get_pixels (src);
+
+ for (i = 0; i < height; i++) {
+ pixdest = target_pixels + i*destrowstride;
+ pixsrc = original_pixels + i*srcrowstride;
+ for (j = 0; j < width; j++) {
+ r = *(pixsrc++);
+ g = *(pixsrc++);
+ b = *(pixsrc++);
+ val = r + shift;
+ *(pixdest++) = CLAMP(val, 0, 255);
+ val = g + shift;
+ *(pixdest++) = CLAMP(val, 0, 255);
+ val = b + shift;
+ *(pixdest++) = CLAMP(val, 0, 255);
+ if (has_alpha)
+ *(pixdest++) = *(pixsrc++);
+ }
+ }
+}
+
+static GdkPixbuf *
+make_hc_pixbuf (GdkPixbuf *pb)
+{
+ GdkPixbuf *new;
+
+ if (!pb)
+ return NULL;
+
+ new = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pb),
+ gdk_pixbuf_get_has_alpha (pb),
+ gdk_pixbuf_get_bits_per_sample (pb),
+ gdk_pixbuf_get_width (pb),
+ gdk_pixbuf_get_height (pb));
+ do_colorshift (new, pb, 30);
+
+ return new;
+}
+
+static void
+button_widget_realize(GtkWidget *widget)
+{
+ GtkAllocation allocation;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GtkButton *button;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (BUTTON_IS_WIDGET (widget));
+
+ button = GTK_BUTTON (widget);
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ gtk_widget_set_window (widget, gtk_widget_get_parent_window (widget));
+ g_object_ref (gtk_widget_get_window (widget));
+
+ button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes,
+ attributes_mask);
+ gdk_window_set_user_data (button->event_window, widget);
+
+ widget->style = gtk_style_attach (widget->style, gtk_widget_get_window (widget));
+
+ BUTTON_WIDGET (widget)->priv->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
+ g_signal_connect_object (BUTTON_WIDGET (widget)->priv->icon_theme,
+ "changed",
+ G_CALLBACK (button_widget_icon_theme_changed),
+ button,
+ G_CONNECT_SWAPPED);
+
+ button_widget_reload_pixbuf (BUTTON_WIDGET (widget));
+}
+
+static void
+button_widget_unrealize (GtkWidget *widget)
+{
+ GtkButton *button;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (BUTTON_IS_WIDGET (widget));
+
+ button = GTK_BUTTON (widget);
+
+ if (button->event_window != NULL) {
+ gdk_window_set_user_data (button->event_window, NULL);
+ gdk_window_destroy (button->event_window);
+ button->event_window = NULL;
+ }
+
+ GTK_WIDGET_CLASS (button_widget_parent_class)->unrealize (widget);
+}
+
+static void
+button_widget_unset_pixbufs (ButtonWidget *button)
+{
+ if (button->priv->pixbuf)
+ g_object_unref (button->priv->pixbuf);
+ button->priv->pixbuf = NULL;
+
+ if (button->priv->pixbuf_hc)
+ g_object_unref (button->priv->pixbuf_hc);
+ button->priv->pixbuf_hc = NULL;
+}
+
+static void
+button_widget_reload_pixbuf (ButtonWidget *button)
+{
+ button_widget_unset_pixbufs (button);
+
+ if (button->priv->size <= 1 || button->priv->icon_theme == NULL)
+ return;
+
+ if (button->priv->filename != NULL &&
+ button->priv->filename [0] != '\0') {
+ char *error = NULL;
+
+ button->priv->pixbuf =
+ panel_load_icon (button->priv->icon_theme,
+ button->priv->filename,
+ button->priv->size,
+ button->priv->orientation & PANEL_VERTICAL_MASK ? button->priv->size : -1,
+ button->priv->orientation & PANEL_HORIZONTAL_MASK ? button->priv->size : -1,
+ &error);
+ if (error) {
+ //FIXME: this is not rendered at button->priv->size
+ button->priv->pixbuf =
+ gtk_widget_render_icon (GTK_WIDGET (button),
+ GTK_STOCK_MISSING_IMAGE,
+ (GtkIconSize) -1, NULL);
+ g_free (error);
+ }
+ }
+
+ button->priv->pixbuf_hc = make_hc_pixbuf (button->priv->pixbuf);
+
+ gtk_widget_queue_resize (GTK_WIDGET (button));
+}
+
+static void
+button_widget_icon_theme_changed (ButtonWidget *button)
+{
+ if (button->priv->filename != NULL)
+ button_widget_reload_pixbuf (button);
+}
+
+static void
+button_widget_finalize (GObject *object)
+{
+ ButtonWidget *button = (ButtonWidget *) object;
+
+ button_widget_unset_pixbufs (button);
+
+ g_free (button->priv->filename);
+ button->priv->filename = NULL;
+
+ G_OBJECT_CLASS (button_widget_parent_class)->finalize (object);
+}
+
+static void
+button_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ButtonWidget *button;
+
+ g_return_if_fail (BUTTON_IS_WIDGET (object));
+
+ button = BUTTON_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVATABLE:
+ g_value_set_boolean (value, button->priv->activatable);
+ break;
+ case PROP_IGNORE_LEAVE:
+ g_value_set_boolean (value, button->priv->ignore_leave);
+ break;
+ case PROP_HAS_ARROW:
+ g_value_set_boolean (value, button->priv->arrow);
+ break;
+ case PROP_DND_HIGHLIGHT:
+ g_value_set_boolean (value, button->priv->dnd_highlight);
+ break;
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, button->priv->orientation);
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value, button->priv->filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+button_widget_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ButtonWidget *button;
+
+ g_return_if_fail (BUTTON_IS_WIDGET (object));
+
+ button = BUTTON_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVATABLE:
+ button_widget_set_activatable (button, g_value_get_boolean (value));
+ break;
+ case PROP_IGNORE_LEAVE:
+ button_widget_set_ignore_leave (button, g_value_get_boolean (value));
+ break;
+ case PROP_HAS_ARROW:
+ button_widget_set_has_arrow (button, g_value_get_boolean (value));
+ break;
+ case PROP_DND_HIGHLIGHT:
+ button_widget_set_dnd_highlight (button, g_value_get_boolean (value));
+ break;
+ case PROP_ORIENTATION:
+ button_widget_set_orientation (button, g_value_get_enum (value));
+ break;
+ case PROP_ICON_NAME:
+ button_widget_set_icon_name (button, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GtkArrowType
+calc_arrow (PanelOrientation orientation,
+ int button_width,
+ int button_height,
+ int *x,
+ int *y,
+ int *width,
+ int *height)
+{
+ GtkArrowType retval = GTK_ARROW_UP;
+ double scale;
+
+ scale = (orientation & PANEL_HORIZONTAL_MASK ? button_height : button_width) / 48.0;
+
+ *width = 12 * scale;
+ *height = 12 * scale;
+
+ switch (orientation) {
+ case PANEL_ORIENTATION_TOP:
+ *x = scale * 3;
+ *y = scale * (48 - 13);
+ retval = GTK_ARROW_DOWN;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ *x = scale * (48 - 13);
+ *y = scale * 1;
+ retval = GTK_ARROW_UP;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ *x = scale * (48 - 13);
+ *y = scale * 3;
+ retval = GTK_ARROW_RIGHT;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ *x = scale * 1;
+ *y = scale * 3;
+ retval = GTK_ARROW_LEFT;
+ break;
+ }
+
+ return retval;
+}
+
+static gboolean
+button_widget_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ ButtonWidget *button_widget;
+ GtkButton *button;
+ GdkWindow *window;
+ GtkAllocation allocation;
+ GdkRectangle area, image_bound;
+ GtkStyle *style;
+ int off;
+ int x, y, w, h;
+ GdkPixbuf *pb = NULL;
+
+ g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (!gtk_widget_get_visible (widget) || !gtk_widget_get_mapped (widget))
+ return FALSE;
+
+ button_widget = BUTTON_WIDGET (widget);
+
+ if (!button_widget->priv->pixbuf_hc && !button_widget->priv->pixbuf)
+ return FALSE;
+
+ button = GTK_BUTTON (widget);
+ window = gtk_widget_get_window (widget);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ /* offset for pressed buttons */
+ off = (button_widget->priv->activatable &&
+ button->in_button && button->button_down) ?
+ BUTTON_WIDGET_DISPLACEMENT * allocation.height / 48.0 : 0;
+
+ if (!button_widget->priv->activatable) {
+ pb = gdk_pixbuf_copy (button_widget->priv->pixbuf);
+ gdk_pixbuf_saturate_and_pixelate (button_widget->priv->pixbuf,
+ pb,
+ 0.8,
+ TRUE);
+ } else if (panel_global_config_get_highlight_when_over () &&
+ (button->in_button || gtk_widget_has_focus (widget)))
+ pb = g_object_ref (button_widget->priv->pixbuf_hc);
+ else
+ pb = g_object_ref (button_widget->priv->pixbuf);
+
+ g_assert (pb != NULL);
+
+ w = gdk_pixbuf_get_width (pb);
+ h = gdk_pixbuf_get_height (pb);
+ x = allocation.x + off + (allocation.width - w)/2;
+ y = allocation.y + off + (allocation.height - h)/2;
+
+ image_bound.x = x;
+ image_bound.y = y;
+ image_bound.width = w;
+ image_bound.height = h;
+
+ area = event->area;
+
+ if (gdk_rectangle_intersect (&area, &allocation, &area) &&
+ gdk_rectangle_intersect (&image_bound, &area, &image_bound))
+ gdk_draw_pixbuf (window, NULL, pb,
+ image_bound.x - x, image_bound.y - y,
+ image_bound.x, image_bound.y,
+ image_bound.width, image_bound.height,
+ GDK_RGB_DITHER_NORMAL,
+ 0, 0);
+
+ g_object_unref (pb);
+
+ style = gtk_widget_get_style (widget);
+
+ if (button_widget->priv->arrow) {
+ GtkArrowType arrow_type;
+ int x, y, width, height;
+
+ x = y = width = height = -1;
+
+ arrow_type = calc_arrow (button_widget->priv->orientation,
+ allocation.width,
+ allocation.height,
+ &x,
+ &y,
+ &width,
+ &height);
+
+ gtk_paint_arrow (style,
+ window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE,
+ NULL,
+ widget,
+ "panel-button",
+ arrow_type,
+ TRUE,
+ allocation.x + x,
+ allocation.y + y,
+ width,
+ height);
+ }
+
+ if (button_widget->priv->dnd_highlight) {
+ gdk_draw_rectangle(window, style->black_gc, FALSE,
+ allocation.x, allocation.y,
+ allocation.width - 1,
+ allocation.height - 1);
+ }
+
+ if (gtk_widget_has_focus (widget)) {
+ gint focus_width, focus_pad;
+ gint x, y, width, height;
+
+ gtk_widget_style_get (widget,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ NULL);
+ x = allocation.x + focus_pad;
+ y = allocation.y + focus_pad;
+ width = allocation.width - 2 * focus_pad;
+ height = allocation.height - 2 * focus_pad;
+ gtk_paint_focus (style, window,
+ GTK_STATE_NORMAL,
+ &event->area, widget, "button",
+ x, y, width, height);
+ }
+
+ return FALSE;
+}
+
+static void
+button_widget_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ ButtonWidget *button_widget = BUTTON_WIDGET (widget);
+
+ if (button_widget->priv->pixbuf) {
+ requisition->width = gdk_pixbuf_get_width (button_widget->priv->pixbuf);
+ requisition->height = gdk_pixbuf_get_height (button_widget->priv->pixbuf);
+ }
+}
+
+static void
+button_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ ButtonWidget *button_widget = BUTTON_WIDGET (widget);
+ GtkButton *button = GTK_BUTTON (widget);
+ int size;
+
+ if (button_widget->priv->orientation & PANEL_HORIZONTAL_MASK)
+ size = allocation->height;
+ else
+ size = allocation->width;
+
+ if (size < 22)
+ size = 16;
+ else if (size < 24)
+ size = 22;
+ else if (size < 32)
+ size = 24;
+ else if (size < 48)
+ size = 32;
+ else
+ size = 48;
+
+ if (button_widget->priv->size != size) {
+ button_widget->priv->size = size;
+
+ button_widget_reload_pixbuf (button_widget);
+ }
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (gtk_widget_get_realized (widget)) {
+ gdk_window_move_resize (button->event_window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+ }
+}
+
+static void
+button_widget_activate (GtkButton *button)
+{
+ ButtonWidget *button_widget = BUTTON_WIDGET (button);
+
+ if (!button_widget->priv->activatable)
+ return;
+
+ if (GTK_BUTTON_CLASS (button_widget_parent_class)->activate)
+ GTK_BUTTON_CLASS (button_widget_parent_class)->activate (button);
+}
+
+static gboolean
+button_widget_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->button == 1 && BUTTON_WIDGET (widget)->priv->activatable &&
+ /* we don't want to have two/three "click" events for double/triple
+ * clicks. FIXME: this is only a workaround, waiting for bug 159101 */
+ event->type == GDK_BUTTON_PRESS)
+ return GTK_WIDGET_CLASS (button_widget_parent_class)->button_press_event (widget, event);
+
+ return FALSE;
+}
+
+static gboolean
+button_widget_enter_notify (GtkWidget *widget, GdkEventCrossing *event)
+{
+ gboolean in_button;
+
+ g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
+
+ in_button = GTK_BUTTON (widget)->in_button;
+ GTK_WIDGET_CLASS (button_widget_parent_class)->enter_notify_event (widget, event);
+ if (in_button != GTK_BUTTON (widget)->in_button &&
+ panel_global_config_get_highlight_when_over ())
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gboolean
+button_widget_leave_notify (GtkWidget *widget, GdkEventCrossing *event)
+{
+ gboolean in_button;
+
+ g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
+
+ in_button = GTK_BUTTON (widget)->in_button;
+ GTK_WIDGET_CLASS (button_widget_parent_class)->leave_notify_event (widget, event);
+ if (in_button != GTK_BUTTON (widget)->in_button &&
+ panel_global_config_get_highlight_when_over ())
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static void
+button_widget_init (ButtonWidget *button)
+{
+ button->priv = BUTTON_WIDGET_GET_PRIVATE (button);
+
+ button->priv->icon_theme = NULL;
+ button->priv->pixbuf = NULL;
+ button->priv->pixbuf_hc = NULL;
+
+ button->priv->filename = NULL;
+
+ button->priv->orientation = PANEL_ORIENTATION_TOP;
+
+ button->priv->size = 0;
+
+ button->priv->activatable = FALSE;
+ button->priv->ignore_leave = FALSE;
+ button->priv->arrow = FALSE;
+ button->priv->dnd_highlight = FALSE;
+}
+
+static void
+button_widget_class_init (ButtonWidgetClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+ GtkButtonClass *button_class = (GtkButtonClass *) klass;
+
+ gobject_class->finalize = button_widget_finalize;
+ gobject_class->get_property = button_widget_get_property;
+ gobject_class->set_property = button_widget_set_property;
+
+ g_type_class_add_private (klass, sizeof (ButtonWidgetPrivate));
+
+ widget_class->realize = button_widget_realize;
+ widget_class->unrealize = button_widget_unrealize;
+ widget_class->size_allocate = button_widget_size_allocate;
+ widget_class->size_request = button_widget_size_request;
+ widget_class->button_press_event = button_widget_button_press;
+ widget_class->enter_notify_event = button_widget_enter_notify;
+ widget_class->leave_notify_event = button_widget_leave_notify;
+ widget_class->expose_event = button_widget_expose;
+
+ button_class->activate = button_widget_activate;
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ACTIVATABLE,
+ g_param_spec_boolean ("activatable",
+ "Activatable",
+ "Whether the button is activatable",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_IGNORE_LEAVE,
+ g_param_spec_boolean ("ignore-leave",
+ "Ignore leaving to not unhighlight the icon",
+ "Whether or not to unhighlight the icon when the cursor leaves it",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_HAS_ARROW,
+ g_param_spec_boolean ("has-arrow",
+ "Has Arrow",
+ "Whether or not to draw an arrow indicator",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_DND_HIGHLIGHT,
+ g_param_spec_boolean ("dnd-highlight",
+ "Drag and drop Highlight",
+ "Whether or not to highlight the icon during drag and drop",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ "Orientation",
+ "The ButtonWidget orientation",
+ PANEL_TYPE_ORIENTATION,
+ PANEL_ORIENTATION_TOP,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ICON_NAME,
+ g_param_spec_string ("icon-name",
+ "Icon Name",
+ "The desired icon for the ButtonWidget",
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+GtkWidget *
+button_widget_new (const char *filename,
+ gboolean arrow,
+ PanelOrientation orientation)
+{
+ GtkWidget *retval;
+
+ retval = g_object_new (
+ BUTTON_TYPE_WIDGET,
+ "has-arrow", arrow,
+ "orientation", orientation,
+ "icon-name", filename,
+ NULL);
+
+ return retval;
+}
+
+void
+button_widget_set_activatable (ButtonWidget *button,
+ gboolean activatable)
+{
+ g_return_if_fail (BUTTON_IS_WIDGET (button));
+
+ activatable = activatable != FALSE;
+
+ if (button->priv->activatable != activatable) {
+ button->priv->activatable = activatable;
+
+ if (gtk_widget_is_drawable (GTK_WIDGET (button)))
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+
+ g_object_notify (G_OBJECT (button), "activatable");
+ }
+}
+
+gboolean
+button_widget_get_activatable (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE);
+
+ return button->priv->activatable;
+}
+
+void
+button_widget_set_icon_name (ButtonWidget *button,
+ const char *icon_name)
+{
+ g_return_if_fail (BUTTON_IS_WIDGET (button));
+
+ if (button->priv->filename && icon_name &&
+ !strcmp (button->priv->filename, icon_name))
+ return;
+
+ if (button->priv->filename)
+ g_free (button->priv->filename);
+ button->priv->filename = g_strdup (icon_name);
+
+ button_widget_reload_pixbuf (button);
+
+ g_object_notify (G_OBJECT (button), "icon-name");
+}
+
+const char *
+button_widget_get_icon_name (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL);
+
+ return button->priv->filename;
+}
+
+void
+button_widget_set_orientation (ButtonWidget *button,
+ PanelOrientation orientation)
+{
+ g_return_if_fail (BUTTON_IS_WIDGET (button));
+
+ if (button->priv->orientation == orientation)
+ return;
+
+ button->priv->orientation = orientation;
+
+ /* Force a re-scale */
+ button->priv->size = -1;
+
+ gtk_widget_queue_resize (GTK_WIDGET (button));
+
+ g_object_notify (G_OBJECT (button), "orientation");
+}
+
+PanelOrientation
+button_widget_get_orientation (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), 0);
+
+ return button->priv->orientation;
+}
+
+void
+button_widget_set_has_arrow (ButtonWidget *button,
+ gboolean has_arrow)
+{
+ g_return_if_fail (BUTTON_IS_WIDGET (button));
+
+ has_arrow = has_arrow != FALSE;
+
+ if (button->priv->arrow == has_arrow)
+ return;
+
+ button->priv->arrow = has_arrow;
+
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+
+ g_object_notify (G_OBJECT (button), "has-arrow");
+}
+
+gboolean
+button_widget_get_has_arrow (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE);
+
+ return button->priv->arrow;
+}
+
+void
+button_widget_set_dnd_highlight (ButtonWidget *button,
+ gboolean dnd_highlight)
+{
+ g_return_if_fail (BUTTON_IS_WIDGET (button));
+
+ dnd_highlight = dnd_highlight != FALSE;
+
+ if (button->priv->dnd_highlight == dnd_highlight)
+ return;
+
+ button->priv->dnd_highlight = dnd_highlight;
+
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+
+ g_object_notify (G_OBJECT (button), "dnd-highlight");
+}
+
+gboolean
+button_widget_get_dnd_highlight (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE);
+
+ return button->priv->dnd_highlight;
+}
+
+void
+button_widget_set_ignore_leave (ButtonWidget *button,
+ gboolean ignore_leave)
+{
+ g_return_if_fail (BUTTON_IS_WIDGET (button));
+
+ ignore_leave = ignore_leave != FALSE;
+
+ if (button->priv->ignore_leave == ignore_leave)
+ return;
+
+ button->priv->ignore_leave = ignore_leave;
+
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+
+ g_object_notify (G_OBJECT (button), "ignore-leave");
+}
+
+gboolean
+button_widget_get_ignore_leave (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE);
+
+ return button->priv->ignore_leave;
+}
+
+GtkIconTheme *
+button_widget_get_icon_theme (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL);
+
+ return button->priv->icon_theme;
+}
+
+GdkPixbuf *
+button_widget_get_pixbuf (ButtonWidget *button)
+{
+ g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL);
+
+ if (!button->priv->pixbuf)
+ return NULL;
+
+ return g_object_ref (button->priv->pixbuf);
+}
diff --git a/mate-panel/button-widget.h b/mate-panel/button-widget.h
new file mode 100644
index 00000000..e9b87e6d
--- /dev/null
+++ b/mate-panel/button-widget.h
@@ -0,0 +1,60 @@
+#ifndef BUTTON_WIDGET_H
+#define BUTTON_WIDGET_H
+
+#include <gtk/gtk.h>
+#include "panel-enums.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BUTTON_TYPE_WIDGET (button_widget_get_type ())
+#define BUTTON_WIDGET(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), BUTTON_TYPE_WIDGET, ButtonWidget))
+#define BUTTON_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass, BUTTON_TYPE_WIDGET, ButtonWidgetClass))
+#define BUTTON_IS_WIDGET(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), BUTTON_TYPE_WIDGET))
+#define BUTTON_IS_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BUTTON_TYPE_WIDGET))
+
+typedef struct _ButtonWidget ButtonWidget;
+typedef struct _ButtonWidgetClass ButtonWidgetClass;
+typedef struct _ButtonWidgetPrivate ButtonWidgetPrivate;
+
+struct _ButtonWidget {
+ GtkButton parent;
+
+ ButtonWidgetPrivate *priv;
+};
+
+struct _ButtonWidgetClass {
+ GtkButtonClass parent_class;
+};
+
+GType button_widget_get_type (void) G_GNUC_CONST;
+GtkWidget * button_widget_new (const char *pixmap,
+ gboolean arrow,
+ PanelOrientation orientation);
+void button_widget_set_activatable (ButtonWidget *button,
+ gboolean activatable);
+gboolean button_widget_get_activatable (ButtonWidget *button);
+void button_widget_set_icon_name (ButtonWidget *button,
+ const char *icon_name);
+const char * button_widget_get_icon_name (ButtonWidget *button);
+void button_widget_set_orientation (ButtonWidget *button,
+ PanelOrientation orientation);
+PanelOrientation button_widget_get_orientation (ButtonWidget *button);
+void button_widget_set_has_arrow (ButtonWidget *button,
+ gboolean has_arrow);
+gboolean button_widget_get_has_arrow (ButtonWidget *button);
+void button_widget_set_dnd_highlight (ButtonWidget *button,
+ gboolean dnd_highlight);
+gboolean button_widget_get_dnd_highlight (ButtonWidget *button);
+void button_widget_set_ignore_leave (ButtonWidget *button,
+ gboolean ignore_leave);
+gboolean button_widget_get_ignore_leave (ButtonWidget *button);
+GtkIconTheme *button_widget_get_icon_theme (ButtonWidget *button);
+GdkPixbuf *button_widget_get_pixbuf (ButtonWidget *button);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BUTTON_WIDGET_H__ */
diff --git a/mate-panel/drawer.c b/mate-panel/drawer.c
new file mode 100644
index 00000000..924acb42
--- /dev/null
+++ b/mate-panel/drawer.c
@@ -0,0 +1,806 @@
+/*
+ * MATE panel drawer module.
+ * (C) 1997 The Free Software Foundation
+ *
+ * Authors: Miguel de Icaza
+ * Federico Mena
+ * George Lebl
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "drawer.h"
+
+#include "applet.h"
+#include "button-widget.h"
+#include "panel-config-global.h"
+#include "panel-mateconf.h"
+#include "panel-profile.h"
+#include "panel-util.h"
+#include "xstuff.h"
+#include "panel-globals.h"
+#include "panel-lockdown.h"
+#include "panel-icon-names.h"
+
+static void
+drawer_click (GtkWidget *w, Drawer *drawer)
+{
+ if (!panel_toplevel_get_is_hidden (drawer->toplevel))
+ panel_toplevel_hide (drawer->toplevel, FALSE, -1);
+ else
+ panel_toplevel_unhide (drawer->toplevel);
+}
+
+static void
+toplevel_destroyed (GtkWidget *widget,
+ Drawer *drawer)
+{
+ drawer->toplevel = NULL;
+ gtk_widget_destroy (drawer->button);
+}
+
+static void
+destroy_drawer (GtkWidget *widget,
+ Drawer *drawer)
+{
+ MateConfClient *client;
+ int i;
+
+ client = panel_mateconf_get_client ();
+
+ for (i = 0; i < PANEL_DRAWER_N_LISTENERS; i++) {
+ if (drawer->listeners [i])
+ mateconf_client_notify_remove (client, drawer->listeners [i]);
+ drawer->listeners [i] = 0;
+ }
+
+ if (drawer->toplevel)
+ gtk_widget_destroy (GTK_WIDGET (drawer->toplevel));
+ drawer->toplevel = NULL;
+
+ if (drawer->close_timeout_id)
+ g_source_remove (drawer->close_timeout_id);
+ drawer->close_timeout_id = 0;
+}
+
+static void
+drawer_focus_panel_widget (Drawer *drawer,
+ GtkDirectionType direction)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = panel_toplevel_get_panel_widget (drawer->toplevel);
+
+ gtk_window_present (GTK_WINDOW (drawer->toplevel));
+ gtk_container_set_focus_child (GTK_CONTAINER (panel_widget), NULL);
+ gtk_widget_child_focus (GTK_WIDGET (panel_widget), direction);
+}
+
+static gboolean
+key_press_drawer (GtkWidget *widget,
+ GdkEventKey *event,
+ Drawer *drawer)
+{
+ gboolean retval = TRUE;
+ GtkOrientation orient;
+
+ if (event->state & gtk_accelerator_get_default_mod_mask ())
+ return FALSE;
+
+ orient = PANEL_WIDGET (gtk_widget_get_parent (drawer->button))->orient;
+
+ switch (event->keyval) {
+ case GDK_Up:
+ case GDK_KP_Up:
+ if (orient == GTK_ORIENTATION_HORIZONTAL) {
+ if (!panel_toplevel_get_is_hidden (drawer->toplevel))
+ drawer_focus_panel_widget (drawer, GTK_DIR_TAB_BACKWARD);
+ } else {
+ /* let default focus movement happen */
+ retval = FALSE;
+ }
+ break;
+ case GDK_Left:
+ case GDK_KP_Left:
+ if (orient == GTK_ORIENTATION_VERTICAL) {
+ if (!panel_toplevel_get_is_hidden (drawer->toplevel))
+ drawer_focus_panel_widget (drawer, GTK_DIR_TAB_BACKWARD);
+ } else {
+ /* let default focus movement happen */
+ retval = FALSE;
+ }
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ if (orient == GTK_ORIENTATION_HORIZONTAL) {
+ if (!panel_toplevel_get_is_hidden (drawer->toplevel))
+ drawer_focus_panel_widget (drawer, GTK_DIR_TAB_FORWARD);
+ } else {
+ /* let default focus movement happen */
+ retval = FALSE;
+ }
+ break;
+ case GDK_Right:
+ case GDK_KP_Right:
+ if (orient == GTK_ORIENTATION_VERTICAL) {
+ if (!panel_toplevel_get_is_hidden (drawer->toplevel))
+ drawer_focus_panel_widget (drawer, GTK_DIR_TAB_FORWARD);
+ } else {
+ /* let default focus movement happen */
+ retval = FALSE;
+ }
+ break;
+ case GDK_Escape:
+ panel_toplevel_hide (drawer->toplevel, FALSE, -1);
+ break;
+ default:
+ retval = FALSE;
+ break;
+ }
+
+ return retval;
+}
+
+/*
+ * This function implements Esc moving focus from the drawer to the drawer
+ * icon and closing the drawer and Shift+Esc moving focus from the drawer
+ * to the drawer icon without closing the drawer when focus is in the drawer.
+ */
+static gboolean
+key_press_drawer_widget (GtkWidget *widget,
+ GdkEventKey *event,
+ Drawer *drawer)
+{
+ PanelWidget *panel_widget;
+
+ if (event->keyval != GDK_Escape)
+ return FALSE;
+
+ panel_widget = panel_toplevel_get_panel_widget (drawer->toplevel);
+
+ gtk_window_present (GTK_WINDOW (panel_widget->toplevel));
+
+ if ((event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK ||
+ panel_toplevel_get_is_hidden (drawer->toplevel))
+ return TRUE;
+
+ panel_toplevel_hide (drawer->toplevel, FALSE, -1);
+
+ return TRUE;
+}
+
+static void
+drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time_,
+ Drawer *drawer)
+{
+ PanelWidget *panel_widget;
+
+ if (!panel_check_dnd_target_data (widget, context, &info, NULL)) {
+ gtk_drag_finish (context, FALSE, FALSE, time_);
+ return;
+ }
+
+ panel_widget = panel_toplevel_get_panel_widget (drawer->toplevel);
+
+ panel_receive_dnd_data (
+ panel_widget, info, -1, selection_data, context, time_);
+}
+
+static gboolean
+drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ guint time_,
+ Drawer *drawer)
+{
+ PanelWidget *panel_widget;
+ guint info = 0;
+
+ if (!panel_check_dnd_target_data (widget, context, &info, NULL))
+ return FALSE;
+
+ panel_widget = panel_toplevel_get_panel_widget (drawer->toplevel);
+
+ if (!panel_check_drop_forbidden (panel_widget, context, info, time_))
+ return FALSE;
+
+ if (drawer->close_timeout_id)
+ g_source_remove (drawer->close_timeout_id);
+ drawer->close_timeout_id = 0;
+
+ button_widget_set_dnd_highlight (BUTTON_WIDGET (widget), TRUE);
+
+ if (panel_toplevel_get_is_hidden (drawer->toplevel)) {
+ panel_toplevel_unhide (drawer->toplevel);
+ drawer->opened_for_drag = TRUE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+close_drawer_in_idle (gpointer data)
+{
+ Drawer *drawer = (Drawer *) data;
+
+ drawer->close_timeout_id = 0;
+
+ if (drawer->opened_for_drag) {
+ panel_toplevel_hide (drawer->toplevel, FALSE, -1);
+ drawer->opened_for_drag = FALSE;
+ }
+
+ return FALSE;
+}
+
+static void
+queue_drawer_close_for_drag (Drawer *drawer)
+{
+ if (!drawer->close_timeout_id)
+ drawer->close_timeout_id =
+ g_timeout_add_seconds (1, close_drawer_in_idle, drawer);
+}
+
+static void
+drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time_,
+ Drawer *drawer)
+{
+ queue_drawer_close_for_drag (drawer);
+
+ button_widget_set_dnd_highlight (BUTTON_WIDGET (widget), FALSE);
+}
+
+static gboolean
+drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ guint time_,
+ Drawer *drawer)
+{
+ GdkAtom atom = NULL;
+
+ if (!panel_check_dnd_target_data (widget, context, NULL, &atom))
+ return FALSE;
+
+ gtk_drag_get_data (widget, context, atom, time_);
+
+ return TRUE;
+}
+
+static void
+drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ Drawer *drawer)
+{
+ char *foo;
+
+ foo = g_strdup_printf ("DRAWER:%d", panel_find_applet_index (widget));
+
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8, (guchar *)foo,
+ strlen (foo));
+
+ g_free (foo);
+}
+
+static void
+set_tooltip_and_name (Drawer *drawer,
+ const char *tooltip)
+{
+ g_return_if_fail (drawer != NULL);
+ g_return_if_fail (tooltip != NULL);
+
+ if (tooltip && !tooltip [0])
+ tooltip = NULL;
+
+ panel_toplevel_set_name (drawer->toplevel, tooltip);
+ panel_util_set_tooltip_text (drawer->button, tooltip);
+}
+
+static Drawer *
+create_drawer_applet (PanelToplevel *toplevel,
+ PanelToplevel *parent_toplevel,
+ const char *tooltip,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ PanelOrientation orientation)
+{
+ Drawer *drawer;
+ AtkObject *atk_obj;
+
+ drawer = g_new0 (Drawer, 1);
+
+ drawer->toplevel = toplevel;
+
+ if (!use_custom_icon || !custom_icon || !custom_icon [0]) {
+ drawer->button = button_widget_new (PANEL_ICON_DRAWER, TRUE,
+ orientation);
+ } else {
+ drawer->button = button_widget_new (custom_icon, TRUE,
+ orientation);
+ }
+
+ if (!drawer->button) {
+ g_free (drawer);
+ return NULL;
+ }
+ atk_obj = gtk_widget_get_accessible (drawer->button);
+ atk_object_set_name (atk_obj, _("Drawer"));
+
+ set_tooltip_and_name (drawer, tooltip);
+
+ gtk_drag_dest_set (drawer->button, 0, NULL, 0, 0);
+
+ g_signal_connect (drawer->button, "drag_data_get",
+ G_CALLBACK (drag_data_get_cb), drawer);
+ g_signal_connect (drawer->button, "drag_data_received",
+ G_CALLBACK (drag_data_received_cb), drawer);
+ g_signal_connect (drawer->button, "drag_motion",
+ G_CALLBACK (drag_motion_cb), drawer);
+ g_signal_connect (drawer->button, "drag_leave",
+ G_CALLBACK (drag_leave_cb), drawer);
+ g_signal_connect (drawer->button, "drag_drop",
+ G_CALLBACK (drag_drop_cb), drawer);
+
+ g_signal_connect (drawer->button, "clicked",
+ G_CALLBACK (drawer_click), drawer);
+ g_signal_connect (drawer->button, "destroy",
+ G_CALLBACK (destroy_drawer), drawer);
+ g_signal_connect (drawer->button, "key_press_event",
+ G_CALLBACK (key_press_drawer), drawer);
+ g_signal_connect (toplevel, "destroy",
+ G_CALLBACK (toplevel_destroyed), drawer);
+
+ gtk_widget_show (drawer->button);
+
+ g_signal_connect (drawer->toplevel, "key_press_event",
+ G_CALLBACK (key_press_drawer_widget), drawer);
+
+ panel_toplevel_attach_to_widget (
+ toplevel, parent_toplevel, GTK_WIDGET (drawer->button));
+
+ return drawer;
+}
+
+static PanelToplevel *
+create_drawer_toplevel (const char *drawer_id)
+{
+ PanelToplevel *toplevel;
+ MateConfClient *client;
+ const char *key;
+ char *toplevel_id;
+
+ client = panel_mateconf_get_client ();
+
+ toplevel_id = panel_profile_find_new_id (PANEL_MATECONF_TOPLEVELS);
+
+ toplevel = panel_profile_load_toplevel (client, PANEL_CONFIG_DIR,
+ PANEL_MATECONF_TOPLEVELS, toplevel_id);
+
+ if (!toplevel) {
+ g_free (toplevel_id);
+ return NULL;
+ }
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer_id, "attached_toplevel_id");
+ mateconf_client_set_string (client, key, toplevel_id, NULL);
+ g_free (toplevel_id);
+
+ panel_profile_set_toplevel_enable_buttons (toplevel, TRUE);
+ panel_profile_set_toplevel_enable_arrows (toplevel, TRUE);
+
+ return toplevel;
+}
+
+static void
+drawer_button_size_allocated (GtkWidget *widget,
+ GtkAllocation *alloc,
+ Drawer *drawer)
+{
+ if (!gtk_widget_get_realized (widget))
+ return;
+
+ gtk_widget_queue_resize (GTK_WIDGET (drawer->toplevel));
+
+ g_object_set_data (G_OBJECT (widget), "allocated", GINT_TO_POINTER (TRUE));
+}
+
+static void
+panel_drawer_use_custom_icon_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ Drawer *drawer)
+{
+ gboolean use_custom_icon;
+ char *custom_icon = NULL;
+
+ if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ use_custom_icon = mateconf_value_get_bool (entry->value);
+
+ if (use_custom_icon) {
+ const char *key;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer->info->id, "custom_icon");
+ custom_icon = mateconf_client_get_string (client, key, NULL);
+ }
+
+ button_widget_set_icon_name (BUTTON_WIDGET (drawer->button), custom_icon);
+
+ g_free (custom_icon);
+}
+
+static void
+panel_drawer_custom_icon_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ Drawer *drawer)
+{
+ const char *custom_icon;
+
+ if (!entry->value || entry->value->type != MATECONF_VALUE_STRING)
+ return;
+
+ custom_icon = mateconf_value_get_string (entry->value);
+
+ if (custom_icon && custom_icon [0]) {
+ const char *key;
+ gboolean use_custom_icon;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer->info->id, "use_custom_icon");
+ use_custom_icon = mateconf_client_get_bool (client, key, NULL);
+ if (use_custom_icon)
+ button_widget_set_icon_name (BUTTON_WIDGET (drawer->button), custom_icon);
+ }
+}
+
+static void
+panel_drawer_tooltip_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ Drawer *drawer)
+{
+ if (!entry->value || entry->value->type != MATECONF_VALUE_STRING)
+ return;
+
+ set_tooltip_and_name (drawer,
+ mateconf_value_get_string (entry->value));
+}
+
+static void
+panel_drawer_connect_to_mateconf (Drawer *drawer)
+{
+ MateConfClient *client;
+ const char *key;
+ int i = 0;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer->info->id, "use_custom_icon");
+ drawer->listeners [i++] =
+ mateconf_client_notify_add (client, key,
+ (MateConfClientNotifyFunc) panel_drawer_use_custom_icon_changed,
+ drawer, NULL, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer->info->id, "custom_icon");
+ drawer->listeners [i++] =
+ mateconf_client_notify_add (client, key,
+ (MateConfClientNotifyFunc) panel_drawer_custom_icon_changed,
+ drawer, NULL, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer->info->id, "tooltip");
+ drawer->listeners [i++] =
+ mateconf_client_notify_add (client, key,
+ (MateConfClientNotifyFunc) panel_drawer_tooltip_changed,
+ drawer, NULL, NULL);
+
+ g_assert (i == PANEL_DRAWER_N_LISTENERS);
+}
+
+static gboolean
+drawer_changes_enabled (void)
+{
+ return !panel_lockdown_get_locked_down ();
+}
+
+static void
+load_drawer_applet (char *toplevel_id,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip,
+ PanelToplevel *parent_toplevel,
+ gboolean locked,
+ int pos,
+ gboolean exactpos,
+ const char *id)
+{
+ PanelOrientation orientation;
+ PanelToplevel *toplevel = NULL;
+ Drawer *drawer = NULL;
+ PanelWidget *panel_widget;
+
+ orientation = panel_toplevel_get_orientation (parent_toplevel);
+
+ if (toplevel_id)
+ toplevel = panel_profile_get_toplevel_by_id (toplevel_id);
+
+ if (!toplevel)
+ toplevel = create_drawer_toplevel (id);
+
+ if (toplevel) {
+ panel_toplevel_hide (toplevel, FALSE, -1);
+ drawer = create_drawer_applet (toplevel,
+ parent_toplevel,
+ tooltip,
+ custom_icon,
+ use_custom_icon,
+ orientation);
+ }
+
+ if (!drawer)
+ return;
+
+ panel_widget = panel_toplevel_get_panel_widget (parent_toplevel);
+
+ drawer->info = mate_panel_applet_register (drawer->button, drawer,
+ (GDestroyNotify) g_free,
+ panel_widget,
+ locked, pos, exactpos,
+ PANEL_OBJECT_DRAWER, id);
+
+ if (!drawer->info) {
+ gtk_widget_destroy (GTK_WIDGET (toplevel));
+ return;
+ }
+
+ g_signal_connect_after (drawer->button, "size_allocate",
+ G_CALLBACK (drawer_button_size_allocated), drawer);
+
+ panel_widget_add_forbidden (panel_toplevel_get_panel_widget (drawer->toplevel));
+ panel_widget_set_applet_expandable (panel_widget, GTK_WIDGET (drawer->button), FALSE, TRUE);
+ panel_widget_set_applet_size_constrained (panel_widget, GTK_WIDGET (drawer->button), TRUE);
+
+ mate_panel_applet_add_callback (drawer->info,
+ "add",
+ GTK_STOCK_ADD,
+ _("_Add to Drawer..."),
+ drawer_changes_enabled);
+
+ mate_panel_applet_add_callback (drawer->info,
+ "properties",
+ GTK_STOCK_PROPERTIES,
+ _("_Properties"),
+ drawer_changes_enabled);
+
+ mate_panel_applet_add_callback (drawer->info,
+ "help",
+ GTK_STOCK_HELP,
+ _("_Help"),
+ NULL);
+
+ panel_drawer_connect_to_mateconf (drawer);
+}
+
+static void
+panel_drawer_prepare (const char *drawer_id,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip,
+ char **attached_toplevel_id)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ if (tooltip) {
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer_id, "tooltip");
+ mateconf_client_set_string (client, key, tooltip, NULL);
+ }
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer_id, "use_custom_icon");
+ mateconf_client_set_bool (client, key, use_custom_icon, NULL);
+
+ if (custom_icon) {
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer_id, "custom_icon");
+ mateconf_client_set_string (client, key, custom_icon, NULL);
+ }
+
+ if (attached_toplevel_id) {
+ char *toplevel_id;
+ char *toplevel_dir;
+
+ toplevel_id = panel_profile_find_new_id (PANEL_MATECONF_TOPLEVELS);
+
+ toplevel_dir = g_strdup_printf (PANEL_CONFIG_DIR "/toplevels/%s",
+ toplevel_id);
+ panel_mateconf_associate_schemas_in_dir (client, toplevel_dir, PANEL_SCHEMAS_DIR "/toplevels");
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, drawer_id, "attached_toplevel_id");
+ mateconf_client_set_string (client, key, toplevel_id, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS, toplevel_id, "enable_buttons");
+ mateconf_client_set_bool (client, key, TRUE, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS, toplevel_id, "enable_arrows");
+ mateconf_client_set_bool (client, key, TRUE, NULL);
+
+ *attached_toplevel_id = toplevel_id;
+ }
+}
+
+void
+panel_drawer_create (PanelToplevel *toplevel,
+ int position,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip)
+{
+ char *id;
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_DRAWER, toplevel, position, FALSE);
+
+ panel_drawer_prepare (id, custom_icon, use_custom_icon, tooltip, NULL);
+
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+
+ g_free (id);
+}
+
+char *
+panel_drawer_create_with_id (const char *toplevel_id,
+ int position,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip)
+{
+ char *id;
+ char *attached_toplevel_id = NULL;
+
+ id = panel_profile_prepare_object_with_id (PANEL_OBJECT_DRAWER, toplevel_id, position, FALSE);
+
+ panel_drawer_prepare (id, custom_icon, use_custom_icon, tooltip, &attached_toplevel_id);
+
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+
+ g_free (id);
+
+ return attached_toplevel_id;
+}
+
+void
+drawer_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ gint position,
+ const char *id)
+{
+ MateConfClient *client;
+ const char *key;
+ gboolean use_custom_icon;
+ char *toplevel_id;
+ char *custom_icon;
+ char *tooltip;
+
+ g_return_if_fail (panel_widget != NULL);
+ g_return_if_fail (id != NULL);
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "attached_toplevel_id");
+ toplevel_id = mateconf_client_get_string (client, key, NULL);
+
+ panel_profile_load_toplevel (client, PANEL_CONFIG_DIR, PANEL_MATECONF_TOPLEVELS, toplevel_id);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "use_custom_icon");
+ use_custom_icon = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "custom_icon");
+ custom_icon = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "tooltip");
+ tooltip = mateconf_client_get_string (client, key, NULL);
+
+ load_drawer_applet (toplevel_id,
+ custom_icon,
+ use_custom_icon,
+ tooltip,
+ panel_widget->toplevel,
+ locked,
+ position,
+ TRUE,
+ id);
+
+ g_free (toplevel_id);
+ g_free (custom_icon);
+ g_free (tooltip);
+}
+
+void
+panel_drawer_set_dnd_enabled (Drawer *drawer,
+ gboolean dnd_enabled)
+{
+ if (dnd_enabled) {
+ static GtkTargetEntry dnd_targets[] = {
+ { "application/x-mate-panel-applet-internal", 0, 0 }
+ };
+
+ gtk_widget_set_has_window (drawer->button, TRUE);
+ gtk_drag_source_set (drawer->button,
+ GDK_BUTTON1_MASK,
+ dnd_targets, 1,
+ GDK_ACTION_MOVE);
+ //FIXME: we're forgetting the use_custom_icon case, here
+ gtk_drag_source_set_icon_name (drawer->button,
+ button_widget_get_icon_name (BUTTON_WIDGET (drawer->button)));
+
+ gtk_widget_set_has_window (drawer->button, FALSE);
+
+ } else
+ gtk_drag_source_unset (drawer->button);
+}
+
+static void
+drawer_deletion_response (GtkWidget *dialog,
+ int response,
+ Drawer *drawer)
+{
+ if (response == GTK_RESPONSE_OK)
+ panel_profile_delete_object (drawer->info);
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+drawer_query_deletion (Drawer *drawer)
+{
+ GtkWidget *dialog;
+
+ if (drawer->toplevel) {
+ PanelWidget *panel_widget;
+
+ panel_widget = panel_toplevel_get_panel_widget (
+ drawer->toplevel);
+
+ if (!panel_global_config_get_confirm_panel_remove () ||
+ !g_list_length (panel_widget->applet_list)) {
+ panel_profile_delete_object (drawer->info);
+ return;
+ }
+
+ dialog = panel_deletion_dialog (drawer->toplevel);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (drawer_deletion_response),
+ drawer);
+
+ g_signal_connect_object (drawer->toplevel, "destroy",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog,
+ G_CONNECT_SWAPPED);
+
+ gtk_widget_show_all (dialog);
+ }
+}
diff --git a/mate-panel/drawer.h b/mate-panel/drawer.h
new file mode 100644
index 00000000..800e1a86
--- /dev/null
+++ b/mate-panel/drawer.h
@@ -0,0 +1,52 @@
+#ifndef DRAWER_H
+#define DRAWER_H
+
+#include "panel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_DRAWER_N_LISTENERS 3
+
+typedef struct {
+ char *tooltip;
+
+ PanelToplevel *toplevel;
+ GtkWidget *button;
+
+ gboolean opened_for_drag;
+ guint close_timeout_id;
+
+ AppletInfo *info;
+
+ guint listeners [PANEL_DRAWER_N_LISTENERS];
+} Drawer;
+
+void panel_drawer_create (PanelToplevel *toplevel,
+ int position,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip);
+
+char *panel_drawer_create_with_id (const char *toplevel_id,
+ int position,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip);
+
+void panel_drawer_set_dnd_enabled (Drawer *drawer,
+ gboolean dnd_enabled);
+
+void drawer_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ gint position,
+ const char *id);
+
+void drawer_query_deletion (Drawer *drawer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mate-panel/launcher.c b/mate-panel/launcher.c
new file mode 100644
index 00000000..657bc0c8
--- /dev/null
+++ b/mate-panel/launcher.c
@@ -0,0 +1,1114 @@
+/*
+ * MATE panel launcher module.
+ * (C) 1997,1998,1999,2000 The Free Software Foundation
+ * (C) 2000 Eazel, Inc.
+ *
+ * Authors: Miguel de Icaza
+ * Federico Mena
+ * CORBAized by George Lebl
+ * de-CORBAized by George Lebl
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdkx.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-launch.h>
+#include <libpanel-util/panel-show.h>
+
+#include "launcher.h"
+
+#include "button-widget.h"
+#include "panel-util.h"
+#include "panel-config-global.h"
+#include "panel-mateconf.h"
+#include "panel-profile.h"
+#include "xstuff.h"
+#include "panel-toplevel.h"
+#include "panel-a11y.h"
+#include "panel-globals.h"
+#include "panel-multiscreen.h"
+#include "panel-lockdown.h"
+#include "panel-compatibility.h"
+#include "panel-ditem-editor.h"
+#include "panel-icon-names.h"
+
+static GdkScreen *
+launcher_get_screen (Launcher *launcher)
+{
+ PanelWidget *panel_widget;
+
+ g_return_val_if_fail (launcher != NULL, NULL);
+ g_return_val_if_fail (launcher->info != NULL, NULL);
+ g_return_val_if_fail (launcher->info->widget != NULL, NULL);
+
+ panel_widget = PANEL_WIDGET (gtk_widget_get_parent (launcher->info->widget));
+
+ return gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel));
+}
+
+static void
+launcher_widget_open_dialog_destroyed (GtkWidget *dialog,
+ Launcher *launcher)
+{
+ g_return_if_fail (launcher->error_dialogs != NULL);
+
+ launcher->error_dialogs = g_slist_remove (launcher->error_dialogs, dialog);
+}
+
+static void
+launcher_widget_destroy_open_dialogs (Launcher *launcher)
+{
+ GSList *l, *list;
+
+ list = launcher->error_dialogs;
+ launcher->error_dialogs = NULL;
+
+ for (l = list; l; l = l->next) {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
+ G_CALLBACK (launcher_widget_open_dialog_destroyed),
+ launcher);
+ gtk_widget_destroy (l->data);
+ }
+ g_slist_free (list);
+}
+
+static void
+launcher_register_error_dialog (Launcher *launcher,
+ GtkWidget *dialog)
+{
+ launcher->error_dialogs = g_slist_append (launcher->error_dialogs,
+ dialog);
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (launcher_widget_open_dialog_destroyed),
+ launcher);
+}
+
+static void
+launch_url (Launcher *launcher)
+{
+ char *url;
+ GdkScreen *screen;
+
+ g_return_if_fail (launcher != NULL);
+ g_return_if_fail (launcher->key_file != NULL);
+
+ /* FIXME panel_ditem_launch() should be enough for this! */
+ url = panel_key_file_get_string (launcher->key_file, "URL");
+
+ screen = launcher_get_screen (launcher);
+
+ if (!url || *url == 0) {
+ GtkWidget *error_dialog;
+
+ error_dialog = panel_error_dialog (NULL, screen,
+ "no_url_dialog", TRUE,
+ _("Could not show this URL"),
+ _("No URL was specified."));
+ launcher_register_error_dialog (launcher, error_dialog);
+ g_free (url);
+ return;
+ }
+
+ panel_show_uri (screen, url, gtk_get_current_event_time (), NULL);
+
+ g_free (url);
+}
+
+void
+launcher_launch (Launcher *launcher,
+ GtkWidget *widget)
+{
+ char *type;
+
+ g_return_if_fail (launcher != NULL);
+ g_return_if_fail (launcher->key_file != NULL);
+
+ if (panel_global_config_get_enable_animations ())
+ xstuff_zoom_animate (widget,
+ button_widget_get_pixbuf (BUTTON_WIDGET (widget)),
+ button_widget_get_orientation (BUTTON_WIDGET (widget)),
+ NULL);
+
+ type = panel_key_file_get_string (launcher->key_file, "Type");
+ if (type && !strcmp (type, "Link"))
+ launch_url (launcher);
+ else {
+ GError *error = NULL;
+
+ panel_launch_key_file (launcher->key_file, NULL,
+ launcher_get_screen (launcher), &error);
+ if (error) {
+ GtkWidget *error_dialog;
+
+ error_dialog = panel_error_dialog (
+ NULL,
+ launcher_get_screen (launcher),
+ "cannot_launch_application",
+ TRUE,
+ _("Could not launch application"),
+ error->message);
+ launcher_register_error_dialog (launcher, error_dialog);
+ g_clear_error (&error);
+ }
+ }
+ g_free (type);
+
+ if (panel_global_config_get_drawer_auto_close ()) {
+ PanelToplevel *toplevel;
+ PanelToplevel *parent;
+
+ toplevel = PANEL_WIDGET (gtk_widget_get_parent (launcher->button))->toplevel;
+
+ if (panel_toplevel_get_is_attached (toplevel)) {
+ parent = panel_toplevel_get_attach_toplevel (toplevel);
+
+ while (panel_toplevel_get_is_attached (parent)) {
+ toplevel = parent;
+ parent = panel_toplevel_get_attach_toplevel (toplevel);
+ }
+
+ panel_toplevel_hide (toplevel, FALSE, -1);
+ }
+ }
+}
+
+static void
+drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ Launcher *launcher)
+{
+ GError *error = NULL;
+ char **uris;
+ int i;
+ GList *file_list;
+
+ if (panel_global_config_get_enable_animations ())
+ xstuff_zoom_animate (widget,
+ button_widget_get_pixbuf (BUTTON_WIDGET (widget)),
+ button_widget_get_orientation (BUTTON_WIDGET (widget)),
+ NULL);
+
+ file_list = NULL;
+ uris = g_uri_list_extract_uris ((const char *) gtk_selection_data_get_data (selection_data));
+ for (i = 0; uris[i]; i++)
+ file_list = g_list_prepend (file_list, uris[i]);
+ file_list = g_list_reverse (file_list);
+
+ panel_launch_key_file (launcher->key_file, file_list,
+ launcher_get_screen (launcher), &error);
+
+ g_list_free (file_list);
+ g_strfreev (uris);
+
+ if (error) {
+ GtkWidget *error_dialog;
+ error_dialog = panel_error_dialog (NULL,
+ launcher_get_screen (launcher),
+ "cannot_use_dropped_item",
+ TRUE,
+ _("Could not use dropped item"),
+ error->message);
+ launcher_register_error_dialog (launcher, error_dialog);
+ g_clear_error (&error);
+ }
+
+ gtk_drag_finish (context, TRUE, FALSE, time);
+}
+
+static void
+destroy_launcher (GtkWidget *widget,
+ Launcher *launcher)
+{
+ launcher_properties_destroy (launcher);
+ launcher_widget_destroy_open_dialogs (launcher);
+}
+
+void
+launcher_properties_destroy (Launcher *launcher)
+{
+ GtkWidget *dialog;
+
+ dialog = launcher->prop_dialog;
+ launcher->prop_dialog = NULL;
+
+ if (dialog)
+ gtk_widget_destroy (dialog);
+}
+
+static void
+free_launcher (gpointer data)
+{
+ Launcher *launcher = data;
+
+ if (launcher->key_file)
+ g_key_file_free (launcher->key_file);
+ launcher->key_file = NULL;
+
+ if (launcher->location != NULL)
+ g_free (launcher->location);
+ launcher->location = NULL;
+
+ g_free (launcher);
+}
+
+void
+panel_launcher_delete (Launcher *launcher)
+{
+ if (!launcher->location)
+ return;
+
+ /* do not remove the file if it's not in the user's launchers path */
+ if (panel_launcher_is_in_personal_path (launcher->location)) {
+ GError *error;
+ GFile *file;
+
+ file = panel_launcher_get_gfile (launcher->location);
+
+ error = NULL;
+ if (!g_file_delete (file, NULL, &error)) {
+ char *path;
+
+ path = g_file_get_path (file);
+ g_warning ("Error deleting '%s': %s\n",
+ path, error->message);
+ g_free (path);
+ g_error_free (error);
+ }
+
+ g_object_unref (file);
+ }
+}
+
+static gboolean
+is_this_drop_ok (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ static GdkAtom text_uri_list = GDK_NONE;
+ GList *l;
+ GtkWidget *source;
+
+ source = gtk_drag_get_source_widget (context);
+
+ if (source == widget)
+ return FALSE;
+
+ if (!(gdk_drag_context_get_actions (context) & GDK_ACTION_COPY))
+ return FALSE;
+
+ if (!text_uri_list)
+ text_uri_list = gdk_atom_intern_static_string ("text/uri-list");
+
+ for (l = gdk_drag_context_list_targets (context); l; l = l->next) {
+ if (GDK_POINTER_TO_ATOM (l->data) == text_uri_list)
+ break;
+ }
+
+ return l ? TRUE : FALSE;
+}
+
+static void
+drag_leave_cb(GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ Launcher *launcher)
+{
+ button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), FALSE);
+}
+
+
+static gboolean
+drag_motion_cb(GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ Launcher *launcher)
+{
+ if ( ! is_this_drop_ok (widget, context))
+ return FALSE;
+
+ gdk_drag_status (context, GDK_ACTION_COPY, time);
+
+ button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ Launcher *launcher)
+{
+ static GdkAtom text_uri_list = NULL;
+
+ if ( ! is_this_drop_ok (widget, context))
+ return FALSE;
+
+ if (text_uri_list == NULL)
+ text_uri_list = gdk_atom_intern_static_string ("text/uri-list");
+
+ gtk_drag_get_data (widget, context, text_uri_list, time);
+
+ return TRUE;
+}
+
+enum {
+ TARGET_ICON_INTERNAL,
+ TARGET_URI_LIST
+};
+
+
+static void
+drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ Launcher *launcher)
+{
+ char *location;
+
+ g_return_if_fail (launcher != NULL);
+
+ location = launcher->location;
+
+ if (info == TARGET_URI_LIST) {
+ char *uri[2];
+
+ uri[0] = panel_launcher_get_uri (location);
+ uri[1] = NULL;
+
+ gtk_selection_data_set_uris (selection_data, uri);
+
+ g_free (uri[0]);
+ } else if (info == TARGET_ICON_INTERNAL)
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8,
+ (unsigned char *) location,
+ strlen (location));
+
+}
+
+static Launcher *
+create_launcher (const char *location)
+{
+ GKeyFile *key_file;
+ gboolean loaded;
+ Launcher *launcher;
+ GError *error = NULL;
+ char *new_location;
+
+ if (!location) {
+ g_printerr (_("No URI provided for panel launcher desktop file\n"));
+ return NULL;
+ }
+
+ new_location = NULL;
+ key_file = g_key_file_new ();
+
+ if (!strchr (location, G_DIR_SEPARATOR)) {
+ /* try to first load a file in our config directory, and if it
+ * doesn't exist there, try to find it in the xdg data dirs */
+ char *path;
+
+ path = panel_make_full_path (NULL, location);
+
+ if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+ g_free (path);
+ path = panel_g_lookup_in_applications_dirs (location);
+ /* it's important to keep the full path if the desktop
+ * file comes from a data dir: when the user will edit
+ * it, we'll want to save it in PANEL_LAUNCHERS_PATH
+ * with a random name (and not evolution.desktop, eg)
+ * and having only a basename as location will make
+ * this impossible */
+ if (path)
+ new_location = g_strdup (path);
+ }
+
+ if (path) {
+ loaded = g_key_file_load_from_file (key_file, path,
+ G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
+ &error);
+ g_free (path);
+ }
+ } else
+ loaded = panel_key_file_load_from_uri (key_file, location,
+ G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
+ &error);
+
+ if (!loaded) {
+ g_printerr (_("Unable to open desktop file %s for panel launcher%s%s\n"),
+ location,
+ error ? ": " : "",
+ error ? error->message : "");
+ if (error)
+ g_error_free (error);
+
+ g_key_file_free (key_file);
+
+ return NULL; /*button is null*/
+ }
+
+ if (!new_location)
+ new_location = g_strdup (location);
+
+ launcher = g_new0 (Launcher, 1);
+
+ launcher->info = NULL;
+ launcher->button = NULL;
+ launcher->location = new_location;
+ launcher->key_file = key_file;
+ launcher->prop_dialog = NULL;
+ launcher->destroy_handler = 0;
+
+ /* Icon will be setup later */
+ launcher->button = button_widget_new (NULL /* icon */,
+ FALSE,
+ PANEL_ORIENTATION_TOP);
+
+ gtk_widget_show (launcher->button);
+
+ /*gtk_drag_dest_set (GTK_WIDGET (launcher->button),
+ GTK_DEST_DEFAULT_ALL,
+ dnd_targets, 2,
+ GDK_ACTION_COPY);*/
+ gtk_drag_dest_set (GTK_WIDGET (launcher->button),
+ 0, NULL, 0, 0);
+
+ g_signal_connect (launcher->button, "drag_data_get",
+ G_CALLBACK (drag_data_get_cb), launcher);
+ g_signal_connect (launcher->button, "drag_data_received",
+ G_CALLBACK (drag_data_received_cb), launcher);
+ g_signal_connect (launcher->button, "drag_motion",
+ G_CALLBACK (drag_motion_cb), launcher);
+ g_signal_connect (launcher->button, "drag_drop",
+ G_CALLBACK (drag_drop_cb), launcher);
+ g_signal_connect (launcher->button, "drag_leave",
+ G_CALLBACK (drag_leave_cb), launcher);
+ g_signal_connect_swapped (launcher->button, "clicked",
+ G_CALLBACK (launcher_launch), launcher);
+
+ launcher->destroy_handler =
+ g_signal_connect (launcher->button, "destroy",
+ G_CALLBACK (destroy_launcher),
+ launcher);
+
+ return launcher;
+}
+
+static void
+setup_button (Launcher *launcher)
+{
+ char *comment;
+ char *name;
+ char *str;
+ char *icon;
+ char *unescaped_str;
+
+ g_return_if_fail (launcher != NULL);
+
+ name = panel_key_file_get_locale_string (launcher->key_file, "Name");
+ comment = panel_key_file_get_locale_string (launcher->key_file,
+ "Comment");
+
+ /* Setup tooltip */
+ if (!PANEL_GLIB_STR_EMPTY (name) && !PANEL_GLIB_STR_EMPTY (comment))
+ str = g_strdup_printf ("%s\n%s", name, comment);
+ else if (!PANEL_GLIB_STR_EMPTY (name))
+ str = g_strdup (name);
+ else
+ str = g_strdup (comment);
+
+ g_free (name);
+ g_free (comment);
+
+ /* If we can unescape the string, then we probably have an escaped
+ * string (a location e.g.). If we can't, then it most probably means
+ * we have a % that is not here to encode a character, and we don't
+ * want to unescape in this case. See bug #170516 for details. */
+ unescaped_str = g_uri_unescape_string (str, NULL);
+ if (unescaped_str) {
+ g_free (str);
+ str = unescaped_str;
+ }
+
+ panel_util_set_tooltip_text (launcher->button, str);
+
+ /* Setup accessible name */
+ panel_a11y_set_atk_name_desc (launcher->button, str, NULL);
+
+ g_free (str);
+
+ /* Setup icon */
+ icon = panel_key_file_get_locale_string (launcher->key_file, "Icon");
+ if (icon && icon[0] == '\0') {
+ g_free (icon);
+ icon = NULL;
+ }
+
+ if (!icon)
+ icon = guess_icon_from_exec (button_widget_get_icon_theme (BUTTON_WIDGET (launcher->button)),
+ launcher->key_file);
+ if (!icon)
+ icon = g_strdup (PANEL_ICON_LAUNCHER);
+
+ button_widget_set_icon_name (BUTTON_WIDGET (launcher->button), icon);
+ g_free (icon);
+}
+
+static char *
+panel_launcher_find_writable_uri (const char *launcher_location,
+ const char *source)
+{
+ char *path;
+ char *uri;
+
+ if (!launcher_location)
+ return panel_make_unique_desktop_uri (NULL, source);
+
+ if (!strchr (launcher_location, G_DIR_SEPARATOR)) {
+ path = panel_make_full_path (NULL, launcher_location);
+ uri = g_filename_to_uri (path, NULL, NULL);
+ g_free (path);
+ return uri;
+ }
+
+ if (panel_launcher_get_filename (launcher_location) != NULL) {
+ /* we have a file in the user directory. We either have a path
+ * or an URI */
+ if (g_path_is_absolute (launcher_location))
+ return g_filename_to_uri (launcher_location,
+ NULL, NULL);
+ else
+ return g_strdup (launcher_location);
+ }
+
+ return panel_make_unique_desktop_uri (NULL, source);
+}
+
+static void
+launcher_changed (PanelDItemEditor *dialog,
+ Launcher *launcher)
+{
+ /* Setup the button look */
+ setup_button (launcher);
+}
+
+static void
+launcher_command_changed (PanelDItemEditor *dialog,
+ const char *command,
+ Launcher *launcher)
+{
+ char *exec;
+ char *old_exec;
+ GKeyFile *revert_key_file;
+
+ revert_key_file = panel_ditem_editor_get_revert_key_file (dialog);
+
+ if (revert_key_file) {
+ exec = panel_key_file_get_string (launcher->key_file, "Exec");
+ old_exec = panel_key_file_get_string (revert_key_file, "Exec");
+
+ if (!old_exec || !exec || strcmp (old_exec, exec))
+ panel_key_file_remove_key (launcher->key_file,
+ "StartupNotify");
+
+ g_free (exec);
+ g_free (old_exec);
+ }
+}
+
+static char *
+launcher_save_uri (PanelDItemEditor *dialog,
+ gpointer data)
+{
+ GKeyFile *key_file;
+ char *type;
+ char *exec_or_uri;
+ Launcher *launcher;
+ char *new_uri;
+ const char *uri;
+
+ key_file = panel_ditem_editor_get_key_file (dialog);
+ type = panel_key_file_get_string (key_file, "Type");
+ if (type && !strcmp (type, "Application"))
+ exec_or_uri = panel_key_file_get_string (key_file, "Exec");
+ else if (type && !strcmp (type, "Link"))
+ exec_or_uri = panel_key_file_get_string (key_file, "URL");
+ else
+ exec_or_uri = panel_key_file_get_string (key_file, "Name");
+ g_free (type);
+
+ launcher = (Launcher *) data;
+
+ if (launcher)
+ new_uri = panel_launcher_find_writable_uri (launcher->location,
+ exec_or_uri);
+ else
+ new_uri = panel_launcher_find_writable_uri (NULL, exec_or_uri);
+
+ g_free (exec_or_uri);
+
+ uri = panel_ditem_editor_get_uri (dialog);
+
+ if (!uri || (new_uri && strcmp (new_uri, uri)))
+ return new_uri;
+
+ g_free (new_uri);
+
+ return NULL;
+}
+
+static void
+launcher_saved (GtkWidget *dialog,
+ Launcher *launcher)
+{
+ const char *uri;
+ MateConfClient *client;
+ const char *key;
+
+ uri = panel_ditem_editor_get_uri (PANEL_DITEM_EDITOR (dialog));
+ if (panel_launcher_get_filename (uri) != NULL)
+ uri = panel_launcher_get_filename (uri);
+
+ if (uri && launcher->location && strcmp (uri, launcher->location)) {
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS,
+ launcher->info->id,
+ "launcher_location");
+
+ mateconf_client_set_string (client, key, uri, NULL);
+
+ if (launcher->location)
+ g_free (launcher->location);
+ launcher->location = g_strdup (uri);
+ }
+}
+
+static void
+launcher_error_reported (GtkWidget *dialog,
+ const char *primary,
+ const char *secondary,
+ gpointer data)
+{
+ panel_error_dialog (GTK_WINDOW (dialog), NULL,
+ "error_editing_launcher", TRUE,
+ primary, secondary);
+}
+
+void
+launcher_properties (Launcher *launcher)
+{
+ if (launcher->prop_dialog != NULL) {
+ gtk_window_set_screen (GTK_WINDOW (launcher->prop_dialog),
+ gtk_widget_get_screen (launcher->button));
+ gtk_window_present (GTK_WINDOW (launcher->prop_dialog));
+ return;
+ }
+
+ launcher->prop_dialog = panel_ditem_editor_new (NULL,
+ launcher->key_file,
+ launcher->location,
+ _("Launcher Properties"));
+
+ panel_widget_register_open_dialog (PANEL_WIDGET
+ (gtk_widget_get_parent (launcher->info->widget)),
+ launcher->prop_dialog);
+
+ panel_ditem_register_save_uri_func (PANEL_DITEM_EDITOR (launcher->prop_dialog),
+ launcher_save_uri,
+ launcher);
+
+ g_signal_connect (launcher->prop_dialog, "changed",
+ G_CALLBACK (launcher_changed), launcher);
+
+ g_signal_connect (launcher->prop_dialog, "command_changed",
+ G_CALLBACK (launcher_command_changed), launcher);
+
+ g_signal_connect (launcher->prop_dialog, "saved",
+ G_CALLBACK (launcher_saved), launcher);
+
+ g_signal_connect (launcher->prop_dialog, "error_reported",
+ G_CALLBACK (launcher_error_reported), NULL);
+
+ g_signal_connect (launcher->prop_dialog, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &launcher->prop_dialog);
+
+ gtk_widget_show (launcher->prop_dialog);
+}
+
+static gboolean
+lancher_properties_enabled (void)
+{
+ if (panel_lockdown_get_locked_down () ||
+ panel_lockdown_get_disable_command_line ())
+ return FALSE;
+
+ return TRUE;
+}
+
+static Launcher *
+load_launcher_applet (const char *location,
+ PanelWidget *panel,
+ gboolean locked,
+ int pos,
+ gboolean exactpos,
+ const char *id)
+{
+ Launcher *launcher;
+
+ launcher = create_launcher (location);
+
+ if (!launcher)
+ return NULL;
+
+ launcher->info = mate_panel_applet_register (launcher->button, launcher,
+ free_launcher,
+ panel, locked, pos, exactpos,
+ PANEL_OBJECT_LAUNCHER, id);
+ if (!launcher->info) {
+ free_launcher (launcher);
+ return NULL;
+ }
+
+ mate_panel_applet_add_callback (launcher->info,
+ "launch",
+ GTK_STOCK_EXECUTE,
+ _("_Launch"),
+ NULL);
+
+ mate_panel_applet_add_callback (launcher->info,
+ "properties",
+ GTK_STOCK_PROPERTIES,
+ _("_Properties"),
+ lancher_properties_enabled);
+
+ panel_widget_set_applet_expandable (panel, GTK_WIDGET (launcher->button), FALSE, TRUE);
+ panel_widget_set_applet_size_constrained (panel, GTK_WIDGET (launcher->button), TRUE);
+
+ /* setup button according to ditem */
+ setup_button (launcher);
+
+ return launcher;
+}
+
+void
+launcher_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ int position,
+ const char *id)
+{
+ MateConfClient *client;
+ Launcher *launcher;
+ const char *key;
+ char *launcher_location;
+
+ g_return_if_fail (panel_widget != NULL);
+ g_return_if_fail (id != NULL);
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "launcher_location");
+ panel_compatibility_migrate_applications_scheme (client, key);
+ launcher_location = mateconf_client_get_string (client, key, NULL);
+
+ if (!launcher_location) {
+ g_printerr (_("Key %s is not set, cannot load launcher\n"),
+ key);
+ return;
+ }
+
+ launcher = load_launcher_applet (launcher_location,
+ panel_widget,
+ locked,
+ position,
+ TRUE,
+ id);
+
+ if (launcher) {
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "launcher_location");
+ if (!mateconf_client_key_is_writable (client, key, NULL)) {
+ AppletUserMenu *menu;
+
+ menu = mate_panel_applet_get_callback (launcher->info->user_menu,
+ "properties");
+ if (menu != NULL)
+ menu->sensitive = FALSE;
+ }
+ }
+
+ g_free (launcher_location);
+}
+
+static void
+launcher_new_saved (GtkWidget *dialog,
+ gpointer data)
+{
+ PanelWidget *panel;
+ int pos;
+ const char *uri;
+
+ pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "pos"));
+ panel = g_object_get_data (G_OBJECT (dialog), "panel");
+
+ uri = panel_ditem_editor_get_uri (PANEL_DITEM_EDITOR (dialog));
+ if (panel_launcher_get_filename (uri) != NULL)
+ uri = panel_launcher_get_filename (uri);
+ panel_launcher_create (panel->toplevel, pos, uri);
+}
+
+void
+ask_about_launcher (const char *file,
+ PanelWidget *panel,
+ int pos,
+ gboolean exactpos)
+{
+ GtkWidget *dialog;
+ GKeyFile *key_file;
+
+ if (panel_lockdown_get_disable_command_line ())
+ return;
+
+ dialog = panel_ditem_editor_new (NULL, NULL, NULL,
+ _("Create Launcher"));
+ panel_widget_register_open_dialog (panel, dialog);
+
+ key_file = panel_ditem_editor_get_key_file (PANEL_DITEM_EDITOR (dialog));
+ if (file != NULL)
+ panel_key_file_set_string (key_file, "Exec", file);
+ panel_key_file_set_string (key_file, "Type", "Application");
+ panel_ditem_editor_sync_display (PANEL_DITEM_EDITOR (dialog));
+
+ panel_ditem_register_save_uri_func (PANEL_DITEM_EDITOR (dialog),
+ launcher_save_uri,
+ NULL);
+
+ g_signal_connect (G_OBJECT (dialog), "saved",
+ G_CALLBACK (launcher_new_saved), NULL);
+
+ g_signal_connect (G_OBJECT (dialog), "error_reported",
+ G_CALLBACK (launcher_error_reported), NULL);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_widget_get_screen (GTK_WIDGET (panel)));
+
+ g_object_set_data (G_OBJECT (dialog), "pos", GINT_TO_POINTER (pos));
+ g_object_set_data (G_OBJECT (dialog), "panel", panel);
+
+ gtk_widget_show (dialog);
+}
+
+void
+panel_launcher_create_from_info (PanelToplevel *toplevel,
+ int position,
+ gboolean exec_info,
+ const char *exec_or_uri,
+ const char *name,
+ const char *comment,
+ const char *icon)
+{
+ GKeyFile *key_file;
+ char *location;
+ GError *error;
+
+ key_file = panel_key_file_new_desktop ();
+
+ /* set current language and the "C" locale to this name,
+ * this is kind of evil... */
+ panel_key_file_set_string (key_file, "Name", name);
+ panel_key_file_set_string (key_file, "Comment", comment);
+ panel_key_file_set_string (key_file, "Icon", icon);
+ panel_key_file_set_locale_string (key_file, "Name", name);
+ panel_key_file_set_locale_string (key_file, "Comment", comment);
+ panel_key_file_set_locale_string (key_file, "Icon", icon);
+
+ if (exec_info) {
+ panel_key_file_set_string (key_file, "Exec", exec_or_uri);
+ panel_key_file_set_string (key_file, "Type", "Application");
+ } else {
+ panel_key_file_set_string (key_file, "URL", exec_or_uri);
+ panel_key_file_set_string (key_file, "Type", "Link");
+ }
+
+ location = panel_make_unique_desktop_uri (NULL, exec_or_uri);
+
+ error = NULL;
+ if (panel_key_file_to_file (key_file, location, &error)) {
+ panel_launcher_create (toplevel, position, location);
+ } else {
+ panel_error_dialog (GTK_WINDOW (toplevel),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)),
+ "cannot_save_launcher", TRUE,
+ _("Could not save launcher"),
+ error->message);
+ g_error_free (error);
+ }
+
+ g_key_file_free (key_file);
+}
+
+void
+panel_launcher_create_with_id (const char *toplevel_id,
+ int position,
+ const char *location)
+{
+ MateConfClient *client;
+ const char *key;
+ char *id;
+ char *no_uri;
+ const char *new_location;
+
+ g_return_if_fail (location != NULL);
+
+ client = panel_mateconf_get_client ();
+
+ id = panel_profile_prepare_object_with_id (PANEL_OBJECT_LAUNCHER,
+ toplevel_id,
+ position,
+ FALSE);
+
+ no_uri = NULL;
+ /* if we have an URI, it might contain escaped characters (? : etc)
+ * that might get unescaped on disk */
+ if (!g_ascii_strncasecmp (location, "file:", strlen ("file:")))
+ no_uri = g_filename_from_uri (location, NULL, NULL);
+ if (!no_uri)
+ no_uri = g_strdup (location);
+
+ new_location = panel_launcher_get_filename (no_uri);
+ if (new_location == NULL)
+ new_location = no_uri;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS,
+ id,
+ "launcher_location");
+ mateconf_client_set_string (client, key, new_location, NULL);
+
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+
+ g_free (no_uri);
+ g_free (id);
+}
+
+void
+panel_launcher_create (PanelToplevel *toplevel,
+ int position,
+ const char *location)
+{
+ panel_launcher_create_with_id (panel_profile_get_toplevel_id (toplevel),
+ position,
+ location);
+}
+
+gboolean
+panel_launcher_create_copy (PanelToplevel *toplevel,
+ int position,
+ const char *location)
+{
+ char *new_location;
+ GFile *source;
+ GFile *dest;
+ gboolean copied;
+ const char *filename;
+
+ new_location = panel_make_unique_desktop_uri (NULL, location);
+
+ source = panel_launcher_get_gfile (location);
+ dest = g_file_new_for_uri (new_location);
+
+ copied = g_file_copy (source, dest, G_FILE_COPY_OVERWRITE,
+ NULL, NULL, NULL, NULL);
+
+ if (!copied) {
+ g_free (new_location);
+ return FALSE;
+ }
+
+ filename = panel_launcher_get_filename (new_location);
+ panel_launcher_create (toplevel, position, filename);
+ g_free (new_location);
+
+ return TRUE;
+}
+
+Launcher *
+find_launcher (const char *path)
+{
+ GSList *l;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ for (l = mate_panel_applet_list_applets (); l; l = l->next) {
+ AppletInfo *info = l->data;
+ Launcher *launcher;
+
+ if (info->type != PANEL_OBJECT_LAUNCHER)
+ continue;
+
+ launcher = info->data;
+
+ if (launcher->key_file == NULL)
+ continue;
+
+ if (launcher->location != NULL &&
+ strcmp (launcher->location, path) == 0)
+ return launcher;
+ }
+
+ return NULL;
+}
+
+void
+panel_launcher_set_dnd_enabled (Launcher *launcher,
+ gboolean dnd_enabled)
+{
+ GdkPixbuf *pixbuf;
+
+ if (dnd_enabled) {
+ static GtkTargetEntry dnd_targets[] = {
+ { "application/x-panel-icon-internal", 0, TARGET_ICON_INTERNAL },
+ { "text/uri-list", 0, TARGET_URI_LIST }
+ };
+
+ gtk_widget_set_has_window (launcher->button, TRUE);
+ gtk_drag_source_set (launcher->button,
+ GDK_BUTTON1_MASK,
+ dnd_targets, 2,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ //FIXME: this doesn't work since the pixbuf isn't loaded yet
+ pixbuf = button_widget_get_pixbuf (BUTTON_WIDGET (launcher->button));
+ if (pixbuf) {
+ gtk_drag_source_set_icon_pixbuf (launcher->button,
+ pixbuf);
+ g_object_unref (pixbuf);
+ }
+ gtk_widget_set_has_window (launcher->button, FALSE);
+
+
+ } else
+ gtk_drag_source_unset (launcher->button);
+}
diff --git a/mate-panel/launcher.h b/mate-panel/launcher.h
new file mode 100644
index 00000000..1b2d7b88
--- /dev/null
+++ b/mate-panel/launcher.h
@@ -0,0 +1,80 @@
+/*
+ * MATE panel launcher module.
+ * (C) 1997 The Free Software Foundation
+ *
+ * Authors: Miguel de Icaza
+ * Federico Mena
+ * CORBAized by George Lebl
+ * de-CORBAized by George Lebl
+ */
+
+#ifndef LAUNCHER_H
+#define LAUNCHER_H
+
+#include "applet.h"
+#include "panel-widget.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ AppletInfo *info;
+ GtkWidget *button;
+
+ char *location;
+ GKeyFile *key_file;
+
+ GtkWidget *prop_dialog;
+ GSList *error_dialogs;
+
+ gulong destroy_handler;
+} Launcher;
+
+void panel_launcher_create (PanelToplevel *toplevel,
+ int position,
+ const char *location);
+void panel_launcher_create_with_id (const char *toplevel_id,
+ int position,
+ const char *location);
+gboolean panel_launcher_create_copy (PanelToplevel *toplevel,
+ int position,
+ const char *location);
+void panel_launcher_create_from_info (PanelToplevel *toplevel,
+ int position,
+ gboolean exec_info,
+ const char *exec_or_uri,
+ const char *name,
+ const char *comment,
+ const char *icon);
+
+void launcher_launch (Launcher *launcher,
+ GtkWidget *widget);
+
+void launcher_properties (Launcher *launcher);
+
+void launcher_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ gint position,
+ const char *id);
+
+void panel_launcher_delete (Launcher *launcher);
+
+void ask_about_launcher (const char *file,
+ PanelWidget *panel,
+ int pos,
+ gboolean exactpos);
+
+Launcher * find_launcher (const char *path);
+
+void launcher_properties_destroy (Launcher *launcher);
+
+void panel_launcher_set_dnd_enabled (Launcher *launcher,
+ gboolean dnd_enabled);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mate-panel/libegg/Makefile.am b/mate-panel/libegg/Makefile.am
new file mode 100644
index 00000000..c50c1fa0
--- /dev/null
+++ b/mate-panel/libegg/Makefile.am
@@ -0,0 +1,25 @@
+platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
+platform_sources = eggsmclient-xsmp.c
+
+noinst_LTLIBRARIES = libegg.la
+
+AM_CPPFLAGS = \
+ $(EGG_SMCLIENT_CFLAGS) \
+ -DG_LOG_DOMAIN=\""EggSMClient"\"\
+ $(platform_defines) \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+
+libegg_la_SOURCES = \
+ eggdesktopfile.c \
+ eggdesktopfile.h \
+ eggsmclient.c \
+ eggsmclient.h \
+ eggsmclient-private.h \
+ $(platform_sources)
+
+libegg_la_LIBADD = \
+ $(EGG_SMCLIENT_LIBS)
+
+-include $(top_srcdir)/git.mk
diff --git a/mate-panel/libegg/Makefile.in b/mate-panel/libegg/Makefile.in
new file mode 100644
index 00000000..742fd6ed
--- /dev/null
+++ b/mate-panel/libegg/Makefile.in
@@ -0,0 +1,622 @@
+# 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 = mate-panel/libegg
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/d-type.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/mate-doc-utils.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 =
+libegg_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__objects_1 = eggsmclient-xsmp.lo
+am_libegg_la_OBJECTS = eggdesktopfile.lo eggsmclient.lo \
+ $(am__objects_1)
+libegg_la_OBJECTS = $(am_libegg_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libegg_la_SOURCES)
+DIST_SOURCES = $(libegg_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CLOCK_CFLAGS = @CLOCK_CFLAGS@
+CLOCK_EDS_ICONDIR = @CLOCK_EDS_ICONDIR@
+CLOCK_LIBS = @CLOCK_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DISABLE_DEPRECATED_CFLAGS = @DISABLE_DEPRECATED_CFLAGS@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DLLTOOL = @DLLTOOL@
+DOC_USER_FORMATS = @DOC_USER_FORMATS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGG_SMCLIENT_CFLAGS = @EGG_SMCLIENT_CFLAGS@
+EGG_SMCLIENT_LIBS = @EGG_SMCLIENT_LIBS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FISH_CFLAGS = @FISH_CFLAGS@
+FISH_LIBS = @FISH_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_QUERYMODULES = @GIO_QUERYMODULES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+HELP_DIR = @HELP_DIR@
+HTML_DIR = @HTML_DIR@
+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@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBMATE_PANEL_APPLET_CFLAGS = @LIBMATE_PANEL_APPLET_CFLAGS@
+LIBMATE_PANEL_APPLET_LIBS = @LIBMATE_PANEL_APPLET_LIBS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MATE_PANEL_APPLET_LT_VERSION = @LIB_MATE_PANEL_APPLET_LT_VERSION@
+LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION = @LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECOMPONENT_ACT_IDLDIR = @MATECOMPONENT_ACT_IDLDIR@
+MATECOMPONENT_CFLAGS = @MATECOMPONENT_CFLAGS@
+MATECOMPONENT_IDLDIR = @MATECOMPONENT_IDLDIR@
+MATECOMPONENT_LIBS = @MATECOMPONENT_LIBS@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATECORBA_IDL = @MATECORBA_IDL@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NETWORK_MANAGER_CFLAGS = @NETWORK_MANAGER_CFLAGS@
+NETWORK_MANAGER_LIBS = @NETWORK_MANAGER_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NOTIFICATION_AREA_CFLAGS = @NOTIFICATION_AREA_CFLAGS@
+NOTIFICATION_AREA_LIBS = @NOTIFICATION_AREA_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OMF_DIR = @OMF_DIR@
+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@
+PANEL_CFLAGS = @PANEL_CFLAGS@
+PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE = @PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE@
+PANEL_LIBS = @PANEL_LIBS@
+PANEL_MODULE_MATECOMPONENT_CFLAGS = @PANEL_MODULE_MATECOMPONENT_CFLAGS@
+PANEL_MODULE_MATECOMPONENT_LIBS = @PANEL_MODULE_MATECOMPONENT_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+REBUILD = @REBUILD@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TZ_CFLAGS = @TZ_CFLAGS@
+TZ_LIBS = @TZ_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WNCKLET_CFLAGS = @WNCKLET_CFLAGS@
+WNCKLET_LIBS = @WNCKLET_LIBS@
+XGETTEXT = @XGETTEXT@
+XMKMF = @XMKMF@
+XRANDR_CFLAGS = @XRANDR_CFLAGS@
+XRANDR_LIBS = @XRANDR_LIBS@
+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_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@
+appletsdir = @appletsdir@
+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@
+modulesdir = @modulesdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+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@
+platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
+platform_sources = eggsmclient-xsmp.c
+noinst_LTLIBRARIES = libegg.la
+AM_CPPFLAGS = \
+ $(EGG_SMCLIENT_CFLAGS) \
+ -DG_LOG_DOMAIN=\""EggSMClient"\"\
+ $(platform_defines) \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+libegg_la_SOURCES = \
+ eggdesktopfile.c \
+ eggdesktopfile.h \
+ eggsmclient.c \
+ eggsmclient.h \
+ eggsmclient-private.h \
+ $(platform_sources)
+
+libegg_la_LIBADD = \
+ $(EGG_SMCLIENT_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 mate-panel/libegg/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu mate-panel/libegg/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(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
+libegg.la: $(libegg_la_OBJECTS) $(libegg_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libegg_la_OBJECTS) $(libegg_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eggdesktopfile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eggsmclient-xsmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eggsmclient.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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."
+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
+
+
+-include $(top_srcdir)/git.mk
+
+# 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/mate-panel/libegg/eggdesktopfile.c b/mate-panel/libegg/eggdesktopfile.c
new file mode 100644
index 00000000..5ac79507
--- /dev/null
+++ b/mate-panel/libegg/eggdesktopfile.c
@@ -0,0 +1,1510 @@
+/* eggdesktopfile.c - Freedesktop.Org Desktop Files
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * Based on mate-desktop-item.c
+ * Copyright (C) 1999, 2000 Red Hat Inc.
+ * Copyright (C) 2001 George Lebl
+ *
+ * This library 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 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place -
+ * Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "eggdesktopfile.h"
+
+#include <string.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+struct EggDesktopFile {
+ GKeyFile *key_file;
+ char *source;
+
+ char *name, *icon;
+ EggDesktopFileType type;
+ char document_code;
+};
+
+/**
+ * egg_desktop_file_new:
+ * @desktop_file_path: path to a Freedesktop-style Desktop file
+ * @error: error pointer
+ *
+ * Creates a new #EggDesktopFile for @desktop_file.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new (const char *desktop_file_path, GError **error)
+{
+ GKeyFile *key_file;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (key_file, desktop_file_path, 0, error))
+ {
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ return egg_desktop_file_new_from_key_file (key_file, desktop_file_path,
+ error);
+}
+
+/**
+ * egg_desktop_file_new_from_data_dirs:
+ * @desktop_file_path: relative path to a Freedesktop-style Desktop file
+ * @error: error pointer
+ *
+ * Looks for @desktop_file_path in the paths returned from
+ * g_get_user_data_dir() and g_get_system_data_dirs(), and creates
+ * a new #EggDesktopFile from it.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
+ GError **error)
+{
+ EggDesktopFile *desktop_file;
+ GKeyFile *key_file;
+ char *full_path;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_data_dirs (key_file, desktop_file_path,
+ &full_path, 0, error))
+ {
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ desktop_file = egg_desktop_file_new_from_key_file (key_file,
+ full_path,
+ error);
+ g_free (full_path);
+ return desktop_file;
+}
+
+/**
+ * egg_desktop_file_new_from_dirs:
+ * @desktop_file_path: relative path to a Freedesktop-style Desktop file
+ * @search_dirs: NULL-terminated array of directories to search
+ * @error: error pointer
+ *
+ * Looks for @desktop_file_path in the paths returned from
+ * g_get_user_data_dir() and g_get_system_data_dirs(), and creates
+ * a new #EggDesktopFile from it.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_dirs (const char *desktop_file_path,
+ const char **search_dirs,
+ GError **error)
+{
+ EggDesktopFile *desktop_file;
+ GKeyFile *key_file;
+ char *full_path;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_dirs (key_file, desktop_file_path, search_dirs,
+ &full_path, 0, error))
+ {
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ desktop_file = egg_desktop_file_new_from_key_file (key_file,
+ full_path,
+ error);
+ g_free (full_path);
+ return desktop_file;
+}
+
+/**
+ * egg_desktop_file_new_from_key_file:
+ * @key_file: a #GKeyFile representing a desktop file
+ * @source: the path or URI that @key_file was loaded from, or %NULL
+ * @error: error pointer
+ *
+ * Creates a new #EggDesktopFile for @key_file. Assumes ownership of
+ * @key_file (on success or failure); you should consider @key_file to
+ * be freed after calling this function.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_key_file (GKeyFile *key_file,
+ const char *source,
+ GError **error)
+{
+ EggDesktopFile *desktop_file;
+ char *version, *type;
+
+ if (!g_key_file_has_group (key_file, EGG_DESKTOP_FILE_GROUP))
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_INVALID,
+ _("File is not a valid .desktop file"));
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ version = g_key_file_get_value (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_VERSION,
+ NULL);
+ if (version)
+ {
+ double version_num;
+ char *end;
+
+ version_num = g_ascii_strtod (version, &end);
+ if (*end)
+ {
+ g_warning ("Invalid Version string '%s' in %s",
+ version, source ? source : "(unknown)");
+ }
+ else if (version_num > 1.0)
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_INVALID,
+ _("Unrecognized desktop file Version '%s'"), version);
+ g_free (version);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+ g_free (version);
+ }
+
+ desktop_file = g_new0 (EggDesktopFile, 1);
+ desktop_file->key_file = key_file;
+
+ if (g_path_is_absolute (source))
+ desktop_file->source = g_filename_to_uri (source, NULL, NULL);
+ else
+ desktop_file->source = g_strdup (source);
+
+ desktop_file->name = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_NAME, error);
+ if (!desktop_file->name)
+ {
+ egg_desktop_file_free (desktop_file);
+ return NULL;
+ }
+
+ type = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TYPE, error);
+ if (!type)
+ {
+ egg_desktop_file_free (desktop_file);
+ return NULL;
+ }
+
+ if (!strcmp (type, "Application"))
+ {
+ char *exec, *p;
+
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_APPLICATION;
+
+ exec = g_key_file_get_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ error);
+ if (!exec)
+ {
+ egg_desktop_file_free (desktop_file);
+ g_free (type);
+ return NULL;
+ }
+
+ /* See if it takes paths or URIs or neither */
+ for (p = exec; *p; p++)
+ {
+ if (*p == '%')
+ {
+ if (p[1] == '\0' || strchr ("FfUu", p[1]))
+ {
+ desktop_file->document_code = p[1];
+ break;
+ }
+ p++;
+ }
+ }
+
+ g_free (exec);
+ }
+ else if (!strcmp (type, "Link"))
+ {
+ char *url;
+
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_LINK;
+
+ url = g_key_file_get_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_URL,
+ error);
+ if (!url)
+ {
+ egg_desktop_file_free (desktop_file);
+ g_free (type);
+ return NULL;
+ }
+ g_free (url);
+ }
+ else if (!strcmp (type, "Directory"))
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_DIRECTORY;
+ else
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED;
+
+ g_free (type);
+
+ /* Check the Icon key */
+ desktop_file->icon = g_key_file_get_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_ICON,
+ NULL);
+ if (desktop_file->icon && !g_path_is_absolute (desktop_file->icon))
+ {
+ char *ext;
+
+ /* Lots of .desktop files still get this wrong */
+ ext = strrchr (desktop_file->icon, '.');
+ if (ext && (!strcmp (ext, ".png") ||
+ !strcmp (ext, ".xpm") ||
+ !strcmp (ext, ".svg")))
+ {
+ g_warning ("Desktop file '%s' has malformed Icon key '%s'"
+ "(should not include extension)",
+ source ? source : "(unknown)",
+ desktop_file->icon);
+ *ext = '\0';
+ }
+ }
+
+ return desktop_file;
+}
+
+/**
+ * egg_desktop_file_free:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Frees @desktop_file.
+ **/
+void
+egg_desktop_file_free (EggDesktopFile *desktop_file)
+{
+ g_key_file_free (desktop_file->key_file);
+ g_free (desktop_file->source);
+ g_free (desktop_file->name);
+ g_free (desktop_file->icon);
+ g_free (desktop_file);
+}
+
+/**
+ * egg_desktop_file_get_source:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the URI that @desktop_file was loaded from.
+ *
+ * Return value: @desktop_file's source URI
+ **/
+const char *
+egg_desktop_file_get_source (EggDesktopFile *desktop_file)
+{
+ return desktop_file->source;
+}
+
+/**
+ * egg_desktop_file_get_desktop_file_type:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the desktop file type of @desktop_file.
+ *
+ * Return value: @desktop_file's type
+ **/
+EggDesktopFileType
+egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file)
+{
+ return desktop_file->type;
+}
+
+/**
+ * egg_desktop_file_get_name:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the (localized) value of @desktop_file's "Name" key.
+ *
+ * Return value: the application/link name
+ **/
+const char *
+egg_desktop_file_get_name (EggDesktopFile *desktop_file)
+{
+ return desktop_file->name;
+}
+
+/**
+ * egg_desktop_file_get_icon:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the value of @desktop_file's "Icon" key.
+ *
+ * If the icon string is a full path (that is, if g_path_is_absolute()
+ * returns %TRUE when called on it), it points to a file containing an
+ * unthemed icon. If the icon string is not a full path, it is the
+ * name of a themed icon, which can be looked up with %GtkIconTheme,
+ * or passed directly to a theme-aware widget like %GtkImage or
+ * %GtkCellRendererPixbuf.
+ *
+ * Return value: the icon path or name
+ **/
+const char *
+egg_desktop_file_get_icon (EggDesktopFile *desktop_file)
+{
+ return desktop_file->icon;
+}
+
+gboolean
+egg_desktop_file_has_key (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_has_key (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+char *
+egg_desktop_file_get_string (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+char *
+egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ GError **error)
+{
+ return g_key_file_get_locale_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key, locale,
+ error);
+}
+
+gboolean
+egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_boolean (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+double
+egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_double (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+char **
+egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ gsize *length,
+ GError **error)
+{
+ return g_key_file_get_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key, length,
+ error);
+}
+
+char **
+egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ gsize *length,
+ GError **error)
+{
+ return g_key_file_get_locale_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ locale, length,
+ error);
+}
+
+/**
+ * egg_desktop_file_can_launch:
+ * @desktop_file: an #EggDesktopFile
+ * @desktop_environment: the name of the running desktop environment,
+ * or %NULL
+ *
+ * Tests if @desktop_file can/should be launched in the current
+ * environment. If @desktop_environment is non-%NULL, @desktop_file's
+ * "OnlyShowIn" and "NotShowIn" keys are checked to make sure that
+ * this desktop_file is appropriate for the named environment.
+ *
+ * Furthermore, if @desktop_file has type
+ * %EGG_DESKTOP_FILE_TYPE_APPLICATION, its "TryExec" key (if any) is
+ * also checked, to make sure the binary it points to exists.
+ *
+ * egg_desktop_file_can_launch() does NOT check the value of the
+ * "Hidden" key.
+ *
+ * Return value: %TRUE if @desktop_file can be launched
+ **/
+gboolean
+egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
+ const char *desktop_environment)
+{
+ char *try_exec, *found_program;
+ char **only_show_in, **not_show_in;
+ gboolean found;
+ int i;
+
+ if (desktop_file->type != EGG_DESKTOP_FILE_TYPE_APPLICATION &&
+ desktop_file->type != EGG_DESKTOP_FILE_TYPE_LINK)
+ return FALSE;
+
+ if (desktop_environment)
+ {
+ only_show_in = g_key_file_get_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN,
+ NULL, NULL);
+ if (only_show_in)
+ {
+ for (i = 0, found = FALSE; only_show_in[i] && !found; i++)
+ {
+ if (!strcmp (only_show_in[i], desktop_environment))
+ found = TRUE;
+ }
+
+ g_strfreev (only_show_in);
+
+ if (!found)
+ return FALSE;
+ }
+
+ not_show_in = g_key_file_get_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN,
+ NULL, NULL);
+ if (not_show_in)
+ {
+ for (i = 0, found = FALSE; not_show_in[i] && !found; i++)
+ {
+ if (!strcmp (not_show_in[i], desktop_environment))
+ found = TRUE;
+ }
+
+ g_strfreev (not_show_in);
+
+ if (found)
+ return FALSE;
+ }
+ }
+
+ if (desktop_file->type == EGG_DESKTOP_FILE_TYPE_APPLICATION)
+ {
+ try_exec = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TRY_EXEC,
+ NULL);
+ if (try_exec)
+ {
+ found_program = g_find_program_in_path (try_exec);
+ g_free (try_exec);
+
+ if (!found_program)
+ return FALSE;
+ g_free (found_program);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * egg_desktop_file_accepts_documents:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file represents an application that can accept
+ * documents on the command line.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file)
+{
+ return desktop_file->document_code != 0;
+}
+
+/**
+ * egg_desktop_file_accepts_multiple:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file can accept multiple documents at once.
+ *
+ * If this returns %FALSE, you can still pass multiple documents to
+ * egg_desktop_file_launch(), but that will result in multiple copies
+ * of the application being launched. See egg_desktop_file_launch()
+ * for more details.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file)
+{
+ return (desktop_file->document_code == 'F' ||
+ desktop_file->document_code == 'U');
+}
+
+/**
+ * egg_desktop_file_accepts_uris:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file can accept (non-"file:") URIs as documents to
+ * open.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file)
+{
+ return (desktop_file->document_code == 'U' ||
+ desktop_file->document_code == 'u');
+}
+
+static void
+append_quoted_word (GString *str,
+ const char *s,
+ gboolean in_single_quotes,
+ gboolean in_double_quotes)
+{
+ const char *p;
+
+ if (!in_single_quotes && !in_double_quotes)
+ g_string_append_c (str, '\'');
+ else if (!in_single_quotes && in_double_quotes)
+ g_string_append (str, "\"'");
+
+ if (!strchr (s, '\''))
+ g_string_append (str, s);
+ else
+ {
+ for (p = s; *p != '\0'; p++)
+ {
+ if (*p == '\'')
+ g_string_append (str, "'\\''");
+ else
+ g_string_append_c (str, *p);
+ }
+ }
+
+ if (!in_single_quotes && !in_double_quotes)
+ g_string_append_c (str, '\'');
+ else if (!in_single_quotes && in_double_quotes)
+ g_string_append (str, "'\"");
+}
+
+static void
+do_percent_subst (EggDesktopFile *desktop_file,
+ char code,
+ GString *str,
+ GSList **documents,
+ gboolean in_single_quotes,
+ gboolean in_double_quotes)
+{
+ GSList *d;
+ char *doc;
+
+ switch (code)
+ {
+ case '%':
+ g_string_append_c (str, '%');
+ break;
+
+ case 'F':
+ case 'U':
+ for (d = *documents; d; d = d->next)
+ {
+ doc = d->data;
+ g_string_append (str, " ");
+ append_quoted_word (str, doc, in_single_quotes, in_double_quotes);
+ }
+ *documents = NULL;
+ break;
+
+ case 'f':
+ case 'u':
+ if (*documents)
+ {
+ doc = (*documents)->data;
+ g_string_append (str, " ");
+ append_quoted_word (str, doc, in_single_quotes, in_double_quotes);
+ *documents = (*documents)->next;
+ }
+ break;
+
+ case 'i':
+ if (desktop_file->icon)
+ {
+ g_string_append (str, "--icon ");
+ append_quoted_word (str, desktop_file->icon,
+ in_single_quotes, in_double_quotes);
+ }
+ break;
+
+ case 'c':
+ if (desktop_file->name)
+ {
+ append_quoted_word (str, desktop_file->name,
+ in_single_quotes, in_double_quotes);
+ }
+ break;
+
+ case 'k':
+ if (desktop_file->source)
+ {
+ append_quoted_word (str, desktop_file->source,
+ in_single_quotes, in_double_quotes);
+ }
+ break;
+
+ case 'D':
+ case 'N':
+ case 'd':
+ case 'n':
+ case 'v':
+ case 'm':
+ /* Deprecated; skip */
+ break;
+
+ default:
+ g_warning ("Unrecognized %%-code '%%%c' in Exec", code);
+ break;
+ }
+}
+
+static char *
+parse_exec (EggDesktopFile *desktop_file,
+ GSList **documents,
+ GError **error)
+{
+ char *exec, *p, *command;
+ gboolean escape, single_quot, double_quot;
+ GString *gs;
+
+ exec = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ error);
+ if (!exec)
+ return NULL;
+
+ /* Build the command */
+ gs = g_string_new (NULL);
+ escape = single_quot = double_quot = FALSE;
+
+ for (p = exec; *p != '\0'; p++)
+ {
+ if (escape)
+ {
+ escape = FALSE;
+ g_string_append_c (gs, *p);
+ }
+ else if (*p == '\\')
+ {
+ if (!single_quot)
+ escape = TRUE;
+ g_string_append_c (gs, *p);
+ }
+ else if (*p == '\'')
+ {
+ g_string_append_c (gs, *p);
+ if (!single_quot && !double_quot)
+ single_quot = TRUE;
+ else if (single_quot)
+ single_quot = FALSE;
+ }
+ else if (*p == '"')
+ {
+ g_string_append_c (gs, *p);
+ if (!single_quot && !double_quot)
+ double_quot = TRUE;
+ else if (double_quot)
+ double_quot = FALSE;
+ }
+ else if (*p == '%' && p[1])
+ {
+ do_percent_subst (desktop_file, p[1], gs, documents,
+ single_quot, double_quot);
+ p++;
+ }
+ else
+ g_string_append_c (gs, *p);
+ }
+
+ g_free (exec);
+ command = g_string_free (gs, FALSE);
+
+ /* Prepend "xdg-terminal " if needed (FIXME: use gvfs) */
+ if (g_key_file_has_key (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TERMINAL,
+ NULL))
+ {
+ GError *terminal_error = NULL;
+ gboolean use_terminal =
+ g_key_file_get_boolean (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TERMINAL,
+ &terminal_error);
+ if (terminal_error)
+ {
+ g_free (command);
+ g_propagate_error (error, terminal_error);
+ return NULL;
+ }
+
+ if (use_terminal)
+ {
+ gs = g_string_new ("xdg-terminal ");
+ append_quoted_word (gs, command, FALSE, FALSE);
+ g_free (command);
+ command = g_string_free (gs, FALSE);
+ }
+ }
+
+ return command;
+}
+
+static GSList *
+translate_document_list (EggDesktopFile *desktop_file, GSList *documents)
+{
+ gboolean accepts_uris = egg_desktop_file_accepts_uris (desktop_file);
+ GSList *ret, *d;
+
+ for (d = documents, ret = NULL; d; d = d->next)
+ {
+ const char *document = d->data;
+ gboolean is_uri = !g_path_is_absolute (document);
+ char *translated;
+
+ if (accepts_uris)
+ {
+ if (is_uri)
+ translated = g_strdup (document);
+ else
+ translated = g_filename_to_uri (document, NULL, NULL);
+ }
+ else
+ {
+ if (is_uri)
+ translated = g_filename_from_uri (document, NULL, NULL);
+ else
+ translated = g_strdup (document);
+ }
+
+ if (translated)
+ ret = g_slist_prepend (ret, translated);
+ }
+
+ return g_slist_reverse (ret);
+}
+
+static void
+free_document_list (GSList *documents)
+{
+ GSList *d;
+
+ for (d = documents; d; d = d->next)
+ g_free (d->data);
+ g_slist_free (documents);
+}
+
+/**
+ * egg_desktop_file_parse_exec:
+ * @desktop_file: a #EggDesktopFile
+ * @documents: a list of document paths or URIs
+ * @error: error pointer
+ *
+ * Parses @desktop_file's Exec key, inserting @documents into it, and
+ * returns the result.
+ *
+ * If @documents contains non-file: URIs and @desktop_file does not
+ * accept URIs, those URIs will be ignored. Likewise, if @documents
+ * contains more elements than @desktop_file accepts, the extra
+ * documents will be ignored.
+ *
+ * Return value: the parsed Exec string
+ **/
+char *
+egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
+ GSList *documents,
+ GError **error)
+{
+ GSList *translated, *docs;
+ char *command;
+
+ docs = translated = translate_document_list (desktop_file, documents);
+ command = parse_exec (desktop_file, &docs, error);
+ free_document_list (translated);
+
+ return command;
+}
+
+static gboolean
+parse_link (EggDesktopFile *desktop_file,
+ EggDesktopFile **app_desktop_file,
+ GSList **documents,
+ GError **error)
+{
+ char *url;
+ GKeyFile *key_file;
+
+ url = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_URL,
+ error);
+ if (!url)
+ return FALSE;
+ *documents = g_slist_prepend (NULL, url);
+
+ /* FIXME: use gvfs */
+ key_file = g_key_file_new ();
+ g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_NAME,
+ "xdg-open");
+ g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TYPE,
+ "Application");
+ g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ "xdg-open %u");
+ *app_desktop_file = egg_desktop_file_new_from_key_file (key_file, NULL, NULL);
+ return TRUE;
+}
+
+#if GTK_CHECK_VERSION (2, 12, 0)
+static char *
+start_startup_notification (GdkDisplay *display,
+ EggDesktopFile *desktop_file,
+ const char *argv0,
+ int screen,
+ int workspace,
+ guint32 launch_time)
+{
+ static int sequence = 0;
+ char *startup_id;
+ char *description, *wmclass;
+ char *screen_str, *workspace_str;
+
+ if (g_key_file_has_key (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY,
+ NULL))
+ {
+ if (!g_key_file_get_boolean (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY,
+ NULL))
+ return NULL;
+ wmclass = NULL;
+ }
+ else
+ {
+ wmclass = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS,
+ NULL);
+ if (!wmclass)
+ return NULL;
+ }
+
+ if (launch_time == (guint32)-1)
+ launch_time = gdk_x11_display_get_user_time (display);
+ startup_id = g_strdup_printf ("%s-%lu-%s-%s-%d_TIME%lu",
+ g_get_prgname (),
+ (unsigned long)getpid (),
+ g_get_host_name (),
+ argv0,
+ sequence++,
+ (unsigned long)launch_time);
+
+ description = g_strdup_printf (_("Starting %s"), desktop_file->name);
+ screen_str = g_strdup_printf ("%d", screen);
+ workspace_str = workspace == -1 ? NULL : g_strdup_printf ("%d", workspace);
+
+ gdk_x11_display_broadcast_startup_message (display, "new",
+ "ID", startup_id,
+ "NAME", desktop_file->name,
+ "SCREEN", screen_str,
+ "BIN", argv0,
+ "ICON", desktop_file->icon,
+ "DESKTOP", workspace_str,
+ "DESCRIPTION", description,
+ "WMCLASS", wmclass,
+ NULL);
+
+ g_free (description);
+ g_free (wmclass);
+ g_free (screen_str);
+ g_free (workspace_str);
+
+ return startup_id;
+}
+
+static void
+end_startup_notification (GdkDisplay *display,
+ const char *startup_id)
+{
+ gdk_x11_display_broadcast_startup_message (display, "remove",
+ "ID", startup_id,
+ NULL);
+}
+
+#define EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH (30 /* seconds */)
+
+typedef struct {
+ GdkDisplay *display;
+ char *startup_id;
+} StartupNotificationData;
+
+static gboolean
+startup_notification_timeout (gpointer data)
+{
+ StartupNotificationData *sn_data = data;
+
+ end_startup_notification (sn_data->display, sn_data->startup_id);
+ g_object_unref (sn_data->display);
+ g_free (sn_data->startup_id);
+ g_free (sn_data);
+
+ return FALSE;
+}
+
+static void
+set_startup_notification_timeout (GdkDisplay *display,
+ const char *startup_id)
+{
+ StartupNotificationData *sn_data;
+
+ sn_data = g_new (StartupNotificationData, 1);
+ sn_data->display = g_object_ref (display);
+ sn_data->startup_id = g_strdup (startup_id);
+
+ g_timeout_add_seconds (EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH,
+ startup_notification_timeout, sn_data);
+}
+#endif /* GTK 2.12 */
+
+static GPtrArray *
+array_putenv (GPtrArray *env, char *variable)
+{
+ guint i, keylen;
+
+ if (!env)
+ {
+ char **envp;
+
+ env = g_ptr_array_new ();
+
+ envp = g_listenv ();
+ for (i = 0; envp[i]; i++)
+ {
+ const char *value;
+
+ value = g_getenv (envp[i]);
+ g_ptr_array_add (env, g_strdup_printf ("%s=%s", envp[i],
+ value ? value : ""));
+ }
+ g_strfreev (envp);
+ }
+
+ keylen = strcspn (variable, "=");
+
+ /* Remove old value of key */
+ for (i = 0; i < env->len; i++)
+ {
+ char *envvar = env->pdata[i];
+
+ if (!strncmp (envvar, variable, keylen) && envvar[keylen] == '=')
+ {
+ g_free (envvar);
+ g_ptr_array_remove_index_fast (env, i);
+ break;
+ }
+ }
+
+ /* Add new value */
+ g_ptr_array_add (env, g_strdup (variable));
+
+ return env;
+}
+
+static gboolean
+egg_desktop_file_launchv (EggDesktopFile *desktop_file,
+ GSList *documents, va_list args,
+ GError **error)
+{
+ EggDesktopFileLaunchOption option;
+ GSList *translated_documents = NULL, *docs = NULL;
+ char *command, **argv;
+ int argc, i, screen_num;
+ gboolean success, current_success;
+ GdkDisplay *display;
+ char *startup_id;
+
+ GPtrArray *env = NULL;
+ char **variables = NULL;
+ GdkScreen *screen = NULL;
+ int workspace = -1;
+ const char *directory = NULL;
+ guint32 launch_time = (guint32)-1;
+ GSpawnFlags flags = G_SPAWN_SEARCH_PATH;
+ GSpawnChildSetupFunc setup_func = NULL;
+ gpointer setup_data = NULL;
+
+ GPid *ret_pid = NULL;
+ int *ret_stdin = NULL, *ret_stdout = NULL, *ret_stderr = NULL;
+ char **ret_startup_id = NULL;
+
+ if (documents && desktop_file->document_code == 0)
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ _("Application does not accept documents on command line"));
+ return FALSE;
+ }
+
+ /* Read the options: technically it's incorrect for the caller to
+ * NULL-terminate the list of options (rather than 0-terminating
+ * it), but NULL-terminating lets us use G_GNUC_NULL_TERMINATED,
+ * it's more consistent with other glib/gtk methods, and it will
+ * work as long as sizeof (int) <= sizeof (NULL), and NULL is
+ * represented as 0. (Which is true everywhere we care about.)
+ */
+ while ((option = va_arg (args, EggDesktopFileLaunchOption)))
+ {
+ switch (option)
+ {
+ case EGG_DESKTOP_FILE_LAUNCH_CLEARENV:
+ if (env)
+ g_ptr_array_free (env, TRUE);
+ env = g_ptr_array_new ();
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_PUTENV:
+ variables = va_arg (args, char **);
+ for (i = 0; variables[i]; i++)
+ env = array_putenv (env, variables[i]);
+ break;
+
+ case EGG_DESKTOP_FILE_LAUNCH_SCREEN:
+ screen = va_arg (args, GdkScreen *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_WORKSPACE:
+ workspace = va_arg (args, int);
+ break;
+
+ case EGG_DESKTOP_FILE_LAUNCH_DIRECTORY:
+ directory = va_arg (args, const char *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_TIME:
+ launch_time = va_arg (args, guint32);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_FLAGS:
+ flags |= va_arg (args, GSpawnFlags);
+ /* Make sure they didn't set any flags that don't make sense. */
+ flags &= ~G_SPAWN_FILE_AND_ARGV_ZERO;
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC:
+ setup_func = va_arg (args, GSpawnChildSetupFunc);
+ setup_data = va_arg (args, gpointer);
+ break;
+
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_PID:
+ ret_pid = va_arg (args, GPid *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE:
+ ret_stdin = va_arg (args, int *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE:
+ ret_stdout = va_arg (args, int *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE:
+ ret_stderr = va_arg (args, int *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID:
+ ret_startup_id = va_arg (args, char **);
+ break;
+
+ default:
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION,
+ _("Unrecognized launch option: %d"),
+ GPOINTER_TO_INT (option));
+ success = FALSE;
+ goto out;
+ }
+ }
+
+ if (screen)
+ {
+ char *display_name = gdk_screen_make_display_name (screen);
+ char *display_env = g_strdup_printf ("DISPLAY=%s", display_name);
+ env = array_putenv (env, display_env);
+ g_free (display_name);
+ g_free (display_env);
+
+ display = gdk_screen_get_display (screen);
+ }
+ else
+ {
+ display = gdk_display_get_default ();
+ screen = gdk_display_get_default_screen (display);
+ }
+ screen_num = gdk_screen_get_number (screen);
+
+ translated_documents = translate_document_list (desktop_file, documents);
+ docs = translated_documents;
+
+ success = FALSE;
+
+ do
+ {
+ command = parse_exec (desktop_file, &docs, error);
+ if (!command)
+ goto out;
+
+ if (!g_shell_parse_argv (command, &argc, &argv, error))
+ {
+ g_free (command);
+ goto out;
+ }
+ g_free (command);
+
+#if GTK_CHECK_VERSION (2, 12, 0)
+ startup_id = start_startup_notification (display, desktop_file,
+ argv[0], screen_num,
+ workspace, launch_time);
+ if (startup_id)
+ {
+ char *startup_id_env = g_strdup_printf ("DESKTOP_STARTUP_ID=%s",
+ startup_id);
+ env = array_putenv (env, startup_id_env);
+ g_free (startup_id_env);
+ }
+#else
+ startup_id = NULL;
+#endif /* GTK 2.12 */
+
+ if (env != NULL)
+ g_ptr_array_add (env, NULL);
+
+ current_success =
+ g_spawn_async_with_pipes (directory,
+ argv,
+ env ? (char **)(env->pdata) : NULL,
+ flags,
+ setup_func, setup_data,
+ ret_pid,
+ ret_stdin, ret_stdout, ret_stderr,
+ error);
+ g_strfreev (argv);
+
+ if (startup_id)
+ {
+#if GTK_CHECK_VERSION (2, 12, 0)
+ if (current_success)
+ {
+ set_startup_notification_timeout (display, startup_id);
+
+ if (ret_startup_id)
+ *ret_startup_id = startup_id;
+ else
+ g_free (startup_id);
+ }
+ else
+#endif /* GTK 2.12 */
+ g_free (startup_id);
+ }
+ else if (ret_startup_id)
+ *ret_startup_id = NULL;
+
+ if (current_success)
+ {
+ /* If we successfully launch any instances of the app, make
+ * sure we return TRUE and don't set @error.
+ */
+ success = TRUE;
+ error = NULL;
+
+ /* Also, only set the output params on the first one */
+ ret_pid = NULL;
+ ret_stdin = ret_stdout = ret_stderr = NULL;
+ ret_startup_id = NULL;
+ }
+ }
+ while (docs && current_success);
+
+ out:
+ if (env)
+ {
+ g_ptr_array_foreach (env, (GFunc)g_free, NULL);
+ g_ptr_array_free (env, TRUE);
+ }
+ free_document_list (translated_documents);
+
+ return success;
+}
+
+/**
+ * egg_desktop_file_launch:
+ * @desktop_file: an #EggDesktopFile
+ * @documents: a list of URIs or paths to documents to open
+ * @error: error pointer
+ * @...: additional options
+ *
+ * Launches @desktop_file with the given arguments. Additional options
+ * can be specified as follows:
+ *
+ * %EGG_DESKTOP_FILE_LAUNCH_CLEARENV: (no arguments)
+ * clears the environment in the child process
+ * %EGG_DESKTOP_FILE_LAUNCH_PUTENV: (char **variables)
+ * adds the NAME=VALUE strings in the given %NULL-terminated
+ * array to the child process's environment
+ * %EGG_DESKTOP_FILE_LAUNCH_SCREEN: (GdkScreen *screen)
+ * causes the application to be launched on the given screen
+ * %EGG_DESKTOP_FILE_LAUNCH_WORKSPACE: (int workspace)
+ * causes the application to be launched on the given workspace
+ * %EGG_DESKTOP_FILE_LAUNCH_DIRECTORY: (char *dir)
+ * causes the application to be launched in the given directory
+ * %EGG_DESKTOP_FILE_LAUNCH_TIME: (guint32 launch_time)
+ * sets the "launch time" for the application. If the user
+ * interacts with another window after @launch_time but before
+ * the launched application creates its first window, the window
+ * manager may choose to not give focus to the new application.
+ * Passing 0 for @launch_time will explicitly request that the
+ * application not receive focus.
+ * %EGG_DESKTOP_FILE_LAUNCH_FLAGS (GSpawnFlags flags)
+ * Sets additional #GSpawnFlags to use. See g_spawn_async() for
+ * more details.
+ * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC (GSpawnChildSetupFunc, gpointer)
+ * Sets the child setup callback and the data to pass to it.
+ * (See g_spawn_async() for more details.)
+ *
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID (GPid **pid)
+ * On a successful launch, sets *@pid to the PID of the launched
+ * application.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID (char **startup_id)
+ * On a successful launch, sets *@startup_id to the Startup
+ * Notification "startup id" of the launched application.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE (int *fd)
+ * On a successful launch, sets *@fd to the file descriptor of
+ * a pipe connected to the application's stdin.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE (int *fd)
+ * On a successful launch, sets *@fd to the file descriptor of
+ * a pipe connected to the application's stdout.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE (int *fd)
+ * On a successful launch, sets *@fd to the file descriptor of
+ * a pipe connected to the application's stderr.
+ *
+ * The options should be terminated with a single %NULL.
+ *
+ * If @documents contains multiple documents, but
+ * egg_desktop_file_accepts_multiple() returns %FALSE for
+ * @desktop_file, then egg_desktop_file_launch() will actually launch
+ * multiple instances of the application. In that case, the return
+ * value (as well as any values passed via
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID, etc) will only reflect the
+ * first instance of the application that was launched (but the
+ * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC will be called for each
+ * instance).
+ *
+ * Return value: %TRUE if the application was successfully launched.
+ **/
+gboolean
+egg_desktop_file_launch (EggDesktopFile *desktop_file,
+ GSList *documents, GError **error,
+ ...)
+{
+ va_list args;
+ gboolean success;
+ EggDesktopFile *app_desktop_file;
+
+ switch (desktop_file->type)
+ {
+ case EGG_DESKTOP_FILE_TYPE_APPLICATION:
+ va_start (args, error);
+ success = egg_desktop_file_launchv (desktop_file, documents,
+ args, error);
+ va_end (args);
+ break;
+
+ case EGG_DESKTOP_FILE_TYPE_LINK:
+ if (documents)
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ _("Can't pass document URIs to a 'Type=Link' desktop entry"));
+ return FALSE;
+ }
+
+ if (!parse_link (desktop_file, &app_desktop_file, &documents, error))
+ return FALSE;
+
+ va_start (args, error);
+ success = egg_desktop_file_launchv (app_desktop_file, documents,
+ args, error);
+ va_end (args);
+
+ egg_desktop_file_free (app_desktop_file);
+ free_document_list (documents);
+ break;
+
+ case EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED:
+ case EGG_DESKTOP_FILE_TYPE_DIRECTORY:
+ default:
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ _("Not a launchable item"));
+ success = FALSE;
+ break;
+ }
+
+ return success;
+}
+
+
+GQuark
+egg_desktop_file_error_quark (void)
+{
+ return g_quark_from_static_string ("egg-desktop_file-error-quark");
+}
+
+
+G_LOCK_DEFINE_STATIC (egg_desktop_file);
+static EggDesktopFile *egg_desktop_file;
+
+static void
+egg_set_desktop_file_internal (const char *desktop_file_path,
+ gboolean set_defaults)
+{
+ GError *error = NULL;
+
+ G_LOCK (egg_desktop_file);
+ if (egg_desktop_file)
+ egg_desktop_file_free (egg_desktop_file);
+
+ egg_desktop_file = egg_desktop_file_new (desktop_file_path, &error);
+ if (error)
+ {
+ g_warning ("Could not load desktop file '%s': %s",
+ desktop_file_path, error->message);
+ g_error_free (error);
+ }
+
+ if (set_defaults && egg_desktop_file != NULL) {
+ /* Set localized application name and default window icon */
+ if (egg_desktop_file->name)
+ g_set_application_name (egg_desktop_file->name);
+ if (egg_desktop_file->icon)
+ {
+ if (g_path_is_absolute (egg_desktop_file->icon))
+ gtk_window_set_default_icon_from_file (egg_desktop_file->icon, NULL);
+ else
+ gtk_window_set_default_icon_name (egg_desktop_file->icon);
+ }
+ }
+
+ G_UNLOCK (egg_desktop_file);
+}
+
+/**
+ * egg_set_desktop_file:
+ * @desktop_file_path: path to the application's desktop file
+ *
+ * Creates an #EggDesktopFile for the application from the data at
+ * @desktop_file_path. This will also call g_set_application_name()
+ * with the localized application name from the desktop file, and
+ * gtk_window_set_default_icon_name() or
+ * gtk_window_set_default_icon_from_file() with the application's
+ * icon. Other code may use additional information from the desktop
+ * file.
+ * See egg_set_desktop_file_without_defaults() for a variant of this
+ * function that does not set the application name and default window
+ * icon.
+ *
+ * Note that for thread safety reasons, this function can only
+ * be called once, and is mutually exclusive with calling
+ * egg_set_desktop_file_without_defaults().
+ **/
+void
+egg_set_desktop_file (const char *desktop_file_path)
+{
+ egg_set_desktop_file_internal (desktop_file_path, TRUE);
+}
+
+/**
+ * egg_set_desktop_file_without_defaults:
+ * @desktop_file_path: path to the application's desktop file
+ *
+ * Creates an #EggDesktopFile for the application from the data at
+ * @desktop_file_path.
+ * See egg_set_desktop_file() for a variant of this function that
+ * sets the application name and default window icon from the information
+ * in the desktop file.
+ *
+ * Note that for thread safety reasons, this function can only
+ * be called once, and is mutually exclusive with calling
+ * egg_set_desktop_file().
+ **/
+void
+egg_set_desktop_file_without_defaults (const char *desktop_file_path)
+{
+ egg_set_desktop_file_internal (desktop_file_path, FALSE);
+}
+
+/**
+ * egg_get_desktop_file:
+ *
+ * Gets the application's #EggDesktopFile, as set by
+ * egg_set_desktop_file().
+ *
+ * Return value: the #EggDesktopFile, or %NULL if it hasn't been set.
+ **/
+EggDesktopFile *
+egg_get_desktop_file (void)
+{
+ EggDesktopFile *retval;
+
+ G_LOCK (egg_desktop_file);
+ retval = egg_desktop_file;
+ G_UNLOCK (egg_desktop_file);
+
+ return retval;
+}
diff --git a/mate-panel/libegg/eggdesktopfile.h b/mate-panel/libegg/eggdesktopfile.h
new file mode 100644
index 00000000..68850b71
--- /dev/null
+++ b/mate-panel/libegg/eggdesktopfile.h
@@ -0,0 +1,164 @@
+/* eggdesktopfile.h - Freedesktop.Org Desktop Files
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library 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 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place -
+ * Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_DESKTOP_FILE_H__
+#define __EGG_DESKTOP_FILE_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct EggDesktopFile EggDesktopFile;
+
+typedef enum {
+ EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,
+
+ EGG_DESKTOP_FILE_TYPE_APPLICATION,
+ EGG_DESKTOP_FILE_TYPE_LINK,
+ EGG_DESKTOP_FILE_TYPE_DIRECTORY
+} EggDesktopFileType;
+
+EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
+ GError **error);
+
+EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
+ GError **error);
+EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
+ const char **search_dirs,
+ GError **error);
+EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
+ const char *source,
+ GError **error);
+
+void egg_desktop_file_free (EggDesktopFile *desktop_file);
+
+const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file);
+
+EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file);
+
+const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file);
+const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file);
+
+gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
+ const char *desktop_environment);
+
+gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
+gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
+gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);
+
+char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
+ GSList *documents,
+ GError **error);
+
+gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
+ GSList *documents,
+ GError **error,
+ ...) G_GNUC_NULL_TERMINATED;
+
+typedef enum {
+ EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
+ EGG_DESKTOP_FILE_LAUNCH_PUTENV,
+ EGG_DESKTOP_FILE_LAUNCH_SCREEN,
+ EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
+ EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
+ EGG_DESKTOP_FILE_LAUNCH_TIME,
+ EGG_DESKTOP_FILE_LAUNCH_FLAGS,
+ EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
+} EggDesktopFileLaunchOption;
+
+/* Standard Keys */
+#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"
+
+#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
+#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
+#define EGG_DESKTOP_FILE_KEY_NAME "Name"
+#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
+#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
+#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
+#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
+#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
+#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
+#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
+#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
+#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
+#define EGG_DESKTOP_FILE_KEY_PATH "Path"
+#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
+#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
+#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
+#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
+#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
+#define EGG_DESKTOP_FILE_KEY_URL "URL"
+
+/* Accessors */
+gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error) G_GNUC_MALLOC;
+char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ GError **error) G_GNUC_MALLOC;
+gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ gsize *length,
+ GError **error) G_GNUC_MALLOC;
+char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ gsize *length,
+ GError **error) G_GNUC_MALLOC;
+
+
+/* Errors */
+#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
+
+GQuark egg_desktop_file_error_quark (void);
+
+typedef enum {
+ EGG_DESKTOP_FILE_ERROR_INVALID,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
+} EggDesktopFileError;
+
+/* Global application desktop file */
+void egg_set_desktop_file (const char *desktop_file_path);
+void egg_set_desktop_file_without_defaults (const char *desktop_file_path);
+EggDesktopFile *egg_get_desktop_file (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EGG_DESKTOP_FILE_H__ */
diff --git a/mate-panel/libegg/eggsmclient-private.h b/mate-panel/libegg/eggsmclient-private.h
new file mode 100644
index 00000000..9f2498ac
--- /dev/null
+++ b/mate-panel/libegg/eggsmclient-private.h
@@ -0,0 +1,57 @@
+/* eggsmclient-private.h
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library 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 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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_SM_CLIENT_PRIVATE_H__
+#define __EGG_SM_CLIENT_PRIVATE_H__
+
+#include <gdkconfig.h>
+#include "eggsmclient.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GKeyFile *egg_sm_client_save_state (EggSMClient *client);
+void egg_sm_client_quit_requested (EggSMClient *client);
+void egg_sm_client_quit_cancelled (EggSMClient *client);
+void egg_sm_client_quit (EggSMClient *client);
+
+#if defined (GDK_WINDOWING_X11)
+# ifdef EGG_SM_CLIENT_BACKEND_XSMP
+GType egg_sm_client_xsmp_get_type (void);
+EggSMClient *egg_sm_client_xsmp_new (void);
+# endif
+# ifdef EGG_SM_CLIENT_BACKEND_DBUS
+GType egg_sm_client_dbus_get_type (void);
+EggSMClient *egg_sm_client_dbus_new (void);
+# endif
+#elif defined (GDK_WINDOWING_WIN32)
+GType egg_sm_client_win32_get_type (void);
+EggSMClient *egg_sm_client_win32_new (void);
+#elif defined (GDK_WINDOWING_QUARTZ)
+GType egg_sm_client_osx_get_type (void);
+EggSMClient *egg_sm_client_osx_new (void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */
diff --git a/mate-panel/libegg/eggsmclient-xsmp.c b/mate-panel/libegg/eggsmclient-xsmp.c
new file mode 100644
index 00000000..a6d3f11f
--- /dev/null
+++ b/mate-panel/libegg/eggsmclient-xsmp.c
@@ -0,0 +1,1370 @@
+/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * Inspired by various other pieces of code including GsmClient (C)
+ * 2001 Havoc Pennington, MateClient (C) 1998 Carsten Schaar, and twm
+ * session code (C) 1998 The Open Group.
+ *
+ * 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 "config.h"
+
+#include "eggsmclient.h"
+#include "eggsmclient-private.h"
+
+#include "eggdesktopfile.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/SM/SMlib.h>
+
+#include <gdk/gdk.h>
+
+#define EGG_TYPE_SM_CLIENT_XSMP (egg_sm_client_xsmp_get_type ())
+#define EGG_SM_CLIENT_XSMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMP))
+#define EGG_SM_CLIENT_XSMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass))
+#define EGG_IS_SM_CLIENT_XSMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_XSMP))
+#define EGG_IS_SM_CLIENT_XSMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_XSMP))
+#define EGG_SM_CLIENT_XSMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass))
+
+typedef struct _EggSMClientXSMP EggSMClientXSMP;
+typedef struct _EggSMClientXSMPClass EggSMClientXSMPClass;
+
+/* These mostly correspond to the similarly-named states in section
+ * 9.1 of the XSMP spec. Some of the states there aren't represented
+ * here, because we don't need them. SHUTDOWN_CANCELLED is slightly
+ * different from the spec; we use it when the client is IDLE after a
+ * ShutdownCancelled message, but the application is still interacting
+ * and doesn't know the shutdown has been cancelled yet.
+ */
+typedef enum
+{
+ XSMP_STATE_IDLE,
+ XSMP_STATE_SAVE_YOURSELF,
+ XSMP_STATE_INTERACT_REQUEST,
+ XSMP_STATE_INTERACT,
+ XSMP_STATE_SAVE_YOURSELF_DONE,
+ XSMP_STATE_SHUTDOWN_CANCELLED,
+ XSMP_STATE_CONNECTION_CLOSED
+} EggSMClientXSMPState;
+
+static const char *state_names[] = {
+ "idle",
+ "save-yourself",
+ "interact-request",
+ "interact",
+ "save-yourself-done",
+ "shutdown-cancelled",
+ "connection-closed"
+};
+
+#define EGG_SM_CLIENT_XSMP_STATE(xsmp) (state_names[(xsmp)->state])
+
+struct _EggSMClientXSMP
+{
+ EggSMClient parent;
+
+ SmcConn connection;
+ char *client_id;
+
+ EggSMClientXSMPState state;
+ char **restart_command;
+ gboolean set_restart_command;
+ int restart_style;
+
+ guint idle;
+
+ /* Current SaveYourself state */
+ guint expecting_initial_save_yourself : 1;
+ guint need_save_state : 1;
+ guint need_quit_requested : 1;
+ guint interact_errors : 1;
+ guint shutting_down : 1;
+
+ /* Todo list */
+ guint waiting_to_set_initial_properties : 1;
+ guint waiting_to_emit_quit : 1;
+ guint waiting_to_emit_quit_cancelled : 1;
+ guint waiting_to_save_myself : 1;
+
+};
+
+struct _EggSMClientXSMPClass
+{
+ EggSMClientClass parent_class;
+
+};
+
+static void sm_client_xsmp_startup (EggSMClient *client,
+ const char *client_id);
+static void sm_client_xsmp_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv);
+static void sm_client_xsmp_will_quit (EggSMClient *client,
+ gboolean will_quit);
+static gboolean sm_client_xsmp_end_session (EggSMClient *client,
+ EggSMClientEndStyle style,
+ gboolean request_confirmation);
+
+static void xsmp_save_yourself (SmcConn smc_conn,
+ SmPointer client_data,
+ int save_style,
+ Bool shutdown,
+ int interact_style,
+ Bool fast);
+static void xsmp_die (SmcConn smc_conn,
+ SmPointer client_data);
+static void xsmp_save_complete (SmcConn smc_conn,
+ SmPointer client_data);
+static void xsmp_shutdown_cancelled (SmcConn smc_conn,
+ SmPointer client_data);
+static void xsmp_interact (SmcConn smc_conn,
+ SmPointer client_data);
+
+static SmProp *array_prop (const char *name,
+ ...);
+static SmProp *ptrarray_prop (const char *name,
+ GPtrArray *values);
+static SmProp *string_prop (const char *name,
+ const char *value);
+static SmProp *card8_prop (const char *name,
+ unsigned char value);
+
+static void set_properties (EggSMClientXSMP *xsmp, ...);
+static void delete_properties (EggSMClientXSMP *xsmp, ...);
+
+static GPtrArray *generate_command (char **restart_command,
+ const char *client_id,
+ const char *state_file);
+
+static void save_state (EggSMClientXSMP *xsmp);
+static void do_save_yourself (EggSMClientXSMP *xsmp);
+static void update_pending_events (EggSMClientXSMP *xsmp);
+
+static void ice_init (void);
+static gboolean process_ice_messages (IceConn ice_conn);
+static void smc_error_handler (SmcConn smc_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ SmPointer values);
+
+G_DEFINE_TYPE (EggSMClientXSMP, egg_sm_client_xsmp, EGG_TYPE_SM_CLIENT)
+
+static void
+egg_sm_client_xsmp_init (EggSMClientXSMP *xsmp)
+{
+ xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+ xsmp->connection = NULL;
+ xsmp->restart_style = SmRestartIfRunning;
+}
+
+static void
+egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass)
+{
+ EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
+
+ sm_client_class->startup = sm_client_xsmp_startup;
+ sm_client_class->set_restart_command = sm_client_xsmp_set_restart_command;
+ sm_client_class->will_quit = sm_client_xsmp_will_quit;
+ sm_client_class->end_session = sm_client_xsmp_end_session;
+}
+
+EggSMClient *
+egg_sm_client_xsmp_new (void)
+{
+ if (!g_getenv ("SESSION_MANAGER"))
+ return NULL;
+
+ return g_object_new (EGG_TYPE_SM_CLIENT_XSMP, NULL);
+}
+
+static gboolean
+sm_client_xsmp_set_initial_properties (gpointer user_data)
+{
+ EggSMClientXSMP *xsmp = user_data;
+ EggDesktopFile *desktop_file;
+ GPtrArray *clone, *restart;
+ char pid_str[64];
+
+ if (xsmp->idle)
+ {
+ g_source_remove (xsmp->idle);
+ xsmp->idle = 0;
+ }
+ xsmp->waiting_to_set_initial_properties = FALSE;
+
+ if (egg_sm_client_get_mode () == EGG_SM_CLIENT_MODE_NO_RESTART)
+ xsmp->restart_style = SmRestartNever;
+
+ /* Parse info out of desktop file */
+ desktop_file = egg_get_desktop_file ();
+ if (desktop_file)
+ {
+ GError *err = NULL;
+ char *cmdline, **argv;
+ int argc;
+
+ if (xsmp->restart_style == SmRestartIfRunning)
+ {
+ if (egg_desktop_file_get_boolean (desktop_file,
+ "X-MATE-AutoRestart", NULL))
+ xsmp->restart_style = SmRestartImmediately;
+ }
+
+ if (!xsmp->set_restart_command)
+ {
+ cmdline = egg_desktop_file_parse_exec (desktop_file, NULL, &err);
+ if (cmdline && g_shell_parse_argv (cmdline, &argc, &argv, &err))
+ {
+ egg_sm_client_set_restart_command (EGG_SM_CLIENT (xsmp),
+ argc, (const char **)argv);
+ g_strfreev (argv);
+ }
+ else
+ {
+ g_warning ("Could not parse Exec line in desktop file: %s",
+ err->message);
+ g_error_free (err);
+ }
+ g_free (cmdline);
+ }
+ }
+
+ if (!xsmp->set_restart_command)
+ xsmp->restart_command = g_strsplit (g_get_prgname (), " ", -1);
+
+ clone = generate_command (xsmp->restart_command, NULL, NULL);
+ restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL);
+
+ g_debug ("Setting initial properties");
+
+ /* Program, CloneCommand, RestartCommand, and UserID are required.
+ * ProcessID isn't required, but the SM may be able to do something
+ * useful with it.
+ */
+ g_snprintf (pid_str, sizeof (pid_str), "%lu", (gulong) getpid ());
+ set_properties (xsmp,
+ string_prop (SmProgram, g_get_prgname ()),
+ ptrarray_prop (SmCloneCommand, clone),
+ ptrarray_prop (SmRestartCommand, restart),
+ string_prop (SmUserID, g_get_user_name ()),
+ string_prop (SmProcessID, pid_str),
+ card8_prop (SmRestartStyleHint, xsmp->restart_style),
+ NULL);
+ g_ptr_array_free (clone, TRUE);
+ g_ptr_array_free (restart, TRUE);
+
+ if (desktop_file)
+ {
+ set_properties (xsmp,
+ string_prop ("_GSM_DesktopFile", egg_desktop_file_get_source (desktop_file)),
+ NULL);
+ }
+
+ update_pending_events (xsmp);
+ return FALSE;
+}
+
+/* This gets called from two different places: xsmp_die() (when the
+ * server asks us to disconnect) and process_ice_messages() (when the
+ * server disconnects unexpectedly).
+ */
+static void
+sm_client_xsmp_disconnect (EggSMClientXSMP *xsmp)
+{
+ SmcConn connection;
+
+ if (!xsmp->connection)
+ return;
+
+ g_debug ("Disconnecting");
+
+ connection = xsmp->connection;
+ xsmp->connection = NULL;
+ SmcCloseConnection (connection, 0, NULL);
+ xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+
+ xsmp->waiting_to_save_myself = FALSE;
+ update_pending_events (xsmp);
+}
+
+static void
+sm_client_xsmp_startup (EggSMClient *client,
+ const char *client_id)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+ SmcCallbacks callbacks;
+ char *ret_client_id;
+ char error_string_ret[256];
+
+ xsmp->client_id = g_strdup (client_id);
+
+ ice_init ();
+ SmcSetErrorHandler (smc_error_handler);
+
+ callbacks.save_yourself.callback = xsmp_save_yourself;
+ callbacks.die.callback = xsmp_die;
+ callbacks.save_complete.callback = xsmp_save_complete;
+ callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
+
+ callbacks.save_yourself.client_data = xsmp;
+ callbacks.die.client_data = xsmp;
+ callbacks.save_complete.client_data = xsmp;
+ callbacks.shutdown_cancelled.client_data = xsmp;
+
+ client_id = NULL;
+ error_string_ret[0] = '\0';
+ xsmp->connection =
+ SmcOpenConnection (NULL, xsmp, SmProtoMajor, SmProtoMinor,
+ SmcSaveYourselfProcMask | SmcDieProcMask |
+ SmcSaveCompleteProcMask |
+ SmcShutdownCancelledProcMask,
+ &callbacks,
+ xsmp->client_id, &ret_client_id,
+ sizeof (error_string_ret), error_string_ret);
+
+ if (!xsmp->connection)
+ {
+ g_warning ("Failed to connect to the session manager: %s\n",
+ error_string_ret[0] ?
+ error_string_ret : "no error message given");
+ xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+ return;
+ }
+
+ /* We expect a pointless initial SaveYourself if either (a) we
+ * didn't have an initial client ID, or (b) we DID have an initial
+ * client ID, but the server rejected it and gave us a new one.
+ */
+ if (!xsmp->client_id ||
+ (ret_client_id && strcmp (xsmp->client_id, ret_client_id) != 0))
+ xsmp->expecting_initial_save_yourself = TRUE;
+
+ if (ret_client_id)
+ {
+ g_free (xsmp->client_id);
+ xsmp->client_id = g_strdup (ret_client_id);
+ free (ret_client_id);
+
+ gdk_threads_enter ();
+ gdk_set_sm_client_id (xsmp->client_id);
+ gdk_threads_leave ();
+
+ g_debug ("Got client ID \"%s\"", xsmp->client_id);
+ }
+
+ xsmp->state = XSMP_STATE_IDLE;
+
+ /* Do not set the initial properties until we reach the main loop,
+ * so that the application has a chance to call
+ * egg_set_desktop_file(). (This may also help the session manager
+ * have a better idea of when the application is fully up and
+ * running.)
+ */
+ xsmp->waiting_to_set_initial_properties = TRUE;
+ xsmp->idle = g_idle_add (sm_client_xsmp_set_initial_properties, client);
+}
+
+static void
+sm_client_xsmp_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+ int i;
+
+ g_strfreev (xsmp->restart_command);
+
+ xsmp->restart_command = g_new (char *, argc + 1);
+ for (i = 0; i < argc; i++)
+ xsmp->restart_command[i] = g_strdup (argv[i]);
+ xsmp->restart_command[i] = NULL;
+
+ xsmp->set_restart_command = TRUE;
+}
+
+static void
+sm_client_xsmp_will_quit (EggSMClient *client,
+ gboolean will_quit)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+
+ if (xsmp->state == XSMP_STATE_CONNECTION_CLOSED)
+ {
+ /* The session manager has already exited! Schedule a quit
+ * signal.
+ */
+ xsmp->waiting_to_emit_quit = TRUE;
+ update_pending_events (xsmp);
+ return;
+ }
+ else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ /* We received a ShutdownCancelled message while the application
+ * was interacting; Schedule a quit_cancelled signal.
+ */
+ xsmp->waiting_to_emit_quit_cancelled = TRUE;
+ update_pending_events (xsmp);
+ return;
+ }
+
+ g_return_if_fail (xsmp->state == XSMP_STATE_INTERACT);
+
+ g_debug ("Sending InteractDone(%s)", will_quit ? "False" : "True");
+ SmcInteractDone (xsmp->connection, !will_quit);
+
+ if (will_quit && xsmp->need_save_state)
+ save_state (xsmp);
+
+ g_debug ("Sending SaveYourselfDone(%s)", will_quit ? "True" : "False");
+ SmcSaveYourselfDone (xsmp->connection, will_quit);
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+}
+
+static gboolean
+sm_client_xsmp_end_session (EggSMClient *client,
+ EggSMClientEndStyle style,
+ gboolean request_confirmation)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+ int save_type;
+
+ /* To end the session via XSMP, we have to send a
+ * SaveYourselfRequest. We aren't allowed to do that if anything
+ * else is going on, but we don't want to expose this fact to the
+ * application. So we do our best to patch things up here...
+ *
+ * In the worst case, this method might block for some length of
+ * time in process_ice_messages, but the only time that code path is
+ * honestly likely to get hit is if the application tries to end the
+ * session as the very first thing it does, in which case it
+ * probably won't actually block anyway. It's not worth gunking up
+ * the API to try to deal nicely with the other 0.01% of cases where
+ * this happens.
+ */
+
+ while (xsmp->state != XSMP_STATE_IDLE ||
+ xsmp->expecting_initial_save_yourself)
+ {
+ /* If we're already shutting down, we don't need to do anything. */
+ if (xsmp->shutting_down)
+ return TRUE;
+
+ switch (xsmp->state)
+ {
+ case XSMP_STATE_CONNECTION_CLOSED:
+ return FALSE;
+
+ case XSMP_STATE_SAVE_YOURSELF:
+ /* Trying to log out from the save_state callback? Whatever.
+ * Abort the save_state.
+ */
+ SmcSaveYourselfDone (xsmp->connection, FALSE);
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+ break;
+
+ case XSMP_STATE_INTERACT_REQUEST:
+ case XSMP_STATE_INTERACT:
+ case XSMP_STATE_SHUTDOWN_CANCELLED:
+ /* Already in a shutdown-related state, just ignore
+ * the new shutdown request...
+ */
+ return TRUE;
+
+ case XSMP_STATE_IDLE:
+ if (xsmp->waiting_to_set_initial_properties)
+ sm_client_xsmp_set_initial_properties (xsmp);
+
+ if (!xsmp->expecting_initial_save_yourself)
+ break;
+ /* else fall through */
+
+ case XSMP_STATE_SAVE_YOURSELF_DONE:
+ /* We need to wait for some response from the server.*/
+ process_ice_messages (SmcGetIceConnection (xsmp->connection));
+ break;
+
+ default:
+ /* Hm... shouldn't happen */
+ return FALSE;
+ }
+ }
+
+ /* xfce4-session will do the wrong thing if we pass SmSaveGlobal and
+ * the user chooses to save the session. But mate-session will do
+ * the wrong thing if we pass SmSaveBoth and the user chooses NOT to
+ * save the session... Sigh.
+ */
+ if (!strcmp (SmcVendor (xsmp->connection), "xfce4-session"))
+ save_type = SmSaveBoth;
+ else
+ save_type = SmSaveGlobal;
+
+ g_debug ("Sending SaveYourselfRequest(SmSaveGlobal, Shutdown, SmInteractStyleAny, %sFast)", request_confirmation ? "!" : "");
+ SmcRequestSaveYourself (xsmp->connection,
+ save_type,
+ True, /* shutdown */
+ SmInteractStyleAny,
+ !request_confirmation, /* fast */
+ True /* global */);
+ return TRUE;
+}
+
+static gboolean
+idle_do_pending_events (gpointer data)
+{
+ EggSMClientXSMP *xsmp = data;
+ EggSMClient *client = data;
+
+ gdk_threads_enter ();
+
+ xsmp->idle = 0;
+
+ if (xsmp->waiting_to_emit_quit)
+ {
+ xsmp->waiting_to_emit_quit = FALSE;
+ egg_sm_client_quit (client);
+ goto out;
+ }
+
+ if (xsmp->waiting_to_emit_quit_cancelled)
+ {
+ xsmp->waiting_to_emit_quit_cancelled = FALSE;
+ egg_sm_client_quit_cancelled (client);
+ xsmp->state = XSMP_STATE_IDLE;
+ }
+
+ if (xsmp->waiting_to_save_myself)
+ {
+ xsmp->waiting_to_save_myself = FALSE;
+ do_save_yourself (xsmp);
+ }
+
+ out:
+ gdk_threads_leave ();
+ return FALSE;
+}
+
+static void
+update_pending_events (EggSMClientXSMP *xsmp)
+{
+ gboolean want_idle =
+ xsmp->waiting_to_emit_quit ||
+ xsmp->waiting_to_emit_quit_cancelled ||
+ xsmp->waiting_to_save_myself;
+
+ if (want_idle)
+ {
+ if (xsmp->idle == 0)
+ xsmp->idle = g_idle_add (idle_do_pending_events, xsmp);
+ }
+ else
+ {
+ if (xsmp->idle != 0)
+ g_source_remove (xsmp->idle);
+ xsmp->idle = 0;
+ }
+}
+
+static void
+fix_broken_state (EggSMClientXSMP *xsmp, const char *message,
+ gboolean send_interact_done,
+ gboolean send_save_yourself_done)
+{
+ g_warning ("Received XSMP %s message in state %s: client or server error",
+ message, EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ /* Forget any pending SaveYourself plans we had */
+ xsmp->waiting_to_save_myself = FALSE;
+ update_pending_events (xsmp);
+
+ if (send_interact_done)
+ SmcInteractDone (xsmp->connection, False);
+ if (send_save_yourself_done)
+ SmcSaveYourselfDone (xsmp->connection, True);
+
+ xsmp->state = send_save_yourself_done ? XSMP_STATE_SAVE_YOURSELF_DONE : XSMP_STATE_IDLE;
+}
+
+/* SM callbacks */
+
+static void
+xsmp_save_yourself (SmcConn smc_conn,
+ SmPointer client_data,
+ int save_type,
+ Bool shutdown,
+ int interact_style,
+ Bool fast)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ gboolean wants_quit_requested;
+
+ g_debug ("Received SaveYourself(%s, %s, %s, %s) in state %s",
+ save_type == SmSaveLocal ? "SmSaveLocal" :
+ save_type == SmSaveGlobal ? "SmSaveGlobal" : "SmSaveBoth",
+ shutdown ? "Shutdown" : "!Shutdown",
+ interact_style == SmInteractStyleAny ? "SmInteractStyleAny" :
+ interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
+ "SmInteractStyleNone", fast ? "Fast" : "!Fast",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ if (xsmp->state != XSMP_STATE_IDLE &&
+ xsmp->state != XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ fix_broken_state (xsmp, "SaveYourself", FALSE, TRUE);
+ return;
+ }
+
+ if (xsmp->waiting_to_set_initial_properties)
+ sm_client_xsmp_set_initial_properties (xsmp);
+
+ /* If this is the initial SaveYourself, ignore it; we've already set
+ * properties and there's no reason to actually save state too.
+ */
+ if (xsmp->expecting_initial_save_yourself)
+ {
+ xsmp->expecting_initial_save_yourself = FALSE;
+
+ if (save_type == SmSaveLocal &&
+ interact_style == SmInteractStyleNone &&
+ !shutdown && !fast)
+ {
+ g_debug ("Sending SaveYourselfDone(True) for initial SaveYourself");
+ SmcSaveYourselfDone (xsmp->connection, True);
+ /* As explained in the comment at the end of
+ * do_save_yourself(), SAVE_YOURSELF_DONE is the correct
+ * state here, not IDLE.
+ */
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+ return;
+ }
+ else
+ g_warning ("First SaveYourself was not the expected one!");
+ }
+
+ /* Even ignoring the "fast" flag completely, there are still 18
+ * different combinations of save_type, shutdown and interact_style.
+ * We interpret them as follows:
+ *
+ * Type Shutdown Interact Interpretation
+ * G F A/E/N do nothing (1)
+ * G T N do nothing (1)*
+ * G T A/E quit_requested (2)
+ * L/B F A/E/N save_state (3)
+ * L/B T N save_state (3)*
+ * L/B T A/E quit_requested, then save_state (4)
+ *
+ * 1. Do nothing, because the SM asked us to do something
+ * uninteresting (save open files, but then don't quit
+ * afterward) or rude (save open files without asking the user
+ * for confirmation).
+ *
+ * 2. Request interaction and then emit ::quit_requested. This
+ * perhaps isn't quite correct for the SmInteractStyleErrors
+ * case, but we don't care.
+ *
+ * 3. Emit ::save_state. The SmSaveBoth SaveYourselfs in these
+ * rows essentially get demoted to SmSaveLocal, because their
+ * Global halves correspond to "do nothing".
+ *
+ * 4. Request interaction, emit ::quit_requested, and then emit
+ * ::save_state after interacting. This is the SmSaveBoth
+ * equivalent of #2, but we also promote SmSaveLocal shutdown
+ * SaveYourselfs to SmSaveBoth here, because we want to give
+ * the user a chance to save open files before quitting.
+ *
+ * (* It would be nice if we could do something useful when the
+ * session manager sends a SaveYourself with shutdown True and
+ * SmInteractStyleNone. But we can't, so we just pretend it didn't
+ * even tell us it was shutting down. The docs for ::quit mention
+ * that it might not always be preceded by ::quit_requested.)
+ */
+
+ /* As an optimization, we don't actually request interaction and
+ * emit ::quit_requested if the application isn't listening to the
+ * signal.
+ */
+ wants_quit_requested = g_signal_has_handler_pending (xsmp, g_signal_lookup ("quit_requested", EGG_TYPE_SM_CLIENT), 0, FALSE);
+
+ xsmp->need_save_state = (save_type != SmSaveGlobal);
+ xsmp->need_quit_requested = (shutdown && wants_quit_requested &&
+ interact_style != SmInteractStyleNone);
+ xsmp->interact_errors = (interact_style == SmInteractStyleErrors);
+
+ xsmp->shutting_down = shutdown;
+
+ do_save_yourself (xsmp);
+}
+
+static void
+do_save_yourself (EggSMClientXSMP *xsmp)
+{
+ if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ /* The SM cancelled a previous SaveYourself, but we haven't yet
+ * had a chance to tell the application, so we can't start
+ * processing this SaveYourself yet.
+ */
+ xsmp->waiting_to_save_myself = TRUE;
+ update_pending_events (xsmp);
+ return;
+ }
+
+ if (xsmp->need_quit_requested)
+ {
+ xsmp->state = XSMP_STATE_INTERACT_REQUEST;
+
+ g_debug ("Sending InteractRequest(%s)",
+ xsmp->interact_errors ? "Error" : "Normal");
+ SmcInteractRequest (xsmp->connection,
+ xsmp->interact_errors ? SmDialogError : SmDialogNormal,
+ xsmp_interact,
+ xsmp);
+ return;
+ }
+
+ if (xsmp->need_save_state)
+ {
+ save_state (xsmp);
+
+ /* Though unlikely, the client could have been disconnected
+ * while the application was saving its state.
+ */
+ if (!xsmp->connection)
+ return;
+ }
+
+ g_debug ("Sending SaveYourselfDone(True)");
+ SmcSaveYourselfDone (xsmp->connection, True);
+
+ /* The client state diagram in the XSMP spec says that after a
+ * non-shutdown SaveYourself, we go directly back to "idle". But
+ * everything else in both the XSMP spec and the libSM docs
+ * disagrees.
+ */
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+}
+
+static void
+save_state (EggSMClientXSMP *xsmp)
+{
+ GKeyFile *state_file;
+ char *state_file_path, *data;
+ EggDesktopFile *desktop_file;
+ GPtrArray *restart;
+ int offset, fd;
+
+ /* We set xsmp->state before emitting save_state, but our caller is
+ * responsible for setting it back afterward.
+ */
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF;
+
+ state_file = egg_sm_client_save_state ((EggSMClient *)xsmp);
+ if (!state_file)
+ {
+ restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL);
+ set_properties (xsmp,
+ ptrarray_prop (SmRestartCommand, restart),
+ NULL);
+ g_ptr_array_free (restart, TRUE);
+ delete_properties (xsmp, SmDiscardCommand, NULL);
+ return;
+ }
+
+ desktop_file = egg_get_desktop_file ();
+ if (desktop_file)
+ {
+ GKeyFile *merged_file;
+ char *desktop_file_path;
+
+ merged_file = g_key_file_new ();
+ desktop_file_path =
+ g_filename_from_uri (egg_desktop_file_get_source (desktop_file),
+ NULL, NULL);
+ if (desktop_file_path &&
+ g_key_file_load_from_file (merged_file, desktop_file_path,
+ G_KEY_FILE_KEEP_COMMENTS |
+ G_KEY_FILE_KEEP_TRANSLATIONS, NULL))
+ {
+ guint g, k, i;
+ char **groups, **keys, *value, *exec;
+
+ groups = g_key_file_get_groups (state_file, NULL);
+ for (g = 0; groups[g]; g++)
+ {
+ keys = g_key_file_get_keys (state_file, groups[g], NULL, NULL);
+ for (k = 0; keys[k]; k++)
+ {
+ value = g_key_file_get_value (state_file, groups[g],
+ keys[k], NULL);
+ if (value)
+ {
+ g_key_file_set_value (merged_file, groups[g],
+ keys[k], value);
+ g_free (value);
+ }
+ }
+ g_strfreev (keys);
+ }
+ g_strfreev (groups);
+
+ g_key_file_free (state_file);
+ state_file = merged_file;
+
+ /* Update Exec key using "--sm-client-state-file %k" */
+ restart = generate_command (xsmp->restart_command,
+ NULL, "%k");
+ for (i = 0; i < restart->len; i++)
+ restart->pdata[i] = g_shell_quote (restart->pdata[i]);
+ g_ptr_array_add (restart, NULL);
+ exec = g_strjoinv (" ", (char **)restart->pdata);
+ g_strfreev ((char **)restart->pdata);
+ g_ptr_array_free (restart, FALSE);
+
+ g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ exec);
+ g_free (exec);
+ }
+ else
+ desktop_file = NULL;
+
+ g_free (desktop_file_path);
+ }
+
+ /* Now write state_file to disk. (We can't use mktemp(), because
+ * that requires the filename to end with "XXXXXX", and we want
+ * it to end with ".desktop".)
+ */
+
+ data = g_key_file_to_data (state_file, NULL, NULL);
+ g_key_file_free (state_file);
+
+ offset = 0;
+ while (1)
+ {
+ state_file_path = g_strdup_printf ("%s%csession-state%c%s-%ld.%s",
+ g_get_user_config_dir (),
+ G_DIR_SEPARATOR, G_DIR_SEPARATOR,
+ g_get_prgname (),
+ (long)time (NULL) + offset,
+ desktop_file ? "desktop" : "state");
+
+ fd = open (state_file_path, O_WRONLY | O_CREAT | O_EXCL, 0644);
+ if (fd == -1)
+ {
+ if (errno == EEXIST)
+ {
+ offset++;
+ g_free (state_file_path);
+ continue;
+ }
+ else if (errno == ENOTDIR || errno == ENOENT)
+ {
+ char *sep = strrchr (state_file_path, G_DIR_SEPARATOR);
+
+ *sep = '\0';
+ if (g_mkdir_with_parents (state_file_path, 0755) != 0)
+ {
+ g_warning ("Could not create directory '%s'",
+ state_file_path);
+ g_free (state_file_path);
+ state_file_path = NULL;
+ break;
+ }
+
+ continue;
+ }
+
+ g_warning ("Could not create file '%s': %s",
+ state_file_path, g_strerror (errno));
+ g_free (state_file_path);
+ state_file_path = NULL;
+ break;
+ }
+
+ close (fd);
+ g_file_set_contents (state_file_path, data, -1, NULL);
+ break;
+ }
+ g_free (data);
+
+ restart = generate_command (xsmp->restart_command, xsmp->client_id,
+ state_file_path);
+ set_properties (xsmp,
+ ptrarray_prop (SmRestartCommand, restart),
+ NULL);
+ g_ptr_array_free (restart, TRUE);
+
+ if (state_file_path)
+ {
+ set_properties (xsmp,
+ array_prop (SmDiscardCommand,
+ "/bin/rm", "-rf", state_file_path,
+ NULL),
+ NULL);
+ g_free (state_file_path);
+ }
+}
+
+static void
+xsmp_interact (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ EggSMClient *client = client_data;
+
+ g_debug ("Received Interact message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ if (xsmp->state != XSMP_STATE_INTERACT_REQUEST)
+ {
+ fix_broken_state (xsmp, "Interact", TRUE, TRUE);
+ return;
+ }
+
+ xsmp->state = XSMP_STATE_INTERACT;
+ egg_sm_client_quit_requested (client);
+}
+
+static void
+xsmp_die (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ EggSMClient *client = client_data;
+
+ g_debug ("Received Die message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ sm_client_xsmp_disconnect (xsmp);
+ egg_sm_client_quit (client);
+}
+
+static void
+xsmp_save_complete (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+
+ g_debug ("Received SaveComplete message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
+ xsmp->state = XSMP_STATE_IDLE;
+ else
+ fix_broken_state (xsmp, "SaveComplete", FALSE, FALSE);
+}
+
+static void
+xsmp_shutdown_cancelled (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ EggSMClient *client = client_data;
+
+ g_debug ("Received ShutdownCancelled message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ xsmp->shutting_down = FALSE;
+
+ if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
+ {
+ /* We've finished interacting and now the SM has agreed to
+ * cancel the shutdown.
+ */
+ xsmp->state = XSMP_STATE_IDLE;
+ egg_sm_client_quit_cancelled (client);
+ }
+ else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ /* Hm... ok, so we got a shutdown SaveYourself, which got
+ * cancelled, but the application was still interacting, so we
+ * didn't tell it yet, and then *another* SaveYourself arrived,
+ * which we must still be waiting to tell the app about, except
+ * that now that SaveYourself has been cancelled too! Dizzy yet?
+ */
+ xsmp->waiting_to_save_myself = FALSE;
+ update_pending_events (xsmp);
+ }
+ else
+ {
+ g_debug ("Sending SaveYourselfDone(False)");
+ SmcSaveYourselfDone (xsmp->connection, False);
+
+ if (xsmp->state == XSMP_STATE_INTERACT)
+ {
+ /* The application is currently interacting, so we can't
+ * tell it about the cancellation yet; we will wait until
+ * after it calls egg_sm_client_will_quit().
+ */
+ xsmp->state = XSMP_STATE_SHUTDOWN_CANCELLED;
+ }
+ else
+ {
+ /* The shutdown was cancelled before the application got a
+ * chance to interact.
+ */
+ xsmp->state = XSMP_STATE_IDLE;
+ }
+ }
+}
+
+/* Utilities */
+
+/* Create a restart/clone/Exec command based on @restart_command.
+ * If @client_id is non-%NULL, add "--sm-client-id @client_id".
+ * If @state_file is non-%NULL, add "--sm-client-state-file @state_file".
+ *
+ * None of the input strings are g_strdup()ed; the caller must keep
+ * them around until it is done with the returned GPtrArray, and must
+ * then free the array, but not its contents.
+ */
+static GPtrArray *
+generate_command (char **restart_command, const char *client_id,
+ const char *state_file)
+{
+ GPtrArray *cmd;
+ int i;
+
+ cmd = g_ptr_array_new ();
+ g_ptr_array_add (cmd, restart_command[0]);
+
+ if (client_id)
+ {
+ g_ptr_array_add (cmd, (char *)"--sm-client-id");
+ g_ptr_array_add (cmd, (char *)client_id);
+ }
+
+ if (state_file)
+ {
+ g_ptr_array_add (cmd, (char *)"--sm-client-state-file");
+ g_ptr_array_add (cmd, (char *)state_file);
+ }
+
+ for (i = 1; restart_command[i]; i++)
+ g_ptr_array_add (cmd, restart_command[i]);
+
+ return cmd;
+}
+
+/* Takes a NULL-terminated list of SmProp * values, created by
+ * array_prop, ptrarray_prop, string_prop, card8_prop, sets them, and
+ * frees them.
+ */
+static void
+set_properties (EggSMClientXSMP *xsmp, ...)
+{
+ GPtrArray *props;
+ SmProp *prop;
+ va_list ap;
+ guint i;
+
+ props = g_ptr_array_new ();
+
+ va_start (ap, xsmp);
+ while ((prop = va_arg (ap, SmProp *)))
+ g_ptr_array_add (props, prop);
+ va_end (ap);
+
+ if (xsmp->connection)
+ {
+ SmcSetProperties (xsmp->connection, props->len,
+ (SmProp **)props->pdata);
+ }
+
+ for (i = 0; i < props->len; i++)
+ {
+ prop = props->pdata[i];
+ g_free (prop->vals);
+ g_free (prop);
+ }
+ g_ptr_array_free (props, TRUE);
+}
+
+/* Takes a NULL-terminated list of property names and deletes them. */
+static void
+delete_properties (EggSMClientXSMP *xsmp, ...)
+{
+ GPtrArray *props;
+ char *prop;
+ va_list ap;
+
+ if (!xsmp->connection)
+ return;
+
+ props = g_ptr_array_new ();
+
+ va_start (ap, xsmp);
+ while ((prop = va_arg (ap, char *)))
+ g_ptr_array_add (props, prop);
+ va_end (ap);
+
+ SmcDeleteProperties (xsmp->connection, props->len,
+ (char **)props->pdata);
+
+ g_ptr_array_free (props, TRUE);
+}
+
+/* Takes an array of strings and creates a LISTofARRAY8 property. The
+ * strings are neither dupped nor freed; they need to remain valid
+ * until you're done with the SmProp.
+ */
+static SmProp *
+array_prop (const char *name, ...)
+{
+ SmProp *prop;
+ SmPropValue pv;
+ GArray *vals;
+ char *value;
+ va_list ap;
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmLISTofARRAY8;
+
+ vals = g_array_new (FALSE, FALSE, sizeof (SmPropValue));
+
+ va_start (ap, name);
+ while ((value = va_arg (ap, char *)))
+ {
+ pv.length = strlen (value);
+ pv.value = value;
+ g_array_append_val (vals, pv);
+ }
+
+ prop->num_vals = vals->len;
+ prop->vals = (SmPropValue *)vals->data;
+
+ g_array_free (vals, FALSE);
+
+ return prop;
+}
+
+/* Takes a GPtrArray of strings and creates a LISTofARRAY8 property.
+ * The array contents are neither dupped nor freed; they need to
+ * remain valid until you're done with the SmProp.
+ */
+static SmProp *
+ptrarray_prop (const char *name, GPtrArray *values)
+{
+ SmProp *prop;
+ SmPropValue pv;
+ GArray *vals;
+ guint i;
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmLISTofARRAY8;
+
+ vals = g_array_new (FALSE, FALSE, sizeof (SmPropValue));
+
+ for (i = 0; i < values->len; i++)
+ {
+ pv.length = strlen (values->pdata[i]);
+ pv.value = values->pdata[i];
+ g_array_append_val (vals, pv);
+ }
+
+ prop->num_vals = vals->len;
+ prop->vals = (SmPropValue *)vals->data;
+
+ g_array_free (vals, FALSE);
+
+ return prop;
+}
+
+/* Takes a string and creates an ARRAY8 property. The string is
+ * neither dupped nor freed; it needs to remain valid until you're
+ * done with the SmProp.
+ */
+static SmProp *
+string_prop (const char *name, const char *value)
+{
+ SmProp *prop;
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmARRAY8;
+
+ prop->num_vals = 1;
+ prop->vals = g_new (SmPropValue, 1);
+
+ prop->vals[0].length = strlen (value);
+ prop->vals[0].value = (char *)value;
+
+ return prop;
+}
+
+/* Takes a char and creates a CARD8 property. */
+static SmProp *
+card8_prop (const char *name, unsigned char value)
+{
+ SmProp *prop;
+ char *card8val;
+
+ /* To avoid having to allocate and free prop->vals[0], we cheat and
+ * make vals a 2-element-long array and then use the second element
+ * to store value.
+ */
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmCARD8;
+
+ prop->num_vals = 1;
+ prop->vals = g_new (SmPropValue, 2);
+ card8val = (char *)(&prop->vals[1]);
+ card8val[0] = value;
+
+ prop->vals[0].length = 1;
+ prop->vals[0].value = card8val;
+
+ return prop;
+}
+
+/* ICE code. This makes no effort to play nice with anyone else trying
+ * to use libICE. Fortunately, no one uses libICE for anything other
+ * than SM. (DCOP uses ICE, but it has its own private copy of
+ * libICE.)
+ *
+ * When this moves to gtk, it will need to be cleverer, to avoid
+ * tripping over old apps that use MateClient or that use libSM
+ * directly.
+ */
+
+#include <X11/ICE/ICElib.h>
+#include <fcntl.h>
+
+static void ice_error_handler (IceConn ice_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ IcePointer values);
+static void ice_io_error_handler (IceConn ice_conn);
+static void ice_connection_watch (IceConn ice_conn,
+ IcePointer client_data,
+ Bool opening,
+ IcePointer *watch_data);
+
+static void
+ice_init (void)
+{
+ IceSetIOErrorHandler (ice_io_error_handler);
+ IceSetErrorHandler (ice_error_handler);
+ IceAddConnectionWatch (ice_connection_watch, NULL);
+}
+
+static gboolean
+process_ice_messages (IceConn ice_conn)
+{
+ IceProcessMessagesStatus status;
+
+ gdk_threads_enter ();
+ status = IceProcessMessages (ice_conn, NULL, NULL);
+ gdk_threads_leave ();
+
+ switch (status)
+ {
+ case IceProcessMessagesSuccess:
+ return TRUE;
+
+ case IceProcessMessagesIOError:
+ sm_client_xsmp_disconnect (IceGetConnectionContext (ice_conn));
+ return FALSE;
+
+ case IceProcessMessagesConnectionClosed:
+ return FALSE;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gboolean
+ice_iochannel_watch (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer client_data)
+{
+ return process_ice_messages (client_data);
+}
+
+static void
+ice_connection_watch (IceConn ice_conn,
+ IcePointer client_data,
+ Bool opening,
+ IcePointer *watch_data)
+{
+ guint watch_id;
+
+ if (opening)
+ {
+ GIOChannel *channel;
+ int fd = IceConnectionNumber (ice_conn);
+
+ fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
+ channel = g_io_channel_unix_new (fd);
+ watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR,
+ ice_iochannel_watch, ice_conn);
+ g_io_channel_unref (channel);
+
+ *watch_data = GUINT_TO_POINTER (watch_id);
+ }
+ else
+ {
+ watch_id = GPOINTER_TO_UINT (*watch_data);
+ g_source_remove (watch_id);
+ }
+}
+
+static void
+ice_error_handler (IceConn ice_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ IcePointer values)
+{
+ /* Do nothing */
+}
+
+static void
+ice_io_error_handler (IceConn ice_conn)
+{
+ /* Do nothing */
+}
+
+static void
+smc_error_handler (SmcConn smc_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ SmPointer values)
+{
+ /* Do nothing */
+}
diff --git a/mate-panel/libegg/eggsmclient.c b/mate-panel/libegg/eggsmclient.c
new file mode 100644
index 00000000..2b480cca
--- /dev/null
+++ b/mate-panel/libegg/eggsmclient.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * 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 "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "eggsmclient.h"
+#include "eggsmclient-private.h"
+
+static void egg_sm_client_debug_handler (const char *log_domain,
+ GLogLevelFlags log_level,
+ const char *message,
+ gpointer user_data);
+
+enum {
+ SAVE_STATE,
+ QUIT_REQUESTED,
+ QUIT_CANCELLED,
+ QUIT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+struct _EggSMClientPrivate {
+ GKeyFile *state_file;
+};
+
+#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
+
+G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
+
+static EggSMClient *global_client;
+static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
+
+static void
+egg_sm_client_init (EggSMClient *client)
+{
+ ;
+}
+
+static void
+egg_sm_client_class_init (EggSMClientClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
+
+ /**
+ * EggSMClient::save_state:
+ * @client: the client
+ * @state_file: a #GKeyFile to save state information into
+ *
+ * Emitted when the session manager has requested that the
+ * application save information about its current state. The
+ * application should save its state into @state_file, and then the
+ * session manager may then restart the application in a future
+ * session and tell it to initialize itself from that state.
+ *
+ * You should not save any data into @state_file's "start group"
+ * (ie, the %NULL group). Instead, applications should save their
+ * data into groups with names that start with the application name,
+ * and libraries that connect to this signal should save their data
+ * into groups with names that start with the library name.
+ *
+ * Alternatively, rather than (or in addition to) using @state_file,
+ * the application can save its state by calling
+ * egg_sm_client_set_restart_command() during the processing of this
+ * signal (eg, to include a list of files to open).
+ **/
+ signals[SAVE_STATE] =
+ g_signal_new ("save_state",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, save_state),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
+ /**
+ * EggSMClient::quit_requested:
+ * @client: the client
+ *
+ * Emitted when the session manager requests that the application
+ * exit (generally because the user is logging out). The application
+ * should decide whether or not it is willing to quit (perhaps after
+ * asking the user what to do with documents that have unsaved
+ * changes) and then call egg_sm_client_will_quit(), passing %TRUE
+ * or %FALSE to give its answer to the session manager. (It does not
+ * need to give an answer before returning from the signal handler;
+ * it can interact with the user asynchronously and then give its
+ * answer later on.) If the application does not connect to this
+ * signal, then #EggSMClient will automatically return %TRUE on its
+ * behalf.
+ *
+ * The application should not save its session state as part of
+ * handling this signal; if the user has requested that the session
+ * be saved when logging out, then ::save_state will be emitted
+ * separately.
+ *
+ * If the application agrees to quit, it should then wait for either
+ * the ::quit_cancelled or ::quit signals to be emitted.
+ **/
+ signals[QUIT_REQUESTED] =
+ g_signal_new ("quit_requested",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * EggSMClient::quit_cancelled:
+ * @client: the client
+ *
+ * Emitted when the session manager decides to cancel a logout after
+ * the application has already agreed to quit. After receiving this
+ * signal, the application can go back to what it was doing before
+ * receiving the ::quit_requested signal.
+ **/
+ signals[QUIT_CANCELLED] =
+ g_signal_new ("quit_cancelled",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * EggSMClient::quit:
+ * @client: the client
+ *
+ * Emitted when the session manager wants the application to quit
+ * (generally because the user is logging out). The application
+ * should exit as soon as possible after receiving this signal; if
+ * it does not, the session manager may choose to forcibly kill it.
+ *
+ * Normally a GUI application would only be sent a ::quit if it
+ * agreed to quit in response to a ::quit_requested signal. However,
+ * this is not guaranteed; in some situations the session manager
+ * may decide to end the session without giving applications a
+ * chance to object.
+ **/
+ signals[QUIT] =
+ g_signal_new ("quit",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, quit),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+static gboolean sm_client_disable = FALSE;
+static char *sm_client_state_file = NULL;
+static char *sm_client_id = NULL;
+static char *sm_config_prefix = NULL;
+
+static gboolean
+sm_client_post_parse_func (GOptionContext *context,
+ GOptionGroup *group,
+ gpointer data,
+ GError **error)
+{
+ EggSMClient *client = egg_sm_client_get ();
+
+ if (sm_client_id == NULL)
+ {
+ const gchar *desktop_autostart_id;
+
+ desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+
+ if (desktop_autostart_id != NULL)
+ sm_client_id = g_strdup (desktop_autostart_id);
+ }
+
+ /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
+ * use the same client id. */
+ g_unsetenv ("DESKTOP_AUTOSTART_ID");
+
+ if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
+ EGG_SM_CLIENT_GET_CLASS (client)->startup)
+ EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
+ return TRUE;
+}
+
+/**
+ * egg_sm_client_get_option_group:
+ *
+ * Creates a %GOptionGroup containing the session-management-related
+ * options. You should add this group to the application's
+ * %GOptionContext if you want to use #EggSMClient.
+ *
+ * Return value: the %GOptionGroup
+ **/
+GOptionGroup *
+egg_sm_client_get_option_group (void)
+{
+ const GOptionEntry entries[] = {
+ { "sm-client-disable", 0, 0,
+ G_OPTION_ARG_NONE, &sm_client_disable,
+ N_("Disable connection to session manager"), NULL },
+ { "sm-client-state-file", 0, 0,
+ G_OPTION_ARG_FILENAME, &sm_client_state_file,
+ N_("Specify file containing saved configuration"), N_("FILE") },
+ { "sm-client-id", 0, 0,
+ G_OPTION_ARG_STRING, &sm_client_id,
+ N_("Specify session management ID"), N_("ID") },
+ /* MateClient compatibility option */
+ { "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_NONE, &sm_client_disable,
+ NULL, NULL },
+ /* MateClient compatibility option. This is a dummy option that only
+ * exists so that sessions saved by apps with MateClient can be restored
+ * later when they've switched to EggSMClient. See bug #575308.
+ */
+ { "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_STRING, &sm_config_prefix,
+ NULL, NULL },
+ { NULL }
+ };
+ GOptionGroup *group;
+
+ /* Use our own debug handler for the "EggSMClient" domain. */
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ egg_sm_client_debug_handler, NULL);
+
+ group = g_option_group_new ("sm-client",
+ _("Session management options:"),
+ _("Show session management options"),
+ NULL, NULL);
+ g_option_group_add_entries (group, entries);
+ g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
+
+ return group;
+}
+
+/**
+ * egg_sm_client_set_mode:
+ * @mode: an #EggSMClient mode
+ *
+ * Sets the "mode" of #EggSMClient as follows:
+ *
+ * %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
+ * disabled, until the mode is changed again. The application will
+ * not even connect to the session manager. (egg_sm_client_get()
+ * will still return an #EggSMClient object.)
+ *
+ * %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
+ * the session manager (and thus will receive notification when the
+ * user is logging out, etc), but will request to not be
+ * automatically restarted with saved state in future sessions.
+ *
+ * %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
+ * function normally.
+ *
+ * This must be called before the application's main loop begins and
+ * before any call to egg_sm_client_get(), unless the mode was set
+ * earlier to %EGG_SM_CLIENT_MODE_DISABLED and this call enables
+ * session management. Note that option parsing will call
+ * egg_sm_client_get().
+ **/
+void
+egg_sm_client_set_mode (EggSMClientMode mode)
+{
+ EggSMClientMode old_mode = global_client_mode;
+
+ g_return_if_fail (global_client == NULL || global_client_mode == EGG_SM_CLIENT_MODE_DISABLED);
+ g_return_if_fail (!(global_client != NULL && mode == EGG_SM_CLIENT_MODE_DISABLED));
+
+ global_client_mode = mode;
+
+ if (global_client != NULL && old_mode == EGG_SM_CLIENT_MODE_DISABLED)
+ {
+ if (EGG_SM_CLIENT_GET_CLASS (global_client)->startup)
+ EGG_SM_CLIENT_GET_CLASS (global_client)->startup (global_client, sm_client_id);
+ }
+}
+
+/**
+ * egg_sm_client_get_mode:
+ *
+ * Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
+ * for details.
+ *
+ * Return value: the global #EggSMClientMode
+ **/
+EggSMClientMode
+egg_sm_client_get_mode (void)
+{
+ return global_client_mode;
+}
+
+/**
+ * egg_sm_client_get:
+ *
+ * Returns the master #EggSMClient for the application.
+ *
+ * On platforms that support saved sessions (ie, POSIX/X11), the
+ * application will only request to be restarted by the session
+ * manager if you call egg_set_desktop_file() to set an application
+ * desktop file. In particular, if the desktop file contains the key
+ * "X
+ *
+ * Return value: the master #EggSMClient.
+ **/
+EggSMClient *
+egg_sm_client_get (void)
+{
+ if (!global_client)
+ {
+ if (!sm_client_disable)
+ {
+#if defined (GDK_WINDOWING_WIN32)
+ global_client = egg_sm_client_win32_new ();
+#elif defined (GDK_WINDOWING_QUARTZ)
+ global_client = egg_sm_client_osx_new ();
+#else
+ /* If both D-Bus and XSMP are compiled in, try XSMP first
+ * (since it supports state saving) and fall back to D-Bus
+ * if XSMP isn't available.
+ */
+# ifdef EGG_SM_CLIENT_BACKEND_XSMP
+ global_client = egg_sm_client_xsmp_new ();
+# endif
+# ifdef EGG_SM_CLIENT_BACKEND_DBUS
+ if (!global_client)
+ global_client = egg_sm_client_dbus_new ();
+# endif
+#endif
+ }
+
+ /* Fallback: create a dummy client, so that callers don't have
+ * to worry about a %NULL return value.
+ */
+ if (!global_client)
+ global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
+ }
+
+ return global_client;
+}
+
+/**
+ * egg_sm_client_is_resumed:
+ * @client: the client
+ *
+ * Checks whether or not the current session has been resumed from
+ * a previous saved session. If so, the application should call
+ * egg_sm_client_get_state_file() and restore its state from the
+ * returned #GKeyFile.
+ *
+ * Return value: %TRUE if the session has been resumed
+ **/
+gboolean
+egg_sm_client_is_resumed (EggSMClient *client)
+{
+ g_return_val_if_fail (client == global_client, FALSE);
+
+ return sm_client_state_file != NULL;
+}
+
+/**
+ * egg_sm_client_get_state_file:
+ * @client: the client
+ *
+ * If the application was resumed by the session manager, this will
+ * return the #GKeyFile containing its state from the previous
+ * session.
+ *
+ * Note that other libraries and #EggSMClient itself may also store
+ * state in the key file, so if you call egg_sm_client_get_groups(),
+ * on it, the return value will likely include groups that you did not
+ * put there yourself. (It is also not guaranteed that the first
+ * group created by the application will still be the "start group"
+ * when it is resumed.)
+ *
+ * Return value: the #GKeyFile containing the application's earlier
+ * state, or %NULL on error. You should not free this key file; it
+ * is owned by @client.
+ **/
+GKeyFile *
+egg_sm_client_get_state_file (EggSMClient *client)
+{
+ EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
+ char *state_file_path;
+ GError *err = NULL;
+
+ g_return_val_if_fail (client == global_client, NULL);
+
+ if (!sm_client_state_file)
+ return NULL;
+ if (priv->state_file)
+ return priv->state_file;
+
+ if (!strncmp (sm_client_state_file, "file://", 7))
+ state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
+ else
+ state_file_path = g_strdup (sm_client_state_file);
+
+ priv->state_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
+ {
+ g_warning ("Could not load SM state file '%s': %s",
+ sm_client_state_file, err->message);
+ g_clear_error (&err);
+ g_key_file_free (priv->state_file);
+ priv->state_file = NULL;
+ }
+
+ g_free (state_file_path);
+ return priv->state_file;
+}
+
+/**
+ * egg_sm_client_set_restart_command:
+ * @client: the client
+ * @argc: the length of @argv
+ * @argv: argument vector
+ *
+ * Sets the command used to restart @client if it does not have a
+ * .desktop file that can be used to find its restart command.
+ *
+ * This can also be used when handling the ::save_state signal, to
+ * save the current state via an updated command line. (Eg, providing
+ * a list of filenames to open when the application is resumed.)
+ **/
+void
+egg_sm_client_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv)
+{
+ g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+ if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
+ EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
+}
+
+/**
+ * egg_sm_client_will_quit:
+ * @client: the client
+ * @will_quit: whether or not the application is willing to quit
+ *
+ * This MUST be called in response to the ::quit_requested signal, to
+ * indicate whether or not the application is willing to quit. The
+ * application may call it either directly from the signal handler, or
+ * at some later point (eg, after asynchronously interacting with the
+ * user).
+ *
+ * If the application does not connect to ::quit_requested,
+ * #EggSMClient will call this method on its behalf (passing %TRUE
+ * for @will_quit).
+ *
+ * After calling this method, the application should wait to receive
+ * either ::quit_cancelled or ::quit.
+ **/
+void
+egg_sm_client_will_quit (EggSMClient *client,
+ gboolean will_quit)
+{
+ g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+ if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
+ EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
+}
+
+/**
+ * egg_sm_client_end_session:
+ * @style: a hint at how to end the session
+ * @request_confirmation: whether or not the user should get a chance
+ * to confirm the action
+ *
+ * Requests that the session manager end the current session. @style
+ * indicates how the session should be ended, and
+ * @request_confirmation indicates whether or not the user should be
+ * given a chance to confirm the logout/reboot/shutdown. Both of these
+ * flags are merely hints though; the session manager may choose to
+ * ignore them.
+ *
+ * Return value: %TRUE if the request was sent; %FALSE if it could not
+ * be (eg, because it could not connect to the session manager).
+ **/
+gboolean
+egg_sm_client_end_session (EggSMClientEndStyle style,
+ gboolean request_confirmation)
+{
+ EggSMClient *client = egg_sm_client_get ();
+
+ g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
+
+ if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
+ {
+ return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
+ request_confirmation);
+ }
+ else
+ return FALSE;
+}
+
+/* Signal-emitting callbacks from platform-specific code */
+
+GKeyFile *
+egg_sm_client_save_state (EggSMClient *client)
+{
+ GKeyFile *state_file;
+ char *group;
+
+ g_return_val_if_fail (client == global_client, NULL);
+
+ state_file = g_key_file_new ();
+
+ g_debug ("Emitting save_state");
+ g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
+ g_debug ("Done emitting save_state");
+
+ group = g_key_file_get_start_group (state_file);
+ if (group)
+ {
+ g_free (group);
+ return state_file;
+ }
+ else
+ {
+ g_key_file_free (state_file);
+ return NULL;
+ }
+}
+
+void
+egg_sm_client_quit_requested (EggSMClient *client)
+{
+ g_return_if_fail (client == global_client);
+
+ if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
+ {
+ g_debug ("Not emitting quit_requested because no one is listening");
+ egg_sm_client_will_quit (client, TRUE);
+ return;
+ }
+
+ g_debug ("Emitting quit_requested");
+ g_signal_emit (client, signals[QUIT_REQUESTED], 0);
+ g_debug ("Done emitting quit_requested");
+}
+
+void
+egg_sm_client_quit_cancelled (EggSMClient *client)
+{
+ g_return_if_fail (client == global_client);
+
+ g_debug ("Emitting quit_cancelled");
+ g_signal_emit (client, signals[QUIT_CANCELLED], 0);
+ g_debug ("Done emitting quit_cancelled");
+}
+
+void
+egg_sm_client_quit (EggSMClient *client)
+{
+ g_return_if_fail (client == global_client);
+
+ g_debug ("Emitting quit");
+ g_signal_emit (client, signals[QUIT], 0);
+ g_debug ("Done emitting quit");
+
+ /* FIXME: should we just call gtk_main_quit() here? */
+}
+
+static void
+egg_sm_client_debug_handler (const char *log_domain,
+ GLogLevelFlags log_level,
+ const char *message,
+ gpointer user_data)
+{
+ static int debug = -1;
+
+ if (debug < 0)
+ debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
+
+ if (debug)
+ g_log_default_handler (log_domain, log_level, message, NULL);
+}
diff --git a/mate-panel/libegg/eggsmclient.h b/mate-panel/libegg/eggsmclient.h
new file mode 100644
index 00000000..be585376
--- /dev/null
+++ b/mate-panel/libegg/eggsmclient.h
@@ -0,0 +1,121 @@
+/* eggsmclient.h
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library 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 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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_SM_CLIENT_H__
+#define __EGG_SM_CLIENT_H__
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
+#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
+#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
+#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
+#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
+#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))
+
+typedef struct _EggSMClient EggSMClient;
+typedef struct _EggSMClientClass EggSMClientClass;
+typedef struct _EggSMClientPrivate EggSMClientPrivate;
+
+typedef enum {
+ EGG_SM_CLIENT_END_SESSION_DEFAULT,
+ EGG_SM_CLIENT_LOGOUT,
+ EGG_SM_CLIENT_REBOOT,
+ EGG_SM_CLIENT_SHUTDOWN
+} EggSMClientEndStyle;
+
+typedef enum {
+ EGG_SM_CLIENT_MODE_DISABLED,
+ EGG_SM_CLIENT_MODE_NO_RESTART,
+ EGG_SM_CLIENT_MODE_NORMAL
+} EggSMClientMode;
+
+struct _EggSMClient
+{
+ GObject parent;
+
+};
+
+struct _EggSMClientClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*save_state) (EggSMClient *client,
+ GKeyFile *state_file);
+
+ void (*quit_requested) (EggSMClient *client);
+ void (*quit_cancelled) (EggSMClient *client);
+ void (*quit) (EggSMClient *client);
+
+ /* virtual methods */
+ void (*startup) (EggSMClient *client,
+ const char *client_id);
+ void (*set_restart_command) (EggSMClient *client,
+ int argc,
+ const char **argv);
+ void (*will_quit) (EggSMClient *client,
+ gboolean will_quit);
+ gboolean (*end_session) (EggSMClient *client,
+ EggSMClientEndStyle style,
+ gboolean request_confirmation);
+
+ /* Padding for future expansion */
+ void (*_egg_reserved1) (void);
+ void (*_egg_reserved2) (void);
+ void (*_egg_reserved3) (void);
+ void (*_egg_reserved4) (void);
+};
+
+GType egg_sm_client_get_type (void) G_GNUC_CONST;
+
+GOptionGroup *egg_sm_client_get_option_group (void);
+
+/* Initialization */
+void egg_sm_client_set_mode (EggSMClientMode mode);
+EggSMClientMode egg_sm_client_get_mode (void);
+EggSMClient *egg_sm_client_get (void);
+
+/* Resuming a saved session */
+gboolean egg_sm_client_is_resumed (EggSMClient *client);
+GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);
+
+/* Alternate means of saving state */
+void egg_sm_client_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv);
+
+/* Handling "quit_requested" signal */
+void egg_sm_client_will_quit (EggSMClient *client,
+ gboolean will_quit);
+
+/* Initiate a logout/reboot/shutdown */
+gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
+ gboolean request_confirmation);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __EGG_SM_CLIENT_H__ */
diff --git a/mate-panel/libmate-panel-applet-private/Makefile.am b/mate-panel/libmate-panel-applet-private/Makefile.am
new file mode 100644
index 00000000..9dd4b631
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/Makefile.am
@@ -0,0 +1,34 @@
+noinst_LTLIBRARIES = \
+ libmate-panel-applet-private.la \
+ libmate-panel-applet-private-mini.la
+
+AM_CPPFLAGS = \
+ $(PANEL_CFLAGS) \
+ -I. \
+ -I$(srcdir) \
+ -I$(top_srcdir)/mate-panel \
+ -I$(top_builddir)/mate-panel \
+ -I$(top_builddir)/mate-panel/libmate-panel-applets-private \
+ -I$(top_builddir)/mate-panel/libpanel-util \
+ -DDATADIR=\""$(datadir)"\" \
+ -DMATE_PANEL_APPLETS_DIR=\"$(appletsdir)\" \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+
+libmate_panel_applet_private_la_SOURCES = \
+ mate-panel-applets-manager-dbus.c \
+ mate-panel-applets-manager-dbus.h \
+ mate-panel-applet-container.c \
+ mate-panel-applet-container.h \
+ mate-panel-applet-frame-dbus.c \
+ mate-panel-applet-frame-dbus.h
+
+libmate_panel_applet_private_mini_la_SOURCES =\
+ mate-panel-applet-mini.c \
+ mate-panel-applets-manager-dbus.c \
+ mate-panel-applets-manager-dbus.h \
+ mate-panel-applet-container.c \
+ mate-panel-applet-container.h
+
+-include $(top_srcdir)/git.mk
diff --git a/mate-panel/libmate-panel-applet-private/Makefile.in b/mate-panel/libmate-panel-applet-private/Makefile.in
new file mode 100644
index 00000000..9c7e63bf
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/Makefile.in
@@ -0,0 +1,644 @@
+# 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 = mate-panel/libmate-panel-applet-private
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/d-type.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/mate-doc-utils.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)
+libmate_panel_applet_private_mini_la_LIBADD =
+am_libmate_panel_applet_private_mini_la_OBJECTS = \
+ mate-panel-applet-mini.lo mate-panel-applets-manager-dbus.lo \
+ mate-panel-applet-container.lo
+libmate_panel_applet_private_mini_la_OBJECTS = \
+ $(am_libmate_panel_applet_private_mini_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libmate_panel_applet_private_la_LIBADD =
+am_libmate_panel_applet_private_la_OBJECTS = \
+ mate-panel-applets-manager-dbus.lo \
+ mate-panel-applet-container.lo mate-panel-applet-frame-dbus.lo
+libmate_panel_applet_private_la_OBJECTS = \
+ $(am_libmate_panel_applet_private_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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libmate_panel_applet_private_mini_la_SOURCES) \
+ $(libmate_panel_applet_private_la_SOURCES)
+DIST_SOURCES = $(libmate_panel_applet_private_mini_la_SOURCES) \
+ $(libmate_panel_applet_private_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CLOCK_CFLAGS = @CLOCK_CFLAGS@
+CLOCK_EDS_ICONDIR = @CLOCK_EDS_ICONDIR@
+CLOCK_LIBS = @CLOCK_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DISABLE_DEPRECATED_CFLAGS = @DISABLE_DEPRECATED_CFLAGS@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DLLTOOL = @DLLTOOL@
+DOC_USER_FORMATS = @DOC_USER_FORMATS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGG_SMCLIENT_CFLAGS = @EGG_SMCLIENT_CFLAGS@
+EGG_SMCLIENT_LIBS = @EGG_SMCLIENT_LIBS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FISH_CFLAGS = @FISH_CFLAGS@
+FISH_LIBS = @FISH_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_QUERYMODULES = @GIO_QUERYMODULES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+HELP_DIR = @HELP_DIR@
+HTML_DIR = @HTML_DIR@
+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@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBMATE_PANEL_APPLET_CFLAGS = @LIBMATE_PANEL_APPLET_CFLAGS@
+LIBMATE_PANEL_APPLET_LIBS = @LIBMATE_PANEL_APPLET_LIBS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MATE_PANEL_APPLET_LT_VERSION = @LIB_MATE_PANEL_APPLET_LT_VERSION@
+LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION = @LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECOMPONENT_ACT_IDLDIR = @MATECOMPONENT_ACT_IDLDIR@
+MATECOMPONENT_CFLAGS = @MATECOMPONENT_CFLAGS@
+MATECOMPONENT_IDLDIR = @MATECOMPONENT_IDLDIR@
+MATECOMPONENT_LIBS = @MATECOMPONENT_LIBS@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATECORBA_IDL = @MATECORBA_IDL@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NETWORK_MANAGER_CFLAGS = @NETWORK_MANAGER_CFLAGS@
+NETWORK_MANAGER_LIBS = @NETWORK_MANAGER_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NOTIFICATION_AREA_CFLAGS = @NOTIFICATION_AREA_CFLAGS@
+NOTIFICATION_AREA_LIBS = @NOTIFICATION_AREA_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OMF_DIR = @OMF_DIR@
+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@
+PANEL_CFLAGS = @PANEL_CFLAGS@
+PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE = @PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE@
+PANEL_LIBS = @PANEL_LIBS@
+PANEL_MODULE_MATECOMPONENT_CFLAGS = @PANEL_MODULE_MATECOMPONENT_CFLAGS@
+PANEL_MODULE_MATECOMPONENT_LIBS = @PANEL_MODULE_MATECOMPONENT_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+REBUILD = @REBUILD@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TZ_CFLAGS = @TZ_CFLAGS@
+TZ_LIBS = @TZ_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WNCKLET_CFLAGS = @WNCKLET_CFLAGS@
+WNCKLET_LIBS = @WNCKLET_LIBS@
+XGETTEXT = @XGETTEXT@
+XMKMF = @XMKMF@
+XRANDR_CFLAGS = @XRANDR_CFLAGS@
+XRANDR_LIBS = @XRANDR_LIBS@
+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_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@
+appletsdir = @appletsdir@
+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@
+modulesdir = @modulesdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+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 = \
+ libmate-panel-applet-private.la \
+ libmate-panel-applet-private-mini.la
+
+AM_CPPFLAGS = \
+ $(PANEL_CFLAGS) \
+ -I. \
+ -I$(srcdir) \
+ -I$(top_srcdir)/mate-panel \
+ -I$(top_builddir)/mate-panel \
+ -I$(top_builddir)/mate-panel/libmate-panel-applets-private \
+ -I$(top_builddir)/mate-panel/libpanel-util \
+ -DDATADIR=\""$(datadir)"\" \
+ -DMATE_PANEL_APPLETS_DIR=\"$(appletsdir)\" \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+libmate_panel_applet_private_la_SOURCES = \
+ mate-panel-applets-manager-dbus.c \
+ mate-panel-applets-manager-dbus.h \
+ mate-panel-applet-container.c \
+ mate-panel-applet-container.h \
+ mate-panel-applet-frame-dbus.c \
+ mate-panel-applet-frame-dbus.h
+
+libmate_panel_applet_private_mini_la_SOURCES = \
+ mate-panel-applet-mini.c \
+ mate-panel-applets-manager-dbus.c \
+ mate-panel-applets-manager-dbus.h \
+ mate-panel-applet-container.c \
+ mate-panel-applet-container.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 mate-panel/libmate-panel-applet-private/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu mate-panel/libmate-panel-applet-private/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(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
+libmate-panel-applet-private-mini.la: $(libmate_panel_applet_private_mini_la_OBJECTS) $(libmate_panel_applet_private_mini_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libmate_panel_applet_private_mini_la_OBJECTS) $(libmate_panel_applet_private_mini_la_LIBADD) $(LIBS)
+libmate-panel-applet-private.la: $(libmate_panel_applet_private_la_OBJECTS) $(libmate_panel_applet_private_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libmate_panel_applet_private_la_OBJECTS) $(libmate_panel_applet_private_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate-panel-applet-container.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate-panel-applet-frame-dbus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate-panel-applet-mini.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mate-panel-applets-manager-dbus.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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."
+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
+
+
+-include $(top_srcdir)/git.mk
+
+# 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/mate-panel/libmate-panel-applet-private/mate-panel-applet-container.c b/mate-panel/libmate-panel-applet-private/mate-panel-applet-container.c
new file mode 100644
index 00000000..f2e39019
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applet-container.c
@@ -0,0 +1,790 @@
+/*
+ * mate-panel-applet-container.c: a container for applets.
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ *
+ * 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 <string.h>
+#include "mate-panel-applet-container.h"
+#include "panel-marshal.h"
+
+struct _MatePanelAppletContainerPrivate {
+ GDBusProxy *applet_proxy;
+
+ guint name_watcher_id;
+ gchar *bus_name;
+
+ guint32 xid;
+ GtkWidget *socket;
+
+ GHashTable *pending_ops;
+};
+
+enum {
+ APPLET_BROKEN,
+ APPLET_MOVE,
+ APPLET_REMOVE,
+ APPLET_LOCK,
+ CHILD_PROPERTY_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+typedef struct {
+ const gchar *name;
+ const gchar *dbus_name;
+} AppletPropertyInfo;
+
+static const AppletPropertyInfo applet_properties [] = {
+ { "prefs-key", "PrefsKey" },
+ { "orient", "Orient" },
+ { "size", "Size" },
+ { "size-hints", "SizeHints" },
+ { "background", "Background" },
+ { "flags", "Flags" },
+ { "locked", "Locked" },
+ { "locked-down", "LockedDown" }
+};
+
+#define MATE_PANEL_APPLET_CONTAINER_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_APPLET_CONTAINER, MatePanelAppletContainerPrivate))
+
+#define MATE_PANEL_APPLET_BUS_NAME "org.mate.panel.applet.%s"
+#define MATE_PANEL_APPLET_FACTORY_INTERFACE "org.mate.panel.applet.AppletFactory"
+#define MATE_PANEL_APPLET_FACTORY_OBJECT_PATH "/org/mate/panel/applet/%s"
+#define MATE_PANEL_APPLET_INTERFACE "org.mate.panel.applet.Applet"
+
+static gboolean mate_panel_applet_container_plug_removed (MatePanelAppletContainer *container);
+
+G_DEFINE_TYPE (MatePanelAppletContainer, mate_panel_applet_container, GTK_TYPE_EVENT_BOX);
+
+GQuark mate_panel_applet_container_error_quark (void)
+{
+ return g_quark_from_static_string ("mate-panel-applet-container-error-quark");
+}
+
+static void mate_panel_applet_container_init(MatePanelAppletContainer* container)
+{
+ container->priv = MATE_PANEL_APPLET_CONTAINER_GET_PRIVATE (container);
+
+ container->priv->socket = gtk_socket_new ();
+ g_signal_connect_swapped (container->priv->socket, "plug-removed", G_CALLBACK (mate_panel_applet_container_plug_removed), container);
+
+ container->priv->pending_ops = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify) g_object_unref);
+
+ gtk_container_add (GTK_CONTAINER (container),
+ container->priv->socket);
+ gtk_widget_show (container->priv->socket);
+}
+
+static void
+mate_panel_applet_container_cancel_pending_operations (MatePanelAppletContainer *container)
+{
+ GList *keys, *l;
+
+ if (!container->priv->pending_ops)
+ return;
+
+ keys = g_hash_table_get_keys (container->priv->pending_ops);
+ for (l = keys; l; l = g_list_next (l)) {
+ GCancellable *cancellable;
+
+ cancellable = G_CANCELLABLE (g_hash_table_lookup (container->priv->pending_ops, l->data));
+ g_cancellable_cancel (cancellable);
+ }
+ g_list_free (keys);
+}
+
+static void
+mate_panel_applet_container_dispose (GObject *object)
+{
+ MatePanelAppletContainer *container = MATE_PANEL_APPLET_CONTAINER (object);
+
+ if (container->priv->pending_ops) {
+ mate_panel_applet_container_cancel_pending_operations (container);
+ g_hash_table_destroy (container->priv->pending_ops);
+ container->priv->pending_ops = NULL;
+ }
+
+ if (container->priv->bus_name) {
+ g_free (container->priv->bus_name);
+ container->priv->bus_name = NULL;
+ }
+
+ if (container->priv->name_watcher_id > 0) {
+ g_bus_unwatch_name (container->priv->name_watcher_id);
+ container->priv->name_watcher_id = 0;
+ }
+
+ if (container->priv->applet_proxy) {
+ g_object_unref (container->priv->applet_proxy);
+ container->priv->applet_proxy = NULL;
+ }
+
+ G_OBJECT_CLASS (mate_panel_applet_container_parent_class)->dispose (object);
+}
+
+static void
+mate_panel_applet_container_class_init (MatePanelAppletContainerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (MatePanelAppletContainerPrivate));
+
+ gobject_class->dispose = mate_panel_applet_container_dispose;
+
+ signals[APPLET_BROKEN] =
+ g_signal_new ("applet-broken",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MatePanelAppletContainerClass, applet_broken),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals[APPLET_MOVE] =
+ g_signal_new ("applet-move",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MatePanelAppletContainerClass, applet_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals[APPLET_REMOVE] =
+ g_signal_new ("applet-remove",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MatePanelAppletContainerClass, applet_remove),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals[APPLET_LOCK] =
+ g_signal_new ("applet-lock",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MatePanelAppletContainerClass, applet_lock),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1, G_TYPE_BOOLEAN);
+ signals[CHILD_PROPERTY_CHANGED] =
+ g_signal_new ("child-property-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE |
+ G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
+ G_STRUCT_OFFSET (MatePanelAppletContainerClass, child_property_changed),
+ NULL,
+ NULL,
+ panel_marshal_VOID__STRING_POINTER,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+}
+
+static const AppletPropertyInfo *
+mate_panel_applet_container_child_property_get_info (const gchar *property_name)
+{
+ gint i;
+
+ g_assert (property_name != NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (applet_properties); i++) {
+ if (g_ascii_strcasecmp (applet_properties[i].name, property_name) == 0)
+ return &applet_properties[i];
+ }
+
+ return NULL;
+}
+
+GtkWidget *
+mate_panel_applet_container_new (void)
+{
+ GtkWidget *container;
+
+ container = GTK_WIDGET (g_object_new (PANEL_TYPE_APPLET_CONTAINER, NULL));
+
+ return container;
+}
+
+static gboolean
+mate_panel_applet_container_plug_removed (MatePanelAppletContainer *container)
+{
+ if (!container->priv->applet_proxy)
+ return FALSE;
+
+ mate_panel_applet_container_cancel_pending_operations (container);
+
+ if (container->priv->name_watcher_id > 0) {
+ g_bus_unwatch_name (container->priv->name_watcher_id);
+ container->priv->name_watcher_id = 0;
+ }
+
+ g_object_unref (container->priv->applet_proxy);
+ container->priv->applet_proxy = NULL;
+
+ g_signal_emit (container, signals[APPLET_BROKEN], 0);
+
+ /* Continue destroying, in case of reloading
+ * a new frame widget is created
+ */
+ return FALSE;
+}
+
+static void
+mate_panel_applet_container_child_signal (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ MatePanelAppletContainer *container)
+{
+ if (g_strcmp0 (signal_name, "Move") == 0) {
+ g_signal_emit (container, signals[APPLET_MOVE], 0);
+ } else if (g_strcmp0 (signal_name, "RemoveFromPanel") == 0) {
+ g_signal_emit (container, signals[APPLET_REMOVE], 0);
+ } else if (g_strcmp0 (signal_name, "Lock") == 0) {
+ g_signal_emit (container, signals[APPLET_LOCK], 0, TRUE);
+ } else if (g_strcmp0 (signal_name, "Unlock") == 0) {
+ g_signal_emit (container, signals[APPLET_LOCK], 0, FALSE);
+ }
+}
+
+static void
+on_property_changed (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ MatePanelAppletContainer *container)
+{
+ GVariant *props;
+ GVariantIter iter;
+ GVariant *value;
+ gchar *key;
+
+ g_variant_get (parameters, "(s@a{sv}*)", NULL, &props, NULL);
+
+ g_variant_iter_init (&iter, props);
+ while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) {
+ if (g_strcmp0 (key, "Flags") == 0) {
+ g_signal_emit (container, signals[CHILD_PROPERTY_CHANGED],
+ g_quark_from_string ("flags"),
+ "flags", value);
+ } else if (g_strcmp0 (key, "SizeHints") == 0) {
+ g_signal_emit (container, signals[CHILD_PROPERTY_CHANGED],
+ g_quark_from_string ("size-hints"),
+ "size-hints", value);
+ }
+ }
+
+ g_variant_unref (props);
+}
+
+static void
+on_proxy_appeared (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ MatePanelAppletContainer *container;
+ GDBusProxy *proxy;
+ GError *error = NULL;
+
+ proxy = g_dbus_proxy_new_finish (res, &error);
+ if (!proxy) {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+ return;
+ }
+
+ container = MATE_PANEL_APPLET_CONTAINER (g_async_result_get_source_object (G_ASYNC_RESULT (result)));
+
+ container->priv->applet_proxy = proxy;
+ g_signal_connect (container->priv->applet_proxy, "g-signal",
+ G_CALLBACK (mate_panel_applet_container_child_signal),
+ container);
+ g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_dbus_proxy_get_object_path (proxy),
+ MATE_PANEL_APPLET_INTERFACE,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ (GDBusSignalCallback) on_property_changed,
+ container, NULL);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+ if (container->priv->xid > 0) {
+ gtk_socket_add_id (GTK_SOCKET (container->priv->socket),
+ container->priv->xid);
+ }
+
+ /* g_async_result_get_source_object returns new ref */
+ g_object_unref (container);
+}
+
+static void
+get_applet_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ MatePanelAppletContainer *container;
+ GVariant *retvals;
+ const gchar *applet_path;
+ GError *error = NULL;
+
+ retvals = g_dbus_connection_call_finish (connection, res, &error);
+ if (!retvals) {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+ return;
+ }
+
+ container = MATE_PANEL_APPLET_CONTAINER (g_async_result_get_source_object (G_ASYNC_RESULT (result)));
+ g_variant_get (retvals, "(&ou)", &applet_path, &container->priv->xid);
+
+ g_dbus_proxy_new (connection,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL,
+ container->priv->bus_name,
+ applet_path,
+ MATE_PANEL_APPLET_INTERFACE,
+ NULL,
+ (GAsyncReadyCallback) on_proxy_appeared,
+ result);
+
+ g_variant_unref (retvals);
+
+ /* g_async_result_get_source_object returns new ref */
+ g_object_unref (container);
+}
+
+typedef struct {
+ GSimpleAsyncResult *result;
+ gchar *factory_id;
+ GVariant *parameters;
+ GCancellable *cancellable;
+} AppletFactoryData;
+
+static void
+applet_factory_data_free (AppletFactoryData *data)
+{
+ g_free (data->factory_id);
+ if (data->cancellable)
+ g_object_unref (data->cancellable);
+
+ g_free (data);
+}
+
+static void
+on_factory_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ AppletFactoryData *data)
+{
+ MatePanelAppletContainer *container;
+ gchar *object_path;
+
+ container = MATE_PANEL_APPLET_CONTAINER (g_async_result_get_source_object (G_ASYNC_RESULT (data->result)));
+ container->priv->bus_name = g_strdup (name_owner);
+ object_path = g_strdup_printf (MATE_PANEL_APPLET_FACTORY_OBJECT_PATH, data->factory_id);
+ g_dbus_connection_call (connection,
+ name_owner,
+ object_path,
+ MATE_PANEL_APPLET_FACTORY_INTERFACE,
+ "GetApplet",
+ data->parameters,
+ G_VARIANT_TYPE ("(ou)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ data->cancellable,
+ get_applet_cb,
+ data->result);
+ g_free (object_path);
+}
+
+static void
+mate_panel_applet_container_get_applet (MatePanelAppletContainer *container,
+ const gchar *iid,
+ GVariant *props,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ AppletFactoryData *data;
+ gint screen;
+ gchar *bus_name;
+ gchar *factory_id;
+ gchar *applet_id;
+
+ result = g_simple_async_result_new (G_OBJECT (container),
+ callback,
+ user_data,
+ mate_panel_applet_container_get_applet);
+
+ applet_id = g_strrstr (iid, "::");
+ if (!applet_id) {
+ g_simple_async_result_set_error (result,
+ MATE_PANEL_APPLET_CONTAINER_ERROR,
+ MATE_PANEL_APPLET_CONTAINER_INVALID_APPLET,
+ "Invalid applet iid: %s", iid);
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+ return;
+ }
+
+ factory_id = g_strndup (iid, strlen (iid) - strlen (applet_id));
+ applet_id += 2;
+
+ screen = gdk_screen_get_number (gtk_widget_get_screen (container->priv->socket));
+
+ data = g_new (AppletFactoryData, 1);
+ data->result = result;
+ data->factory_id = factory_id;
+ data->parameters = g_variant_new ("(si*)", applet_id, screen, props);
+ data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ bus_name = g_strdup_printf (MATE_PANEL_APPLET_BUS_NAME, factory_id);
+
+ container->priv->name_watcher_id =
+ g_bus_watch_name (G_BUS_TYPE_SESSION,
+ bus_name,
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ (GBusNameAppearedCallback) on_factory_appeared,
+ NULL,
+ data,
+ (GDestroyNotify) applet_factory_data_free);
+
+ g_free (bus_name);
+}
+
+void
+mate_panel_applet_container_add (MatePanelAppletContainer *container,
+ const gchar *iid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GVariant *properties)
+{
+ g_return_if_fail (PANEL_IS_APPLET_CONTAINER (container));
+ g_return_if_fail (iid != NULL);
+
+ mate_panel_applet_container_cancel_pending_operations (container);
+
+ mate_panel_applet_container_get_applet (container, iid, properties,
+ cancellable, callback, user_data);
+}
+
+gboolean
+mate_panel_applet_container_add_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == mate_panel_applet_container_get_applet);
+
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/* Child Properties */
+static void
+set_applet_property_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ MatePanelAppletContainer *container;
+ GVariant *retvals;
+ GError *error = NULL;
+
+ retvals = g_dbus_connection_call_finish (connection, res, &error);
+ if (!retvals) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error setting property: %s\n", error->message);
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ } else {
+ g_variant_unref (retvals);
+ }
+
+ container = MATE_PANEL_APPLET_CONTAINER (g_async_result_get_source_object (G_ASYNC_RESULT (result)));
+ g_hash_table_remove (container->priv->pending_ops, result);
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+ /* g_async_result_get_source_object returns new ref */
+ g_object_unref (container);
+}
+
+void
+mate_panel_applet_container_child_set (MatePanelAppletContainer *container,
+ const gchar *property_name,
+ const GVariant *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDBusProxy *proxy = container->priv->applet_proxy;
+ const AppletPropertyInfo *info;
+ GSimpleAsyncResult *result;
+
+ if (!proxy)
+ return;
+
+ info = mate_panel_applet_container_child_property_get_info (property_name);
+ if (!info) {
+ g_simple_async_report_error_in_idle (G_OBJECT (container),
+ callback, user_data,
+ MATE_PANEL_APPLET_CONTAINER_ERROR,
+ MATE_PANEL_APPLET_CONTAINER_INVALID_CHILD_PROPERTY,
+ "%s: Applet has no child property named `%s'",
+ G_STRLOC, property_name);
+ return;
+ }
+
+ result = g_simple_async_result_new (G_OBJECT (container),
+ callback,
+ user_data,
+ mate_panel_applet_container_child_set);
+
+ if (cancellable)
+ g_object_ref (cancellable);
+ else
+ cancellable = g_cancellable_new ();
+ g_hash_table_insert (container->priv->pending_ops, result, cancellable);
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ g_dbus_proxy_get_object_path (proxy),
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ g_variant_new ("(ssv)",
+ g_dbus_proxy_get_interface_name (proxy),
+ info->dbus_name,
+ value),
+ NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, cancellable,
+ set_applet_property_cb,
+ result);
+}
+
+gboolean
+mate_panel_applet_container_child_set_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == mate_panel_applet_container_child_set);
+
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+get_applet_property_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ MatePanelAppletContainer *container;
+ GVariant *retvals;
+ GError *error = NULL;
+
+ retvals = g_dbus_connection_call_finish (connection, res, &error);
+ if (!retvals) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error getting property: %s\n", error->message);
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ } else {
+ GVariant *value, *item;
+
+ item = g_variant_get_child_value (retvals, 0);
+ value = g_variant_get_variant (item);
+ g_variant_unref (item);
+ g_simple_async_result_set_op_res_gpointer (result, value,
+ (GDestroyNotify) g_variant_unref);
+ g_variant_unref (retvals);
+ }
+
+ container = MATE_PANEL_APPLET_CONTAINER (g_async_result_get_source_object (G_ASYNC_RESULT (result)));
+ g_hash_table_remove (container->priv->pending_ops, result);
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+ /* g_async_result_get_source_object returns new ref */
+ g_object_unref (container);
+}
+
+void
+mate_panel_applet_container_child_get (MatePanelAppletContainer *container,
+ const gchar *property_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDBusProxy *proxy = container->priv->applet_proxy;
+ const AppletPropertyInfo *info;
+ GSimpleAsyncResult *result;
+
+ if (!proxy)
+ return;
+
+ info = mate_panel_applet_container_child_property_get_info (property_name);
+ if (!info) {
+ g_simple_async_report_error_in_idle (G_OBJECT (container),
+ callback, user_data,
+ MATE_PANEL_APPLET_CONTAINER_ERROR,
+ MATE_PANEL_APPLET_CONTAINER_INVALID_CHILD_PROPERTY,
+ "%s: Applet has no child property named `%s'",
+ G_STRLOC, property_name);
+ return;
+ }
+
+ result = g_simple_async_result_new (G_OBJECT (container),
+ callback,
+ user_data,
+ mate_panel_applet_container_child_get);
+ if (cancellable)
+ g_object_ref (cancellable);
+ else
+ cancellable = g_cancellable_new ();
+ g_hash_table_insert (container->priv->pending_ops, result, cancellable);
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ g_dbus_proxy_get_object_path (proxy),
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ g_dbus_proxy_get_interface_name (proxy),
+ info->dbus_name),
+ G_VARIANT_TYPE ("(v)"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, cancellable,
+ get_applet_property_cb,
+ result);
+}
+
+GVariant *
+mate_panel_applet_container_child_get_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == mate_panel_applet_container_child_get);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ return g_variant_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+static void
+child_popup_menu_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ GVariant *retvals;
+ GError *error = NULL;
+
+ retvals = g_dbus_connection_call_finish (connection, res, &error);
+ if (!retvals) {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ } else {
+ g_variant_unref (retvals);
+ }
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+void
+mate_panel_applet_container_child_popup_menu (MatePanelAppletContainer *container,
+ guint button,
+ guint32 timestamp,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ GDBusProxy *proxy = container->priv->applet_proxy;
+
+ if (!proxy)
+ return;
+
+ result = g_simple_async_result_new (G_OBJECT (container),
+ callback,
+ user_data,
+ mate_panel_applet_container_child_popup_menu);
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ g_dbus_proxy_get_object_path (proxy),
+ MATE_PANEL_APPLET_INTERFACE,
+ "PopupMenu",
+ g_variant_new ("(uu)", button, timestamp),
+ NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, cancellable,
+ child_popup_menu_cb,
+ result);
+}
+
+gboolean
+mate_panel_applet_container_child_popup_menu_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == mate_panel_applet_container_child_popup_menu);
+
+ return !g_simple_async_result_propagate_error (simple, error);
+}
diff --git a/mate-panel/libmate-panel-applet-private/mate-panel-applet-container.h b/mate-panel/libmate-panel-applet-private/mate-panel-applet-container.h
new file mode 100644
index 00000000..4b1e316a
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applet-container.h
@@ -0,0 +1,118 @@
+/*
+ * mate-panel-applet-container.c: a container for applets.
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ *
+ * 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 __MATE_PANEL_APPLET_CONTAINER_H__
+#define __MATE_PANEL_APPLET_CONTAINER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "panel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_APPLET_CONTAINER (mate_panel_applet_container_get_type ())
+#define MATE_PANEL_APPLET_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_APPLET_CONTAINER, MatePanelAppletContainer))
+#define MATE_PANEL_APPLET_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANEL_TYPE_APPLET_CONTAINER, MatePanelAppletContainerClass))
+#define PANEL_IS_APPLET_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_APPLET_CONTAINER))
+#define PANEL_IS_APPLET_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_APPLET_CONTAINER))
+#define MATE_PANEL_APPLET_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_APPLET_CONTAINER, MatePanelAppletContainerClass))
+
+#define MATE_PANEL_APPLET_CONTAINER_ERROR (mate_panel_applet_container_error_quark())
+
+typedef enum {
+ MATE_PANEL_APPLET_CONTAINER_INVALID_APPLET,
+ MATE_PANEL_APPLET_CONTAINER_INVALID_CHILD_PROPERTY
+} MatePanelAppletContainerError;
+
+typedef struct _MatePanelAppletContainer MatePanelAppletContainer;
+typedef struct _MatePanelAppletContainerClass MatePanelAppletContainerClass;
+typedef struct _MatePanelAppletContainerPrivate MatePanelAppletContainerPrivate;
+
+struct _MatePanelAppletContainer {
+ GtkEventBox parent;
+
+ MatePanelAppletContainerPrivate *priv;
+};
+
+struct _MatePanelAppletContainerClass {
+ GtkEventBoxClass parent_class;
+
+ /* Signals */
+ void (*applet_broken) (MatePanelAppletContainer *container);
+ void (*applet_move) (MatePanelAppletContainer *container);
+ void (*applet_remove) (MatePanelAppletContainer *container);
+ void (*applet_lock) (MatePanelAppletContainer *container,
+ gboolean locked);
+ void (*child_property_changed) (MatePanelAppletContainer *container,
+ const gchar *property_name,
+ GVariant *value);
+};
+
+GType mate_panel_applet_container_get_type (void) G_GNUC_CONST;
+GQuark mate_panel_applet_container_error_quark (void) G_GNUC_CONST;
+GtkWidget *mate_panel_applet_container_new (void);
+
+
+void mate_panel_applet_container_add (MatePanelAppletContainer *container,
+ const gchar *iid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GVariant *properties);
+gboolean mate_panel_applet_container_add_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error);
+void mate_panel_applet_container_child_popup_menu (MatePanelAppletContainer *container,
+ guint button,
+ guint32 timestamp,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mate_panel_applet_container_child_popup_menu_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error);
+
+void mate_panel_applet_container_child_set (MatePanelAppletContainer *container,
+ const gchar *property_name,
+ const GVariant *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mate_panel_applet_container_child_set_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error);
+void mate_panel_applet_container_child_get (MatePanelAppletContainer *container,
+ const gchar *property_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GVariant *mate_panel_applet_container_child_get_finish (MatePanelAppletContainer *container,
+ GAsyncResult *result,
+ GError **error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_PANEL_APPLET_CONTAINER_H__ */
diff --git a/mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.c b/mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.c
new file mode 100644
index 00000000..b2e90e73
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.c
@@ -0,0 +1,468 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * mate-panel-applet-frame-dbus.c: panel side container for applets
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <mate-panel-applet-frame.h>
+#include <mate-panel-applets-manager.h>
+
+#include "mate-panel-applet-container.h"
+
+#include "mate-panel-applet-frame-dbus.h"
+
+G_DEFINE_TYPE (MatePanelAppletFrameDBus,
+ mate_panel_applet_frame_dbus,
+ PANEL_TYPE_APPLET_FRAME)
+
+struct _MatePanelAppletFrameDBusPrivate
+{
+ MatePanelAppletContainer *container;
+ GCancellable *bg_cancellable;
+};
+
+/* Keep in sync with mate-panel-applet.h. Uggh. */
+typedef enum {
+ APPLET_FLAGS_NONE = 0,
+ APPLET_EXPAND_MAJOR = 1 << 0,
+ APPLET_EXPAND_MINOR = 1 << 1,
+ APPLET_HAS_HANDLE = 1 << 2
+} MatePanelAppletFlags;
+
+
+static guint
+get_mate_panel_applet_orient (PanelOrientation orientation)
+{
+ /* For some reason libmate-panel-applet and panel use a different logic for
+ * orientation, so we need to convert it. We should fix this. */
+ switch (orientation) {
+ case PANEL_ORIENTATION_TOP:
+ return 1;
+ case PANEL_ORIENTATION_BOTTOM:
+ return 0;
+ case PANEL_ORIENTATION_LEFT:
+ return 3;
+ case PANEL_ORIENTATION_RIGHT:
+ return 2;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+mate_panel_applet_frame_dbus_update_flags (MatePanelAppletFrame *frame,
+ GVariant *value)
+{
+ guint32 flags;
+ gboolean major;
+ gboolean minor;
+ gboolean has_handle;
+
+ flags = g_variant_get_uint32 (value);
+
+ major = (flags & APPLET_EXPAND_MAJOR) != 0;
+ minor = (flags & APPLET_EXPAND_MINOR) != 0;
+ has_handle = (flags & APPLET_HAS_HANDLE) != 0;
+
+ _mate_panel_applet_frame_update_flags (frame, major, minor, has_handle);
+}
+
+
+static void
+mate_panel_applet_frame_dbus_get_flags_cb (MatePanelAppletContainer *container,
+ GAsyncResult *res,
+ MatePanelAppletFrame *frame)
+{
+ GVariant *value;
+ GError *error = NULL;
+
+ value = mate_panel_applet_container_child_get_finish (container, res, &error);
+ if (!value) {
+ g_warning ("%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ mate_panel_applet_frame_dbus_update_flags (frame, value);
+ g_variant_unref (value);
+}
+
+static void
+mate_panel_applet_frame_dbus_get_size_hints_cb (MatePanelAppletContainer *container,
+ GAsyncResult *res,
+ MatePanelAppletFrame *frame)
+{
+ GVariant *value;
+ const gint *sz;
+ gint *size_hints = NULL;
+ gsize n_elements;
+ GError *error = NULL;
+
+ value = mate_panel_applet_container_child_get_finish (container, res, &error);
+ if (!value) {
+ g_warning ("%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ sz = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
+ if (n_elements > 0) {
+ size_hints = g_new (gint32, n_elements);
+ memcpy (size_hints, sz, n_elements * sizeof (gint32));
+ }
+
+ _mate_panel_applet_frame_update_size_hints (frame, size_hints, n_elements);
+ g_variant_unref (value);
+}
+
+static void
+mate_panel_applet_frame_dbus_init_properties (MatePanelAppletFrame *frame)
+{
+ MatePanelAppletFrameDBus *dbus_frame = MATE_PANEL_APPLET_FRAME_DBUS (frame);
+
+ mate_panel_applet_container_child_get (dbus_frame->priv->container, "flags", NULL,
+ (GAsyncReadyCallback) mate_panel_applet_frame_dbus_get_flags_cb,
+ frame);
+ mate_panel_applet_container_child_get (dbus_frame->priv->container, "size-hints", NULL,
+ (GAsyncReadyCallback) mate_panel_applet_frame_dbus_get_size_hints_cb,
+ frame);
+}
+
+static void
+mate_panel_applet_frame_dbus_sync_menu_state (MatePanelAppletFrame *frame,
+ gboolean movable,
+ gboolean removable,
+ gboolean lockable,
+ gboolean locked,
+ gboolean locked_down)
+{
+ MatePanelAppletFrameDBus *dbus_frame = MATE_PANEL_APPLET_FRAME_DBUS (frame);
+
+ mate_panel_applet_container_child_set (dbus_frame->priv->container,
+ "locked", g_variant_new_boolean (lockable && locked),
+ NULL, NULL, NULL);
+ mate_panel_applet_container_child_set (dbus_frame->priv->container,
+ "locked-down", g_variant_new_boolean (locked_down),
+ NULL, NULL, NULL);
+}
+
+static void
+mate_panel_applet_frame_dbus_popup_menu (MatePanelAppletFrame *frame,
+ guint button,
+ guint32 timestamp)
+{
+ MatePanelAppletFrameDBus *dbus_frame = MATE_PANEL_APPLET_FRAME_DBUS (frame);
+
+ mate_panel_applet_container_child_popup_menu (dbus_frame->priv->container,
+ button, timestamp,
+ NULL, NULL, NULL);
+}
+
+static void
+change_orientation_cb (MatePanelAppletContainer *container,
+ GAsyncResult *res,
+ MatePanelAppletFrame *frame)
+{
+ GError *error = NULL;
+
+ if (!mate_panel_applet_container_child_set_finish (container, res, &error)) {
+ g_warning ("%s\n", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (frame));
+}
+
+static void
+mate_panel_applet_frame_dbus_change_orientation (MatePanelAppletFrame *frame,
+ PanelOrientation orientation)
+{
+ MatePanelAppletFrameDBus *dbus_frame = MATE_PANEL_APPLET_FRAME_DBUS (frame);
+
+ mate_panel_applet_container_child_set (dbus_frame->priv->container,
+ "orient",
+ g_variant_new_uint32 (get_mate_panel_applet_orient (orientation)),
+ NULL,
+ (GAsyncReadyCallback)change_orientation_cb,
+ frame);
+}
+
+static void
+mate_panel_applet_frame_dbus_change_size (MatePanelAppletFrame *frame,
+ guint size)
+{
+ MatePanelAppletFrameDBus *dbus_frame = MATE_PANEL_APPLET_FRAME_DBUS (frame);
+
+ mate_panel_applet_container_child_set (dbus_frame->priv->container,
+ "size", g_variant_new_uint32 (size),
+ NULL, NULL, NULL);
+}
+
+static void
+container_child_background_set (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ MatePanelAppletContainer *container = MATE_PANEL_APPLET_CONTAINER (source_object);
+ MatePanelAppletFrameDBus *frame = MATE_PANEL_APPLET_FRAME_DBUS (user_data);
+
+ mate_panel_applet_container_child_set_finish (container, res, NULL);
+
+ if (frame->priv->bg_cancellable)
+ g_object_unref (frame->priv->bg_cancellable);
+ frame->priv->bg_cancellable = NULL;
+}
+
+static void
+mate_panel_applet_frame_dbus_change_background (MatePanelAppletFrame *frame,
+ PanelBackgroundType type)
+{
+ MatePanelAppletFrameDBus *dbus_frame = MATE_PANEL_APPLET_FRAME_DBUS (frame);
+ char *bg_str;
+
+ bg_str = _mate_panel_applet_frame_get_background_string (
+ frame, PANEL_WIDGET (gtk_widget_get_parent (GTK_WIDGET (frame))), type);
+
+ if (bg_str != NULL) {
+ if (dbus_frame->priv->bg_cancellable)
+ g_cancellable_cancel (dbus_frame->priv->bg_cancellable);
+ dbus_frame->priv->bg_cancellable = g_cancellable_new ();
+
+ mate_panel_applet_container_child_set (dbus_frame->priv->container,
+ "background",
+ g_variant_new_string (bg_str),
+ dbus_frame->priv->bg_cancellable,
+ container_child_background_set,
+ dbus_frame);
+ g_free (bg_str);
+ }
+}
+
+static void
+mate_panel_applet_frame_dbus_flags_changed (MatePanelAppletContainer *container,
+ const gchar *prop_name,
+ GVariant *value,
+ MatePanelAppletFrame *frame)
+{
+ mate_panel_applet_frame_dbus_update_flags (frame, value);
+}
+
+static void
+mate_panel_applet_frame_dbus_size_hints_changed (MatePanelAppletContainer *container,
+ const gchar *prop_name,
+ GVariant *value,
+ MatePanelAppletFrame *frame)
+{
+ const gint *sz;
+ gint *size_hints = NULL;
+ gsize n_elements;
+
+ sz = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
+ if (n_elements > 0) {
+ size_hints = g_new (gint32, n_elements);
+ memcpy (size_hints, sz, n_elements * sizeof (gint32));
+ }
+
+ _mate_panel_applet_frame_update_size_hints (frame, size_hints, n_elements);
+}
+
+static void
+mate_panel_applet_frame_dbus_applet_broken (MatePanelAppletContainer *container,
+ MatePanelAppletFrame *frame)
+{
+ _mate_panel_applet_frame_applet_broken (frame);
+}
+
+static void
+mate_panel_applet_frame_dbus_applet_remove (MatePanelAppletContainer *container,
+ MatePanelAppletFrame *frame)
+{
+ _mate_panel_applet_frame_applet_remove (frame);
+}
+
+static void
+mate_panel_applet_frame_dbus_applet_move (MatePanelAppletContainer *container,
+ MatePanelAppletFrame *frame)
+{
+ _mate_panel_applet_frame_applet_move (frame);
+}
+
+static void
+mate_panel_applet_frame_dbus_applet_lock (MatePanelAppletContainer *container,
+ gboolean locked,
+ MatePanelAppletFrame *frame)
+{
+ _mate_panel_applet_frame_applet_lock (frame, locked);
+}
+
+static void
+mate_panel_applet_frame_dbus_finalize (GObject *object)
+{
+ MatePanelAppletFrameDBus *frame = MATE_PANEL_APPLET_FRAME_DBUS (object);
+
+ if (frame->priv->bg_cancellable)
+ g_object_unref (frame->priv->bg_cancellable);
+ frame->priv->bg_cancellable = NULL;
+
+ G_OBJECT_CLASS (mate_panel_applet_frame_dbus_parent_class)->finalize (object);
+}
+
+static void
+mate_panel_applet_frame_dbus_init (MatePanelAppletFrameDBus *frame)
+{
+ GtkWidget *container;
+
+ frame->priv = G_TYPE_INSTANCE_GET_PRIVATE (frame,
+ PANEL_TYPE_APPLET_FRAME_DBUS,
+ MatePanelAppletFrameDBusPrivate);
+
+ container = mate_panel_applet_container_new ();
+ gtk_widget_show (container);
+ gtk_container_add (GTK_CONTAINER (frame), container);
+ frame->priv->container = MATE_PANEL_APPLET_CONTAINER (container);
+
+ g_signal_connect (container, "child-property-changed::flags",
+ G_CALLBACK (mate_panel_applet_frame_dbus_flags_changed),
+ frame);
+ g_signal_connect (container, "child-property-changed::size-hints",
+ G_CALLBACK (mate_panel_applet_frame_dbus_size_hints_changed),
+ frame);
+ g_signal_connect (container, "applet-broken",
+ G_CALLBACK (mate_panel_applet_frame_dbus_applet_broken),
+ frame);
+ g_signal_connect (container, "applet-remove",
+ G_CALLBACK (mate_panel_applet_frame_dbus_applet_remove),
+ frame);
+ g_signal_connect (container, "applet-move",
+ G_CALLBACK (mate_panel_applet_frame_dbus_applet_move),
+ frame);
+ g_signal_connect (container, "applet-lock",
+ G_CALLBACK (mate_panel_applet_frame_dbus_applet_lock),
+ frame);
+}
+
+static void
+mate_panel_applet_frame_dbus_class_init (MatePanelAppletFrameDBusClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ MatePanelAppletFrameClass *frame_class = MATE_PANEL_APPLET_FRAME_CLASS (class);
+
+ gobject_class->finalize = mate_panel_applet_frame_dbus_finalize;
+
+ frame_class->init_properties = mate_panel_applet_frame_dbus_init_properties;
+ frame_class->sync_menu_state = mate_panel_applet_frame_dbus_sync_menu_state;
+ frame_class->popup_menu = mate_panel_applet_frame_dbus_popup_menu;
+ frame_class->change_orientation = mate_panel_applet_frame_dbus_change_orientation;
+ frame_class->change_size = mate_panel_applet_frame_dbus_change_size;
+ frame_class->change_background = mate_panel_applet_frame_dbus_change_background;
+
+ g_type_class_add_private (class, sizeof (MatePanelAppletFrameDBusPrivate));
+}
+
+static void
+mate_panel_applet_frame_dbus_activated (MatePanelAppletContainer *container,
+ GAsyncResult *res,
+ MatePanelAppletFrame *frame)
+{
+ MatePanelAppletFrameActivating *frame_act;
+ GError *error = NULL;
+
+ if (!mate_panel_applet_container_add_finish (container, res, &error))
+ g_assert (error != NULL);
+
+ frame_act = g_object_get_data (G_OBJECT (frame), "mate-panel-applet-frame-activating");
+ g_object_set_data (G_OBJECT (frame), "mate-panel-applet-frame-activating", NULL);
+
+ _mate_panel_applet_frame_activated (frame, frame_act, error);
+}
+
+gboolean
+mate_panel_applet_frame_dbus_load (const gchar *iid,
+ MatePanelAppletFrameActivating *frame_act)
+{
+ MatePanelAppletFrameDBus *dbus_frame;
+ MatePanelAppletFrame *frame;
+ GVariantBuilder builder;
+ gchar *conf_path;
+ gchar *background;
+ guint orient;
+
+ g_return_val_if_fail (iid != NULL, FALSE);
+ g_return_val_if_fail (frame_act != NULL, FALSE);
+
+ if (!mate_panel_applets_manager_factory_activate (iid))
+ return FALSE;
+
+ dbus_frame = g_object_new (PANEL_TYPE_APPLET_FRAME_DBUS, NULL);
+ frame = MATE_PANEL_APPLET_FRAME (dbus_frame);
+ _mate_panel_applet_frame_set_iid (frame, iid);
+
+ orient = get_mate_panel_applet_orient (mate_panel_applet_frame_activating_get_orientation (frame_act));
+ conf_path = mate_panel_applet_frame_activating_get_conf_path (frame_act);
+ /* we can't really get a background string at this point since we don't
+ * know the position of the applet */
+ background = NULL;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}",
+ "prefs-key",
+ g_variant_new_string (conf_path));
+ g_variant_builder_add (&builder, "{sv}",
+ "orient",
+ g_variant_new_uint32 (orient));
+ g_variant_builder_add (&builder, "{sv}",
+ "size",
+ g_variant_new_uint32 (mate_panel_applet_frame_activating_get_size (frame_act)));
+ g_variant_builder_add (&builder, "{sv}",
+ "locked",
+ g_variant_new_boolean (mate_panel_applet_frame_activating_get_locked (frame_act)));
+ g_variant_builder_add (&builder, "{sv}",
+ "locked-down",
+ g_variant_new_boolean (mate_panel_applet_frame_activating_get_locked_down (frame_act)));
+ if (background) {
+ g_variant_builder_add (&builder, "{sv}",
+ "background",
+ g_variant_new_string (background));
+ }
+
+ g_object_set_data (G_OBJECT (frame), "mate-panel-applet-frame-activating", frame_act);
+
+ mate_panel_applet_container_add (dbus_frame->priv->container,
+ iid, NULL,
+ (GAsyncReadyCallback) mate_panel_applet_frame_dbus_activated,
+ frame,
+ g_variant_builder_end (&builder));
+
+ g_free (conf_path);
+ g_free (background);
+
+ return TRUE;
+}
diff --git a/mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.h b/mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.h
new file mode 100644
index 00000000..e42e792b
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applet-frame-dbus.h
@@ -0,0 +1,65 @@
+/*
+ * mate-panel-applet-frame-dbus.h: panel side container for applets
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2010 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __MATE_PANEL_APPLET_FRAME_DBUS_H__
+#define __MATE_PANEL_APPLET_FRAME_DBUS_H__
+
+#include <mate-panel-applet-frame.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_APPLET_FRAME_DBUS (mate_panel_applet_frame_dbus_get_type ())
+#define MATE_PANEL_APPLET_FRAME_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_APPLET_FRAME_DBUS, MatePanelAppletFrameDBus))
+#define MATE_PANEL_APPLET_FRAME_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_APPLET_FRAME_DBUS, MatePanelAppletFrameDBusClass))
+#define PANEL_IS_APPLET_FRAME_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_APPLET_FRAME_DBUS))
+#define PANEL_IS_APPLET_FRAME_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_APPLET_FRAME_DBUS))
+#define MATE_PANEL_APPLET_FRAME_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_APPLET_FRAME_DBUS, MatePanelAppletFrameDBusClass))
+
+typedef struct _MatePanelAppletFrameDBus MatePanelAppletFrameDBus;
+typedef struct _MatePanelAppletFrameDBusClass MatePanelAppletFrameDBusClass;
+typedef struct _MatePanelAppletFrameDBusPrivate MatePanelAppletFrameDBusPrivate;
+
+struct _MatePanelAppletFrameDBusClass {
+ MatePanelAppletFrameClass parent_class;
+};
+
+struct _MatePanelAppletFrameDBus{
+ MatePanelAppletFrame parent;
+
+ MatePanelAppletFrameDBusPrivate *priv;
+};
+
+GType mate_panel_applet_frame_dbus_get_type (void) G_GNUC_CONST;
+
+gboolean mate_panel_applet_frame_dbus_load (const gchar *iid,
+ MatePanelAppletFrameActivating *frame_act);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_PANEL_APPLET_FRAME_DBUS_H__ */
diff --git a/mate-panel/libmate-panel-applet-private/mate-panel-applet-mini.c b/mate-panel/libmate-panel-applet-private/mate-panel-applet-mini.c
new file mode 100644
index 00000000..13112376
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applet-mini.c
@@ -0,0 +1,5 @@
+/* Symbols needed for libmate-panel-applet-private-mini, which is used by the test
+ * program */
+#include <glib.h>
+gboolean mate_panel_applet_frame_dbus_load (const gchar *iid, gpointer frame_act);
+gboolean mate_panel_applet_frame_dbus_load (const gchar *iid, gpointer frame_act) { return FALSE; }
diff --git a/mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.c b/mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.c
new file mode 100644
index 00000000..9e330f9e
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.c
@@ -0,0 +1,604 @@
+/*
+ * mate-panel-applets-manager-dbus.c
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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.
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+#include <gmodule.h>
+#include <string.h>
+
+#include <mate-panel-applets-manager.h>
+
+#include "mate-panel-applet-frame-dbus.h"
+
+#include "mate-panel-applets-manager-dbus.h"
+
+G_DEFINE_TYPE_WITH_CODE (MatePanelAppletsManagerDBus,
+ mate_panel_applets_manager_dbus,
+ PANEL_TYPE_APPLETS_MANAGER,
+ g_io_extension_point_implement (MATE_PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME,
+ g_define_type_id,
+ "dbus",
+ 10))
+
+struct _MatePanelAppletsManagerDBusPrivate
+{
+ GHashTable *applet_factories;
+ GList *monitors;
+};
+
+typedef gint (* ActivateAppletFunc) (void);
+
+typedef struct _MatePanelAppletFactoryInfo {
+ gchar *id;
+ gchar *location;
+ gboolean in_process;
+ GModule *module;
+ ActivateAppletFunc activate_applet;
+ guint n_applets;
+
+ gchar *srcdir;
+
+ GList *applet_list;
+ gboolean has_old_ids;
+} MatePanelAppletFactoryInfo;
+
+#define MATE_PANEL_APPLET_FACTORY_GROUP "Applet Factory"
+#define MATE_PANEL_APPLETS_EXTENSION ".mate-panel-applet"
+
+static void
+mate_panel_applet_factory_info_free (MatePanelAppletFactoryInfo *info)
+{
+ if (!info)
+ return;
+
+ g_free (info->id);
+ g_free (info->location);
+ g_list_foreach (info->applet_list,
+ (GFunc) mate_panel_applet_info_free,
+ NULL);
+ g_list_free (info->applet_list);
+ info->applet_list = NULL;
+ g_free (info->srcdir);
+
+ g_slice_free (MatePanelAppletFactoryInfo, info);
+}
+
+static MatePanelAppletInfo *
+_mate_panel_applets_manager_get_applet_info (GKeyFile *applet_file,
+ const gchar *group,
+ const gchar *factory_id)
+{
+ MatePanelAppletInfo *info;
+ char *iid;
+ char *name;
+ char *comment;
+ char *icon;
+ char **old_ids;
+
+ iid = g_strdup_printf ("%s::%s", factory_id, group);
+ name = g_key_file_get_locale_string (applet_file, group,
+ "Name", NULL, NULL);
+ comment = g_key_file_get_locale_string (applet_file, group,
+ "Description", NULL, NULL);
+ icon = g_key_file_get_string (applet_file, group, "Icon", NULL);
+ /* MateComponent compatibility */
+ old_ids = g_key_file_get_string_list (applet_file, group,
+ "MateComponentId", NULL, NULL);
+
+ info = mate_panel_applet_info_new (iid, name, comment, icon, (const char **) old_ids);
+
+ g_free (iid);
+ g_free (name);
+ g_free (comment);
+ g_free (icon);
+ g_strfreev (old_ids);
+
+ return info;
+}
+
+static MatePanelAppletFactoryInfo *
+mate_panel_applets_manager_get_applet_factory_info_from_file (const gchar *filename)
+{
+ MatePanelAppletFactoryInfo *info;
+ GKeyFile *applet_file;
+ gchar **groups;
+ gsize n_groups;
+ gint i;
+ GError *error = NULL;
+
+ applet_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (applet_file, filename, G_KEY_FILE_NONE, &error)) {
+ g_warning ("Error opening panel applet file %s: %s",
+ filename, error->message);
+ g_error_free (error);
+ g_key_file_free (applet_file);
+
+ return NULL;
+ }
+
+ info = g_slice_new0 (MatePanelAppletFactoryInfo);
+ info->id = g_key_file_get_string (applet_file, MATE_PANEL_APPLET_FACTORY_GROUP, "Id", NULL);
+ if (!info->id) {
+ g_warning ("Bad panel applet file %s: Could not find 'Id' in group '%s'",
+ filename, MATE_PANEL_APPLET_FACTORY_GROUP);
+ mate_panel_applet_factory_info_free (info);
+ g_key_file_free (applet_file);
+
+ return NULL;
+ }
+
+ info->in_process = g_key_file_get_boolean (applet_file, MATE_PANEL_APPLET_FACTORY_GROUP,
+ "InProcess", NULL);
+ if (info->in_process) {
+ info->location = g_key_file_get_string (applet_file, MATE_PANEL_APPLET_FACTORY_GROUP,
+ "Location", NULL);
+ if (!info->location) {
+ g_warning ("Bad panel applet file %s: In-process applet without 'Location'",
+ filename);
+ mate_panel_applet_factory_info_free (info);
+ g_key_file_free (applet_file);
+
+ return NULL;
+ }
+ }
+
+ info->has_old_ids = FALSE;
+
+ groups = g_key_file_get_groups (applet_file, &n_groups);
+ for (i = 0; i < n_groups; i++) {
+ MatePanelAppletInfo *ainfo;
+
+ if (g_strcmp0 (groups[i], MATE_PANEL_APPLET_FACTORY_GROUP) == 0)
+ continue;
+
+ ainfo = _mate_panel_applets_manager_get_applet_info (applet_file,
+ groups[i], info->id);
+ if (mate_panel_applet_info_get_old_ids (ainfo) != NULL)
+ info->has_old_ids = TRUE;
+
+ info->applet_list = g_list_prepend (info->applet_list, ainfo);
+ }
+ g_strfreev (groups);
+
+ g_key_file_free (applet_file);
+
+ if (!info->applet_list) {
+ mate_panel_applet_factory_info_free (info);
+ return NULL;
+ }
+
+ info->srcdir = g_path_get_dirname (filename);
+
+ return info;
+}
+
+static GSList *
+mate_panel_applets_manager_get_applets_dirs (void)
+{
+ const gchar *dir = NULL;
+ gchar **paths;
+ guint i;
+ GSList *retval = NULL;
+
+ dir = g_getenv ("MATE_PANEL_APPLETS_DIR");
+ if (!dir || g_strcmp0 (dir, "") == 0) {
+ return g_slist_prepend (NULL, g_strdup (MATE_PANEL_APPLETS_DIR));
+ }
+
+ paths = g_strsplit (dir, ":", 0);
+ for (i = 0; paths[i]; i++) {
+ if (g_slist_find_custom (retval, paths[i], (GCompareFunc) g_strcmp0))
+ continue;
+ retval = g_slist_prepend (retval, g_strdup (paths[i]));
+ }
+ g_strfreev (paths);
+
+ return g_slist_reverse (retval);
+}
+
+static void
+applets_directory_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ MatePanelAppletsManagerDBus *manager = MATE_PANEL_APPLETS_MANAGER_DBUS (user_data);
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_CREATED: {
+ MatePanelAppletFactoryInfo *info;
+ MatePanelAppletFactoryInfo *old_info;
+ gchar *filename;
+ GSList *dirs, *d;
+
+ filename = g_file_get_path (file);
+ if (!g_str_has_suffix (filename, MATE_PANEL_APPLETS_EXTENSION)) {
+ g_free (filename);
+ return;
+ }
+
+ info = mate_panel_applets_manager_get_applet_factory_info_from_file (filename);
+ g_free (filename);
+
+ if (!info)
+ return;
+
+ old_info = g_hash_table_lookup (manager->priv->applet_factories, info->id);
+ if (!old_info) {
+ /* New applet, just insert it */
+ g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info);
+ return;
+ }
+
+ /* Make sure we don't update an applet that has changed in
+ * another source dir unless it takes precedence over the
+ * current one */
+ if (g_strcmp0 (info->srcdir, old_info->srcdir) == 0) {
+ g_hash_table_replace (manager->priv->applet_factories, g_strdup (info->id), info);
+ return;
+ }
+
+ dirs = mate_panel_applets_manager_get_applets_dirs ();
+
+ for (d = dirs; d; d = g_slist_next (d)) {
+ gchar *path = (gchar *) d->data;
+
+ if (g_strcmp0 (path, old_info->srcdir) == 0) {
+ mate_panel_applet_factory_info_free (info);
+ break;
+ } else if (g_strcmp0 (path, info->srcdir) == 0) {
+ g_hash_table_replace (manager->priv->applet_factories, g_strdup (info->id), info);
+ break;
+ }
+ }
+
+ g_slist_foreach (dirs, (GFunc) g_free, NULL);
+ g_slist_free (dirs);
+ }
+ break;
+ default:
+ /* Ignore any other change */
+ break;
+ }
+}
+
+static void
+mate_panel_applets_manager_dbus_load_applet_infos (MatePanelAppletsManagerDBus *manager)
+{
+ GSList *dirs, *d;
+ GDir *dir;
+ const gchar *dirent;
+ GError *error = NULL;
+
+ dirs = mate_panel_applets_manager_get_applets_dirs ();
+ for (d = dirs; d; d = g_slist_next (d)) {
+ GFileMonitor *monitor;
+ GFile *dir_file;
+ gchar *path = (gchar *) d->data;
+
+ dir = g_dir_open (path, 0, &error);
+ if (!dir) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ g_free (path);
+
+ continue;
+ }
+
+ /* Monitor dir */
+ dir_file = g_file_new_for_path (path);
+ monitor = g_file_monitor_directory (dir_file,
+ G_FILE_MONITOR_NONE,
+ NULL, NULL);
+ if (monitor) {
+ g_signal_connect (monitor, "changed",
+ G_CALLBACK (applets_directory_changed),
+ manager);
+ manager->priv->monitors = g_list_prepend (manager->priv->monitors, monitor);
+ }
+ g_object_unref (dir_file);
+
+ while ((dirent = g_dir_read_name (dir))) {
+ MatePanelAppletFactoryInfo *info;
+ gchar *file;
+
+ if (!g_str_has_suffix (dirent, MATE_PANEL_APPLETS_EXTENSION))
+ continue;
+
+ file = g_build_filename (path, dirent, NULL);
+ info = mate_panel_applets_manager_get_applet_factory_info_from_file (file);
+ g_free (file);
+
+ if (!info)
+ continue;
+
+ if (g_hash_table_lookup (manager->priv->applet_factories, info->id)) {
+ mate_panel_applet_factory_info_free (info);
+ continue;
+ }
+
+ g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info);
+ }
+
+ g_dir_close (dir);
+ g_free (path);
+ }
+
+ g_slist_free (dirs);
+}
+
+static GList *
+mate_panel_applets_manager_dbus_get_applets (MatePanelAppletsManager *manager)
+{
+ MatePanelAppletsManagerDBus *dbus_manager = MATE_PANEL_APPLETS_MANAGER_DBUS (manager);
+
+ GHashTableIter iter;
+ gpointer key, value;
+ GList *retval = NULL;
+
+ g_hash_table_iter_init (&iter, dbus_manager->priv->applet_factories);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ MatePanelAppletFactoryInfo *info;
+
+ info = (MatePanelAppletFactoryInfo *) value;
+ retval = g_list_concat (retval, g_list_copy (info->applet_list));
+ }
+
+ return retval;
+}
+
+static MatePanelAppletFactoryInfo *
+get_applet_factory_info (MatePanelAppletsManager *manager,
+ const gchar *iid)
+{
+ MatePanelAppletsManagerDBus *dbus_manager = MATE_PANEL_APPLETS_MANAGER_DBUS (manager);
+
+ MatePanelAppletFactoryInfo *info;
+ const gchar *sp;
+ gchar *factory_id;
+
+ sp = g_strrstr (iid, "::");
+ if (!sp)
+ return NULL;
+
+ factory_id = g_strndup (iid, strlen (iid) - strlen (sp));
+ info = g_hash_table_lookup (dbus_manager->priv->applet_factories, factory_id);
+ g_free (factory_id);
+
+ return info;
+}
+
+static gboolean
+mate_panel_applets_manager_dbus_factory_activate (MatePanelAppletsManager *manager,
+ const gchar *iid)
+{
+ MatePanelAppletFactoryInfo *info;
+ ActivateAppletFunc activate_applet;
+
+ info = get_applet_factory_info (manager, iid);
+ if (!info)
+ return FALSE;
+
+ /* Out-of-process applets are activated by the session bus */
+ if (!info->in_process)
+ return TRUE;
+
+ if (info->module) {
+ if (info->n_applets == 0) {
+ if (info->activate_applet () != 0) {
+ g_warning ("Failed to reactivate factory %s\n", iid);
+ return FALSE;
+ }
+ }
+ info->n_applets++;
+
+ return TRUE;
+ }
+
+ info->module = g_module_open (info->location, G_MODULE_BIND_LAZY);
+ if (!info->module) {
+ /* FIXME: use a GError? */
+ g_warning ("Failed to load applet %s: %s\n",
+ iid, g_module_error ());
+ return FALSE;
+ }
+
+ if (!g_module_symbol (info->module, "_mate_panel_applet_shlib_factory", (gpointer *) &activate_applet)) {
+ /* FIXME: use a GError? */
+ g_warning ("Failed to load applet %s: %s\n",
+ iid, g_module_error ());
+ g_module_close (info->module);
+ info->module = NULL;
+
+ return FALSE;
+ }
+
+ /* Activate the applet */
+ if (activate_applet () != 0) {
+ /* FIXME: use a GError? */
+ g_warning ("Failed to load applet %s\n", iid);
+ g_module_close (info->module);
+ info->module = NULL;
+
+ return FALSE;
+ }
+ info->activate_applet = activate_applet;
+
+ info->n_applets = 1;
+
+ return TRUE;
+}
+
+static gboolean
+mate_panel_applets_manager_dbus_factory_deactivate (MatePanelAppletsManager *manager,
+ const gchar *iid)
+{
+ MatePanelAppletFactoryInfo *info;
+
+ info = get_applet_factory_info (manager, iid);
+ if (!info)
+ return FALSE;
+
+ /* Out-of-process applets are deactivated by the session bus */
+ if (!info->in_process)
+ return TRUE;
+
+ if (!info->module)
+ return TRUE;
+
+ info->n_applets--;
+ if (info->n_applets == 0) {
+ /* FIXME: we should close the module here, however applet types
+ * are registered static */
+#if 0
+ g_module_close (info->module);
+ info->module = NULL;
+#endif
+ }
+
+ return TRUE;
+}
+
+static MatePanelAppletInfo *
+mate_panel_applets_manager_dbus_get_applet_info (MatePanelAppletsManager *manager,
+ const gchar *iid)
+{
+ MatePanelAppletFactoryInfo *info;
+ GList *l;
+
+ info = get_applet_factory_info (manager, iid);
+ if (!info)
+ return NULL;
+
+ for (l = info->applet_list; l; l = g_list_next (l)) {
+ MatePanelAppletInfo *ainfo = (MatePanelAppletInfo *) l->data;
+
+ if (g_strcmp0 (mate_panel_applet_info_get_iid (ainfo), iid) == 0)
+ return ainfo;
+ }
+
+ return NULL;
+}
+
+static MatePanelAppletInfo *
+mate_panel_applets_manager_dbus_get_applet_info_from_old_id (MatePanelAppletsManager *manager,
+ const gchar *iid)
+{
+ MatePanelAppletsManagerDBus *dbus_manager = MATE_PANEL_APPLETS_MANAGER_DBUS (manager);
+
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, dbus_manager->priv->applet_factories);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ MatePanelAppletFactoryInfo *info;
+ GList *l;
+
+ info = (MatePanelAppletFactoryInfo *) value;
+ if (!info->has_old_ids)
+ continue;
+
+ for (l = info->applet_list; l; l = g_list_next (l)) {
+ MatePanelAppletInfo *ainfo;
+ gint i = 0;
+ const gchar * const *old_ids;
+
+ ainfo = (MatePanelAppletInfo *) l->data;
+
+ old_ids = mate_panel_applet_info_get_old_ids (ainfo);
+
+ if (old_ids == NULL)
+ continue;
+
+ while (old_ids[i]) {
+ if (g_strcmp0 (old_ids[i], iid) == 0)
+ return ainfo;
+ i++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean
+mate_panel_applets_manager_dbus_load_applet (MatePanelAppletsManager *manager,
+ const gchar *iid,
+ MatePanelAppletFrameActivating *frame_act)
+{
+ return mate_panel_applet_frame_dbus_load (iid, frame_act);
+}
+
+static void
+mate_panel_applets_manager_dbus_finalize (GObject *object)
+{
+ MatePanelAppletsManagerDBus *manager = MATE_PANEL_APPLETS_MANAGER_DBUS (object);
+
+ if (manager->priv->monitors) {
+ g_list_foreach (manager->priv->monitors, (GFunc) g_object_unref, NULL);
+ g_list_free (manager->priv->monitors);
+ manager->priv->monitors = NULL;
+ }
+
+ if (manager->priv->applet_factories) {
+ g_hash_table_destroy (manager->priv->applet_factories);
+ manager->priv->applet_factories = NULL;
+ }
+
+ G_OBJECT_CLASS (mate_panel_applets_manager_dbus_parent_class)->finalize (object);
+}
+
+static void
+mate_panel_applets_manager_dbus_init (MatePanelAppletsManagerDBus *manager)
+{
+ manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
+ PANEL_TYPE_APPLETS_MANAGER_DBUS,
+ MatePanelAppletsManagerDBusPrivate);
+
+ manager->priv->applet_factories = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) mate_panel_applet_factory_info_free);
+
+ mate_panel_applets_manager_dbus_load_applet_infos (manager);
+}
+
+static void
+mate_panel_applets_manager_dbus_class_init (MatePanelAppletsManagerDBusClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ MatePanelAppletsManagerClass *manager_class = MATE_PANEL_APPLETS_MANAGER_CLASS (class);
+
+ gobject_class->finalize = mate_panel_applets_manager_dbus_finalize;
+
+ manager_class->get_applets = mate_panel_applets_manager_dbus_get_applets;
+ manager_class->factory_activate = mate_panel_applets_manager_dbus_factory_activate;
+ manager_class->factory_deactivate = mate_panel_applets_manager_dbus_factory_deactivate;
+ manager_class->get_applet_info = mate_panel_applets_manager_dbus_get_applet_info;
+ manager_class->get_applet_info_from_old_id = mate_panel_applets_manager_dbus_get_applet_info_from_old_id;
+ manager_class->load_applet = mate_panel_applets_manager_dbus_load_applet;
+
+ g_type_class_add_private (class, sizeof (MatePanelAppletsManagerDBusPrivate));
+}
diff --git a/mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.h b/mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.h
new file mode 100644
index 00000000..808795be
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/mate-panel-applets-manager-dbus.h
@@ -0,0 +1,60 @@
+/*
+ * mate-panel-applets-manager-dbus.h
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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 __MATE_PANEL_APPLETS_MANAGER_DBUS_H__
+#define __MATE_PANEL_APPLETS_MANAGER_DBUS_H__
+
+#include <mate-panel-applets-manager.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_APPLETS_MANAGER_DBUS (mate_panel_applets_manager_dbus_get_type ())
+#define MATE_PANEL_APPLETS_MANAGER_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_APPLETS_MANAGER_DBUS, MatePanelAppletsManagerDBus))
+#define MATE_PANEL_APPLETS_MANAGER_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_APPLETS_MANAGER_DBUS, MatePanelAppletsManagerDBusClass))
+#define PANEL_IS_APPLETS_MANAGER_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_APPLETS_MANAGER_DBUS))
+#define PANEL_IS_APPLETS_MANAGER_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_APPLETS_MANAGER_DBUS))
+#define MATE_PANEL_APPLETS_MANAGER_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_APPLETS_MANAGER_DBUS, MatePanelAppletsManagerDBusClass))
+
+typedef struct _MatePanelAppletsManagerDBus MatePanelAppletsManagerDBus;
+typedef struct _MatePanelAppletsManagerDBusClass MatePanelAppletsManagerDBusClass;
+typedef struct _MatePanelAppletsManagerDBusPrivate MatePanelAppletsManagerDBusPrivate;
+
+struct _MatePanelAppletsManagerDBusClass {
+ MatePanelAppletsManagerClass parent_class;
+};
+
+struct _MatePanelAppletsManagerDBus {
+ MatePanelAppletsManager parent;
+
+ /*< private > */
+ MatePanelAppletsManagerDBusPrivate *priv;
+};
+
+GType mate_panel_applets_manager_dbus_get_type (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_PANEL_APPLETS_MANAGER_DBUS_H__ */
diff --git a/mate-panel/libpanel-util/Makefile.am b/mate-panel/libpanel-util/Makefile.am
new file mode 100644
index 00000000..377e26e5
--- /dev/null
+++ b/mate-panel/libpanel-util/Makefile.am
@@ -0,0 +1,39 @@
+noinst_LTLIBRARIES = libpanel-util.la
+
+AM_CPPFLAGS = \
+ $(PANEL_CFLAGS) \
+ -I. \
+ -I$(srcdir) \
+ -I$(top_builddir)/mate-panel/libpanel-util \
+ -DDATADIR=\""$(datadir)"\" \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+
+libpanel_util_la_SOURCES = \
+ panel-cleanup.c \
+ panel-cleanup.h \
+ panel-dbus-service.c \
+ panel-dbus-service.h \
+ panel-error.c \
+ panel-error.h \
+ panel-glib.c \
+ panel-glib.h \
+ panel-gtk.c \
+ panel-gtk.h \
+ panel-icon-chooser.c \
+ panel-icon-chooser.h \
+ panel-keyfile.c \
+ panel-keyfile.h \
+ panel-launch.c \
+ panel-launch.h \
+ panel-list.c \
+ panel-list.h \
+ panel-session-manager.c \
+ panel-session-manager.h \
+ panel-show.c \
+ panel-show.h \
+ panel-xdg.c \
+ panel-xdg.h
+
+-include $(top_srcdir)/git.mk
diff --git a/mate-panel/libpanel-util/Makefile.in b/mate-panel/libpanel-util/Makefile.in
new file mode 100644
index 00000000..05758f14
--- /dev/null
+++ b/mate-panel/libpanel-util/Makefile.in
@@ -0,0 +1,647 @@
+# 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 = mate-panel/libpanel-util
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/d-type.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/mate-doc-utils.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)
+libpanel_util_la_LIBADD =
+am_libpanel_util_la_OBJECTS = panel-cleanup.lo panel-dbus-service.lo \
+ panel-error.lo panel-glib.lo panel-gtk.lo \
+ panel-icon-chooser.lo panel-keyfile.lo panel-launch.lo \
+ panel-list.lo panel-session-manager.lo panel-show.lo \
+ panel-xdg.lo
+libpanel_util_la_OBJECTS = $(am_libpanel_util_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libpanel_util_la_SOURCES)
+DIST_SOURCES = $(libpanel_util_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CLOCK_CFLAGS = @CLOCK_CFLAGS@
+CLOCK_EDS_ICONDIR = @CLOCK_EDS_ICONDIR@
+CLOCK_LIBS = @CLOCK_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DISABLE_DEPRECATED_CFLAGS = @DISABLE_DEPRECATED_CFLAGS@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DLLTOOL = @DLLTOOL@
+DOC_USER_FORMATS = @DOC_USER_FORMATS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGG_SMCLIENT_CFLAGS = @EGG_SMCLIENT_CFLAGS@
+EGG_SMCLIENT_LIBS = @EGG_SMCLIENT_LIBS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FISH_CFLAGS = @FISH_CFLAGS@
+FISH_LIBS = @FISH_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_QUERYMODULES = @GIO_QUERYMODULES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+HELP_DIR = @HELP_DIR@
+HTML_DIR = @HTML_DIR@
+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@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBMATE_PANEL_APPLET_CFLAGS = @LIBMATE_PANEL_APPLET_CFLAGS@
+LIBMATE_PANEL_APPLET_LIBS = @LIBMATE_PANEL_APPLET_LIBS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_CFLAGS@
+LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS = @LIBMATE_PANEL_APPLET_MATECOMPONENT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MATE_PANEL_APPLET_LT_VERSION = @LIB_MATE_PANEL_APPLET_LT_VERSION@
+LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION = @LIB_MATE_PANEL_APPLET_MATECOMPONENT_LT_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECOMPONENT_ACT_IDLDIR = @MATECOMPONENT_ACT_IDLDIR@
+MATECOMPONENT_CFLAGS = @MATECOMPONENT_CFLAGS@
+MATECOMPONENT_IDLDIR = @MATECOMPONENT_IDLDIR@
+MATECOMPONENT_LIBS = @MATECOMPONENT_LIBS@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MATECORBA_IDL = @MATECORBA_IDL@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NETWORK_MANAGER_CFLAGS = @NETWORK_MANAGER_CFLAGS@
+NETWORK_MANAGER_LIBS = @NETWORK_MANAGER_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NOTIFICATION_AREA_CFLAGS = @NOTIFICATION_AREA_CFLAGS@
+NOTIFICATION_AREA_LIBS = @NOTIFICATION_AREA_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OMF_DIR = @OMF_DIR@
+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@
+PANEL_CFLAGS = @PANEL_CFLAGS@
+PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE = @PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE@
+PANEL_LIBS = @PANEL_LIBS@
+PANEL_MODULE_MATECOMPONENT_CFLAGS = @PANEL_MODULE_MATECOMPONENT_CFLAGS@
+PANEL_MODULE_MATECOMPONENT_LIBS = @PANEL_MODULE_MATECOMPONENT_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+REBUILD = @REBUILD@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TZ_CFLAGS = @TZ_CFLAGS@
+TZ_LIBS = @TZ_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WNCKLET_CFLAGS = @WNCKLET_CFLAGS@
+WNCKLET_LIBS = @WNCKLET_LIBS@
+XGETTEXT = @XGETTEXT@
+XMKMF = @XMKMF@
+XRANDR_CFLAGS = @XRANDR_CFLAGS@
+XRANDR_LIBS = @XRANDR_LIBS@
+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_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@
+appletsdir = @appletsdir@
+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@
+modulesdir = @modulesdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+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 = libpanel-util.la
+AM_CPPFLAGS = \
+ $(PANEL_CFLAGS) \
+ -I. \
+ -I$(srcdir) \
+ -I$(top_builddir)/mate-panel/libpanel-util \
+ -DDATADIR=\""$(datadir)"\" \
+ $(DISABLE_DEPRECATED_CFLAGS)
+
+AM_CFLAGS = $(WARN_CFLAGS)
+libpanel_util_la_SOURCES = \
+ panel-cleanup.c \
+ panel-cleanup.h \
+ panel-dbus-service.c \
+ panel-dbus-service.h \
+ panel-error.c \
+ panel-error.h \
+ panel-glib.c \
+ panel-glib.h \
+ panel-gtk.c \
+ panel-gtk.h \
+ panel-icon-chooser.c \
+ panel-icon-chooser.h \
+ panel-keyfile.c \
+ panel-keyfile.h \
+ panel-launch.c \
+ panel-launch.h \
+ panel-list.c \
+ panel-list.h \
+ panel-session-manager.c \
+ panel-session-manager.h \
+ panel-show.c \
+ panel-show.h \
+ panel-xdg.c \
+ panel-xdg.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 mate-panel/libpanel-util/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu mate-panel/libpanel-util/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(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
+libpanel-util.la: $(libpanel_util_la_OBJECTS) $(libpanel_util_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libpanel_util_la_OBJECTS) $(libpanel_util_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-cleanup.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-dbus-service.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-glib.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-gtk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-icon-chooser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-keyfile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-launch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-session-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-show.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel-xdg.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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."
+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
+
+
+-include $(top_srcdir)/git.mk
+
+# 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/mate-panel/libpanel-util/panel-cleanup.c b/mate-panel/libpanel-util/panel-cleanup.c
new file mode 100644
index 00000000..90b089da
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-cleanup.c
@@ -0,0 +1,110 @@
+/*
+ * panel-cleanup.c: utility to clean up things on exit
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "panel-cleanup.h"
+
+typedef struct {
+ PanelCleanFunc func;
+ gpointer data;
+} PanelClean;
+
+static GSList *cleaner;
+
+void
+panel_cleanup_do (void)
+{
+ GSList *l;
+
+ if (!cleaner)
+ return;
+
+ for (l = cleaner; l; l = l->next) {
+ PanelClean *clean;
+
+ clean = l->data;
+ clean->func (clean->data);
+ g_slice_free (PanelClean, clean);
+ }
+
+ g_slist_free (cleaner);
+ cleaner = NULL;
+}
+
+void
+panel_cleanup_register (PanelCleanFunc func,
+ gpointer data)
+{
+ PanelClean *clean;
+
+ g_return_if_fail (func != NULL);
+
+ clean = g_slice_new (PanelClean);
+ clean->func = func;
+ clean->data = data;
+
+ cleaner = g_slist_prepend (cleaner, clean);
+}
+
+void
+panel_cleanup_unregister (PanelCleanFunc func,
+ gpointer data)
+{
+ GSList *l, *next;
+ PanelClean *clean;
+
+ g_return_if_fail (func != NULL);
+
+ if (!cleaner)
+ return;
+
+ l = cleaner;
+
+ do {
+ next = l->next;
+
+ clean = l->data;
+ if (clean->func == func && clean->data == data) {
+ g_slice_free (PanelClean, clean);
+ cleaner = g_slist_delete_link (cleaner, l);
+ }
+
+ l = next;
+ } while (l);
+}
+
+void
+panel_cleanup_unref_and_nullify (gpointer data)
+{
+ GObject **obj;
+
+ g_return_if_fail (data != NULL);
+
+ obj = data;
+
+ g_object_unref (*obj);
+ *obj = NULL;
+}
diff --git a/mate-panel/libpanel-util/panel-cleanup.h b/mate-panel/libpanel-util/panel-cleanup.h
new file mode 100644
index 00000000..3e5a27ab
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-cleanup.h
@@ -0,0 +1,51 @@
+/*
+ * panel-cleanup.h: utility to clean up things on exit
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_CLEANUP_H
+#define PANEL_CLEANUP_H
+
+#include "glib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_CLEAN_FUNC(f) ((PanelCleanFunc) (f))
+
+typedef void (*PanelCleanFunc) (gpointer data);
+
+void panel_cleanup_unref_and_nullify (gpointer data);
+
+void panel_cleanup_do (void);
+
+void panel_cleanup_register (PanelCleanFunc func,
+ gpointer data);
+void panel_cleanup_unregister (PanelCleanFunc func,
+ gpointer data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_CLEANUP_H */
diff --git a/mate-panel/libpanel-util/panel-dbus-service.c b/mate-panel/libpanel-util/panel-dbus-service.c
new file mode 100644
index 00000000..740d9212
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-dbus-service.c
@@ -0,0 +1,307 @@
+/*
+ * panel-dbus-service.c: a simple base object to use a DBus service. Only
+ * useful when subclassed.
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Based on code from panel-power-manager.c:
+ * Copyright (C) 2006 Ray Strode <[email protected]>
+ * (not sure the copyright header was complete)
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+
+#include "panel-dbus-service.h"
+
+struct _PanelDBusServicePrivate {
+ DBusGConnection *dbus_connection;
+ DBusGProxy *bus_proxy;
+ DBusGProxy *service_proxy;
+ guint32 is_connected : 1;
+
+ const char *service_name;
+ const char *service_path;
+ const char *service_interface;
+};
+
+static void panel_dbus_service_finalize (GObject *object);
+static void panel_dbus_service_class_install_properties (PanelDBusServiceClass *service_class);
+
+static void panel_dbus_service_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+enum {
+ PROP_0 = 0,
+ PROP_IS_CONNECTED
+};
+
+G_DEFINE_TYPE (PanelDBusService, panel_dbus_service, G_TYPE_OBJECT);
+
+static void
+panel_dbus_service_class_init (PanelDBusServiceClass *service_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (service_class);
+
+ object_class->finalize = panel_dbus_service_finalize;
+
+ panel_dbus_service_class_install_properties (service_class);
+
+ g_type_class_add_private (service_class,
+ sizeof (PanelDBusServicePrivate));
+}
+
+static void
+panel_dbus_service_class_install_properties (PanelDBusServiceClass *service_class)
+{
+ GObjectClass *object_class;
+ GParamSpec *param_spec;
+
+ object_class = G_OBJECT_CLASS (service_class);
+ object_class->get_property = panel_dbus_service_get_property;
+
+ param_spec = g_param_spec_boolean ("is-connected",
+ "Is connected",
+ "Whether the panel is connected to "
+ "a DBus service",
+ FALSE,
+ G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_IS_CONNECTED,
+ param_spec);
+}
+
+static void
+panel_dbus_service_init (PanelDBusService *service)
+{
+ service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service,
+ PANEL_TYPE_DBUS_SERVICE,
+ PanelDBusServicePrivate);
+
+ service->priv->dbus_connection = NULL;
+ service->priv->bus_proxy = NULL;
+ service->priv->service_proxy = NULL;
+ service->priv->is_connected = FALSE;
+
+ service->priv->service_name = NULL;
+ service->priv->service_path = NULL;
+ service->priv->service_interface = NULL;
+}
+
+static void
+panel_dbus_service_finalize (GObject *object)
+{
+ PanelDBusService *service;
+
+ service = PANEL_DBUS_SERVICE (object);
+
+ if (service->priv->dbus_connection != NULL) {
+ dbus_g_connection_unref (service->priv->dbus_connection);
+ service->priv->dbus_connection = NULL;
+ }
+
+ if (service->priv->bus_proxy != NULL) {
+ g_object_unref (service->priv->bus_proxy);
+ service->priv->bus_proxy = NULL;
+ }
+
+ if (service->priv->service_proxy != NULL) {
+ g_object_unref (service->priv->service_proxy);
+ service->priv->service_proxy = NULL;
+ }
+
+ G_OBJECT_CLASS (panel_dbus_service_parent_class)->finalize (object);
+}
+
+static void
+panel_dbus_service_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelDBusService *service;
+
+ service = PANEL_DBUS_SERVICE (object);
+
+ switch (prop_id) {
+ case PROP_IS_CONNECTED:
+ g_value_set_boolean (value,
+ service->priv->is_connected);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ pspec);
+ }
+}
+
+static void
+panel_dbus_service_on_name_owner_changed (DBusGProxy *bus_proxy,
+ const char *name,
+ const char *prev_owner,
+ const char *new_owner,
+ PanelDBusService *service)
+{
+ g_assert (service->priv->service_name != NULL);
+
+ if (name && strcmp (name, service->priv->service_name) != 0)
+ return;
+
+ if (service->priv->service_proxy != NULL) {
+ g_object_unref (service->priv->service_proxy);
+ service->priv->service_proxy = NULL;
+ }
+
+ panel_dbus_service_ensure_connection (service, NULL);
+}
+
+gboolean
+panel_dbus_service_ensure_connection (PanelDBusService *service,
+ GError **error)
+{
+ GError *connection_error;
+ gboolean is_connected;
+
+ g_return_val_if_fail (PANEL_IS_DBUS_SERVICE (service), FALSE);
+
+ if (!service->priv->service_name ||
+ !service->priv->service_path ||
+ !service->priv->service_interface)
+ return FALSE;
+
+ connection_error = NULL;
+ if (service->priv->dbus_connection == NULL) {
+ service->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION,
+ &connection_error);
+
+ if (service->priv->dbus_connection == NULL) {
+ g_propagate_error (error, connection_error);
+ is_connected = FALSE;
+ goto out;
+ }
+ }
+
+ if (service->priv->bus_proxy == NULL) {
+ service->priv->bus_proxy =
+ dbus_g_proxy_new_for_name_owner (service->priv->dbus_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ &connection_error);
+
+ if (service->priv->bus_proxy == NULL) {
+ g_propagate_error (error, connection_error);
+ is_connected = FALSE;
+ goto out;
+ }
+
+ dbus_g_proxy_add_signal (service->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (service->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_CALLBACK (panel_dbus_service_on_name_owner_changed),
+ service, NULL);
+ }
+
+ if (service->priv->service_proxy == NULL) {
+ service->priv->service_proxy =
+ dbus_g_proxy_new_for_name_owner (
+ service->priv->dbus_connection,
+ service->priv->service_name,
+ service->priv->service_path,
+ service->priv->service_interface,
+ &connection_error);
+
+ if (service->priv->service_proxy == NULL) {
+ g_propagate_error (error, connection_error);
+ is_connected = FALSE;
+ goto out;
+ }
+ }
+ is_connected = TRUE;
+
+out:
+ if (service->priv->is_connected != is_connected) {
+ service->priv->is_connected = is_connected;
+ g_object_notify (G_OBJECT (service), "is-connected");
+ }
+
+ if (!is_connected) {
+ if (service->priv->dbus_connection == NULL) {
+ if (service->priv->bus_proxy != NULL) {
+ g_object_unref (service->priv->bus_proxy);
+ service->priv->bus_proxy = NULL;
+ }
+
+ if (service->priv->service_proxy != NULL) {
+ g_object_unref (service->priv->service_proxy);
+ service->priv->service_proxy = NULL;
+ }
+ } else if (service->priv->bus_proxy == NULL) {
+ if (service->priv->service_proxy != NULL) {
+ g_object_unref (service->priv->service_proxy);
+ service->priv->service_proxy = NULL;
+ }
+ }
+ }
+
+ return is_connected;
+}
+
+void
+panel_dbus_service_define_service (PanelDBusService *service,
+ const char *name,
+ const char *path,
+ const char *interface)
+{
+ g_return_if_fail (PANEL_IS_DBUS_SERVICE (service));
+
+ g_assert (name != NULL);
+ g_assert (path != NULL);
+ g_assert (interface != NULL);
+ g_assert (service->priv->service_name == NULL);
+ g_assert (service->priv->service_path == NULL);
+ g_assert (service->priv->service_interface == NULL);
+
+ service->priv->service_name = name;
+ service->priv->service_path = path;
+ service->priv->service_interface = interface;
+}
+
+DBusGProxy *
+panel_dbus_service_get_proxy (PanelDBusService *service)
+{
+ g_return_val_if_fail (PANEL_IS_DBUS_SERVICE (service), NULL);
+
+ return service->priv->service_proxy;
+}
diff --git a/mate-panel/libpanel-util/panel-dbus-service.h b/mate-panel/libpanel-util/panel-dbus-service.h
new file mode 100644
index 00000000..bfd1830f
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-dbus-service.h
@@ -0,0 +1,78 @@
+/*
+ * panel-dbus-service.h: a simple base object to use a DBus service. Only
+ * useful when subclassed.
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Based on code from panel-power-manager.h:
+ * Copyright (C) 2006 Ray Strode <[email protected]>
+ * (not sure the copyright header was complete)
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_DBUS_SERVICE_H
+#define PANEL_DBUS_SERVICE_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_DBUS_SERVICE (panel_dbus_service_get_type ())
+#define PANEL_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_DBUS_SERVICE, PanelDBusService))
+#define PANEL_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_DBUS_SERVICE, PanelDBusServiceClass))
+#define PANEL_IS_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_DBUS_SERVICE))
+#define PANEL_IS_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_DBUS_SERVICE))
+#define PANEL_DBUS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_DBUS_SERVICE, PanelDBusServiceClass))
+
+typedef struct _PanelDBusService PanelDBusService;
+typedef struct _PanelDBusServiceClass PanelDBusServiceClass;
+typedef struct _PanelDBusServicePrivate PanelDBusServicePrivate;
+
+struct _PanelDBusService {
+ GObject parent;
+
+ /*< private > */
+ PanelDBusServicePrivate *priv;
+};
+
+struct _PanelDBusServiceClass {
+ GObjectClass parent_class;
+};
+
+GType panel_dbus_service_get_type (void);
+
+void panel_dbus_service_define_service (PanelDBusService *service,
+ const char *name,
+ const char *path,
+ const char *interface);
+
+gboolean panel_dbus_service_ensure_connection (PanelDBusService *service,
+ GError **error);
+
+DBusGProxy *panel_dbus_service_get_proxy (PanelDBusService *service);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_DBUS_SERVICE_H */
diff --git a/mate-panel/libpanel-util/panel-error.c b/mate-panel/libpanel-util/panel-error.c
new file mode 100644
index 00000000..de5c9704
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-error.c
@@ -0,0 +1,96 @@
+/*
+ * panel-error.c: an easy-to-use error dialog
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Originally based on code from panel-util.c (there was no relevant copyright
+ * header at the time).
+ *
+ * Originally based on code from panel-util.c (there was no relevant copyright
+ * header at the time), but the code was:
+ * Copyright (C) Novell, Inc. (for the panel_g_utf8_strstrcase() code)
+ * Copyright (C) Dennis Cranston (for the panel_g_lookup_in_data_dirs() code)
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+
+#include "panel-error.h"
+
+GtkWidget *
+panel_error_dialog (GtkWindow *parent,
+ GdkScreen *screen,
+ const char *dialog_class,
+ gboolean auto_destroy,
+ const char *primary_text,
+ const char *secondary_text)
+{
+ GtkWidget *dialog;
+ char *freeme;
+
+ freeme = NULL;
+
+ if (primary_text == NULL) {
+ g_warning ("NULL dialog");
+ /* No need to translate this, this should NEVER happen */
+ freeme = g_strdup_printf ("Error with displaying error "
+ "for dialog of class %s",
+ dialog_class);
+ primary_text = freeme;
+ }
+
+ dialog = gtk_message_dialog_new (parent, 0, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE, "%s", primary_text);
+ if (secondary_text != NULL)
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary_text);
+
+ /* FIXME: we're losing this feature
+ gtk_widget_add_events (dialog, GDK_KEY_PRESS_MASK);
+ g_signal_connect (dialog, "event",
+ G_CALLBACK (panel_dialog_window_event), NULL);
+ */
+
+ if (screen)
+ gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+
+ if (!parent) {
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
+ /* FIXME: We need a title in this case, but we don't know what
+ * the format should be. Let's put something simple until
+ * the following bug gets fixed:
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+ }
+
+ gtk_widget_show_all (dialog);
+
+ if (auto_destroy)
+ g_signal_connect_swapped (G_OBJECT (dialog), "response",
+ G_CALLBACK (gtk_widget_destroy),
+ G_OBJECT (dialog));
+
+ if (freeme)
+ g_free (freeme);
+
+ return dialog;
+}
diff --git a/mate-panel/libpanel-util/panel-error.h b/mate-panel/libpanel-util/panel-error.h
new file mode 100644
index 00000000..314acb08
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-error.h
@@ -0,0 +1,49 @@
+/*
+ * panel-error.h: an easy-to-use error dialog
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Originally based on code from panel-util.h (there was no relevant copyright
+ * header at the time).
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_ERROR_H
+#define PANEL_ERROR_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GtkWidget *panel_error_dialog (GtkWindow *parent,
+ GdkScreen *screen,
+ const char *dialog_class,
+ gboolean auto_destroy,
+ const char *primary_text,
+ const char *secondary_text);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_ERROR_H */
diff --git a/mate-panel/libpanel-util/panel-glib.c b/mate-panel/libpanel-util/panel-glib.c
new file mode 100644
index 00000000..a728f25d
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-glib.c
@@ -0,0 +1,164 @@
+/*
+ * panel-glib.c: various small extensions to glib
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Originally based on code from panel-util.c (there was no relevant copyright
+ * header at the time), but the code was:
+ * Copyright (C) Novell, Inc. (for the panel_g_utf8_strstrcase() code)
+ * Copyright (C) Dennis Cranston (for the panel_g_lookup_in_data_dirs() code)
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <string.h>
+
+#include <glib.h>
+
+#include "panel-glib.h"
+
+typedef char * (*LookupInDir) (const char *basename, const char *dir);
+
+static char *
+_lookup_in_dir (const char *basename,
+ const char *dir)
+{
+ char *path;
+
+ path = g_build_filename (dir, basename, NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+ g_free (path);
+ return NULL;
+ }
+
+ return path;
+}
+
+static char *
+_lookup_in_applications_subdir (const char *basename,
+ const char *dir)
+{
+ char *path;
+
+ path = g_build_filename (dir, "applications", basename, NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+ g_free (path);
+ return NULL;
+ }
+
+ return path;
+}
+
+static char *
+_panel_g_lookup_in_data_dirs_internal (const char *basename,
+ LookupInDir lookup)
+{
+ const char * const *system_data_dirs;
+ const char *user_data_dir;
+ char *retval;
+ int i;
+
+ user_data_dir = g_get_user_data_dir ();
+ system_data_dirs = g_get_system_data_dirs ();
+
+ if ((retval = lookup (basename, user_data_dir)))
+ return retval;
+
+ for (i = 0; system_data_dirs[i]; i++)
+ if ((retval = lookup (basename, system_data_dirs[i])))
+ return retval;
+
+ return NULL;
+}
+
+char *
+panel_g_lookup_in_data_dirs (const char *basename)
+{
+ return _panel_g_lookup_in_data_dirs_internal (basename,
+ _lookup_in_dir);
+}
+
+char *
+panel_g_lookup_in_applications_dirs (const char *basename)
+{
+ return _panel_g_lookup_in_data_dirs_internal (basename,
+ _lookup_in_applications_subdir);
+}
+
+/* Copied from evolution-data-server/libedataserver/e-util.c:
+ * e_util_unicode_get_utf8() */
+static char *
+_unicode_get_utf8 (const char *text, gunichar *out)
+{
+ *out = g_utf8_get_char (text);
+ return (*out == (gunichar)-1) ? NULL : g_utf8_next_char (text);
+}
+
+/* Copied from evolution-data-server/libedataserver/e-util.c:
+ * e_util_utf8_strstrcase() */
+const char *
+panel_g_utf8_strstrcase (const char *haystack, const char *needle)
+{
+ gunichar *nuni;
+ gunichar unival;
+ gint nlen;
+ const char *o, *p;
+
+ if (haystack == NULL) return NULL;
+ if (needle == NULL) return NULL;
+ if (strlen (needle) == 0) return haystack;
+ if (strlen (haystack) == 0) return NULL;
+
+ nuni = g_alloca (sizeof (gunichar) * strlen (needle));
+
+ nlen = 0;
+ for (p = _unicode_get_utf8 (needle, &unival);
+ p && unival;
+ p = _unicode_get_utf8 (p, &unival)) {
+ nuni[nlen++] = g_unichar_tolower (unival);
+ }
+ /* NULL means there was illegal utf-8 sequence */
+ if (!p) return NULL;
+
+ o = haystack;
+ for (p = _unicode_get_utf8 (o, &unival);
+ p && unival;
+ p = _unicode_get_utf8 (p, &unival)) {
+ gint sc;
+ sc = g_unichar_tolower (unival);
+ /* We have valid stripped char */
+ if (sc == nuni[0]) {
+ const char *q = p;
+ gint npos = 1;
+ while (npos < nlen) {
+ q = _unicode_get_utf8 (q, &unival);
+ if (!q || !unival) return NULL;
+ sc = g_unichar_tolower (unival);
+ if (sc != nuni[npos]) break;
+ npos++;
+ }
+ if (npos == nlen) {
+ return o;
+ }
+ }
+ o = p;
+ }
+
+ return NULL;
+}
diff --git a/mate-panel/libpanel-util/panel-glib.h b/mate-panel/libpanel-util/panel-glib.h
new file mode 100644
index 00000000..6b7b4878
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-glib.h
@@ -0,0 +1,46 @@
+/*
+ * panel-glib.h: various small extensions to glib
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_GLIB_H
+#define PANEL_GLIB_H
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_GLIB_STR_EMPTY(x) ((x) == NULL || (x)[0] == '\0')
+
+char *panel_g_lookup_in_data_dirs (const char *basename);
+char *panel_g_lookup_in_applications_dirs (const char *basename);
+
+const char *panel_g_utf8_strstrcase (const char *haystack,
+ const char *needle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_GLIB_H */
diff --git a/mate-panel/libpanel-util/panel-gtk.c b/mate-panel/libpanel-util/panel-gtk.c
new file mode 100644
index 00000000..097367fb
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-gtk.c
@@ -0,0 +1,83 @@
+/*
+ * panel-gtk.c: various small extensions to gtk+
+ *
+ * Copyright (C) 2010 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <gtk/gtk.h>
+
+#include "panel-gtk.h"
+
+/*
+ * Originally based on code from panel-properties-dialog.c. This part of the
+ * code was:
+ * Copyright (C) 2005 Vincent Untz <[email protected]>
+ */
+
+static void
+panel_gtk_file_chooser_preview_update (GtkFileChooser *chooser,
+ gpointer data)
+{
+ GtkWidget *preview;
+ char *filename;
+ GdkPixbuf *pixbuf;
+ gboolean have_preview;
+
+ preview = GTK_WIDGET (data);
+ filename = gtk_file_chooser_get_preview_filename (chooser);
+
+ if (filename == NULL)
+ return;
+
+ pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL);
+ have_preview = (pixbuf != NULL);
+ g_free (filename);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ gtk_file_chooser_set_preview_widget_active (chooser,
+ have_preview);
+}
+
+void
+panel_gtk_file_chooser_add_image_preview (GtkFileChooser *chooser)
+{
+ GtkFileFilter *filter;
+ GtkWidget *chooser_preview;
+
+ g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pixbuf_formats (filter);
+ gtk_file_chooser_set_filter (chooser, filter);
+
+ chooser_preview = gtk_image_new ();
+ gtk_file_chooser_set_preview_widget (chooser, chooser_preview);
+ g_signal_connect (chooser, "update-preview",
+ G_CALLBACK (panel_gtk_file_chooser_preview_update),
+ chooser_preview);
+}
+
+/*
+ * End of code coming from panel-properties-dialog.c
+ */
diff --git a/mate-panel/libpanel-util/panel-gtk.h b/mate-panel/libpanel-util/panel-gtk.h
new file mode 100644
index 00000000..282fb82f
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-gtk.h
@@ -0,0 +1,42 @@
+/*
+ * panel-gtk.h: various small extensions to gtk+
+ *
+ * Copyright (C) 2009-2010 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_GTK_H
+#define PANEL_GTK_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_GTK_BUILDER_GET(builder, name) GTK_WIDGET (gtk_builder_get_object (builder, name))
+
+void panel_gtk_file_chooser_add_image_preview (GtkFileChooser *chooser);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_GTK_H */
diff --git a/mate-panel/libpanel-util/panel-icon-chooser.c b/mate-panel/libpanel-util/panel-icon-chooser.c
new file mode 100644
index 00000000..07d14641
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-icon-chooser.c
@@ -0,0 +1,555 @@
+/*
+ * panel-icon-chooser.c: An icon chooser widget
+ *
+ * Copyright (C) 2010 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "panel-gtk.h"
+#include "panel-xdg.h"
+
+#include "panel-icon-chooser.h"
+
+#define PANEL_ICON_CHOOSER_ICON_SIZE GTK_ICON_SIZE_DIALOG
+
+struct _PanelIconChooserPrivate
+{
+ char *fallback_icon_name;
+ char *icon;
+
+ char *icon_theme_dir;
+
+ GtkWidget *image;
+
+ GtkWidget *filechooser;
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_FALLBACK_ICON,
+ PROP_ICON
+};
+
+static guint panel_icon_chooser_signals[LAST_SIGNAL] = { 0 };
+
+#define PANEL_ICON_CHOOSER_GET_PRIVATE(o) (PANEL_ICON_CHOOSER (o)->priv)
+
+G_DEFINE_TYPE (PanelIconChooser, panel_icon_chooser, GTK_TYPE_BUTTON)
+
+static void _panel_icon_chooser_clicked (GtkButton *button);
+static void _panel_icon_chooser_style_set (GtkWidget *widget,
+ GtkStyle *prev_style);
+static void _panel_icon_chooser_screen_changed (GtkWidget *widget,
+ GdkScreen *prev_screen);
+
+/* gobject stuff */
+
+static GObject *
+panel_icon_chooser_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ PanelIconChooser *chooser;
+
+ obj = G_OBJECT_CLASS (panel_icon_chooser_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ chooser = PANEL_ICON_CHOOSER (obj);
+ gtk_container_add (GTK_CONTAINER (chooser), chooser->priv->image);
+ gtk_widget_show (chooser->priv->image);
+
+ return obj;
+}
+
+static void
+panel_icon_chooser_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelIconChooser *chooser;
+
+ g_return_if_fail (PANEL_IS_ICON_CHOOSER (object));
+
+ chooser = PANEL_ICON_CHOOSER (object);
+
+ switch (prop_id) {
+ case PROP_FALLBACK_ICON:
+ g_value_set_string (value, panel_icon_chooser_get_fallback_icon_name (chooser));
+ break;
+ case PROP_ICON:
+ g_value_set_string (value, panel_icon_chooser_get_icon (chooser));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_icon_chooser_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelIconChooser *chooser;
+
+ g_return_if_fail (PANEL_IS_ICON_CHOOSER (object));
+
+ chooser = PANEL_ICON_CHOOSER (object);
+
+ switch (prop_id) {
+ case PROP_FALLBACK_ICON:
+ panel_icon_chooser_set_fallback_icon_name (chooser,
+ g_value_get_string (value));
+ break;
+ case PROP_ICON:
+ panel_icon_chooser_set_icon (chooser,
+ g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_icon_chooser_destroy (GtkObject *object)
+{
+ PanelIconChooser *chooser;
+
+ chooser = PANEL_ICON_CHOOSER (object);
+
+ if (chooser->priv->filechooser) {
+ gtk_widget_destroy (chooser->priv->filechooser);
+ chooser->priv->filechooser = NULL;
+ }
+
+ /* remember, destroy can be run multiple times! */
+
+ if (chooser->priv->fallback_icon_name != NULL)
+ g_free (chooser->priv->fallback_icon_name);
+ chooser->priv->fallback_icon_name = NULL;
+
+ if (chooser->priv->icon != NULL)
+ g_free (chooser->priv->icon);
+ chooser->priv->icon = NULL;
+
+ if (chooser->priv->icon_theme_dir != NULL)
+ g_free (chooser->priv->icon_theme_dir);
+ chooser->priv->icon_theme_dir = NULL;
+
+ GTK_OBJECT_CLASS (panel_icon_chooser_parent_class)->destroy (object);
+}
+
+static void
+panel_icon_chooser_class_init (PanelIconChooserClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (class);
+ GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (class);
+ GtkButtonClass *gtkbutton_class = GTK_BUTTON_CLASS (class);
+
+ gobject_class->constructor = panel_icon_chooser_constructor;
+ gobject_class->get_property = panel_icon_chooser_get_property;
+ gobject_class->set_property = panel_icon_chooser_set_property;
+
+ gtkobject_class->destroy = panel_icon_chooser_destroy;
+
+ gtkwidget_class->style_set = _panel_icon_chooser_style_set;
+ gtkwidget_class->screen_changed = _panel_icon_chooser_screen_changed;
+
+ gtkbutton_class->clicked = _panel_icon_chooser_clicked;
+
+ g_type_class_add_private (class,
+ sizeof (PanelIconChooserPrivate));
+
+ panel_icon_chooser_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelIconChooserClass,
+ changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_FALLBACK_ICON,
+ g_param_spec_string ("fallback-icon-name",
+ "Fallback Icon Name",
+ "Icon name of the icon displayed (but not returned) if the current icon does not exit",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ICON,
+ g_param_spec_string ("icon",
+ "Icon",
+ "Icon name or path",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+panel_icon_chooser_init (PanelIconChooser *chooser)
+{
+ PanelIconChooserPrivate *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (chooser,
+ PANEL_TYPE_ICON_CHOOSER,
+ PanelIconChooserPrivate);
+
+ chooser->priv = priv;
+
+ priv->fallback_icon_name = g_strdup ("gtk-missing-image");
+ priv->icon = NULL;
+ priv->icon_theme_dir = NULL;
+
+ priv->image = gtk_image_new_from_icon_name (priv->fallback_icon_name,
+ PANEL_ICON_CHOOSER_ICON_SIZE);
+
+ priv->filechooser = NULL;
+}
+
+/* internal code */
+
+static void
+_panel_icon_chooser_update (PanelIconChooser *chooser)
+{
+ if (!chooser->priv->icon) {
+ gtk_image_set_from_icon_name (GTK_IMAGE (chooser->priv->image),
+ chooser->priv->fallback_icon_name,
+ PANEL_ICON_CHOOSER_ICON_SIZE);
+
+ } else if (g_path_is_absolute (chooser->priv->icon)) {
+ gboolean fallback;
+
+ fallback = TRUE;
+
+ if (g_file_test (chooser->priv->icon, G_FILE_TEST_EXISTS)) {
+ /* we pass via a pixbuf to force the size we want */
+ GdkPixbuf *pixbuf;
+ int width, height;
+
+ gtk_icon_size_lookup (PANEL_ICON_CHOOSER_ICON_SIZE,
+ &width, &height);
+ pixbuf = gdk_pixbuf_new_from_file_at_size (chooser->priv->icon,
+ width, height,
+ NULL);
+
+ if (pixbuf) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image),
+ pixbuf);
+ g_object_unref (pixbuf);
+ fallback = FALSE;
+ }
+ }
+
+ if (fallback) {
+ gtk_image_set_from_icon_name (GTK_IMAGE (chooser->priv->image),
+ chooser->priv->fallback_icon_name,
+ PANEL_ICON_CHOOSER_ICON_SIZE);
+ }
+
+ } else {
+ /* Note: using GThemedIcon doesn't work well, see bug #606752.
+ * When we'll remove the alternative code, we won't need the
+ * style_set/screen_changed handlers anymore.
+ */
+#if 0
+ GIcon *icon;
+ char *names[2];
+
+ names[0] = panel_xdg_icon_remove_extension (chooser->priv->icon);
+ names[1] = chooser->priv->fallback_icon_name;
+ icon = g_themed_icon_new_from_names (names, 2);
+
+ gtk_image_set_from_gicon (GTK_IMAGE (chooser->priv->image),
+ icon,
+ PANEL_ICON_CHOOSER_ICON_SIZE);
+
+ g_free (names[0]);
+#endif
+ GtkIconTheme *icon_theme;
+ const char *icon;
+ char *no_ext;
+
+ no_ext = panel_xdg_icon_remove_extension (chooser->priv->icon);
+
+ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (chooser)));
+ if (gtk_icon_theme_has_icon (icon_theme, no_ext))
+ icon = no_ext;
+ else
+ icon = chooser->priv->fallback_icon_name;
+
+ gtk_image_set_from_icon_name (GTK_IMAGE (chooser->priv->image),
+ icon,
+ PANEL_ICON_CHOOSER_ICON_SIZE);
+
+ g_free (no_ext);
+ }
+}
+
+static char *
+_panel_icon_chooser_find_icon_from_path (PanelIconChooser *chooser,
+ const char *path)
+{
+ GdkScreen *screen;
+ char *icon;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (chooser));
+
+ icon = panel_xdg_icon_name_from_icon_path (path, screen);
+ if (!icon)
+ icon = g_strdup (path);
+
+ return icon;
+}
+
+static void
+_panel_icon_chooser_file_chooser_response (GtkFileChooser *filechooser,
+ gint response_id,
+ PanelIconChooser *chooser)
+{
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ char *path;
+ char *icon;
+
+ path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
+ icon = _panel_icon_chooser_find_icon_from_path (chooser, path);
+ g_free (path);
+
+ panel_icon_chooser_set_icon (chooser, icon);
+ g_free (icon);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (filechooser));
+}
+
+static void
+_panel_icon_chooser_clicked (GtkButton *button)
+{
+ PanelIconChooser *chooser = PANEL_ICON_CHOOSER (button);
+ GtkWidget *filechooser;
+ GtkWidget *toplevel;
+ GtkWindow *parent;
+ char *path;
+ gboolean filechooser_path_set;
+
+ if (chooser->priv->filechooser) {
+ gtk_window_present (GTK_WINDOW (chooser->priv->filechooser));
+ return;
+ }
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
+ if (gtk_widget_is_toplevel (toplevel))
+ parent = GTK_WINDOW (toplevel);
+ else
+ parent = NULL;
+
+ filechooser = gtk_file_chooser_dialog_new (_("Choose an icon"),
+ parent,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ panel_gtk_file_chooser_add_image_preview (GTK_FILE_CHOOSER (filechooser));
+
+ path = g_build_filename (DATADIR, "icons", NULL);
+ gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (filechooser),
+ path, NULL);
+ g_free (path);
+
+ path = g_build_filename (DATADIR, "pixmaps", NULL);
+ gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (filechooser),
+ path, NULL);
+ g_free (path);
+
+ filechooser_path_set = FALSE;
+
+ if (chooser->priv->icon) {
+ char *path = NULL;
+ if (g_path_is_absolute (chooser->priv->icon)) {
+ path = g_strdup (chooser->priv->icon);
+ } else {
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *info;
+ char *no_ext;
+ int size;
+
+ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (chooser)));
+ no_ext = panel_xdg_icon_remove_extension (chooser->priv->icon);
+ gtk_icon_size_lookup (PANEL_ICON_CHOOSER_ICON_SIZE,
+ &size, NULL);
+
+ info = gtk_icon_theme_lookup_icon (icon_theme, no_ext,
+ size, 0);
+ g_free (no_ext);
+
+ if (info) {
+ path = g_strdup (gtk_icon_info_get_filename (info));
+ gtk_icon_info_free (info);
+ }
+ }
+
+ if (path) {
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser),
+ path);
+ g_free (path);
+ filechooser_path_set = TRUE;
+ }
+ }
+
+ if (!filechooser_path_set) {
+ char *path;
+ // FIXME? Use current icon theme? But there might not be a lot
+ // of icons there...
+ path = g_build_filename (DATADIR, "icons", NULL);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser),
+ path);
+ }
+
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (filechooser), TRUE);
+
+ g_signal_connect (filechooser, "response",
+ G_CALLBACK (_panel_icon_chooser_file_chooser_response),
+ chooser);
+
+ chooser->priv->filechooser = filechooser;
+
+ g_signal_connect (G_OBJECT (filechooser), "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &chooser->priv->filechooser);
+
+ gtk_widget_show (filechooser);
+}
+
+static void
+_panel_icon_chooser_style_set (GtkWidget *widget,
+ GtkStyle *prev_style)
+{
+ PanelIconChooser *chooser;
+
+ chooser = PANEL_ICON_CHOOSER (widget);
+
+ GTK_WIDGET_CLASS (panel_icon_chooser_parent_class)->style_set (widget, prev_style);
+
+ _panel_icon_chooser_update (chooser);
+}
+
+static void
+_panel_icon_chooser_screen_changed (GtkWidget *widget,
+ GdkScreen *prev_screen)
+{
+ PanelIconChooser *chooser;
+
+ chooser = PANEL_ICON_CHOOSER (widget);
+
+ if (GTK_WIDGET_CLASS (panel_icon_chooser_parent_class)->screen_changed)
+ GTK_WIDGET_CLASS (panel_icon_chooser_parent_class)->screen_changed (widget, prev_screen);
+
+ _panel_icon_chooser_update (chooser);
+}
+
+/* public methods */
+
+GtkWidget *
+panel_icon_chooser_new (const char *icon)
+{
+ GtkWidget *chooser;
+
+ chooser = g_object_new (PANEL_TYPE_ICON_CHOOSER,
+ "icon", icon,
+ NULL);
+
+ return chooser;
+}
+
+const char *
+panel_icon_chooser_get_fallback_icon_name (PanelIconChooser *chooser)
+{
+ g_return_val_if_fail (PANEL_IS_ICON_CHOOSER (chooser), NULL);
+
+ return chooser->priv->fallback_icon_name;
+}
+
+void
+panel_icon_chooser_set_fallback_icon_name (PanelIconChooser *chooser,
+ const char *fallback_icon_name)
+{
+ g_return_if_fail (PANEL_IS_ICON_CHOOSER (chooser));
+
+ if (g_strcmp0 (chooser->priv->fallback_icon_name, fallback_icon_name) == 0)
+ return;
+
+ if (chooser->priv->fallback_icon_name)
+ g_free (chooser->priv->fallback_icon_name);
+ chooser->priv->fallback_icon_name = g_strdup (fallback_icon_name);
+
+ _panel_icon_chooser_update (chooser);
+
+ g_object_notify (G_OBJECT (chooser), "fallback-icon-name");
+}
+
+const char *
+panel_icon_chooser_get_icon (PanelIconChooser *chooser)
+{
+ g_return_val_if_fail (PANEL_IS_ICON_CHOOSER (chooser), NULL);
+
+ return chooser->priv->icon;
+}
+
+void
+panel_icon_chooser_set_icon (PanelIconChooser *chooser,
+ const char *icon)
+{
+ g_return_if_fail (PANEL_IS_ICON_CHOOSER (chooser));
+
+ if (g_strcmp0 (chooser->priv->icon, icon) == 0)
+ return;
+
+ if (chooser->priv->icon)
+ g_free (chooser->priv->icon);
+ chooser->priv->icon = g_strdup (icon);
+
+ _panel_icon_chooser_update (chooser);
+
+ g_object_notify (G_OBJECT (chooser), "icon");
+
+ g_signal_emit (G_OBJECT (chooser),
+ panel_icon_chooser_signals[CHANGED], 0, icon);
+}
diff --git a/mate-panel/libpanel-util/panel-icon-chooser.h b/mate-panel/libpanel-util/panel-icon-chooser.h
new file mode 100644
index 00000000..03475e8f
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-icon-chooser.h
@@ -0,0 +1,79 @@
+/*
+ * panel-icon-chooser.h: An icon chooser widget
+ *
+ * Copyright (C) 2010 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_ICON_CHOOSER_H
+#define PANEL_ICON_CHOOSER_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_ICON_CHOOSER (panel_icon_chooser_get_type ())
+#define PANEL_ICON_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_ICON_CHOOSER, PanelIconChooser))
+#define PANEL_ICON_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_ICON_CHOOSER, PanelIconChooserClass))
+#define PANEL_IS_ICON_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_ICON_CHOOSER))
+#define PANEL_IS_ICON_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_ICON_CHOOSER))
+#define PANEL_ICON_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_ICON_CHOOSER, PanelIconChooserClass))
+
+typedef struct _PanelIconChooser PanelIconChooser;
+typedef struct _PanelIconChooserClass PanelIconChooserClass;
+
+typedef struct _PanelIconChooserPrivate PanelIconChooserPrivate;
+
+struct _PanelIconChooserClass
+{
+ GtkButtonClass parent_class;
+
+ void (* changed) (PanelIconChooser *chooser,
+ const char *icon);
+};
+
+struct _PanelIconChooser
+{
+ GtkButton parent_instance;
+
+ PanelIconChooserPrivate *priv;
+};
+
+GType panel_icon_chooser_get_type (void);
+
+GtkWidget *panel_icon_chooser_new (const char *icon);
+
+const char *panel_icon_chooser_get_fallback_icon_name (PanelIconChooser *chooser);
+
+void panel_icon_chooser_set_fallback_icon_name (PanelIconChooser *chooser,
+ const char *fallback_icon_name);
+
+const char *panel_icon_chooser_get_icon (PanelIconChooser *chooser);
+
+void panel_icon_chooser_set_icon (PanelIconChooser *chooser,
+ const char *icon);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_ICON_CHOOSER_H */
diff --git a/mate-panel/libpanel-util/panel-keyfile.c b/mate-panel/libpanel-util/panel-keyfile.c
new file mode 100644
index 00000000..28ec5853
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-keyfile.c
@@ -0,0 +1,363 @@
+/*
+ * panel-keyfile.c: GKeyFile extensions
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Based on code from panel-util.c (there was no copyright header at the time)
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <string.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "panel-keyfile.h"
+
+#define KEYFILE_TRUSTED_SHEBANG "#!/usr/bin/env xdg-open\n"
+
+GKeyFile *
+panel_key_file_new_desktop (void)
+{
+ GKeyFile *retval;
+
+ retval = g_key_file_new ();
+
+ //FIXME? g_key_file_set_string (retval, G_KEY_FILE_DESKTOP_GROUP, "Name", _("No Name"));
+ g_key_file_set_string (retval, G_KEY_FILE_DESKTOP_GROUP, "Version", "1.0");
+
+ return retval;
+}
+
+static void
+_panel_key_file_make_executable (const gchar *path)
+{
+ GFile *file;
+ GFileInfo *info;
+ guint32 current_perms;
+ guint32 new_perms;
+
+ file = g_file_new_for_path (path);
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE","
+ G_FILE_ATTRIBUTE_UNIX_MODE,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ NULL);
+
+ if (info == NULL) {
+ g_warning ("Cannot mark %s executable", path);
+ g_object_unref (file);
+ return;
+ }
+
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE)) {
+ current_perms = g_file_info_get_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_UNIX_MODE);
+ new_perms = current_perms | S_IXGRP | S_IXUSR | S_IXOTH;
+ if ((current_perms != new_perms) &&
+ !g_file_set_attribute_uint32 (file,
+ G_FILE_ATTRIBUTE_UNIX_MODE,
+ new_perms,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL))
+ g_warning ("Cannot mark %s executable", path);
+ }
+
+ g_object_unref (info);
+ g_object_unref (file);
+}
+
+//FIXME: kill this when bug #309224 is fixed
+gboolean
+panel_key_file_to_file (GKeyFile *keyfile,
+ const gchar *file,
+ GError **error)
+{
+ gchar *filename;
+ GError *write_error;
+ gchar *data;
+ gsize length;
+ gboolean res;
+
+ g_return_val_if_fail (keyfile != NULL, FALSE);
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ write_error = NULL;
+ data = g_key_file_to_data (keyfile, &length, &write_error);
+ if (write_error) {
+ g_propagate_error (error, write_error);
+ return FALSE;
+ }
+
+ if (!g_path_is_absolute (file))
+ filename = g_filename_from_uri (file, NULL, &write_error);
+ else
+ filename = g_filename_from_utf8 (file, -1, NULL, NULL,
+ &write_error);
+
+ if (write_error) {
+ g_propagate_error (error, write_error);
+ g_free (data);
+ return FALSE;
+ }
+
+ if (!g_str_has_prefix (data, "#!")) {
+ gchar *new_data;
+ gsize new_length;
+
+ new_length = length + strlen (KEYFILE_TRUSTED_SHEBANG);
+ new_data = g_malloc (new_length);
+
+ strcpy (new_data, KEYFILE_TRUSTED_SHEBANG);
+ memcpy (new_data + strlen (KEYFILE_TRUSTED_SHEBANG),
+ data, length);
+
+ g_free (data);
+ data = new_data;
+ length = new_length;
+ }
+
+ res = g_file_set_contents (filename, data, length, &write_error);
+
+ if (write_error) {
+ g_propagate_error (error, write_error);
+ g_free (data);
+ g_free (filename);
+ return FALSE;
+ }
+
+ g_free (data);
+
+ _panel_key_file_make_executable (filename);
+ g_free (filename);
+
+ return res;
+}
+
+gboolean
+panel_key_file_load_from_uri (GKeyFile *keyfile,
+ const gchar *uri,
+ GKeyFileFlags flags,
+ GError **error)
+{
+ char *scheme;
+ gboolean is_local;
+ gboolean result;
+
+ g_return_val_if_fail (keyfile != NULL, FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ scheme = g_uri_parse_scheme (uri);
+ is_local = (scheme == NULL) || !g_ascii_strcasecmp (scheme, "file");
+ g_free (scheme);
+
+ if (is_local) {
+ char *path;
+
+ if (g_path_is_absolute (uri))
+ path = g_filename_from_utf8 (uri, -1, NULL, NULL, NULL);
+ else
+ path = g_filename_from_uri (uri, NULL, NULL);
+ result = g_key_file_load_from_file (keyfile, path,
+ flags, error);
+ g_free (path);
+ } else {
+ GFile *file;
+ char *contents;
+ gsize size;
+ gboolean ret;
+
+ file = g_file_new_for_uri (uri);
+ ret = g_file_load_contents (file, NULL, &contents, &size,
+ NULL, NULL);
+ g_object_unref (file);
+
+ if (!ret)
+ return FALSE;
+
+ result = g_key_file_load_from_data (keyfile, contents, size,
+ flags, error);
+
+ g_free (contents);
+ }
+
+ return result;
+}
+
+gboolean
+panel_key_file_copy_and_mark_trusted (const char *source_path,
+ const char *target_path,
+ GError **error)
+{
+ GKeyFile *key_file;
+ gboolean res = FALSE;
+
+ key_file = g_key_file_new ();
+ res = g_key_file_load_from_file (key_file, source_path,
+ G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
+ error);
+ if (!res) {
+ g_key_file_free (key_file);
+ return FALSE;
+ }
+
+ res = panel_key_file_to_file (key_file, target_path, error);
+
+ g_key_file_free (key_file);
+
+ return res;
+}
+
+gboolean
+panel_key_file_get_boolean (GKeyFile *keyfile,
+ const gchar *key,
+ gboolean default_value)
+{
+ GError *error;
+ gboolean retval;
+
+ error = NULL;
+ retval = g_key_file_get_boolean (keyfile, G_KEY_FILE_DESKTOP_GROUP, key, &error);
+ if (error != NULL) {
+ retval = default_value;
+ g_error_free (error);
+ }
+
+ return retval;
+}
+
+void
+panel_key_file_set_locale_string (GKeyFile *keyfile,
+ const gchar *key,
+ const gchar *value)
+{
+ const char *locale;
+ const char * const *langs_pointer;
+ int i;
+
+ locale = NULL;
+ langs_pointer = g_get_language_names ();
+ for (i = 0; langs_pointer[i] != NULL; i++) {
+ /* find first without encoding */
+ if (strchr (langs_pointer[i], '.') == NULL) {
+ locale = langs_pointer[i];
+ break;
+ }
+ }
+
+ if (locale)
+ g_key_file_set_locale_string (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ key, locale, value);
+ else
+ g_key_file_set_string (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ key, value);
+}
+
+void
+panel_key_file_remove_locale_key (GKeyFile *keyfile,
+ const gchar *key)
+{
+ const char * const *langs_pointer;
+ int i;
+ char *locale_key;
+
+ locale_key = NULL;
+ langs_pointer = g_get_language_names ();
+ for (i = 0; langs_pointer[i] != NULL; i++) {
+ /* find first without encoding */
+ if (strchr (langs_pointer[i], '.') == NULL) {
+ locale_key = g_strdup_printf ("%s[%s]",
+ key, langs_pointer[i]);
+ if (g_key_file_has_key (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ locale_key, NULL))
+ break;
+
+ g_free (locale_key);
+ locale_key = NULL;
+ }
+ }
+
+ if (locale_key) {
+ g_key_file_remove_key (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ locale_key, NULL);
+ g_free (locale_key);
+ } else
+ g_key_file_remove_key (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ key, NULL);
+}
+
+void
+panel_key_file_remove_all_locale_key (GKeyFile *keyfile,
+ const gchar *key)
+{
+ char **keys;
+ int key_len;
+ int i;
+
+ if (!key)
+ return;
+
+ keys = g_key_file_get_keys (keyfile, G_KEY_FILE_DESKTOP_GROUP, NULL, NULL);
+ if (!keys)
+ return;
+
+ key_len = strlen (key);
+
+ for (i = 0; keys[i] != NULL; i++) {
+ int len;
+
+ if (strncmp (keys[i], key, key_len))
+ continue;
+
+ len = strlen (keys[i]);
+ if (len == key_len ||
+ (len > key_len && keys[i][key_len] == '['))
+ g_key_file_remove_key (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ keys[i], NULL);
+ }
+
+ g_strfreev (keys);
+}
+
+void
+panel_key_file_ensure_C_key (GKeyFile *keyfile,
+ const char *key)
+{
+ char *C_value;
+ char *buffer;
+
+ /* Make sure we set the "C" locale strings to the terms we set here.
+ * This is so that if the user logs into another locale they get their
+ * own description there rather then empty. It is not the C locale
+ * however, but the user created this entry herself so it's OK */
+ C_value = panel_key_file_get_string (keyfile, key);
+ if (C_value == NULL || C_value [0] == '\0') {
+ buffer = panel_key_file_get_locale_string (keyfile, key);
+ if (buffer) {
+ panel_key_file_set_string (keyfile, key, buffer);
+ g_free (buffer);
+ }
+ }
+ g_free (C_value);
+}
diff --git a/mate-panel/libpanel-util/panel-keyfile.h b/mate-panel/libpanel-util/panel-keyfile.h
new file mode 100644
index 00000000..addcefe4
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-keyfile.h
@@ -0,0 +1,79 @@
+/*
+ * panel-keyfile.h: GKeyFile extensions
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Based on code from panel-util.h (there was no copyright header at the time)
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_KEYFILE_H
+#define PANEL_KEYFILE_H
+
+#include "glib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+GKeyFile *panel_key_file_new_desktop (void);
+gboolean panel_key_file_to_file (GKeyFile *keyfile,
+ const gchar *file,
+ GError **error);
+gboolean panel_key_file_load_from_uri (GKeyFile *keyfile,
+ const gchar *uri,
+ GKeyFileFlags flags,
+ GError **error);
+
+gboolean panel_key_file_copy_and_mark_trusted (const char *source_path,
+ const char *target_path,
+ GError **error);
+
+gboolean panel_key_file_get_boolean (GKeyFile *keyfile,
+ const gchar *key,
+ gboolean default_value);
+#define panel_key_file_get_string(key_file, key) \
+ g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, key, NULL)
+#define panel_key_file_get_locale_string(key_file, key) \
+ g_key_file_get_locale_string(key_file, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL)
+
+#define panel_key_file_set_boolean(key_file, key, value) \
+ g_key_file_set_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, key, value)
+#define panel_key_file_set_string(key_file, key, value) \
+ g_key_file_set_string (key_file, G_KEY_FILE_DESKTOP_GROUP, key, value)
+void panel_key_file_set_locale_string (GKeyFile *keyfile,
+ const gchar *key,
+ const gchar *value);
+
+#define panel_key_file_remove_key(key_file, key) \
+ g_key_file_remove_key (key_file, G_KEY_FILE_DESKTOP_GROUP, key, NULL)
+void panel_key_file_remove_locale_key (GKeyFile *keyfile,
+ const gchar *key);
+void panel_key_file_remove_all_locale_key (GKeyFile *keyfile,
+ const gchar *key);
+void panel_key_file_ensure_C_key (GKeyFile *keyfile,
+ const char *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_KEYFILE_H */
diff --git a/mate-panel/libpanel-util/panel-launch.c b/mate-panel/libpanel-util/panel-launch.c
new file mode 100644
index 00000000..af2b4282
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-launch.c
@@ -0,0 +1,234 @@
+/*
+ * panel-launch.c: some helpers to launch desktop files
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "panel-error.h"
+#include "panel-glib.h"
+
+#include "panel-launch.h"
+
+static void
+_panel_launch_error_dialog (const gchar *name,
+ GdkScreen *screen,
+ const gchar *message)
+{
+ char *primary;
+
+ if (name)
+ primary = g_markup_printf_escaped (_("Could not launch '%s'"),
+ name);
+ else
+ primary = g_strdup (_("Could not launch application"));
+
+ panel_error_dialog (NULL, screen, "cannot_launch", TRUE,
+ primary, message);
+ g_free (primary);
+}
+
+static gboolean
+_panel_launch_handle_error (const gchar *name,
+ GdkScreen *screen,
+ GError *local_error,
+ GError **error)
+{
+ if (local_error == NULL)
+ return TRUE;
+
+ else if (g_error_matches (local_error,
+ G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (local_error);
+ return TRUE;
+ }
+
+ else if (error != NULL)
+ g_propagate_error (error, local_error);
+
+ else {
+ _panel_launch_error_dialog (name, screen, local_error->message);
+ g_error_free (local_error);
+ }
+
+ return FALSE;
+}
+
+gboolean
+panel_app_info_launch_uris (GAppInfo *appinfo,
+ GList *uris,
+ GdkScreen *screen,
+ guint32 timestamp,
+ GError **error)
+{
+ GdkAppLaunchContext *context;
+ GError *local_error;
+ gboolean retval;
+
+ g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ context = gdk_app_launch_context_new ();
+ gdk_app_launch_context_set_screen (context, screen);
+ gdk_app_launch_context_set_timestamp (context, timestamp);
+
+ local_error = NULL;
+ retval = g_app_info_launch_uris (appinfo, uris,
+ (GAppLaunchContext *) context,
+ &local_error);
+
+ g_object_unref (context);
+
+ return _panel_launch_handle_error (g_app_info_get_name (appinfo),
+ screen, local_error, error);
+}
+
+gboolean
+panel_app_info_launch_uri (GAppInfo *appinfo,
+ const gchar *uri,
+ GdkScreen *screen,
+ guint32 timestamp,
+ GError **error)
+{
+ GList *uris;
+ gboolean retval;
+
+ g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ uris = NULL;
+ if (uri)
+ uris = g_list_prepend (uris, (gpointer) uri);
+
+ retval = panel_app_info_launch_uris (appinfo, uris,
+ screen, timestamp, error);
+
+ g_list_free (uris);
+
+ return retval;
+}
+
+gboolean
+panel_launch_key_file (GKeyFile *keyfile,
+ GList *uri_list,
+ GdkScreen *screen,
+ GError **error)
+{
+ GDesktopAppInfo *appinfo;
+ gboolean retval;
+
+ g_return_val_if_fail (keyfile != NULL, FALSE);
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ appinfo = g_desktop_app_info_new_from_keyfile (keyfile);
+
+ if (appinfo == NULL)
+ return FALSE;
+
+ retval = panel_app_info_launch_uris (G_APP_INFO (appinfo),
+ uri_list, screen,
+ gtk_get_current_event_time (),
+ error);
+
+ g_object_unref (appinfo);
+
+ return retval;
+}
+
+gboolean
+panel_launch_desktop_file (const char *desktop_file,
+ GdkScreen *screen,
+ GError **error)
+{
+ GDesktopAppInfo *appinfo;
+ gboolean retval;
+
+ g_return_val_if_fail (desktop_file != NULL, FALSE);
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ appinfo = NULL;
+
+ if (g_path_is_absolute (desktop_file))
+ appinfo = g_desktop_app_info_new_from_filename (desktop_file);
+ else {
+ char *full;
+
+ full = panel_g_lookup_in_applications_dirs (desktop_file);
+ if (full) {
+ appinfo = g_desktop_app_info_new_from_filename (full);
+ g_free (full);
+ }
+ }
+
+ if (appinfo == NULL)
+ return FALSE;
+
+ retval = panel_app_info_launch_uris (G_APP_INFO (appinfo), NULL, screen,
+ gtk_get_current_event_time (),
+ error);
+
+ g_object_unref (appinfo);
+
+ return retval;
+}
+
+gboolean
+panel_launch_desktop_file_with_fallback (const char *desktop_file,
+ const char *fallback_exec,
+ GdkScreen *screen,
+ GError **error)
+{
+ char *argv[2] = { (char *) fallback_exec, NULL };
+ GError *local_error;
+ gboolean retval;
+
+ g_return_val_if_fail (desktop_file != NULL, FALSE);
+ g_return_val_if_fail (fallback_exec != NULL, FALSE);
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* need to pass a non-NULL error to avoid getting a dialog */
+ local_error = NULL;
+ if (panel_launch_desktop_file (desktop_file, screen, &local_error))
+ return TRUE;
+
+ if (local_error) {
+ g_error_free (local_error);
+ local_error = NULL;
+ }
+
+ retval = gdk_spawn_on_screen (screen, NULL, argv, NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &local_error);
+
+ return _panel_launch_handle_error (fallback_exec,
+ screen, local_error, error);
+}
diff --git a/mate-panel/libpanel-util/panel-launch.h b/mate-panel/libpanel-util/panel-launch.h
new file mode 100644
index 00000000..d580f375
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-launch.h
@@ -0,0 +1,65 @@
+/*
+ * panel-launch.h: some helpers to launch desktop files
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_LAUNCH_H
+#define PANEL_LAUNCH_H
+
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean panel_app_info_launch_uris (GAppInfo *appinfo,
+ GList *uris,
+ GdkScreen *screen,
+ guint32 timestamp,
+ GError **error);
+
+gboolean panel_app_info_launch_uri (GAppInfo *appinfo,
+ const gchar *uri,
+ GdkScreen *screen,
+ guint32 timestamp,
+ GError **error);
+
+gboolean panel_launch_key_file (GKeyFile *keyfile,
+ GList *uri_list,
+ GdkScreen *screen,
+ GError **error);
+
+gboolean panel_launch_desktop_file (const char *desktop_file,
+ GdkScreen *screen,
+ GError **error);
+
+gboolean panel_launch_desktop_file_with_fallback (const char *desktop_file,
+ const char *fallback_exec,
+ GdkScreen *screen,
+ GError **error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_LAUNCH_H */
diff --git a/mate-panel/libpanel-util/panel-list.c b/mate-panel/libpanel-util/panel-list.c
new file mode 100644
index 00000000..db036186
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-list.c
@@ -0,0 +1,212 @@
+/*
+ * panel-list.c: GList & GSList extensions
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * Originally based on code from panel-util.c (there was no relevant copyright
+ * header at the time), but the code was:
+ * Copyright (C) Mark McLoughlin <[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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <glib.h>
+
+#include "panel-list.h"
+
+GList *
+panel_g_list_insert_before (GList *list,
+ GList *sibling,
+ GList *link)
+{
+ if (!list) {
+ g_return_val_if_fail (sibling == NULL, list);
+ return link;
+ } else if (sibling) {
+ if (sibling->prev) {
+ link->prev = sibling->prev;
+ link->prev->next = link;
+ link->next = sibling;
+ sibling->prev = link;
+ return list;
+ } else {
+ link->next = sibling;
+ sibling->prev = link;
+ g_return_val_if_fail (sibling == list, link);
+ return link;
+ }
+ } else {
+ GList *last;
+
+ last = list;
+ while (last->next)
+ last = last->next;
+
+ last->next = link;
+ link->prev = last;
+ return list;
+ }
+}
+
+GList *
+panel_g_list_insert_after (GList *list,
+ GList *sibling,
+ GList *link)
+{
+ if (!list) {
+ g_return_val_if_fail (sibling == NULL, link);
+ return link;
+ } else if (sibling) {
+ if (sibling->next) {
+ link->next = sibling->next;
+ link->next->prev = link;
+ link->prev = sibling;
+ sibling->next = link;
+ return list;
+ } else {
+ sibling->next = link;
+ link->prev = sibling;
+ return list;
+ }
+
+ } else {
+ link->next = list;
+ list->prev = link;
+ return link;
+ }
+}
+
+GList *
+panel_g_list_swap_next (GList *list,
+ GList *dl)
+{
+ GList *t;
+
+ if (!dl)
+ return list;
+
+ if (!dl->next)
+ return list;
+
+ if (dl->prev)
+ dl->prev->next = dl->next;
+ t = dl->prev;
+ dl->prev = dl->next;
+ dl->next->prev = t;
+ if (dl->next->next)
+ dl->next->next->prev = dl;
+ t = dl->next->next;
+ dl->next->next = dl;
+ dl->next = t;
+
+ if (list == dl)
+ return dl->prev;
+
+ return list;
+}
+
+GList *
+panel_g_list_swap_prev (GList *list,
+ GList *dl)
+{
+ GList *t;
+
+ if (!dl)
+ return list;
+
+ if (!dl->prev)
+ return list;
+
+ if (dl->next)
+ dl->next->prev = dl->prev;
+ t = dl->next;
+ dl->next = dl->prev;
+ dl->prev->next = t;
+ if (dl->prev->prev)
+ dl->prev->prev->next = dl;
+ t = dl->prev->prev;
+ dl->prev->prev = dl;
+ dl->prev = t;
+
+ if (list == dl->next)
+ return dl;
+
+ return list;
+}
+
+/*maybe this should be a glib function?
+ it resorts a single item in the list*/
+GList *
+panel_g_list_resort_item (GList *list,
+ gpointer data,
+ GCompareFunc func)
+{
+ GList *dl;
+
+ g_return_val_if_fail (func != NULL, list);
+
+ if (!list)
+ return NULL;
+
+ dl = g_list_find (list, data);
+
+ if (dl != NULL)
+ return list;
+
+ while (dl->next &&
+ (*func)(dl->data, dl->next->data) > 0)
+ list = panel_g_list_swap_next (list, dl);
+ while (dl->prev &&
+ (*func) (dl->data, dl->prev->data) < 0)
+ list = panel_g_list_swap_prev (list, dl);
+
+ return list;
+}
+
+GSList *
+panel_g_slist_make_unique (GSList *list,
+ GCompareFunc compare,
+ gboolean free_data)
+{
+ GSList *sorted, *l;
+
+ g_return_val_if_fail (compare != NULL, list);
+
+ if (!list)
+ return NULL;
+
+ sorted = g_slist_copy (list);
+ sorted = g_slist_sort (sorted, compare);
+
+ for (l = sorted; l; l = l->next) {
+ GSList *next;
+
+ next = l->next;
+ if (l->data && next && next->data)
+ if (!compare (l->data, next->data)) {
+ list = g_slist_remove (list, l->data);
+ if (free_data)
+ g_free (l->data);
+ }
+ }
+
+ g_slist_free (sorted);
+
+ return list;
+}
diff --git a/mate-panel/libpanel-util/panel-list.h b/mate-panel/libpanel-util/panel-list.h
new file mode 100644
index 00000000..c3e48f53
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-list.h
@@ -0,0 +1,56 @@
+/*
+ * panel-list.h: GList & GSList extensions
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_LIST_H
+#define PANEL_LIST_H
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GList *panel_g_list_insert_before (GList *list,
+ GList *sibling,
+ GList *link);
+GList *panel_g_list_insert_after (GList *list,
+ GList *sibling,
+ GList *link);
+GList *panel_g_list_swap_next (GList *list,
+ GList *dl);
+GList *panel_g_list_swap_prev (GList *list,
+ GList *dl);
+GList *panel_g_list_resort_item (GList *list,
+ gpointer data,
+ GCompareFunc func);
+
+GSList *panel_g_slist_make_unique (GSList *list,
+ GCompareFunc compare,
+ gboolean free_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_LIST_H */
diff --git a/mate-panel/libpanel-util/panel-session-manager.c b/mate-panel/libpanel-util/panel-session-manager.c
new file mode 100644
index 00000000..63152e1a
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-session-manager.c
@@ -0,0 +1,192 @@
+/*
+ * panel-session.c:
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <dbus/dbus-glib.h>
+
+#include "panel-cleanup.h"
+#include "panel-dbus-service.h"
+
+#include "panel-session-manager.h"
+
+static GObject *panel_session_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+
+G_DEFINE_TYPE (PanelSessionManager, panel_session_manager, PANEL_TYPE_DBUS_SERVICE);
+
+static void
+panel_session_manager_class_init (PanelSessionManagerClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = panel_session_manager_constructor;
+}
+
+static void
+panel_session_manager_init (PanelSessionManager *manager)
+{
+}
+
+static GObject *
+panel_session_manager_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ GError *error;
+
+ obj = G_OBJECT_CLASS (panel_session_manager_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties);
+
+
+ panel_dbus_service_define_service (PANEL_DBUS_SERVICE (obj),
+ "org.mate.SessionManager",
+ "/org/mate/SessionManager",
+ "org.mate.SessionManager");
+
+ error = NULL;
+ if (!panel_dbus_service_ensure_connection (PANEL_DBUS_SERVICE (obj),
+ &error)) {
+ g_message ("Could not connect to session manager: %s",
+ error->message);
+ g_error_free (error);
+ }
+
+ return obj;
+}
+
+void
+panel_session_manager_request_logout (PanelSessionManager *manager,
+ PanelSessionManagerLogoutType mode)
+{
+ GError *error;
+ DBusGProxy *proxy;
+
+ g_return_if_fail (PANEL_IS_SESSION_MANAGER (manager));
+
+ error = NULL;
+
+ if (!panel_dbus_service_ensure_connection (PANEL_DBUS_SERVICE (manager),
+ &error)) {
+ g_warning ("Could not connect to session manager: %s",
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ proxy = panel_dbus_service_get_proxy (PANEL_DBUS_SERVICE (manager));
+
+ if (!dbus_g_proxy_call (proxy, "Logout", &error,
+ G_TYPE_UINT, mode, G_TYPE_INVALID,
+ G_TYPE_INVALID) &&
+ error != NULL) {
+ g_warning ("Could not ask session manager to log out: %s",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+void
+panel_session_manager_request_shutdown (PanelSessionManager *manager)
+{
+ GError *error;
+ DBusGProxy *proxy;
+
+ g_return_if_fail (PANEL_IS_SESSION_MANAGER (manager));
+
+ error = NULL;
+
+ if (!panel_dbus_service_ensure_connection (PANEL_DBUS_SERVICE (manager),
+ &error)) {
+ g_warning ("Could not connect to session manager: %s",
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ proxy = panel_dbus_service_get_proxy (PANEL_DBUS_SERVICE (manager));
+
+ if (!dbus_g_proxy_call (proxy, "Shutdown", &error,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID) &&
+ error != NULL) {
+ g_warning ("Could not ask session manager to shut down: %s",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+gboolean
+panel_session_manager_is_shutdown_available (PanelSessionManager *manager)
+{
+ GError *error;
+ DBusGProxy *proxy;
+ gboolean is_shutdown_available;
+
+ g_return_val_if_fail (PANEL_IS_SESSION_MANAGER (manager), FALSE);
+
+ error = NULL;
+
+ if (!panel_dbus_service_ensure_connection (PANEL_DBUS_SERVICE (manager),
+ &error)) {
+ g_warning ("Could not connect to session manager: %s",
+ error->message);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ proxy = panel_dbus_service_get_proxy (PANEL_DBUS_SERVICE (manager));
+
+ if (!dbus_g_proxy_call (proxy, "CanShutdown", &error,
+ G_TYPE_INVALID, G_TYPE_BOOLEAN,
+ &is_shutdown_available, G_TYPE_INVALID) &&
+ error != NULL) {
+ g_warning ("Could not ask session manager if shut down is available: %s",
+ error->message);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ return is_shutdown_available;
+}
+
+PanelSessionManager *
+panel_session_manager_get (void)
+{
+ static PanelSessionManager *manager = NULL;
+
+ if (manager == NULL) {
+ manager = g_object_new (PANEL_TYPE_SESSION_MANAGER, NULL);
+ panel_cleanup_register (panel_cleanup_unref_and_nullify,
+ &manager);
+ }
+
+ return manager;
+}
diff --git a/mate-panel/libpanel-util/panel-session-manager.h b/mate-panel/libpanel-util/panel-session-manager.h
new file mode 100644
index 00000000..d48ce5d3
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-session-manager.h
@@ -0,0 +1,75 @@
+/*
+ * panel-session.h:
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_SESSION_MANAGER_H
+#define PANEL_SESSION_MANAGER_H
+
+#include <glib-object.h>
+
+#include "panel-dbus-service.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_SESSION_MANAGER (panel_session_manager_get_type ())
+#define PANEL_SESSION_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_SESSION_MANAGER, PanelSessionManager))
+#define PANEL_SESSION_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_SESSION_MANAGER, PanelSessionManagerClass))
+#define PANEL_IS_SESSION_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_SESSION_MANAGER))
+#define PANEL_IS_SESSION_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_SESSION_MANAGER))
+#define PANEL_SESSION_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_SESSION_MANAGER, PanelSessionManagerClass))
+
+typedef struct _PanelSessionManager PanelSessionManager;
+typedef struct _PanelSessionManagerClass PanelSessionManagerClass;
+
+struct _PanelSessionManager {
+ PanelDBusService parent;
+};
+
+struct _PanelSessionManagerClass {
+ PanelDBusServiceClass parent_class;
+};
+
+GType panel_session_manager_get_type (void);
+
+/* Keep in sync with the values defined in mate-session/session.h */
+typedef enum {
+ PANEL_SESSION_MANAGER_LOGOUT_MODE_NORMAL = 0,
+ PANEL_SESSION_MANAGER_LOGOUT_MODE_NO_CONFIRMATION,
+ PANEL_SESSION_MANAGER_LOGOUT_MODE_FORCE
+} PanelSessionManagerLogoutType;
+
+PanelSessionManager *panel_session_manager_get (void);
+
+void panel_session_manager_request_logout (PanelSessionManager *session,
+ PanelSessionManagerLogoutType mode);
+void panel_session_manager_request_shutdown (PanelSessionManager *session);
+
+gboolean panel_session_manager_is_shutdown_available (PanelSessionManager *session);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_SESSION_MANAGER_H */
diff --git a/mate-panel/libpanel-util/panel-show.c b/mate-panel/libpanel-util/panel-show.c
new file mode 100644
index 00000000..02ea2e63
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-show.c
@@ -0,0 +1,283 @@
+/*
+ * panel-show.c: a helper around gtk_show_uri
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+#include <gtk/gtk.h>
+
+#include "panel-error.h"
+#include "panel-glib.h"
+#include "panel-launch.h"
+
+#include "panel-show.h"
+
+static void
+_panel_show_error_dialog (const gchar *uri,
+ GdkScreen *screen,
+ const gchar *message)
+{
+ char *primary;
+
+ primary = g_markup_printf_escaped (_("Could not open location '%s'"),
+ uri);
+ panel_error_dialog (NULL, screen, "cannot_show_url", TRUE,
+ primary, message);
+ g_free (primary);
+}
+
+typedef struct {
+ GMountOperation *mount_op;
+ GdkScreen *screen;
+} PanelShowMountOperationHandle;
+
+static void
+_panel_show_mount_async_callback (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GFile *file;
+ PanelShowMountOperationHandle *handle = user_data;
+
+ file = G_FILE (source_object);
+
+ error = NULL;
+ if (g_file_mount_enclosing_volume_finish (file, result, &error)) {
+ char *uri = g_file_get_uri (file);
+
+ panel_show_uri (handle->screen, uri,
+ gtk_get_current_event_time (), NULL);
+ g_free (uri);
+ } else {
+ if (!g_error_matches (error, G_IO_ERROR,
+ G_IO_ERROR_PERMISSION_DENIED) &&
+ !g_error_matches (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED_HANDLED)) {
+ char *uri;
+
+ uri = g_file_get_uri (file);
+ _panel_show_error_dialog (uri, handle->screen,
+ error->message);
+ g_free (uri);
+ }
+ g_error_free (error);
+ }
+
+ if (handle->mount_op)
+ g_object_unref (handle->mount_op);
+
+ g_slice_free (PanelShowMountOperationHandle, handle);
+}
+
+static gboolean _panel_show_handle_error(const gchar* uri, GdkScreen* screen, GError* local_error, GError** error)
+{
+ if (local_error == NULL)
+ {
+ return TRUE;
+ }
+
+ else if (g_error_matches (local_error,
+ G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (local_error);
+ return TRUE;
+ }
+
+ else if (g_error_matches (local_error,
+ G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
+ GFile *file;
+ PanelShowMountOperationHandle *handle;
+
+ handle = g_slice_new (PanelShowMountOperationHandle);
+ file = g_file_new_for_uri (uri);
+
+ /* If it's not mounted, try to mount it ourselves */
+ handle->mount_op = gtk_mount_operation_new (NULL);
+ gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (handle->mount_op),
+ screen);
+ handle->screen = screen;
+
+ g_file_mount_enclosing_volume (file, G_MOUNT_MOUNT_NONE,
+ handle->mount_op, NULL,
+ _panel_show_mount_async_callback,
+ handle);
+ g_object_unref (file);
+
+ return TRUE;
+ }
+
+ else if (error != NULL)
+ g_propagate_error (error, local_error);
+
+ else {
+ _panel_show_error_dialog (uri, screen, local_error->message);
+ g_error_free (local_error);
+ }
+
+ return FALSE;
+}
+
+static gboolean panel_show_caja_search_uri(GdkScreen* screen, const gchar* uri, guint32 timestamp, GError** error)
+{
+ char* desktopfile;
+ GDesktopAppInfo* appinfo;
+ gboolean ret;
+
+ desktopfile = panel_g_lookup_in_applications_dirs("caja-folder-handler.desktop");
+
+ if (desktopfile)
+ {
+ appinfo = g_desktop_app_info_new_from_filename(desktopfile);
+ g_free(desktopfile);
+ }
+
+ if (!appinfo)
+ {
+ _panel_show_error_dialog (uri, screen, _("No application to handle search folders is installed."));
+ return FALSE;
+ }
+
+ ret = panel_app_info_launch_uri((GAppInfo*) appinfo, uri, screen, timestamp, error);
+ g_object_unref(appinfo);
+
+ return ret;
+}
+
+gboolean panel_show_uri(GdkScreen* screen, const gchar* uri, guint32 timestamp, GError** error)
+{
+ GError* local_error = NULL;
+
+ g_return_val_if_fail(GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail(uri != NULL, FALSE);
+ g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
+
+ if (g_str_has_prefix(uri, "x-caja-search:"))
+ {
+ return panel_show_caja_search_uri(screen, uri, timestamp, error);
+ }
+
+ gtk_show_uri(screen, uri, timestamp, &local_error);
+
+ return _panel_show_handle_error(uri, screen, local_error, error);
+}
+
+gboolean
+panel_show_uri_force_mime_type (GdkScreen *screen,
+ const gchar *uri,
+ const gchar *mime_type,
+ guint32 timestamp,
+ GError **error)
+{
+ GFile *file;
+ GAppInfo *app;
+ gboolean ret;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (mime_type != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ file = g_file_new_for_uri (uri);
+ app = g_app_info_get_default_for_type (mime_type,
+ !g_file_is_native (file));
+ g_object_unref (file);
+
+ if (app == NULL) {
+ /* no application for the mime type, so let's fallback on
+ * automatic detection */
+ return panel_show_uri (screen, uri, timestamp, error);
+ }
+
+ ret = panel_app_info_launch_uri (app, uri, screen, timestamp, error);
+ g_object_unref (app);
+
+ return ret;
+}
+
+static void
+_panel_show_help_error_dialog (const gchar *doc,
+ GdkScreen *screen,
+ const gchar *message)
+{
+ char *primary;
+
+ primary = g_markup_printf_escaped (_("Could not display help document '%s'"),
+ doc);
+ panel_error_dialog (NULL, screen, "cannot_show_help", TRUE,
+ primary, message);
+ g_free (primary);
+}
+
+static gboolean
+_panel_show_help_handle_error (const gchar *doc,
+ GdkScreen *screen,
+ GError *local_error,
+ GError **error)
+{
+ if (local_error == NULL)
+ return TRUE;
+
+ else if (g_error_matches (local_error,
+ G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (local_error);
+ return TRUE;
+ }
+
+ else if (error != NULL)
+ g_propagate_error (error, local_error);
+
+ else {
+ _panel_show_help_error_dialog (doc, screen,
+ local_error->message);
+ g_error_free (local_error);
+ }
+
+ return FALSE;
+}
+
+gboolean
+panel_show_help (GdkScreen *screen,
+ const gchar *doc,
+ const gchar *link,
+ GError **error)
+{
+ GError *local_error = NULL;
+ char *uri;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (doc != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (link)
+ uri = g_strdup_printf ("ghelp:%s?%s", doc, link);
+ else
+ uri = g_strdup_printf ("ghelp:%s", doc);
+
+ gtk_show_uri (screen, uri, gtk_get_current_event_time (), &local_error);
+
+ g_free (uri);
+
+ return _panel_show_help_handle_error (doc, screen, local_error, error);
+}
diff --git a/mate-panel/libpanel-util/panel-show.h b/mate-panel/libpanel-util/panel-show.h
new file mode 100644
index 00000000..a0eac9bc
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-show.h
@@ -0,0 +1,54 @@
+/*
+ * panel-show.h: a helper around gtk_show_uri
+ *
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_SHOW_H
+#define PANEL_SHOW_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean panel_show_uri (GdkScreen *screen,
+ const gchar *uri,
+ guint32 timestamp,
+ GError **error);
+
+gboolean panel_show_uri_force_mime_type (GdkScreen *screen,
+ const gchar *uri,
+ const gchar *mime_type,
+ guint32 timestamp,
+ GError **error);
+
+gboolean panel_show_help (GdkScreen *screen,
+ const gchar *doc,
+ const gchar *link,
+ GError **error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_SHOW_H */
diff --git a/mate-panel/libpanel-util/panel-xdg.c b/mate-panel/libpanel-util/panel-xdg.c
new file mode 100644
index 00000000..5415a22e
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-xdg.c
@@ -0,0 +1,152 @@
+/*
+ * panel-xdg.c: miscellaneous XDG-related functions.
+ *
+ * Copyright (C) 2010 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "panel-xdg.h"
+
+#define DEFAULT_THEME_NAME "hicolor"
+
+/*
+ * Originally based on code from panel-util.c. This part of the code was:
+ * Copyright (C) 2006 Vincent Untz <[email protected]>
+ */
+
+char *
+panel_xdg_icon_remove_extension (const char *icon)
+{
+ char *icon_no_extension;
+ char *p;
+
+ icon_no_extension = g_strdup (icon);
+ p = strrchr (icon_no_extension, '.');
+ if (p &&
+ (strcmp (p, ".png") == 0 ||
+ strcmp (p, ".xpm") == 0 ||
+ strcmp (p, ".svg") == 0)) {
+ *p = 0;
+ }
+
+ return icon_no_extension;
+}
+
+/*
+ * End of code coming from panel-util.c
+ */
+
+char *
+panel_xdg_icon_name_from_icon_path (const char *path,
+ GdkScreen *screen)
+{
+ GtkIconTheme *theme;
+ GtkSettings *settings;
+ char *theme_name;
+ char *icon;
+ char **paths;
+ int n_paths;
+ int i;
+ GFile *file;
+
+ /* we look if the icon comes from the current icon theme */
+ if (!screen)
+ screen = gdk_screen_get_default ();
+
+ settings = gtk_settings_get_for_screen (screen);
+ g_object_get (settings,
+ "gtk-icon-theme-name", &theme_name,
+ NULL);
+
+ theme = gtk_icon_theme_get_for_screen (screen);
+ gtk_icon_theme_get_search_path (theme, &paths, &n_paths);
+
+ file = g_file_new_for_path (path);
+ icon = NULL;
+
+ for (i = 0; i < n_paths; i++) {
+ GFile *parent;
+ char *basename;
+
+ parent = g_file_new_for_path (paths[i]);
+
+ if (!g_file_has_prefix (file, parent)) {
+ g_object_unref (parent);
+ continue;
+ }
+
+ basename = g_file_get_basename (parent);
+
+ if (g_strcmp0 (basename, "pixmaps") == 0) {
+ char *relative_path;
+
+ relative_path = g_file_get_relative_path (parent, file);
+
+ /* if the icon is in a subdir of pixmaps, then it's not
+ * a real icon name */
+ if (!strchr (relative_path, G_DIR_SEPARATOR))
+ icon = panel_xdg_icon_remove_extension (relative_path);
+
+ g_free (relative_path);
+ } else {
+ /* real icon theme; but is it the current one? */
+ GFile *theme_dir;
+ gboolean current;
+
+ theme_dir = g_file_get_child (parent, theme_name);
+
+ current = FALSE;
+ if (g_file_has_prefix (file, theme_dir)) {
+ /* it's the current one */
+ current = TRUE;
+ } else {
+ /* it's the default one */
+ g_object_unref (theme_dir);
+ theme_dir = g_file_get_child (parent, DEFAULT_THEME_NAME);
+ current = g_file_has_prefix (file, theme_dir);
+ }
+
+ g_object_unref (theme_dir);
+
+ if (current) {
+ char *buffer;
+
+ buffer = g_file_get_basename (file);
+ icon = panel_xdg_icon_remove_extension (buffer);
+ g_free (buffer);
+ }
+ }
+
+ g_free (basename);
+ g_object_unref (parent);
+
+ break;
+ }
+
+ g_object_unref (file);
+ g_free (theme_name);
+
+ return icon;
+}
diff --git a/mate-panel/libpanel-util/panel-xdg.h b/mate-panel/libpanel-util/panel-xdg.h
new file mode 100644
index 00000000..8fa71b2e
--- /dev/null
+++ b/mate-panel/libpanel-util/panel-xdg.h
@@ -0,0 +1,43 @@
+/*
+ * panel-xdg.h: miscellaneous XDG-related functions.
+ *
+ * Copyright (C) 2010 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 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_XDG_H
+#define PANEL_XDG_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *panel_xdg_icon_remove_extension (const char *icon);
+
+char *panel_xdg_icon_name_from_icon_path (const char *path,
+ GdkScreen *screen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_XDG_H */
diff --git a/mate-panel/main.c b/mate-panel/main.c
new file mode 100644
index 00000000..7721fade
--- /dev/null
+++ b/mate-panel/main.c
@@ -0,0 +1,153 @@
+/* Mate panel: Initialization routines
+ * (C) 1997,1998,1999,2000 the Free Software Foundation
+ * (C) 2000 Eazel, Inc.
+ *
+ * Authors: Federico Mena
+ * Miguel de Icaza
+ * George Lebl
+ */
+
+#include <config.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include <glib/gi18n.h>
+
+#include <libegg/eggdesktopfile.h>
+#include <libegg/eggsmclient.h>
+
+#include <libpanel-util/panel-cleanup.h>
+#include <libpanel-util/panel-glib.h>
+
+#include "panel-mateconf.h"
+#include "panel-profile.h"
+#include "panel-config-global.h"
+#include "panel-shell.h"
+#include "panel-multiscreen.h"
+#include "panel-session.h"
+#include "panel-stock-icons.h"
+#include "panel-action-protocol.h"
+#include "panel-lockdown.h"
+#include "panel-icon-names.h"
+#include "panel-reset.h"
+#include "xstuff.h"
+
+#include "nothing.cP"
+
+/* globals */
+GSList *panels = NULL;
+GSList *panel_list = NULL;
+
+static char* deprecated_profile;
+static gboolean replace = FALSE;
+static gboolean reset = FALSE;
+
+static const GOptionEntry options[] = {
+ { "replace", 0, 0, G_OPTION_ARG_NONE, &replace, N_("Replace a currently running panel"), NULL },
+ /* keep this for compatibilty with old MATE < 2.10 */
+ { "profile", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &deprecated_profile, NULL, NULL },
+ /* this feature was request in #mate irc channel */
+ { "reset", 0, 0, G_OPTION_ARG_NONE, &reset, N_("Reset the panel configuration to default"), NULL },
+ { NULL }
+};
+
+int
+main (int argc, char **argv)
+{
+ char *desktopfile;
+ GOptionContext *context;
+ GError *error;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ /* We will register explicitly when we're ready -- see panel-session.c */
+ egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_DISABLED);
+
+ g_set_prgname ("mate-panel");
+
+ desktopfile = panel_g_lookup_in_applications_dirs ("mate-panel.desktop");
+ if (desktopfile) {
+ egg_set_desktop_file (desktopfile);
+ g_free (desktopfile);
+ }
+
+ context = g_option_context_new ("");
+ g_option_context_add_group (context,
+ egg_sm_client_get_option_group ());
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+ g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ error = NULL;
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ g_option_context_free (context);
+
+ return 1;
+ }
+
+ g_option_context_free (context);
+
+ /* reset the configuration and exit. */
+ if (reset == TRUE)
+ {
+ panel_reset();
+ return 0;
+ }
+
+
+ if (!egg_get_desktop_file ()) {
+ g_set_application_name (_("Panel"));
+ gtk_window_set_default_icon_name (PANEL_ICON_PANEL);
+ }
+
+ if (!panel_shell_register (replace)) {
+ panel_cleanup_do ();
+ return -1;
+ }
+
+ panel_action_protocol_init ();
+ panel_multiscreen_init ();
+ panel_init_stock_icons_and_items ();
+
+ mateconf_client_add_dir (panel_mateconf_get_client (),
+ "/desktop/mate/interface",
+ MATECONF_CLIENT_PRELOAD_NONE,
+ NULL);
+
+ panel_global_config_load ();
+ panel_lockdown_init ();
+ panel_profile_load ();
+
+ /*add forbidden lists to ALL panels*/
+ g_slist_foreach (panels,
+ (GFunc)panel_widget_add_forbidden,
+ NULL);
+
+ xstuff_init ();
+
+ /* Flush to make sure our struts are seen by everyone starting
+ * immediate after (eg, the caja desktop). */
+ gdk_flush ();
+
+ /* Do this at the end, to be sure that we're really ready when
+ * connecting to the session manager */
+ panel_session_init ();
+
+ gtk_main ();
+
+ panel_lockdown_finalize ();
+
+ mateconf_client_remove_dir (panel_mateconf_get_client (),
+ "/desktop/mate/interface",
+ NULL);
+
+ panel_cleanup_do ();
+
+ return 0;
+}
diff --git a/mate-panel/mate-desktop-item-edit.c b/mate-panel/mate-desktop-item-edit.c
new file mode 100644
index 00000000..f94b9254
--- /dev/null
+++ b/mate-panel/mate-desktop-item-edit.c
@@ -0,0 +1,225 @@
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-keyfile.h>
+
+#include "panel-ditem-editor.h"
+#include "panel-icon-names.h"
+#include "panel-util.h"
+
+/* FIXME Symbols needed by panel-util.c - sucky */
+#include "applet.h"
+GSList *mate_panel_applet_list_applets (void) { return NULL; }
+#include "panel-mateconf.h"
+MateConfClient *panel_mateconf_get_client (void) { return NULL; }
+#include "panel-config-global.h"
+gboolean panel_global_config_get_tooltips_enabled (void) { return FALSE; }
+#include "panel-lockdown.h"
+gboolean panel_lockdown_get_disable_lock_screen (void) { return FALSE; }
+
+static int dialogs = 0;
+static gboolean create_new = FALSE;
+static char **desktops = NULL;
+
+static GOptionEntry options[] = {
+ { "create-new", 0, 0, G_OPTION_ARG_NONE, &create_new, N_("Create new file in the given directory"), NULL },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &desktops, NULL, N_("[FILE...]") },
+ { NULL }
+};
+
+static void
+dialog_destroyed (GtkWidget *dialog, gpointer data)
+{
+ dialogs --;
+
+ if (dialogs <= 0)
+ gtk_main_quit ();
+}
+
+static void
+validate_for_filename (char *file)
+{
+ char *ptr;
+
+ g_return_if_fail (file != NULL);
+
+ ptr = file;
+ while (*ptr != '\0') {
+ if (*ptr == '/')
+ *ptr = '_';
+ ptr++;
+ }
+}
+
+static char *
+find_uri_on_save (PanelDItemEditor *dialog,
+ gpointer data)
+{
+ GKeyFile *keyfile;
+ char *name;
+ char *filename;
+ char *uri;
+ char *dir;
+
+ keyfile = panel_ditem_editor_get_key_file (dialog);
+ name = panel_key_file_get_string (keyfile, "Name");
+
+ validate_for_filename (name);
+ filename = g_filename_from_utf8 (name, -1, NULL, NULL, NULL);
+ g_free (name);
+
+ if (filename == NULL)
+ filename = g_strdup ("foo");
+
+ dir = g_object_get_data (G_OBJECT (dialog), "dir");
+ uri = panel_make_unique_desktop_path_from_name (dir, filename);
+
+ g_free (filename);
+
+ return uri;
+}
+
+static void
+error_reported (GtkWidget *dialog,
+ const char *primary,
+ const char *secondary,
+ gpointer data)
+{
+ panel_error_dialog (GTK_WINDOW (dialog), NULL,
+ "error_editing_launcher", TRUE,
+ primary, secondary);
+}
+
+int
+main (int argc, char * argv[])
+{
+ GError *error = NULL;
+ int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ if (!gtk_init_with_args (&argc, &argv,
+ _("- Edit .desktop files"),
+ options,
+ GETTEXT_PACKAGE,
+ &error)) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ gtk_window_set_default_icon_name (PANEL_ICON_LAUNCHER);
+
+ if (desktops == NULL ||
+ desktops[0] == NULL) {
+ g_printerr ("mate-desktop-item-edit: no file to edit\n");
+ return 0;
+ }
+
+ for (i = 0; desktops[i] != NULL; i++) {
+ GFile *file;
+ GFileInfo *info;
+ GFileType type;
+ char *uri;
+ char *path;
+ GtkWidget *dlg = NULL;
+
+ file = g_file_new_for_commandline_arg (desktops[i]);
+ uri = g_file_get_uri (file);
+ path = g_file_get_path (file);
+ info = g_file_query_info (file, "standard::type",
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ g_object_unref (file);
+
+ if (info) {
+ type = g_file_info_get_file_type (info);
+
+ if (type == G_FILE_TYPE_DIRECTORY && create_new) {
+
+ dlg = panel_ditem_editor_new (NULL, NULL, NULL,
+ _("Create Launcher"));
+ g_object_set_data_full (G_OBJECT (dlg), "dir",
+ g_strdup (path),
+ (GDestroyNotify)g_free);
+
+ panel_ditem_register_save_uri_func (PANEL_DITEM_EDITOR (dlg),
+ find_uri_on_save,
+ NULL);
+
+ } else if (type == G_FILE_TYPE_DIRECTORY) {
+ /* Rerun this iteration with the .directory
+ * file
+ * Note: No need to free, for one we can't free
+ * an individual member of desktops and
+ * secondly we will soon exit */
+ desktops[i] = g_build_path ("/", uri,
+ ".directory", NULL);
+ i--;
+ } else if (type == G_FILE_TYPE_REGULAR
+ && g_str_has_suffix (desktops [i],
+ ".directory")
+ && !create_new) {
+ dlg = panel_ditem_editor_new_directory (NULL,
+ NULL,
+ uri,
+ _("Directory Properties"));
+ } else if (type == G_FILE_TYPE_REGULAR
+ && g_str_has_suffix (desktops [i],
+ ".desktop")
+ && !create_new) {
+ dlg = panel_ditem_editor_new (NULL, NULL, uri,
+ _("Launcher Properties"));
+ } else if (type == G_FILE_TYPE_REGULAR
+ && create_new) {
+ g_printerr ("mate-desktop-item-edit: %s "
+ "already exists\n", uri);
+ } else {
+ g_printerr ("mate-desktop-item-edit: %s "
+ "does not look like a desktop "
+ "item\n", uri);
+ }
+
+ g_object_unref (info);
+
+ } else if (g_str_has_suffix (desktops [i], ".directory")) {
+ /* a non-existant file. Well we can still edit that
+ * sort of. We will just create it new */
+ dlg = panel_ditem_editor_new_directory (NULL, NULL, uri,
+ _("Directory Properties"));
+
+ } else if (g_str_has_suffix (desktops [i], ".desktop")) {
+ /* a non-existant file. Well we can still edit that
+ * sort of. We will just create it new */
+ dlg = panel_ditem_editor_new (NULL, NULL, uri,
+ _("Create Launcher"));
+
+ } else {
+ g_printerr ("mate-desktop-item-edit: %s does not "
+ "have a .desktop or .directory "
+ "suffix\n", uri);
+ }
+
+ if (dlg != NULL) {
+ dialogs ++;
+ g_signal_connect (G_OBJECT (dlg), "destroy",
+ G_CALLBACK (dialog_destroyed), NULL);
+ g_signal_connect (G_OBJECT (dlg), "error_reported",
+ G_CALLBACK (error_reported), NULL);
+ gtk_widget_show (dlg);
+ }
+
+ g_free (uri);
+ g_free (path);
+ }
+
+ if (dialogs > 0)
+ gtk_main ();
+
+ return 0;
+}
diff --git a/mate-panel/mate-panel-add.in b/mate-panel/mate-panel-add.in
new file mode 100644
index 00000000..b50669cd
--- /dev/null
+++ b/mate-panel/mate-panel-add.in
@@ -0,0 +1,325 @@
+#!@PYTHON@
+# vim: set ts=4 sw=4 et:
+
+#
+# Copyright (C) 2009 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import optparse
+import os
+import shutil
+import sys
+import urllib
+import ConfigParser
+
+try:
+ import matecomponent
+ has_matecomponent = True
+except ImportError:
+ has_matecomponent = False
+
+import mateconf
+
+PANEL_SCHEMAS_OBJECTS_DIR='/schemas/apps/panel/objects'
+
+PANEL_TOPLEVELS_DIR='/apps/panel/toplevels'
+PANEL_TOPLEVELS_KEY='/apps/panel/general/toplevel_id_list'
+MATE_PANEL_APPLETS_DIR='/apps/panel/applets'
+MATE_PANEL_APPLETS_KEY='/apps/panel/general/applet_id_list'
+PANEL_OBJECTS_DIR='/apps/panel/objects'
+PANEL_OBJECTS_KEY='/apps/panel/general/object_id_list'
+
+PANEL_LAUNCHER_USER_DIR=os.path.join(os.path.expanduser('~'), '.mate2', 'panel2.d', 'default', 'launchers')
+
+PANEL_TYPE_NONE = 0
+PANEL_TYPE_APPLET = 1
+PANEL_TYPE_LAUNCHER = 2
+
+MATE_PANEL_APPLETS_EXTENSION='.mate-panel-applet'
+MATE_PANEL_APPLETS_PATH='@MATE_PANEL_APPLETS_DIR@'
+MATE_PANEL_APPLET_FACTORY_GROUP='Applet Factory'
+
+class PanelAddException(Exception):
+ pass
+
+class PanelAdder:
+
+ def __init__(self, toplevel, position, right_stick, applet_iid = None, launcher_path = None, copy_launcher = False):
+ self.toplevel = toplevel
+ self.position = position
+ self.right_stick = right_stick
+
+ # FIXME workaround: -1 and right_click don't play well together. Just
+ # use an arbitrary value so that the applet ends up at the left of all
+ # right-click applets (it'd be surprising to have a config with more
+ # than 10 applets...)
+ if self.right_stick and self.position < 0:
+ self.position = 10
+
+ self.type = PANEL_TYPE_NONE
+ self.applet_iid = None
+ self.launcher_path = None
+ self.copy_launcher = False
+
+ self.client = None
+
+ if applet_iid:
+ self._set_applet_iid(applet_iid)
+ self.type = PANEL_TYPE_APPLET
+ elif launcher_path:
+ self._set_launcher_path(launcher_path)
+ self.copy_launcher = copy_launcher
+ self.type = PANEL_TYPE_LAUNCHER
+
+ def _panel_get_subdirs(self, key):
+ return [ os.path.basename(s) for s in self.client.all_dirs(key) ]
+
+ def _panel_get_list(self, key):
+ list_v = self.client.get(key)
+
+ if not list_v:
+ return []
+
+ if list_v.type != mateconf.VALUE_LIST or list_v.get_list_type() != mateconf.VALUE_STRING:
+ return []
+
+ return [ v.get_string() for v in list_v.get_list() ]
+
+ def _toplevel_id_ensure(self):
+ toplevel_subdirs = self._panel_get_subdirs(PANEL_TOPLEVELS_DIR)
+ toplevel_id_list = self._panel_get_list(PANEL_TOPLEVELS_KEY)
+
+ if self.toplevel:
+ if not self.toplevel in toplevel_subdirs or not self.toplevel in toplevel_id_list:
+ raise PanelAddException('%s is not an existing panel identifier' % self.toplevel)
+ else:
+ for toplevel in toplevel_id_list:
+ if toplevel in toplevel_subdirs:
+ self.toplevel = toplevel
+ return
+
+ raise PanelAddException('Cannot find a panel identifier')
+
+ def _get_applet_list(self):
+ dirs = os.getenv('MATE_PANEL_APPLETS_DIR')
+ if not dirs:
+ dirs = MATE_PANEL_APPLETS_PATH
+
+ retval = []
+ dups = []
+ for path in dirs.split(":"):
+ if not os.path.isdir(path):
+ continue
+
+ if path in dups:
+ continue
+
+ dups.append(path)
+
+ for f in os.listdir(path):
+ if not f.endswith(MATE_PANEL_APPLETS_EXTENSION):
+ continue
+
+ config = ConfigParser.RawConfigParser()
+ try:
+ config.read(os.path.join(path, f))
+ except ConfigParser.ParsingError:
+ continue
+
+ fid = config.get(MATE_PANEL_APPLET_FACTORY_GROUP, 'Id')
+ retval.extend(["%s::%s" % (fid, s) for s in config.sections() if s != MATE_PANEL_APPLET_FACTORY_GROUP])
+
+ return retval
+
+ def _set_applet_iid(self, applet_iid):
+ if not applet_iid:
+ raise PanelAddException('No applet specified')
+
+ applets = self._get_applet_list ()
+ if not applet_iid in applets:
+ if has_matecomponent:
+ applets = matecomponent.activation.query ("has_all (repo_ids, ['IDL:MateComponent/Control:1.0', 'IDL:MATE/Vertigo/MatePanelAppletShell:1.0'])")
+ if not applet_iid in [ a.iid for a in applets ]:
+ raise PanelAddException('%s is not a valid applet' % applet_iid)
+ else:
+ raise PanelAddException('%s is not a valid applet' % applet_iid)
+
+ self.applet_iid = applet_iid
+
+ def _set_launcher_path(self, launcher_path):
+ if not launcher_path:
+ raise PanelAddException('No launcher specified')
+
+ if not launcher_path.endswith('.desktop'):
+ raise PanelAddException('%s does not have a .desktop extension' % launcher_path)
+
+ if not os.path.exists(launcher_path):
+ raise PanelAddException('%s is not an existing launcher' % launcher_path)
+
+ self.launcher_path = launcher_path
+
+ def _object_id_find_unused(self):
+ if self.type == PANEL_TYPE_APPLET:
+ subdirs = self._panel_get_subdirs(MATE_PANEL_APPLETS_DIR)
+ id_list = self._panel_get_list(MATE_PANEL_APPLETS_KEY)
+ prefix = 'applet'
+ else:
+ subdirs = self._panel_get_subdirs(PANEL_OBJECTS_DIR)
+ id_list = self._panel_get_list(PANEL_OBJECTS_KEY)
+ prefix = 'object'
+
+ i = 0
+ while i < 1000:
+ id = '%s_%d' % (prefix, i)
+ if id not in subdirs and id not in id_list:
+ return id
+ i += 1
+
+ return None
+
+ def _launcher_find_unused(self):
+ basename = os.path.basename(self.launcher_path)
+ if not os.path.exists(os.path.join(PANEL_LAUNCHER_USER_DIR, basename)):
+ return basename
+
+ dot = basename.rfind('.')
+ prefix = basename[:dot]
+ extension = basename[dot:]
+
+ i = 0
+ while i < 1000:
+ basename = '%s-%d%s' % (prefix, i, extension)
+ if not os.path.exists(os.path.join(PANEL_LAUNCHER_USER_DIR, basename)):
+ return basename
+ i += 1
+
+ raise PanelAddException('Copying %s would overwrite existing launchers' % self.launcher_path)
+
+ def _associate_schemas(self, engine, schema_dir, dest_dir):
+ entries = self.client.all_entries(schema_dir)
+ for entry in entries:
+ dest_key = os.path.basename(entry.key)
+ engine.associate_schema(os.path.join(dest_dir, dest_key), entry.key)
+
+ subdirs = self.client.all_dirs(schema_dir)
+ for subdir in subdirs:
+ dest_subdir = os.path.join(subdir)
+ self._associate_schemas(engine, subdir, os.path.join(dest_dir, dest_subdir))
+
+ def run(self):
+ self.client = mateconf.client_get_default ()
+ self._toplevel_id_ensure()
+
+ id = self._object_id_find_unused()
+ if not id:
+ raise PanelAddException('No identifier available for the new object')
+
+ if self.type == PANEL_TYPE_APPLET:
+ dir = os.path.join(MATE_PANEL_APPLETS_DIR, id)
+
+ elif self.type == PANEL_TYPE_LAUNCHER:
+ dir = os.path.join(PANEL_OBJECTS_DIR, id)
+
+ if self.copy_launcher:
+ try:
+ if not os.path.exists(PANEL_LAUNCHER_USER_DIR):
+ os.makedirs(PANEL_LAUNCHER_USER_DIR)
+ unused = self._launcher_find_unused()
+ dest = os.path.join (PANEL_LAUNCHER_USER_DIR, unused)
+ shutil.copyfile(self.launcher_path, dest)
+
+ launcher_location = unused
+ except (OSError, IOError), e:
+ raise PanelAddException('Cannot copy launcher: %s' % e)
+ else:
+ launcher_location = 'file://' + urllib.pathname2url(os.path.realpath(self.launcher_path))
+
+ else:
+ raise PanelAddException('Unknown panel object type %d' % self.type)
+
+ engine = mateconf.engine_get_default()
+ self._associate_schemas(engine, PANEL_SCHEMAS_OBJECTS_DIR, dir)
+
+ self.client.set_string(os.path.join(dir, 'toplevel_id'), self.toplevel)
+ self.client.set_int(os.path.join(dir, 'position'), self.position)
+ self.client.set_bool(os.path.join(dir, 'panel_right_stick'), self.right_stick)
+
+ if self.type == PANEL_TYPE_APPLET:
+ self.client.set_string(os.path.join(dir, 'object_type'), 'matecomponent-applet')
+ self.client.set_string(os.path.join(dir, 'applet_iid'), self.applet_iid)
+ id_list = self._panel_get_list(MATE_PANEL_APPLETS_KEY)
+ id_list.append(id)
+ self.client.set_list(MATE_PANEL_APPLETS_KEY, mateconf.VALUE_STRING, id_list)
+
+ elif self.type == PANEL_TYPE_LAUNCHER:
+ self.client.set_string(os.path.join(dir, 'object_type'), 'launcher-object')
+ self.client.set_string(os.path.join(dir, 'launcher_location'), launcher_location)
+ id_list = self._panel_get_list(PANEL_OBJECTS_KEY)
+ id_list.append(id)
+ self.client.set_list(PANEL_OBJECTS_KEY, mateconf.VALUE_STRING, id_list)
+
+ else:
+ raise PanelAddException('Unknown panel object type %d' % self.type)
+
+def main(args):
+ parser = optparse.OptionParser()
+
+ parser.add_option('--applet', dest='applet',
+ help='Applet to add')
+ parser.add_option('--copy-launcher', dest='copy_launcher',
+ action='store_true', default=False,
+ help='Copy the launcher to the user directory')
+ parser.add_option('--launcher', dest='launcher',
+ help='Launcher to add')
+ parser.add_option('--panel', dest='toplevel',
+ help='Identifier of the panel where to add the applet')
+ parser.add_option('--position', dest='position',
+ help='Position on the panel where to add the applet')
+ parser.add_option('--right-stick', dest='right_stick',
+ action='store_true', default=False,
+ help='Make the applet right-aligned on the panel')
+
+ (options, args) = parser.parse_args()
+
+ if not options.applet and not options.launcher:
+ print parser.format_help()
+ return 1
+
+ if options.applet and options.launcher:
+ raise PanelAddException('Cannot add an applet and a launcher at the same time')
+
+ if options.position:
+ try:
+ position = int(options.position)
+ except ValueError:
+ raise PanelAddException('%s is not an integer, required for position' % options.position)
+ else:
+ position = -1
+
+ adder = PanelAdder(options.toplevel, position, options.right_stick, options.applet, options.launcher, options.copy_launcher)
+ adder.run()
+
+if __name__ == '__main__':
+ try:
+ main(sys.argv)
+ except PanelAddException, e:
+ print >> sys.stderr, e
+ sys.exit(1)
+ except KeyboardInterrupt:
+ pass
diff --git a/mate-panel/mate-panel-applet-frame.c b/mate-panel/mate-panel-applet-frame.c
new file mode 100644
index 00000000..12f1c103
--- /dev/null
+++ b/mate-panel/mate-panel-applet-frame.c
@@ -0,0 +1,1002 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * mate-panel-applet-frame.c: panel side container for applets
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2001 - 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include <mateconf/mateconf.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include "mate-panel-applets-manager.h"
+#include "panel-profile.h"
+#include "panel.h"
+#include "applet.h"
+#include "panel-marshal.h"
+#include "panel-background.h"
+#include "panel-lockdown.h"
+#include "panel-stock-icons.h"
+#include "xstuff.h"
+#include "panel-compatibility.h"
+
+#include "mate-panel-applet-frame.h"
+
+static void mate_panel_applet_frame_activating_free (MatePanelAppletFrameActivating *frame_act);
+
+static void mate_panel_applet_frame_loading_failed (const char *iid,
+ PanelWidget *panel,
+ const char *id);
+
+static void mate_panel_applet_frame_load (const gchar *iid,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id);
+
+struct _MatePanelAppletFrameActivating {
+ gboolean locked;
+ PanelWidget *panel;
+ int position;
+ gboolean exactpos;
+ char *id;
+};
+
+/* MatePanelAppletFrame implementation */
+
+G_DEFINE_TYPE (MatePanelAppletFrame, mate_panel_applet_frame, GTK_TYPE_EVENT_BOX)
+
+#define MATE_PANEL_APPLET_FRAME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_APPLET_FRAME, MatePanelAppletFramePrivate))
+
+#define HANDLE_SIZE 10
+#define MATE_PANEL_APPLET_PREFS_KEY "/apps/panel/applets/%s/prefs"
+
+struct _MatePanelAppletFramePrivate {
+ PanelWidget *panel;
+ AppletInfo *applet_info;
+
+ PanelOrientation orientation;
+
+ gchar *iid;
+
+ GtkAllocation child_allocation;
+ GdkRectangle handle_rect;
+
+ guint has_handle : 1;
+};
+
+static void
+mate_panel_applet_frame_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ MatePanelAppletFrame *frame;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+
+ if (!frame->priv->has_handle)
+ return;
+
+ if (gtk_widget_is_drawable (widget)) {
+ GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ orientation = GTK_ORIENTATION_VERTICAL;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ orientation = GTK_ORIENTATION_HORIZONTAL;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_paint_handle (
+ gtk_widget_get_style (widget), gtk_widget_get_window (widget),
+ gtk_widget_get_state (widget),
+ GTK_SHADOW_OUT,
+ area, widget, "handlebox",
+ frame->priv->handle_rect.x,
+ frame->priv->handle_rect.y,
+ frame->priv->handle_rect.width,
+ frame->priv->handle_rect.height,
+ orientation);
+ }
+}
+
+static gboolean mate_panel_applet_frame_expose(GtkWidget* widget, GdkEventExpose* event)
+{
+ if (gtk_widget_is_drawable (widget))
+ {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->expose_event (widget, event);
+
+ mate_panel_applet_frame_paint (widget, &event->area);
+ }
+
+ return FALSE;
+}
+
+static void
+mate_panel_applet_frame_update_background_size (MatePanelAppletFrame *frame,
+ GtkAllocation *old_allocation,
+ GtkAllocation *new_allocation)
+{
+ PanelBackground *background;
+
+ if (old_allocation->x == new_allocation->x &&
+ old_allocation->y == new_allocation->y &&
+ old_allocation->width == new_allocation->width &&
+ old_allocation->height == new_allocation->height)
+ return;
+
+ background = &frame->priv->panel->background;
+
+ if (background->type == PANEL_BACK_NONE ||
+ (background->type == PANEL_BACK_COLOR && !background->has_alpha))
+ return;
+
+ mate_panel_applet_frame_change_background (frame, background->type);
+}
+
+static void
+mate_panel_applet_frame_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ MatePanelAppletFrame *frame;
+ GtkBin *bin;
+ GtkWidget *child;
+ GtkRequisition child_requisition;
+ guint border_width;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (!frame->priv->has_handle) {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->size_request (widget, requisition);
+ return;
+ }
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child)) {
+ gtk_widget_size_request (child, &child_requisition);
+
+ requisition->width = child_requisition.width;
+ requisition->height = child_requisition.height;
+ }
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ requisition->width += border_width;
+ requisition->height += border_width;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ requisition->width += HANDLE_SIZE;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ requisition->height += HANDLE_SIZE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+mate_panel_applet_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ MatePanelAppletFrame *frame;
+ GtkBin *bin;
+ GtkWidget *child;
+ GdkWindow *window;
+ GtkAllocation new_allocation;
+ GtkAllocation old_allocation;
+ GtkAllocation widget_allocation;
+
+ gtk_widget_get_allocation (widget, &widget_allocation);
+
+ old_allocation.x = widget_allocation.x;
+ old_allocation.y = widget_allocation.y;
+ old_allocation.width = widget_allocation.width;
+ old_allocation.height = widget_allocation.height;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (!frame->priv->has_handle) {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->size_allocate (widget, allocation);
+ mate_panel_applet_frame_update_background_size (frame, &old_allocation, allocation);
+ return;
+ }
+
+ window = gtk_widget_get_window (widget);
+ child = gtk_bin_get_child (bin);
+ gtk_widget_set_allocation (widget, allocation);
+
+ frame->priv->handle_rect.x = 0;
+ frame->priv->handle_rect.y = 0;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ frame->priv->handle_rect.width = HANDLE_SIZE;
+ frame->priv->handle_rect.height = allocation->height;
+
+ if (gtk_widget_get_direction (GTK_WIDGET (frame)) !=
+ GTK_TEXT_DIR_RTL) {
+ frame->priv->handle_rect.x = 0;
+ new_allocation.x = HANDLE_SIZE;
+ } else {
+ frame->priv->handle_rect.x = allocation->width - HANDLE_SIZE;
+ new_allocation.x = 0;
+ }
+
+ new_allocation.y = 0;
+ new_allocation.width = allocation->width - HANDLE_SIZE;
+ new_allocation.height = allocation->height;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ frame->priv->handle_rect.width = allocation->width;
+ frame->priv->handle_rect.height = HANDLE_SIZE;
+
+ new_allocation.x = 0;
+ new_allocation.y = HANDLE_SIZE;
+ new_allocation.width = allocation->width;
+ new_allocation.height = allocation->height - HANDLE_SIZE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ new_allocation.width = MAX (1, new_allocation.width);
+ new_allocation.height = MAX (1, new_allocation.height);
+
+ /* If the child allocation changed, that means that the frame is drawn
+ * in a new place, so we must redraw the entire widget.
+ */
+ if (gtk_widget_get_mapped (widget) &&
+ (new_allocation.x != frame->priv->child_allocation.x ||
+ new_allocation.y != frame->priv->child_allocation.y ||
+ new_allocation.width != frame->priv->child_allocation.width ||
+ new_allocation.height != frame->priv->child_allocation.height))
+ gdk_window_invalidate_rect (window, &widget_allocation, FALSE);
+
+ if (gtk_widget_get_realized (widget)) {
+ guint border_width;
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ gdk_window_move_resize (window,
+ allocation->x + border_width,
+ allocation->y + border_width,
+ MAX (allocation->width - border_width * 2, 0),
+ MAX (allocation->height - border_width * 2, 0));
+ }
+
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_allocate (child, &new_allocation);
+
+ frame->priv->child_allocation = new_allocation;
+
+ mate_panel_applet_frame_update_background_size (frame,
+ &old_allocation,
+ allocation);
+}
+
+static inline gboolean
+button_event_in_rect (GdkEventButton *event,
+ GdkRectangle *rect)
+{
+ if (event->x >= rect->x &&
+ event->x <= (rect->x + rect->width) &&
+ event->y >= rect->y &&
+ event->y <= (rect->y + rect->height))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+mate_panel_applet_frame_button_changed (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ MatePanelAppletFrame *frame;
+ gboolean handled = FALSE;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+
+ if (!frame->priv->has_handle)
+ return handled;
+
+ if (event->window != gtk_widget_get_window (widget))
+ return FALSE;
+
+ switch (event->button) {
+ case 1:
+ case 2:
+ if (button_event_in_rect (event, &frame->priv->handle_rect)) {
+ if (event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_2BUTTON_PRESS) {
+ panel_widget_applet_drag_start (
+ frame->priv->panel, GTK_WIDGET (frame),
+ PW_DRAG_OFF_CURSOR, event->time);
+ handled = TRUE;
+ } else if (event->type == GDK_BUTTON_RELEASE) {
+ panel_widget_applet_drag_end (frame->priv->panel);
+ handled = TRUE;
+ }
+ }
+ break;
+ case 3:
+ if (event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_2BUTTON_PRESS) {
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->popup_menu (frame,
+ event->button,
+ event->time);
+
+ handled = TRUE;
+ } else if (event->type == GDK_BUTTON_RELEASE)
+ handled = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return handled;
+}
+
+static void
+mate_panel_applet_frame_finalize (GObject *object)
+{
+ MatePanelAppletFrame *frame = MATE_PANEL_APPLET_FRAME (object);
+
+ mate_panel_applets_manager_factory_deactivate (frame->priv->iid);
+
+ panel_lockdown_notify_remove (G_CALLBACK (mate_panel_applet_frame_sync_menu_state),
+ frame);
+
+ g_free (frame->priv->iid);
+ frame->priv->iid = NULL;
+
+ G_OBJECT_CLASS (mate_panel_applet_frame_parent_class)->finalize (object);
+}
+
+static void
+mate_panel_applet_frame_class_init (MatePanelAppletFrameClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+
+ gobject_class->finalize = mate_panel_applet_frame_finalize;
+
+ widget_class->expose_event = mate_panel_applet_frame_expose;
+ widget_class->size_request = mate_panel_applet_frame_size_request;
+ widget_class->size_allocate = mate_panel_applet_frame_size_allocate;
+ widget_class->button_press_event = mate_panel_applet_frame_button_changed;
+ widget_class->button_release_event = mate_panel_applet_frame_button_changed;
+
+ g_type_class_add_private (klass, sizeof (MatePanelAppletFramePrivate));
+}
+
+static void
+mate_panel_applet_frame_init (MatePanelAppletFrame *frame)
+{
+ frame->priv = MATE_PANEL_APPLET_FRAME_GET_PRIVATE (frame);
+
+ frame->priv->panel = NULL;
+ frame->priv->orientation = PANEL_ORIENTATION_TOP;
+ frame->priv->applet_info = NULL;
+ frame->priv->has_handle = FALSE;
+}
+
+static void
+mate_panel_applet_frame_init_properties (MatePanelAppletFrame *frame)
+{
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->init_properties (frame);
+}
+
+void
+mate_panel_applet_frame_sync_menu_state (MatePanelAppletFrame *frame)
+{
+ PanelWidget *panel_widget;
+ gboolean locked_down;
+ gboolean locked;
+ gboolean lockable;
+ gboolean movable;
+ gboolean removable;
+
+ panel_widget = PANEL_WIDGET (gtk_widget_get_parent (GTK_WIDGET (frame)));
+
+ movable = mate_panel_applet_can_freely_move (frame->priv->applet_info);
+ removable = panel_profile_id_lists_are_writable ();
+ lockable = mate_panel_applet_lockable (frame->priv->applet_info);
+
+ locked = panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame));
+ locked_down = panel_lockdown_get_locked_down ();
+
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->sync_menu_state (frame, movable, removable, lockable, locked, locked_down);
+}
+
+void
+mate_panel_applet_frame_change_orientation (MatePanelAppletFrame *frame,
+ PanelOrientation orientation)
+{
+ if (orientation == frame->priv->orientation)
+ return;
+
+ frame->priv->orientation = orientation;
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->change_orientation (frame, orientation);
+}
+
+void
+mate_panel_applet_frame_change_size (MatePanelAppletFrame *frame,
+ guint size)
+{
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->change_size (frame, size);
+}
+
+void
+mate_panel_applet_frame_change_background (MatePanelAppletFrame *frame,
+ PanelBackgroundType type)
+{
+ GtkWidget *parent;
+
+ g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (frame));
+
+ g_return_if_fail (PANEL_IS_WIDGET (parent));
+
+ if (frame->priv->has_handle) {
+ PanelBackground *background;
+
+ background = &PANEL_WIDGET (parent)->background;
+ panel_background_change_background_on_widget (background,
+ GTK_WIDGET (frame));
+ }
+
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->change_background (frame, type);
+}
+
+void
+mate_panel_applet_frame_set_panel (MatePanelAppletFrame *frame,
+ PanelWidget *panel)
+{
+ g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+ frame->priv->panel = panel;
+}
+
+void
+_mate_panel_applet_frame_set_iid (MatePanelAppletFrame *frame,
+ const gchar *iid)
+{
+ if (frame->priv->iid)
+ g_free (frame->priv->iid);
+ frame->priv->iid = g_strdup (iid);
+}
+
+void
+_mate_panel_applet_frame_activated (MatePanelAppletFrame *frame,
+ MatePanelAppletFrameActivating *frame_act,
+ GError *error)
+{
+ AppletInfo *info;
+
+ g_assert (frame->priv->iid != NULL);
+
+ if (error != NULL) {
+ g_warning ("Failed to load applet %s:\n%s",
+ frame->priv->iid, error->message);
+ g_error_free (error);
+
+ mate_panel_applet_frame_loading_failed (frame->priv->iid,
+ frame_act->panel,
+ frame_act->id);
+ mate_panel_applet_frame_activating_free (frame_act);
+ gtk_widget_destroy (GTK_WIDGET (frame));
+
+ return;
+ }
+
+ frame->priv->panel = frame_act->panel;
+ gtk_widget_show_all (GTK_WIDGET (frame));
+
+ info = mate_panel_applet_register (GTK_WIDGET (frame), GTK_WIDGET (frame),
+ NULL, frame->priv->panel,
+ frame_act->locked, frame_act->position,
+ frame_act->exactpos, PANEL_OBJECT_APPLET,
+ frame_act->id);
+ frame->priv->applet_info = info;
+
+ panel_widget_set_applet_size_constrained (frame->priv->panel,
+ GTK_WIDGET (frame), TRUE);
+
+ mate_panel_applet_frame_sync_menu_state (frame);
+ mate_panel_applet_frame_init_properties (frame);
+
+ panel_lockdown_notify_add (G_CALLBACK (mate_panel_applet_frame_sync_menu_state),
+ frame);
+
+ mate_panel_applet_stop_loading (frame_act->id);
+ mate_panel_applet_frame_activating_free (frame_act);
+}
+
+void
+_mate_panel_applet_frame_update_flags (MatePanelAppletFrame *frame,
+ gboolean major,
+ gboolean minor,
+ gboolean has_handle)
+{
+ gboolean old_has_handle;
+
+ panel_widget_set_applet_expandable (
+ frame->priv->panel, GTK_WIDGET (frame), major, minor);
+
+ old_has_handle = frame->priv->has_handle;
+ frame->priv->has_handle = has_handle;
+
+ if (!old_has_handle && frame->priv->has_handle) {
+ /* we've added an handle, so we need to get the background for
+ * it */
+ PanelBackground *background;
+
+ background = &frame->priv->panel->background;
+ mate_panel_applet_frame_change_background (frame, background->type);
+ }
+}
+
+void
+_mate_panel_applet_frame_update_size_hints (MatePanelAppletFrame *frame,
+ gint *size_hints,
+ guint n_elements)
+{
+ if (frame->priv->has_handle) {
+ gint extra_size = HANDLE_SIZE + 1;
+ gint i;
+
+ for (i = 0; i < n_elements; i++)
+ size_hints[i] += extra_size;
+ }
+
+ /* It takes the ownership of size-hints array */
+ panel_widget_set_applet_size_hints (frame->priv->panel,
+ GTK_WIDGET (frame),
+ size_hints,
+ n_elements);
+}
+
+char *
+_mate_panel_applet_frame_get_background_string (MatePanelAppletFrame *frame,
+ PanelWidget *panel,
+ PanelBackgroundType type)
+{
+ GtkAllocation allocation;
+ int x;
+ int y;
+
+ gtk_widget_get_allocation (GTK_WIDGET (frame), &allocation);
+
+ x = allocation.x;
+ y = allocation.y;
+
+ if (frame->priv->has_handle) {
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ if (gtk_widget_get_direction (GTK_WIDGET (frame)) !=
+ GTK_TEXT_DIR_RTL)
+ x += frame->priv->handle_rect.width;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ y += frame->priv->handle_rect.height;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ return panel_background_make_string (&panel->background, x, y);
+}
+
+static void
+mate_panel_applet_frame_reload_response (GtkWidget *dialog,
+ int response,
+ MatePanelAppletFrame *frame)
+{
+ AppletInfo *info;
+
+ g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+
+ if (!frame->priv->iid || !frame->priv->panel) {
+ g_object_unref (frame);
+ gtk_widget_destroy (dialog);
+ return;
+ }
+
+ info = frame->priv->applet_info;
+
+ if (response == GTK_RESPONSE_YES) {
+ PanelWidget *panel;
+ char *iid;
+ char *id = NULL;
+ int position = -1;
+ gboolean locked = FALSE;
+
+ panel = frame->priv->panel;
+ iid = g_strdup (frame->priv->iid);
+
+ if (info) {
+ id = g_strdup (info->id);
+ position = mate_panel_applet_get_position (info);
+ locked = panel_widget_get_applet_locked (panel, info->widget);
+ mate_panel_applet_clean (info);
+ }
+
+ mate_panel_applet_frame_load (iid, panel, locked,
+ position, TRUE, id);
+
+ g_free (iid);
+ g_free (id);
+
+ } else if (info) {
+ /* if we can't write to applets list we can't really delete
+ it, so we'll just ignore this. FIXME: handle this
+ more correctly I suppose. */
+ if (panel_profile_id_lists_are_writable ())
+ panel_profile_delete_object (info);
+ }
+
+ g_object_unref (frame);
+ gtk_widget_destroy (dialog);
+}
+
+void
+_mate_panel_applet_frame_applet_broken (MatePanelAppletFrame *frame)
+{
+ GtkWidget *dialog;
+ GdkScreen *screen;
+ const char *applet_name = NULL;
+ char *dialog_txt;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (frame));
+
+ if (xstuff_is_display_dead ())
+ return;
+
+ if (frame->priv->iid) {
+ MatePanelAppletInfo *info;
+
+ info = (MatePanelAppletInfo *)mate_panel_applets_manager_get_applet_info (frame->priv->iid);
+ applet_name = mate_panel_applet_info_get_name (info);
+ }
+
+ if (applet_name)
+ dialog_txt = g_strdup_printf (_("\"%s\" has quit unexpectedly"), applet_name);
+ else
+ dialog_txt = g_strdup (_("Panel object has quit unexpectedly"));
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
+ dialog_txt, applet_name ? applet_name : NULL);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you reload a panel object, it will automatically "
+ "be added back to the panel."));
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Don't Reload"), GTK_RESPONSE_NO,
+ _("_Reload"), GTK_RESPONSE_YES,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_YES);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (mate_panel_applet_frame_reload_response),
+ g_object_ref (frame));
+
+ panel_widget_register_open_dialog (frame->priv->panel, dialog);
+ gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
+ /* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+
+ gtk_widget_show (dialog);
+ g_free (dialog_txt);
+}
+
+void
+_mate_panel_applet_frame_applet_remove (MatePanelAppletFrame *frame)
+{
+ AppletInfo *info;
+
+ if (!frame->priv->applet_info)
+ return;
+
+ info = frame->priv->applet_info;
+ frame->priv->applet_info = NULL;
+
+ panel_profile_delete_object (info);
+}
+
+void
+_mate_panel_applet_frame_applet_move (MatePanelAppletFrame *frame)
+{
+ GtkWidget *widget = GTK_WIDGET (frame);
+ GtkWidget *parent = gtk_widget_get_parent (widget);
+
+ if (!PANEL_IS_WIDGET (parent))
+ return;
+
+ panel_widget_applet_drag_start (PANEL_WIDGET (parent),
+ widget,
+ PW_DRAG_OFF_CENTER,
+ GDK_CURRENT_TIME);
+}
+
+void
+_mate_panel_applet_frame_applet_lock (MatePanelAppletFrame *frame,
+ gboolean locked)
+{
+ PanelWidget *panel_widget = PANEL_WIDGET (gtk_widget_get_parent (GTK_WIDGET (frame)));
+
+ if (panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame)) == locked)
+ return;
+
+ mate_panel_applet_toggle_locked (frame->priv->applet_info);
+}
+
+/* Generic methods */
+
+static GSList *no_reload_applets = NULL;
+
+enum {
+ LOADING_FAILED_RESPONSE_DONT_DELETE,
+ LOADING_FAILED_RESPONSE_DELETE
+};
+
+static void
+mate_panel_applet_frame_activating_free (MatePanelAppletFrameActivating *frame_act)
+{
+ g_free (frame_act->id);
+ g_slice_free (MatePanelAppletFrameActivating, frame_act);
+}
+
+PanelOrientation
+mate_panel_applet_frame_activating_get_orientation(MatePanelAppletFrameActivating *frame_act)
+{
+ return panel_widget_get_applet_orientation(frame_act->panel);
+}
+
+guint32
+mate_panel_applet_frame_activating_get_size (MatePanelAppletFrameActivating *frame_act)
+{
+ return frame_act->panel->sz;
+}
+
+gboolean
+mate_panel_applet_frame_activating_get_locked (MatePanelAppletFrameActivating *frame_act)
+{
+ return frame_act->locked;
+}
+
+gboolean
+mate_panel_applet_frame_activating_get_locked_down (MatePanelAppletFrameActivating *frame_act)
+{
+ return panel_lockdown_get_locked_down ();
+}
+
+gchar *
+mate_panel_applet_frame_activating_get_conf_path (MatePanelAppletFrameActivating *frame_act)
+{
+ return g_strdup_printf (MATE_PANEL_APPLET_PREFS_KEY, frame_act->id);
+}
+
+static void
+mate_panel_applet_frame_loading_failed_response (GtkWidget *dialog,
+ guint response,
+ char *id)
+{
+ gtk_widget_destroy (dialog);
+
+ if (response == LOADING_FAILED_RESPONSE_DELETE &&
+ !panel_lockdown_get_locked_down () &&
+ panel_profile_id_lists_are_writable ()) {
+ GSList *item;
+
+ item = g_slist_find_custom (no_reload_applets, id,
+ (GCompareFunc) strcmp);
+ if (item) {
+ g_free (item->data);
+ no_reload_applets = g_slist_delete_link (no_reload_applets,
+ item);
+ }
+
+ panel_profile_remove_from_list (PANEL_MATECONF_APPLETS, id);
+ }
+
+ g_free (id);
+}
+
+static void
+mate_panel_applet_frame_loading_failed (const char *iid,
+ PanelWidget *panel,
+ const char *id)
+{
+ GtkWidget *dialog;
+ char *problem_txt;
+ gboolean locked_down;
+
+ no_reload_applets = g_slist_prepend (no_reload_applets,
+ g_strdup (id));
+
+ locked_down = panel_lockdown_get_locked_down ();
+
+ problem_txt = g_strdup_printf (_("The panel encountered a problem "
+ "while loading \"%s\"."),
+ iid);
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ locked_down ? GTK_MESSAGE_INFO : GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "%s", problem_txt);
+ g_free (problem_txt);
+
+ if (locked_down) {
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_OK, LOADING_FAILED_RESPONSE_DONT_DELETE,
+ NULL);
+ } else {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Do you want to delete the applet "
+ "from your configuration?"));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ PANEL_STOCK_DONT_DELETE, LOADING_FAILED_RESPONSE_DONT_DELETE,
+ GTK_STOCK_DELETE, LOADING_FAILED_RESPONSE_DELETE,
+ NULL);
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ LOADING_FAILED_RESPONSE_DONT_DELETE);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_window_get_screen (GTK_WINDOW (panel->toplevel)));
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (mate_panel_applet_frame_loading_failed_response),
+ g_strdup (id));
+
+ panel_widget_register_open_dialog (panel, dialog);
+ gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
+ /* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+
+ gtk_widget_show_all (dialog);
+
+ /* Note: this call will free the memory for id, so the variable should
+ * not get accessed afterwards. */
+ mate_panel_applet_stop_loading (id);
+}
+
+static void
+mate_panel_applet_frame_load (const gchar *iid,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id)
+{
+ MatePanelAppletFrameActivating *frame_act;
+
+ g_return_if_fail (iid != NULL);
+ g_return_if_fail (panel != NULL);
+ g_return_if_fail (id != NULL);
+
+ if (g_slist_find_custom (no_reload_applets, id,
+ (GCompareFunc) strcmp)) {
+ mate_panel_applet_stop_loading (id);
+ return;
+ }
+
+ if (panel_lockdown_is_applet_disabled (iid)) {
+ mate_panel_applet_stop_loading (id);
+ return;
+ }
+
+ frame_act = g_slice_new0 (MatePanelAppletFrameActivating);
+ frame_act->locked = locked;
+ frame_act->panel = panel;
+ frame_act->position = position;
+ frame_act->exactpos = exactpos;
+ frame_act->id = g_strdup (id);
+
+ if (!mate_panel_applets_manager_load_applet (iid, frame_act)) {
+ mate_panel_applet_frame_loading_failed (iid, panel, id);
+ mate_panel_applet_frame_activating_free (frame_act);
+ }
+}
+
+void
+mate_panel_applet_frame_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ int position,
+ const char *id)
+{
+ gchar *applet_iid;
+
+ g_return_if_fail (panel_widget != NULL);
+ g_return_if_fail (id != NULL);
+
+ applet_iid = panel_compatibility_get_applet_iid (id);
+ if (!applet_iid) {
+ mate_panel_applet_stop_loading (id);
+ return;
+ }
+
+ mate_panel_applet_frame_load (applet_iid, panel_widget,
+ locked, position, TRUE, id);
+
+ g_free (applet_iid);
+}
+
+void
+mate_panel_applet_frame_create (PanelToplevel *toplevel,
+ int position,
+ const char *iid)
+{
+ MateConfClient *client;
+ const char *key;
+ char *id;
+
+ g_return_if_fail (iid != NULL);
+
+ client = panel_mateconf_get_client ();
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_APPLET, toplevel, position, FALSE);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_APPLETS, id, "applet_iid");
+ mateconf_client_set_string (client, key, iid, NULL);
+
+ panel_profile_add_to_list (PANEL_MATECONF_APPLETS, id);
+
+ g_free (id);
+}
diff --git a/mate-panel/mate-panel-applet-frame.h b/mate-panel/mate-panel-applet-frame.h
new file mode 100644
index 00000000..d8518830
--- /dev/null
+++ b/mate-panel/mate-panel-applet-frame.h
@@ -0,0 +1,146 @@
+/*
+ * mate-panel-applet-frame.h: panel side container for applets
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __MATE_PANEL_APPLET_FRAME_H__
+#define __MATE_PANEL_APPLET_FRAME_H__
+
+#include <gtk/gtk.h>
+
+#include "panel-widget.h"
+#include "applet.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_APPLET_FRAME (mate_panel_applet_frame_get_type ())
+#define MATE_PANEL_APPLET_FRAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_APPLET_FRAME, MatePanelAppletFrame))
+#define MATE_PANEL_APPLET_FRAME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_APPLET_FRAME, MatePanelAppletFrameClass))
+#define PANEL_IS_APPLET_FRAME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_APPLET_FRAME))
+#define PANEL_IS_APPLET_FRAME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_APPLET_FRAME))
+#define MATE_PANEL_APPLET_FRAME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_APPLET_FRAME, MatePanelAppletFrameClass))
+
+typedef struct _MatePanelAppletFrame MatePanelAppletFrame;
+typedef struct _MatePanelAppletFrameClass MatePanelAppletFrameClass;
+typedef struct _MatePanelAppletFramePrivate MatePanelAppletFramePrivate;
+
+struct _MatePanelAppletFrameClass {
+ GtkEventBoxClass parent_class;
+
+ void (*init_properties) (MatePanelAppletFrame *frame);
+
+ void (*sync_menu_state) (MatePanelAppletFrame *frame,
+ gboolean movable,
+ gboolean removable,
+ gboolean lockable,
+ gboolean locked,
+ gboolean locked_down);
+
+ void (*popup_menu) (MatePanelAppletFrame *frame,
+ guint button,
+ guint32 timestamp);
+
+ void (*change_orientation) (MatePanelAppletFrame *frame,
+ PanelOrientation orientation);
+
+ void (*change_size) (MatePanelAppletFrame *frame,
+ guint size);
+
+ void (*change_background) (MatePanelAppletFrame *frame,
+ PanelBackgroundType type);
+};
+
+struct _MatePanelAppletFrame {
+ GtkEventBox parent;
+
+ MatePanelAppletFramePrivate *priv;
+};
+
+GType mate_panel_applet_frame_get_type (void) G_GNUC_CONST;
+
+void mate_panel_applet_frame_create (PanelToplevel *toplevel,
+ int position,
+ const char *iid);
+
+void mate_panel_applet_frame_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ int position,
+ const char *id);
+
+void mate_panel_applet_frame_sync_menu_state (MatePanelAppletFrame *frame);
+
+void mate_panel_applet_frame_change_orientation (MatePanelAppletFrame *frame,
+ PanelOrientation orientation);
+
+void mate_panel_applet_frame_change_size (MatePanelAppletFrame *frame,
+ guint size);
+
+void mate_panel_applet_frame_change_background (MatePanelAppletFrame *frame,
+ PanelBackgroundType type);
+
+void mate_panel_applet_frame_set_panel (MatePanelAppletFrame *frame,
+ PanelWidget *panel);
+
+
+/* For module implementations only */
+
+typedef struct _MatePanelAppletFrameActivating MatePanelAppletFrameActivating;
+
+PanelOrientation mate_panel_applet_frame_activating_get_orientation (MatePanelAppletFrameActivating *frame_act);
+guint32 mate_panel_applet_frame_activating_get_size (MatePanelAppletFrameActivating *frame_act);
+gboolean mate_panel_applet_frame_activating_get_locked (MatePanelAppletFrameActivating *frame_act);
+gboolean mate_panel_applet_frame_activating_get_locked_down (MatePanelAppletFrameActivating *frame_act);
+gchar *mate_panel_applet_frame_activating_get_conf_path (MatePanelAppletFrameActivating *frame_act);
+
+void _mate_panel_applet_frame_set_iid (MatePanelAppletFrame *frame,
+ const gchar *iid);
+
+void _mate_panel_applet_frame_activated (MatePanelAppletFrame *frame,
+ MatePanelAppletFrameActivating *frame_act,
+ GError *error);
+
+void _mate_panel_applet_frame_update_flags (MatePanelAppletFrame *frame,
+ gboolean major,
+ gboolean minor,
+ gboolean has_handle);
+
+void _mate_panel_applet_frame_update_size_hints (MatePanelAppletFrame *frame,
+ gint *size_hints,
+ guint n_elements);
+
+char *_mate_panel_applet_frame_get_background_string (MatePanelAppletFrame *frame,
+ PanelWidget *panel,
+ PanelBackgroundType type);
+
+void _mate_panel_applet_frame_applet_broken (MatePanelAppletFrame *frame);
+
+void _mate_panel_applet_frame_applet_remove (MatePanelAppletFrame *frame);
+void _mate_panel_applet_frame_applet_move (MatePanelAppletFrame *frame);
+void _mate_panel_applet_frame_applet_lock (MatePanelAppletFrame *frame,
+ gboolean locked);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_PANEL_APPLET_FRAME_H__ */
diff --git a/mate-panel/mate-panel-applet-info.c b/mate-panel/mate-panel-applet-info.c
new file mode 100644
index 00000000..123b0806
--- /dev/null
+++ b/mate-panel/mate-panel-applet-info.c
@@ -0,0 +1,113 @@
+/*
+ * mate-panel-applet-info.c
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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.
+ */
+
+#include <config.h>
+
+#include "mate-panel-applet-info.h"
+
+struct _MatePanelAppletInfo {
+ gchar *iid;
+
+ gchar *name;
+ gchar *comment;
+ gchar *icon;
+
+ gchar **old_ids;
+};
+
+MatePanelAppletInfo *
+mate_panel_applet_info_new (const gchar *iid,
+ const gchar *name,
+ const gchar *comment,
+ const gchar *icon,
+ const gchar **old_ids)
+{
+ MatePanelAppletInfo *info;
+ int len;
+
+ info = g_slice_new0 (MatePanelAppletInfo);
+
+ info->iid = g_strdup (iid);
+ info->name = g_strdup (name);
+ info->comment = g_strdup (comment);
+ info->icon = g_strdup (icon);
+
+ /* MateComponent compatibility */
+ if (old_ids != NULL) {
+ len = g_strv_length ((gchar **) old_ids);
+ if (len > 0) {
+ int i;
+
+ info->old_ids = g_new0 (gchar *, len + 1);
+
+ for (i = 0; i < len; i++)
+ info->old_ids[i] = g_strdup (old_ids[i]);
+ }
+ }
+
+ return info;
+}
+
+void
+mate_panel_applet_info_free (MatePanelAppletInfo *info)
+{
+ if (!info)
+ return;
+
+ g_free (info->iid);
+ g_free (info->name);
+ g_free (info->comment);
+ g_free (info->icon);
+ g_strfreev (info->old_ids);
+
+ g_slice_free (MatePanelAppletInfo, info);
+}
+
+const gchar *
+mate_panel_applet_info_get_iid (MatePanelAppletInfo *info)
+{
+ return info->iid;
+}
+
+const gchar *
+mate_panel_applet_info_get_name (MatePanelAppletInfo *info)
+{
+ return info->name;
+}
+
+const gchar *
+mate_panel_applet_info_get_description (MatePanelAppletInfo *info)
+{
+ return info->comment;
+}
+
+const gchar *
+mate_panel_applet_info_get_icon (MatePanelAppletInfo *info)
+{
+ return info->icon;
+}
+
+const gchar * const *
+mate_panel_applet_info_get_old_ids (MatePanelAppletInfo *info)
+{
+ return (const gchar * const *) info->old_ids;
+}
diff --git a/mate-panel/mate-panel-applet-info.h b/mate-panel/mate-panel-applet-info.h
new file mode 100644
index 00000000..264c0730
--- /dev/null
+++ b/mate-panel/mate-panel-applet-info.h
@@ -0,0 +1,51 @@
+/*
+ * mate-panel-applet-info.h
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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 __MATE_PANEL_APPLET_INFO_H__
+#define __MATE_PANEL_APPLET_INFO_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _MatePanelAppletInfo MatePanelAppletInfo;
+
+MatePanelAppletInfo *mate_panel_applet_info_new (const gchar *iid,
+ const gchar *name,
+ const gchar *comment,
+ const gchar *icon,
+ const gchar **old_ids);
+void mate_panel_applet_info_free (MatePanelAppletInfo *info);
+
+const gchar *mate_panel_applet_info_get_iid (MatePanelAppletInfo *info);
+const gchar *mate_panel_applet_info_get_name (MatePanelAppletInfo *info);
+const gchar *mate_panel_applet_info_get_description (MatePanelAppletInfo *info);
+const gchar *mate_panel_applet_info_get_icon (MatePanelAppletInfo *info);
+const gchar * const *mate_panel_applet_info_get_old_ids (MatePanelAppletInfo *info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_PANEL_APPLET_INFO_H__ */
diff --git a/mate-panel/mate-panel-applets-manager.c b/mate-panel/mate-panel-applets-manager.c
new file mode 100644
index 00000000..347176e4
--- /dev/null
+++ b/mate-panel/mate-panel-applets-manager.c
@@ -0,0 +1,201 @@
+/*
+ * mate-panel-applets-manager.c
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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.
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+
+#include <libpanel-util/panel-cleanup.h>
+
+#include "panel-modules.h"
+
+#include "mate-panel-applets-manager.h"
+
+G_DEFINE_ABSTRACT_TYPE (MatePanelAppletsManager, mate_panel_applets_manager, G_TYPE_OBJECT)
+
+static void
+mate_panel_applets_manager_init (MatePanelAppletsManager *manager)
+{
+}
+
+static void
+mate_panel_applets_manager_class_init (MatePanelAppletsManagerClass *class)
+{
+}
+
+/* Generic methods */
+
+static GSList *mate_panel_applets_managers = NULL;
+
+static void
+_mate_panel_applets_manager_cleanup (gpointer data)
+{
+ g_slist_foreach (mate_panel_applets_managers, (GFunc) g_object_unref, NULL);
+ g_slist_free (mate_panel_applets_managers);
+ mate_panel_applets_managers = NULL;
+}
+
+static void
+_mate_panel_applets_managers_ensure_loaded (void)
+{
+ GIOExtensionPoint *point;
+ GList *extensions, *l;
+
+ if (mate_panel_applets_managers != NULL)
+ return;
+
+ panel_cleanup_register (PANEL_CLEAN_FUNC (_mate_panel_applets_manager_cleanup), NULL);
+
+ panel_modules_ensure_loaded ();
+
+ point = g_io_extension_point_lookup (MATE_PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME);
+
+ extensions = g_io_extension_point_get_extensions (point);
+
+ if (extensions == NULL)
+ g_error ("No MatePanelAppletsManager implementations exist.");
+
+ for (l = extensions; l != NULL; l = l->next) {
+ GIOExtension *extension;
+ GType type;
+ GObject *object;
+
+ extension = l->data;
+ type = g_io_extension_get_type (extension);
+ object = g_object_new (type, NULL);
+ mate_panel_applets_managers = g_slist_prepend (mate_panel_applets_managers, object);
+ }
+
+ mate_panel_applets_managers = g_slist_reverse (mate_panel_applets_managers);
+}
+
+GList *
+mate_panel_applets_manager_get_applets (void)
+{
+ GSList *l;
+ GList *retval = NULL;
+
+ _mate_panel_applets_managers_ensure_loaded ();
+
+ for (l = mate_panel_applets_managers; l != NULL; l = l->next) {
+ GList *applets;
+ MatePanelAppletsManager *manager = MATE_PANEL_APPLETS_MANAGER (l->data);
+
+ applets = MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applets (manager);
+ if (applets)
+ retval = g_list_concat (retval, applets);
+ }
+
+ return retval;
+}
+
+gboolean
+mate_panel_applets_manager_factory_activate (const gchar *iid)
+{
+ GSList *l;
+
+ _mate_panel_applets_managers_ensure_loaded ();
+
+ for (l = mate_panel_applets_managers; l != NULL; l = l->next) {
+ MatePanelAppletsManager *manager = MATE_PANEL_APPLETS_MANAGER (l->data);
+
+ if (MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->factory_activate (manager, iid))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+mate_panel_applets_manager_factory_deactivate (const gchar *iid)
+{
+ GSList *l;
+
+ _mate_panel_applets_managers_ensure_loaded ();
+
+ for (l = mate_panel_applets_managers; l != NULL; l = l->next) {
+ MatePanelAppletsManager *manager = MATE_PANEL_APPLETS_MANAGER (l->data);
+
+ if (MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->factory_deactivate (manager, iid))
+ return;
+ }
+}
+
+MatePanelAppletInfo *
+mate_panel_applets_manager_get_applet_info (const gchar *iid)
+{
+ GSList *l;
+ MatePanelAppletInfo *retval = NULL;
+
+ _mate_panel_applets_managers_ensure_loaded ();
+
+ for (l = mate_panel_applets_managers; l != NULL; l = l->next) {
+ MatePanelAppletsManager *manager = MATE_PANEL_APPLETS_MANAGER (l->data);
+
+ retval = MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applet_info (manager, iid);
+
+ if (retval != NULL)
+ return retval;
+ }
+
+ return NULL;
+}
+
+MatePanelAppletInfo *
+mate_panel_applets_manager_get_applet_info_from_old_id (const gchar *iid)
+{
+ GSList *l;
+ MatePanelAppletInfo *retval = NULL;
+
+ _mate_panel_applets_managers_ensure_loaded ();
+
+ for (l = mate_panel_applets_managers; l != NULL; l = l->next) {
+ MatePanelAppletsManager *manager = MATE_PANEL_APPLETS_MANAGER (l->data);
+
+ retval = MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applet_info_from_old_id (manager, iid);
+
+ if (retval != NULL)
+ return retval;
+ }
+
+ return NULL;
+}
+
+gboolean
+mate_panel_applets_manager_load_applet (const gchar *iid,
+ MatePanelAppletFrameActivating *frame_act)
+{
+ GSList *l;
+
+ _mate_panel_applets_managers_ensure_loaded ();
+
+ for (l = mate_panel_applets_managers; l != NULL; l = l->next) {
+ MatePanelAppletsManager *manager = MATE_PANEL_APPLETS_MANAGER (l->data);
+
+ if (!MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applet_info (manager, iid))
+ continue;
+
+ return MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->load_applet (manager, iid, frame_act);
+ }
+
+ return FALSE;
+}
diff --git a/mate-panel/mate-panel-applets-manager.h b/mate-panel/mate-panel-applets-manager.h
new file mode 100644
index 00000000..dfe98074
--- /dev/null
+++ b/mate-panel/mate-panel-applets-manager.h
@@ -0,0 +1,94 @@
+/*
+ * mate-panel-applets-manager.h
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2010 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 __MATE_PANEL_APPLETS_MANAGER_H__
+#define __MATE_PANEL_APPLETS_MANAGER_H__
+
+#include <glib-object.h>
+
+#include "mate-panel-applet-frame.h"
+#include "mate-panel-applet-info.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_APPLETS_MANAGER (mate_panel_applets_manager_get_type ())
+#define MATE_PANEL_APPLETS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_APPLETS_MANAGER, MatePanelAppletsManager))
+#define MATE_PANEL_APPLETS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_APPLETS_MANAGER, MatePanelAppletsManagerClass))
+#define PANEL_IS_APPLETS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_APPLETS_MANAGER))
+#define PANEL_IS_APPLETS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_APPLETS_MANAGER))
+#define MATE_PANEL_APPLETS_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_APPLETS_MANAGER, MatePanelAppletsManagerClass))
+
+/**
+ * MATE_PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME:
+ *
+ * Extension point for #MatePanelAppletsManager functionality.
+ **/
+#define MATE_PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME "mate-panel-applets-manager"
+
+typedef struct _MatePanelAppletsManager MatePanelAppletsManager;
+typedef struct _MatePanelAppletsManagerClass MatePanelAppletsManagerClass;
+
+struct _MatePanelAppletsManagerClass {
+ GObjectClass parent_class;
+
+ GList * (*get_applets) (MatePanelAppletsManager *manager);
+
+ gboolean (*factory_activate) (MatePanelAppletsManager *manager,
+ const gchar *iid);
+ gboolean (*factory_deactivate) (MatePanelAppletsManager *manager,
+ const gchar *iid);
+
+ MatePanelAppletInfo * (*get_applet_info) (MatePanelAppletsManager *manager,
+ const gchar *iid);
+
+ MatePanelAppletInfo * (*get_applet_info_from_old_id) (MatePanelAppletsManager *manager,
+ const gchar *iid);
+
+ gboolean (*load_applet) (MatePanelAppletsManager *manager,
+ const gchar *iid,
+ MatePanelAppletFrameActivating *frame_act);
+};
+
+struct _MatePanelAppletsManager {
+ GObject parent;
+};
+
+GType mate_panel_applets_manager_get_type (void);
+
+GList *mate_panel_applets_manager_get_applets (void);
+
+gboolean mate_panel_applets_manager_factory_activate (const gchar *iid);
+void mate_panel_applets_manager_factory_deactivate (const gchar *iid);
+
+MatePanelAppletInfo *mate_panel_applets_manager_get_applet_info (const gchar *iid);
+MatePanelAppletInfo *mate_panel_applets_manager_get_applet_info_from_old_id (const gchar *iid);
+
+gboolean mate_panel_applets_manager_load_applet (const gchar *iid,
+ MatePanelAppletFrameActivating *frame_act);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATE_PANEL_APPLETS_MANAGER_H__ */
diff --git a/mate-panel/mate-panel.desktop.in.in b/mate-panel/mate-panel.desktop.in.in
new file mode 100644
index 00000000..068eaba5
--- /dev/null
+++ b/mate-panel/mate-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Type=Application
+_Name=Panel
+_Comment=Launch other applications and provide various utilities to manage windows, show the time, etc.
+Icon=mate-panel
+Exec=mate-panel
+StartupNotify=true
+Terminal=false
+X-MATE-Bugzilla-Bugzilla=MATE
+X-MATE-Bugzilla-Product=mate-panel
+X-MATE-Bugzilla-Component=general
+X-MATE-Bugzilla-Version=@VERSION@
+Categories=MATE;GTK;Utility;Core;
+OnlyShowIn=MATE;
+NoDisplay=true
+X-MATE-AutoRestart=true
+X-MATE-Autostart-Phase=Panel
+X-MATE-Provides=panel
+X-MATE-Autostart-Notify=true
diff --git a/mate-panel/mate-panelrc b/mate-panel/mate-panelrc
new file mode 100644
index 00000000..0fb54692
--- /dev/null
+++ b/mate-panel/mate-panelrc
@@ -0,0 +1,4 @@
+#
+# This file is intentionally left empty. You may add gtk theme
+# definitions here and they will only apply to the MATE Panel.
+#
diff --git a/mate-panel/menu.c b/mate-panel/menu.c
new file mode 100644
index 00000000..273fae86
--- /dev/null
+++ b/mate-panel/menu.c
@@ -0,0 +1,1914 @@
+/*
+ * Copyright (C) 1997 - 2000 The Free Software Foundation
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 2000 Eazel, Inc.
+ * Copyright (C) 2004 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 "menu.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdkkeysyms.h>
+#include <mateconf/mateconf-client.h>
+
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-xdg.h>
+
+#include "launcher.h"
+#include "panel-util.h"
+#include "panel.h"
+#include "drawer.h"
+#include "panel-config-global.h"
+#include "panel-stock-icons.h"
+#include "panel-action-button.h"
+#include "panel-profile.h"
+#include "panel-menu-button.h"
+#include "panel-menu-items.h"
+#include "panel-globals.h"
+#include "panel-run-dialog.h"
+#include "panel-lockdown.h"
+#include "panel-icon-names.h"
+
+typedef struct {
+ GtkWidget *pixmap;
+ const char *stock_id;
+ GIcon *gicon;
+ char *image;
+ char *fallback_image;
+ GtkIconTheme *icon_theme;
+ GtkIconSize icon_size;
+} IconToLoad;
+
+typedef struct {
+ GtkWidget *image;
+ const char *stock_id;
+ GIcon *gicon;
+ GdkPixbuf *pixbuf;
+ GtkIconSize icon_size;
+} IconToAdd;
+
+static guint load_icons_id = 0;
+static GHashTable *loaded_icons = NULL;
+static GList *icons_to_load = NULL;
+static GList *icons_to_add = NULL;
+
+static GSList *image_menu_items = NULL;
+
+static GtkWidget *populate_menu_from_directory (GtkWidget *menu,
+ MateMenuTreeDirectory *directory);
+
+static void panel_load_menu_image_deferred (GtkWidget *image_menu_item,
+ GtkIconSize icon_size,
+ const char *stock_id,
+ GIcon *gicon,
+ const char *image_filename,
+ const char *fallback_image_filename);
+
+static gboolean panel_menu_key_press_handler (GtkWidget *widget,
+ GdkEventKey *event);
+
+static inline gboolean desktop_is_home_dir(void)
+{
+ return mateconf_client_get_bool(panel_mateconf_get_client(), "/apps/caja/preferences/desktop_is_home_dir", NULL);
+}
+
+GtkWidget *
+add_menu_separator (GtkWidget *menu)
+{
+ GtkWidget *menuitem;
+
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+
+ return menuitem;
+}
+
+static void
+activate_app_def (GtkWidget *menuitem,
+ MateMenuTreeEntry *entry)
+{
+ const char *path;
+
+ path = matemenu_tree_entry_get_desktop_file_path (entry);
+ panel_menu_item_activate_desktop_file (menuitem, path);
+}
+
+PanelWidget *
+menu_get_panel (GtkWidget *menu)
+{
+ PanelWidget *retval = NULL;
+
+ g_return_val_if_fail (menu != NULL, NULL);
+
+ if (GTK_IS_MENU_ITEM (menu))
+ menu = gtk_widget_get_parent (menu);
+
+ g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
+
+ while (menu) {
+ retval = g_object_get_data (G_OBJECT (menu), "menu_panel");
+ if (retval)
+ break;
+
+ menu = gtk_widget_get_parent (gtk_menu_get_attach_widget (GTK_MENU (menu)));
+ if (!GTK_IS_MENU (menu))
+ break;
+ }
+
+ if (retval && !PANEL_IS_WIDGET (retval)) {
+ g_warning ("Invalid PanelWidget associated with menu");
+ retval = NULL;
+ }
+
+ if (!retval) {
+ g_warning ("Cannot find the PanelWidget associated with menu");
+ retval = panels->data;
+ }
+
+ return retval;
+}
+
+static void
+setup_menu_panel (GtkWidget *menu)
+{
+ PanelWidget *panel;
+
+ panel = g_object_get_data (G_OBJECT (menu), "menu_panel");
+ if (panel)
+ return;
+
+ panel = menu_get_panel (menu);
+ g_object_set_data (G_OBJECT (menu), "menu_panel", panel);
+
+ if (panel)
+ gtk_menu_set_screen (GTK_MENU (menu),
+ gtk_widget_get_screen (GTK_WIDGET (panel)));
+}
+
+GdkScreen *
+menuitem_to_screen (GtkWidget *menuitem)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = menu_get_panel (menuitem);
+
+ return gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel));
+}
+
+static void
+reload_image_menu_items (void)
+{
+ GSList* l;
+
+ for (l = image_menu_items; l; l = l->next) {
+ GtkWidget *image = l->data;
+ gboolean is_mapped;
+
+ is_mapped = gtk_widget_get_mapped (image);
+
+ if (is_mapped)
+ gtk_widget_unmap (image);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (image), NULL);
+
+ if (is_mapped)
+ gtk_widget_map (image);
+
+ }
+}
+
+static void
+icon_theme_changed (GtkIconTheme *icon_theme,
+ gpointer data)
+{
+ reload_image_menu_items ();
+}
+
+GtkWidget *
+panel_create_menu (void)
+{
+ GtkWidget *retval;
+ static gboolean registered_icon_theme_changer = FALSE;
+
+ if (!registered_icon_theme_changer) {
+ registered_icon_theme_changer = TRUE;
+
+ g_signal_connect (gtk_icon_theme_get_default (), "changed",
+ G_CALLBACK (icon_theme_changed), NULL);
+ }
+
+ retval = gtk_menu_new ();
+ gtk_widget_set_name (retval, "mate-panel-main-menu");
+
+ g_signal_connect (retval, "key_press_event",
+ G_CALLBACK (panel_menu_key_press_handler),
+ NULL);
+
+ return retval;
+}
+
+GtkWidget *
+create_empty_menu (void)
+{
+ GtkWidget *retval;
+
+ retval = panel_create_menu ();
+
+ g_signal_connect (retval, "show", G_CALLBACK (setup_menu_panel), NULL);
+
+ /* intercept all right button clicks makes sure they don't
+ go to the object itself */
+ g_signal_connect (retval, "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+
+ return retval;
+}
+
+static void
+icon_to_load_free (IconToLoad *icon)
+{
+ if (!icon)
+ return;
+
+ if (icon->pixmap)
+ g_object_unref (icon->pixmap);
+ icon->pixmap = NULL;
+
+ if (icon->gicon)
+ g_object_unref (icon->gicon);
+ icon->gicon = NULL;
+
+ g_free (icon->image); icon->image = NULL;
+ g_free (icon->fallback_image); icon->fallback_image = NULL;
+ g_free (icon);
+}
+
+static IconToLoad *
+icon_to_load_copy (IconToLoad *icon)
+{
+ IconToLoad *retval;
+
+ if (!icon)
+ return NULL;
+
+ retval = g_new0 (IconToLoad, 1);
+
+ retval->pixmap = g_object_ref (icon->pixmap);
+ if (icon->gicon)
+ retval->gicon = g_object_ref (icon->gicon);
+ else
+ retval->gicon = NULL;
+ retval->image = g_strdup (icon->image);
+ retval->fallback_image = g_strdup (icon->fallback_image);
+ retval->stock_id = icon->stock_id;
+ retval->icon_size = icon->icon_size;
+
+ return retval;
+}
+
+static void
+remove_pixmap_from_loaded (gpointer data, GObject *where_the_object_was)
+{
+ char *key = data;
+
+ if (loaded_icons != NULL)
+ g_hash_table_remove (loaded_icons, key);
+
+ g_free (key);
+}
+
+GdkPixbuf *
+panel_make_menu_icon (GtkIconTheme *icon_theme,
+ const char *icon,
+ const char *fallback,
+ int size,
+ gboolean *long_operation)
+{
+ GdkPixbuf *pb;
+ char *file, *key;
+ gboolean loaded;
+
+ g_return_val_if_fail (size > 0, NULL);
+
+ file = NULL;
+ if (icon != NULL)
+ file = panel_find_icon (icon_theme, icon, size);
+ if (file == NULL && fallback != NULL)
+ file = panel_find_icon (icon_theme, fallback, size);
+
+ if (file == NULL)
+ return NULL;
+
+ if (long_operation != NULL)
+ *long_operation = TRUE;
+
+ pb = NULL;
+
+ loaded = FALSE;
+
+ key = g_strdup_printf ("%d:%s", size, file);
+
+ if (loaded_icons != NULL &&
+ (pb = g_hash_table_lookup (loaded_icons, key)) != NULL) {
+ if (pb != NULL)
+ g_object_ref (G_OBJECT (pb));
+ }
+
+ if (pb == NULL) {
+ pb = gdk_pixbuf_new_from_file (file, NULL);
+ if (pb) {
+ gint width, height;
+
+ width = gdk_pixbuf_get_width (pb);
+ height = gdk_pixbuf_get_height (pb);
+
+ /* if we want 24 and we get 22, do nothing;
+ * else scale */
+ if (!(size - 2 <= width && width <= size &&
+ size - 2 <= height && height <= size)) {
+ GdkPixbuf *tmp;
+
+ tmp = gdk_pixbuf_scale_simple (pb, size, size,
+ GDK_INTERP_BILINEAR);
+
+ g_object_unref (pb);
+ pb = tmp;
+ }
+ }
+
+ /* add icon to the hash table so we don't load it again */
+ loaded = TRUE;
+ }
+
+ if (pb == NULL) {
+ g_free (file);
+ g_free (key);
+ return NULL;
+ }
+
+ if (loaded &&
+ (gdk_pixbuf_get_width (pb) != size &&
+ gdk_pixbuf_get_height (pb) != size)) {
+ GdkPixbuf *pb2;
+ int dest_width;
+ int dest_height;
+ int width;
+ int height;
+
+ width = gdk_pixbuf_get_width (pb);
+ height = gdk_pixbuf_get_height (pb);
+
+ if (height > width) {
+ dest_width = (size * width) / height;
+ dest_height = size;
+ } else {
+ dest_width = size;
+ dest_height = (size * height) / width;
+ }
+
+ pb2 = gdk_pixbuf_scale_simple (pb, dest_width, dest_height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (G_OBJECT (pb));
+ pb = pb2;
+ }
+
+ if (loaded) {
+ if (loaded_icons == NULL)
+ loaded_icons = g_hash_table_new_full
+ (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+ g_hash_table_replace (loaded_icons,
+ g_strdup (key),
+ g_object_ref (G_OBJECT (pb)));
+ g_object_weak_ref (G_OBJECT (pb),
+ (GWeakNotify) remove_pixmap_from_loaded,
+ g_strdup (key));
+ } else {
+ /* we didn't load from disk */
+ if (long_operation != NULL)
+ *long_operation = FALSE;
+ }
+
+ g_free (file);
+ g_free (key);
+
+ return pb;
+}
+
+static void
+menu_item_style_set (GtkImage *image,
+ gpointer data)
+{
+ GtkWidget *widget;
+ GdkPixbuf *pixbuf;
+ GtkIconSize icon_size = (GtkIconSize) GPOINTER_TO_INT (data);
+ int icon_height;
+ gboolean is_mapped;
+
+ if (!gtk_icon_size_lookup (icon_size, NULL, &icon_height))
+ return;
+
+ pixbuf = gtk_image_get_pixbuf (image);
+ if (!pixbuf)
+ return;
+
+ if (gdk_pixbuf_get_height (pixbuf) == icon_height)
+ return;
+
+ widget = GTK_WIDGET (image);
+
+ is_mapped = gtk_widget_get_mapped (widget);
+ if (is_mapped)
+ gtk_widget_unmap (widget);
+
+ gtk_image_set_from_pixbuf (image, NULL);
+
+ if (is_mapped)
+ gtk_widget_map (widget);
+}
+
+static void
+do_icons_to_add (void)
+{
+ while (icons_to_add) {
+ IconToAdd *icon_to_add = icons_to_add->data;
+
+ icons_to_add = g_list_delete_link (icons_to_add, icons_to_add);
+
+ if (icon_to_add->stock_id) {
+ gtk_image_set_from_stock (
+ GTK_IMAGE (icon_to_add->image),
+ icon_to_add->stock_id,
+ icon_to_add->icon_size);
+ } else if (icon_to_add->gicon) {
+ gtk_image_set_from_gicon (
+ GTK_IMAGE (icon_to_add->image),
+ icon_to_add->gicon,
+ icon_to_add->icon_size);
+ } else {
+ g_assert (icon_to_add->pixbuf);
+
+ gtk_image_set_from_pixbuf (
+ GTK_IMAGE (icon_to_add->image),
+ icon_to_add->pixbuf);
+
+ g_signal_connect (icon_to_add->image, "style-set",
+ G_CALLBACK (menu_item_style_set),
+ GINT_TO_POINTER (icon_to_add->icon_size));
+
+ g_object_unref (icon_to_add->pixbuf);
+ }
+
+ if (icon_to_add->gicon)
+ g_object_unref (icon_to_add->gicon);
+ g_object_unref (icon_to_add->image);
+ g_free (icon_to_add);
+ }
+}
+
+static gboolean
+load_icons_handler (gpointer data)
+{
+ IconToLoad *icon;
+ gboolean long_operation = FALSE;
+
+load_icons_handler_again:
+
+ if (!icons_to_load) {
+ load_icons_id = 0;
+ do_icons_to_add ();
+
+ return FALSE;
+ }
+
+ icon = icons_to_load->data;
+ icons_to_load->data = NULL;
+ /* pop */
+ icons_to_load = g_list_delete_link (icons_to_load, icons_to_load);
+
+ /* if not visible anymore, just ignore */
+ if ( ! gtk_widget_get_visible (icon->pixmap)) {
+ icon_to_load_free (icon);
+ /* we didn't do anything long/hard, so just do this again,
+ * this is fun, don't go back to main loop */
+ goto load_icons_handler_again;
+ }
+
+ if (icon->stock_id || icon->gicon) {
+ IconToAdd *icon_to_add;
+
+ icon_to_add = g_new (IconToAdd, 1);
+ icon_to_add->image = g_object_ref (icon->pixmap);
+ icon_to_add->stock_id = icon->stock_id;
+ icon_to_add->pixbuf = NULL;
+ icon_to_add->icon_size = icon->icon_size;
+ if (icon->gicon)
+ icon_to_add->gicon = g_object_ref (icon->gicon);
+ else
+ icon_to_add->gicon = NULL;
+
+ icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
+ } else {
+ IconToAdd *icon_to_add;
+ GdkPixbuf *pb;
+ int icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
+
+ gtk_icon_size_lookup (icon->icon_size, NULL, &icon_height);
+
+ pb = panel_make_menu_icon (icon->icon_theme,
+ icon->image,
+ icon->fallback_image,
+ icon_height,
+ &long_operation);
+ if (!pb) {
+ icon_to_load_free (icon);
+ if (long_operation)
+ /* this may have been a long operation so jump back to
+ * the main loop for a while */
+ return TRUE;
+ else
+ /* we didn't do anything long/hard, so just do this again,
+ * this is fun, don't go back to main loop */
+ goto load_icons_handler_again;
+ }
+
+ icon_to_add = g_new (IconToAdd, 1);
+ icon_to_add->image = g_object_ref (icon->pixmap);
+ icon_to_add->stock_id = NULL;
+ icon_to_add->gicon = NULL;
+ icon_to_add->pixbuf = pb;
+ icon_to_add->icon_size = icon->icon_size;
+
+ icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
+ }
+
+ icon_to_load_free (icon);
+
+ if (!long_operation)
+ /* we didn't do anything long/hard, so just do this again,
+ * this is fun, don't go back to main loop */
+ goto load_icons_handler_again;
+
+ /* if still more we'll come back */
+ return TRUE;
+}
+
+static void
+add_app_to_panel (GtkWidget *item,
+ MateMenuTreeEntry *entry)
+{
+ PanelWidget *panel_widget;
+ PanelToplevel *toplevel;
+ PanelData *pd;
+ int position;
+
+ panel_widget = menu_get_panel (item);
+ toplevel = panel_widget->toplevel;
+
+ pd = g_object_get_data (G_OBJECT (toplevel), "PanelData");
+ position = pd ? pd->insertion_pos : -1;
+
+ panel_launcher_create (toplevel,
+ position,
+ matemenu_tree_entry_get_desktop_file_path (entry));
+}
+
+
+static void
+add_app_to_desktop (GtkWidget *item,
+ MateMenuTreeEntry *entry)
+{
+ char *source_uri;
+ const char *source;
+ char *target_dir;
+ char *target_uri;
+ char *target;
+ GError *error;
+
+ g_return_if_fail (entry != NULL);
+
+ if (desktop_is_home_dir ()) {
+ target_dir = g_build_filename (g_get_home_dir (), NULL);
+ } else {
+ target_dir = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
+ }
+
+ source = matemenu_tree_entry_get_desktop_file_path (entry);
+ source_uri = g_filename_to_uri (source, NULL, NULL);
+
+ target_uri = panel_make_unique_desktop_uri (target_dir, source_uri);
+ g_free (target_dir);
+ g_free (source_uri);
+
+ g_return_if_fail (target_uri != NULL);
+
+ target = g_filename_from_uri (target_uri, NULL, NULL);
+ g_free (target_uri);
+
+ error = NULL;
+ panel_key_file_copy_and_mark_trusted (source, target, &error);
+
+ g_free (target);
+
+ if (error != NULL) {
+ g_warning ("Problem while copying launcher to desktop: %s",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+
+static void add_drawers_from_dir (MateMenuTreeDirectory *directory,
+ int pos,
+ const char *toplevel_id);
+
+static void
+add_drawers_from_alias (MateMenuTreeAlias *alias,
+ const char *toplevel_id)
+{
+ MateMenuTreeItem *aliased_item;
+
+ aliased_item = matemenu_tree_alias_get_item (alias);
+
+ switch (matemenu_tree_item_get_type (aliased_item)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ add_drawers_from_dir (MATEMENU_TREE_DIRECTORY (aliased_item),
+ G_MAXINT/2,
+ toplevel_id);
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ panel_launcher_create_with_id (toplevel_id,
+ G_MAXINT/2,
+ matemenu_tree_entry_get_desktop_file_path (MATEMENU_TREE_ENTRY (aliased_item)));
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (aliased_item);
+}
+
+static void
+add_drawers_from_dir (MateMenuTreeDirectory *directory,
+ int pos,
+ const char *toplevel_id)
+{
+ const char *name;
+ const char *icon;
+ GSList *items;
+ GSList *l;
+ char *attached_toplevel_id;
+
+ name = matemenu_tree_directory_get_name (directory);
+ icon = matemenu_tree_directory_get_icon (directory);
+
+ attached_toplevel_id = panel_drawer_create_with_id (toplevel_id,
+ pos,
+ icon,
+ icon != NULL,
+ name);
+ if (!attached_toplevel_id)
+ return;
+
+ items = matemenu_tree_directory_get_contents (directory);
+ for (l = items; l; l = l->next) {
+ MateMenuTreeItem *item = l->data;
+
+ switch (matemenu_tree_item_get_type (item)) {
+ case MATEMENU_TREE_ITEM_ENTRY:
+ panel_launcher_create_with_id (attached_toplevel_id,
+ G_MAXINT/2,
+ matemenu_tree_entry_get_desktop_file_path (MATEMENU_TREE_ENTRY (item)));
+ break;
+
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ add_drawers_from_dir (MATEMENU_TREE_DIRECTORY (item),
+ G_MAXINT/2,
+ attached_toplevel_id);
+ break;
+
+ case MATEMENU_TREE_ITEM_ALIAS:
+ add_drawers_from_alias (MATEMENU_TREE_ALIAS (item), attached_toplevel_id);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (item);
+ }
+
+ g_slist_free (items);
+
+ g_free (attached_toplevel_id);
+}
+
+static void
+add_menudrawer_to_panel (GtkWidget *menuitem,
+ MateMenuTreeEntry *entry)
+
+{
+ MateMenuTreeDirectory *directory;
+ PanelWidget *panel;
+ PanelData *pd;
+ int insertion_pos;
+
+ directory = matemenu_tree_item_get_parent (MATEMENU_TREE_ITEM (entry));
+
+ panel = menu_get_panel (menuitem);
+
+ pd = g_object_get_data (G_OBJECT (panel->toplevel), "PanelData");
+ insertion_pos = pd ? pd->insertion_pos : -1;
+
+ add_drawers_from_dir (directory,
+ insertion_pos,
+ panel_profile_get_toplevel_id (panel->toplevel));
+
+ matemenu_tree_item_unref (directory);
+}
+
+static void
+add_menu_to_panel (GtkWidget *menuitem,
+ MateMenuTreeEntry *entry)
+{
+ MateMenuTreeDirectory *directory;
+ MateMenuTree *tree;
+ PanelWidget *panel;
+ PanelData *pd;
+ int insertion_pos;
+ char *menu_path;
+ const char *menu_filename;
+
+ directory = matemenu_tree_item_get_parent (MATEMENU_TREE_ITEM (entry));
+ if (!directory) {
+ g_warning ("Cannot find the filename for the menu: no directory");
+ return;
+ }
+
+ tree = matemenu_tree_directory_get_tree (directory);
+ if (!tree) {
+ matemenu_tree_item_unref (directory);
+ g_warning ("Cannot find the filename for the menu: no tree");
+ return;
+ }
+
+ menu_filename = matemenu_tree_get_menu_file (tree);
+ matemenu_tree_unref (tree);
+ if (!menu_filename) {
+ matemenu_tree_item_unref (directory);
+ g_warning ("Cannot find the filename for the menu: no filename");
+ return;
+ }
+
+ panel = menu_get_panel (menuitem);
+
+ pd = g_object_get_data (G_OBJECT (panel->toplevel), "PanelData");
+ insertion_pos = pd ? pd->insertion_pos : -1;
+
+ menu_path = matemenu_tree_directory_make_path (directory, NULL);
+
+ panel_menu_button_create (panel->toplevel,
+ insertion_pos,
+ menu_filename,
+ menu_path,
+ TRUE,
+ matemenu_tree_directory_get_name (directory));
+
+ g_free (menu_path);
+
+ matemenu_tree_item_unref (directory);
+}
+
+/*most of this function stolen from the real gtk_menu_popup*/
+static void
+restore_grabs(GtkWidget *w, gpointer data)
+{
+ GtkWidget *menu_item = data;
+ GtkMenu *menu = GTK_MENU (gtk_widget_get_parent (menu_item));
+ GtkWidget *xgrab_shell;
+ GtkWidget *parent;
+
+ /* Find the last viewable ancestor, and make an X grab on it
+ */
+ parent = GTK_WIDGET (menu);
+ xgrab_shell = NULL;
+ while (parent) {
+ gboolean viewable = TRUE;
+ GtkWidget *tmp = parent;
+
+ while (tmp) {
+ if (!gtk_widget_get_mapped (tmp)) {
+ viewable = FALSE;
+ break;
+ }
+ tmp = gtk_widget_get_parent (tmp);
+ }
+
+ if (viewable)
+ xgrab_shell = parent;
+
+ parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
+ }
+
+ /*only grab if this HAD a grab before*/
+ if (xgrab_shell && (GTK_MENU_SHELL (xgrab_shell)->have_xgrab))
+ {
+ GdkWindow *window = gtk_widget_get_window (xgrab_shell);
+
+ if (gdk_pointer_grab (window, TRUE,
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK,
+ NULL, NULL, 0) == 0)
+ {
+ if (gdk_keyboard_grab (window, TRUE,
+ GDK_CURRENT_TIME) == 0)
+ GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
+ else
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ }
+ }
+
+ gtk_grab_add (GTK_WIDGET (menu));
+}
+
+static void
+menu_destroy_context_menu (GtkWidget *item,
+ GtkWidget *menu)
+{
+ g_signal_handlers_disconnect_by_func (menu, restore_grabs, item);
+ gtk_widget_destroy (menu);
+}
+
+static GtkWidget *
+create_item_context_menu (GtkWidget *item,
+ PanelWidget *panel_widget)
+{
+ MateMenuTreeEntry *entry;
+ MateMenuTreeDirectory *directory;
+ MateMenuTree *tree;
+ GtkWidget *menu;
+ GtkWidget *submenu;
+ GtkWidget *menuitem;
+ const char *menu_filename;
+ gboolean id_lists_writable;
+
+ id_lists_writable = panel_profile_id_lists_are_writable ();
+
+ entry = g_object_get_data (G_OBJECT (item), "panel-menu-tree-entry");
+ if (!entry)
+ return NULL;
+
+ directory = matemenu_tree_item_get_parent (MATEMENU_TREE_ITEM (entry));
+ if (!directory)
+ return NULL;
+
+ tree = matemenu_tree_directory_get_tree (directory);
+ matemenu_tree_item_unref (directory);
+ if (!tree)
+ return NULL;
+
+ menu_filename = matemenu_tree_get_menu_file (tree);
+ matemenu_tree_unref (tree);
+ if (!menu_filename)
+ return NULL;
+
+ menu = create_empty_menu ();
+ g_object_set_data (G_OBJECT (item), "panel-item-context-menu", menu);
+ g_object_set_data (G_OBJECT (menu), "menu_panel", panel_widget);
+
+ g_signal_connect (item, "destroy",
+ G_CALLBACK (menu_destroy_context_menu), menu);
+ g_signal_connect (menu, "deactivate",
+ G_CALLBACK (restore_grabs), item);
+
+ menuitem = gtk_menu_item_new_with_mnemonic (_("Add this launcher to _panel"));
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (add_app_to_panel), entry);
+ gtk_widget_set_sensitive (menuitem, id_lists_writable);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_mnemonic (_("Add this launcher to _desktop"));
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (add_app_to_desktop), entry);
+ gtk_widget_set_sensitive (menuitem, id_lists_writable);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show (menuitem);
+
+
+ submenu = create_empty_menu ();
+
+ g_object_set_data (G_OBJECT (submenu), "menu_panel", panel_widget);
+
+ menuitem = gtk_menu_item_new_with_mnemonic (_("_Entire menu"));
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_mnemonic (_("Add this as _drawer to panel"));
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (add_menudrawer_to_panel), entry);
+ gtk_widget_set_sensitive (menuitem, id_lists_writable);
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_mnemonic (_("Add this as _menu to panel"));
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (add_menu_to_panel), entry);
+ gtk_widget_set_sensitive (menuitem, id_lists_writable);
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
+ gtk_widget_show (menuitem);
+
+ return menu;
+}
+
+static gboolean
+show_item_menu (GtkWidget *item,
+ GdkEventButton *bevent)
+{
+ PanelWidget *panel_widget;
+ GtkWidget *menu;
+
+ if (panel_lockdown_get_locked_down ())
+ return FALSE;
+
+ panel_widget = menu_get_panel (item);
+
+ menu = g_object_get_data (G_OBJECT (item), "panel-item-context-menu");
+
+ if (!menu)
+ menu = create_item_context_menu (item, panel_widget);
+
+ if (!menu)
+ return FALSE;
+
+ gtk_menu_set_screen (GTK_MENU (menu),
+ gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel)));
+
+ gtk_menu_popup (GTK_MENU (menu),
+ NULL, NULL, NULL, NULL,
+ bevent->button,
+ bevent->time);
+
+ return TRUE;
+}
+
+gboolean
+menu_dummy_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ if (event->button == 3)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+menuitem_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ if (event->button == 3)
+ return show_item_menu (menuitem, event);
+
+ return FALSE;
+}
+
+static void
+drag_begin_menu_cb (GtkWidget *widget, GdkDragContext *context)
+{
+ /* FIXME: workaround for a possible gtk+ bug
+ * See bugs #92085(gtk+) and #91184(panel) for details.
+ * Maybe it's not needed with GtkTooltip?
+ */
+ g_object_set (widget, "has-tooltip", FALSE, NULL);
+}
+
+/* This is a _horrible_ hack to have this here. This needs to be added to the
+ * GTK+ menuing code in some manner.
+ */
+static void
+drag_end_menu_cb (GtkWidget *widget, GdkDragContext *context)
+{
+ GtkWidget *xgrab_shell;
+ GtkWidget *parent;
+
+ /* Find the last viewable ancestor, and make an X grab on it
+ */
+ parent = gtk_widget_get_parent (widget);
+ xgrab_shell = NULL;
+
+ /* FIXME: workaround for a possible gtk+ bug
+ * See bugs #92085(gtk+) and #91184(panel) for details.
+ */
+ g_object_set (widget, "has-tooltip", TRUE, NULL);
+
+ while (parent)
+ {
+ gboolean viewable = TRUE;
+ GtkWidget *tmp = parent;
+
+ while (tmp)
+ {
+ if (!gtk_widget_get_mapped (tmp))
+ {
+ viewable = FALSE;
+ break;
+ }
+ tmp = gtk_widget_get_parent (tmp);
+ }
+
+ if (viewable)
+ xgrab_shell = parent;
+
+ parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
+ }
+
+ if (xgrab_shell && !gtk_menu_get_tearoff_state (GTK_MENU(xgrab_shell)))
+ {
+ GdkWindow *window = gtk_widget_get_window (xgrab_shell);
+ GdkCursor *cursor = gdk_cursor_new (GDK_ARROW);
+
+ if ((gdk_pointer_grab (window, TRUE,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK,
+ NULL, cursor, GDK_CURRENT_TIME) == 0))
+ {
+ if (gdk_keyboard_grab (window, TRUE,
+ GDK_CURRENT_TIME) == 0)
+ GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
+ else
+ {
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ }
+ }
+
+ gdk_cursor_unref (cursor);
+ }
+}
+
+static void
+drag_data_get_menu_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ MateMenuTreeEntry *entry)
+{
+ const char *path;
+ char *uri;
+ char *uri_list;
+
+ path = matemenu_tree_entry_get_desktop_file_path (entry);
+ uri = g_filename_to_uri (path, NULL, NULL);
+ uri_list = g_strconcat (uri, "\r\n", NULL);
+ g_free (uri);
+
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8, (guchar *)uri_list,
+ strlen (uri_list));
+ g_free (uri_list);
+}
+
+static void
+image_menuitem_size_request (GtkWidget *menuitem,
+ GtkRequisition *requisition,
+ gpointer data)
+{
+ GtkIconSize icon_size = (GtkIconSize) GPOINTER_TO_INT (data);
+ int icon_height;
+ int req_height;
+
+ if (!gtk_icon_size_lookup (icon_size, NULL, &icon_height))
+ return;
+
+ /* If we don't have a pixmap for this menuitem
+ * at least make sure its the same height as
+ * the rest.
+ * This is a bit ugly, since we should keep this in sync with what's in
+ * gtk_menu_item_size_request()
+ */
+ req_height = icon_height;
+ req_height += (gtk_container_get_border_width (GTK_CONTAINER (menuitem)) +
+ (gtk_widget_get_style (menuitem))->ythickness) * 2;
+ requisition->height = MAX (requisition->height, req_height);
+}
+
+static char *
+menu_escape_underscores_and_prepend (const char *text)
+{
+ GString *escaped_text;
+ const char *src;
+ int inserted;
+
+ if (!text)
+ return g_strdup (text);
+
+ escaped_text = g_string_sized_new (strlen (text) + 1);
+ g_string_printf (escaped_text, "_%s", text);
+
+ src = text;
+ inserted = 1;
+
+ while (*src) {
+ gunichar c;
+
+ c = g_utf8_get_char (src);
+
+ if (c == (gunichar)-1) {
+ g_warning ("Invalid input string for underscore escaping");
+ return g_strdup (text);
+ } else if (c == '_') {
+ g_string_insert_c (escaped_text,
+ src - text + inserted, '_');
+ inserted++;
+ }
+
+ src = g_utf8_next_char (src);
+ }
+
+ return g_string_free (escaped_text, FALSE);
+}
+
+void
+setup_menuitem (GtkWidget *menuitem,
+ GtkIconSize icon_size,
+ GtkWidget *image,
+ const char *title)
+
+{
+ GtkWidget *label;
+ char *_title;
+
+ /* this creates a label with an invisible mnemonic */
+ label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
+ _title = menu_escape_underscores_and_prepend (title);
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _title);
+ g_free (_title);
+
+ gtk_label_set_pattern (GTK_LABEL (label), "");
+
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), menuitem);
+
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_widget_show (label);
+
+ gtk_container_add (GTK_CONTAINER (menuitem), label);
+
+ if (image) {
+ g_object_set_data_full (G_OBJECT (menuitem),
+ "Panel:Image",
+ g_object_ref (image),
+ (GDestroyNotify) g_object_unref);
+ gtk_widget_show (image);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
+ image);
+ } else if (icon_size != GTK_ICON_SIZE_INVALID)
+ g_signal_connect (menuitem, "size_request",
+ G_CALLBACK (image_menuitem_size_request),
+ GINT_TO_POINTER (icon_size));
+
+ gtk_widget_show (menuitem);
+}
+
+static void
+drag_data_get_string_cb (GtkWidget *widget, GdkDragContext *context,
+ GtkSelectionData *selection_data, guint info,
+ guint time, const char *string)
+{
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8, (guchar *)string,
+ strlen(string));
+}
+
+void
+setup_uri_drag (GtkWidget *menuitem,
+ const char *uri,
+ const char *icon)
+{
+ static GtkTargetEntry menu_item_targets[] = {
+ { "text/uri-list", 0, 0 }
+ };
+
+ if (panel_lockdown_get_locked_down ())
+ return;
+
+ gtk_drag_source_set (menuitem,
+ GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
+ menu_item_targets, 1,
+ GDK_ACTION_COPY);
+
+ if (icon != NULL)
+ gtk_drag_source_set_icon_name (menuitem, icon);
+
+ g_signal_connect (G_OBJECT (menuitem), "drag_begin",
+ G_CALLBACK (drag_begin_menu_cb), NULL);
+ g_signal_connect_data (G_OBJECT (menuitem), "drag_data_get",
+ G_CALLBACK (drag_data_get_string_cb),
+ g_strdup (uri),
+ (GClosureNotify)g_free,
+ 0 /* connect_flags */);
+ g_signal_connect (G_OBJECT (menuitem), "drag_end",
+ G_CALLBACK (drag_end_menu_cb), NULL);
+}
+
+void
+setup_internal_applet_drag (GtkWidget *menuitem,
+ PanelActionButtonType type)
+{
+ static GtkTargetEntry menu_item_targets[] = {
+ { "application/x-mate-panel-applet-internal", 0, 0 }
+ };
+
+ if (panel_lockdown_get_locked_down ())
+ return;
+
+ gtk_drag_source_set (menuitem,
+ GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
+ menu_item_targets, 1,
+ GDK_ACTION_COPY);
+
+ if (panel_action_get_icon_name (type) != NULL)
+ gtk_drag_source_set_icon_name (menuitem,
+ panel_action_get_icon_name (type));
+
+ g_signal_connect (G_OBJECT (menuitem), "drag_begin",
+ G_CALLBACK (drag_begin_menu_cb), NULL);
+ g_signal_connect_data (G_OBJECT (menuitem), "drag_data_get",
+ G_CALLBACK (drag_data_get_string_cb),
+ g_strdup (panel_action_get_drag_id (type)),
+ (GClosureNotify)g_free,
+ 0 /* connect_flags */);
+ g_signal_connect (G_OBJECT (menuitem), "drag_end",
+ G_CALLBACK (drag_end_menu_cb), NULL);
+}
+
+static void
+submenu_to_display (GtkWidget *menu)
+{
+ MateMenuTree *tree;
+ MateMenuTreeDirectory *directory;
+ const char *menu_path;
+ void (*append_callback) (GtkWidget *, gpointer);
+ gpointer append_data;
+
+ if (!g_object_get_data (G_OBJECT (menu), "panel-menu-needs-loading"))
+ return;
+
+ g_object_set_data (G_OBJECT (menu), "panel-menu-needs-loading", NULL);
+
+ directory = g_object_get_data (G_OBJECT (menu),
+ "panel-menu-tree-directory");
+ if (!directory) {
+ menu_path = g_object_get_data (G_OBJECT (menu),
+ "panel-menu-tree-path");
+ if (!menu_path)
+ return;
+
+ tree = g_object_get_data (G_OBJECT (menu), "panel-menu-tree");
+ if (!tree)
+ return;
+
+ directory = matemenu_tree_get_directory_from_path (tree,
+ menu_path);
+
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-tree-directory",
+ directory,
+ (GDestroyNotify) matemenu_tree_item_unref);
+ }
+
+ if (directory)
+ populate_menu_from_directory (menu, directory);
+
+ append_callback = g_object_get_data (G_OBJECT (menu),
+ "panel-menu-append-callback");
+ append_data = g_object_get_data (G_OBJECT (menu),
+ "panel-menu-append-callback-data");
+ if (append_callback)
+ append_callback (menu, append_data);
+}
+
+static gboolean
+submenu_to_display_in_idle (gpointer data)
+{
+ GtkWidget *menu = GTK_WIDGET (data);
+
+ g_object_set_data (G_OBJECT (menu), "panel-menu-idle-id", NULL);
+
+ submenu_to_display (menu);
+
+ return FALSE;
+}
+
+static void
+remove_submenu_to_display_idle (gpointer data)
+{
+ guint idle_id = GPOINTER_TO_UINT (data);
+
+ g_source_remove (idle_id);
+}
+
+static GtkWidget *
+create_fake_menu (MateMenuTreeDirectory *directory)
+{
+ GtkWidget *menu;
+ guint idle_id;
+
+ menu = create_empty_menu ();
+
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-tree-directory",
+ matemenu_tree_item_ref (directory),
+ (GDestroyNotify) matemenu_tree_item_unref);
+
+ g_object_set_data (G_OBJECT (menu),
+ "panel-menu-needs-loading",
+ GUINT_TO_POINTER (TRUE));
+
+ g_signal_connect (menu, "show",
+ G_CALLBACK (submenu_to_display), NULL);
+
+ idle_id = g_idle_add_full (G_PRIORITY_LOW,
+ submenu_to_display_in_idle,
+ menu,
+ NULL);
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-idle-id",
+ GUINT_TO_POINTER (idle_id),
+ remove_submenu_to_display_idle);
+
+ g_signal_connect (menu, "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+
+ return menu;
+}
+
+GtkWidget *
+panel_image_menu_item_new (void)
+{
+ GtkWidget *menuitem;
+
+ menuitem = gtk_image_menu_item_new ();
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem),
+ TRUE);
+ return menuitem;
+}
+
+static GtkWidget *
+create_submenu_entry (GtkWidget *menu,
+ MateMenuTreeDirectory *directory)
+{
+ GtkWidget *menuitem;
+ gboolean force_categories_icon;
+
+ force_categories_icon = g_object_get_data (G_OBJECT (menu),
+ "panel-menu-force-icon-for-categories") != NULL;
+
+ if (force_categories_icon)
+ menuitem = panel_image_menu_item_new ();
+ else
+ menuitem = gtk_image_menu_item_new ();
+
+ panel_load_menu_image_deferred (menuitem,
+ panel_menu_icon_get_size (),
+ NULL, NULL,
+ matemenu_tree_directory_get_icon (directory),
+ PANEL_ICON_FOLDER);
+
+ setup_menuitem (menuitem,
+ panel_menu_icon_get_size (),
+ NULL,
+ matemenu_tree_directory_get_name (directory));
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+
+ gtk_widget_show (menuitem);
+
+ return menuitem;
+}
+
+static void
+create_submenu (GtkWidget *menu,
+ MateMenuTreeDirectory *directory,
+ MateMenuTreeDirectory *alias_directory)
+{
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+ gboolean force_categories_icon;
+
+ if (alias_directory)
+ menuitem = create_submenu_entry (menu, alias_directory);
+ else
+ menuitem = create_submenu_entry (menu, directory);
+
+ submenu = create_fake_menu (directory);
+
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+
+ /* Keep the infor that we force (or not) the icons to be visible */
+ force_categories_icon = g_object_get_data (G_OBJECT (menu),
+ "panel-menu-force-icon-for-categories") != NULL;
+ g_object_set_data (G_OBJECT (submenu),
+ "panel-menu-force-icon-for-categories",
+ GINT_TO_POINTER (force_categories_icon));
+}
+
+static void
+create_header (GtkWidget *menu,
+ MateMenuTreeHeader *header)
+{
+ MateMenuTreeDirectory *directory;
+ GtkWidget *menuitem;
+
+ directory = matemenu_tree_header_get_directory (header);
+ menuitem = create_submenu_entry (menu, directory);
+ matemenu_tree_item_unref (directory);
+
+ g_object_set_data_full (G_OBJECT (menuitem),
+ "panel-matemenu-tree.header",
+ matemenu_tree_item_ref (header),
+ (GDestroyNotify) matemenu_tree_item_unref);
+
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (gtk_false), NULL);
+}
+
+static void
+create_menuitem (GtkWidget *menu,
+ MateMenuTreeEntry *entry,
+ MateMenuTreeDirectory *alias_directory)
+{
+ GtkWidget *menuitem;
+
+ menuitem = panel_image_menu_item_new ();
+
+ g_object_set_data_full (G_OBJECT (menuitem),
+ "panel-menu-tree-entry",
+ matemenu_tree_item_ref (entry),
+ (GDestroyNotify) matemenu_tree_item_unref);
+
+ if (alias_directory)
+ //FIXME: we should probably use this data when we do dnd or
+ //context menu for this menu item
+ g_object_set_data_full (G_OBJECT (menuitem),
+ "panel-menu-tree-alias-directory",
+ matemenu_tree_item_ref (alias_directory),
+ (GDestroyNotify) matemenu_tree_item_unref);
+
+ panel_load_menu_image_deferred (menuitem,
+ panel_menu_icon_get_size (),
+ NULL, NULL,
+ alias_directory ? matemenu_tree_directory_get_icon (alias_directory) :
+ matemenu_tree_entry_get_icon (entry),
+ NULL);
+
+ setup_menuitem (menuitem,
+ panel_menu_icon_get_size (),
+ NULL,
+ alias_directory ? matemenu_tree_directory_get_name (alias_directory) :
+ matemenu_tree_entry_get_display_name (entry));
+
+ if (alias_directory &&
+ matemenu_tree_directory_get_comment (alias_directory))
+ panel_util_set_tooltip_text (menuitem,
+ matemenu_tree_directory_get_comment (alias_directory));
+ else if (!alias_directory &&
+ matemenu_tree_entry_get_comment (entry))
+ panel_util_set_tooltip_text (menuitem,
+ matemenu_tree_entry_get_comment (entry));
+ else if (!alias_directory &&
+ matemenu_tree_entry_get_generic_name (entry))
+ panel_util_set_tooltip_text (menuitem,
+ matemenu_tree_entry_get_generic_name (entry));
+
+ g_signal_connect_after (menuitem, "button_press_event",
+ G_CALLBACK (menuitem_button_press_event), NULL);
+
+ if (!panel_lockdown_get_locked_down ()) {
+ static GtkTargetEntry menu_item_targets[] = {
+ { "text/uri-list", 0, 0 }
+ };
+
+ gtk_drag_source_set (menuitem,
+ GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+ menu_item_targets, 1,
+ GDK_ACTION_COPY);
+
+ if (matemenu_tree_entry_get_icon (entry) != NULL) {
+ const char *icon;
+ char *icon_no_ext;
+
+ icon = matemenu_tree_entry_get_icon (entry);
+ if (!g_path_is_absolute (icon)) {
+ icon_no_ext = panel_xdg_icon_remove_extension (icon);
+ gtk_drag_source_set_icon_name (menuitem,
+ icon_no_ext);
+ g_free (icon_no_ext);
+ }
+ }
+
+ g_signal_connect (G_OBJECT (menuitem), "drag_begin",
+ G_CALLBACK (drag_begin_menu_cb), NULL);
+ g_signal_connect (menuitem, "drag_data_get",
+ G_CALLBACK (drag_data_get_menu_cb), entry);
+ g_signal_connect (menuitem, "drag_end",
+ G_CALLBACK (drag_end_menu_cb), NULL);
+ }
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (activate_app_def), entry);
+
+ gtk_widget_show (menuitem);
+}
+
+static void
+create_menuitem_from_alias (GtkWidget *menu,
+ MateMenuTreeAlias *alias)
+{
+ MateMenuTreeItem *aliased_item;
+
+ aliased_item = matemenu_tree_alias_get_item (alias);
+
+ switch (matemenu_tree_item_get_type (aliased_item)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ create_submenu (menu,
+ MATEMENU_TREE_DIRECTORY (aliased_item),
+ matemenu_tree_alias_get_directory (alias));
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ create_menuitem (menu,
+ MATEMENU_TREE_ENTRY (aliased_item),
+ matemenu_tree_alias_get_directory (alias));
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (aliased_item);
+}
+
+static void
+handle_matemenu_tree_changed (MateMenuTree *tree,
+ GtkWidget *menu)
+{
+ guint idle_id;
+
+ while (GTK_MENU_SHELL (menu)->children)
+ gtk_widget_destroy (GTK_MENU_SHELL (menu)->children->data);
+
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-tree-directory",
+ NULL, NULL);
+
+ g_object_set_data (G_OBJECT (menu),
+ "panel-menu-needs-loading",
+ GUINT_TO_POINTER (TRUE));
+
+ idle_id = g_idle_add_full (G_PRIORITY_LOW,
+ submenu_to_display_in_idle,
+ menu,
+ NULL);
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-idle-id",
+ GUINT_TO_POINTER (idle_id),
+ remove_submenu_to_display_idle);
+}
+
+static void
+remove_matemenu_tree_monitor (GtkWidget *menu,
+ MateMenuTree *tree)
+{
+ matemenu_tree_remove_monitor (tree,
+ (MateMenuTreeChangedFunc) handle_matemenu_tree_changed,
+ menu);
+}
+
+GtkWidget *
+create_applications_menu (const char *menu_file,
+ const char *menu_path,
+ gboolean always_show_image)
+{
+ MateMenuTree *tree;
+ GtkWidget *menu;
+ guint idle_id;
+
+ menu = create_empty_menu ();
+
+ if (always_show_image)
+ g_object_set_data (G_OBJECT (menu),
+ "panel-menu-force-icon-for-categories",
+ GINT_TO_POINTER (TRUE));
+
+ tree = matemenu_tree_lookup (menu_file, MATEMENU_TREE_FLAGS_NONE);
+ matemenu_tree_set_sort_key (tree, MATEMENU_TREE_SORT_DISPLAY_NAME);
+
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-tree",
+ matemenu_tree_ref (tree),
+ (GDestroyNotify) matemenu_tree_unref);
+
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-tree-path",
+ g_strdup (menu_path ? menu_path : "/"),
+ (GDestroyNotify) g_free);
+
+ g_object_set_data (G_OBJECT (menu),
+ "panel-menu-needs-loading",
+ GUINT_TO_POINTER (TRUE));
+
+ g_signal_connect (menu, "show",
+ G_CALLBACK (submenu_to_display), NULL);
+
+ idle_id = g_idle_add_full (G_PRIORITY_LOW,
+ submenu_to_display_in_idle,
+ menu,
+ NULL);
+ g_object_set_data_full (G_OBJECT (menu),
+ "panel-menu-idle-id",
+ GUINT_TO_POINTER (idle_id),
+ remove_submenu_to_display_idle);
+
+ g_signal_connect (menu, "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+
+ matemenu_tree_add_monitor (tree,
+ (MateMenuTreeChangedFunc) handle_matemenu_tree_changed,
+ menu);
+ g_signal_connect (menu, "destroy",
+ G_CALLBACK (remove_matemenu_tree_monitor), tree);
+
+ matemenu_tree_unref (tree);
+
+ return menu;
+}
+
+static GtkWidget *
+populate_menu_from_directory (GtkWidget *menu,
+ MateMenuTreeDirectory *directory)
+{
+ GList *children;
+ GSList *l;
+ GSList *items;
+ gboolean add_separator;
+
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ add_separator = (children != NULL);
+ g_list_free (children);
+
+ items = matemenu_tree_directory_get_contents (directory);
+
+ for (l = items; l; l = l->next) {
+ MateMenuTreeItem *item = l->data;
+
+ if (add_separator ||
+ matemenu_tree_item_get_type (item) == MATEMENU_TREE_ITEM_SEPARATOR) {
+ add_menu_separator (menu);
+ add_separator = FALSE;
+ }
+
+ switch (matemenu_tree_item_get_type (item)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ create_submenu (menu, MATEMENU_TREE_DIRECTORY (item), NULL);
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ create_menuitem (menu, MATEMENU_TREE_ENTRY (item), NULL);
+ break;
+
+ case MATEMENU_TREE_ITEM_SEPARATOR :
+ /* already added */
+ break;
+
+ case MATEMENU_TREE_ITEM_ALIAS:
+ create_menuitem_from_alias (menu, MATEMENU_TREE_ALIAS (item));
+ break;
+
+ case MATEMENU_TREE_ITEM_HEADER:
+ create_header (menu, MATEMENU_TREE_HEADER (item));
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (item);
+ }
+
+ g_slist_free (items);
+
+ return menu;
+}
+
+void
+setup_menu_item_with_icon (GtkWidget *item,
+ GtkIconSize icon_size,
+ const char *icon_name,
+ const char *stock_id,
+ GIcon *gicon,
+ const char *title)
+{
+ if (icon_name || gicon || stock_id)
+ panel_load_menu_image_deferred (item, icon_size,
+ stock_id, gicon,
+ icon_name, NULL);
+
+ setup_menuitem (item, icon_size, NULL, title);
+}
+
+static void
+main_menu_append (GtkWidget *main_menu,
+ gpointer data)
+{
+ PanelWidget *panel;
+ GtkWidget *item;
+ gboolean add_separator;
+ GList *children;
+ GList *last;
+
+ panel = PANEL_WIDGET (data);
+
+ add_separator = FALSE;
+ children = gtk_container_get_children (GTK_CONTAINER (main_menu));
+ last = g_list_last (children);
+ if (last != NULL) {
+ add_separator = !GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
+ }
+ g_list_free (children);
+
+ if (add_separator)
+ add_menu_separator (main_menu);
+
+ item = panel_place_menu_item_new (TRUE);
+ panel_place_menu_item_set_panel (item, panel);
+ gtk_menu_shell_append (GTK_MENU_SHELL (main_menu), item);
+ gtk_widget_show (item);
+
+ item = panel_desktop_menu_item_new (TRUE, FALSE);
+ panel_desktop_menu_item_set_panel (item, panel);
+ gtk_menu_shell_append (GTK_MENU_SHELL (main_menu), item);
+ gtk_widget_show (item);
+
+ panel_menu_items_append_lock_logout (main_menu);
+}
+
+GtkWidget* create_main_menu(PanelWidget* panel)
+{
+ GtkWidget* main_menu;
+
+ main_menu = create_applications_menu("mate-applications.menu", NULL, TRUE);
+
+ g_object_set_data(G_OBJECT(main_menu), "menu_panel", panel);
+ /* FIXME need to update the panel on parent_set */
+
+ g_object_set_data(G_OBJECT(main_menu), "panel-menu-append-callback", main_menu_append);
+ g_object_set_data(G_OBJECT(main_menu), "panel-menu-append-callback-data", panel);
+
+ return main_menu;
+}
+
+static GList *
+find_in_load_list (GtkWidget *image)
+{
+ GList *li;
+ for (li = icons_to_load; li != NULL; li = li->next) {
+ IconToLoad *icon = li->data;
+ if (icon->pixmap == image)
+ return li;
+ }
+ return NULL;
+}
+
+static void
+image_menu_shown (GtkWidget *image, gpointer data)
+{
+ IconToLoad *new_icon;
+ IconToLoad *icon;
+
+ icon = (IconToLoad *) data;
+
+ /* if we've already handled this */
+ if (gtk_image_get_storage_type (GTK_IMAGE (image)) != GTK_IMAGE_EMPTY)
+ return;
+
+ if (find_in_load_list (image) == NULL) {
+ new_icon = icon_to_load_copy (icon);
+ new_icon->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (image));
+ icons_to_load = g_list_append (icons_to_load, new_icon);
+ }
+ if (load_icons_id == 0)
+ load_icons_id = g_idle_add (load_icons_handler, NULL);
+}
+
+static void
+image_menu_destroy (GtkWidget *image, gpointer data)
+{
+ image_menu_items = g_slist_remove (image_menu_items, image);
+}
+
+static void
+panel_load_menu_image_deferred (GtkWidget *image_menu_item,
+ GtkIconSize icon_size,
+ const char *stock_id,
+ GIcon *gicon,
+ const char *image_filename,
+ const char *fallback_image_filename)
+{
+ IconToLoad *icon;
+ GtkWidget *image;
+ int icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
+
+ icon = g_new (IconToLoad, 1);
+
+ gtk_icon_size_lookup (icon_size, NULL, &icon_height);
+
+ image = gtk_image_new ();
+ gtk_widget_set_size_request (image, icon_height, icon_height);
+
+ /* this takes over the floating ref */
+ icon->pixmap = g_object_ref_sink (G_OBJECT (image));
+
+ icon->stock_id = stock_id;
+ if (gicon)
+ icon->gicon = g_object_ref (gicon);
+ else
+ icon->gicon = NULL;
+ icon->image = g_strdup (image_filename);
+ icon->fallback_image = g_strdup (fallback_image_filename);
+ icon->icon_size = icon_size;
+
+ gtk_widget_show (image);
+
+ g_object_set_data_full (G_OBJECT (image_menu_item),
+ "Panel:Image",
+ g_object_ref (image),
+ (GDestroyNotify) g_object_unref);
+
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (image_menu_item),
+ image);
+
+ g_signal_connect_data (image, "map",
+ G_CALLBACK (image_menu_shown), icon,
+ (GClosureNotify) icon_to_load_free, 0);
+
+ g_signal_connect (image, "destroy",
+ G_CALLBACK (image_menu_destroy), NULL);
+
+ image_menu_items = g_slist_prepend (image_menu_items, image);
+}
+
+static gboolean
+panel_menu_key_press_handler (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ gboolean retval = FALSE;
+
+ if ((event->keyval == GDK_Menu) ||
+ (event->keyval == GDK_F10 &&
+ (event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK)) {
+ GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
+
+ if (menu_shell->active_menu_item &&
+ GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL) {
+ GdkEventButton bevent;
+
+ bevent.button = 3;
+ bevent.time = GDK_CURRENT_TIME;
+ retval = show_item_menu (menu_shell->active_menu_item,
+ &bevent);
+ }
+
+ }
+ return retval;
+}
diff --git a/mate-panel/menu.h b/mate-panel/menu.h
new file mode 100644
index 00000000..8638cbb8
--- /dev/null
+++ b/mate-panel/menu.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 1997 - 2000 The Free Software Foundation
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 2000 Eazel, Inc.
+ * Copyright (C) 2004 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 __MENU_H__
+#define __MENU_H__
+
+#include "panel-widget.h"
+#include "applet.h"
+#include <matemenu-tree.h>
+#include <gio/gio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void setup_menuitem (GtkWidget *menuitem,
+ GtkIconSize icon_size,
+ GtkWidget *pixmap,
+ const char *title);
+void setup_menu_item_with_icon (GtkWidget *item,
+ GtkIconSize icon_size,
+ const char *icon_name,
+ const char *stock_id,
+ GIcon *gicon,
+ const char *title);
+
+GtkWidget *create_empty_menu (void);
+GtkWidget *create_applications_menu (const char *menu_file,
+ const char *menu_path,
+ gboolean always_show_image);
+GtkWidget *create_main_menu (PanelWidget *panel);
+
+void setup_internal_applet_drag (GtkWidget *menuitem,
+ PanelActionButtonType type);
+void setup_uri_drag (GtkWidget *menuitem,
+ const char *uri,
+ const char *icon);
+
+GtkWidget * panel_create_menu (void);
+
+GtkWidget * panel_image_menu_item_new (void);
+
+GdkPixbuf * panel_make_menu_icon (GtkIconTheme *icon_theme,
+ const char *icon,
+ const char *fallback,
+ int size,
+ gboolean *long_operation);
+
+GdkScreen *menuitem_to_screen (GtkWidget *menuitem);
+PanelWidget *menu_get_panel (GtkWidget *menu);
+GtkWidget *add_menu_separator (GtkWidget *menu);
+
+gboolean menu_dummy_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MENU_H__ */
diff --git a/mate-panel/nothing.cP b/mate-panel/nothing.cP
new file mode 100644
index 00000000..4ce1f246
--- /dev/null
+++ b/mate-panel/nothing.cP
@@ -0,0 +1,1568 @@
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <cairo.h>
+#include <gdk/gdkkeysyms.h>
+#include <canberra-gtk.h>
+
+#ifdef CA_CHECK_VERSION
+#if CA_CHECK_VERSION(0, 13)
+#define HAVE_CANBERRA_GTK_MULTIHEAD_SAFE
+#endif
+#endif
+
+#include "panel-util.h"
+#include "nothing.h"
+
+static void
+pixbuf_reverse (GdkPixbuf *gp)
+{
+ guchar *pixels = gdk_pixbuf_get_pixels (gp);
+ int rs = gdk_pixbuf_get_rowstride (gp);
+ int w = gdk_pixbuf_get_width (gp);
+ int h = gdk_pixbuf_get_height (gp);
+ int x, y;
+#define DOSWAP(x,y) tmp = x; x = y; y = tmp;
+ for (y = 0; y < h; y++, pixels += rs) {
+ guchar *p = pixels;
+ guchar *p2 = pixels + w*4 - 4;
+ for (x = 0; x < w/2; x++, p+=4, p2-=4) {
+ guchar tmp;
+ DOSWAP (p[0], p2[0]);
+ DOSWAP (p[1], p2[1]);
+ DOSWAP (p[2], p2[2]);
+ DOSWAP (p[3], p2[3]);
+ }
+ }
+#undef DOSWAP
+}
+
+/* This unsea's the phsh */
+/*code snippet, not to be compiled separately*/
+static gboolean goat_loaded=FALSE;
+static int goat_frame=0;
+static GdkPixmap *goat_pix[2] = {NULL,NULL};
+static GdkPixmap *goat_pix_rev[2] = {NULL,NULL};
+static GtkWidget *goat_darea = NULL;
+static int goat_width = 0,goat_height = 0;
+static int goat_timeout = 0;
+static int goat_x = -1, goat_y = -1;
+static int goat_accx = -1, goat_accy = -1;
+
+static void
+destroy_egg(GtkWidget *widget, gpointer data)
+{
+ int i;
+ goat_loaded = FALSE;
+ if(goat_timeout) {
+ g_source_remove(goat_timeout);
+ goat_timeout = 0;
+ }
+ for (i = 0; i < 2; i++) {
+ if (goat_pix[i] != NULL)
+ g_object_unref (G_OBJECT (goat_pix[i]));
+ goat_pix[i] = NULL;
+ if (goat_pix_rev[i] != NULL)
+ g_object_unref (G_OBJECT (goat_pix_rev[i]));
+ goat_pix_rev[i] = NULL;
+ }
+ goat_x = goat_y = -1;
+}
+
+static int
+goat_timeout_func(gpointer data)
+{
+ GtkAllocation allocation;
+ cairo_t *cr;
+ int real_goat_frame;
+ gboolean sound = FALSE;
+ int old_x;
+ int old_y;
+
+ if(!gtk_widget_get_realized(goat_darea) ||
+ !gtk_widget_is_drawable(goat_darea))
+ return TRUE;
+
+ if (!goat_pix[0] || !goat_pix[1]) {
+ destroy_egg (NULL, NULL);
+ return FALSE;
+ }
+
+ gtk_widget_get_allocation (goat_darea, &allocation);
+ cr = gdk_cairo_create (gtk_widget_get_window (goat_darea));
+
+ if(goat_x == -1) {
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ goat_x = 2;
+ goat_y = 2;
+ goat_accx = g_random_int()%4 +3;
+ goat_accy = g_random_int()%4 +3;
+ }
+
+ old_x = goat_x;
+ old_y = goat_y;
+ goat_x += goat_accx;
+ goat_y += goat_accy;
+
+
+ if(goat_x>allocation.width-2-goat_width) {
+ goat_accx = -(g_random_int()%4 +3);
+ goat_x = allocation.width-2-goat_width;
+ sound = TRUE;
+ } else if(goat_x<2) {
+ goat_accx = g_random_int()%4 +3;
+ goat_x = 2;
+ sound = TRUE;
+ }
+ if(goat_y>allocation.height-2-goat_height) {
+ goat_accy = -(g_random_int()%4 +3);
+ goat_y = allocation.height-2-goat_height;
+ sound = TRUE;
+ } else if(goat_y<2) {
+ goat_accy = g_random_int()%4 +3;
+ goat_y = 2;
+ sound = TRUE;
+ }
+
+ if (sound) {
+#ifdef HAVE_CANBERRA_GTK_MULTIHEAD_SAFE
+ ca_context_cancel (ca_gtk_context_get_for_screen (gtk_widget_get_screen (goat_darea)), 42);
+#else
+ ca_context_cancel (ca_gtk_context_get (), 42);
+#endif
+ ca_gtk_play_for_widget (goat_darea, 42,
+ CA_PROP_EVENT_ID, "bell-window-system",
+ CA_PROP_EVENT_DESCRIPTION, "Ouch! This box is small!",
+ NULL);
+ }
+
+ real_goat_frame = goat_frame/2;
+
+ cairo_rectangle (cr, MIN(old_x, goat_x), MIN(old_y, goat_y),
+ goat_width + ABS(goat_x-old_x) + 6,
+ goat_height + ABS(goat_y-old_y) + 6);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ gdk_cairo_set_source_pixmap (cr,
+ goat_accx<0?goat_pix[real_goat_frame]:
+ goat_pix_rev[real_goat_frame],
+ goat_x,goat_y);
+
+ cairo_paint (cr);
+
+ if(++goat_frame == 4)
+ goat_frame = 0;
+
+ cairo_destroy (cr);
+
+ return TRUE;
+}
+
+static int
+goat_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+ cairo_t *cr;
+
+ if(!gtk_widget_is_drawable(widget))
+ return FALSE;
+
+ cr = gdk_cairo_create (gtk_widget_get_window (goat_darea));
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+static void
+goat_realize(GtkWidget *widget)
+{
+ GdkWindow *window;
+ int frame;
+ char *files[] = {
+ "mate-gegl2.png",
+ "mate-gegl2-2.png"
+ };
+ if(goat_pix[0])
+ return;
+ window = gtk_widget_get_window (widget);
+ for(frame=0;frame<2;frame++) {
+ GdkPixbuf *pb;
+ char *file;
+ int width;
+ int height;
+ cairo_t *cr;
+ cairo_matrix_t matrix;
+ cairo_pattern_t *pattern;
+
+ file = g_strdup_printf ("%s/%s", ICONDIR, files[frame]);
+ if(!file)
+ return;
+ pb=gdk_pixbuf_new_from_file (file, NULL);
+ g_free(file);
+
+ if(!pb) {
+ g_warning("Goat is not available!");
+ return;
+ }
+
+ width = gdk_pixbuf_get_width(pb);
+ height = gdk_pixbuf_get_height(pb);
+
+ goat_pix[frame] = gdk_pixmap_new(window,
+ width, height, -1);
+ cr = gdk_cairo_create (goat_pix[frame]);
+ gdk_cairo_set_source_pixbuf (cr, pb, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ goat_pix_rev[frame] = gdk_pixmap_new(window,
+ width, height, -1);
+ cr = gdk_cairo_create (goat_pix_rev[frame]);
+ gdk_cairo_set_source_pixbuf (cr, pb, 0, 0);
+
+ cairo_matrix_init_identity (&matrix);
+ cairo_matrix_translate (&matrix, width, 0);
+ /* scale in -X direction to flip along X */
+ cairo_matrix_scale (&matrix, -1.0, 1.0);
+ pattern = cairo_get_source (cr);
+ cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
+ cairo_pattern_set_matrix (pattern, &matrix);
+
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+
+ goat_width = MAX (width, goat_width);
+ goat_height = MAX (height, goat_height);
+
+ g_object_unref (pb);
+ }
+}
+
+/*thy evil easter egg*/
+int
+config_event(GtkWidget *widget,GdkEvent *event,GtkNotebook *nbook)
+{
+ static int clicks=0;
+ GdkEventButton *bevent;
+
+ if (!nbook)
+ return FALSE;
+
+ if(event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ bevent = (GdkEventButton *)event;
+ if(bevent->button != 3)
+ clicks = 0;
+ else
+ clicks++;
+
+ if(clicks<3)
+ return FALSE;
+ clicks = 0;
+
+ if(!goat_loaded) {
+ goat_darea = gtk_drawing_area_new();
+
+ g_signal_connect (G_OBJECT(goat_darea),"destroy",
+ G_CALLBACK (destroy_egg),NULL);
+ g_signal_connect (GTK_OBJECT(goat_darea),"expose_event",
+ G_CALLBACK (goat_expose),NULL);
+ g_signal_connect_after (G_OBJECT(goat_darea),"realize",
+ G_CALLBACK (goat_realize),NULL);
+
+ gtk_widget_show(goat_darea);
+ goat_timeout = g_timeout_add(60,goat_timeout_func,NULL);
+ /*the GEGL shall not be translated*/
+ g_object_set (G_OBJECT (nbook),
+ "show_tabs", TRUE,
+ "show_border", TRUE,
+ NULL);
+ gtk_notebook_append_page (nbook, goat_darea,
+ gtk_label_new ("GEGL"));
+ gtk_notebook_set_current_page(nbook,-1);
+ goat_loaded = TRUE;
+ } else {
+ gtk_notebook_set_current_page(nbook,-1);
+ }
+ return FALSE;
+}
+
+/* phish code */
+#define PHSHFRAMES 8
+#define PHSHORIGWIDTH 288
+#define PHSHORIGHEIGHT 22
+#define PHSHWIDTH (PHSHORIGWIDTH/PHSHFRAMES)
+#define PHSHHEIGHT PHSHORIGHEIGHT
+#define PHSHCHECKTIMEOUT (g_random_int()%120*1000)
+#define PHSHTIMEOUT 120
+#define PHSHHIDETIMEOUT 80
+#define PHSHXS 5
+#define PHSHYS ((g_random_int() % 2) + 1)
+#define PHSHXSHIDEFACTOR 2.5
+#define PHSHYSHIDEFACTOR 2.5
+#define PHSHPIXELSTOREMOVE(p) (p[3] < 55 || p[2] > 200)
+
+/* Some important code copied from PonG */
+typedef struct _AppletContainer AppletContainer;
+struct _AppletContainer {
+ GdkWindow *win;
+ gboolean hide_mode;
+ int state;
+ int x, y, xs, ys;
+ int handler;
+ GdkPixmap *phsh[2*PHSHFRAMES];
+ GdkBitmap *phsh_mask[2*PHSHFRAMES];
+};
+static AppletContainer phsh = {NULL};
+
+static void
+phsh_kill (void)
+{
+ int i;
+ for (i = 0; i < 2*PHSHFRAMES; i++) {
+ if (phsh.phsh[i] != NULL)
+ g_object_unref (G_OBJECT (phsh.phsh[i]));
+ phsh.phsh[i] = NULL;
+ if (phsh.phsh_mask[i] != NULL)
+ g_object_unref (G_OBJECT (phsh.phsh_mask[i]));
+ phsh.phsh_mask[i] = NULL;
+ }
+ gdk_window_destroy (phsh.win);
+ g_source_remove (phsh.handler);
+ memset (&phsh, 0, sizeof (AppletContainer));
+}
+
+static gboolean
+phsh_move (gpointer data)
+{
+ int orient, state;
+ gboolean change = TRUE;
+
+ phsh.x += phsh.xs;
+ phsh.y += phsh.ys;
+ if (phsh.x <= -PHSHWIDTH ||
+ phsh.x >= gdk_screen_width ()) {
+ phsh_kill ();
+ return FALSE;
+ }
+ if (phsh.y <= 0 ||
+ phsh.y >= gdk_screen_height () - PHSHHEIGHT ||
+ g_random_int() % (phsh.hide_mode?10:50) == 0)
+ phsh.ys = -phsh.ys;
+
+ phsh.state ++;
+ if (phsh.hide_mode) {
+ phsh.state ++;
+ if (phsh.state >= 2*PHSHFRAMES)
+ phsh.state = 0;
+ } else if (phsh.state >= PHSHFRAMES)
+ phsh.state = 0;
+
+ if (!phsh.hide_mode || phsh.state % 2 == 0)
+ change = TRUE;
+
+ state = phsh.state / (phsh.hide_mode?2:1);
+ orient = phsh.xs >= 0 ? 0 : 1;
+
+ if (change) {
+ gdk_window_set_back_pixmap (phsh.win, phsh.phsh[orient + 2*state], FALSE);
+ gdk_window_shape_combine_mask (phsh.win, phsh.phsh_mask[orient + 2*state], 0, 0);
+ gdk_window_clear (phsh.win);
+ }
+
+ gdk_window_move (phsh.win, phsh.x, phsh.y);
+ gdk_window_raise (phsh.win);
+
+ return TRUE;
+}
+
+static void
+phsh_unsea(GdkPixbuf *gp)
+{
+ guchar *pixels = gdk_pixbuf_get_pixels (gp);
+ int rs = gdk_pixbuf_get_rowstride (gp);
+ int w = gdk_pixbuf_get_width (gp);
+ int h = gdk_pixbuf_get_height (gp);
+ int x, y;
+
+ for (y = 0; y < h; y++, pixels += rs) {
+ guchar *p = pixels;
+ for (x = 0; x < w; x++, p+=4) {
+ if (PHSHPIXELSTOREMOVE(p))
+ p[3] = 0;
+ }
+ }
+}
+
+static GdkFilterReturn
+phsh_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
+{
+ XEvent *xevent = (XEvent *)gdk_xevent;
+
+ if (xevent->type == ButtonPress &&
+ ! phsh.hide_mode) {
+ g_source_remove (phsh.handler);
+ phsh.handler = g_timeout_add (PHSHHIDETIMEOUT, phsh_move, NULL);
+ phsh.xs *= PHSHXSHIDEFACTOR;
+ phsh.ys *= PHSHYSHIDEFACTOR;
+ phsh.hide_mode = TRUE;
+ if (phsh.x < (gdk_screen_width () / 2))
+ phsh.xs *= -1;
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+static char *
+get_phsh_file (void)
+{
+ char *phsh_file;
+
+ phsh_file = g_strdup_printf ("%s/%cand%c.png", ICONDIR, 'w', 'a');
+
+ return phsh_file;
+}
+
+static GdkPixbuf *
+get_phsh_frame (GdkPixbuf *pb, int frame)
+{
+ GdkPixbuf *newpb;
+
+ newpb = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ PHSHWIDTH, PHSHHEIGHT);
+ gdk_pixbuf_copy_area (pb, frame * PHSHWIDTH, 0,
+ PHSHWIDTH, PHSHHEIGHT, newpb, 0, 0);
+
+ return newpb;
+}
+
+/* this checks the screen */
+static void
+check_screen (void)
+{
+ GdkWindowAttr attributes;
+ char *phsh_file;
+ GdkPixbuf *gp, *tmp;
+ int i;
+
+ if (phsh.win != NULL)
+ return;
+
+ phsh_file = get_phsh_file ();
+
+ if (phsh_file == NULL)
+ return;
+
+ tmp = gdk_pixbuf_new_from_file (phsh_file, NULL);
+ if (tmp == NULL)
+ return;
+
+ g_free (phsh_file);
+
+ if (gdk_pixbuf_get_width (tmp) != PHSHORIGWIDTH ||
+ gdk_pixbuf_get_height (tmp) != PHSHORIGHEIGHT) {
+ g_object_unref (G_OBJECT (tmp));
+ return;
+ }
+
+ phsh.state = 0;
+ phsh.hide_mode = FALSE;
+ phsh.x = -PHSHWIDTH;
+ phsh.y = (g_random_int() % (gdk_screen_height() - PHSHHEIGHT - 2)) + 1;
+ phsh.xs = PHSHXS;
+ phsh.ys = PHSHYS;
+
+ for (i = 0; i < PHSHFRAMES; i++) {
+ gp = get_phsh_frame (tmp, i);
+ phsh_unsea (gp);
+ gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[2*i+1],
+ &phsh.phsh_mask[2*i+1], 128);
+ pixbuf_reverse (gp);
+ gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[2*i],
+ &phsh.phsh_mask[2*i], 128);
+ g_object_unref (G_OBJECT (gp));
+ }
+
+ g_object_unref (G_OBJECT (tmp));
+
+ attributes.window_type = GDK_WINDOW_TEMP;
+ attributes.x = phsh.x;
+ attributes.y = phsh.y;
+ attributes.width = PHSHWIDTH;
+ attributes.height = PHSHHEIGHT;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gdk_rgb_get_visual();
+ attributes.colormap = gdk_rgb_get_colormap();
+ attributes.event_mask = GDK_BUTTON_PRESS_MASK;
+
+ phsh.win = gdk_window_new (NULL, &attributes,
+ GDK_WA_X | GDK_WA_Y |
+ GDK_WA_VISUAL | GDK_WA_COLORMAP);
+ gdk_window_set_back_pixmap (phsh.win, phsh.phsh[0], FALSE);
+ gdk_window_shape_combine_mask (phsh.win, phsh.phsh_mask[0], 0, 0);
+
+ /* setup the keys filter */
+ gdk_window_add_filter (phsh.win,
+ phsh_filter,
+ NULL);
+
+ gdk_window_show (phsh.win);
+ phsh.handler = g_timeout_add (PHSHTIMEOUT, phsh_move, NULL);
+}
+
+static guint screen_check_id = 0;
+
+static gboolean
+check_screen_timeout (gpointer data)
+{
+ screen_check_id = 0;
+
+ check_screen ();
+
+ screen_check_id = g_timeout_add (PHSHCHECKTIMEOUT,
+ check_screen_timeout, NULL);
+ return FALSE;
+}
+
+void
+start_screen_check (void)
+{
+ if (screen_check_id > 0)
+ g_source_remove (screen_check_id);
+
+ check_screen_timeout (NULL);
+}
+
+typedef struct {
+ gboolean live;
+ int x, y;
+} InvGoat;
+
+typedef struct {
+ gboolean good;
+ int y;
+ int x;
+} InvShot;
+
+
+static GtkWidget *geginv = NULL;
+static GtkWidget *geginv_canvas = NULL;
+static GtkWidget *geginv_label = NULL;
+static GdkPixmap *geginv_pixmap = NULL;
+static GdkPixmap *inv_goat1 = NULL;
+static GdkPixmap *inv_goat2 = NULL;
+static GdkPixmap *inv_phsh1 = NULL;
+static GdkBitmap *inv_phsh1_mask = NULL;
+static GdkPixmap *inv_phsh2 = NULL;
+static GdkBitmap *inv_phsh2_mask = NULL;
+static int inv_phsh_state = 0;
+static int inv_goat_state = 0;
+static int inv_width = 0;
+static int inv_height = 0;
+static int inv_goat_width = 0;
+static int inv_goat_height = 0;
+static int inv_phsh_width = 0;
+static int inv_phsh_height = 0;
+#define INV_ROWS 3
+#define INV_COLS 5
+static InvGoat invs[INV_COLS][INV_ROWS] = { { { FALSE, 0, 0 } } };
+static int inv_num = INV_ROWS * INV_COLS;
+static double inv_factor = 1.0;
+static int inv_our_x = 0;
+static int inv_x = 0;
+static int inv_y = 0;
+static int inv_first_col = 0;
+static int inv_last_col = INV_COLS-1;
+static int inv_level = 0;
+static int inv_lives = 0;
+static gboolean inv_do_pause = FALSE;
+static gboolean inv_reverse = FALSE;
+static gboolean inv_game_over = FALSE;
+static gboolean inv_left_pressed = FALSE;
+static gboolean inv_right_pressed = FALSE;
+static gboolean inv_fire_pressed = FALSE;
+static gboolean inv_left_released = FALSE;
+static gboolean inv_right_released = FALSE;
+static gboolean inv_fire_released = FALSE;
+static gboolean inv_paused = FALSE;
+static GSList *inv_shots = NULL;
+static guint inv_draw_idle = 0;
+
+static void
+inv_show_status (void)
+{
+ gchar *s, *t, *u, *v, *w;
+ if (geginv == NULL)
+ return;
+
+ if (inv_game_over) {
+ t = g_strdup_printf (_("<b>GAME OVER</b> at level %d!"),
+ inv_level+1);
+ u = g_strdup_printf ("<big>%s</big>", t);
+ /* Translators: the first and third strings are similar to a
+ * title, and the second string is a small information text.
+ * The spaces are there only to separate all the strings, so
+ try to keep them as is. */
+ s = g_strdup_printf (_("%1$s %2$s %3$s"),
+ u, _("Press 'q' to quit"), u);
+ g_free (t);
+ g_free (u);
+
+ } else if (inv_paused) {
+ t = g_strdup_printf("<big><b>%s</b></big>", _("Paused"));
+ /* Translators: the first string is a title and the second
+ * string is a small information text. */
+ s = g_strdup_printf (_("%1$s\t%2$s"),
+ t, _("Press 'p' to unpause"));
+ g_free (t);
+
+ } else {
+ t = g_strdup_printf ("<b>%d</b>", inv_level+1);
+ u = g_strdup_printf ("<b>%d</b>", inv_lives);
+ v = g_strdup_printf (_("Level: %s, Lives: %s"), t, u);
+ w = g_strdup_printf ("<big>%s</big>", v);
+ /* Translators: the first string is a title and the second
+ * string is a small information text. */
+ s = g_strdup_printf (_("%1$s\t%2$s"), w,
+ _("Left/Right to move, Space to fire, 'p' to pause, 'q' to quit"));
+ g_free (t);
+ g_free (u);
+ g_free (v);
+ g_free (w);
+
+ }
+ gtk_label_set_markup (GTK_LABEL (geginv_label), s);
+
+ g_free (s);
+}
+
+static gboolean
+inv_draw (gpointer data)
+{
+ GtkStyle *style;
+ GdkPixmap *goat;
+ GSList *li;
+ int i, j;
+
+ if (data != geginv) {
+ inv_draw_idle = 0;
+ return FALSE;
+ }
+
+ if ( ! gtk_widget_is_drawable (geginv_canvas) ||
+ geginv_pixmap == NULL)
+ return TRUE;
+
+ style = gtk_widget_get_style (geginv_canvas);
+
+ gdk_draw_rectangle (geginv_pixmap,
+ style->white_gc,
+ TRUE /* filled */,
+ 0, 0,
+ inv_width, inv_height);
+
+ if (inv_goat_state == 0)
+ goat = inv_goat1;
+ else
+ goat = inv_goat2;
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ int x, y;
+ if ( ! invs[i][j].live)
+ continue;
+
+ x = invs[i][j].x*inv_factor - inv_goat_width/2,
+ y = invs[i][j].y*inv_factor - inv_goat_height/2,
+
+ gdk_draw_drawable (geginv_pixmap,
+ style->white_gc,
+ goat,
+ 0, 0,
+ x, y,
+ inv_goat_width,
+ inv_goat_height);
+ }
+ }
+
+ for (li = inv_shots; li != NULL; li = li->next) {
+ InvShot *shot = li->data;
+
+ gdk_draw_rectangle (geginv_pixmap,
+ style->black_gc,
+ TRUE /* filled */,
+ (shot->x-1)*inv_factor,
+ (shot->y-4)*inv_factor,
+ 3, 8);
+ }
+
+ if ( ! inv_game_over) {
+ GdkPixmap *phsh;
+ GdkBitmap *mask;
+
+ if (inv_phsh_state < 5) {
+ phsh = inv_phsh1;
+ mask = inv_phsh1_mask;
+ } else {
+ phsh = inv_phsh2;
+ mask = inv_phsh2_mask;
+ }
+
+ gdk_gc_set_clip_origin (style->white_gc,
+ inv_our_x*inv_factor - inv_phsh_width/2,
+ 550*inv_factor - inv_phsh_height/2);
+
+ gdk_gc_set_clip_mask (style->white_gc,
+ mask);
+
+ gdk_draw_drawable (geginv_pixmap,
+ style->white_gc,
+ phsh,
+ 0, 0,
+ inv_our_x*inv_factor - inv_phsh_width/2,
+ 550*inv_factor - inv_phsh_height/2,
+ inv_phsh_width,
+ inv_phsh_height);
+
+ gdk_gc_set_clip_origin (style->white_gc, 0, 0);
+
+ gdk_gc_set_clip_mask (style->white_gc, NULL);
+ }
+
+ gdk_draw_drawable (gtk_widget_get_window (geginv_canvas),
+ style->white_gc,
+ geginv_pixmap,
+ 0, 0,
+ 0, 0,
+ inv_width, inv_height);
+
+ gdk_flush ();
+
+ if (inv_do_pause) {
+ sleep (1);
+ inv_do_pause = FALSE;
+ }
+
+ inv_draw_idle = 0;
+ return FALSE;
+}
+
+static void
+inv_queue_draw (GtkWidget *window)
+{
+ if (inv_draw_idle == 0)
+ inv_draw_idle = g_idle_add (inv_draw, window);
+}
+
+static void
+inv_draw_explosion (int x, int y)
+{
+ GdkWindow *window;
+ GtkStyle *style;
+ int i;
+ GdkColormap *cmap;
+ GdkColor red;
+ GdkGC *gc;
+
+ if ( ! gtk_widget_is_drawable (geginv_canvas))
+ return;
+
+ window = gtk_widget_get_window (geginv_canvas);
+ style = gtk_widget_get_style (geginv_canvas);
+
+ cmap = gdk_drawable_get_colormap (window);
+ gdk_color_parse ("red", &red);
+ gdk_colormap_alloc_color (cmap, &red, FALSE, TRUE);
+
+ gc = gdk_gc_new (window);
+ gdk_gc_set_foreground (gc, &red);
+ gdk_gc_set_background (gc, &red);
+
+ for (i = 5; i < 100; i += 5) {
+ gdk_draw_arc (window,
+ gc,
+ TRUE /* filled */,
+ x-i, y-i,
+ i*2, i*2,
+ 0, 360*64);
+ gdk_flush ();
+ g_usleep (50000);
+ }
+
+ g_object_unref (G_OBJECT (gc));
+
+ for (i = 5; i < 100; i += 5) {
+ gdk_draw_arc (window,
+ style->white_gc,
+ TRUE /* filled */,
+ x-i, y-i,
+ i*2, i*2,
+ 0, 360*64);
+ gdk_flush ();
+ g_usleep (50000);
+ }
+
+ gdk_colormap_free_colors (cmap, &red, 1);
+
+ inv_queue_draw (geginv);
+}
+
+
+static void
+inv_do_game_over (void)
+{
+ GSList *li;
+
+ inv_game_over = TRUE;
+
+ for (li = inv_shots; li != NULL; li = li->next) {
+ InvShot *shot = li->data;
+ shot->good = FALSE;
+ }
+
+ inv_queue_draw (geginv);
+
+ inv_show_status ();
+}
+
+
+static GdkPixbuf *
+pb_scale (GdkPixbuf *pb, double scale)
+{
+ int w, h;
+
+ if (scale == 1.0)
+ return (GdkPixbuf *)g_object_ref ((GObject *)pb);
+
+ w = gdk_pixbuf_get_width (pb) * scale;
+ h = gdk_pixbuf_get_height (pb) * scale;
+
+ return gdk_pixbuf_scale_simple (pb, w, h,
+ GDK_INTERP_BILINEAR);
+}
+
+static void
+refind_first_and_last (void)
+{
+ int i, j;
+
+ for (i = 0; i < INV_COLS; i++) {
+ gboolean all_null = TRUE;
+ for (j = 0; j < INV_ROWS; j++) {
+ if (invs[i][j].live) {
+ all_null = FALSE;
+ break;
+ }
+ }
+ if ( ! all_null) {
+ inv_first_col = i;
+ break;
+ }
+ }
+
+ for (i = INV_COLS-1; i >= 0; i--) {
+ gboolean all_null = TRUE;
+ for (j = 0; j < INV_ROWS; j++) {
+ if (invs[i][j].live) {
+ all_null = FALSE;
+ break;
+ }
+ }
+ if ( ! all_null) {
+ inv_last_col = i;
+ break;
+ }
+ }
+}
+
+static void
+whack_gegl (int i, int j)
+{
+ if ( ! invs[i][j].live)
+ return;
+
+ invs[i][j].live = FALSE;
+ inv_num --;
+
+ if (inv_num > 0) {
+ refind_first_and_last ();
+ } else {
+ inv_x = 70;
+ inv_y = 70;
+ inv_first_col = 0;
+ inv_last_col = INV_COLS-1;
+ inv_reverse = FALSE;
+
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ invs[i][j].live = TRUE;
+ invs[i][j].x = 70 + i * 100;
+ invs[i][j].y = 70 + j * 80;
+ }
+ }
+ inv_num = INV_ROWS * INV_COLS;
+
+ inv_level ++;
+
+ inv_show_status ();
+ }
+
+ inv_queue_draw (geginv);
+}
+
+static gboolean
+geginv_timeout (gpointer data)
+{
+ int i, j;
+ int limitx1;
+ int limitx2;
+ int speed;
+ int shots;
+ int max_shots;
+
+ if (inv_paused)
+ return TRUE;
+
+ if (geginv != data ||
+ inv_num <= 0 ||
+ inv_y > 700)
+ return FALSE;
+
+ limitx1 = 70 - (inv_first_col * 100);
+ limitx2 = 800 - 70 - (inv_last_col * 100);
+
+ if (inv_game_over) {
+ inv_y += 30;
+ } else {
+ if (inv_num < (INV_COLS*INV_ROWS)/3)
+ speed = 45+2*inv_level;
+ else if (inv_num < (2*INV_COLS*INV_ROWS)/3)
+ speed = 30+2*inv_level;
+ else
+ speed = 15+2*inv_level;
+
+ if (inv_reverse) {
+ inv_x -= speed;
+ if (inv_x < limitx1) {
+ inv_reverse = FALSE;
+ inv_x = (limitx1 + (limitx1 - inv_x));
+ inv_y += 30+inv_level;
+ }
+ } else {
+ inv_x += speed;
+ if (inv_x > limitx2) {
+ inv_reverse = TRUE;
+ inv_x = (limitx2 - (inv_x - limitx2));
+ inv_y += 30+inv_level;
+ }
+ }
+ }
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ if (invs[i][j].live) {
+ invs[i][j].x = inv_x + i * 100;
+ invs[i][j].y = inv_y + j * 80;
+
+ if ( ! inv_game_over &&
+ invs[i][j].y >= 570) {
+ inv_do_game_over ();
+ } else if ( ! inv_game_over &&
+ invs[i][j].y >= 530 &&
+ invs[i][j].x + 40 > inv_our_x - 25 &&
+ invs[i][j].x - 40 < inv_our_x + 25) {
+ whack_gegl (i,j);
+ inv_lives --;
+ inv_draw_explosion (inv_our_x, 550);
+ if (inv_lives <= 0) {
+ inv_do_game_over ();
+ } else {
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+ inv_our_x = 400;
+ inv_do_pause = TRUE;
+ inv_show_status ();
+ }
+ }
+ }
+ }
+ }
+
+ shots = 0;
+ max_shots = (g_random_int () >> 3) % (2+inv_level);
+ while ( ! inv_game_over && shots < MIN (max_shots, inv_num)) {
+ int i = (g_random_int () >> 3) % INV_COLS;
+ for (j = INV_ROWS-1; j >= 0; j--) {
+ if (invs[i][j].live) {
+ InvShot *shot = g_new0 (InvShot, 1);
+
+ shot->good = FALSE;
+ shot->x = invs[i][j].x + (g_random_int () % 6) - 3;
+ shot->y = invs[i][j].y + inv_goat_height/2 + (g_random_int () % 3);
+
+ inv_shots = g_slist_prepend (inv_shots, shot);
+ shots++;
+ break;
+ }
+ }
+ }
+
+ inv_goat_state = (inv_goat_state+1) % 2;
+
+ inv_queue_draw (geginv);
+
+ g_timeout_add (((inv_num/4)+1) * 100, geginv_timeout, geginv);
+
+ return FALSE;
+}
+
+static gboolean
+find_gegls (int x, int y)
+{
+ int i, j;
+
+ /* FIXME: this is stupid, we can do better */
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ int ix = invs[i][j].x;
+ int iy = invs[i][j].y;
+
+ if ( ! invs[i][j].live)
+ continue;
+
+ if (y >= iy - 30 &&
+ y <= iy + 30 &&
+ x >= ix - 40 &&
+ x <= ix + 40) {
+ whack_gegl (i, j);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+geginv_move_timeout (gpointer data)
+{
+ GSList *li;
+ static int shot_inhibit = 0;
+
+ if (inv_paused)
+ return TRUE;
+
+ if (geginv != data ||
+ inv_num <= 0 ||
+ inv_y > 700)
+ return FALSE;
+
+ inv_phsh_state = (inv_phsh_state+1)%10;
+
+ /* we will be drawing something */
+ if (inv_shots != NULL)
+ inv_queue_draw (geginv);
+
+ li = inv_shots;
+ while (li != NULL) {
+ InvShot *shot = li->data;
+
+ if (shot->good) {
+ shot->y -= 30;
+ if (find_gegls (shot->x, shot->y) ||
+ shot->y <= 0) {
+ GSList *list = li;
+ /* we were restarted */
+ if (inv_shots == NULL)
+ return TRUE;
+ li = li->next;
+ g_free (shot);
+ inv_shots = g_slist_delete_link (inv_shots, list);
+ continue;
+ }
+ } else /* bad */ {
+ shot->y += 30;
+ if ( ! inv_game_over &&
+ shot->y >= 535 &&
+ shot->y <= 565 &&
+ shot->x >= inv_our_x - 25 &&
+ shot->x <= inv_our_x + 25) {
+ inv_lives --;
+ inv_draw_explosion (inv_our_x, 550);
+ if (inv_lives <= 0) {
+ inv_do_game_over ();
+ } else {
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+ inv_our_x = 400;
+ inv_do_pause = TRUE;
+ inv_show_status ();
+ return TRUE;
+ }
+ }
+
+ if (shot->y >= 600) {
+ GSList *list = li;
+ li = li->next;
+ g_free (shot);
+ inv_shots = g_slist_delete_link (inv_shots, list);
+ continue;
+ }
+ }
+
+ li = li->next;
+ }
+
+ if ( ! inv_game_over) {
+ if (inv_left_pressed && inv_our_x > 100) {
+ inv_our_x -= 20;
+ inv_queue_draw (geginv);
+ } else if (inv_right_pressed && inv_our_x < 700) {
+ inv_our_x += 20;
+ inv_queue_draw (geginv);
+ }
+ }
+
+ if (shot_inhibit > 0)
+ shot_inhibit--;
+
+ if ( ! inv_game_over && inv_fire_pressed && shot_inhibit == 0) {
+ InvShot *shot = g_new0 (InvShot, 1);
+
+ shot->good = TRUE;
+ shot->x = inv_our_x;
+ shot->y = 540;
+
+ inv_shots = g_slist_prepend (inv_shots, shot);
+
+ shot_inhibit = 5;
+
+ inv_queue_draw (geginv);
+ }
+
+ if (inv_left_released)
+ inv_left_pressed = FALSE;
+ if (inv_right_released)
+ inv_right_pressed = FALSE;
+ if (inv_fire_released)
+ inv_fire_pressed = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+inv_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ switch (event->keyval) {
+ case GDK_Left:
+ case GDK_KP_Left:
+ case GDK_Pointer_Left:
+ inv_left_pressed = TRUE;
+ inv_left_released = FALSE;
+ return TRUE;
+ case GDK_Right:
+ case GDK_KP_Right:
+ case GDK_Pointer_Right:
+ inv_right_pressed = TRUE;
+ inv_right_released = FALSE;
+ return TRUE;
+ case GDK_space:
+ case GDK_KP_Space:
+ inv_fire_pressed = TRUE;
+ inv_fire_released = FALSE;
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+inv_key_release (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ switch (event->keyval) {
+ case GDK_Left:
+ case GDK_KP_Left:
+ case GDK_Pointer_Left:
+ inv_left_released = TRUE;
+ return TRUE;
+ case GDK_Right:
+ case GDK_KP_Right:
+ case GDK_Pointer_Right:
+ inv_right_released = TRUE;
+ return TRUE;
+ case GDK_space:
+ case GDK_KP_Space:
+ inv_fire_released = TRUE;
+ return TRUE;
+ case GDK_q:
+ case GDK_Q:
+ gtk_widget_destroy (widget);
+ return TRUE;
+ case GDK_p:
+ case GDK_P:
+ inv_paused = ! inv_paused;
+ inv_show_status ();
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+ensure_creatures (void)
+{
+ GdkPixbuf *pb, *pb1, *phsh1, *phsh2, *goat1, *goat2;
+ char *phsh_file;
+ char *goat_file;
+
+ if (inv_goat1 != NULL)
+ return TRUE;
+
+ phsh_file = get_phsh_file ();
+
+ if (phsh_file == NULL)
+ return FALSE;
+
+ pb = gdk_pixbuf_new_from_file (phsh_file, NULL);
+ g_free (phsh_file);
+ if (pb == NULL)
+ return FALSE;
+
+ pb1 = get_phsh_frame (pb, 1);
+ phsh1 = pb_scale (pb1, inv_factor);
+ g_object_unref (G_OBJECT (pb1));
+ phsh_unsea (phsh1);
+
+ pb1 = get_phsh_frame (pb, 2);
+ phsh2 = pb_scale (pb1, inv_factor);
+ g_object_unref (G_OBJECT (pb1));
+ phsh_unsea (phsh2);
+
+ g_object_unref (G_OBJECT (pb));
+
+ goat_file = g_strdup_printf ("%s/mate-gegl2.png", ICONDIR);
+ if (goat_file == NULL) {
+ g_object_unref (G_OBJECT (phsh1));
+ g_object_unref (G_OBJECT (phsh2));
+ return FALSE;
+ }
+
+ pb = gdk_pixbuf_new_from_file (goat_file, NULL);
+ g_free (goat_file);
+ if (pb == NULL) {
+ g_object_unref (G_OBJECT (phsh1));
+ g_object_unref (G_OBJECT (phsh2));
+ return FALSE;
+ }
+
+ goat1 = pb_scale (pb, inv_factor * 0.66);
+ g_object_unref (pb);
+
+ goat_file = g_strdup_printf ("%s/mate-gegl2-2.png", ICONDIR);
+ if (goat_file == NULL) {
+ g_object_unref (G_OBJECT (goat1));
+ g_object_unref (G_OBJECT (phsh1));
+ g_object_unref (G_OBJECT (phsh2));
+ return FALSE;
+ }
+
+ pb = gdk_pixbuf_new_from_file (goat_file, NULL);
+ g_free (goat_file);
+ if (pb == NULL) {
+ g_object_unref (G_OBJECT (goat1));
+ g_object_unref (G_OBJECT (phsh1));
+ g_object_unref (G_OBJECT (phsh2));
+ return FALSE;
+ }
+
+ goat2 = pb_scale (pb, inv_factor * 0.66);
+ g_object_unref (pb);
+
+ inv_goat_width = gdk_pixbuf_get_width (goat1);
+ inv_goat_height = gdk_pixbuf_get_height (goat1);
+ inv_phsh_width = gdk_pixbuf_get_width (phsh1);
+ inv_phsh_height = gdk_pixbuf_get_height (phsh1);
+
+ gdk_pixbuf_render_pixmap_and_mask (goat1, &inv_goat1, NULL, 127);
+ g_object_unref (G_OBJECT (goat1));
+ gdk_pixbuf_render_pixmap_and_mask (goat2, &inv_goat2, NULL, 127);
+ g_object_unref (G_OBJECT (goat2));
+ gdk_pixbuf_render_pixmap_and_mask (phsh1, &inv_phsh1, &inv_phsh1_mask, 127);
+ g_object_unref (G_OBJECT (phsh1));
+ gdk_pixbuf_render_pixmap_and_mask (phsh2, &inv_phsh2, &inv_phsh2_mask, 127);
+ g_object_unref (G_OBJECT (phsh2));
+
+ return TRUE;
+}
+
+static void
+geginv_destroyed (GtkWidget *w, gpointer data)
+{
+ geginv = NULL;
+ if (geginv_pixmap != NULL)
+ g_object_unref (G_OBJECT (geginv_pixmap));
+ geginv_pixmap = NULL;
+}
+
+static void
+geginv_realized (GtkWidget *w, gpointer data)
+{
+ if (geginv_pixmap == NULL)
+ geginv_pixmap = gdk_pixmap_new (gtk_widget_get_window (w),
+ inv_width, inv_height,
+ gdk_visual_get_depth (gtk_widget_get_visual (w)));
+}
+
+static gboolean
+inv_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+ if ( ! gtk_widget_is_drawable (widget) ||
+ geginv_pixmap == NULL)
+ return FALSE;
+
+ inv_queue_draw (geginv);
+ /*
+ gdk_draw_drawable (geginv_canvas->window,
+ geginv_canvas->style->white_gc,
+ geginv_pixmap,
+ event->area.x, event->area.x,
+ event->area.x, event->area.x,
+ event->area.width, event->area.height);
+ */
+
+ return FALSE;
+}
+
+void
+start_geginv (void)
+{
+ GtkWidget *vbox;
+ int i, j;
+
+ if (geginv != NULL) {
+ gtk_window_present (GTK_WINDOW (geginv));
+ return;
+ }
+
+ inv_width = 800;
+ inv_height = 600;
+
+ if (inv_width > gdk_screen_width () * 0.9) {
+ inv_width = gdk_screen_width () * 0.9;
+ inv_height = inv_width * (600.0/800.0);
+ }
+
+ if (inv_height > gdk_screen_height () * 0.9) {
+ inv_height = gdk_screen_height () * 0.9;
+ inv_width = inv_height * (800.0/600.0);
+ }
+
+ inv_factor = (double)inv_width / 800.0;
+
+ if ( ! ensure_creatures ())
+ return;
+
+ geginv = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (geginv), _("Killer GEGLs from Outer Space"));
+ g_object_set (G_OBJECT (geginv), "resizable", FALSE, NULL);
+ g_signal_connect (G_OBJECT (geginv), "destroy",
+ G_CALLBACK (geginv_destroyed),
+ NULL);
+
+ geginv_canvas = gtk_drawing_area_new ();
+ gtk_widget_set_double_buffered (GTK_WIDGET (geginv_canvas), FALSE);
+ gtk_widget_set_size_request (geginv_canvas, inv_width, inv_height);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (geginv), vbox);
+ gtk_box_pack_start (GTK_BOX (vbox), geginv_canvas, TRUE, TRUE, 0);
+
+ geginv_label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (vbox), geginv_label, FALSE, FALSE, 0);
+
+ inv_our_x = 400;
+ inv_x = 70;
+ inv_y = 70;
+ inv_first_col = 0;
+ inv_level = 0;
+ inv_lives = 3;
+ inv_last_col = INV_COLS-1;
+ inv_reverse = FALSE;
+ inv_game_over = FALSE;
+ inv_left_pressed = FALSE;
+ inv_right_pressed = FALSE;
+ inv_fire_pressed = FALSE;
+ inv_left_released = FALSE;
+ inv_right_released = FALSE;
+ inv_fire_released = FALSE;
+ inv_paused = FALSE;
+
+ gtk_widget_add_events (geginv, GDK_KEY_RELEASE_MASK);
+
+ g_signal_connect (G_OBJECT (geginv), "key_press_event",
+ G_CALLBACK (inv_key_press), NULL);
+ g_signal_connect (G_OBJECT (geginv), "key_release_event",
+ G_CALLBACK (inv_key_release), NULL);
+ g_signal_connect (G_OBJECT (geginv), "realize",
+ G_CALLBACK (geginv_realized), NULL);
+ g_signal_connect (GTK_OBJECT (geginv_canvas), "expose_event",
+ G_CALLBACK (inv_expose), NULL);
+
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ invs[i][j].live = TRUE;
+ invs[i][j].x = 70 + i * 100;
+ invs[i][j].y = 70 + j * 80;
+ }
+ }
+ inv_num = INV_ROWS * INV_COLS;
+
+ g_timeout_add (((inv_num/4)+1) * 100, geginv_timeout, geginv);
+ g_timeout_add (90, geginv_move_timeout, geginv);
+
+ inv_show_status ();
+
+ gtk_widget_show_all (geginv);
+}
+
+static gboolean
+move_window_handler (gpointer data)
+{
+ int x, y, sx, sy, wx, wy, foox, fooy;
+ GtkWidget *win = data;
+ GtkAllocation allocation;
+
+ data = g_object_get_data (G_OBJECT (win), "move_speed_x");
+ sx = GPOINTER_TO_INT (data);
+ data = g_object_get_data (G_OBJECT (win), "move_speed_y");
+ sy = GPOINTER_TO_INT (data);
+
+ gtk_widget_get_allocation (win, &allocation);
+
+ gdk_window_get_pointer (NULL, &x, &y, NULL);
+ wx = allocation.x;
+ wy = allocation.y;
+
+ foox = wx + (allocation.width / 2);
+ fooy = wy + (allocation.height / 2);
+
+ if (sqrt ((foox - x)*(foox - x) + (fooy - y)*(fooy - y)) <
+ MAX (allocation.width, allocation.height)) {
+ if (foox < x) sx -= 5;
+ else sx += 5;
+ if (fooy < y) sy -= 5;
+ else sy += 5;
+ } else {
+ sx /= 2;
+ sy /= 2;
+ }
+
+ if (sx > 50) sx = 50;
+ else if (sx < -50) sx = -50;
+ if (sy > 50) sy = 50;
+ else if (sy < -50) sy = -50;
+
+ wx += sx;
+ wy += sy;
+
+ if (wx < 0) wx = 0;
+ if (wy < 0) wy = 0;
+ if (wx + allocation.width > gdk_screen_width ())
+ wx = gdk_screen_width () - allocation.width;
+ if (wy + allocation.height > gdk_screen_height ())
+ wy = gdk_screen_height () - allocation.height;
+
+ gtk_window_move (GTK_WINDOW (win), wx, wy);
+ allocation.x = wx;
+ allocation.y = wy;
+ gtk_widget_set_allocation (win, &allocation);
+
+ data = GINT_TO_POINTER (sx);
+ g_object_set_data (G_OBJECT (win), "move_speed_x", data);
+ data = GINT_TO_POINTER (sy);
+ g_object_set_data (G_OBJECT (win), "move_speed_y", data);
+
+ return TRUE;
+}
+
+static void
+move_window_destroyed (GtkWidget *win)
+{
+ gpointer data = g_object_get_data (G_OBJECT (win), "move_window_handler");
+ int handler = GPOINTER_TO_INT (data);
+
+ if (handler != 0)
+ g_source_remove (handler);
+ g_object_set_data (G_OBJECT (win), "move_window_handler", NULL);
+}
+
+static void
+doblah (GtkWidget *window)
+{
+ gpointer data = g_object_get_data (G_OBJECT (window), "move_window_handler");
+ int handler = GPOINTER_TO_INT (data);
+
+ if (handler == 0) {
+ handler = g_timeout_add (30, move_window_handler, window);
+ data = GINT_TO_POINTER (handler);
+ g_object_set_data (G_OBJECT (window), "move_window_handler", data);
+ g_signal_connect (G_OBJECT (window), "destroy",
+ G_CALLBACK (move_window_destroyed),
+ NULL);
+ }
+}
+
+gboolean
+panel_dialog_window_event (GtkWidget *window,
+ GdkEvent *event)
+{
+ switch (event->type) {
+ static int foo = 0;
+ case GDK_KEY_PRESS:
+ if((event->key.state & GDK_CONTROL_MASK) && foo < 4) {
+ switch (event->key.keyval) {
+ case GDK_r:
+ case GDK_R:
+ if(foo == 3) { doblah (window); } foo = 0; break;
+ case GDK_a:
+ case GDK_A:
+ if(foo == 2) { foo++; } else { foo = 0; } break;
+ case GDK_e:
+ case GDK_E:
+ if(foo == 1) { foo++; } else { foo = 0; } break;
+ case GDK_f:
+ case GDK_F:
+ if(foo == 0) { foo++; } else { foo = 0; } break;
+ default:
+ foo = 0;
+ }
+ }
+ default:
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/mate-panel/nothing.h b/mate-panel/nothing.h
new file mode 100644
index 00000000..1dc7f02f
--- /dev/null
+++ b/mate-panel/nothing.h
@@ -0,0 +1,22 @@
+#ifndef NOTHING_H
+#define NOTHING_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void start_screen_check (void);
+void start_geginv (void);
+gboolean panel_dialog_window_event (GtkWidget *window,
+ GdkEvent *event);
+int config_event (GtkWidget *widget,
+ GdkEvent *event,
+ GtkNotebook *nbook);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mate-panel/panel-a11y.c b/mate-panel/panel-a11y.c
new file mode 100644
index 00000000..0c308c4d
--- /dev/null
+++ b/mate-panel/panel-a11y.c
@@ -0,0 +1,135 @@
+/*
+ * panel-a11y.c: panel accessibility support module
+ *
+ * Copyright (C) 2002, 2003 Sun Microsystems 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 Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include "panel-a11y.h"
+
+gboolean
+panel_a11y_get_is_a11y_enabled (GtkWidget *widget)
+{
+ static gboolean initialised = FALSE;
+ static gboolean a11y_enabled = FALSE;
+
+ if (!initialised) {
+ a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (widget));
+ initialised = TRUE;
+ }
+
+ return a11y_enabled;
+}
+
+void
+panel_a11y_set_atk_name_desc (GtkWidget *widget,
+ const char *name,
+ const char *desc)
+{
+ AtkObject *aobj;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (!panel_a11y_get_is_a11y_enabled (widget))
+ return;
+
+ aobj = gtk_widget_get_accessible (widget);
+
+ if (name)
+ atk_object_set_name (aobj, name);
+
+ if (desc)
+ atk_object_set_description (aobj, desc);
+}
+
+/**
+ * panel_a11y_set_atk_relation
+ * @widget : The Gtk widget which is labelled by @label
+ * @label : The label for the @widget.
+ *
+ * Description : This function establishes atk relation
+ * between a gtk widget and a label.
+ */
+void
+panel_a11y_set_atk_relation (GtkWidget *widget,
+ GtkLabel *label)
+{
+ AtkObject *aobject;
+ AtkRelationSet *relation_set;
+ AtkRelation *relation;
+ AtkObject *targets [1];
+
+ g_return_if_fail (GTK_IS_WIDGET(widget));
+ g_return_if_fail (GTK_IS_LABEL(label));
+
+ if (!panel_a11y_get_is_a11y_enabled (widget))
+ return;
+
+ aobject = gtk_widget_get_accessible (widget);
+
+ gtk_label_set_mnemonic_widget (label, widget);
+
+ targets [0] = gtk_widget_get_accessible (GTK_WIDGET (label));
+
+ relation_set = atk_object_ref_relation_set (aobject);
+
+ relation = atk_relation_new (targets, 1, ATK_RELATION_LABELLED_BY);
+ atk_relation_set_add (relation_set, relation);
+ g_object_unref (relation);
+}
+
+/**
+ * panel_a11y_query_accessible_parent_type
+ * @type: widget type
+ * @type_info: accessible object type info to complete
+ *
+ * Standard hack which figures out the #GType of the accessible
+ * object for @type's parent type. Also, fills out the class_size
+ * and instance_size of @type_info to match the size of the parent
+ * type.
+ *
+ * Basically, this is the hack to use if you want to derive from
+ * an accessible object implementation in gail.
+ *
+ * Returns: the #GType of @type's parent's accessible peer
+ */
+GType
+panel_a11y_query_accessible_parent_type (GType type,
+ GTypeInfo *type_info)
+{
+ AtkObjectFactory *factory;
+ GType parent_type;
+ GType accessible_parent_type;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (type), G_TYPE_INVALID);
+
+ parent_type = g_type_parent (type);
+
+ factory = atk_registry_get_factory (atk_get_default_registry (), parent_type);
+
+ accessible_parent_type = atk_object_factory_get_accessible_type (factory);
+
+ if (type_info) {
+ GTypeQuery query;
+
+ g_type_query (accessible_parent_type, &query);
+
+ type_info->class_size = query.class_size;
+ type_info->instance_size = query.instance_size;
+ }
+
+ return atk_object_factory_get_accessible_type (factory);
+}
diff --git a/mate-panel/panel-a11y.h b/mate-panel/panel-a11y.h
new file mode 100644
index 00000000..927698aa
--- /dev/null
+++ b/mate-panel/panel-a11y.h
@@ -0,0 +1,43 @@
+/*
+ * panel-a11y.h: panel accessibility support module
+ *
+ * Copyright (C) 2002, 2003 Sun Microsystems 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 Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANEL_A11Y_H__
+#define __PANEL_A11Y_H__
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean panel_a11y_get_is_a11y_enabled (GtkWidget *widget);
+void panel_a11y_set_atk_name_desc (GtkWidget *widget,
+ const char *name,
+ const char *desc);
+void panel_a11y_set_atk_relation (GtkWidget *widget,
+ GtkLabel *label);
+GType panel_a11y_query_accessible_parent_type (GType type,
+ GTypeInfo *type_info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_A11Y_H__ */
diff --git a/mate-panel/panel-action-button.c b/mate-panel/panel-action-button.c
new file mode 100644
index 00000000..04536fff
--- /dev/null
+++ b/mate-panel/panel-action-button.c
@@ -0,0 +1,907 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * panel-action-button.c: panel "Action Button" module
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ * Copyright (C) 2004 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "panel-action-button.h"
+
+#include <glib/gi18n.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-launch.h>
+#include <libpanel-util/panel-session-manager.h>
+#include <libpanel-util/panel-show.h>
+
+#include "applet.h"
+#include "panel-config-global.h"
+#include "panel-mateconf.h"
+#include "panel-profile.h"
+#include "panel-typebuiltins.h"
+#include "panel-force-quit.h"
+#include "panel-util.h"
+#include "panel-session.h"
+#include "panel-globals.h"
+#include "panel-run-dialog.h"
+#include "panel-a11y.h"
+#include "panel-lockdown.h"
+#include "panel-compatibility.h"
+#include "panel-icon-names.h"
+
+G_DEFINE_TYPE (PanelActionButton, panel_action_button, BUTTON_TYPE_WIDGET)
+
+#define PANEL_ACTION_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_ACTION_BUTTON, PanelActionButtonPrivate))
+
+#define LOGOUT_PROMPT_KEY "/apps/mate-session/options/logout_prompt"
+
+enum {
+ PROP_0,
+ PROP_ACTION_TYPE,
+ PROP_DND_ENABLED
+};
+
+struct _PanelActionButtonPrivate {
+ PanelActionButtonType type;
+ AppletInfo *info;
+
+ guint mateconf_notify;
+
+ guint dnd_enabled : 1;
+};
+
+static MateConfEnumStringPair panel_action_type_map [] = {
+ { PANEL_ACTION_NONE, "none" },
+ { PANEL_ACTION_LOCK, "lock" },
+ { PANEL_ACTION_LOGOUT, "logout" },
+ { PANEL_ACTION_RUN, "run" },
+ { PANEL_ACTION_SEARCH, "search" },
+ { PANEL_ACTION_FORCE_QUIT, "force-quit" },
+ { PANEL_ACTION_CONNECT_SERVER, "connect-server" },
+ { PANEL_ACTION_SHUTDOWN, "shutdown" },
+ /* compatibility with MATE < 2.13.90 */
+ { PANEL_ACTION_SCREENSHOT, "screenshot" },
+ { 0, NULL },
+};
+
+/* Lock Screen
+ */
+static void panel_action_lock_screen(GtkWidget* widget)
+{
+ panel_lock_screen(gtk_widget_get_screen(widget));
+}
+
+static gboolean
+screensaver_properties_enabled (void)
+{
+ if (panel_lockdown_get_locked_down () ||
+ panel_lockdown_get_disable_lock_screen ())
+ return FALSE;
+
+ return panel_lock_screen_action_available ("prefs");
+}
+
+static gboolean
+screensaver_enabled (void)
+{
+ if (panel_lockdown_get_disable_lock_screen ())
+ return FALSE;
+
+ return panel_lock_screen_action_available ("lock");
+}
+
+static gboolean
+panel_action_lock_is_disabled (void)
+{
+ return !screensaver_enabled ();
+}
+
+static void
+panel_action_lock_setup_menu (PanelActionButton *button)
+{
+ mate_panel_applet_add_callback (button->priv->info,
+ "activate",
+ NULL,
+ _("_Activate Screensaver"),
+ screensaver_enabled);
+
+ mate_panel_applet_add_callback (button->priv->info,
+ "lock",
+ NULL,
+ _("_Lock Screen"),
+ screensaver_enabled);
+
+ mate_panel_applet_add_callback (button->priv->info,
+ "prefs",
+ GTK_STOCK_PROPERTIES,
+ _("_Properties"),
+ screensaver_properties_enabled);
+}
+
+static void
+panel_action_lock_invoke_menu (PanelActionButton *button,
+ const char *callback_name)
+{
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (button));
+ g_return_if_fail (callback_name != NULL);
+
+ panel_lock_screen_action (gtk_widget_get_screen (GTK_WIDGET (button)),
+ callback_name);
+}
+
+/* Log Out
+ */
+static void
+panel_action_logout (GtkWidget *widget)
+{
+ PanelSessionManager *manager;
+ gboolean not_prompt;
+
+ not_prompt = mateconf_client_get_bool (panel_mateconf_get_client (),
+ LOGOUT_PROMPT_KEY, NULL);
+ /* this avoids handling errors from mateconf since prompting is
+ * safer */
+ not_prompt = !not_prompt;
+
+ manager = panel_session_manager_get ();
+
+ if (not_prompt)
+ panel_session_manager_request_logout (manager,
+ PANEL_SESSION_MANAGER_LOGOUT_MODE_NO_CONFIRMATION);
+ else
+ /* FIXME: we need to use widget to get the screen for the
+ * confirmation dialog, see
+ * http://bugzilla.gnome.org/show_bug.cgi?id=536914 */
+ panel_session_manager_request_logout (manager,
+ PANEL_SESSION_MANAGER_LOGOUT_MODE_NORMAL);
+}
+
+static void
+panel_action_shutdown (GtkWidget *widget)
+{
+ PanelSessionManager *manager;
+
+ manager = panel_session_manager_get ();
+ panel_session_manager_request_shutdown (manager);
+}
+
+static gboolean
+panel_action_shutdown_reboot_is_disabled (void)
+{
+ PanelSessionManager *manager;
+
+ if (panel_lockdown_get_disable_log_out())
+ return TRUE;
+
+ manager = panel_session_manager_get ();
+
+ return (!panel_session_manager_is_shutdown_available (manager));
+}
+
+/* Run Application
+ */
+static void
+panel_action_run_program (GtkWidget *widget)
+{
+ panel_run_dialog_present (gtk_widget_get_screen (widget),
+ gtk_get_current_event_time ());
+}
+
+/* Search For Files
+ */
+static void
+panel_action_search (GtkWidget *widget)
+{
+ GdkScreen *screen;
+
+ screen = gtk_widget_get_screen (widget);
+ panel_launch_desktop_file_with_fallback ("mate-search-tool.desktop",
+ "mate-search-tool",
+ screen, NULL);
+}
+
+/* Force Quit
+ */
+static void
+panel_action_force_quit (GtkWidget *widget)
+{
+ panel_force_quit (gtk_widget_get_screen (widget),
+ gtk_get_current_event_time ());
+}
+
+/* Connect Server
+ */
+static void
+panel_action_connect_server (GtkWidget *widget)
+{
+ GdkScreen *screen;
+ GError *error;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (widget));
+ error = NULL;
+
+ gdk_spawn_command_line_on_screen (screen, "caja-connect-server",
+ &error);
+
+ if (error) {
+ panel_error_dialog (NULL, screen,
+ "cannot_connect_server",
+ TRUE,
+ _("Could not connect to server"),
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+typedef struct {
+ PanelActionButtonType type;
+ char *icon_name;
+ char *text;
+ char *tooltip;
+ char *help_index;
+ char *drag_id;
+ void (*invoke) (GtkWidget *widget);
+ void (*setup_menu) (PanelActionButton *button);
+ void (*invoke_menu) (PanelActionButton *button,
+ const char *callback_name);
+ gboolean (*is_disabled) (void);
+} PanelAction;
+
+/* Keep order in sync with PanelActionButtonType
+ */
+static PanelAction actions [] = {
+ {
+ PANEL_ACTION_NONE,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+ },
+ {
+ PANEL_ACTION_LOCK,
+ PANEL_ICON_LOCKSCREEN,
+ N_("Lock Screen"),
+ N_("Protect your computer from unauthorized use"),
+ "gospanel-21",
+ "ACTION:lock:NEW",
+ panel_action_lock_screen,
+ panel_action_lock_setup_menu,
+ panel_action_lock_invoke_menu,
+ panel_action_lock_is_disabled
+ },
+ {
+ PANEL_ACTION_LOGOUT,
+ PANEL_ICON_LOGOUT,
+ /* when changing one of those two strings, don't forget to
+ * update the ones in panel-menu-items.c (look for
+ * "1" (msgctxt: "panel:showusername")) */
+ N_("Log Out..."),
+ N_("Log out of this session to log in as a different user"),
+ "gospanel-20",
+ "ACTION:logout:NEW",
+ panel_action_logout, NULL, NULL,
+ panel_lockdown_get_disable_log_out
+ },
+ {
+ PANEL_ACTION_RUN,
+ PANEL_ICON_RUN,
+ N_("Run Application..."),
+ N_("Run an application by typing a command or choosing from a list"),
+ "gospanel-555",
+ "ACTION:run:NEW",
+ panel_action_run_program, NULL, NULL,
+ panel_lockdown_get_disable_command_line
+ },
+ {
+ PANEL_ACTION_SEARCH,
+ PANEL_ICON_SEARCHTOOL,
+ N_("Search for Files..."),
+ N_("Locate documents and folders on this computer by name or content"),
+ "gospanel-554",
+ "ACTION:search:NEW",
+ panel_action_search, NULL, NULL, NULL
+ },
+ {
+ PANEL_ACTION_FORCE_QUIT,
+ PANEL_ICON_FORCE_QUIT,
+ N_("Force Quit"),
+ N_("Force a misbehaving application to quit"),
+ "gospanel-563",
+ "ACTION:force-quit:NEW",
+ panel_action_force_quit, NULL, NULL,
+ panel_lockdown_get_disable_force_quit
+ },
+ {
+ PANEL_ACTION_CONNECT_SERVER,
+ PANEL_ICON_REMOTE, //FIXME icon
+ N_("Connect to Server..."),
+ N_("Connect to a remote computer or shared disk"),
+ "caja-server-connect",
+ "ACTION:connect-server:NEW",
+ panel_action_connect_server, NULL, NULL, NULL
+ },
+ {
+ PANEL_ACTION_SHUTDOWN,
+ PANEL_ICON_SHUTDOWN,
+ N_("Shut Down..."),
+ N_("Shut down the computer"),
+ "gospanel-20",
+ "ACTION:shutdown:NEW",
+ panel_action_shutdown, NULL, NULL,
+ panel_action_shutdown_reboot_is_disabled
+ },
+ /* deprecated actions */
+ {
+ PANEL_ACTION_SCREENSHOT,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+ }
+};
+
+static gboolean
+panel_action_get_is_deprecated (PanelActionButtonType type)
+{
+ g_return_val_if_fail (type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, FALSE);
+
+ return (type >= PANEL_ACTION_SCREENSHOT);
+}
+
+gboolean
+panel_action_get_is_disabled (PanelActionButtonType type)
+{
+ g_return_val_if_fail (type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, FALSE);
+
+ if (panel_action_get_is_deprecated (type))
+ return TRUE;
+
+ if (actions [type].is_disabled)
+ return actions [type].is_disabled ();
+
+ return FALSE;
+}
+
+GCallback
+panel_action_get_invoke (PanelActionButtonType type)
+{
+ g_return_val_if_fail (type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, NULL);
+
+ g_assert (actions[type].invoke != NULL);
+
+ return G_CALLBACK (actions[type].invoke);
+}
+
+const char* panel_action_get_icon_name(PanelActionButtonType type)
+{
+ g_return_val_if_fail(type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, NULL);
+
+ return actions[type].icon_name;
+}
+
+const char* panel_action_get_text(PanelActionButtonType type)
+{
+ g_return_val_if_fail(type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, NULL);
+
+ return _(actions[type].text);
+}
+
+const char* panel_action_get_tooltip(PanelActionButtonType type)
+{
+ g_return_val_if_fail(type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, NULL);
+
+ return _(actions[type].tooltip);
+}
+
+const char* panel_action_get_drag_id(PanelActionButtonType type)
+{
+ g_return_val_if_fail(type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, NULL);
+
+ return actions[type].drag_id;
+}
+
+static void
+panel_action_button_update_sensitivity (PanelActionButton *button)
+{
+ if (actions [button->priv->type].is_disabled)
+ button_widget_set_activatable (BUTTON_WIDGET (button),
+ !actions [button->priv->type].is_disabled ());
+}
+
+static void
+panel_action_button_finalize (GObject *object)
+{
+ PanelActionButton *button = PANEL_ACTION_BUTTON (object);
+
+ button->priv->info = NULL;
+ button->priv->type = PANEL_ACTION_NONE;
+
+ panel_lockdown_notify_remove (G_CALLBACK (panel_action_button_update_sensitivity),
+ button);
+
+ mateconf_client_notify_remove (panel_mateconf_get_client (),
+ button->priv->mateconf_notify);
+ button->priv->mateconf_notify = 0;
+
+ G_OBJECT_CLASS (panel_action_button_parent_class)->finalize (object);
+}
+
+static void
+panel_action_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelActionButton *button;
+
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (object));
+
+ button = PANEL_ACTION_BUTTON (object);
+
+ switch (prop_id) {
+ case PROP_ACTION_TYPE:
+ g_value_set_enum (value, button->priv->type);
+ break;
+ case PROP_DND_ENABLED:
+ g_value_set_boolean (value, button->priv->dnd_enabled);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_action_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelActionButton *button;
+
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (object));
+
+ button = PANEL_ACTION_BUTTON (object);
+
+ switch (prop_id) {
+ case PROP_ACTION_TYPE:
+ panel_action_button_set_type (button,
+ g_value_get_enum (value));
+ break;
+ case PROP_DND_ENABLED:
+ panel_action_button_set_dnd_enabled (button,
+ g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_action_button_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ PanelActionButton *button;
+ char *drag_data;
+
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (widget));
+
+ button = PANEL_ACTION_BUTTON (widget);
+
+ drag_data = g_strdup_printf ("ACTION:%s:%d",
+ mateconf_enum_to_string (panel_action_type_map, button->priv->type),
+ panel_find_applet_index (widget));
+
+ gtk_selection_data_set (
+ selection_data, gtk_selection_data_get_target (selection_data),
+ 8, (guchar *) drag_data, strlen (drag_data));
+
+ g_free (drag_data);
+}
+
+static void
+panel_action_button_clicked (GtkButton *gtk_button)
+{
+ PanelActionButton *button;
+
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (gtk_button));
+
+ button = PANEL_ACTION_BUTTON (gtk_button);
+
+ g_return_if_fail (button->priv->type > PANEL_ACTION_NONE);
+ g_return_if_fail (button->priv->type < PANEL_ACTION_LAST);
+
+ if (panel_global_config_get_drawer_auto_close ()) {
+ PanelToplevel *toplevel;
+
+ toplevel = PANEL_WIDGET (gtk_widget_get_parent (GTK_WIDGET (button)))->toplevel;
+
+ if (panel_toplevel_get_is_attached (toplevel))
+ panel_toplevel_hide (toplevel, FALSE, -1);
+ }
+
+ if (actions [button->priv->type].invoke)
+ actions [button->priv->type].invoke (GTK_WIDGET (button));
+}
+
+static void
+panel_action_button_class_init (PanelActionButtonClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+ GtkButtonClass *button_class = (GtkButtonClass *) klass;
+
+ gobject_class->finalize = panel_action_button_finalize;
+ gobject_class->get_property = panel_action_button_get_property;
+ gobject_class->set_property = panel_action_button_set_property;
+
+ widget_class->drag_data_get = panel_action_button_drag_data_get;
+
+ button_class->clicked = panel_action_button_clicked;
+
+ g_type_class_add_private (klass, sizeof (PanelActionButtonPrivate));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ACTION_TYPE,
+ g_param_spec_enum ("action-type",
+ "Action Type",
+ "The type of action this button implements",
+ PANEL_TYPE_ACTION_BUTTON_TYPE,
+ PANEL_ORIENTATION_TOP,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_DND_ENABLED,
+ g_param_spec_boolean ("dnd-enabled",
+ "Drag and drop enabled",
+ "Whether or not drag and drop is enabled on the widget",
+ TRUE,
+ G_PARAM_READWRITE));
+}
+
+static void
+panel_action_button_init (PanelActionButton *button)
+{
+ button->priv = PANEL_ACTION_BUTTON_GET_PRIVATE (button);
+
+ button->priv->type = PANEL_ACTION_NONE;
+ button->priv->info = NULL;
+
+ button->priv->mateconf_notify = 0;
+ button->priv->dnd_enabled = FALSE;
+}
+
+void
+panel_action_button_set_type (PanelActionButton *button,
+ PanelActionButtonType type)
+{
+ g_return_if_fail (type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST);
+
+ if (panel_action_get_is_deprecated (type))
+ return;
+
+ if (type == button->priv->type)
+ return;
+
+ button->priv->type = type;
+
+ if (actions [type].icon_name != NULL)
+ button_widget_set_icon_name (BUTTON_WIDGET (button), actions [type].icon_name);
+
+ panel_util_set_tooltip_text (GTK_WIDGET (button),
+ _(actions [type].tooltip));
+ panel_a11y_set_atk_name_desc (GTK_WIDGET (button), _(actions [type].tooltip), NULL);
+
+ panel_action_button_update_sensitivity (button);
+}
+
+static void
+panel_action_button_type_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelActionButton *button)
+{
+ int type;
+ const char *action_type;
+
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (button));
+
+ if (!entry->value || entry->value->type != MATECONF_VALUE_STRING)
+ return;
+
+ action_type = mateconf_value_get_string (entry->value);
+
+ if (!mateconf_string_to_enum (panel_action_type_map, action_type, &type))
+ return;
+
+ panel_action_button_set_type (button, type);
+}
+
+static void
+panel_action_button_connect_to_mateconf (PanelActionButton *button)
+{
+ const char *key;
+
+ key = panel_mateconf_full_key (
+ PANEL_MATECONF_OBJECTS, button->priv->info->id, "action_type");
+
+ button->priv->mateconf_notify =
+ mateconf_client_notify_add (panel_mateconf_get_client (), key,
+ (MateConfClientNotifyFunc) panel_action_button_type_changed,
+ button, NULL, NULL);
+
+ panel_lockdown_notify_add (G_CALLBACK (panel_action_button_update_sensitivity),
+ button);
+}
+
+static void
+panel_action_button_style_set (PanelActionButton *button)
+{
+ if (actions [button->priv->type].icon_name != NULL)
+ button_widget_set_icon_name (BUTTON_WIDGET (button), actions [button->priv->type].icon_name);
+}
+
+static void
+panel_action_button_load (PanelActionButtonType type,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id,
+ gboolean compatibility)
+{
+ PanelActionButton *button;
+ PanelObjectType object_type;
+
+ g_return_if_fail (panel != NULL);
+
+ button = g_object_new (PANEL_TYPE_ACTION_BUTTON, "action-type", type, NULL);
+
+ object_type = PANEL_OBJECT_ACTION;
+
+ if (compatibility)
+ { /* Backward compatibility with MATE 2.0.x */
+ if (type == PANEL_ACTION_LOCK)
+ {
+ object_type = PANEL_OBJECT_LOCK;
+ }
+ else if (type == PANEL_ACTION_LOGOUT)
+ {
+ object_type = PANEL_OBJECT_LOGOUT;
+ }
+ }
+
+ button->priv->info = mate_panel_applet_register (GTK_WIDGET (button),
+ NULL, NULL,
+ panel, locked, position,
+ exactpos, object_type, id);
+ if (!button->priv->info) {
+ gtk_widget_destroy (GTK_WIDGET (button));
+ return;
+ }
+
+ mate_panel_applet_add_callback (button->priv->info,
+ "help",
+ GTK_STOCK_HELP,
+ _("_Help"),
+ NULL);
+
+ panel_widget_set_applet_expandable (panel, GTK_WIDGET (button), FALSE, TRUE);
+ panel_widget_set_applet_size_constrained (panel, GTK_WIDGET (button), TRUE);
+
+ if (actions [button->priv->type].setup_menu)
+ actions [button->priv->type].setup_menu (button);
+
+ panel_action_button_connect_to_mateconf (button);
+
+ g_signal_connect (button, "style-set",
+ G_CALLBACK (panel_action_button_style_set), NULL);
+}
+
+void
+panel_action_button_create (PanelToplevel *toplevel,
+ int position,
+ PanelActionButtonType type)
+{
+ MateConfClient *client;
+ const char *key;
+ char *id;
+
+ client = panel_mateconf_get_client ();
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_ACTION, toplevel, position, FALSE);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "action_type");
+ mateconf_client_set_string (client,
+ key,
+ mateconf_enum_to_string (panel_action_type_map, type),
+ NULL);
+
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+
+ g_free (id);
+}
+
+/* This is only for backwards compatibility with 2.0.x
+ * We load an old-style lock/logout button as an action
+ * button but make sure to retain the lock/logout configuration
+ * so logging back into 2.0.x still works.
+ */
+void
+panel_action_button_load_compatible (PanelObjectType object_type,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id)
+{
+ PanelActionButtonType action_type;
+
+ g_assert (object_type == PANEL_OBJECT_LOGOUT || object_type == PANEL_OBJECT_LOCK);
+
+ action_type = object_type == PANEL_OBJECT_LOGOUT ? PANEL_ACTION_LOGOUT : PANEL_ACTION_LOCK;
+
+ panel_action_button_load (action_type, panel, locked, position, exactpos, id, TRUE);
+}
+
+void
+panel_action_button_load_from_mateconf (PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id)
+{
+ int type;
+ const char *key;
+ char *action_type;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "action_type");
+ action_type = mateconf_client_get_string (panel_mateconf_get_client (), key, NULL);
+
+ if (!mateconf_string_to_enum (panel_action_type_map, action_type, &type)) {
+ g_warning ("Unkown action type '%s' from %s", action_type, key);
+ g_free (action_type);
+ return;
+ }
+
+ g_free (action_type);
+
+ /* compatibility: migrate from MATE < 2.13.90 */
+ if (type == PANEL_ACTION_SCREENSHOT)
+ panel_compatibility_migrate_screenshot_action (panel_mateconf_get_client (),
+ id);
+ else
+ panel_action_button_load (type, panel, locked,
+ position, exactpos, id, FALSE);
+}
+
+void
+panel_action_button_invoke_menu (PanelActionButton *button,
+ const char *callback_name)
+{
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (button));
+ g_return_if_fail (callback_name != NULL);
+ g_return_if_fail (button->priv->type > PANEL_ACTION_NONE &&
+ button->priv->type < PANEL_ACTION_LAST);
+
+ if (!strcmp (callback_name, "help")) {
+ GdkScreen *screen;
+
+ if (!actions [button->priv->type].help_index)
+ return;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (button));
+
+ panel_show_help (screen, "user-guide",
+ actions [button->priv->type].help_index, NULL);
+
+ return;
+ }
+
+ if (actions [button->priv->type].invoke_menu)
+ actions [button->priv->type].invoke_menu (button, callback_name);
+}
+
+gboolean
+panel_action_button_load_from_drag (PanelToplevel *toplevel,
+ int position,
+ const char *drag_string,
+ int *old_applet_idx)
+{
+ PanelActionButtonType type = PANEL_ACTION_NONE;
+ gboolean retval = FALSE;
+ char **elements;
+
+ if (strncmp (drag_string, "ACTION:", strlen ("ACTION:")))
+ return retval;
+
+ elements = g_strsplit (drag_string, ":", 0);
+
+ g_assert (elements != NULL);
+
+ if (!elements [1] || !elements [2]) {
+ g_strfreev (elements);
+ return retval;
+ }
+
+ if (!mateconf_string_to_enum (panel_action_type_map, elements [1], (gpointer) &type)) {
+ g_strfreev (elements);
+ return retval;
+ }
+
+ g_return_val_if_fail (type > PANEL_ACTION_NONE && type < PANEL_ACTION_LAST, FALSE);
+
+ if (panel_action_get_is_deprecated (type))
+ return retval;
+
+ if (strcmp (elements [2], "NEW")) {
+ *old_applet_idx = strtol (elements [2], NULL, 10);
+ retval = TRUE; /* Remove the old applet */
+ }
+
+ g_strfreev (elements);
+
+ panel_action_button_create (toplevel, position, type);
+
+ return retval;
+}
+
+void
+panel_action_button_set_dnd_enabled (PanelActionButton *button,
+ gboolean enabled)
+{
+ g_return_if_fail (PANEL_IS_ACTION_BUTTON (button));
+
+ if (!button->priv->type)
+ return; /* wait until we know what type it is */
+
+ enabled = enabled != FALSE;
+
+ if (button->priv->dnd_enabled == enabled)
+ return;
+
+ if (enabled) {
+ static GtkTargetEntry dnd_targets [] = {
+ { "application/x-mate-panel-applet-internal", 0, 0 }
+ };
+
+ gtk_widget_set_has_window (GTK_WIDGET (button), TRUE);
+ gtk_drag_source_set (GTK_WIDGET (button), GDK_BUTTON1_MASK,
+ dnd_targets, 1,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ if (actions [button->priv->type].icon_name != NULL)
+ gtk_drag_source_set_icon_name (GTK_WIDGET (button),
+ actions [button->priv->type].icon_name);
+ gtk_widget_set_has_window (GTK_WIDGET (button), FALSE);
+ } else
+ gtk_drag_source_unset (GTK_WIDGET (button));
+
+ button->priv->dnd_enabled = enabled;
+
+ g_object_notify (G_OBJECT (button), "dnd-enabled");
+}
diff --git a/mate-panel/panel-action-button.h b/mate-panel/panel-action-button.h
new file mode 100644
index 00000000..7139aef6
--- /dev/null
+++ b/mate-panel/panel-action-button.h
@@ -0,0 +1,103 @@
+/*
+ * panel-action-button.h: panel "Action Button" module
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ * Copyright (C) 2004 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_ACTION_BUTTON_H__
+#define __PANEL_ACTION_BUTTON_H__
+
+#include <gtk/gtk.h>
+#include "button-widget.h"
+#include "panel-widget.h"
+#include "panel-enums.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_ACTION_BUTTON (panel_action_button_get_type ())
+#define PANEL_ACTION_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_ACTION_BUTTON, PanelActionButton))
+#define PANEL_ACTION_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_ACTION_BUTTON, PanelActionButtonClass))
+#define PANEL_IS_ACTION_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_ACTION_BUTTON))
+#define PANEL_IS_ACTION_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_ACTION_BUTTON))
+#define PANEL_ACTION_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_ACTION_BUTTON, PanelActionButtonClass))
+
+typedef struct _PanelActionButton PanelActionButton;
+typedef struct _PanelActionButtonClass PanelActionButtonClass;
+typedef struct _PanelActionButtonPrivate PanelActionButtonPrivate;
+
+struct _PanelActionButton{
+ ButtonWidget button;
+
+ PanelActionButtonPrivate *priv;
+};
+
+struct _PanelActionButtonClass {
+ ButtonWidgetClass button_class;
+};
+
+GType panel_action_button_get_type (void) G_GNUC_CONST;
+
+void panel_action_button_create (PanelToplevel *toplevel,
+ int position,
+ PanelActionButtonType type);
+
+void panel_action_button_set_type (PanelActionButton *button,
+ PanelActionButtonType type);
+
+void panel_action_button_load_from_mateconf (PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id);
+
+void panel_action_button_load_compatible (PanelObjectType object_type,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id);
+
+void panel_action_button_invoke_menu (PanelActionButton *button,
+ const char *callback_name);
+
+void panel_action_button_set_dnd_enabled (PanelActionButton *button,
+ gboolean dnd_enabled);
+
+gboolean panel_action_button_load_from_drag (PanelToplevel *toplevel,
+ int position,
+ const char *drag_string,
+ int *old_applet_idx);
+
+gboolean panel_action_get_is_disabled (PanelActionButtonType type);
+GCallback panel_action_get_invoke (PanelActionButtonType type);
+const char* panel_action_get_icon_name(PanelActionButtonType type);
+const char* panel_action_get_text(PanelActionButtonType type);
+const char* panel_action_get_tooltip(PanelActionButtonType type);
+const char* panel_action_get_drag_id(PanelActionButtonType type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_ACTION_BUTTON_H__ */
diff --git a/mate-panel/panel-action-protocol.c b/mate-panel/panel-action-protocol.c
new file mode 100644
index 00000000..3f2e3e52
--- /dev/null
+++ b/mate-panel/panel-action-protocol.c
@@ -0,0 +1,158 @@
+/*
+ * panel-action-protocol.h: _MATE_PANEL_ACTION protocol impl.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-action-protocol.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#include "menu.h"
+#include "applet.h"
+#include "panel-globals.h"
+#include "panel-toplevel.h"
+#include "panel-util.h"
+#include "panel-force-quit.h"
+#include "panel-run-dialog.h"
+#include "panel-menu-button.h"
+#include "panel-menu-bar.h"
+
+static Atom atom_mate_panel_action = None;
+static Atom atom_mate_panel_action_main_menu = None;
+static Atom atom_mate_panel_action_run_dialog = None;
+static Atom atom_mate_panel_action_kill_dialog = None;
+
+static void
+panel_action_protocol_main_menu (GdkScreen *screen,
+ guint32 activate_time)
+{
+ PanelWidget *panel_widget;
+ GtkWidget *menu;
+ AppletInfo *info;
+
+ info = mate_panel_applet_get_by_type (PANEL_OBJECT_MENU_BAR, screen);
+ if (info) {
+ panel_menu_bar_popup_menu (PANEL_MENU_BAR (info->widget),
+ activate_time);
+ return;
+ }
+
+ info = mate_panel_applet_get_by_type (PANEL_OBJECT_MENU, screen);
+ if (info && !panel_menu_button_get_use_menu_path (PANEL_MENU_BUTTON (info->widget))) {
+ panel_menu_button_popup_menu (PANEL_MENU_BUTTON (info->widget),
+ 1, activate_time);
+ return;
+ }
+
+ panel_widget = panels->data;
+ menu = create_main_menu (panel_widget);
+
+ panel_toplevel_push_autohide_disabler (panel_widget->toplevel);
+
+ gtk_menu_set_screen (GTK_MENU (menu), screen);
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+ NULL, NULL, 0, activate_time);
+}
+
+static void
+panel_action_protocol_run_dialog (GdkScreen *screen,
+ guint32 activate_time)
+{
+ panel_run_dialog_present (screen, activate_time);
+}
+
+static void
+panel_action_protocol_kill_dialog (GdkScreen *screen,
+ guint32 activate_time)
+{
+ panel_force_quit (screen, activate_time);
+}
+
+static GdkFilterReturn
+panel_action_protocol_filter (GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ GdkWindow *window;
+ GdkScreen *screen;
+ XEvent *xevent = (XEvent *) gdk_xevent;
+
+ if (xevent->type != ClientMessage)
+ return GDK_FILTER_CONTINUE;
+
+ if (xevent->xclient.message_type != atom_mate_panel_action)
+ return GDK_FILTER_CONTINUE;
+
+ window = gdk_window_lookup (xevent->xclient.window);
+ if (!window)
+ return GDK_FILTER_CONTINUE;
+
+ screen = gdk_drawable_get_screen (window);
+
+ if (xevent->xclient.data.l [0] == atom_mate_panel_action_main_menu)
+ panel_action_protocol_main_menu (screen, xevent->xclient.data.l [1]);
+ else if (xevent->xclient.data.l [0] == atom_mate_panel_action_run_dialog)
+ panel_action_protocol_run_dialog (screen, xevent->xclient.data.l [1]);
+ else if (xevent->xclient.data.l [0] == atom_mate_panel_action_kill_dialog)
+ panel_action_protocol_kill_dialog (screen, xevent->xclient.data.l [1]);
+ else
+ return GDK_FILTER_CONTINUE;
+
+ return GDK_FILTER_REMOVE;
+}
+
+void
+panel_action_protocol_init (void)
+{
+ GdkDisplay *display;
+ GdkAtom gdk_atom_mate_panel_action;
+
+ display = gdk_display_get_default ();
+
+ gdk_atom_mate_panel_action =
+ gdk_atom_intern_static_string ("_MATE_PANEL_ACTION");
+
+ atom_mate_panel_action =
+ XInternAtom (GDK_DISPLAY_XDISPLAY (display),
+ "_MATE_PANEL_ACTION",
+ FALSE);
+ atom_mate_panel_action_main_menu =
+ XInternAtom (GDK_DISPLAY_XDISPLAY (display),
+ "_MATE_PANEL_ACTION_MAIN_MENU",
+ FALSE);
+ atom_mate_panel_action_run_dialog =
+ XInternAtom (GDK_DISPLAY_XDISPLAY (display),
+ "_MATE_PANEL_ACTION_RUN_DIALOG",
+ FALSE);
+ atom_mate_panel_action_kill_dialog =
+ XInternAtom (GDK_DISPLAY_XDISPLAY (display),
+ "_MATE_PANEL_ACTION_KILL_DIALOG",
+ FALSE);
+
+ gdk_display_add_client_message_filter (
+ display, gdk_atom_mate_panel_action,
+ panel_action_protocol_filter, NULL);
+}
diff --git a/mate-panel/panel-action-protocol.h b/mate-panel/panel-action-protocol.h
new file mode 100644
index 00000000..3c90da9e
--- /dev/null
+++ b/mate-panel/panel-action-protocol.h
@@ -0,0 +1,40 @@
+/*
+ * panel-action-protocol.h: _MATE_PANEL_ACTION protocol impl.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_ACTION_PROTOCOL_H__
+#define __PANEL_ACTION_PROTOCOL_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_action_protocol_init (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_ACTION_PROTOCOL_H__ */
diff --git a/mate-panel/panel-addto.c b/mate-panel/panel-addto.c
new file mode 100644
index 00000000..150d83de
--- /dev/null
+++ b/mate-panel/panel-addto.c
@@ -0,0 +1,1428 @@
+/*
+ * panel-addto.c:
+ *
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include <matemenu-tree.h>
+
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-show.h>
+
+#include "launcher.h"
+#include "panel.h"
+#include "drawer.h"
+#include "mate-panel-applets-manager.h"
+#include "mate-panel-applet-frame.h"
+#include "panel-action-button.h"
+#include "panel-menu-bar.h"
+#include "panel-separator.h"
+#include "panel-toplevel.h"
+#include "panel-menu-button.h"
+#include "panel-globals.h"
+#include "panel-lockdown.h"
+#include "panel-util.h"
+#include "panel-profile.h"
+#include "panel-addto.h"
+#include "panel-icon-names.h"
+
+typedef struct {
+ PanelWidget *panel_widget;
+
+ GtkWidget *addto_dialog;
+ GtkWidget *label;
+ GtkWidget *search_entry;
+ GtkWidget *back_button;
+ GtkWidget *add_button;
+ GtkWidget *tree_view;
+ GtkTreeModel *applet_model;
+ GtkTreeModel *filter_applet_model;
+ GtkTreeModel *application_model;
+ GtkTreeModel *filter_application_model;
+
+ MateMenuTree *menu_tree;
+
+ GSList *applet_list;
+ GSList *application_list;
+ GSList *settings_list;
+
+ gchar *search_text;
+ gchar *applet_search_text;
+
+ guint name_notify;
+
+ int insertion_position;
+} PanelAddtoDialog;
+
+static GQuark panel_addto_dialog_quark = 0;
+
+typedef enum {
+ PANEL_ADDTO_APPLET,
+ PANEL_ADDTO_ACTION,
+ PANEL_ADDTO_LAUNCHER_MENU,
+ PANEL_ADDTO_LAUNCHER,
+ PANEL_ADDTO_LAUNCHER_NEW,
+ PANEL_ADDTO_MENU,
+ PANEL_ADDTO_MENUBAR,
+ PANEL_ADDTO_SEPARATOR,
+ PANEL_ADDTO_DRAWER
+} PanelAddtoItemType;
+
+typedef struct {
+ PanelAddtoItemType type;
+ char *name;
+ char *description;
+ char *icon;
+ PanelActionButtonType action_type;
+ char *launcher_path;
+ char *menu_filename;
+ char *menu_path;
+ char *iid;
+ gboolean static_data;
+} PanelAddtoItemInfo;
+
+typedef struct {
+ GSList *children;
+ PanelAddtoItemInfo item_info;
+} PanelAddtoAppList;
+
+static PanelAddtoItemInfo special_addto_items [] = {
+
+ { PANEL_ADDTO_LAUNCHER_NEW,
+ N_("Custom Application Launcher"),
+ N_("Create a new launcher"),
+ PANEL_ICON_LAUNCHER,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "LAUNCHER:ASK",
+ TRUE },
+
+ { PANEL_ADDTO_LAUNCHER_MENU,
+ N_("Application Launcher..."),
+ N_("Copy a launcher from the applications menu"),
+ PANEL_ICON_LAUNCHER,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "LAUNCHER:MENU",
+ TRUE }
+
+};
+
+static PanelAddtoItemInfo internal_addto_items [] = {
+
+ { PANEL_ADDTO_MENU,
+ N_("Main Menu"),
+ N_("The main MATE menu"),
+ PANEL_ICON_MAIN_MENU,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "MENU:MAIN",
+ TRUE },
+
+ { PANEL_ADDTO_MENUBAR,
+ N_("Menu Bar"),
+ N_("A custom menu bar"),
+ PANEL_ICON_MAIN_MENU,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "MENUBAR:NEW",
+ TRUE },
+
+ { PANEL_ADDTO_SEPARATOR,
+ N_("Separator"),
+ N_("A separator to organize the panel items"),
+ PANEL_ICON_SEPARATOR,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "SEPARATOR:NEW",
+ TRUE },
+
+ { PANEL_ADDTO_DRAWER,
+ N_("Drawer"),
+ N_("A pop out drawer to store other items in"),
+ PANEL_ICON_DRAWER,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "DRAWER:NEW",
+ TRUE }
+};
+
+enum {
+ COLUMN_ICON,
+ COLUMN_TEXT,
+ COLUMN_DATA,
+ COLUMN_SEARCH,
+ NUMBER_COLUMNS
+};
+
+enum {
+ PANEL_ADDTO_RESPONSE_BACK,
+ PANEL_ADDTO_RESPONSE_ADD
+};
+
+static void panel_addto_present_applications (PanelAddtoDialog *dialog);
+static void panel_addto_present_applets (PanelAddtoDialog *dialog);
+static gboolean panel_addto_filter_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data);
+
+static int
+panel_addto_applet_info_sort_func (PanelAddtoItemInfo *a,
+ PanelAddtoItemInfo *b)
+{
+ return g_utf8_collate (a->name, b->name);
+}
+
+static GSList *
+panel_addto_prepend_internal_applets (GSList *list)
+{
+ static gboolean translated = FALSE;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (internal_addto_items); i++) {
+ if (!translated) {
+ internal_addto_items [i].name = _(internal_addto_items [i].name);
+ internal_addto_items [i].description = _(internal_addto_items [i].description);
+ }
+
+ list = g_slist_prepend (list, &internal_addto_items [i]);
+ }
+
+ translated = TRUE;
+
+ for (i = PANEL_ACTION_LOCK; i < PANEL_ACTION_LAST; i++) {
+ PanelAddtoItemInfo *info;
+
+ if (panel_action_get_is_disabled (i))
+ continue;
+
+ info = g_new0 (PanelAddtoItemInfo, 1);
+ info->type = PANEL_ADDTO_ACTION;
+ info->action_type = i;
+ info->name = g_strdup (panel_action_get_text (i));
+ info->description = g_strdup (panel_action_get_tooltip (i));
+ info->icon = g_strdup (panel_action_get_icon_name (i));
+ info->iid = g_strdup (panel_action_get_drag_id (i));
+ info->static_data = FALSE;
+
+ list = g_slist_prepend (list, info);
+ }
+
+ return list;
+}
+
+static char *
+panel_addto_make_text (const char *name,
+ const char *desc)
+{
+ const char *real_name;
+ char *result;
+
+ real_name = name ? name : _("(empty)");
+
+ if (!PANEL_GLIB_STR_EMPTY (desc)) {
+ result = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>\n%s",
+ real_name, desc);
+ } else {
+ result = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>",
+ real_name);
+ }
+
+ return result;
+}
+
+#define ICON_SIZE 32
+
+static GdkPixbuf *
+panel_addto_make_pixbuf (const char *filename)
+{
+ //FIXME: size shouldn't be fixed but should depend on the font size
+ return panel_load_icon (gtk_icon_theme_get_default (),
+ filename,
+ ICON_SIZE, ICON_SIZE, ICON_SIZE,
+ NULL);
+}
+
+static void
+panel_addto_drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ const char *string)
+{
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8,
+ (guchar *) string, strlen (string));
+}
+
+static void
+panel_addto_drag_begin_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+ GdkPixbuf *pixbuf;
+
+ filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+
+ gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &path, NULL);
+ gtk_tree_model_get_iter (filter_model, &filter_iter, path);
+ gtk_tree_path_free (path);
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter, &filter_iter);
+
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter,
+ COLUMN_ICON, &pixbuf,
+ -1);
+
+ gtk_drag_set_icon_pixbuf (context, pixbuf, 0, 0);
+ g_object_unref (pixbuf);
+}
+
+static void
+panel_addto_setup_drag (GtkTreeView *tree_view,
+ const GtkTargetEntry *target,
+ const char *text)
+{
+ if (!text || panel_lockdown_get_locked_down ())
+ return;
+
+ gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree_view),
+ GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
+ target, 1, GDK_ACTION_COPY);
+
+ g_signal_connect_data (G_OBJECT (tree_view), "drag_data_get",
+ G_CALLBACK (panel_addto_drag_data_get_cb),
+ g_strdup (text),
+ (GClosureNotify) g_free,
+ 0 /* connect_flags */);
+ g_signal_connect_after (G_OBJECT (tree_view), "drag-begin",
+ G_CALLBACK (panel_addto_drag_begin_cb),
+ NULL);
+}
+
+static void
+panel_addto_setup_launcher_drag (GtkTreeView *tree_view,
+ const char *path)
+{
+ static GtkTargetEntry target[] = {
+ { "text/uri-list", 0, 0 }
+ };
+ char *uri;
+ char *uri_list;
+
+ uri = g_filename_to_uri (path, NULL, NULL);
+ uri_list = g_strconcat (uri, "\r\n", NULL);
+ panel_addto_setup_drag (tree_view, target, uri_list);
+ g_free (uri_list);
+ g_free (uri);
+}
+
+static void
+panel_addto_setup_applet_drag (GtkTreeView *tree_view,
+ const char *iid)
+{
+ static GtkTargetEntry target[] = {
+ { "application/x-mate-panel-applet-iid", 0, 0 }
+ };
+
+ panel_addto_setup_drag (tree_view, target, iid);
+}
+
+static void
+panel_addto_setup_internal_applet_drag (GtkTreeView *tree_view,
+ const char *applet_type)
+{
+ static GtkTargetEntry target[] = {
+ { "application/x-mate-panel-applet-internal", 0, 0 }
+ };
+
+ panel_addto_setup_drag (tree_view, target, applet_type);
+}
+
+static GSList *
+panel_addto_query_applets (GSList *list)
+{
+ GList *applet_list, *l;
+
+ applet_list = mate_panel_applets_manager_get_applets ();
+
+ for (l = applet_list; l; l = g_list_next (l)) {
+ MatePanelAppletInfo *info;
+ const char *iid, *name, *description, *icon;
+ PanelAddtoItemInfo *applet;
+
+ info = (MatePanelAppletInfo *)l->data;
+
+ iid = mate_panel_applet_info_get_iid (info);
+ name = mate_panel_applet_info_get_name (info);
+ description = mate_panel_applet_info_get_description (info);
+ icon = mate_panel_applet_info_get_icon (info);
+
+ if (!name || panel_lockdown_is_applet_disabled (iid)) {
+ continue;
+ }
+
+ applet = g_new0 (PanelAddtoItemInfo, 1);
+ applet->type = PANEL_ADDTO_APPLET;
+ applet->name = g_strdup (name);
+ applet->description = g_strdup (description);
+ applet->icon = g_strdup (icon);
+ applet->iid = g_strdup (iid);
+ applet->static_data = FALSE;
+
+ list = g_slist_prepend (list, applet);
+ }
+
+ g_list_free (applet_list);
+
+ return list;
+}
+
+static void
+panel_addto_append_item (PanelAddtoDialog *dialog,
+ GtkListStore *model,
+ PanelAddtoItemInfo *applet)
+{
+ char *text;
+ GdkPixbuf *pixbuf;
+ GtkTreeIter iter;
+
+ if (applet == NULL) {
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_ICON, NULL,
+ COLUMN_TEXT, NULL,
+ COLUMN_DATA, NULL,
+ COLUMN_SEARCH, NULL,
+ -1);
+ } else {
+ pixbuf = NULL;
+
+ if (applet->icon != NULL) {
+ pixbuf = panel_addto_make_pixbuf (applet->icon);
+ }
+
+ gtk_list_store_append (model, &iter);
+
+ text = panel_addto_make_text (applet->name,
+ applet->description);
+
+ gtk_list_store_set (model, &iter,
+ COLUMN_ICON, pixbuf,
+ COLUMN_TEXT, text,
+ COLUMN_DATA, applet,
+ COLUMN_SEARCH, applet->name,
+ -1);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ g_free (text);
+ }
+}
+
+static void
+panel_addto_append_special_applets (PanelAddtoDialog *dialog,
+ GtkListStore *model)
+{
+ static gboolean translated = FALSE;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (special_addto_items); i++) {
+ if (!translated) {
+ special_addto_items [i].name = _(special_addto_items [i].name);
+ special_addto_items [i].description = _(special_addto_items [i].description);
+ }
+
+ if (special_addto_items [i].type == PANEL_ADDTO_LAUNCHER_NEW
+ && panel_lockdown_get_disable_command_line ())
+ continue;
+
+ panel_addto_append_item (dialog, model, &special_addto_items [i]);
+ }
+
+ translated = TRUE;
+}
+
+static void
+panel_addto_make_applet_model (PanelAddtoDialog *dialog)
+{
+ GtkListStore *model;
+ GSList *l;
+
+ if (dialog->filter_applet_model != NULL)
+ return;
+
+ if (panel_profile_id_lists_are_writable ()) {
+ dialog->applet_list = panel_addto_query_applets (dialog->applet_list);
+ dialog->applet_list = panel_addto_prepend_internal_applets (dialog->applet_list);
+ }
+
+ dialog->applet_list = g_slist_sort (dialog->applet_list,
+ (GCompareFunc) panel_addto_applet_info_sort_func);
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_STRING,
+ G_TYPE_POINTER,
+ G_TYPE_STRING);
+
+ if (panel_profile_id_lists_are_writable ()) {
+ panel_addto_append_special_applets (dialog, model);
+ if (dialog->applet_list)
+ panel_addto_append_item (dialog, model, NULL);
+ }
+
+ for (l = dialog->applet_list; l; l = l->next)
+ panel_addto_append_item (dialog, model, l->data);
+
+ dialog->applet_model = GTK_TREE_MODEL (model);
+ dialog->filter_applet_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->applet_model),
+ NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (dialog->filter_applet_model),
+ panel_addto_filter_func,
+ dialog, NULL);
+}
+
+static void panel_addto_make_application_list (GSList **parent_list,
+ MateMenuTreeDirectory *directory,
+ const char *filename);
+
+static void
+panel_addto_prepend_directory (GSList **parent_list,
+ MateMenuTreeDirectory *directory,
+ const char *filename)
+{
+ PanelAddtoAppList *data;
+
+ data = g_new0 (PanelAddtoAppList, 1);
+
+ data->item_info.type = PANEL_ADDTO_MENU;
+ data->item_info.name = g_strdup (matemenu_tree_directory_get_name (directory));
+ data->item_info.description = g_strdup (matemenu_tree_directory_get_comment (directory));
+ data->item_info.icon = g_strdup (matemenu_tree_directory_get_icon (directory));
+ data->item_info.menu_filename = g_strdup (filename);
+ data->item_info.menu_path = matemenu_tree_directory_make_path (directory, NULL);
+ data->item_info.static_data = FALSE;
+
+ /* We should set the iid here to something and do
+ * iid = g_strdup_printf ("MENU:%s", tfr->name)
+ * but this means we'd have to free the iid later
+ * and this would complexify too much the free
+ * function.
+ * So the iid is built when we select the row.
+ */
+
+ *parent_list = g_slist_prepend (*parent_list, data);
+
+ panel_addto_make_application_list (&data->children, directory, filename);
+}
+
+static void
+panel_addto_prepend_entry (GSList **parent_list,
+ MateMenuTreeEntry *entry,
+ const char *filename)
+{
+ PanelAddtoAppList *data;
+
+ data = g_new0 (PanelAddtoAppList, 1);
+
+ data->item_info.type = PANEL_ADDTO_LAUNCHER;
+ data->item_info.name = g_strdup (matemenu_tree_entry_get_display_name (entry));
+ data->item_info.description = g_strdup (matemenu_tree_entry_get_comment (entry));
+ data->item_info.icon = g_strdup (matemenu_tree_entry_get_icon (entry));
+ data->item_info.launcher_path = g_strdup (matemenu_tree_entry_get_desktop_file_path (entry));
+ data->item_info.static_data = FALSE;
+
+ *parent_list = g_slist_prepend (*parent_list, data);
+}
+
+static void
+panel_addto_prepend_alias (GSList **parent_list,
+ MateMenuTreeAlias *alias,
+ const char *filename)
+{
+ MateMenuTreeItem *aliased_item;
+
+ aliased_item = matemenu_tree_alias_get_item (alias);
+
+ switch (matemenu_tree_item_get_type (aliased_item)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ panel_addto_prepend_directory (parent_list,
+ MATEMENU_TREE_DIRECTORY (aliased_item),
+ filename);
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ panel_addto_prepend_entry (parent_list,
+ MATEMENU_TREE_ENTRY (aliased_item),
+ filename);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (aliased_item);
+}
+
+static void
+panel_addto_make_application_list (GSList **parent_list,
+ MateMenuTreeDirectory *directory,
+ const char *filename)
+{
+ GSList *items;
+ GSList *l;
+
+ items = matemenu_tree_directory_get_contents (directory);
+
+ for (l = items; l; l = l->next) {
+ switch (matemenu_tree_item_get_type (l->data)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ panel_addto_prepend_directory (parent_list, l->data, filename);
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ panel_addto_prepend_entry (parent_list, l->data, filename);
+ break;
+
+ case MATEMENU_TREE_ITEM_ALIAS:
+ panel_addto_prepend_alias (parent_list, l->data, filename);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (l->data);
+ }
+
+ g_slist_free (items);
+
+ *parent_list = g_slist_reverse (*parent_list);
+}
+
+static void
+panel_addto_populate_application_model (GtkTreeStore *store,
+ GtkTreeIter *parent,
+ GSList *app_list)
+{
+ PanelAddtoAppList *data;
+ GtkTreeIter iter;
+ char *text;
+ GdkPixbuf *pixbuf;
+ GSList *app;
+
+ for (app = app_list; app != NULL; app = app->next) {
+ data = app->data;
+ gtk_tree_store_append (store, &iter, parent);
+
+ text = panel_addto_make_text (data->item_info.name,
+ data->item_info.description);
+ pixbuf = panel_addto_make_pixbuf (data->item_info.icon);
+ gtk_tree_store_set (store, &iter,
+ COLUMN_ICON, pixbuf,
+ COLUMN_TEXT, text,
+ COLUMN_DATA, &(data->item_info),
+ COLUMN_SEARCH, data->item_info.name,
+ -1);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ g_free (text);
+
+ if (data->children != NULL)
+ panel_addto_populate_application_model (store,
+ &iter,
+ data->children);
+ }
+}
+
+static void panel_addto_make_application_model(PanelAddtoDialog* dialog)
+{
+ GtkTreeStore* store;
+ MateMenuTree* tree;
+ MateMenuTreeDirectory* root;
+
+ if (dialog->filter_application_model != NULL)
+ return;
+
+ store = gtk_tree_store_new(NUMBER_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
+
+ tree = matemenu_tree_lookup("mate-applications.menu", MATEMENU_TREE_FLAGS_NONE);
+ matemenu_tree_set_sort_key(tree, MATEMENU_TREE_SORT_DISPLAY_NAME);
+
+ if ((root = matemenu_tree_get_root_directory (tree)))
+ {
+ panel_addto_make_application_list(&dialog->application_list, root, "mate-applications.menu");
+ panel_addto_populate_application_model(store, NULL, dialog->application_list);
+
+ matemenu_tree_item_unref(root);
+ }
+
+ matemenu_tree_unref(tree);
+
+ tree = matemenu_tree_lookup("mate-settings.menu", MATEMENU_TREE_FLAGS_NONE);
+ matemenu_tree_set_sort_key(tree, MATEMENU_TREE_SORT_DISPLAY_NAME);
+
+ if ((root = matemenu_tree_get_root_directory(tree)))
+ {
+ GtkTreeIter iter;
+
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store, &iter, COLUMN_ICON, NULL, COLUMN_TEXT, NULL, COLUMN_DATA, NULL, COLUMN_SEARCH, NULL, -1);
+
+ panel_addto_make_application_list(&dialog->settings_list, root, "mate-settings.menu");
+ panel_addto_populate_application_model(store, NULL, dialog->settings_list);
+
+ matemenu_tree_item_unref(root);
+ }
+
+ matemenu_tree_unref(tree);
+
+ dialog->application_model = GTK_TREE_MODEL(store);
+ dialog->filter_application_model = gtk_tree_model_filter_new(GTK_TREE_MODEL(dialog->application_model), NULL);
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(dialog->filter_application_model), panel_addto_filter_func, dialog, NULL);
+}
+
+static void
+panel_addto_add_item (PanelAddtoDialog *dialog,
+ PanelAddtoItemInfo *item_info)
+{
+ g_assert (item_info != NULL);
+
+ switch (item_info->type) {
+ case PANEL_ADDTO_APPLET:
+ mate_panel_applet_frame_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->iid);
+ break;
+ case PANEL_ADDTO_ACTION:
+ panel_action_button_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->action_type);
+ break;
+ case PANEL_ADDTO_LAUNCHER_MENU:
+ panel_addto_present_applications (dialog);
+ break;
+ case PANEL_ADDTO_LAUNCHER:
+ panel_launcher_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->launcher_path);
+ break;
+ case PANEL_ADDTO_LAUNCHER_NEW:
+ ask_about_launcher (NULL, dialog->panel_widget,
+ dialog->insertion_position, FALSE);
+ break;
+ case PANEL_ADDTO_MENU:
+ panel_menu_button_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->menu_filename,
+ item_info->menu_path,
+ item_info->menu_path != NULL,
+ item_info->name);
+ break;
+ case PANEL_ADDTO_MENUBAR:
+ panel_menu_bar_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position);
+ break;
+ case PANEL_ADDTO_SEPARATOR:
+ panel_separator_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position);
+ break;
+ case PANEL_ADDTO_DRAWER:
+ panel_drawer_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ NULL, FALSE, NULL);
+ break;
+ }
+}
+
+static void
+panel_addto_dialog_response (GtkWidget *widget_dialog,
+ guint response_id,
+ PanelAddtoDialog *dialog)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+
+ switch (response_id) {
+ case GTK_RESPONSE_HELP:
+ panel_show_help (gtk_window_get_screen (GTK_WINDOW (dialog->addto_dialog)),
+ "user-guide", "gospanel-15", NULL);
+ break;
+
+ case PANEL_ADDTO_RESPONSE_ADD:
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+ if (gtk_tree_selection_get_selected (selection, &filter_model,
+ &filter_iter)) {
+ PanelAddtoItemInfo *data;
+
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter,
+ &filter_iter);
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter,
+ COLUMN_DATA, &data, -1);
+
+ if (data != NULL)
+ panel_addto_add_item (dialog, data);
+ }
+ break;
+
+ case PANEL_ADDTO_RESPONSE_BACK:
+ /* This response only happens when we're showing the
+ * application list and the user wants to go back to the
+ * applet list. */
+ panel_addto_present_applets (dialog);
+ break;
+
+ case GTK_RESPONSE_CLOSE:
+ gtk_widget_destroy (widget_dialog);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+panel_addto_dialog_destroy (GtkWidget *widget_dialog,
+ PanelAddtoDialog *dialog)
+{
+ panel_toplevel_pop_autohide_disabler (PANEL_TOPLEVEL (dialog->panel_widget->toplevel));
+ g_object_set_qdata (G_OBJECT (dialog->panel_widget->toplevel),
+ panel_addto_dialog_quark,
+ NULL);
+}
+
+static void
+panel_addto_present_applications (PanelAddtoDialog *dialog)
+{
+ if (dialog->filter_application_model == NULL)
+ panel_addto_make_application_model (dialog);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->tree_view),
+ dialog->filter_application_model);
+ gtk_window_set_focus (GTK_WINDOW (dialog->addto_dialog),
+ dialog->search_entry);
+ gtk_widget_set_sensitive (dialog->back_button, TRUE);
+
+ if (dialog->applet_search_text)
+ g_free (dialog->applet_search_text);
+
+ dialog->applet_search_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->search_entry)));
+ /* show everything */
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_entry), "");
+}
+
+static void
+panel_addto_present_applets (PanelAddtoDialog *dialog)
+{
+ if (dialog->filter_applet_model == NULL)
+ panel_addto_make_applet_model (dialog);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->tree_view),
+ dialog->filter_applet_model);
+ gtk_window_set_focus (GTK_WINDOW (dialog->addto_dialog),
+ dialog->search_entry);
+ gtk_widget_set_sensitive (dialog->back_button, FALSE);
+
+ if (dialog->applet_search_text) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_entry),
+ dialog->applet_search_text);
+ gtk_editable_set_position (GTK_EDITABLE (dialog->search_entry),
+ -1);
+
+ g_free (dialog->applet_search_text);
+ dialog->applet_search_text = NULL;
+ }
+}
+
+static void
+panel_addto_dialog_free_item_info (PanelAddtoItemInfo *item_info)
+{
+ if (item_info == NULL || item_info->static_data)
+ return;
+
+ if (item_info->name != NULL)
+ g_free (item_info->name);
+ item_info->name = NULL;
+
+ if (item_info->description != NULL)
+ g_free (item_info->description);
+ item_info->description = NULL;
+
+ if (item_info->icon != NULL)
+ g_free (item_info->icon);
+ item_info->icon = NULL;
+
+ if (item_info->iid != NULL)
+ g_free (item_info->iid);
+ item_info->iid = NULL;
+
+ if (item_info->launcher_path != NULL)
+ g_free (item_info->launcher_path);
+ item_info->launcher_path = NULL;
+
+ if (item_info->menu_filename != NULL)
+ g_free (item_info->menu_filename);
+ item_info->menu_filename = NULL;
+
+ if (item_info->menu_path != NULL)
+ g_free (item_info->menu_path);
+ item_info->menu_path = NULL;
+}
+
+static void
+panel_addto_dialog_free_application_list (GSList *application_list)
+{
+ PanelAddtoAppList *data;
+ GSList *app;
+
+ if (application_list == NULL)
+ return;
+
+ for (app = application_list; app != NULL; app = app->next) {
+ data = app->data;
+ if (data->children) {
+ panel_addto_dialog_free_application_list (data->children);
+ }
+ panel_addto_dialog_free_item_info (&data->item_info);
+ g_free (data);
+ }
+ g_slist_free (application_list);
+}
+
+static void
+panel_addto_dialog_free (PanelAddtoDialog *dialog)
+{
+ MateConfClient *client;
+ GSList *item;
+
+ client = panel_mateconf_get_client ();
+
+ if (dialog->name_notify)
+ mateconf_client_notify_remove (client, dialog->name_notify);
+ dialog->name_notify = 0;
+
+ if (dialog->search_text)
+ g_free (dialog->search_text);
+ dialog->search_text = NULL;
+
+ if (dialog->applet_search_text)
+ g_free (dialog->applet_search_text);
+ dialog->applet_search_text = NULL;
+
+ if (dialog->addto_dialog)
+ gtk_widget_destroy (dialog->addto_dialog);
+ dialog->addto_dialog = NULL;
+
+ for (item = dialog->applet_list; item != NULL; item = item->next) {
+ PanelAddtoItemInfo *applet;
+
+ applet = (PanelAddtoItemInfo *) item->data;
+ if (!applet->static_data) {
+ panel_addto_dialog_free_item_info (applet);
+ g_free (applet);
+ }
+ }
+ g_slist_free (dialog->applet_list);
+
+ panel_addto_dialog_free_application_list (dialog->application_list);
+ panel_addto_dialog_free_application_list (dialog->settings_list);
+
+ if (dialog->filter_applet_model)
+ g_object_unref (dialog->filter_applet_model);
+ dialog->filter_applet_model = NULL;
+
+ if (dialog->applet_model)
+ g_object_unref (dialog->applet_model);
+ dialog->applet_model = NULL;
+
+ if (dialog->filter_application_model)
+ g_object_unref (dialog->filter_application_model);
+ dialog->filter_application_model = NULL;
+
+ if (dialog->application_model)
+ g_object_unref (dialog->application_model);
+ dialog->application_model = NULL;
+
+ if (dialog->menu_tree)
+ matemenu_tree_unref (dialog->menu_tree);
+ dialog->menu_tree = NULL;
+
+ g_free (dialog);
+}
+
+static void
+panel_addto_name_change (PanelAddtoDialog *dialog,
+ const char *name)
+{
+ char *title;
+ char *label;
+
+ label = NULL;
+
+ if (!PANEL_GLIB_STR_EMPTY (name))
+ label = g_strdup_printf (_("Find an _item to add to \"%s\":"),
+ name);
+
+ if (panel_toplevel_get_is_attached (dialog->panel_widget->toplevel)) {
+ title = g_strdup_printf (_("Add to Drawer"));
+ if (label == NULL)
+ label = g_strdup (_("Find an _item to add to the drawer:"));
+ } else {
+ title = g_strdup_printf (_("Add to Panel"));
+ if (label == NULL)
+ label = g_strdup (_("Find an _item to add to the panel:"));
+ }
+
+ gtk_window_set_title (GTK_WINDOW (dialog->addto_dialog), title);
+ g_free (title);
+
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->label), label);
+ g_free (label);
+}
+
+static void
+panel_addto_name_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelAddtoDialog *dialog)
+{
+ MateConfValue *value;
+ const char *key;
+ const char *text = NULL;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+
+ if (strcmp (key, "name"))
+ return;
+
+ value = mateconf_entry_get_value (entry);
+
+ if (value && value->type == MATECONF_VALUE_STRING)
+ text = mateconf_value_get_string (value);
+
+ if (text)
+ panel_addto_name_change (dialog, text);
+}
+
+static gboolean
+panel_addto_filter_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer userdata)
+{
+ PanelAddtoDialog *dialog;
+ PanelAddtoItemInfo *data;
+
+ dialog = (PanelAddtoDialog *) userdata;
+
+ if (!dialog->search_text || !dialog->search_text[0])
+ return TRUE;
+
+ gtk_tree_model_get (model, iter, COLUMN_DATA, &data, -1);
+
+ if (data == NULL)
+ return FALSE;
+
+ /* This is more a workaround than anything else: show all the root
+ * items in a tree store */
+ if (GTK_IS_TREE_STORE (model) &&
+ gtk_tree_store_iter_depth (GTK_TREE_STORE (model), iter) == 0)
+ return TRUE;
+
+ return (panel_g_utf8_strstrcase (data->name,
+ dialog->search_text) != NULL ||
+ panel_g_utf8_strstrcase (data->description,
+ dialog->search_text) != NULL);
+}
+
+static void
+panel_addto_search_entry_changed (GtkWidget *entry,
+ PanelAddtoDialog *dialog)
+{
+ GtkTreeModel *model;
+ char *new_text;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ new_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->search_entry)));
+ g_strchomp (new_text);
+
+ if (dialog->search_text &&
+ g_utf8_collate (new_text, dialog->search_text) == 0) {
+ g_free (new_text);
+ return;
+ }
+
+ if (dialog->search_text)
+ g_free (dialog->search_text);
+ dialog->search_text = new_text;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
+
+ path = gtk_tree_path_new_first ();
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ GtkTreeSelection *selection;
+
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dialog->tree_view),
+ path, NULL, FALSE, 0, 0);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+ gtk_tree_selection_select_path (selection, path);
+ }
+ gtk_tree_path_free (path);
+}
+
+static void
+panel_addto_search_entry_activated (GtkWidget *entry,
+ PanelAddtoDialog *dialog)
+{
+ gtk_dialog_response (GTK_DIALOG (dialog->addto_dialog),
+ PANEL_ADDTO_RESPONSE_ADD);
+}
+
+static void
+panel_addto_selection_changed (GtkTreeSelection *selection,
+ PanelAddtoDialog *dialog)
+{
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+ PanelAddtoItemInfo *data;
+ char *iid;
+
+ if (!gtk_tree_selection_get_selected (selection,
+ &filter_model,
+ &filter_iter)) {
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button),
+ FALSE);
+ return;
+ }
+
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter, &filter_iter);
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter, COLUMN_DATA, &data, -1);
+
+ if (!data) {
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button),
+ FALSE);
+ return;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button), TRUE);
+
+ if (data->type == PANEL_ADDTO_LAUNCHER_MENU) {
+ gtk_button_set_label (GTK_BUTTON (dialog->add_button),
+ GTK_STOCK_GO_FORWARD);
+ } else {
+ gtk_button_set_label (GTK_BUTTON (dialog->add_button),
+ GTK_STOCK_ADD);
+ }
+ gtk_button_set_use_stock (GTK_BUTTON (dialog->add_button),
+ TRUE);
+
+ /* only allow dragging applets if we can add applets */
+ if (panel_profile_id_lists_are_writable ()) {
+ switch (data->type) {
+ case PANEL_ADDTO_LAUNCHER:
+ panel_addto_setup_launcher_drag (GTK_TREE_VIEW (dialog->tree_view),
+ data->launcher_path);
+ break;
+ case PANEL_ADDTO_APPLET:
+ panel_addto_setup_applet_drag (GTK_TREE_VIEW (dialog->tree_view),
+ data->iid);
+ break;
+ case PANEL_ADDTO_LAUNCHER_MENU:
+ gtk_tree_view_unset_rows_drag_source (GTK_TREE_VIEW (dialog->tree_view));
+ break;
+ case PANEL_ADDTO_MENU:
+ /* build the iid for menus other than the main menu */
+ if (data->iid == NULL) {
+ iid = g_strdup_printf ("MENU:%s/%s",
+ data->menu_filename,
+ data->menu_path);
+ } else {
+ iid = g_strdup (data->iid);
+ }
+ panel_addto_setup_internal_applet_drag (GTK_TREE_VIEW (dialog->tree_view),
+ iid);
+ g_free (iid);
+ break;
+ default:
+ panel_addto_setup_internal_applet_drag (GTK_TREE_VIEW (dialog->tree_view),
+ data->iid);
+ break;
+ }
+ }
+}
+
+static void
+panel_addto_selection_activated (GtkTreeView *view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ PanelAddtoDialog *dialog)
+{
+ gtk_dialog_response (GTK_DIALOG (dialog->addto_dialog),
+ PANEL_ADDTO_RESPONSE_ADD);
+}
+
+static gboolean
+panel_addto_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ int column = GPOINTER_TO_INT (data);
+ char *text;
+
+ gtk_tree_model_get (model, iter, column, &text, -1);
+
+ if (!text)
+ return TRUE;
+
+ g_free(text);
+ return FALSE;
+}
+
+static PanelAddtoDialog *
+panel_addto_dialog_new (PanelWidget *panel_widget)
+{
+ PanelAddtoDialog *dialog;
+ GtkWidget *dialog_vbox;
+ GtkWidget *vbox;
+ GtkWidget *inner_vbox;
+ GtkWidget *find_hbox;
+ GtkWidget *sw;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+
+ dialog = g_new0 (PanelAddtoDialog, 1);
+
+ g_object_set_qdata_full (G_OBJECT (panel_widget->toplevel),
+ panel_addto_dialog_quark,
+ dialog,
+ (GDestroyNotify) panel_addto_dialog_free);
+
+ dialog->panel_widget = panel_widget;
+ dialog->name_notify =
+ panel_profile_toplevel_notify_add (
+ dialog->panel_widget->toplevel,
+ "name",
+ (MateConfClientNotifyFunc) panel_addto_name_notify,
+ dialog);
+
+
+ dialog->addto_dialog = gtk_dialog_new ();
+ gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_HELP, GTK_RESPONSE_HELP);
+ dialog->back_button = gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_GO_BACK,
+ PANEL_ADDTO_RESPONSE_BACK);
+ dialog->add_button = gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_ADD,
+ PANEL_ADDTO_RESPONSE_ADD);
+ gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button), FALSE);
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog->addto_dialog),
+ FALSE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog->addto_dialog),
+ PANEL_ADDTO_RESPONSE_ADD);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog->addto_dialog), 5);
+
+ dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog->addto_dialog));
+ gtk_box_set_spacing (GTK_BOX (dialog_vbox), 2);
+
+ g_signal_connect (G_OBJECT (dialog->addto_dialog), "response",
+ G_CALLBACK (panel_addto_dialog_response), dialog);
+ g_signal_connect (dialog->addto_dialog, "destroy",
+ G_CALLBACK (panel_addto_dialog_destroy), dialog);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+ gtk_container_add (GTK_CONTAINER (dialog_vbox), vbox);
+
+ inner_vbox = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), inner_vbox, TRUE, TRUE, 0);
+
+ find_hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (inner_vbox), find_hbox, FALSE, FALSE, 0);
+
+ dialog->label = gtk_label_new_with_mnemonic ("");
+ gtk_misc_set_alignment (GTK_MISC (dialog->label), 0.0, 0.5);
+ gtk_label_set_use_markup (GTK_LABEL (dialog->label), TRUE);
+
+ gtk_box_pack_start (GTK_BOX (find_hbox), dialog->label,
+ FALSE, FALSE, 0);
+
+ dialog->search_entry = gtk_entry_new ();
+ g_signal_connect (G_OBJECT (dialog->search_entry), "changed",
+ G_CALLBACK (panel_addto_search_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->search_entry), "activate",
+ G_CALLBACK (panel_addto_search_entry_activated), dialog);
+
+ gtk_box_pack_end (GTK_BOX (find_hbox), dialog->search_entry,
+ TRUE, TRUE, 0);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (dialog->label),
+ dialog->search_entry);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (inner_vbox), sw, TRUE, TRUE, 0);
+
+ dialog->tree_view = gtk_tree_view_new ();
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->tree_view),
+ FALSE);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (dialog->tree_view));
+
+ renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
+ "xpad", 4,
+ "ypad", 4,
+ NULL);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (dialog->tree_view),
+ -1, NULL,
+ renderer,
+ "pixbuf", COLUMN_ICON,
+ NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (dialog->tree_view),
+ -1, NULL,
+ renderer,
+ "markup", COLUMN_TEXT,
+ NULL);
+
+ //FIXME use the same search than the one for the search entry?
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (dialog->tree_view),
+ COLUMN_SEARCH);
+
+ gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (dialog->tree_view),
+ panel_addto_separator_func,
+ GINT_TO_POINTER (COLUMN_TEXT),
+ NULL);
+
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->tree_view),
+ COLUMN_TEXT);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (panel_addto_selection_changed),
+ dialog);
+
+ g_signal_connect (dialog->tree_view, "row-activated",
+ G_CALLBACK (panel_addto_selection_activated),
+ dialog);
+
+ gtk_container_add (GTK_CONTAINER (sw), dialog->tree_view);
+
+ gtk_widget_show_all (vbox);
+
+ panel_toplevel_push_autohide_disabler (dialog->panel_widget->toplevel);
+ panel_widget_register_open_dialog (panel_widget,
+ dialog->addto_dialog);
+
+ panel_addto_name_change (dialog,
+ panel_toplevel_get_name (dialog->panel_widget->toplevel));
+
+ return dialog;
+}
+
+#define MAX_ADDTOPANEL_HEIGHT 490
+
+void
+panel_addto_present (GtkMenuItem *item,
+ PanelWidget *panel_widget)
+{
+ PanelAddtoDialog *dialog;
+ PanelToplevel *toplevel;
+ PanelData *pd;
+ GdkScreen *screen;
+ gint screen_height;
+ gint height;
+
+ toplevel = panel_widget->toplevel;
+ pd = g_object_get_data (G_OBJECT (toplevel), "PanelData");
+
+ if (!panel_addto_dialog_quark)
+ panel_addto_dialog_quark =
+ g_quark_from_static_string ("panel-addto-dialog");
+
+ dialog = g_object_get_qdata (G_OBJECT (toplevel),
+ panel_addto_dialog_quark);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+ screen_height = gdk_screen_get_height (screen);
+ height = MIN (MAX_ADDTOPANEL_HEIGHT, 3 * (screen_height / 4));
+
+ if (!dialog) {
+ dialog = panel_addto_dialog_new (panel_widget);
+ panel_addto_present_applets (dialog);
+ }
+
+ dialog->insertion_position = pd ? pd->insertion_pos : -1;
+ gtk_window_set_screen (GTK_WINDOW (dialog->addto_dialog), screen);
+ gtk_window_set_default_size (GTK_WINDOW (dialog->addto_dialog),
+ height * 8 / 7, height);
+ gtk_window_present (GTK_WINDOW (dialog->addto_dialog));
+}
diff --git a/mate-panel/panel-addto.h b/mate-panel/panel-addto.h
new file mode 100644
index 00000000..5a2bb993
--- /dev/null
+++ b/mate-panel/panel-addto.h
@@ -0,0 +1,39 @@
+/*
+ * panel-addto.h:
+ *
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef __PANEL_ADDTO_H__
+#define __PANEL_ADDTO_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_addto_present (GtkMenuItem *item,
+ PanelWidget *panel_widget);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_ADDTO_H__ */
diff --git a/mate-panel/panel-background-monitor.c b/mate-panel/panel-background-monitor.c
new file mode 100644
index 00000000..1b4428dd
--- /dev/null
+++ b/mate-panel/panel-background-monitor.c
@@ -0,0 +1,440 @@
+/*
+ * panel-background-monitor.c:
+ *
+ * Copyright (C) 2001, 2002 Ian McKellar <[email protected]>
+ * 2002 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ian McKellar <[email protected]>
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "panel-background-monitor.h"
+#include "panel-util.h"
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static void panel_background_monitor_changed (PanelBackgroundMonitor *monitor);
+
+static GdkFilterReturn panel_background_monitor_xevent_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data);
+
+struct _PanelBackgroundMonitorClass {
+ GObjectClass parent_class;
+ void (*changed) (PanelBackgroundMonitor *monitor);
+};
+
+struct _PanelBackgroundMonitor {
+ GObject parent_instance;
+
+ GdkScreen *screen;
+
+ Window xwindow;
+ GdkWindow *gdkwindow;
+
+ Atom xatom;
+ GdkAtom gdkatom;
+
+ GdkPixmap *gdkpixmap;
+ GdkPixbuf *gdkpixbuf;
+
+ int width;
+ int height;
+
+ gboolean display_grabbed;
+};
+
+G_DEFINE_TYPE (PanelBackgroundMonitor, panel_background_monitor, G_TYPE_OBJECT)
+
+static PanelBackgroundMonitor **global_background_monitors = NULL;
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+static void
+panel_background_monitor_finalize (GObject *object)
+{
+ PanelBackgroundMonitor *monitor;
+
+ monitor = PANEL_BACKGROUND_MONITOR (object);
+
+ gdk_window_remove_filter (
+ monitor->gdkwindow, panel_background_monitor_xevent_filter, monitor);
+ g_signal_handlers_disconnect_by_func (monitor->screen,
+ panel_background_monitor_changed, monitor);
+
+ if (monitor->gdkpixmap)
+ g_object_unref (monitor->gdkpixmap);
+ monitor->gdkpixmap = NULL;
+
+ if (monitor->gdkpixbuf)
+ g_object_unref (monitor->gdkpixbuf);
+ monitor->gdkpixbuf = NULL;
+
+ G_OBJECT_CLASS (panel_background_monitor_parent_class)->finalize (object);
+}
+
+static void
+panel_background_monitor_class_init (PanelBackgroundMonitorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ signals [CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelBackgroundMonitorClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ object_class->finalize = panel_background_monitor_finalize;
+}
+
+static void
+panel_background_monitor_init (PanelBackgroundMonitor *monitor)
+{
+ monitor->screen = NULL;
+
+ monitor->gdkwindow = NULL;
+ monitor->xwindow = None;
+
+ monitor->gdkatom = gdk_atom_intern_static_string ("_XROOTPMAP_ID");
+ monitor->xatom = gdk_x11_atom_to_xatom (monitor->gdkatom);
+
+ monitor->gdkpixmap = NULL;
+ monitor->gdkpixbuf = NULL;
+
+ monitor->display_grabbed = FALSE;
+}
+
+static void
+panel_background_monitor_connect_to_screen (PanelBackgroundMonitor *monitor,
+ GdkScreen *screen)
+{
+ if (monitor->screen != NULL && monitor->gdkwindow != NULL) {
+ gdk_window_remove_filter (monitor->gdkwindow,
+ panel_background_monitor_xevent_filter,
+ monitor);
+ }
+
+ monitor->screen = screen;
+ g_signal_connect_swapped (screen, "size-changed",
+ G_CALLBACK (panel_background_monitor_changed), monitor);
+
+ monitor->gdkwindow = gdk_screen_get_root_window (screen);
+ monitor->xwindow = gdk_x11_drawable_get_xid (monitor->gdkwindow);
+
+ gdk_window_add_filter (
+ monitor->gdkwindow, panel_background_monitor_xevent_filter, monitor);
+
+ gdk_window_set_events (
+ monitor->gdkwindow,
+ gdk_window_get_events (monitor->gdkwindow) | GDK_PROPERTY_CHANGE_MASK);
+}
+
+static PanelBackgroundMonitor *
+panel_background_monitor_new (GdkScreen *screen)
+{
+ PanelBackgroundMonitor *monitor;
+
+ monitor = g_object_new (PANEL_TYPE_BACKGROUND_MONITOR, NULL);
+
+ panel_background_monitor_connect_to_screen (monitor, screen);
+
+ return monitor;
+}
+
+PanelBackgroundMonitor *
+panel_background_monitor_get_for_screen (GdkScreen *screen)
+{
+ int screen_number;
+
+ screen_number = gdk_screen_get_number (screen);
+
+ if (!global_background_monitors) {
+ int n_screens;
+
+ n_screens = gdk_display_get_n_screens (gdk_display_get_default ());
+
+ global_background_monitors = g_new0 (PanelBackgroundMonitor *, n_screens);
+ }
+
+ if (!global_background_monitors [screen_number]) {
+ global_background_monitors [screen_number] =
+ panel_background_monitor_new (screen);
+
+ g_object_add_weak_pointer (
+ G_OBJECT (global_background_monitors [screen_number]),
+ (void **) &global_background_monitors [screen_number]);
+
+ return global_background_monitors [screen_number];
+ }
+
+ return g_object_ref (global_background_monitors [screen_number]);
+}
+
+static void
+panel_background_monitor_changed (PanelBackgroundMonitor *monitor)
+{
+ if (monitor->gdkpixmap)
+ g_object_unref (monitor->gdkpixmap);
+ monitor->gdkpixmap = NULL;
+
+ if (monitor->gdkpixbuf)
+ g_object_unref (monitor->gdkpixbuf);
+ monitor->gdkpixbuf = NULL;
+
+ g_signal_emit (monitor, signals [CHANGED], 0);
+}
+
+static GdkFilterReturn
+panel_background_monitor_xevent_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ PanelBackgroundMonitor *monitor;
+ XEvent *xev;
+
+ g_return_val_if_fail (PANEL_IS_BACKGROUND_MONITOR (data), GDK_FILTER_CONTINUE);
+
+ monitor = PANEL_BACKGROUND_MONITOR (data);
+ xev = (XEvent *) xevent;
+
+ if (xev->type == PropertyNotify &&
+ xev->xproperty.atom == monitor->xatom &&
+ xev->xproperty.window == monitor->xwindow)
+ panel_background_monitor_changed (monitor);
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+panel_background_monitor_setup_pixmap (PanelBackgroundMonitor *monitor)
+{
+ Pixmap *prop_data = NULL;
+ GdkAtom prop_type;
+
+ g_assert (monitor->display_grabbed);
+
+ if (!gdk_property_get (
+ monitor->gdkwindow, monitor->gdkatom,
+ gdk_x11_xatom_to_atom (XA_PIXMAP), 0, 10,
+ FALSE, &prop_type, NULL, NULL, (gpointer) &prop_data))
+ return;
+
+ if ((prop_type == GDK_TARGET_PIXMAP) && prop_data && prop_data [0]) {
+ GdkDisplay *display;
+
+ g_assert (monitor->gdkpixmap == NULL);
+
+ display = gdk_screen_get_display (monitor->screen);
+
+ monitor->gdkpixmap = gdk_pixmap_foreign_new_for_display (display,
+ prop_data [0]);
+
+ if (!monitor->gdkpixmap)
+ g_warning ("couldn't get background pixmap\n");
+ }
+
+ g_free (prop_data);
+}
+
+static GdkPixbuf *
+panel_background_monitor_tile_background (PanelBackgroundMonitor *monitor,
+ int width,
+ int height)
+{
+ GdkPixbuf *retval;
+ int tilewidth, tileheight;
+
+ retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+
+ tilewidth = gdk_pixbuf_get_width (monitor->gdkpixbuf);
+ tileheight = gdk_pixbuf_get_height (monitor->gdkpixbuf);
+
+ if (tilewidth == 1 && tileheight == 1) {
+ guchar *pixels;
+ int n_channels;
+ guint32 pixel = 0;
+
+ n_channels = gdk_pixbuf_get_n_channels (monitor->gdkpixbuf);
+ pixels = gdk_pixbuf_get_pixels (monitor->gdkpixbuf);
+
+ if (pixels) {
+ if (n_channels == 4)
+ pixel = ((guint32 *) pixels) [0];
+ else if (n_channels == 3)
+ pixel = pixels [0] << 24 | pixels [1] << 16 | pixels [2] << 8;
+ }
+
+ gdk_pixbuf_fill (retval, pixel);
+ } else {
+ unsigned char *data;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ cairo_pattern_t *pattern;
+
+ data = g_malloc (width * height * 4);
+ if (!data)
+ return NULL;
+
+ surface = cairo_image_surface_create_for_data (data,
+ CAIRO_FORMAT_RGB24,
+ width, height,
+ width * 4);
+ cr = cairo_create (surface);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, monitor->gdkpixbuf, 0, 0);
+ pattern = cairo_get_source (cr);
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+ retval = panel_util_cairo_rgbdata_to_pixbuf (data,
+ width, height);
+
+ g_free (data);
+ }
+
+ return retval;
+}
+
+static void
+panel_background_monitor_setup_pixbuf (PanelBackgroundMonitor *monitor)
+{
+ GdkColormap *colormap = NULL;
+ GdkDisplay *display;
+ int rwidth, rheight;
+ int pwidth, pheight;
+
+ display = gdk_screen_get_display (monitor->screen);
+
+ gdk_x11_display_grab (display);
+ monitor->display_grabbed = TRUE;
+
+ if (!monitor->gdkpixmap)
+ panel_background_monitor_setup_pixmap (monitor);
+
+ if (!monitor->gdkpixmap) {
+ gdk_x11_display_ungrab (display);
+ monitor->display_grabbed = FALSE;
+ return;
+ }
+
+ #if GTK_CHECK_VERSION(3, 0, 0)
+ pwidth = gdk_window_get_width(monitor->gdkpixmap);
+ pheight = gdk_window_get_height(monitor->gdkpixmap);
+ #else
+ gdk_drawable_get_size(GDK_DRAWABLE(monitor->gdkpixmap), &pwidth, &pheight);
+ #endif
+
+ gdk_window_get_geometry (monitor->gdkwindow,
+ NULL, NULL, &rwidth, &rheight, NULL);
+
+ monitor->width = MIN (pwidth, rwidth);
+ monitor->height = MIN (pheight, rheight);
+
+ colormap = gdk_drawable_get_colormap (monitor->gdkwindow);
+
+ g_assert (monitor->gdkpixbuf == NULL);
+ monitor->gdkpixbuf = gdk_pixbuf_get_from_drawable (
+ NULL, monitor->gdkpixmap, colormap,
+ 0, 0, 0, 0,
+ monitor->width, monitor->height);
+
+ gdk_x11_display_ungrab (display);
+ monitor->display_grabbed = FALSE;
+
+ if (monitor->gdkpixbuf == NULL)
+ return;
+
+ if ((monitor->width < rwidth || monitor->height < rheight)) {
+ GdkPixbuf *tiled;
+
+ tiled = panel_background_monitor_tile_background (
+ monitor, rwidth, rheight);
+ g_object_unref (monitor->gdkpixbuf);
+ monitor->gdkpixbuf = tiled;
+
+ monitor->width = rwidth;
+ monitor->height = rheight;
+ }
+}
+
+GdkPixbuf *
+panel_background_monitor_get_region (PanelBackgroundMonitor *monitor,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ GdkPixbuf *pixbuf, *tmpbuf;
+ int subwidth, subheight;
+ int subx, suby;
+
+ if (!monitor->gdkpixbuf)
+ panel_background_monitor_setup_pixbuf (monitor);
+
+ if (!monitor->gdkpixbuf)
+ return NULL;
+
+ subwidth = MIN (width, monitor->width - x);
+ subheight = MIN (height, monitor->height - y);
+ /* if x or y are negative numbers */
+ subwidth = MIN (subwidth, width + x);
+ subheight = MIN (subheight, height + y);
+
+ subx = MAX (x, 0);
+ suby = MAX (y, 0);
+
+ if ((subwidth <= 0) || (subheight <= 0) ||
+ (monitor->width-x < 0) || (monitor->height-y < 0) )
+ /* region is completely offscreen */
+ return gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+ width, height);
+
+ pixbuf = gdk_pixbuf_new_subpixbuf (
+ monitor->gdkpixbuf, subx, suby, subwidth, subheight);
+
+ if ((subwidth < width) || (subheight < height)) {
+ tmpbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+ width, height);
+ gdk_pixbuf_copy_area (pixbuf, 0, 0, subwidth, subheight,
+ tmpbuf, (x < 0) ? -x : 0, (y < 0) ? -y : 0);
+ g_object_unref (pixbuf);
+ pixbuf = tmpbuf;
+ }
+
+ return pixbuf;
+}
diff --git a/mate-panel/panel-background-monitor.h b/mate-panel/panel-background-monitor.h
new file mode 100644
index 00000000..b74f15fd
--- /dev/null
+++ b/mate-panel/panel-background-monitor.h
@@ -0,0 +1,60 @@
+/*
+ * panel-background-monitor.h:
+ *
+ * Copyright (C) 2001, 2002 Ian McKellar <[email protected]>
+ * 2002 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ian McKellar <[email protected]>
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_BACKGROUND_MONITOR_H__
+#define __PANEL_BACKGROUND_MONITOR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define PANEL_TYPE_BACKGROUND_MONITOR (panel_background_monitor_get_type ())
+#define PANEL_BACKGROUND_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \
+ PANEL_TYPE_BACKGROUND_MONITOR, \
+ PanelBackgroundMonitor))
+#define PANEL_BACKGROUND_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \
+ PANEL_TYPE_BACKGROUND_MONITOR, \
+ PanelBackgroundMonitorClass))
+#define PANEL_IS_BACKGROUND_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
+ PANEL_TYPE_BACKGROUND_MONITOR))
+#define PANEL_IS_BACKGROUND_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \
+ PANEL_TYPE_BACKGROUND_MONITOR))
+#define PANEL_BACKGROUND_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), \
+ PANEL_TYPE_BACKGROUND_MONITOR, \
+ PanelBackgroundMonitorClass))
+
+typedef struct _PanelBackgroundMonitorClass PanelBackgroundMonitorClass;
+typedef struct _PanelBackgroundMonitor PanelBackgroundMonitor;
+
+GType panel_background_monitor_get_type (void);
+PanelBackgroundMonitor *panel_background_monitor_get_for_screen (GdkScreen *screen);
+GdkPixbuf *panel_background_monitor_get_region (PanelBackgroundMonitor *monitor,
+ int x,
+ int y,
+ int width,
+ int height);
+
+#endif /* __PANEL_BACKGROUND_MONITOR_H__ */
diff --git a/mate-panel/panel-background.c b/mate-panel/panel-background.c
new file mode 100644
index 00000000..6341b290
--- /dev/null
+++ b/mate-panel/panel-background.c
@@ -0,0 +1,1156 @@
+/*
+ * panel-background.c: panel background rendering
+ *
+ * Copyright (C) 2002, 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-background.h"
+
+#include <string.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdk.h>
+#include <cairo.h>
+
+#include "panel-background-monitor.h"
+#include "panel-util.h"
+
+
+static gboolean panel_background_composite (PanelBackground *background);
+static void load_background_file (PanelBackground *background);
+
+
+static void
+free_prepared_resources (PanelBackground *background)
+{
+ background->prepared = FALSE;
+
+ switch (background->type) {
+ case PANEL_BACK_NONE:
+ break;
+ case PANEL_BACK_COLOR:
+ if (background->has_alpha) {
+ if (background->pixmap)
+ g_object_unref (background->pixmap);
+ background->pixmap = NULL;
+ } else {
+ if (background->colormap && background->color.gdk.pixel)
+ gdk_colormap_free_colors (
+ background->colormap,
+ &background->color.gdk, 1);
+ background->color.gdk.pixel = 0;
+ }
+ break;
+ case PANEL_BACK_IMAGE:
+ if (background->pixmap)
+ g_object_unref (background->pixmap);
+ background->pixmap = NULL;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+set_pixbuf_background (PanelBackground *background)
+{
+ g_assert (background->composited_image != NULL);
+
+ gdk_pixbuf_render_pixmap_and_mask_for_colormap (
+ background->composited_image,
+ background->colormap,
+ &background->pixmap, NULL, 128);
+
+ gdk_window_set_back_pixmap (
+ background->window, background->pixmap, FALSE);
+}
+
+static gboolean
+panel_background_prepare (PanelBackground *background)
+{
+ PanelBackgroundType effective_type;
+ GtkWidget *widget = NULL;
+
+ if (!background->colormap || !background->transformed)
+ return FALSE;
+
+ free_prepared_resources (background);
+
+ effective_type = panel_background_effective_type (background);
+
+ switch (effective_type) {
+ case PANEL_BACK_NONE:
+ if (background->default_pixmap) {
+ if (background->default_pixmap != (GdkPixmap*) GDK_PARENT_RELATIVE)
+ gdk_window_set_back_pixmap (background->window,
+ background->default_pixmap,
+ FALSE);
+ else
+ gdk_window_set_back_pixmap (background->window,
+ NULL,
+ TRUE);
+ } else
+ gdk_window_set_background (
+ background->window, &background->default_color);
+ break;
+ case PANEL_BACK_COLOR:
+ if (background->has_alpha &&
+ background->composited_image)
+ set_pixbuf_background (background);
+ else {
+ gdk_colormap_alloc_color (
+ background->colormap,
+ &background->color.gdk,
+ FALSE, TRUE);
+ gdk_window_set_background (
+ background->window, &background->color.gdk);
+ }
+ break;
+ case PANEL_BACK_IMAGE:
+ set_pixbuf_background (background);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ /* Panel applets may use the panel's background pixmap to
+ * decide how to draw themselves. Therefore, we need to
+ * make sure that all drawing has been completed before
+ * the applet looks at the pixmap. */
+ gdk_display_sync (gdk_drawable_get_display (background->window));
+
+ gdk_window_get_user_data (GDK_WINDOW (background->window),
+ (gpointer) &widget);
+
+ if (GTK_IS_WIDGET (widget))
+ gtk_widget_queue_draw (widget);
+
+ background->prepared = TRUE;
+
+ background->notify_changed (background, background->user_data);
+
+ return TRUE;
+}
+
+static void
+free_composited_resources (PanelBackground *background)
+{
+ free_prepared_resources (background);
+
+ background->composited = FALSE;
+
+ if (background->composited_image)
+ g_object_unref (background->composited_image);
+ background->composited_image = NULL;
+}
+
+static void
+background_changed (PanelBackgroundMonitor *monitor,
+ PanelBackground *background)
+{
+ GdkPixbuf *tmp;
+
+ tmp = background->desktop;
+
+ background->desktop = panel_background_monitor_get_region (
+ background->monitor,
+ background->region.x,
+ background->region.y,
+ background->region.width,
+ background->region.height);
+
+ if (tmp)
+ g_object_unref (tmp);
+
+ panel_background_composite (background);
+}
+
+static GdkPixbuf *
+get_desktop_pixbuf (PanelBackground *background)
+{
+ GdkPixbuf *desktop;
+
+ if (!background->monitor) {
+ background->monitor =
+ panel_background_monitor_get_for_screen (
+ gdk_drawable_get_screen (background->window));
+
+ background->monitor_signal =
+ g_signal_connect (
+ background->monitor, "changed",
+ G_CALLBACK (background_changed), background);
+ }
+
+ desktop = panel_background_monitor_get_region (
+ background->monitor,
+ background->region.x,
+ background->region.y,
+ background->region.width,
+ background->region.height);
+
+ return desktop;
+}
+
+static GdkPixbuf *
+composite_image_onto_desktop (PanelBackground *background)
+{
+ GdkPixbuf *retval;
+ int width, height;
+ unsigned char *data;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ cairo_pattern_t *pattern;
+
+ if (!background->desktop)
+ background->desktop = get_desktop_pixbuf (background);
+
+ if (!background->desktop)
+ return NULL;
+
+ width = gdk_pixbuf_get_width (background->desktop);
+ height = gdk_pixbuf_get_height (background->desktop);
+
+ data = g_malloc (width * height * 4);
+ if (!data)
+ return NULL;
+
+ surface = cairo_image_surface_create_for_data (data,
+ CAIRO_FORMAT_RGB24,
+ width, height,
+ width * 4);
+ cr = cairo_create (surface);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, background->desktop, 0, 0);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, background->transformed_image, 0, 0);
+ pattern = cairo_get_source (cr);
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+ retval = panel_util_cairo_rgbdata_to_pixbuf (data, width, height);
+
+ g_free (data);
+
+ return retval;
+}
+
+static GdkPixbuf *
+composite_color_onto_desktop (PanelBackground *background)
+{
+ guint32 color;
+
+ if (!background->desktop)
+ background->desktop = get_desktop_pixbuf (background);
+
+ if (!background->desktop)
+ return NULL;
+
+ color = ((background->color.gdk.red & 0xff00) << 8) +
+ (background->color.gdk.green & 0xff00) +
+ (background->color.gdk.blue >> 8);
+
+ return gdk_pixbuf_composite_color_simple (
+ background->desktop,
+ gdk_pixbuf_get_width (background->desktop),
+ gdk_pixbuf_get_height (background->desktop),
+ GDK_INTERP_NEAREST,
+ (255 - (background->color.alpha >> 8)),
+ 255, color, color);
+}
+
+static GdkPixbuf *
+get_composited_pixbuf (PanelBackground *background)
+{
+ GdkPixbuf *retval = NULL;
+
+ switch (background->type) {
+ case PANEL_BACK_NONE:
+ break;
+ case PANEL_BACK_COLOR:
+ retval = composite_color_onto_desktop (background);
+ break;
+ case PANEL_BACK_IMAGE:
+ retval = composite_image_onto_desktop (background);
+ if (!retval)
+ retval = g_object_ref (background->transformed_image);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return retval;
+}
+
+static gboolean
+panel_background_composite (PanelBackground *background)
+{
+ if (!background->transformed)
+ return FALSE;
+
+ free_composited_resources (background);
+
+ switch (background->type) {
+ case PANEL_BACK_NONE:
+ break;
+ case PANEL_BACK_COLOR:
+ if (background->has_alpha)
+ background->composited_image =
+ get_composited_pixbuf (background);
+ break;
+ case PANEL_BACK_IMAGE:
+ if (background->transformed_image) {
+ if (background->has_alpha)
+ background->composited_image =
+ get_composited_pixbuf (background);
+ else
+ background->composited_image =
+ g_object_ref (background->transformed_image);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ background->composited = TRUE;
+
+ panel_background_prepare (background);
+
+ return TRUE;
+}
+
+static void
+free_transformed_resources (PanelBackground *background)
+{
+ free_composited_resources (background);
+
+ background->transformed = FALSE;
+
+ if (background->type != PANEL_BACK_IMAGE)
+ return;
+
+ if (background->transformed_image)
+ g_object_unref (background->transformed_image);
+ background->transformed_image = NULL;
+}
+
+static GdkPixbuf *
+get_scaled_and_rotated_pixbuf (PanelBackground *background)
+{
+ GdkPixbuf *scaled;
+ GdkPixbuf *retval;
+ int orig_width, orig_height;
+ int panel_width, panel_height;
+ int width, height;
+
+ load_background_file (background);
+ if (!background->loaded_image)
+ return NULL;
+
+ orig_width = gdk_pixbuf_get_width (background->loaded_image);
+ orig_height = gdk_pixbuf_get_height (background->loaded_image);
+
+ panel_width = background->region.width;
+ panel_height = background->region.height;
+
+ width = orig_width;
+ height = orig_height;
+
+ if (background->fit_image) {
+ switch (background->orientation) {
+ case GTK_ORIENTATION_HORIZONTAL:
+ width = orig_width * panel_height / orig_height;
+ height = panel_height;
+ break;
+ case GTK_ORIENTATION_VERTICAL:
+ if (background->rotate_image) {
+ width = orig_width * panel_width / orig_height;
+ height = panel_width;
+ } else {
+ width = panel_width;
+ height = orig_height * panel_width / orig_width;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ } else if (background->stretch_image) {
+ if (background->orientation == GTK_ORIENTATION_VERTICAL &&
+ background->rotate_image) {
+ width = panel_height;
+ height = panel_width;
+ } else {
+ width = panel_width;
+ height = panel_height;
+ }
+ } else if (background->orientation == GTK_ORIENTATION_VERTICAL &&
+ background->rotate_image) {
+ int tmp = width;
+ width = height;
+ height = tmp;
+ }
+
+ if (width == orig_width &&
+ height == orig_height) {
+ scaled = background->loaded_image;
+ g_object_ref (scaled);
+ } else {
+ scaled = gdk_pixbuf_scale_simple (
+ background->loaded_image,
+ width, height,
+ GDK_INTERP_BILINEAR);
+ }
+
+ if (background->rotate_image &&
+ background->orientation == GTK_ORIENTATION_VERTICAL) {
+ if (!background->has_alpha) {
+ guchar *dest;
+ guchar *src;
+ int x, y;
+ int destrowstride;
+ int srcrowstride;
+
+ retval = gdk_pixbuf_new (
+ GDK_COLORSPACE_RGB, FALSE, 8, height, width);
+
+ dest = gdk_pixbuf_get_pixels (retval);
+ destrowstride = gdk_pixbuf_get_rowstride (retval);
+ src = gdk_pixbuf_get_pixels (scaled);
+ srcrowstride = gdk_pixbuf_get_rowstride (scaled);
+
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++) {
+ guchar *dstptr = & ( dest [3*y + destrowstride * (width - x - 1)] );
+ guchar *srcptr = & ( src [y * srcrowstride + 3*x] );
+ dstptr[0] = srcptr[0];
+ dstptr[1] = srcptr[1];
+ dstptr[2] = srcptr[2];
+ }
+
+ g_object_unref (scaled);
+ } else {
+ guint32 *dest;
+ guint32 *src;
+ int x, y;
+ int destrowstride;
+ int srcrowstride;
+
+ retval = gdk_pixbuf_new (
+ GDK_COLORSPACE_RGB, TRUE, 8, height, width);
+
+ dest = (guint32 *) gdk_pixbuf_get_pixels (retval);
+ destrowstride = gdk_pixbuf_get_rowstride (retval) / 4;
+ src = (guint32 *) gdk_pixbuf_get_pixels (scaled);
+ srcrowstride = gdk_pixbuf_get_rowstride (scaled) / 4;
+
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ dest [y + destrowstride * (width - x - 1)] =
+ src [y * srcrowstride + x];
+
+ g_object_unref (scaled);
+ }
+ } else
+ retval = scaled;
+
+ return retval;
+}
+
+static gboolean
+panel_background_transform (PanelBackground *background)
+{
+ if (background->region.width == -1)
+ return FALSE;
+
+ free_transformed_resources (background);
+
+ if (background->type == PANEL_BACK_IMAGE)
+ background->transformed_image =
+ get_scaled_and_rotated_pixbuf (background);
+
+ background->transformed = TRUE;
+
+ panel_background_composite (background);
+
+ return TRUE;
+}
+
+static void
+disconnect_background_monitor (PanelBackground *background)
+{
+ if (background->monitor) {
+ g_signal_handler_disconnect (
+ background->monitor, background->monitor_signal);
+ background->monitor_signal = -1;
+ g_object_unref (background->monitor);
+ }
+ background->monitor = NULL;
+
+ if (background->desktop)
+ g_object_unref (background->desktop);
+ background->desktop = NULL;
+}
+
+static void
+panel_background_update_has_alpha (PanelBackground *background)
+{
+ gboolean has_alpha = FALSE;
+
+ if (background->type == PANEL_BACK_COLOR)
+ has_alpha = (background->color.alpha != 0xffff);
+
+ else if (background->type == PANEL_BACK_IMAGE &&
+ background->loaded_image)
+ has_alpha = gdk_pixbuf_get_has_alpha (background->loaded_image);
+
+ background->has_alpha = has_alpha;
+
+ if (!has_alpha)
+ disconnect_background_monitor (background);
+}
+
+static void
+load_background_file (PanelBackground *background)
+{
+ GError *error = NULL;
+
+ if (!g_file_test (background->image, G_FILE_TEST_IS_REGULAR))
+ return;
+
+ //FIXME add a monitor on the file so that we reload the background
+ //when it changes
+ background->loaded_image =
+ gdk_pixbuf_new_from_file (background->image, &error);
+ if (!background->loaded_image) {
+ g_assert (error != NULL);
+ g_warning (G_STRLOC ": unable to open '%s': %s",
+ background->image, error->message);
+ g_error_free (error);
+ }
+
+ panel_background_update_has_alpha (background);
+}
+
+void
+panel_background_set_type (PanelBackground *background,
+ PanelBackgroundType type)
+{
+ if (background->type == type)
+ return;
+
+ free_transformed_resources (background);
+
+ background->type = type;
+
+ panel_background_update_has_alpha (background);
+
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_gdk_color_no_update (PanelBackground *background,
+ GdkColor *gdk_color)
+{
+ g_return_if_fail (gdk_color != NULL);
+
+ background->color.gdk.red = gdk_color->red;
+ background->color.gdk.green = gdk_color->green;
+ background->color.gdk.blue = gdk_color->blue;
+}
+
+void
+panel_background_set_gdk_color (PanelBackground *background,
+ GdkColor *gdk_color)
+{
+ g_return_if_fail (gdk_color != NULL);
+
+ if (background->color.gdk.red == gdk_color->red &&
+ background->color.gdk.green == gdk_color->green &&
+ background->color.gdk.blue == gdk_color->blue)
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_gdk_color_no_update (background, gdk_color);
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_opacity_no_update (PanelBackground *background,
+ guint16 opacity)
+{
+ background->color.alpha = opacity;
+ panel_background_update_has_alpha (background);
+}
+
+void
+panel_background_set_opacity (PanelBackground *background,
+ guint16 opacity)
+{
+ if (background->color.alpha == opacity)
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_opacity_no_update (background, opacity);
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_color_no_update (PanelBackground *background,
+ PanelColor *color)
+{
+ g_return_if_fail (color != NULL);
+
+ panel_background_set_gdk_color_no_update (background, &(color->gdk));
+ panel_background_set_opacity_no_update (background, color->alpha);
+}
+
+void
+panel_background_set_color (PanelBackground *background,
+ PanelColor *color)
+{
+ g_return_if_fail (color != NULL);
+
+ if (background->color.gdk.red == color->gdk.red &&
+ background->color.gdk.green == color->gdk.green &&
+ background->color.gdk.blue == color->gdk.blue &&
+ background->color.alpha == color->alpha)
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_color_no_update (background, color);
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_image_no_update (PanelBackground *background,
+ const char *image)
+{
+ if (background->loaded_image)
+ g_object_unref (background->loaded_image);
+ background->loaded_image = NULL;
+
+ if (background->image)
+ g_free (background->image);
+ background->image = NULL;
+
+ if (image && image [0])
+ background->image = g_strdup (image);
+
+ panel_background_update_has_alpha (background);
+}
+
+void
+panel_background_set_image (PanelBackground *background,
+ const char *image)
+{
+ if (!background->image && !image)
+ return;
+
+ if (background->image && image && !strcmp (background->image, image))
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_image_no_update (background, image);
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_fit_no_update (PanelBackground *background,
+ gboolean fit_image)
+{
+ background->fit_image = fit_image != FALSE;
+}
+
+void
+panel_background_set_fit (PanelBackground *background,
+ gboolean fit_image)
+{
+ fit_image = fit_image != FALSE;
+
+ if (background->fit_image == fit_image)
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_fit_no_update (background, fit_image);
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_stretch_no_update (PanelBackground *background,
+ gboolean stretch_image)
+{
+ background->stretch_image = stretch_image != FALSE;
+}
+
+void
+panel_background_set_stretch (PanelBackground *background,
+ gboolean stretch_image)
+{
+ stretch_image = stretch_image != FALSE;
+
+ if (background->stretch_image == stretch_image)
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_stretch_no_update (background, stretch_image);
+ panel_background_transform (background);
+}
+
+static void
+panel_background_set_rotate_no_update (PanelBackground *background,
+ gboolean rotate_image)
+{
+ background->rotate_image = rotate_image != FALSE;
+}
+
+void
+panel_background_set_rotate (PanelBackground *background,
+ gboolean rotate_image)
+{
+ rotate_image = rotate_image != FALSE;
+
+ if (background->rotate_image == rotate_image)
+ return;
+
+ free_transformed_resources (background);
+ panel_background_set_rotate_no_update (background, rotate_image);
+ panel_background_transform (background);
+}
+
+void
+panel_background_set (PanelBackground *background,
+ PanelBackgroundType type,
+ PanelColor *color,
+ const char *image,
+ gboolean fit_image,
+ gboolean stretch_image,
+ gboolean rotate_image)
+{
+ panel_background_set_color_no_update (background, color);
+ panel_background_set_image_no_update (background, image);
+ panel_background_set_fit_no_update (background, fit_image);
+ panel_background_set_stretch_no_update (background, stretch_image);
+ panel_background_set_rotate_no_update (background, rotate_image);
+ panel_background_set_type (background, type);
+}
+
+void
+panel_background_set_default_style (PanelBackground *background,
+ GdkColor *color,
+ GdkPixmap *pixmap)
+{
+ g_return_if_fail (color != NULL);
+
+ background->default_color = *color;
+
+ if (pixmap && pixmap != (GdkPixmap*) GDK_PARENT_RELATIVE)
+ g_object_ref (pixmap);
+
+ if (background->default_pixmap
+ && background->default_pixmap != (GdkPixmap*) GDK_PARENT_RELATIVE)
+ g_object_unref (background->default_pixmap);
+
+ background->default_pixmap = pixmap;
+
+ if (background->type == PANEL_BACK_NONE)
+ panel_background_prepare (background);
+}
+
+void
+panel_background_realized (PanelBackground *background,
+ GdkWindow *window)
+{
+ g_return_if_fail (window != NULL);
+
+ if (background->window && background->colormap && background->gc)
+ return;
+
+ if (!background->window)
+ background->window = g_object_ref (window);
+
+ if (!background->colormap)
+ background->colormap =
+ g_object_ref (gdk_drawable_get_colormap (window));
+
+ if (!background->gc)
+ background->gc = gdk_gc_new (window);
+
+ panel_background_prepare (background);
+}
+
+void
+panel_background_unrealized (PanelBackground *background)
+{
+ free_prepared_resources (background);
+
+ if (background->window)
+ g_object_unref (background->window);
+ background->window = NULL;
+
+ if (background->colormap)
+ g_object_unref (background->colormap);
+ background->colormap = NULL;
+
+ if (background->gc)
+ g_object_unref (background->gc);
+ background->gc = NULL;
+}
+
+void
+panel_background_change_region (PanelBackground *background,
+ GtkOrientation orientation,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ gboolean need_to_retransform = FALSE;
+ gboolean need_to_reprepare = FALSE;
+
+ if (background->region.x == x &&
+ background->region.y == y &&
+ background->region.width == width &&
+ background->region.height == height &&
+ background->orientation == orientation)
+ return;
+
+ /* we only need to retransform anything
+ on size/orientation changes if the
+ background is an image and some
+ conditions are met */
+ if (background->type == PANEL_BACK_IMAGE) {
+ if (background->orientation != orientation &&
+ background->rotate_image) {
+ /* if orientation changes and we are rotating */
+ need_to_retransform = TRUE;
+ } else if ((background->region.width != width ||
+ background->region.height != height) &&
+ (background->fit_image ||
+ background->stretch_image)) {
+ /* or if the size changes and we are
+ stretching or fitting the image */
+ need_to_retransform = TRUE;
+ }
+ }
+
+ /* if size changed, we at least need
+ to "prepare" the background again */
+ if (background->region.width != width ||
+ background->region.height != height)
+ need_to_reprepare = TRUE;
+
+ background->region.x = x;
+ background->region.y = y;
+ background->region.width = width;
+ background->region.height = height;
+
+ background->orientation = orientation;
+
+ if (background->desktop)
+ g_object_unref (background->desktop);
+ background->desktop = NULL;
+
+ if (need_to_retransform || ! background->transformed)
+ /* only retransform the background if we have in
+ fact changed size/orientation */
+ panel_background_transform (background);
+ else if (background->has_alpha || ! background->composited)
+ /* only do compositing if we have some alpha
+ value to worry about */
+ panel_background_composite (background);
+ else if (need_to_reprepare)
+ /* at least we must prepare the background
+ if the size changed */
+ panel_background_prepare (background);
+}
+
+void
+panel_background_init (PanelBackground *background,
+ PanelBackgroundChangedNotify notify_changed,
+ gpointer user_data)
+{
+ background->type = PANEL_BACK_NONE;
+ background->notify_changed = notify_changed;
+ background->user_data = user_data;
+
+ background->color.gdk.red = 0;
+ background->color.gdk.blue = 0;
+ background->color.gdk.green = 0;
+ background->color.gdk.pixel = 0;
+ background->color.alpha = 0xffff;
+
+ background->image = NULL;
+ background->loaded_image = NULL;
+
+ background->orientation = GTK_ORIENTATION_HORIZONTAL;
+ background->region.x = -1;
+ background->region.y = -1;
+ background->region.width = -1;
+ background->region.height = -1;
+ background->transformed_image = NULL;
+ background->composited_image = NULL;
+
+ background->monitor = NULL;
+ background->desktop = NULL;
+ background->monitor_signal = -1;
+
+ background->pixmap = NULL;
+ background->window = NULL;
+ background->colormap = NULL;
+ background->gc = NULL;
+
+ background->default_pixmap = NULL;
+ background->default_color.red = 0;
+ background->default_color.green = 0;
+ background->default_color.blue = 0;
+ background->default_color.pixel = 0;
+
+ background->fit_image = FALSE;
+ background->stretch_image = FALSE;
+ background->rotate_image = FALSE;
+
+ background->has_alpha = FALSE;
+
+ background->transformed = FALSE;
+ background->composited = FALSE;
+ background->prepared = FALSE;
+}
+
+void
+panel_background_free (PanelBackground *background)
+{
+ disconnect_background_monitor (background);
+
+ free_transformed_resources (background);
+
+ if (background->image)
+ g_free (background->image);
+ background->image = NULL;
+
+ if (background->loaded_image)
+ g_object_unref (background->loaded_image);
+ background->loaded_image = NULL;
+
+ if (background->monitor)
+ g_object_unref (background->monitor);
+ background->monitor = NULL;
+
+ if (background->window)
+ g_object_unref (background->window);
+ background->window = NULL;
+
+ if (background->colormap)
+ g_object_unref (background->colormap);
+ background->colormap = NULL;
+
+ if (background->gc)
+ g_object_unref (background->gc);
+ background->gc = NULL;
+
+ if (background->default_pixmap
+ && background->default_pixmap != (GdkPixmap*) GDK_PARENT_RELATIVE)
+ g_object_unref (background->default_pixmap);
+ background->default_pixmap = NULL;
+}
+
+char *
+panel_background_make_string (PanelBackground *background,
+ int x,
+ int y)
+{
+ PanelBackgroundType effective_type;
+ char *retval;
+
+ retval = NULL;
+
+ effective_type = panel_background_effective_type (background);
+
+ if (effective_type == PANEL_BACK_IMAGE ||
+ (effective_type == PANEL_BACK_COLOR && background->has_alpha)) {
+ GdkNativeWindow pixmap_xid;
+
+ if (!background->pixmap)
+ return NULL;
+
+ pixmap_xid = gdk_x11_drawable_get_xid (
+ GDK_DRAWABLE (background->pixmap));
+
+ retval = g_strdup_printf ("pixmap:%d,%d,%d", pixmap_xid, x, y);
+
+ } else if (effective_type == PANEL_BACK_COLOR)
+ retval = g_strdup_printf (
+ "color:%.4x%.4x%.4x",
+ background->color.gdk.red,
+ background->color.gdk.green,
+ background->color.gdk.blue);
+ else
+ retval = g_strdup ("none:");
+
+ return retval;
+
+}
+
+PanelBackgroundType
+panel_background_get_type (PanelBackground *background)
+{
+ return background->type;
+}
+
+const PanelColor *
+panel_background_get_color (PanelBackground *background)
+{
+ return &(background->color);
+}
+
+const GdkPixmap *
+panel_background_get_pixmap (PanelBackground *background)
+{
+ return background->pixmap;
+}
+
+
+/* What are we actually rendering - e.g. if we're supposed to
+ * be rendering an image, but haven't got a valid image, then
+ * we're rendering the default gtk background.
+ */
+PanelBackgroundType
+panel_background_effective_type (PanelBackground *background)
+{
+ PanelBackgroundType retval;
+
+ retval = background->type;
+ if (background->type == PANEL_BACK_IMAGE && !background->composited_image)
+ retval = PANEL_BACK_NONE;
+
+ return retval;
+}
+
+static void
+panel_background_set_no_background_on_widget (PanelBackground *background,
+ GtkWidget *widget)
+{
+ GtkRcStyle *rc_style;
+
+ gtk_widget_set_style (widget, NULL);
+ rc_style = gtk_rc_style_new ();
+ gtk_widget_modify_style (widget, rc_style);
+ g_object_unref (rc_style);
+}
+
+static void
+panel_background_set_image_background_on_widget (PanelBackground *background,
+ GtkWidget *widget)
+{
+ const GdkPixmap *bg_pixmap;
+ GtkAllocation allocation;
+ GdkPixmap *pixmap;
+ cairo_t *cr;
+ cairo_pattern_t *pattern;
+ GtkStyle *style;
+
+ bg_pixmap = panel_background_get_pixmap (background);
+ if (!bg_pixmap)
+ return;
+
+ gtk_widget_get_allocation (widget, &allocation);
+ pixmap = gdk_pixmap_new (gtk_widget_get_window (widget),
+ allocation.width,
+ allocation.height,
+ -1);
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
+ gdk_cairo_set_source_pixmap (cr, (GdkPixmap *) bg_pixmap,
+ -allocation.x,
+ -allocation.y);
+ pattern = cairo_get_source (cr);
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+
+ cairo_rectangle (cr, 0, 0,
+ allocation.width, allocation.height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+
+ style = gtk_style_copy (gtk_widget_get_style (widget));
+ if (style->bg_pixmap[GTK_STATE_NORMAL])
+ g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]);
+ style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (pixmap);
+ gtk_widget_set_style (widget, style);
+ g_object_unref (style);
+
+ g_object_unref (pixmap);
+}
+
+static void
+panel_background_set_color_background_on_widget (PanelBackground *background,
+ GtkWidget *widget)
+{
+ const PanelColor *color;
+
+ color = panel_background_get_color (background);
+ if (color->alpha != 0xffff) {
+ panel_background_set_image_background_on_widget (background,
+ widget);
+ return;
+ }
+
+ gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &color->gdk);
+}
+
+void
+panel_background_change_background_on_widget (PanelBackground *background,
+ GtkWidget *widget)
+{
+ PanelBackgroundType type;
+
+ panel_background_set_no_background_on_widget (background, widget);
+
+ type = panel_background_get_type (background);
+
+ switch (type) {
+ case PANEL_BACK_NONE:
+ break;
+ case PANEL_BACK_COLOR:
+ panel_background_set_color_background_on_widget (background,
+ widget);
+ break;
+ case PANEL_BACK_IMAGE:
+ panel_background_set_image_background_on_widget (background,
+ widget);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
diff --git a/mate-panel/panel-background.h b/mate-panel/panel-background.h
new file mode 100644
index 00000000..a39ae4c3
--- /dev/null
+++ b/mate-panel/panel-background.h
@@ -0,0 +1,133 @@
+/*
+ * panel-background.h: panel background rendering
+ *
+ * Copyright (C) 2002, 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_BACKGROUND_H__
+#define __PANEL_BACKGROUND_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "panel-enums.h"
+#include "panel-types.h"
+#include "panel-background-monitor.h"
+
+typedef struct _PanelBackground PanelBackground;
+
+typedef void (*PanelBackgroundChangedNotify)
+ (PanelBackground *background,
+ gpointer user_data);
+
+struct _PanelBackground {
+ PanelBackgroundType type;
+
+ PanelBackgroundChangedNotify notify_changed;
+ gpointer user_data;
+
+ PanelColor color;
+ char *image;
+ GdkPixbuf *loaded_image;
+
+ GtkOrientation orientation;
+ GdkRectangle region;
+ GdkPixbuf *transformed_image;
+ GdkPixbuf *composited_image;
+
+ PanelBackgroundMonitor *monitor;
+ GdkPixbuf *desktop;
+ gulong monitor_signal;
+
+ GdkPixmap *pixmap;
+ GdkWindow *window;
+ GdkColormap *colormap;
+ GdkGC *gc;
+
+ GdkPixmap *default_pixmap;
+ GdkColor default_color;
+
+ guint fit_image : 1;
+ guint stretch_image : 1;
+ guint rotate_image : 1;
+
+ guint has_alpha : 1;
+
+ guint loaded : 1;
+ guint transformed : 1;
+ guint composited : 1;
+ guint prepared : 1;
+};
+
+void panel_background_init (PanelBackground *background,
+ PanelBackgroundChangedNotify notify_changed,
+ gpointer user_data);
+void panel_background_free (PanelBackground *background);
+void panel_background_set (PanelBackground *background,
+ PanelBackgroundType type,
+ PanelColor *color,
+ const char *image,
+ gboolean fit_image,
+ gboolean stretch_image,
+ gboolean rotate_image);
+void panel_background_set_type (PanelBackground *background,
+ PanelBackgroundType type);
+void panel_background_set_gdk_color (PanelBackground *background,
+ GdkColor *gdk_color);
+void panel_background_set_opacity (PanelBackground *background,
+ guint16 opacity);
+void panel_background_set_color (PanelBackground *background,
+ PanelColor *color);
+void panel_background_set_image (PanelBackground *background,
+ const char *image);
+void panel_background_set_fit (PanelBackground *background,
+ gboolean fit_image);
+void panel_background_set_stretch (PanelBackground *background,
+ gboolean stretch_image);
+void panel_background_set_rotate (PanelBackground *background,
+ gboolean rotate_image);
+void panel_background_set_default_style (PanelBackground *background,
+ GdkColor *color,
+ GdkPixmap *pixmap);
+void panel_background_realized (PanelBackground *background,
+ GdkWindow *window);
+void panel_background_unrealized (PanelBackground *background);
+void panel_background_change_region (PanelBackground *background,
+ GtkOrientation orientation,
+ int x,
+ int y,
+ int width,
+ int height);
+char *panel_background_make_string (PanelBackground *background,
+ int x,
+ int y);
+
+PanelBackgroundType panel_background_get_type (PanelBackground *background);
+const PanelColor *panel_background_get_color (PanelBackground *background);
+const GdkPixmap *panel_background_get_pixmap (PanelBackground *background);
+
+PanelBackgroundType
+ panel_background_effective_type (PanelBackground *background);
+
+void panel_background_change_background_on_widget (PanelBackground *background,
+ GtkWidget *widget);
+
+#endif /* __PANEL_BACKGROUND_H__ */
diff --git a/mate-panel/panel-bindings.c b/mate-panel/panel-bindings.c
new file mode 100644
index 00000000..5b580005
--- /dev/null
+++ b/mate-panel/panel-bindings.c
@@ -0,0 +1,303 @@
+/*
+ * panel-bindings.c: panel keybindings support module
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-bindings.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "panel-mateconf.h"
+#include "panel-profile.h"
+#include "panel-xutils.h"
+
+#define BINDINGS_PREFIX "/apps/marco/window_keybindings"
+#define MOUSE_MODIFIER_DIR "/apps/marco/general"
+#define MOUSE_MODIFIER_KEY "/apps/marco/general/mouse_button_modifier"
+#define DEFAULT_MOUSE_MODIFIER GDK_MOD1_MASK
+
+typedef struct {
+ char *key;
+ char *signal;
+ guint keyval;
+ GdkModifierType modifiers;
+} PanelBinding;
+
+static gboolean initialised = FALSE;
+
+static PanelBinding bindings [] = {
+ { "activate_window_menu", "popup-panel-menu", 0, 0 },
+ { "toggle_maximized", "toggle-expand", 0, 0 },
+ { "maximize", "expand", 0, 0 },
+ { "unmaximize", "unexpand", 0, 0 },
+ { "toggle_shaded", "toggle-hidden", 0, 0 },
+ { "begin_move", "begin-move", 0, 0 },
+ { "begin_resize", "begin-resize", 0, 0 },
+};
+
+static guint mouse_button_modifier_keymask = DEFAULT_MOUSE_MODIFIER;
+
+static void
+panel_binding_set_from_string (PanelBinding *binding,
+ const char *str)
+{
+ g_assert (binding->keyval == 0);
+ g_assert (binding->modifiers == 0);
+
+ if (!str || !str [0] || !strcmp (str, "disabled")) {
+ binding->keyval = 0;
+ binding->modifiers = 0;
+ return;
+ }
+
+ gtk_accelerator_parse (str, &binding->keyval, &binding->modifiers);
+ if (binding->keyval == 0 && binding->modifiers == 0) {
+ g_warning ("Unable to parse binding '%s'\n", str);
+ return;
+ }
+}
+
+static inline GtkBindingSet *
+get_binding_set (GtkBindingSet *binding_set)
+{
+ if (!binding_set) {
+ PanelToplevelClass *toplevel_class;
+
+ toplevel_class = g_type_class_peek (PANEL_TYPE_TOPLEVEL);
+ if (!toplevel_class)
+ return NULL;
+
+ g_assert (PANEL_IS_TOPLEVEL_CLASS (toplevel_class));
+
+ binding_set = gtk_binding_set_by_class (toplevel_class);
+ }
+
+ return binding_set;
+}
+
+static void
+panel_binding_clear_entry (PanelBinding *binding,
+ GtkBindingSet *binding_set)
+{
+ binding_set = get_binding_set (binding_set);
+
+ gtk_binding_entry_remove (binding_set, binding->keyval, binding->modifiers);
+}
+
+static void
+panel_binding_set_entry (PanelBinding *binding,
+ GtkBindingSet *binding_set)
+{
+ binding_set = get_binding_set (binding_set);
+
+ gtk_binding_entry_add_signal (binding_set,
+ binding->keyval,
+ binding->modifiers,
+ binding->signal,
+ 0);
+}
+
+static void
+panel_binding_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelBinding *binding)
+{
+ MateConfValue *value;
+
+ if (binding->keyval)
+ panel_binding_clear_entry (binding, NULL);
+
+ binding->keyval = 0;
+ binding->modifiers = 0;
+
+ value = mateconf_entry_get_value (entry);
+
+ if (!value || value->type != MATECONF_VALUE_STRING)
+ return;
+
+ panel_binding_set_from_string (binding, mateconf_value_get_string (value));
+
+ if (!binding->keyval)
+ return;
+
+ panel_binding_set_entry (binding, NULL);
+}
+
+static void
+panel_binding_watch (PanelBinding *binding,
+ const char *key)
+{
+ GError *error = NULL;
+
+ mateconf_client_notify_add (panel_mateconf_get_client (), key,
+ (MateConfClientNotifyFunc) panel_binding_changed,
+ binding, NULL, &error);
+ if (error) {
+ g_warning ("Error watching mateconf key '%s': %s",
+ key, error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+panel_bindings_mouse_modifier_set_from_string (const char *str)
+{
+ guint modifier_keysym;
+ guint modifier_keymask;
+
+ gtk_accelerator_parse (str, &modifier_keysym, &modifier_keymask);
+
+ if (modifier_keysym == 0 && modifier_keymask == 0) {
+ g_warning ("Unable to parse mouse modifier '%s'\n", str);
+ return;
+ }
+
+ if (modifier_keymask)
+ mouse_button_modifier_keymask = modifier_keymask;
+ else
+ mouse_button_modifier_keymask = DEFAULT_MOUSE_MODIFIER;
+}
+
+static void
+panel_bindings_mouse_modifier_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ MateConfValue *value;
+ const char *str;
+
+ value = mateconf_entry_get_value (entry);
+
+ if (!value || value->type != MATECONF_VALUE_STRING)
+ return;
+
+ str = mateconf_value_get_string (value);
+ panel_bindings_mouse_modifier_set_from_string (str);
+}
+
+static void
+panel_bindings_initialise (void)
+{
+ MateConfClient *client;
+ GError *error;
+ int i;
+ char *str;
+
+ if (initialised)
+ return;
+
+ client = panel_mateconf_get_client ();
+
+ error = NULL;
+ mateconf_client_add_dir (client, BINDINGS_PREFIX,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL, &error);
+ if (error) {
+ g_warning ("Error loading mateconf directory '%s': %s",
+ BINDINGS_PREFIX, error->message),
+ g_error_free (error);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (bindings); i++) {
+ const char *key;
+
+ key = panel_mateconf_sprintf ("%s/%s", BINDINGS_PREFIX, bindings [i].key);
+
+ error = NULL;
+ str = mateconf_client_get_string (client, key, &error);
+ if (error) {
+ g_warning ("Error getting value for '%s': %s",
+ key, error->message);
+ g_error_free (error);
+ continue;
+ }
+
+ panel_binding_set_from_string (&bindings [i], str);
+ panel_binding_watch (&bindings [i], key);
+
+ g_free (str);
+ }
+
+ /* mouse button modifier */
+ error = NULL;
+ mateconf_client_add_dir (client, MOUSE_MODIFIER_DIR,
+ MATECONF_CLIENT_PRELOAD_NONE, &error);
+ if (error) {
+ g_warning ("Error loading mateconf directory '%s': %s",
+ MOUSE_MODIFIER_DIR, error->message),
+ g_error_free (error);
+ }
+
+ error = NULL;
+ mateconf_client_notify_add (client, MOUSE_MODIFIER_KEY,
+ panel_bindings_mouse_modifier_changed,
+ NULL, NULL, &error);
+ if (error) {
+ g_warning ("Error watching mateconf key '%s': %s",
+ MOUSE_MODIFIER_KEY, error->message);
+ g_error_free (error);
+ }
+
+ error = NULL;
+ str = mateconf_client_get_string (client, MOUSE_MODIFIER_KEY, &error);
+ if (error) {
+ g_warning ("Error getting value for '%s': %s",
+ MOUSE_MODIFIER_KEY, error->message);
+ g_error_free (error);
+ } else {
+ panel_bindings_mouse_modifier_set_from_string (str);
+ g_free (str);
+ }
+
+ initialised = TRUE;
+}
+
+void
+panel_bindings_set_entries (GtkBindingSet *binding_set)
+{
+ int i;
+
+ if (!initialised)
+ panel_bindings_initialise ();
+
+ for (i = 0; i < G_N_ELEMENTS (bindings); i++) {
+ if (!bindings [i].keyval)
+ continue;
+
+ panel_binding_set_entry (&bindings [i], binding_set);
+ }
+}
+
+guint
+panel_bindings_get_mouse_button_modifier_keymask (void)
+{
+ g_assert (mouse_button_modifier_keymask != 0);
+
+ if (!initialised)
+ panel_bindings_initialise ();
+
+ return panel_get_real_modifier_mask (mouse_button_modifier_keymask);
+}
diff --git a/mate-panel/panel-bindings.h b/mate-panel/panel-bindings.h
new file mode 100644
index 00000000..e9b2d850
--- /dev/null
+++ b/mate-panel/panel-bindings.h
@@ -0,0 +1,42 @@
+/*
+ * panel-bindings.h: panel keybindings support module
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_BINDINGS_H__
+#define __PANEL_BINDINGS_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_bindings_set_entries (GtkBindingSet *binding_set);
+guint panel_bindings_get_mouse_button_modifier_keymask (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_BINDINGS_H__ */
diff --git a/mate-panel/panel-compatibility.c b/mate-panel/panel-compatibility.c
new file mode 100644
index 00000000..a746f695
--- /dev/null
+++ b/mate-panel/panel-compatibility.c
@@ -0,0 +1,1167 @@
+/*
+ * panel-compatibility.c: panel backwards compatibility support
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "string.h"
+
+#include <libpanel-util/panel-glib.h>
+
+#include "panel-compatibility.h"
+
+#include "panel-profile.h"
+#include "panel-menu-bar.h"
+#include "mate-panel-applet-frame.h"
+#include "mate-panel-applets-manager.h"
+#include "panel-globals.h"
+#include "panel-util.h"
+
+typedef enum {
+ PANEL_ORIENT_UP,
+ PANEL_ORIENT_DOWN,
+ PANEL_ORIENT_LEFT,
+ PANEL_ORIENT_RIGHT,
+} PanelOrient;
+
+static MateConfEnumStringPair panel_orient_map [] = {
+ { PANEL_ORIENT_UP, "panel-orient-up" },
+ { PANEL_ORIENT_DOWN, "panel-orient-down" },
+ { PANEL_ORIENT_LEFT, "panel-orient-left" },
+ { PANEL_ORIENT_RIGHT, "panel-orient-right" },
+ { 0, NULL }
+};
+
+static gboolean
+panel_compatibility_map_orient_string (const char *str,
+ PanelOrient *orient)
+{
+ int mapped;
+
+ g_return_val_if_fail (orient != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_orient_map, str, &mapped))
+ return FALSE;
+
+ *orient = mapped;
+
+ return TRUE;
+}
+
+static MateConfEnumStringPair panel_orientation_map [] = {
+ { GTK_ORIENTATION_HORIZONTAL, "panel-orientation-horizontal" },
+ { GTK_ORIENTATION_VERTICAL, "panel-orientation-vertical" },
+ { 0, NULL }
+};
+
+
+static gboolean
+panel_compatibility_map_orientation_string (const char *str,
+ GtkOrientation *orientation)
+{
+ int mapped;
+
+ g_return_val_if_fail (orientation != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_orientation_map, str, &mapped))
+ return FALSE;
+
+ *orientation = mapped;
+
+ return TRUE;
+}
+
+typedef enum {
+ BORDER_TOP,
+ BORDER_RIGHT,
+ BORDER_BOTTOM,
+ BORDER_LEFT
+} BorderEdge;
+
+static MateConfEnumStringPair panel_edge_map [] = {
+ { BORDER_TOP, "panel-edge-top" },
+ { BORDER_RIGHT, "panel-edge-right" },
+ { BORDER_BOTTOM, "panel-edge-bottom" },
+ { BORDER_LEFT, "panel-edge-left" },
+ { 0, NULL }
+};
+
+static gboolean
+panel_compatibility_map_edge_string (const char *str,
+ BorderEdge *edge)
+{
+ int mapped;
+
+ g_return_val_if_fail (edge != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_edge_map, str, &mapped))
+ return FALSE;
+
+ *edge = mapped;
+
+ return TRUE;
+}
+
+typedef enum {
+ EDGE_PANEL,
+ DRAWER_PANEL,
+ ALIGNED_PANEL,
+ SLIDING_PANEL,
+ FLOATING_PANEL,
+ MENU_PANEL
+} PanelType;
+
+static MateConfEnumStringPair panel_type_map [] = {
+ { EDGE_PANEL, "edge-panel" },
+ { DRAWER_PANEL, "drawer-panel" },
+ { ALIGNED_PANEL, "aligned-panel" },
+ { SLIDING_PANEL, "sliding-panel" },
+ { FLOATING_PANEL, "floating-panel" },
+ { MENU_PANEL, "menu-panel" },
+ { 0, NULL }
+};
+
+static gboolean
+panel_compatibility_map_panel_type_string (const char *str,
+ PanelType *type)
+{
+ int mapped;
+
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_type_map, str, &mapped))
+ return FALSE;
+
+ *type = mapped;
+
+ return TRUE;
+}
+
+enum {
+ PANEL_SIZE_XX_SMALL = 12,
+ PANEL_SIZE_X_SMALL = 24,
+ PANEL_SIZE_SMALL = 36,
+ PANEL_SIZE_MEDIUM = 48,
+ PANEL_SIZE_LARGE = 64,
+ PANEL_SIZE_X_LARGE = 80,
+ PANEL_SIZE_XX_LARGE = 128
+};
+
+static MateConfEnumStringPair panel_size_map [] = {
+ { PANEL_SIZE_XX_SMALL, "panel-size-xx-small" },
+ { PANEL_SIZE_X_SMALL, "panel-size-x-small" },
+ { PANEL_SIZE_SMALL, "panel-size-small" },
+ { PANEL_SIZE_MEDIUM, "panel-size-medium" },
+ { PANEL_SIZE_LARGE, "panel-size-large" },
+ { PANEL_SIZE_X_LARGE, "panel-size-x-large" },
+ { PANEL_SIZE_XX_LARGE, "panel-size-xx-large" },
+ { 0, NULL }
+};
+
+static gboolean
+panel_compatibility_map_panel_size_string (const char *str,
+ int *size)
+{
+ int mapped;
+
+ g_return_val_if_fail (size != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_size_map, str, &mapped))
+ return FALSE;
+
+ *size = mapped;
+
+ return TRUE;
+}
+
+static MateConfEnumStringPair panel_background_type_map [] = {
+ { PANEL_BACK_NONE, "no-background" },
+ { PANEL_BACK_COLOR, "color-background" },
+ { PANEL_BACK_IMAGE, "pixmap-background" },
+ { 0, NULL }
+};
+
+static gboolean
+panel_compatibility_map_background_type_string (const char *str,
+ PanelBackgroundType *type)
+{
+ int mapped;
+
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_background_type_map, str, &mapped))
+ return FALSE;
+
+ *type = mapped;
+
+ return TRUE;
+}
+
+static void
+panel_compatibility_migrate_background_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ PanelBackgroundType type;
+ const char *key;
+ char *background_dir;
+ char *type_str;
+ char *color_str;
+ char *image_str;
+ gboolean fit;
+ gboolean stretch;
+ gboolean rotate;
+ int opacity;
+
+ background_dir = mateconf_concat_dir_and_key (toplevel_dir, "background");
+
+ /* panel_background_type -> background/type */
+ key = panel_mateconf_sprintf ("%s/panel_background_type", panel_dir);
+ type_str = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_compatibility_map_background_type_string (type_str, &type)) {
+ key = panel_mateconf_sprintf ("%s/type", background_dir);
+ mateconf_client_set_string (client,
+ key,
+ panel_profile_map_background_type (type),
+ NULL);
+ }
+
+ g_free (type_str);
+
+ /* panel_background_color -> background/color */
+ key = panel_mateconf_sprintf ("%s/panel_background_color", panel_dir);
+ color_str = mateconf_client_get_string (client, key, NULL);
+
+ if (color_str) {
+ key = panel_mateconf_sprintf ("%s/color", background_dir);
+ mateconf_client_set_string (client, key, color_str, NULL);
+ }
+
+ g_free (color_str);
+
+ /* panel_background_color_alpha -> background/opacity */
+ key = panel_mateconf_sprintf ("%s/panel_background_color_alpha", panel_dir);
+ opacity = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/opacity", background_dir);
+ mateconf_client_set_int (client, key, opacity, NULL);
+
+ /* panel_background_pixmap -> background/image */
+ key = panel_mateconf_sprintf ("%s/panel_background_pixmap", panel_dir);
+ image_str = mateconf_client_get_string (client, key, NULL);
+
+ if (image_str) {
+ key = panel_mateconf_sprintf ("%s/image", background_dir);
+ mateconf_client_set_string (client, key, image_str, NULL);
+ }
+
+ g_free (image_str);
+
+ /* panel_background_pixmap_fit -> background/fit */
+ key = panel_mateconf_sprintf ("%s/panel_background_pixmap_fit", panel_dir);
+ fit = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/fit", background_dir);
+ mateconf_client_set_bool (client, key, fit, NULL);
+
+ /* panel_background_pixmap_stretch -> background/stretch */
+ key = panel_mateconf_sprintf ("%s/panel_background_pixmap_stretch", panel_dir);
+ stretch = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/stretch", background_dir);
+ mateconf_client_set_bool (client, key, stretch, NULL);
+
+ /* panel_background_pixmap_rotate -> background/rotate */
+ key = panel_mateconf_sprintf ("%s/panel_background_pixmap_rotate", panel_dir);
+ rotate = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/rotate", background_dir);
+ mateconf_client_set_bool (client, key, rotate, NULL);
+
+ g_free (background_dir);
+}
+
+static void
+panel_compatibility_migrate_edge_setting (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ BorderEdge edge;
+ const char *key;
+ char *edge_str;
+
+ key = panel_mateconf_sprintf ("%s/screen_edge", panel_dir);
+ edge_str = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_compatibility_map_edge_string (edge_str, &edge)) {
+ PanelOrientation orientation;
+
+ switch (edge) {
+ case BORDER_TOP:
+ orientation = PANEL_ORIENTATION_TOP;
+ break;
+ case BORDER_BOTTOM:
+ orientation = PANEL_ORIENTATION_BOTTOM;
+ break;
+ case BORDER_LEFT:
+ orientation = PANEL_ORIENTATION_LEFT;
+ break;
+ case BORDER_RIGHT:
+ orientation = PANEL_ORIENTATION_RIGHT;
+ break;
+ default:
+ orientation = 0;
+ g_assert_not_reached ();
+ break;
+ }
+
+ key = panel_mateconf_sprintf ("%s/orientation", toplevel_dir);
+ mateconf_client_set_string (client,
+ key,
+ panel_profile_map_orientation (orientation),
+ NULL);
+ }
+
+ g_free (edge_str);
+}
+
+static void
+panel_compatibility_migrate_edge_panel_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ const char *key;
+
+ key = panel_mateconf_sprintf ("%s/expand", toplevel_dir);
+ mateconf_client_set_bool (client, key, TRUE, NULL);
+
+ panel_compatibility_migrate_edge_setting (client, toplevel_dir, panel_dir);
+}
+
+static void
+panel_compatibility_migrate_drawer_panel_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ PanelOrient orient;
+ const char *key;
+ char *orient_str;
+
+ key = panel_mateconf_sprintf ("%s/expand", toplevel_dir);
+ mateconf_client_set_bool (client, key, FALSE, NULL);
+
+ key = panel_mateconf_sprintf ("%s/panel_orient", panel_dir);
+ orient_str = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_compatibility_map_orient_string (orient_str, &orient)) {
+ PanelOrientation orientation;
+
+ switch (orient) {
+ case PANEL_ORIENT_DOWN:
+ orientation = PANEL_ORIENTATION_TOP;
+ break;
+ case PANEL_ORIENT_UP:
+ orientation = PANEL_ORIENTATION_BOTTOM;
+ break;
+ case PANEL_ORIENT_RIGHT:
+ orientation = PANEL_ORIENTATION_LEFT;
+ break;
+ case PANEL_ORIENT_LEFT:
+ orientation = PANEL_ORIENTATION_RIGHT;
+ break;
+ default:
+ orientation = 0;
+ g_assert_not_reached ();
+ break;
+ }
+
+ key = panel_mateconf_sprintf ("%s/orientation", toplevel_dir);
+ mateconf_client_set_string (client,
+ key,
+ panel_profile_map_orientation (orientation),
+ NULL);
+ }
+
+ g_free (orient_str);
+}
+
+static void
+panel_compatibility_migrate_corner_panel_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+
+{
+ const char *key;
+
+ key = panel_mateconf_sprintf ("%s/expand", toplevel_dir);
+ mateconf_client_set_bool (client, key, FALSE, NULL);
+
+ /* screen edge */
+ panel_compatibility_migrate_edge_setting (client, toplevel_dir, panel_dir);
+
+ g_warning ("FIXME: implement migrating the 'panel_align' setting");
+}
+
+static void
+panel_compatibility_migrate_sliding_panel_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ const char *key;
+
+ key = panel_mateconf_sprintf ("%s/expand", toplevel_dir);
+ mateconf_client_set_bool (client, key, FALSE, NULL);
+
+ /* screen edge */
+ panel_compatibility_migrate_edge_setting (client, toplevel_dir, panel_dir);
+
+ g_warning ("FIXME: implement migrating the 'panel_anchor' and 'panel_offset' settings");
+}
+
+static void
+panel_compatibility_migrate_floating_panel_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ GtkOrientation orientation;
+ const char *key;
+ char *orientation_str;
+ int x, y;
+
+ key = panel_mateconf_sprintf ("%s/expand", toplevel_dir);
+ mateconf_client_set_bool (client, key, FALSE, NULL);
+
+ key = panel_mateconf_sprintf ("%s/panel_orient", panel_dir);
+ orientation_str = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_compatibility_map_orientation_string (orientation_str, &orientation)) {
+ PanelOrientation panel_orientation;
+
+ switch (orientation) {
+ case GTK_ORIENTATION_HORIZONTAL:
+ panel_orientation = PANEL_ORIENTATION_TOP;
+ break;
+ case GTK_ORIENTATION_VERTICAL:
+ panel_orientation = PANEL_ORIENTATION_LEFT;
+ break;
+ default:
+ panel_orientation = 0;
+ g_assert_not_reached ();
+ break;
+ }
+
+ key = panel_mateconf_sprintf ("%s/orientation", toplevel_dir);
+ mateconf_client_set_string (client,
+ key,
+ panel_profile_map_orientation (panel_orientation),
+ NULL);
+ }
+
+ g_free (orientation_str);
+
+ /* x */
+ key = panel_mateconf_sprintf ("%s/panel_x_position", panel_dir);
+ x = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/x", toplevel_dir);
+ mateconf_client_set_int (client, key, x, NULL);
+
+ /* y */
+ key = panel_mateconf_sprintf ("%s/panel_y_position", panel_dir);
+ y = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/y", toplevel_dir);
+ mateconf_client_set_int (client, key, y, NULL);
+}
+
+static void
+panel_compatibility_migrate_menu_panel_settings (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir)
+{
+ const char *key;
+ const char *toplevel_id;
+ char *id;
+
+ key = panel_mateconf_sprintf ("%s/expand", toplevel_dir);
+ mateconf_client_set_bool (client, key, TRUE, NULL);
+
+ key = panel_mateconf_sprintf ("%s/orientation", toplevel_dir);
+ mateconf_client_set_string (client, key,
+ panel_profile_map_orientation (PANEL_ORIENTATION_TOP),
+ NULL);
+
+ toplevel_id = panel_mateconf_basename (toplevel_dir);
+
+ /* menu bar on far right corner */
+ id = panel_profile_prepare_object_with_id (PANEL_OBJECT_MENU_BAR, toplevel_id, 0, FALSE);
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+ g_free (id);
+
+ /* window menu on far left corner */
+ id = panel_profile_prepare_object_with_id (PANEL_OBJECT_APPLET, toplevel_id, 0, TRUE);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_APPLETS, id, "matecomponent_iid");
+ mateconf_client_set_string (client, key, "OAFIID:MATE_WindowMenuApplet", NULL);
+
+ panel_profile_add_to_list (PANEL_MATECONF_APPLETS, id);
+ g_free (id);
+}
+
+static void
+panel_compatibility_migrate_panel_type (MateConfClient *client,
+ const char *toplevel_dir,
+ const char *panel_dir,
+ gboolean *is_drawer)
+{
+ PanelType type;
+ const char *key;
+ char *type_str;
+
+ key = panel_mateconf_sprintf ("%s/panel_type", panel_dir);
+ type_str = mateconf_client_get_string (client, key, NULL);
+
+ if (!panel_compatibility_map_panel_type_string (type_str, &type)) {
+ g_free (type_str);
+ return;
+ }
+
+ g_free (type_str);
+
+ switch (type) {
+ case EDGE_PANEL:
+ panel_compatibility_migrate_edge_panel_settings (client, toplevel_dir, panel_dir);
+ break;
+ case DRAWER_PANEL:
+ panel_compatibility_migrate_drawer_panel_settings (client, toplevel_dir, panel_dir);
+ *is_drawer = TRUE;
+ break;
+ case ALIGNED_PANEL:
+ panel_compatibility_migrate_corner_panel_settings (client, toplevel_dir, panel_dir);
+ break;
+ case SLIDING_PANEL:
+ panel_compatibility_migrate_sliding_panel_settings (client, toplevel_dir, panel_dir);
+ break;
+ case FLOATING_PANEL:
+ panel_compatibility_migrate_floating_panel_settings (client, toplevel_dir, panel_dir);
+ break;
+ case MENU_PANEL:
+ panel_compatibility_migrate_menu_panel_settings (client, toplevel_dir, panel_dir);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static char *
+panel_compatibility_migrate_panel_settings (MateConfClient *client,
+ GSList *toplevel_id_list,
+ const char *panel_id,
+ gboolean *is_drawer)
+{
+ const char *key;
+ char *toplevel_id;
+ char *toplevel_dir;
+ char *panel_dir;
+ char *size_str;
+ int screen;
+ int monitor;
+ int size;
+ gboolean enable_buttons;
+ gboolean enable_arrows;
+ gboolean auto_hide;
+
+ toplevel_id = panel_profile_find_new_id (PANEL_MATECONF_TOPLEVELS);
+
+ toplevel_dir = g_strdup_printf (PANEL_CONFIG_DIR "/toplevels/%s", toplevel_id);
+ panel_dir = g_strdup_printf (PANEL_CONFIG_DIR "/panels/%s", panel_id);
+
+ panel_mateconf_associate_schemas_in_dir (
+ client, toplevel_dir, PANEL_SCHEMAS_DIR "/toplevels");
+
+ /* screen */
+ key = panel_mateconf_sprintf ("%s/screen", panel_dir);
+ screen = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/screen", toplevel_dir);
+ mateconf_client_set_int (client, key, screen, NULL);
+
+ /* monitor */
+ key = panel_mateconf_sprintf ("%s/monitor", panel_dir);
+ monitor = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/monitor", toplevel_dir);
+ mateconf_client_set_int (client, key, monitor, NULL);
+
+ /* size */
+ key = panel_mateconf_sprintf ("%s/panel_size", panel_dir);
+ size_str = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_compatibility_map_panel_size_string (size_str, &size)) {
+ key = panel_mateconf_sprintf ("%s/size", toplevel_dir);
+ mateconf_client_set_int (client, key, size, NULL);
+ }
+
+ g_free (size_str);
+
+ /* enable_buttons */
+ key = panel_mateconf_sprintf ("%s/hide_buttons_enabled", panel_dir);
+ enable_buttons = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/enable_buttons", toplevel_dir);
+ mateconf_client_set_bool (client, key, enable_buttons, NULL);
+
+ /* enable_arrows */
+ key = panel_mateconf_sprintf ("%s/hide_button_pixmaps_enabled", panel_dir);
+ enable_arrows = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/enable_arrows", toplevel_dir);
+ mateconf_client_set_bool (client, key, enable_arrows, NULL);
+
+ /* auto hide */
+ key = panel_mateconf_sprintf ("%s/panel_hide_mode", panel_dir);
+ auto_hide = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/auto_hide", toplevel_dir);
+ mateconf_client_set_bool (client, key, auto_hide, NULL);
+
+ /* migrate different panel types to toplevels */
+ panel_compatibility_migrate_panel_type (client, toplevel_dir, panel_dir, is_drawer);
+
+ /* background settings */
+ panel_compatibility_migrate_background_settings (client, toplevel_dir, panel_dir);
+
+ g_free (toplevel_dir);
+ g_free (panel_dir);
+
+ return toplevel_id;
+}
+
+static gboolean
+panel_compatibility_migrate_panel_id (MateConfClient *client,
+ PanelMateConfKeyType key_type,
+ const char *object_id,
+ GHashTable *panel_id_hash)
+{
+ const char *key;
+ char *panel_id;
+ char *toplevel_id;
+ gboolean retval = FALSE;
+
+ /* panel_id -> toplevel_id */
+ key = panel_mateconf_full_key (key_type, object_id, "panel_id");
+ panel_id = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_id && (toplevel_id = g_hash_table_lookup (panel_id_hash, panel_id))) {
+ key = panel_mateconf_full_key (key_type, object_id, "toplevel_id");
+ mateconf_client_set_string (client, key, toplevel_id, NULL);
+
+ retval = TRUE;
+ }
+
+ g_free (panel_id);
+
+ return retval;
+}
+
+static void
+panel_compatibility_migrate_drawer_settings (MateConfClient *client,
+ PanelMateConfKeyType key_type,
+ const char *object_id,
+ GHashTable *panel_id_hash)
+{
+ const char *key;
+ char *toplevel_id;
+ char *panel_id;
+ char *custom_icon;
+ char *pixmap;
+
+ /* unique-drawer-panel-id -> attached_toplevel_id */
+ key = panel_mateconf_full_key (key_type, object_id, "attached_toplevel_id");
+ toplevel_id = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_full_key (key_type, object_id, "unique-drawer-panel-id");
+ panel_id = mateconf_client_get_string (client, key, NULL);
+
+ if (!toplevel_id && panel_id &&
+ (toplevel_id = g_hash_table_lookup (panel_id_hash, panel_id))) {
+ key = panel_mateconf_full_key (key_type, object_id, "attached_toplevel_id");
+ mateconf_client_set_string (client, key, toplevel_id, NULL);
+
+ toplevel_id = NULL;
+ }
+
+ /* pixmap -> custom_icon */
+ key = panel_mateconf_full_key (key_type, object_id, "custom_icon");
+ custom_icon = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_full_key (key_type, object_id, "pixmap");
+ pixmap = mateconf_client_get_string (client, key, NULL);
+
+ if (!custom_icon && pixmap) {
+ key = panel_mateconf_full_key (key_type, object_id, "custom_icon");
+ mateconf_client_set_string (client, key, pixmap, NULL);
+
+ key = panel_mateconf_full_key (key_type, object_id, "use_custom_icon");
+ mateconf_client_set_bool (client, key, TRUE, NULL);
+ }
+
+ g_free (toplevel_id);
+ g_free (panel_id);
+ g_free (custom_icon);
+ g_free (pixmap);
+}
+
+static void
+panel_compatibility_migrate_menu_button_settings (MateConfClient *client,
+ PanelMateConfKeyType key_type,
+ const char *object_id)
+{
+ const char *key;
+ gboolean use_custom_icon;
+ gboolean use_menu_path;
+ char *custom_icon;
+ char *menu_path;
+
+ /* custom-icon -> use_custom_icon */
+ key = panel_mateconf_full_key (key_type, object_id, "custom-icon");
+ use_custom_icon = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_full_key (key_type, object_id, "use_custom_icon");
+ mateconf_client_set_bool (client, key, use_custom_icon, NULL);
+
+ /* custom-icon-file -> custom_icon */
+ key = panel_mateconf_full_key (key_type, object_id, "custom-icon-file");
+ custom_icon = mateconf_client_get_string (client, key, NULL);
+
+ if (custom_icon) {
+ key = panel_mateconf_full_key (key_type, object_id, "custom_icon");
+ mateconf_client_set_string (client, key, custom_icon, NULL);
+ }
+
+ /* main_menu -> ! use_menu_path */
+ key = panel_mateconf_full_key (key_type, object_id, "main-menu");
+ use_menu_path = ! mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_full_key (key_type, object_id, "use_menu_path");
+ mateconf_client_set_bool (client, key, use_menu_path, NULL);
+
+ /* path -> menu_path */
+ key = panel_mateconf_full_key (key_type, object_id, "path");
+ menu_path = mateconf_client_get_string (client, key, NULL);
+
+ if (menu_path) {
+ key = panel_mateconf_full_key (key_type, object_id, "menu_path");
+ mateconf_client_set_string (client, key, menu_path, NULL);
+ }
+
+ g_free (custom_icon);
+ g_free (menu_path);
+}
+
+static void
+panel_compatibility_migrate_objects (MateConfClient *client,
+ PanelMateConfKeyType key_type,
+ GHashTable *panel_id_hash)
+{
+ const char *key;
+ GSList *l, *objects;
+
+ key = panel_mateconf_general_key (panel_mateconf_key_type_to_id_list (key_type));
+ objects = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ for (l = objects; l; l = l->next) {
+ const char *id = l->data;
+ PanelObjectType object_type;
+ char *object_type_str;
+
+ if (!panel_compatibility_migrate_panel_id (client, key_type, id, panel_id_hash)) {
+ g_free (l->data);
+ continue;
+ }
+
+ key = panel_mateconf_full_key (key_type, id, "object_type");
+ object_type_str = mateconf_client_get_string (client, key, NULL);
+
+ if (panel_profile_map_object_type_string (object_type_str, &object_type)) {
+ switch (object_type) {
+ case PANEL_OBJECT_DRAWER:
+ panel_compatibility_migrate_drawer_settings (
+ client, key_type, id, panel_id_hash);
+ break;
+ case PANEL_OBJECT_MENU:
+ panel_compatibility_migrate_menu_button_settings (
+ client, key_type, id);
+ break;
+ default:
+ break;
+ }
+ }
+ g_free (object_type_str);
+ g_free (l->data);
+ }
+ g_slist_free (objects);
+}
+
+/* Major hack, but we now set toplevel_id_list in the defaults database,
+ * so we need to figure out if its actually set in the users database.
+ */
+
+static MateConfEngine *
+get_homedir_source (void)
+{
+ MateConfEngine *engine;
+ GError *error = NULL;
+ char *source;
+
+ source = g_strdup_printf ("xml:readwrite:%s/.mateconf", g_get_home_dir ());
+
+ if (!(engine = mateconf_engine_get_for_address (source, &error))) {
+#if 0
+ g_warning ("Cannot get MateConf source '%s': %s\n",
+ source, error->message);
+#endif
+ g_error_free (error);
+ g_free (source);
+ return NULL;
+ }
+
+ g_free (source);
+
+ return engine;
+}
+
+static gboolean
+is_general_key_set (MateConfEngine *engine,
+ const char *config_dir,
+ const char *general_key)
+{
+ MateConfEntry *entry;
+ const char *key;
+ gboolean retval;
+
+ key = panel_mateconf_sprintf ("%s/general/%s", config_dir, general_key);
+
+ if (!(entry = mateconf_engine_get_entry (engine, key, NULL, FALSE, NULL)))
+ return FALSE;
+
+ retval = mateconf_entry_get_value (entry) != NULL ||
+ mateconf_entry_get_schema_name (entry) != NULL;
+
+ mateconf_entry_unref (entry);
+
+ return retval;
+}
+
+static gboolean
+panel_compatibility_detect_needs_migration (void)
+{
+ MateConfEngine *engine;
+ gboolean needs_migration = FALSE;
+
+ if (!(engine = get_homedir_source ()))
+ return FALSE;
+
+ if (!is_general_key_set (engine, PANEL_CONFIG_DIR, "panel_id_list"))
+ goto no_migration;
+
+ if (is_general_key_set (engine, PANEL_CONFIG_DIR, "toplevel_id_list"))
+ goto no_migration;
+
+ needs_migration = TRUE;
+
+ no_migration:
+ mateconf_engine_unref (engine);
+
+ return needs_migration;
+}
+
+/* If toplevel_id_list is unset, migrate all the panels in
+ * panel_id_list to toplevels
+ */
+void
+panel_compatibility_migrate_panel_id_list (MateConfClient *client)
+{
+ GHashTable *panel_id_hash;
+ const char *key;
+ GSList *panel_id_list;
+ GSList *toplevel_id_list = NULL;
+ GSList *l;
+
+ if (!panel_compatibility_detect_needs_migration ())
+ return;
+
+ panel_id_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ key = panel_mateconf_general_key ("panel_id_list");
+ panel_id_list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ for (l = panel_id_list; l; l = l->next) {
+ char *new_id;
+ gboolean is_drawer = FALSE;
+
+ new_id = panel_compatibility_migrate_panel_settings (client,
+ toplevel_id_list,
+ l->data,
+ &is_drawer);
+
+ /* Drawer toplevels don't belong on the toplevel list */
+ if (!is_drawer)
+ toplevel_id_list = g_slist_prepend (toplevel_id_list, new_id);
+
+ g_hash_table_insert (panel_id_hash, l->data, new_id);
+ }
+
+ key = panel_mateconf_general_key ("toplevel_id_list");
+ mateconf_client_set_list (client, key, MATECONF_VALUE_STRING, toplevel_id_list, NULL);
+
+ g_slist_free (panel_id_list);
+ g_slist_free (toplevel_id_list);
+
+ panel_compatibility_migrate_objects (client, PANEL_MATECONF_OBJECTS, panel_id_hash);
+ panel_compatibility_migrate_objects (client, PANEL_MATECONF_APPLETS, panel_id_hash);
+
+ g_hash_table_destroy (panel_id_hash);
+}
+
+static void
+copy_mateconf_dir (MateConfClient *client,
+ const char *src_dir,
+ const char *dest_dir)
+{
+ GSList *list, *l;
+
+ list = mateconf_client_all_entries (client, src_dir, NULL);
+ for (l = list; l; l = l->next) {
+ MateConfEntry *entry = l->data;
+ const char *key;
+ char *tmp;
+
+ tmp = g_path_get_basename (mateconf_entry_get_key (entry));
+ key = panel_mateconf_sprintf ("%s/%s", dest_dir, tmp);
+ g_free (tmp);
+
+ if (mateconf_entry_get_schema_name (entry))
+ mateconf_engine_associate_schema (client->engine,
+ key,
+ mateconf_entry_get_schema_name (entry),
+ NULL);
+
+ if (entry->value)
+ mateconf_client_set (client, key, entry->value, NULL);
+
+ mateconf_entry_unref (entry);
+ }
+ g_slist_free (list);
+
+ list = mateconf_client_all_dirs (client, src_dir, NULL);
+ for (l = list; l; l = l->next) {
+ char *subdir = l->data;
+ char *src_subdir;
+ char *dest_subdir;
+ char *tmp;
+
+ tmp = g_path_get_basename (subdir);
+ src_subdir = mateconf_concat_dir_and_key (src_dir, tmp);
+ dest_subdir = mateconf_concat_dir_and_key (dest_dir, tmp);
+ g_free (tmp);
+
+ copy_mateconf_dir (client, src_subdir, dest_subdir);
+
+ g_free (src_subdir);
+ g_free (dest_subdir);
+ g_free (subdir);
+ }
+
+ g_slist_free (list);
+}
+
+void
+panel_compatibility_maybe_copy_old_config (MateConfClient *client)
+{
+ MateConfEngine *engine;
+ const char *key;
+
+ key = panel_mateconf_general_key ("profiles_migrated");
+ if (mateconf_client_get_bool (client, key, NULL))
+ return;
+
+ if (!(engine = get_homedir_source ()))
+ goto no_migration_needed;;
+
+ if (!is_general_key_set (engine, PANEL_OLD_CONFIG_DIR, "panel_id_list") &&
+ !is_general_key_set (engine, PANEL_OLD_CONFIG_DIR, "toplevel_id_list") &&
+ !is_general_key_set (engine, PANEL_OLD_CONFIG_DIR, "applet_id_list") &&
+ !is_general_key_set (engine, PANEL_OLD_CONFIG_DIR, "object_id_list"))
+ goto no_migration_needed;
+
+ copy_mateconf_dir (client, PANEL_OLD_CONFIG_DIR, PANEL_CONFIG_DIR);
+
+ key = panel_mateconf_general_key ("profiles_migrated");
+ mateconf_client_set_bool (client, key, TRUE, NULL);
+
+ no_migration_needed:
+ if (engine)
+ mateconf_engine_unref (engine);
+}
+
+void
+panel_compatibility_migrate_applications_scheme (MateConfClient *client,
+ const char *key)
+{
+ char *location;
+
+ location = mateconf_client_get_string (client, key, NULL);
+
+ if (!location)
+ return;
+
+ if (!strncmp (location, "applications:", strlen ("applications:")) ||
+ !strncmp (location, "applications-all-users:", strlen ("applications-all-users:")) ||
+ !strncmp (location, "all-applications:", strlen ("all-applications:")) ||
+ !strncmp (location, "preferences:", strlen ("preferences:")) ||
+ !strncmp (location, "preferences-all-users:", strlen ("preferences-all-users:")) ||
+ !strncmp (location, "all-preferences:", strlen ("all-preferences:")) ||
+ !strncmp (location, "system-settings:", strlen ("system-settings:")) ||
+ !strncmp (location, "server-settings:", strlen ("server-settings:"))) {
+ char *basename;
+ char *new_location;
+
+ basename = g_path_get_basename (location);
+ new_location = panel_g_lookup_in_applications_dirs (basename);
+ g_free (basename);
+
+ if (new_location != NULL) {
+ mateconf_client_set_string (client, key,
+ new_location, NULL);
+ g_free (new_location);
+ }
+ }
+
+ g_free (location);
+}
+
+void
+panel_compatibility_migrate_screenshot_action (MateConfClient *client,
+ const char *id)
+{
+ const char *key;
+
+ panel_profile_remove_from_list (PANEL_MATECONF_OBJECTS, id);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id,
+ "launcher_location");
+ mateconf_client_set_string (client, key, "mate-screenshot.desktop", NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id,
+ "object_type");
+ //FIXME: ideally, we would use panel_object_type_map, but it's private
+ //in panel-profile.c
+ mateconf_client_set_string (client, key, "launcher-object", NULL);
+
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+}
+
+gchar *
+panel_compatibility_get_applet_iid (const gchar *id)
+{
+ MateConfClient *client = panel_mateconf_get_client ();
+ MatePanelAppletInfo *info;
+ const char *key;
+ gchar *applet_iid;
+ gboolean needs_migration;
+ const char *iid;
+
+ /*
+ * There are two compatibility steps here:
+ *
+ * 1) we need to migrate from matecomponent_iid to applet_iid if there's no
+ * value in the applet_iid key. Always.
+ *
+ * 2) we need to try to migrate the iid to a new iid. We can't assume
+ * that the fact that the applet_iid key was used mean anything
+ * since the value there could well be a matecomponent iid.
+ * The reason we really have to try to migrate first is this case:
+ * if an applet was added with the matecomponent iid but gets ported later
+ * to dbus, then the reference to the matecomponent iid will only be valid
+ * as an old reference.
+ * And if migration fails, we just use the iid as it is.
+ */
+
+ needs_migration = FALSE;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_APPLETS, id, "applet_iid");
+ applet_iid = mateconf_client_get_string (client, key, NULL);
+
+ if (!applet_iid || !applet_iid[0]) {
+ needs_migration = TRUE;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_APPLETS, id, "matecomponent_iid");
+ applet_iid = mateconf_client_get_string (client, key, NULL);
+
+ if (!applet_iid || !applet_iid[0])
+ return NULL;
+ }
+
+ info = mate_panel_applets_manager_get_applet_info_from_old_id (applet_iid);
+ if (!info)
+ info = mate_panel_applets_manager_get_applet_info (applet_iid);
+
+ if (!info)
+ return NULL;
+
+ iid = mate_panel_applet_info_get_iid (info);
+
+ /* migrate if the iid in the configuration is different than the real
+ * iid that will get used */
+ if (!g_str_equal (iid, applet_iid))
+ needs_migration = TRUE;
+
+ g_free (applet_iid);
+
+ if (needs_migration) {
+ key = panel_mateconf_full_key (PANEL_MATECONF_APPLETS, id, "applet_iid");
+ mateconf_client_set_string (client, key, iid, NULL);
+ }
+
+ return g_strdup (iid);
+}
diff --git a/mate-panel/panel-compatibility.h b/mate-panel/panel-compatibility.h
new file mode 100644
index 00000000..4413fb95
--- /dev/null
+++ b/mate-panel/panel-compatibility.h
@@ -0,0 +1,48 @@
+/*
+ * panel-compatibility.h: panel backwards compatibility support
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_COMPATIBILITY_H__
+#define __PANEL_COMPATIBILITY_H__
+
+#include <glib.h>
+#include <mateconf/mateconf-client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_compatibility_migrate_panel_id_list (MateConfClient *client);
+void panel_compatibility_maybe_copy_old_config (MateConfClient *client);
+void panel_compatibility_migrate_applications_scheme (MateConfClient *client,
+ const char *key);
+void panel_compatibility_migrate_screenshot_action (MateConfClient *client,
+ const char *id);
+
+gchar *panel_compatibility_get_applet_iid (const gchar *id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_MENU_BAR_H__ */
diff --git a/mate-panel/panel-compatibility.schemas b/mate-panel/panel-compatibility.schemas
new file mode 100644
index 00000000..ea4a7a68
--- /dev/null
+++ b/mate-panel/panel-compatibility.schemas
@@ -0,0 +1,546 @@
+<?xml version="1.0"?>
+<mateconfschemafile>
+
+<!--
+ Schemas to maintain compatibility with the 2.0/2.2 configurations.
+
+ The problem being addressed here is that because the 2.0/2.2 panel
+ applies schemas to keys at runtime, existing user configurations
+ will end up with dangling references to the old schemas unless we
+ install these old schemas.
+
+ For example, a 2.0/2.2 panel will apply the medium/general/panel_id_list
+ schema to profiles/default/general/panel_id_list. This association
+ is in the user's configuration, not in the system MateConf database.
+ If the user never changes panel_id_list and logs into a machine without
+ this schema, then panel_id_list will be empty.
+ -->
+
+ <schemalist>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/general/panel_id_list</key>
+ <owner>panel</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[00000001,00000002]</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/general/applet_id_list</key>
+ <owner>panel</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[00000001,00000002,00000003,00000004,show_desktop_button]</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/general/object_id_list</key>
+ <owner>panel</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[00000001,00000002]</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>edge-panel</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_size</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>panel-size-x-small</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_hide_mode</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_hide_state</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/screen</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/monitor</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/screen_edge</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>panel-edge-bottom</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/hide_buttons_enabled</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/hide_button_pixmaps_enabled</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>no-background</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_pixmap</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_pixmap_fit</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_pixmap_stretch</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_pixmap_rotate</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_color</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>#ffffff</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000001/panel_background_color_alpha</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>65535</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000001/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>launcher-object</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000001/launcher_location</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>applications:///caja.desktop</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000001/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000002</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000001/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>20</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000001/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000002/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>launcher-object</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000002/launcher_location</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>applications:///System/mate-terminal.desktop</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000002/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000002</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000002/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>25</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/objects/00000002/panel_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/show_desktop_button/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>matecomponent-applet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/show_desktop_button/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000001</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/show_desktop_button/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/show_desktop_button/matecomponent_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>OAFIID:MATE_ShowDesktopApplet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/show_desktop_button/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000001/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>matecomponent-applet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000001/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000001</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000001/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>1</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000001/matecomponent_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>OAFIID:MATE_TasklistApplet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000001/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000002/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>matecomponent-applet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000002/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000001</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000002/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000002/matecomponent_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>OAFIID:MATE_PagerApplet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000002/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000003/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>matecomponent-applet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000003/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000002</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000003/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000003/matecomponent_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>OAFIID:MATE_MixerApplet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000003/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000004/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>matecomponent-applet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000004/panel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>00000002</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000004/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000004/matecomponent_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>OAFIID:MATE_ClockApplet</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/applets/00000004/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>menu-panel</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_size</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>panel-size-x-small</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/screen</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/monitor</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_background_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>no-background</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_background_pixmap</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default> </default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_background_pixmap_fit</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_background_pixmap_stretch</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_background_pixmap_rotate</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/panel_background_color</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>#000000</default>
+ <locale name="C"/>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/default_profiles/medium/panels/00000002/clock_format</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>%I:%M %p</default>
+ <locale name="C"/>
+ </schema>
+
+ </schemalist>
+
+</mateconfschemafile>
diff --git a/mate-panel/panel-config-global.c b/mate-panel/panel-config-global.c
new file mode 100644
index 00000000..1ed3348a
--- /dev/null
+++ b/mate-panel/panel-config-global.c
@@ -0,0 +1,153 @@
+/*
+ * panel-config-global.c: panel global configuration module
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ * Glynn Foster <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-config-global.h"
+
+#include <string.h>
+#include <mateconf/mateconf.h>
+
+#include "panel-globals.h"
+#include "panel-mateconf.h"
+
+typedef struct {
+ guint tooltips_enabled : 1;
+ guint enable_animations : 1;
+ guint drawer_auto_close : 1;
+ guint confirm_panel_remove : 1;
+ guint highlight_when_over : 1;
+} GlobalConfig;
+
+static GlobalConfig global_config = { 0, };
+static gboolean global_config_initialised = FALSE;
+
+gboolean
+panel_global_config_get_highlight_when_over (void)
+{
+ g_assert (global_config_initialised == TRUE);
+
+ return global_config.highlight_when_over;
+}
+
+gboolean
+panel_global_config_get_enable_animations (void)
+{
+ g_assert (global_config_initialised == TRUE);
+
+ return global_config.enable_animations;
+}
+
+gboolean
+panel_global_config_get_drawer_auto_close (void)
+{
+ g_assert (global_config_initialised == TRUE);
+
+ return global_config.drawer_auto_close;
+}
+
+gboolean
+panel_global_config_get_tooltips_enabled (void)
+{
+ g_assert (global_config_initialised == TRUE);
+
+ return global_config.tooltips_enabled;
+}
+
+gboolean
+panel_global_config_get_confirm_panel_remove (void)
+{
+ g_assert (global_config_initialised == TRUE);
+
+ return global_config.confirm_panel_remove;
+}
+
+static void
+panel_global_config_set_entry (MateConfEntry *entry)
+{
+ MateConfValue *value;
+ const char *key;
+
+ g_return_if_fail (entry != NULL);
+
+ value = mateconf_entry_get_value (entry);
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+
+ if (!value || !key)
+ return;
+
+ if (strcmp (key, "tooltips_enabled") == 0)
+ global_config.tooltips_enabled =
+ mateconf_value_get_bool (value);
+
+ else if (strcmp (key, "enable_animations") == 0)
+ global_config.enable_animations =
+ mateconf_value_get_bool (value);
+
+ else if (strcmp (key, "drawer_autoclose") == 0)
+ global_config.drawer_auto_close =
+ mateconf_value_get_bool (value);
+
+ else if (strcmp (key, "confirm_panel_remove") == 0)
+ global_config.confirm_panel_remove =
+ mateconf_value_get_bool (value);
+
+ else if (strcmp (key, "highlight_launchers_on_mouseover") == 0)
+ global_config.highlight_when_over =
+ mateconf_value_get_bool (value);
+}
+
+static void
+panel_global_config_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ panel_global_config_set_entry (entry);
+}
+
+void
+panel_global_config_load (void)
+{
+ MateConfClient *client;
+ GSList *l, *entries;
+ const char *key = "/apps/panel/global";
+
+ client = panel_mateconf_get_client ();
+
+ mateconf_client_add_dir (client, key, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ entries = mateconf_client_all_entries (client, key, NULL);
+
+ for (l = entries; l; l = l->next) {
+ panel_global_config_set_entry (l->data);
+ mateconf_entry_unref (l->data);
+ }
+ g_slist_free (entries);
+
+ mateconf_client_notify_add (client, key, panel_global_config_notify, NULL, NULL, NULL);
+
+ global_config_initialised = TRUE;
+}
diff --git a/mate-panel/panel-config-global.h b/mate-panel/panel-config-global.h
new file mode 100644
index 00000000..da3f1641
--- /dev/null
+++ b/mate-panel/panel-config-global.h
@@ -0,0 +1,47 @@
+/*
+ * panel-config-global.h: panel global configuration module
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ * Glynn Foster <[email protected]>
+ */
+
+#ifndef __PANEL_CONFIG_GLOBAL_H__
+#define __PANEL_CONFIG_GLOBAL_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_global_config_load (void);
+
+gboolean panel_global_config_get_highlight_when_over (void);
+gboolean panel_global_config_get_enable_animations (void);
+gboolean panel_global_config_get_drawer_auto_close (void);
+gboolean panel_global_config_get_tooltips_enabled (void);
+gboolean panel_global_config_get_confirm_panel_remove (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_CONFIG_GLOBAL_H__ */
diff --git a/mate-panel/panel-context-menu.c b/mate-panel/panel-context-menu.c
new file mode 100644
index 00000000..a267a140
--- /dev/null
+++ b/mate-panel/panel-context-menu.c
@@ -0,0 +1,307 @@
+/*
+ * panel-context-menu.c: context menu for the panels
+ *
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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.
+ *
+ * Most of the original code come from menu.c
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ *
+ */
+
+#include <config.h>
+
+#include "panel-context-menu.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-show.h>
+
+#include "nothing.h"
+#include "panel-util.h"
+#include "panel.h"
+#include "menu.h"
+#include "applet.h"
+#include "panel-config-global.h"
+#include "panel-profile.h"
+#include "panel-properties-dialog.h"
+#include "panel-lockdown.h"
+#include "panel-addto.h"
+#include "panel-icon-names.h"
+
+static void
+panel_context_menu_show_help (GtkWidget *w,
+ gpointer data)
+{
+ panel_show_help (gtk_widget_get_screen (w),
+ "user-guide", "gospanel-1", NULL);
+}
+
+static gboolean
+panel_context_menu_check_for_screen (GtkWidget *w,
+ GdkEvent *ev,
+ gpointer data)
+{
+ static int times = 0;
+ if (ev->type != GDK_KEY_PRESS)
+ return FALSE;
+ if (ev->key.keyval == GDK_f ||
+ ev->key.keyval == GDK_F) {
+ times++;
+ if (times == 3) {
+ times = 0;
+ start_screen_check ();
+ }
+ }
+ return FALSE;
+}
+
+static void
+panel_context_menu_show_about_dialog (GtkWidget *menuitem)
+{
+ static GtkWidget *about = NULL;
+ char *authors [] = {
+ "Alex Larsson <[email protected]>",
+ "Anders Carlsson <[email protected]>",
+ "Arvind Samptur <[email protected]>",
+ "Darin Adler <[email protected]>",
+ "Elliot Lee <[email protected]>",
+ "Federico Mena <[email protected]>",
+ "George Lebl <[email protected]>",
+ "Glynn Foster <[email protected]>",
+ "Ian Main <[email protected]>",
+ "Ian McKellar <[email protected]>",
+ "Jacob Berkman <[email protected]>",
+ "Mark McLoughlin <[email protected]>",
+ "Martin Baulig <[email protected]>",
+ "Miguel de Icaza <[email protected]>",
+ "Owen Taylor <[email protected]>",
+ "Padraig O'Briain <[email protected]>",
+ "Seth Nickell <[email protected]>",
+ "Stephen Browne <[email protected]>",
+ "Tom Tromey <[email protected]>",
+ "Vincent Untz <[email protected]>",
+ N_("And many, many others..."),
+ NULL
+ };
+ char *documenters[] = {
+ "Alexander Kirillov <[email protected]>",
+ "Dan Mueth <[email protected]>",
+ "Dave Mason <[email protected]>",
+ NULL
+ };
+ int i;
+
+ if (about) {
+ gtk_window_set_screen (GTK_WINDOW (about),
+ menuitem_to_screen (menuitem));
+ gtk_window_present (GTK_WINDOW (about));
+ return;
+ }
+
+ for (i = 0; authors [i]; i++)
+ authors [i] = _(authors [i]);
+
+ /* Note: we don't use gtk_show_about_dialog() since some applets can
+ * be loaded in this process and we don't want to share the about
+ * dialog */
+ about = gtk_about_dialog_new ();
+ g_object_set (about,
+ "program-name", _("The MATE Panel"),
+ "version", VERSION,
+ "copyright", "Copyright \xc2\xa9 1997-2003 Free Software Foundation, Inc.",
+ "comments", _("This program is responsible for launching other "
+ "applications and provides useful utilities."),
+ "authors", authors,
+ "documenters", documenters,
+ "title", _("About the MATE Panel"),
+ "translator-credits", _("translator-credits"),
+ "logo-icon-name", PANEL_ICON_PANEL,
+ NULL);
+
+ gtk_window_set_screen (GTK_WINDOW (about),
+ menuitem_to_screen (menuitem));
+ g_signal_connect (about, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &about);
+ g_signal_connect (about, "event",
+ G_CALLBACK (panel_context_menu_check_for_screen),
+ NULL);
+
+ g_signal_connect (about, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ gtk_widget_show (about);
+}
+
+static void
+panel_context_menu_create_new_panel (GtkWidget *menuitem)
+{
+ panel_profile_create_toplevel (gtk_widget_get_screen (menuitem));
+}
+
+static void
+panel_context_menu_delete_panel (PanelToplevel *toplevel)
+{
+ if (panel_toplevel_is_last_unattached (toplevel)) {
+ panel_error_dialog (GTK_WINDOW (toplevel),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)),
+ "cannot_delete_last_panel", TRUE,
+ _("Cannot delete this panel"),
+ _("You must always have at least one panel."));
+ return;
+ }
+
+ panel_delete (toplevel);
+}
+
+static void
+panel_context_menu_setup_delete_panel_item (GtkWidget *menu,
+ GtkWidget *menuitem)
+{
+ PanelWidget *panel_widget;
+ gboolean sensitive;
+
+ panel_widget = menu_get_panel (menu);
+
+ g_assert (PANEL_IS_TOPLEVEL (panel_widget->toplevel));
+
+ sensitive =
+ !panel_toplevel_is_last_unattached (panel_widget->toplevel) &&
+ !panel_lockdown_get_locked_down () &&
+ panel_profile_id_lists_are_writable ();
+
+ gtk_widget_set_sensitive (menuitem, sensitive);
+}
+
+static void
+panel_context_menu_build_edition (PanelWidget *panel_widget,
+ GtkWidget *menu)
+{
+ GtkWidget *menuitem;
+ GtkWidget *image;
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Add to Panel..."));
+ image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ g_signal_connect (G_OBJECT (menuitem), "activate",
+ G_CALLBACK (panel_addto_present), panel_widget);
+
+ if (!panel_profile_id_lists_are_writable ())
+ gtk_widget_set_sensitive (menuitem, FALSE);
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Properties"));
+ image = gtk_image_new_from_stock (GTK_STOCK_PROPERTIES,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ g_signal_connect_swapped (menuitem, "activate",
+ G_CALLBACK (panel_properties_dialog_present),
+ panel_widget->toplevel);
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Delete This Panel"));
+ image = gtk_image_new_from_stock (GTK_STOCK_DELETE,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
+ G_CALLBACK (panel_context_menu_delete_panel),
+ panel_widget->toplevel);
+ g_signal_connect (G_OBJECT (menu), "show",
+ G_CALLBACK (panel_context_menu_setup_delete_panel_item),
+ menuitem);
+
+ add_menu_separator (menu);
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("_New Panel"));
+ image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (panel_context_menu_create_new_panel),
+ NULL);
+ gtk_widget_set_sensitive (menuitem,
+ panel_profile_id_lists_are_writable ());
+
+ add_menu_separator (menu);
+}
+
+GtkWidget *
+panel_context_menu_create (PanelWidget *panel)
+{
+ GtkWidget *retval;
+ GtkWidget *menuitem;
+ GtkWidget *image;
+
+ if (panel->master_widget) {
+ gpointer *pointer;
+ AppletInfo *info;
+
+ pointer = g_object_get_data (G_OBJECT (panel->master_widget),
+ "applet_info");
+
+ g_assert (pointer != NULL);
+ info = (AppletInfo *) pointer;
+
+ if (info->menu == NULL) {
+ info->menu = mate_panel_applet_create_menu (info);
+ }
+
+ return info->menu;
+ }
+
+ retval = create_empty_menu ();
+ gtk_widget_set_name (retval, "mate-panel-context-menu");
+
+ if (!panel_lockdown_get_locked_down ())
+ panel_context_menu_build_edition (panel, retval);
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Help"));
+ image = gtk_image_new_from_stock (GTK_STOCK_HELP, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (retval), menuitem);
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (panel_context_menu_show_help), NULL);
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (_("A_bout Panels"));
+ image = gtk_image_new_from_stock (GTK_STOCK_ABOUT,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (retval), menuitem);
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (panel_context_menu_show_about_dialog),
+ NULL);
+
+ //FIXME: can we get rid of this? (needed by menu_get_panel())
+ g_object_set_data (G_OBJECT (retval), "menu_panel", panel);
+
+ return retval;
+}
diff --git a/mate-panel/panel-context-menu.h b/mate-panel/panel-context-menu.h
new file mode 100644
index 00000000..562e530c
--- /dev/null
+++ b/mate-panel/panel-context-menu.h
@@ -0,0 +1,33 @@
+/*
+ * panel-context-menu.h: context menu for the panels
+ *
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ *
+ */
+
+#ifndef __PANEL_CONTEXT_MENU_H__
+#define __PANEL_CONTEXT_MENU_H__
+
+#include "panel-widget.h"
+
+GtkWidget *panel_context_menu_create (PanelWidget *panel);
+
+#endif /* __PANEL_CONTEXT_MENU_H__ */
diff --git a/mate-panel/panel-default-setup.entries b/mate-panel/panel-default-setup.entries
new file mode 100644
index 00000000..aad2f5d5
--- /dev/null
+++ b/mate-panel/panel-default-setup.entries
@@ -0,0 +1,657 @@
+<mateconfentryfile>
+
+ <entrylist base="/apps/panel/default_setup">
+
+ <!-- List of toplevels -->
+
+ <entry>
+ <key>general/toplevel_id_list</key>
+ <schema_key>/schemas/apps/panel/general/toplevel_id_list</schema_key>
+ <value>
+ <list type="string">
+ <value>
+ <string>top_panel</string>
+ </value>
+ <value>
+ <string>bottom_panel</string>
+ </value>
+ </list>
+ </value>
+ </entry>
+
+ <!-- List of objects -->
+
+ <entry>
+ <key>general/object_id_list</key>
+ <schema_key>/schemas/apps/panel/general/object_id_list</schema_key>
+ <value>
+ <list type="string">
+ <value>
+ <string>menu_bar</string>
+ </value>
+ <value>
+ <string>browser_launcher</string>
+ </value>
+ <value>
+ <string>email_launcher</string>
+ </value>
+ </list>
+ </value>
+ </entry>
+
+ <!-- List of applets -->
+
+ <entry>
+ <key>general/applet_id_list</key>
+ <schema_key>/schemas/apps/panel/general/applet_id_list</schema_key>
+ <value>
+ <list type="string">
+ <value>
+ <string>window_menu</string>
+ </value>
+ <value>
+ <string>clock</string>
+ </value>
+ <value>
+ <string>notification_area</string>
+ </value>
+ <value>
+ <string>show_desktop_button</string>
+ </value>
+ <value>
+ <string>window_list</string>
+ </value>
+ <value>
+ <string>workspace_switcher</string>
+ </value>
+ </list>
+ </value>
+ </entry>
+
+ <!-- Top Panel -->
+
+ <entry>
+ <key>toplevels/top_panel/expand</key>
+ <schema_key>/schemas/apps/panel/toplevels/expand</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>toplevels/top_panel/orientation</key>
+ <schema_key>/schemas/apps/panel/toplevels/orientation</schema_key>
+ <value>
+ <string>top</string>
+ </value>
+ </entry>
+ <entry>
+ <key>toplevels/top_panel/size</key>
+ <schema_key>/schemas/apps/panel/toplevels/size</schema_key>
+ <value>
+ <int>24</int>
+ </value>
+ </entry>
+
+ <entry><key>toplevels/top_panel/name</key><schema_key>/schemas/apps/panel/toplevels/name</schema_key></entry>
+ <entry><key>toplevels/top_panel/screen</key><schema_key>/schemas/apps/panel/toplevels/screen</schema_key></entry>
+ <entry><key>toplevels/top_panel/monitor</key><schema_key>/schemas/apps/panel/toplevels/monitor</schema_key></entry>
+ <entry><key>toplevels/top_panel/x</key><schema_key>/schemas/apps/panel/toplevels/x</schema_key></entry>
+ <entry><key>toplevels/top_panel/y</key><schema_key>/schemas/apps/panel/toplevels/y</schema_key></entry>
+ <entry><key>toplevels/top_panel/x_right</key><schema_key>/schemas/apps/panel/toplevels/x_right</schema_key></entry>
+ <entry><key>toplevels/top_panel/y_bottom</key><schema_key>/schemas/apps/panel/toplevels/y_bottom</schema_key></entry>
+ <entry><key>toplevels/top_panel/x_centered</key><schema_key>/schemas/apps/panel/toplevels/x_centered</schema_key></entry>
+ <entry><key>toplevels/top_panel/y_centered</key><schema_key>/schemas/apps/panel/toplevels/y_centered</schema_key></entry>
+ <entry><key>toplevels/top_panel/auto_hide</key><schema_key>/schemas/apps/panel/toplevels/auto_hide</schema_key></entry>
+ <entry><key>toplevels/top_panel/enable_animations</key><schema_key>/schemas/apps/panel/toplevels/enable_animations</schema_key></entry>
+ <entry><key>toplevels/top_panel/enable_buttons</key><schema_key>/schemas/apps/panel/toplevels/enable_buttons</schema_key></entry>
+ <entry><key>toplevels/top_panel/enable_arrows</key><schema_key>/schemas/apps/panel/toplevels/enable_arrows</schema_key></entry>
+ <entry><key>toplevels/top_panel/hide_delay</key><schema_key>/schemas/apps/panel/toplevels/hide_delay</schema_key></entry>
+ <entry><key>toplevels/top_panel/unhide_delay</key><schema_key>/schemas/apps/panel/toplevels/unhide_delay</schema_key></entry>
+ <entry><key>toplevels/top_panel/auto_hide_size</key><schema_key>/schemas/apps/panel/toplevels/auto_hide_size</schema_key></entry>
+ <entry><key>toplevels/top_panel/animation_speed</key><schema_key>/schemas/apps/panel/toplevels/animation_speed</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/type</key><schema_key>/schemas/apps/panel/toplevels/background/type</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/color</key><schema_key>/schemas/apps/panel/toplevels/background/color</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/opacity</key><schema_key>/schemas/apps/panel/toplevels/background/opacity</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/image</key><schema_key>/schemas/apps/panel/toplevels/background/image</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/fit</key><schema_key>/schemas/apps/panel/toplevels/background/fit</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/stretch</key><schema_key>/schemas/apps/panel/toplevels/background/stretch</schema_key></entry>
+ <entry><key>toplevels/top_panel/background/rotate</key><schema_key>/schemas/apps/panel/toplevels/background/rotate</schema_key></entry>
+
+ <!-- Bottom Panel -->
+
+ <entry>
+ <key>toplevels/bottom_panel/expand</key>
+ <schema_key>/schemas/apps/panel/toplevels/expand</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>toplevels/bottom_panel/orientation</key>
+ <schema_key>/schemas/apps/panel/toplevels/orientation</schema_key>
+ <value>
+ <string>bottom</string>
+ </value>
+ </entry>
+ <entry>
+ <key>toplevels/bottom_panel/size</key>
+ <schema_key>/schemas/apps/panel/toplevels/size</schema_key>
+ <value>
+ <int>24</int>
+ </value>
+ </entry>
+ <entry>
+ <key>toplevels/bottom_panel/y_bottom</key>
+ <schema_key>/schemas/apps/panel/toplevels/y_bottom</schema_key>
+ <value>
+ <int>0</int>
+ </value>
+ </entry>
+
+ <entry><key>toplevels/bottom_panel/name</key><schema_key>/schemas/apps/panel/toplevels/name</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/screen</key><schema_key>/schemas/apps/panel/toplevels/screen</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/monitor</key><schema_key>/schemas/apps/panel/toplevels/monitor</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/x</key><schema_key>/schemas/apps/panel/toplevels/x</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/y</key><schema_key>/schemas/apps/panel/toplevels/y</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/x_right</key><schema_key>/schemas/apps/panel/toplevels/x_right</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/x_centered</key><schema_key>/schemas/apps/panel/toplevels/x_centered</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/y_centered</key><schema_key>/schemas/apps/panel/toplevels/y_centered</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/auto_hide</key><schema_key>/schemas/apps/panel/toplevels/auto_hide</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/enable_animations</key><schema_key>/schemas/apps/panel/toplevels/enable_animations</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/enable_buttons</key><schema_key>/schemas/apps/panel/toplevels/enable_buttons</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/enable_arrows</key><schema_key>/schemas/apps/panel/toplevels/enable_arrows</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/hide_delay</key><schema_key>/schemas/apps/panel/toplevels/hide_delay</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/unhide_delay</key><schema_key>/schemas/apps/panel/toplevels/unhide_delay</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/auto_hide_size</key><schema_key>/schemas/apps/panel/toplevels/auto_hide_size</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/animation_speed</key><schema_key>/schemas/apps/panel/toplevels/animation_speed</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/type</key><schema_key>/schemas/apps/panel/toplevels/background/type</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/color</key><schema_key>/schemas/apps/panel/toplevels/background/color</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/opacity</key><schema_key>/schemas/apps/panel/toplevels/background/opacity</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/image</key><schema_key>/schemas/apps/panel/toplevels/background/image</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/fit</key><schema_key>/schemas/apps/panel/toplevels/background/fit</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/stretch</key><schema_key>/schemas/apps/panel/toplevels/background/stretch</schema_key></entry>
+ <entry><key>toplevels/bottom_panel/background/rotate</key><schema_key>/schemas/apps/panel/toplevels/background/rotate</schema_key></entry>
+
+ <!-- Menu Bar -->
+
+ <entry>
+ <key>objects/menu_bar/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>menu-bar</string>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/menu_bar/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>top_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/menu_bar/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>0</int>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/menu_bar/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>false</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/menu_bar/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+
+ <entry><key>objects/menu_bar/applet_iid</key><schema_key>/schemas/apps/panel/objects/applet_iid</schema_key></entry>
+ <entry><key>objects/menu_bar/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>objects/menu_bar/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>objects/menu_bar/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>objects/menu_bar/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>objects/menu_bar/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>objects/menu_bar/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>objects/menu_bar/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>objects/menu_bar/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Browser Launcher -->
+
+ <entry>
+ <key>objects/browser_launcher/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>launcher-object</string>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/browser_launcher/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>top_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/browser_launcher/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>1</int>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/browser_launcher/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>false</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/browser_launcher/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/browser_launcher/launcher_location</key>
+ <schema_key>/schemas/apps/panel/objects/launcher_location</schema_key>
+ <value>
+ <string>firefox.desktop</string>
+ </value>
+ </entry>
+
+ <entry><key>objects/browser_launcher/applet_iid</key><schema_key>/schemas/apps/panel/objects/applet_iid</schema_key></entry>
+ <entry><key>objects/browser_launcher/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>objects/browser_launcher/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>objects/browser_launcher/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>objects/browser_launcher/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>objects/browser_launcher/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>objects/browser_launcher/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>objects/browser_launcher/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Email Launcher -->
+
+ <entry>
+ <key>objects/email_launcher/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>launcher-object</string>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/email_launcher/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>top_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/email_launcher/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>2</int>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/email_launcher/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>false</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/email_launcher/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>objects/email_launcher/launcher_location</key>
+ <schema_key>/schemas/apps/panel/objects/launcher_location</schema_key>
+ <value>
+ <string>thunderbird.desktop</string>
+ </value>
+ </entry>
+
+ <entry><key>objects/email_launcher/applet_iid</key><schema_key>/schemas/apps/panel/objects/applet_iid</schema_key></entry>
+ <entry><key>objects/email_launcher/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>objects/email_launcher/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>objects/email_launcher/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>objects/email_launcher/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>objects/email_launcher/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>objects/email_launcher/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>objects/email_launcher/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Window Menu Applet -->
+
+ <entry>
+ <key>applets/window_menu/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>matecomponent-applet</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_menu/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>top_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_menu/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>0</int>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_menu/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_menu/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_menu/applet_iid</key>
+ <schema_key>/schemas/apps/panel/objects/applet_iid</schema_key>
+ <value>
+ <string>WnckletFactory::WindowMenuApplet</string>
+ </value>
+ </entry>
+
+ <entry><key>applets/window_menu/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>applets/window_menu/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>applets/window_menu/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>applets/window_menu/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>applets/window_menu/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>applets/window_menu/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>applets/window_menu/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>applets/window_menu/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Clock Applet -->
+
+ <entry>
+ <key>applets/clock/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>matecomponent-applet</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/clock/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>top_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/clock/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>2</int>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/clock/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/clock/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/clock/applet_iid</key>
+ <schema_key>/schemas/apps/panel/objects/applet_iid</schema_key>
+ <value>
+ <string>ClockAppletFactory::ClockApplet</string>
+ </value>
+ </entry>
+
+ <entry><key>applets/clock/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>applets/clock/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>applets/clock/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>applets/clock/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>applets/clock/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>applets/clock/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>applets/clock/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>applets/clock/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Notification Area Applet -->
+
+ <entry>
+ <key>applets/notification_area/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>matecomponent-applet</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/notification_area/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>top_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/notification_area/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>3</int>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/notification_area/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/notification_area/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/notification_area/applet_iid</key>
+ <schema_key>/schemas/apps/panel/objects/applet_iid</schema_key>
+ <value>
+ <string>NotificationAreaAppletFactory::NotificationArea</string>
+ </value>
+ </entry>
+
+ <entry><key>applets/notification_area/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>applets/notification_area/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>applets/notification_area/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>applets/notification_area/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>applets/notification_area/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>applets/notification_area/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>applets/notification_area/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>applets/notification_area/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Show Desktop Applet -->
+
+ <entry>
+ <key>applets/show_desktop_button/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>matecomponent-applet</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/show_desktop_button/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>bottom_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/show_desktop_button/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>0</int>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/show_desktop_button/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>false</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/show_desktop_button/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/show_desktop_button/applet_iid</key>
+ <schema_key>/schemas/apps/panel/objects/applet_iid</schema_key>
+ <value>
+ <string>WnckletFactory::ShowDesktopApplet</string>
+ </value>
+ </entry>
+
+ <entry><key>applets/show_desktop_button/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>applets/show_desktop_button/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>applets/show_desktop_button/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>applets/show_desktop_button/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>applets/show_desktop_button/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>applets/show_desktop_button/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>applets/show_desktop_button/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>applets/show_desktop_button/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Window List Applet -->
+
+ <entry>
+ <key>applets/window_list/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>matecomponent-applet</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_list/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>bottom_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_list/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>1</int>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_list/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>false</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_list/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/window_list/applet_iid</key>
+ <schema_key>/schemas/apps/panel/objects/applet_iid</schema_key>
+ <value>
+ <string>WnckletFactory::WindowListApplet</string>
+ </value>
+ </entry>
+
+ <entry><key>applets/window_list/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>applets/window_list/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>applets/window_list/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>applets/window_list/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>applets/window_list/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>applets/window_list/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>applets/window_list/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>applets/window_list/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ <!-- Workspace Switcher Applet -->
+
+ <entry>
+ <key>applets/workspace_switcher/object_type</key>
+ <schema_key>/schemas/apps/panel/objects/object_type</schema_key>
+ <value>
+ <string>matecomponent-applet</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/workspace_switcher/toplevel_id</key>
+ <schema_key>/schemas/apps/panel/objects/toplevel_id</schema_key>
+ <value>
+ <string>bottom_panel</string>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/workspace_switcher/position</key>
+ <schema_key>/schemas/apps/panel/objects/position</schema_key>
+ <value>
+ <int>0</int>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/workspace_switcher/panel_right_stick</key>
+ <schema_key>/schemas/apps/panel/objects/panel_right_stick</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/workspace_switcher/locked</key>
+ <schema_key>/schemas/apps/panel/objects/locked</schema_key>
+ <value>
+ <bool>true</bool>
+ </value>
+ </entry>
+ <entry>
+ <key>applets/workspace_switcher/applet_iid</key>
+ <schema_key>/schemas/apps/panel/objects/applet_iid</schema_key>
+ <value>
+ <string>WnckletFactory::WorkspaceSwitcherApplet</string>
+ </value>
+ </entry>
+
+ <entry><key>applets/workspace_switcher/attached_toplevel_id</key><schema_key>/schemas/apps/panel/objects/attached_toplevel_id</schema_key> </entry>
+ <entry><key>applets/workspace_switcher/tooltip</key><schema_key>/schemas/apps/panel/objects/tooltip</schema_key></entry>
+ <entry><key>applets/workspace_switcher/use_custom_icon</key><schema_key>/schemas/apps/panel/objects/use_custom_icon</schema_key></entry>
+ <entry><key>applets/workspace_switcher/custom_icon</key><schema_key>/schemas/apps/panel/objects/custom_icon</schema_key></entry>
+ <entry><key>applets/workspace_switcher/use_menu_path</key><schema_key>/schemas/apps/panel/objects/use_menu_path</schema_key></entry>
+ <entry><key>applets/workspace_switcher/menu_path</key><schema_key>/schemas/apps/panel/objects/menu_path</schema_key></entry>
+ <entry><key>applets/workspace_switcher/launcher_location</key><schema_key>/schemas/apps/panel/objects/launcher_location</schema_key></entry>
+ <entry><key>applets/workspace_switcher/action_type</key><schema_key>/schemas/apps/panel/objects/action_type</schema_key></entry>
+
+ </entrylist>
+
+</mateconfentryfile>
diff --git a/mate-panel/panel-ditem-editor.c b/mate-panel/panel-ditem-editor.c
new file mode 100644
index 00000000..e00f124e
--- /dev/null
+++ b/mate-panel/panel-ditem-editor.c
@@ -0,0 +1,1804 @@
+/*
+ * panel-ditem-editor.c:
+ *
+ * Copyright (C) 2004, 2006 Vincent Untz
+ *
+ * The Mate 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 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 Library General Public
+ * License along with the Mate Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include <libpanel-util/panel-icon-chooser.h>
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-show.h>
+#include <libpanel-util/panel-xdg.h>
+
+#include "panel-ditem-editor.h"
+#include "panel-icon-names.h"
+#include "panel-util.h"
+#include "panel-marshal.h"
+
+struct _PanelDItemEditorPrivate
+{
+ /* we keep a ditem around, since we can never have absolutely
+ everything in the display so we load a file, or get a ditem,
+ sync the display and ref the ditem */
+ GKeyFile *key_file;
+ gboolean free_key_file;
+ /* the revert ditem will only contain relevant keys */
+ GKeyFile *revert_key_file;
+
+ gboolean reverting;
+ gboolean dirty;
+ guint save_timeout;
+
+ char *uri; /* file location */
+ gboolean type_directory;
+ gboolean new_file;
+ gboolean combo_setuped;
+
+ PanelDitemSaveUri save_uri;
+ gpointer save_uri_data;
+
+ GtkWidget *table;
+ GtkWidget *type_label;
+ GtkWidget *type_combo;
+ GtkWidget *name_label;
+ GtkWidget *name_entry;
+ GtkWidget *command_hbox;
+ GtkWidget *command_label;
+ GtkWidget *command_entry;
+ GtkWidget *command_browse_button;
+ GtkWidget *command_browse_filechooser;
+ GtkWidget *comment_label;
+ GtkWidget *comment_entry;
+ GtkWidget *icon_chooser;
+
+ GtkWidget *help_button;
+ GtkWidget *revert_button;
+ GtkWidget *close_button;
+ GtkWidget *cancel_button;
+ GtkWidget *ok_button;
+};
+
+/* Time in seconds after which we save the file on the disk */
+#define SAVE_FREQUENCY 2
+
+enum {
+ REVERT_BUTTON
+};
+
+typedef enum {
+ PANEL_DITEM_EDITOR_TYPE_NULL,
+ PANEL_DITEM_EDITOR_TYPE_APPLICATION,
+ PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION,
+ PANEL_DITEM_EDITOR_TYPE_LINK,
+ PANEL_DITEM_EDITOR_TYPE_DIRECTORY
+} PanelDItemEditorType;
+
+enum {
+ COLUMN_TEXT,
+ COLUMN_TYPE,
+ NUMBER_COLUMNS
+};
+
+typedef struct {
+ const char *name;
+ const char *show_for;
+ PanelDItemEditorType type;
+} ComboItem;
+
+static ComboItem type_items [] = {
+ { N_("Application"), "Application",
+ PANEL_DITEM_EDITOR_TYPE_APPLICATION },
+ { N_("Application in Terminal"), "Application",
+ PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION },
+ { N_("Location"), "Link",
+ PANEL_DITEM_EDITOR_TYPE_LINK },
+ /* FIXME: hack hack hack: we will remove this item from the combo
+ * box if we show it */
+ { NULL, "Directory",
+ PANEL_DITEM_EDITOR_TYPE_DIRECTORY }
+};
+
+typedef struct {
+ const char *key;
+ GType type;
+ gboolean default_value;
+ gboolean locale;
+} RevertKey;
+
+static RevertKey revert_keys [] = {
+ { "Type", G_TYPE_STRING, FALSE, FALSE },
+ { "Terminal", G_TYPE_BOOLEAN, FALSE, FALSE },
+ { "Exec", G_TYPE_STRING, FALSE, FALSE },
+ { "URL", G_TYPE_STRING, FALSE, FALSE },
+ /* locale keys */
+ { "Icon", G_TYPE_STRING, FALSE, TRUE },
+ { "Name", G_TYPE_STRING, FALSE, TRUE },
+ { "Comment", G_TYPE_STRING, FALSE, TRUE },
+ { "X-MATE-FullName", G_TYPE_STRING, FALSE, TRUE },
+ /* C version of those keys */
+ { "Icon", G_TYPE_STRING, FALSE, FALSE },
+ { "Name", G_TYPE_STRING, FALSE, FALSE },
+ { "Comment", G_TYPE_STRING, FALSE, FALSE },
+ { "X-MATE-FullName", G_TYPE_STRING, FALSE, FALSE }
+};
+
+enum {
+ SAVED,
+ CHANGED,
+ NAME_CHANGED,
+ COMMAND_CHANGED,
+ COMMENT_CHANGED,
+ ICON_CHANGED,
+ ERROR_REPORTED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_KEYFILE,
+ PROP_URI,
+ PROP_TYPEDIRECTORY
+};
+
+static guint ditem_edit_signals[LAST_SIGNAL] = { 0 };
+
+#define PANEL_DITEM_EDITOR_GET_PRIVATE(o) (PANEL_DITEM_EDITOR (o)->priv)
+
+G_DEFINE_TYPE (PanelDItemEditor, panel_ditem_editor, GTK_TYPE_DIALOG)
+
+static void panel_ditem_editor_setup_ui (PanelDItemEditor *dialog);
+
+static void type_combo_changed (PanelDItemEditor *dialog);
+
+static void response_cb (GtkDialog *dialog,
+ gint response_id);
+
+static void setup_icon_chooser (PanelDItemEditor *dialog,
+ const char *icon_name);
+
+static gboolean panel_ditem_editor_save (PanelDItemEditor *dialog,
+ gboolean report_errors);
+static gboolean panel_ditem_editor_save_timeout (gpointer data);
+static void panel_ditem_editor_revert (PanelDItemEditor *dialog);
+
+static void panel_ditem_editor_key_file_loaded (PanelDItemEditor *dialog);
+static gboolean panel_ditem_editor_load_uri (PanelDItemEditor *dialog,
+ GError **error);
+
+static void panel_ditem_editor_set_key_file (PanelDItemEditor *dialog,
+ GKeyFile *key_file);
+
+static gboolean panel_ditem_editor_get_type_directory (PanelDItemEditor *dialog);
+static void panel_ditem_editor_set_type_directory (PanelDItemEditor *dialog,
+ gboolean type_directory);
+
+
+static PanelDItemEditorType
+map_type_from_desktop_item (const char *type,
+ gboolean terminal)
+{
+ if (type == NULL)
+ return PANEL_DITEM_EDITOR_TYPE_NULL;
+ else if (!strcmp (type, "Application")) {
+ if (terminal)
+ return PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION;
+ else
+ return PANEL_DITEM_EDITOR_TYPE_APPLICATION;
+ } else if (!strcmp (type, "Link"))
+ return PANEL_DITEM_EDITOR_TYPE_LINK;
+ else if (!strcmp (type, "Directory"))
+ return PANEL_DITEM_EDITOR_TYPE_DIRECTORY;
+ else
+ return PANEL_DITEM_EDITOR_TYPE_NULL;
+}
+
+static GObject *
+panel_ditem_editor_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ PanelDItemEditor *dialog;
+ GFile *file;
+ gboolean loaded;
+ char *desktop_type;
+
+ obj = G_OBJECT_CLASS (panel_ditem_editor_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ dialog = PANEL_DITEM_EDITOR (obj);
+
+ if (dialog->priv->key_file) {
+ panel_ditem_editor_key_file_loaded (dialog);
+ dialog->priv->new_file = FALSE;
+ dialog->priv->free_key_file = FALSE;
+ loaded = TRUE;
+ } else {
+ dialog->priv->key_file = panel_key_file_new_desktop ();
+ if (dialog->priv->type_directory)
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Directory");
+ dialog->priv->free_key_file = TRUE;
+ loaded = FALSE;
+ }
+
+ if (!loaded && dialog->priv->uri) {
+ file = g_file_new_for_uri (dialog->priv->uri);
+ if (g_file_query_exists (file, NULL)) {
+ //FIXME what if there's an error?
+ panel_ditem_editor_load_uri (dialog, NULL);
+ dialog->priv->new_file = FALSE;
+ } else {
+ dialog->priv->new_file = TRUE;
+ }
+ g_object_unref (file);
+ } else {
+ dialog->priv->new_file = !loaded;
+ }
+
+ dialog->priv->dirty = FALSE;
+
+ desktop_type = panel_key_file_get_string (dialog->priv->key_file,
+ "Type");
+ if (desktop_type && !strcmp (desktop_type, "Directory"))
+ dialog->priv->type_directory = TRUE;
+ g_free (desktop_type);
+
+ panel_ditem_editor_setup_ui (dialog);
+
+ if (dialog->priv->new_file)
+ setup_icon_chooser (dialog, NULL);
+
+ return obj;
+}
+
+static void
+panel_ditem_editor_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelDItemEditor *dialog;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (object));
+
+ dialog = PANEL_DITEM_EDITOR (object);
+
+ switch (prop_id) {
+ case PROP_KEYFILE:
+ g_value_set_pointer (value, panel_ditem_editor_get_key_file (dialog));
+ break;
+ case PROP_URI:
+ g_value_set_string (value, panel_ditem_editor_get_uri (dialog));
+ break;
+ case PROP_TYPEDIRECTORY:
+ g_value_set_boolean (value, panel_ditem_editor_get_type_directory (dialog));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_ditem_editor_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelDItemEditor *dialog;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (object));
+
+ dialog = PANEL_DITEM_EDITOR (object);
+
+ switch (prop_id) {
+ case PROP_KEYFILE:
+ panel_ditem_editor_set_key_file (dialog,
+ g_value_get_pointer (value));
+ break;
+ case PROP_URI:
+ panel_ditem_editor_set_uri (dialog,
+ g_value_get_string (value));
+ break;
+ case PROP_TYPEDIRECTORY:
+ panel_ditem_editor_set_type_directory (dialog,
+ g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_ditem_editor_destroy (GtkObject *object)
+{
+ PanelDItemEditor *dialog;
+
+ dialog = PANEL_DITEM_EDITOR (object);
+
+ /* If there was a timeout, then something changed after last save,
+ * so we must save again now */
+ if (dialog->priv->save_timeout) {
+ g_source_remove (dialog->priv->save_timeout);
+ dialog->priv->save_timeout = 0;
+ panel_ditem_editor_save (dialog, FALSE);
+ }
+
+ /* remember, destroy can be run multiple times! */
+
+ if (dialog->priv->free_key_file && dialog->priv->key_file != NULL)
+ g_key_file_free (dialog->priv->key_file);
+ dialog->priv->key_file = NULL;
+
+ if (dialog->priv->revert_key_file != NULL)
+ g_key_file_free (dialog->priv->revert_key_file);
+ dialog->priv->revert_key_file = NULL;
+
+ if (dialog->priv->uri != NULL)
+ g_free (dialog->priv->uri);
+ dialog->priv->uri = NULL;
+
+ GTK_OBJECT_CLASS (panel_ditem_editor_parent_class)->destroy (object);
+}
+
+static void
+panel_ditem_editor_class_init (PanelDItemEditorClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (class);
+
+ gobject_class->constructor = panel_ditem_editor_constructor;
+ gobject_class->get_property = panel_ditem_editor_get_property;
+ gobject_class->set_property = panel_ditem_editor_set_property;
+
+ gtkobject_class->destroy = panel_ditem_editor_destroy;
+
+ g_type_class_add_private (class,
+ sizeof (PanelDItemEditorPrivate));
+
+ ditem_edit_signals[SAVED] =
+ g_signal_new ("saved",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ ditem_edit_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ ditem_edit_signals[NAME_CHANGED] =
+ g_signal_new ("name_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ name_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[COMMAND_CHANGED] =
+ g_signal_new ("command_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ command_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[COMMENT_CHANGED] =
+ g_signal_new ("comment_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ comment_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[ICON_CHANGED] =
+ g_signal_new ("icon_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ icon_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[ERROR_REPORTED] =
+ g_signal_new ("error_reported",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ error_reported),
+ NULL,
+ NULL,
+ panel_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING, G_TYPE_STRING);
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_KEYFILE,
+ g_param_spec_pointer ("keyfile",
+ "Key File",
+ "A key file containing the data from the .desktop file",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_URI,
+ g_param_spec_string ("uri",
+ "URI",
+ "The URI of the .desktop file",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_TYPEDIRECTORY,
+ g_param_spec_boolean ("type-directory",
+ "Type Directory",
+ "Whether the edited file is a .directory file or not",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static GtkWidget *
+label_new_with_mnemonic (const char *text)
+{
+ GtkWidget *label;
+ char *bold;
+
+ bold = g_strdup_printf ("<b>%s</b>", text);
+ label = gtk_label_new_with_mnemonic (bold);
+ g_free (bold);
+
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+
+ gtk_widget_show (label);
+
+ return label;
+}
+
+static inline void
+table_attach_label (GtkTable *table,
+ GtkWidget *label,
+ int left,
+ int right,
+ int top,
+ int bottom)
+{
+ gtk_table_attach (table, label, left, right, top, bottom,
+ GTK_FILL, GTK_FILL,
+ 0, 0);
+}
+
+static inline void
+table_attach_entry (GtkTable *table,
+ GtkWidget *entry,
+ int left,
+ int right,
+ int top,
+ int bottom)
+{
+ gtk_table_attach (table, entry, left, right, top, bottom,
+ GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL,
+ 0, 0);
+}
+
+static void
+setup_combo (GtkWidget *combo_box,
+ ComboItem *items,
+ int nb_items,
+ const char *for_type)
+{
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ int i;
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_INT);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box),
+ GTK_TREE_MODEL (model));
+
+ for (i = 0; i < nb_items; i++) {
+ if (for_type && strcmp (for_type, items [i].show_for))
+ continue;
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_TEXT, _(items [i].name),
+ COLUMN_TYPE, items [i].type,
+ -1);
+ }
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box),
+ renderer, "text", COLUMN_TEXT, NULL);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+}
+
+static PanelDItemEditorType
+panel_ditem_editor_get_item_type (PanelDItemEditor *dialog)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ PanelDItemEditorType type;
+
+ if (dialog->priv->type_directory)
+ return PANEL_DITEM_EDITOR_TYPE_DIRECTORY;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->type_combo),
+ &iter))
+ return PANEL_DITEM_EDITOR_TYPE_NULL;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->type_combo));
+ gtk_tree_model_get (model, &iter, COLUMN_TYPE, &type, -1);
+
+ return type;
+}
+
+static void
+panel_ditem_editor_make_ui (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+ GtkWidget *dialog_vbox;
+
+ priv = dialog->priv;
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_box_set_spacing (GTK_BOX (dialog_vbox), 2);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+ priv->table = gtk_table_new (4, 3, FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (priv->table), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (priv->table), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (priv->table), 12);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox),
+ priv->table, TRUE, TRUE, 0);
+ gtk_widget_show (priv->table);
+
+ /* Type */
+ priv->type_label = label_new_with_mnemonic (_("_Type:"));
+ priv->type_combo = gtk_combo_box_new ();
+ gtk_widget_show (priv->type_combo);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->type_label),
+ priv->type_combo);
+
+ /* Name */
+ priv->name_label = label_new_with_mnemonic (_("_Name:"));
+ priv->name_entry = gtk_entry_new ();
+ gtk_widget_show (priv->name_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->name_label),
+ priv->name_entry);
+
+ /* Icon */
+ priv->icon_chooser = panel_icon_chooser_new (NULL);
+ panel_icon_chooser_set_fallback_icon_name (PANEL_ICON_CHOOSER (priv->icon_chooser),
+ PANEL_ICON_LAUNCHER);
+ gtk_table_attach (GTK_TABLE (priv->table), priv->icon_chooser,
+ 0, 1, 0, 2,
+ 0, 0, 0, 0);
+ gtk_widget_show (priv->icon_chooser);
+
+ /* Command */
+ priv->command_label = label_new_with_mnemonic ("");
+
+ priv->command_hbox = gtk_hbox_new (FALSE, 12);
+ gtk_widget_show (priv->command_hbox);
+
+ priv->command_entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (priv->command_hbox),
+ priv->command_entry,
+ TRUE, TRUE, 0);
+ gtk_widget_show (priv->command_entry);
+
+ priv->command_browse_button = gtk_button_new_with_mnemonic (_("_Browse..."));
+ gtk_box_pack_start (GTK_BOX (priv->command_hbox),
+ priv->command_browse_button,
+ FALSE, FALSE, 0);
+ gtk_widget_show (priv->command_browse_button);
+
+ /* Comment */
+ priv->comment_label = label_new_with_mnemonic (_("Co_mment:"));
+ priv->comment_entry = gtk_entry_new ();
+ gtk_widget_show (priv->comment_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->comment_label),
+ priv->comment_entry);
+
+ priv->help_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_HELP,
+ GTK_RESPONSE_HELP);
+ priv->revert_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_REVERT_TO_SAVED,
+ REVERT_BUTTON);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ REVERT_BUTTON,
+ FALSE);
+ priv->close_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE);
+ priv->cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ priv->ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK);
+
+ /* FIXME: There needs to be a way to edit ALL keys/sections */
+}
+
+static void
+panel_ditem_editor_setup_ui (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+ PanelDItemEditorType type;
+ gboolean show_combo;
+ GList *focus_chain;
+
+ priv = dialog->priv;
+ type = panel_ditem_editor_get_item_type (dialog);
+
+ if (priv->new_file) {
+ gtk_widget_hide (priv->revert_button);
+ gtk_widget_hide (priv->close_button);
+ gtk_widget_show (priv->cancel_button);
+ gtk_widget_show (priv->ok_button);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+
+ if (!priv->combo_setuped) {
+ setup_combo (priv->type_combo,
+ type_items, G_N_ELEMENTS (type_items),
+ NULL);
+ priv->combo_setuped = TRUE;
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->type_combo), 0);
+
+ show_combo = !priv->type_directory;
+ } else {
+
+ gtk_widget_show (priv->revert_button);
+ gtk_widget_show (priv->close_button);
+ gtk_widget_hide (priv->cancel_button);
+ gtk_widget_hide (priv->ok_button);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CLOSE);
+
+ show_combo = (type != PANEL_DITEM_EDITOR_TYPE_LINK) &&
+ (type != PANEL_DITEM_EDITOR_TYPE_DIRECTORY);
+ }
+
+ if (show_combo) {
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ PanelDItemEditorType buf_type;
+
+ table_attach_label (GTK_TABLE (priv->table), priv->type_label,
+ 1, 2, 0, 1);
+ table_attach_entry (GTK_TABLE (priv->table), priv->type_combo,
+ 2, 3, 0, 1);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->name_label,
+ 1, 2, 1, 2);
+ table_attach_entry (GTK_TABLE (priv->table), priv->name_entry,
+ 2, 3, 1, 2);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->command_label,
+ 1, 2, 2, 3);
+ table_attach_entry (GTK_TABLE (priv->table), priv->command_hbox,
+ 2, 3, 2, 3);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->comment_label,
+ 1, 2, 3, 4);
+ table_attach_entry (GTK_TABLE (priv->table), priv->comment_entry,
+ 2, 3, 3, 4);
+
+ /* FIXME: hack hack hack */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->type_combo));
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ g_assert_not_reached ();
+ do {
+ gtk_tree_model_get (model, &iter,
+ COLUMN_TYPE, &buf_type, -1);
+ if (buf_type == PANEL_DITEM_EDITOR_TYPE_DIRECTORY) {
+ gtk_list_store_remove (GTK_LIST_STORE (model),
+ &iter);
+ break;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ } else if (type == PANEL_DITEM_EDITOR_TYPE_DIRECTORY) {
+ table_attach_label (GTK_TABLE (priv->table), priv->name_label,
+ 1, 2, 0, 1);
+ table_attach_entry (GTK_TABLE (priv->table), priv->name_entry,
+ 2, 3, 0, 1);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->comment_label,
+ 1, 2, 1, 2);
+ table_attach_entry (GTK_TABLE (priv->table), priv->comment_entry,
+ 2, 3, 1, 2);
+ } else {
+ table_attach_label (GTK_TABLE (priv->table), priv->name_label,
+ 1, 2, 0, 1);
+ table_attach_entry (GTK_TABLE (priv->table), priv->name_entry,
+ 2, 3, 0, 1);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->command_label,
+ 1, 2, 1, 2);
+ table_attach_entry (GTK_TABLE (priv->table), priv->command_hbox,
+ 2, 3, 1, 2);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->comment_label,
+ 1, 2, 2, 3);
+ table_attach_entry (GTK_TABLE (priv->table), priv->comment_entry,
+ 2, 3, 2, 3);
+ }
+
+ type_combo_changed (dialog);
+
+ /* set a focus chain since GTK+ doesn't want to put the icon entry
+ * as the first widget in the chain */
+ focus_chain = NULL;
+ focus_chain = g_list_prepend (focus_chain, priv->icon_chooser);
+ focus_chain = g_list_prepend (focus_chain, priv->type_combo);
+ focus_chain = g_list_prepend (focus_chain, priv->name_entry);
+ focus_chain = g_list_prepend (focus_chain, priv->command_hbox);
+ focus_chain = g_list_prepend (focus_chain, priv->comment_entry);
+ focus_chain = g_list_reverse (focus_chain);
+ gtk_container_set_focus_chain (GTK_CONTAINER (priv->table),
+ focus_chain);
+ g_list_free (focus_chain);
+
+ gtk_widget_grab_focus (priv->name_entry);
+}
+
+/*
+ * Will save after SAVE_FREQUENCY milliseconds of no changes. If something is
+ * changed, the save is postponed to another SAVE_FREQUENCY seconds. This seems
+ * to be a saner behaviour than just saving every N seconds.
+ */
+static void
+panel_ditem_editor_changed (PanelDItemEditor *dialog)
+{
+ if (!dialog->priv->new_file) {
+ if (dialog->priv->save_timeout != 0)
+ g_source_remove (dialog->priv->save_timeout);
+
+ dialog->priv->save_timeout = g_timeout_add_seconds (
+ SAVE_FREQUENCY,
+ panel_ditem_editor_save_timeout,
+ dialog);
+
+ /* We can revert to the original state */
+ if (dialog->priv->revert_key_file != NULL)
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ REVERT_BUTTON,
+ TRUE);
+ }
+
+ dialog->priv->dirty = TRUE;
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[CHANGED], 0);
+}
+
+static void
+panel_ditem_editor_activated (PanelDItemEditor *dialog)
+{
+ if (gtk_widget_get_visible (dialog->priv->ok_button))
+ gtk_dialog_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+ else if (gtk_widget_get_visible (dialog->priv->close_button))
+ gtk_dialog_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CLOSE);
+}
+
+static void
+panel_ditem_editor_name_changed (PanelDItemEditor *dialog)
+{
+ const char *name;
+
+ name = gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry));
+
+ if (!dialog->priv->reverting) {
+ /* When reverting, we don't need to set the content of the key
+ * file; we only want to send a signal. Changing the key file
+ * could actually break the revert since it might overwrite the
+ * old Name value with the X-MATE-FullName value */
+ if (name && name[0])
+ panel_key_file_set_locale_string (dialog->priv->key_file,
+ "Name", name);
+ else
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "Name");
+
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "X-MATE-FullName");
+ }
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[NAME_CHANGED], 0,
+ name);
+}
+
+static void
+panel_ditem_editor_command_changed (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorType type;
+ const char *exec_or_uri;
+ GtkIconTheme *icon_theme;
+ char *icon;
+
+ exec_or_uri = gtk_entry_get_text (GTK_ENTRY (dialog->priv->command_entry));
+
+ if (exec_or_uri && exec_or_uri[0])
+ type = panel_ditem_editor_get_item_type (dialog);
+ else
+ type = PANEL_DITEM_EDITOR_TYPE_NULL;
+
+ switch (type) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ panel_key_file_remove_key (dialog->priv->key_file, "URL");
+ panel_key_file_set_string (dialog->priv->key_file, "Exec",
+ exec_or_uri);
+
+ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (dialog)));
+ icon = guess_icon_from_exec (icon_theme,
+ dialog->priv->key_file);
+ if (icon) {
+ char *current;
+
+ current = panel_key_file_get_locale_string (dialog->priv->key_file,
+ "Icon");
+
+ if (!current || strcmp (icon, current))
+ setup_icon_chooser (dialog, icon);
+
+ g_free (current);
+ g_free (icon);
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ panel_key_file_remove_key (dialog->priv->key_file, "Exec");
+ panel_key_file_set_string (dialog->priv->key_file, "URL",
+ exec_or_uri);
+ break;
+ default:
+ panel_key_file_remove_key (dialog->priv->key_file, "Exec");
+ panel_key_file_remove_key (dialog->priv->key_file, "URL");
+ }
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[COMMAND_CHANGED],
+ 0, exec_or_uri);
+}
+
+static void
+panel_ditem_editor_comment_changed (PanelDItemEditor *dialog)
+{
+ const char *comment;
+
+ comment = gtk_entry_get_text (GTK_ENTRY (dialog->priv->comment_entry));
+
+ if (comment && comment[0])
+ panel_key_file_set_locale_string (dialog->priv->key_file,
+ "Comment", comment);
+ else
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "Comment");
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[COMMENT_CHANGED],
+ 0, comment);
+}
+
+static void
+panel_ditem_editor_icon_changed (PanelDItemEditor *dialog,
+ const char *icon)
+{
+ if (icon)
+ panel_key_file_set_locale_string (dialog->priv->key_file,
+ "Icon", icon);
+ else
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "Icon");
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[ICON_CHANGED], 0,
+ icon);
+}
+
+static void
+command_browse_chooser_response (GtkFileChooser *chooser,
+ gint response_id,
+ PanelDItemEditor *dialog)
+{
+ char *uri;
+ char *text;
+
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ switch (panel_ditem_editor_get_item_type (dialog)) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+ uri = panel_util_make_exec_uri_for_desktop (text);
+ g_free (text);
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->command_entry),
+ uri);
+ g_free (uri);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (chooser));
+ dialog->priv->command_browse_filechooser = NULL;
+}
+
+static void
+update_chooser_for_type (PanelDItemEditor *dialog)
+{
+ const char *title;
+ gboolean local_only;
+ GtkWidget *chooser;
+
+ if (!dialog->priv->command_browse_filechooser)
+ return;
+
+ switch (panel_ditem_editor_get_item_type (dialog)) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ title = _("Choose an application...");
+ local_only = TRUE;
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ title = _("Choose a file...");
+ local_only = FALSE;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ chooser = dialog->priv->command_browse_filechooser;
+
+ gtk_window_set_title (GTK_WINDOW (chooser),
+ title);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser),
+ local_only);
+}
+
+static void
+command_browse_button_clicked (PanelDItemEditor *dialog)
+{
+ GtkWidget *chooser;
+
+ if (dialog->priv->command_browse_filechooser) {
+ gtk_window_present (GTK_WINDOW (dialog->priv->command_browse_filechooser));
+ return;
+ }
+
+ chooser = gtk_file_chooser_dialog_new ("", GTK_WINDOW (dialog),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
+
+ g_signal_connect (chooser, "response",
+ G_CALLBACK (command_browse_chooser_response), dialog);
+
+ dialog->priv->command_browse_filechooser = chooser;
+ update_chooser_for_type (dialog);
+
+ gtk_widget_show (chooser);
+}
+
+static void
+panel_ditem_editor_connect_signals (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = dialog->priv;
+
+#define CONNECT_CHANGED(widget, callback) \
+ g_signal_connect_swapped (G_OBJECT (widget), "changed", \
+ G_CALLBACK (callback), \
+ dialog); \
+ g_signal_connect_swapped (G_OBJECT (widget), "changed", \
+ G_CALLBACK (panel_ditem_editor_changed), \
+ dialog);
+
+ CONNECT_CHANGED (priv->type_combo, type_combo_changed);
+ CONNECT_CHANGED (priv->name_entry, panel_ditem_editor_name_changed);
+ CONNECT_CHANGED (priv->command_entry, panel_ditem_editor_command_changed);
+ CONNECT_CHANGED (priv->comment_entry, panel_ditem_editor_comment_changed);
+ CONNECT_CHANGED (priv->icon_chooser, panel_ditem_editor_icon_changed);
+
+ g_signal_connect_swapped (priv->name_entry, "activate",
+ G_CALLBACK (panel_ditem_editor_activated),
+ dialog);
+ g_signal_connect_swapped (priv->command_entry, "activate",
+ G_CALLBACK (panel_ditem_editor_activated),
+ dialog);
+ g_signal_connect_swapped (priv->comment_entry, "activate",
+ G_CALLBACK (panel_ditem_editor_activated),
+ dialog);
+
+ g_signal_connect_swapped (priv->command_browse_button, "clicked",
+ G_CALLBACK (command_browse_button_clicked),
+ dialog);
+
+ /* We do a signal connection here rather than overriding the method in
+ * class_init because GtkDialog::response is a RUN_LAST signal. We
+ * want *our* handler to be run *first*, regardless of whether the user
+ * installs response handlers of his own.
+ */
+ g_signal_connect (dialog, "response", G_CALLBACK (response_cb), NULL);
+}
+
+static void
+panel_ditem_editor_block_signals (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = dialog->priv;
+
+#define BLOCK_CHANGED(widget, callback) \
+ g_signal_handlers_block_by_func (G_OBJECT (widget), \
+ G_CALLBACK (callback), \
+ dialog); \
+ g_signal_handlers_block_by_func (G_OBJECT (widget), \
+ G_CALLBACK (panel_ditem_editor_changed), \
+ dialog);
+ BLOCK_CHANGED (priv->type_combo, type_combo_changed);
+ BLOCK_CHANGED (priv->name_entry, panel_ditem_editor_name_changed);
+ BLOCK_CHANGED (priv->command_entry, panel_ditem_editor_command_changed);
+ BLOCK_CHANGED (priv->comment_entry, panel_ditem_editor_comment_changed);
+ BLOCK_CHANGED (priv->icon_chooser, panel_ditem_editor_icon_changed);
+}
+
+static void
+panel_ditem_editor_unblock_signals (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = dialog->priv;
+
+#define UNBLOCK_CHANGED(widget, callback) \
+ g_signal_handlers_unblock_by_func (G_OBJECT (widget), \
+ G_CALLBACK (callback), \
+ dialog); \
+ g_signal_handlers_unblock_by_func (G_OBJECT (widget), \
+ G_CALLBACK (panel_ditem_editor_changed), \
+ dialog);
+ UNBLOCK_CHANGED (priv->type_combo, type_combo_changed);
+ UNBLOCK_CHANGED (priv->name_entry, panel_ditem_editor_name_changed);
+ UNBLOCK_CHANGED (priv->command_entry, panel_ditem_editor_command_changed);
+ UNBLOCK_CHANGED (priv->comment_entry, panel_ditem_editor_comment_changed);
+ UNBLOCK_CHANGED (priv->icon_chooser, panel_ditem_editor_icon_changed);
+}
+
+static void
+panel_ditem_editor_init (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
+ PANEL_TYPE_DITEM_EDITOR,
+ PanelDItemEditorPrivate);
+
+ dialog->priv = priv;
+
+ priv->key_file = NULL;
+ priv->free_key_file = FALSE;
+ priv->revert_key_file = NULL;
+ priv->reverting = FALSE;
+ priv->dirty = FALSE;
+ priv->save_timeout = 0;
+ priv->uri = NULL;
+ priv->type_directory = FALSE;
+ priv->new_file = TRUE;
+ priv->save_uri = NULL;
+ priv->save_uri_data = NULL;
+ priv->combo_setuped = FALSE;
+ priv->command_browse_filechooser = NULL;
+
+ panel_ditem_editor_make_ui (dialog);
+ panel_ditem_editor_connect_signals (dialog);
+}
+
+static void
+type_combo_changed (PanelDItemEditor *dialog)
+{
+ const char *text;
+ char *bold;
+
+ switch (panel_ditem_editor_get_item_type (dialog)) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ text = _("Comm_and:");
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Application");
+ panel_key_file_set_boolean (dialog->priv->key_file,
+ "Terminal", FALSE);
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ text = _("Comm_and:");
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Application");
+ panel_key_file_set_boolean (dialog->priv->key_file,
+ "Terminal", TRUE);
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ text = _("_Location:");
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Link");
+ panel_key_file_remove_key (dialog->priv->key_file,
+ "Terminal");
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_DIRECTORY:
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Directory");
+ }
+ return;
+ default:
+ g_assert_not_reached ();
+ }
+
+ bold = g_strdup_printf ("<b>%s</b>", text);
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (dialog->priv->command_label),
+ bold);
+ g_free (bold);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (dialog->priv->command_label),
+ dialog->priv->command_entry);
+
+ update_chooser_for_type (dialog);
+}
+
+static void
+setup_icon_chooser (PanelDItemEditor *dialog,
+ const char *icon_name)
+{
+ char *buffer;
+
+ if (!icon_name || icon_name[0] == '\0') {
+ if (dialog->priv->type_directory) {
+ buffer = g_strdup (PANEL_ICON_FOLDER);
+ } else {
+ buffer = g_strdup (PANEL_ICON_LAUNCHER);
+ }
+ } else {
+ buffer = g_strdup (icon_name);
+ }
+
+ panel_icon_chooser_set_icon (PANEL_ICON_CHOOSER (dialog->priv->icon_chooser),
+ buffer);
+
+ g_free (buffer);
+}
+
+/* Conform display to ditem */
+void
+panel_ditem_editor_sync_display (PanelDItemEditor *dialog)
+{
+ char *type;
+ PanelDItemEditorType editor_type;
+ gboolean run_in_terminal;
+ GKeyFile *key_file;
+ char *buffer;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ PanelDItemEditorType buf_type;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ key_file = dialog->priv->key_file;
+
+ /* Name */
+ buffer = panel_key_file_get_locale_string (key_file, "X-MATE-FullName");
+ if (!buffer)
+ buffer = panel_key_file_get_locale_string (key_file, "Name");
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->name_entry),
+ buffer ? buffer : "");
+ g_free (buffer);
+
+ /* Type */
+ type = panel_key_file_get_string (key_file, "Type");
+ if (!dialog->priv->combo_setuped) {
+ setup_combo (dialog->priv->type_combo,
+ type_items, G_N_ELEMENTS (type_items),
+ type);
+ dialog->priv->combo_setuped = TRUE;
+ }
+
+ run_in_terminal = panel_key_file_get_boolean (key_file, "Terminal",
+ FALSE);
+ editor_type = map_type_from_desktop_item (type, run_in_terminal);
+ g_free (type);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->type_combo));
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ g_assert_not_reached ();
+ do {
+ gtk_tree_model_get (model, &iter, COLUMN_TYPE, &buf_type, -1);
+ if (editor_type == buf_type) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->type_combo),
+ &iter);
+ break;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ g_assert (editor_type == buf_type ||
+ editor_type == PANEL_DITEM_EDITOR_TYPE_NULL);
+
+ /* Command */
+ if (editor_type == PANEL_DITEM_EDITOR_TYPE_LINK)
+ buffer = panel_key_file_get_string (key_file, "URL");
+ else if (editor_type == PANEL_DITEM_EDITOR_TYPE_APPLICATION ||
+ editor_type == PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION)
+ buffer = panel_key_file_get_string (key_file, "Exec");
+ else
+ buffer = NULL;
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->command_entry),
+ buffer ? buffer : "");
+ g_free (buffer);
+
+ /* Comment */
+ buffer = panel_key_file_get_locale_string (key_file, "Comment");
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->comment_entry),
+ buffer ? buffer : "");
+ g_free (buffer);
+
+
+ /* Icon */
+ buffer = panel_key_file_get_locale_string (key_file, "Icon");
+ setup_icon_chooser (dialog, buffer);
+ g_free (buffer);
+
+ if (dialog->priv->save_timeout != 0) {
+ g_source_remove (dialog->priv->save_timeout);
+ dialog->priv->save_timeout = 0;
+ }
+}
+
+static gboolean
+panel_ditem_editor_save (PanelDItemEditor *dialog,
+ gboolean report_errors)
+{
+ GKeyFile *key_file;
+ const char *const_buf;
+ GError *error;
+
+ g_return_val_if_fail (dialog != NULL, FALSE);
+ g_return_val_if_fail (dialog->priv->save_uri != NULL ||
+ dialog->priv->uri != NULL, FALSE);
+
+ if (dialog->priv->save_timeout != 0)
+ g_source_remove (dialog->priv->save_timeout);
+ dialog->priv->save_timeout = 0;
+
+ if (!dialog->priv->dirty)
+ return TRUE;
+
+ /* Verify that the required informations are set */
+ const_buf = gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry));
+ if (const_buf == NULL || const_buf [0] == '\0') {
+ if (report_errors) {
+ if (!dialog->priv->type_directory)
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save launcher"),
+ _("The name of the launcher is not set."));
+ else
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save directory properties"),
+ _("The name of the directory is not set."));
+ }
+ return FALSE;
+ }
+
+ const_buf = gtk_entry_get_text (GTK_ENTRY (dialog->priv->command_entry));
+ if (!dialog->priv->type_directory &&
+ (const_buf == NULL || const_buf [0] == '\0')) {
+ PanelDItemEditorType type;
+ char *err;
+
+ type = panel_ditem_editor_get_item_type (dialog);
+
+ switch (type) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ err = _("The command of the launcher is not set.");
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ err = _("The location of the launcher is not set.");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (report_errors)
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save launcher"), err);
+ return FALSE;
+ }
+
+ key_file = dialog->priv->key_file;
+
+ panel_key_file_ensure_C_key (key_file, "Name");
+ panel_key_file_ensure_C_key (key_file, "Comment");
+ panel_key_file_ensure_C_key (key_file, "Icon");
+
+ if (dialog->priv->save_uri) {
+ char *uri;
+
+ uri = dialog->priv->save_uri (dialog,
+ dialog->priv->save_uri_data);
+
+ if (uri) {
+ panel_ditem_editor_set_uri (dialog, uri);
+ g_free (uri);
+ }
+ }
+
+ /* And now, try to save */
+ error = NULL;
+ panel_key_file_to_file (dialog->priv->key_file,
+ dialog->priv->uri,
+ &error);
+ if (error != NULL) {
+ if (report_errors)
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save launcher"),
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ } else {
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[SAVED], 0);
+ }
+
+ dialog->priv->dirty = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+panel_ditem_editor_save_timeout (gpointer data)
+{
+ PanelDItemEditor *dialog;
+
+ dialog = PANEL_DITEM_EDITOR (data);
+ panel_ditem_editor_save (dialog, FALSE);
+
+ return FALSE;
+}
+
+static void
+response_cb (GtkDialog *dialog,
+ gint response_id)
+{
+ GError *error = NULL;
+
+ switch (response_id) {
+ case GTK_RESPONSE_HELP:
+ if (!panel_show_help (gtk_window_get_screen (GTK_WINDOW (dialog)),
+ "user-guide", "gospanel-52", &error)) {
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not display help document"),
+ error->message);
+ g_error_free (error);
+ }
+ break;
+ case REVERT_BUTTON:
+ panel_ditem_editor_revert (PANEL_DITEM_EDITOR (dialog));
+ gtk_dialog_set_response_sensitive (dialog,
+ REVERT_BUTTON,
+ FALSE);
+ break;
+ case GTK_RESPONSE_OK:
+ case GTK_RESPONSE_CLOSE:
+ if (panel_ditem_editor_save (PANEL_DITEM_EDITOR (dialog), TRUE))
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ case GTK_RESPONSE_DELETE_EVENT:
+ if (!PANEL_DITEM_EDITOR (dialog)->priv->new_file)
+ /* We need to revert the changes */
+ gtk_dialog_response (dialog, REVERT_BUTTON);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ case GTK_RESPONSE_CANCEL:
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+panel_ditem_editor_revert (PanelDItemEditor *dialog)
+{
+ int i;
+ char *string;
+ gboolean boolean;
+ GKeyFile *key_file;
+ GKeyFile *revert_key_file;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ dialog->priv->reverting = TRUE;
+
+ key_file = dialog->priv->key_file;
+ revert_key_file = dialog->priv->revert_key_file;
+
+ g_assert (revert_key_file != NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (revert_keys); i++) {
+ if (revert_keys [i].type == G_TYPE_STRING) {
+ if (revert_keys [i].locale) {
+ string = panel_key_file_get_locale_string (
+ revert_key_file,
+ revert_keys [i].key);
+ if (string == NULL)
+ panel_key_file_remove_all_locale_key (
+ key_file,
+ revert_keys [i].key);
+ else
+ panel_key_file_set_locale_string (
+ key_file,
+ revert_keys [i].key,
+ string);
+ } else {
+ string = panel_key_file_get_string (
+ revert_key_file,
+ revert_keys [i].key);
+ if (string == NULL)
+ panel_key_file_remove_key (
+ key_file,
+ revert_keys [i].key);
+ else
+ panel_key_file_set_string (
+ key_file,
+ revert_keys [i].key,
+ string);
+ }
+ g_free (string);
+ } else if (revert_keys [i].type == G_TYPE_BOOLEAN) {
+ boolean = panel_key_file_get_boolean (
+ revert_key_file,
+ revert_keys [i].key,
+ revert_keys [i].default_value);
+ panel_key_file_set_boolean (key_file,
+ revert_keys [i].key,
+ boolean);
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+
+ panel_ditem_editor_sync_display (dialog);
+
+ if (!dialog->priv->new_file) {
+ if (dialog->priv->save_timeout != 0)
+ g_source_remove (dialog->priv->save_timeout);
+
+ dialog->priv->save_timeout = g_timeout_add_seconds (
+ SAVE_FREQUENCY,
+ panel_ditem_editor_save_timeout,
+ dialog);
+ }
+
+ dialog->priv->reverting = FALSE;
+}
+
+static void
+panel_ditem_editor_set_revert (PanelDItemEditor *dialog)
+{
+ int i;
+ char *string;
+ gboolean boolean;
+ GKeyFile *key_file;
+ GKeyFile *revert_key_file;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ key_file = dialog->priv->key_file;
+ if (dialog->priv->revert_key_file)
+ g_key_file_free (dialog->priv->revert_key_file);
+ dialog->priv->revert_key_file = g_key_file_new ();
+ revert_key_file = dialog->priv->revert_key_file;
+
+ for (i = 0; i < G_N_ELEMENTS (revert_keys); i++) {
+ if (revert_keys [i].type == G_TYPE_STRING) {
+ if (revert_keys [i].locale) {
+ string = panel_key_file_get_locale_string (
+ key_file,
+ revert_keys [i].key);
+ if (string != NULL)
+ panel_key_file_set_locale_string (
+ revert_key_file,
+ revert_keys [i].key,
+ string);
+ } else {
+ string = panel_key_file_get_string (
+ key_file,
+ revert_keys [i].key);
+ if (string != NULL)
+ panel_key_file_set_string (
+ revert_key_file,
+ revert_keys [i].key,
+ string);
+ }
+ g_free (string);
+ } else if (revert_keys [i].type == G_TYPE_BOOLEAN) {
+ boolean = panel_key_file_get_boolean (
+ key_file,
+ revert_keys [i].key,
+ revert_keys [i].default_value);
+ panel_key_file_set_boolean (revert_key_file,
+ revert_keys [i].key,
+ boolean);
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+}
+
+static void
+panel_ditem_editor_key_file_loaded (PanelDItemEditor *dialog)
+{
+ /* the user is not changing any value here, so block the signals about
+ * changing a value */
+ panel_ditem_editor_block_signals (dialog);
+ panel_ditem_editor_sync_display (dialog);
+ panel_ditem_editor_unblock_signals (dialog);
+
+ /* This should be after panel_ditem_editor_sync_display ()
+ * so the revert button is insensitive */
+ if (dialog->priv->revert_key_file != NULL)
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ REVERT_BUTTON,
+ TRUE);
+ else
+ panel_ditem_editor_set_revert (dialog);
+}
+
+static gboolean
+panel_ditem_editor_load_uri (PanelDItemEditor *dialog,
+ GError **error)
+{
+ GKeyFile *key_file;
+
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), FALSE);
+ g_return_val_if_fail (dialog->priv->uri != NULL, FALSE);
+
+ key_file = g_key_file_new ();
+
+ if (!panel_key_file_load_from_uri (key_file,
+ dialog->priv->uri,
+ G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
+ error)) {
+ g_key_file_free (key_file);
+ return FALSE;
+ }
+
+ if (dialog->priv->free_key_file && dialog->priv->key_file)
+ g_key_file_free (dialog->priv->key_file);
+ dialog->priv->key_file = key_file;
+
+ panel_ditem_editor_key_file_loaded (dialog);
+
+ return TRUE;
+}
+
+static GtkWidget *
+panel_ditem_editor_new_full (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title,
+ gboolean type_directory)
+{
+ GtkWidget *dialog;
+
+ dialog = g_object_new (PANEL_TYPE_DITEM_EDITOR,
+ "title", title,
+ "keyfile", key_file,
+ "uri", uri,
+ "type-directory", type_directory,
+ NULL);
+
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+ return dialog;
+}
+
+GtkWidget *
+panel_ditem_editor_new (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title)
+{
+ return panel_ditem_editor_new_full (parent, key_file, uri,
+ title, FALSE);
+}
+
+GtkWidget *
+panel_ditem_editor_new_directory (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title)
+{
+ return panel_ditem_editor_new_full (parent, key_file, uri,
+ title, TRUE);
+}
+
+static void
+panel_ditem_editor_set_key_file (PanelDItemEditor *dialog,
+ GKeyFile *key_file)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ if (dialog->priv->key_file == key_file)
+ return;
+
+ if (dialog->priv->free_key_file && dialog->priv->key_file)
+ g_key_file_free (dialog->priv->key_file);
+ dialog->priv->key_file = key_file;
+
+ g_object_notify (G_OBJECT (dialog), "keyfile");
+}
+
+void
+panel_ditem_editor_set_uri (PanelDItemEditor *dialog,
+ const char *uri)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ if (!dialog->priv->uri && (!uri || !uri [0]))
+ return;
+
+ if (dialog->priv->uri && uri && uri [0] &&
+ !strcmp (dialog->priv->uri, uri))
+ return;
+
+ if (dialog->priv->uri)
+ g_free (dialog->priv->uri);
+ dialog->priv->uri = NULL;
+
+ if (uri && uri [0])
+ dialog->priv->uri = g_strdup (uri);
+
+ g_object_notify (G_OBJECT (dialog), "uri");
+}
+
+static void
+panel_ditem_editor_set_type_directory (PanelDItemEditor *dialog,
+ gboolean type_directory)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ if (dialog->priv->type_directory == type_directory)
+ return;
+
+ dialog->priv->type_directory = type_directory;
+
+ g_object_notify (G_OBJECT (dialog), "type-directory");
+}
+
+GKeyFile *
+panel_ditem_editor_get_key_file (PanelDItemEditor *dialog)
+{
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), NULL);
+
+ return dialog->priv->key_file;
+}
+
+GKeyFile *
+panel_ditem_editor_get_revert_key_file (PanelDItemEditor *dialog)
+{
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), NULL);
+
+ return dialog->priv->revert_key_file;
+}
+
+const char* panel_ditem_editor_get_uri(PanelDItemEditor* dialog)
+{
+ g_return_val_if_fail(PANEL_IS_DITEM_EDITOR(dialog), NULL);
+
+ return dialog->priv->uri;
+}
+
+static gboolean
+panel_ditem_editor_get_type_directory (PanelDItemEditor *dialog)
+{
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), FALSE);
+
+ return dialog->priv->type_directory;
+}
+
+void
+panel_ditem_register_save_uri_func (PanelDItemEditor *dialog,
+ PanelDitemSaveUri save_uri,
+ gpointer data)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ dialog->priv->save_uri = save_uri;
+ dialog->priv->save_uri_data = data;
+}
diff --git a/mate-panel/panel-ditem-editor.h b/mate-panel/panel-ditem-editor.h
new file mode 100644
index 00000000..32a34923
--- /dev/null
+++ b/mate-panel/panel-ditem-editor.h
@@ -0,0 +1,115 @@
+/*
+ * panel-ditem-editor.h:
+ *
+ * Copyright (C) 2004, 2006 Vincent Untz
+ *
+ * The Mate 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 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 Library General Public
+ * License along with the Mate Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef PANEL_DITEM_EDITOR_H
+#define PANEL_DITEM_EDITOR_H
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_DITEM_EDITOR (panel_ditem_editor_get_type ())
+#define PANEL_DITEM_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_DITEM_EDITOR, PanelDItemEditor))
+#define PANEL_DITEM_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_DITEM_EDITOR, PanelDItemEditorClass))
+#define PANEL_IS_DITEM_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_DITEM_EDITOR))
+#define PANEL_IS_DITEM_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_DITEM_EDITOR))
+#define PANEL_DITEM_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_DITEM_EDITOR, PanelDItemEditorClass))
+
+typedef struct _PanelDItemEditor PanelDItemEditor;
+typedef struct _PanelDItemEditorClass PanelDItemEditorClass;
+
+typedef struct _PanelDItemEditorPrivate PanelDItemEditorPrivate;
+
+struct _PanelDItemEditorClass
+{
+ GtkDialogClass parent_class;
+
+ /* File has been saved */
+ void (* saved) (PanelDItemEditor *dialog);
+
+ /* Any information changed */
+ void (* changed) (PanelDItemEditor *dialog);
+
+ /* These more specific signals are provided since they
+ * will likely require a display update */
+ /* The name of the item has changed. */
+ void (* name_changed) (PanelDItemEditor *dialog,
+ const char *name);
+ /* The command of the item has changed. */
+ void (* command_changed) (PanelDItemEditor *dialog,
+ const char *command);
+ /* The comment of the item has changed. */
+ void (* comment_changed) (PanelDItemEditor *dialog,
+ const char *comment);
+ /* The icon in particular has changed. */
+ void (* icon_changed) (PanelDItemEditor *dialog,
+ const char *icon);
+
+ /* An error is reported. */
+ void (* error_reported) (PanelDItemEditor *dialog,
+ const char *error);
+};
+
+struct _PanelDItemEditor
+{
+ GtkDialog parent_instance;
+
+ PanelDItemEditorPrivate *priv;
+};
+
+typedef char * (*PanelDitemSaveUri) (PanelDItemEditor *dialog, gpointer data);
+
+GType panel_ditem_editor_get_type (void);
+
+GtkWidget *panel_ditem_editor_new (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title);
+
+GtkWidget *panel_ditem_editor_new_directory (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title);
+
+void panel_ditem_editor_sync_display (PanelDItemEditor *dialog);
+
+GKeyFile *panel_ditem_editor_get_key_file (PanelDItemEditor *dialog);
+GKeyFile *panel_ditem_editor_get_revert_key_file (PanelDItemEditor *dialog);
+
+void panel_ditem_editor_set_uri (PanelDItemEditor *dialog,
+ const char *uri);
+
+const char* panel_ditem_editor_get_uri(PanelDItemEditor* dialog);
+
+void panel_ditem_register_save_uri_func (PanelDItemEditor *dialog,
+ PanelDitemSaveUri save_uri,
+ gpointer data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_DITEM_EDITOR_H */
diff --git a/mate-panel/panel-enums.h b/mate-panel/panel-enums.h
new file mode 100644
index 00000000..b9418fbb
--- /dev/null
+++ b/mate-panel/panel-enums.h
@@ -0,0 +1,110 @@
+/*
+ * panel-enums.h:
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_ENUMS_H__
+#define __PANEL_ENUMS_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ PANEL_ORIENTATION_TOP = 1 << 0,
+ PANEL_ORIENTATION_RIGHT = 1 << 1,
+ PANEL_ORIENTATION_BOTTOM = 1 << 2,
+ PANEL_ORIENTATION_LEFT = 1 << 3
+} PanelOrientation;
+
+#define PANEL_HORIZONTAL_MASK (PANEL_ORIENTATION_TOP | PANEL_ORIENTATION_BOTTOM)
+#define PANEL_VERTICAL_MASK (PANEL_ORIENTATION_LEFT | PANEL_ORIENTATION_RIGHT)
+
+typedef enum {
+ PANEL_EDGE_NONE = 0,
+ PANEL_EDGE_TOP = 1 << 0,
+ PANEL_EDGE_BOTTOM = 1 << 1,
+ PANEL_EDGE_LEFT = 1 << 2,
+ PANEL_EDGE_RIGHT = 1 << 3
+} PanelFrameEdge;
+
+typedef enum {
+ PANEL_STATE_NORMAL = 0,
+ PANEL_STATE_AUTO_HIDDEN = 1,
+ PANEL_STATE_HIDDEN_UP = 2,
+ PANEL_STATE_HIDDEN_DOWN = 3,
+ PANEL_STATE_HIDDEN_LEFT = 4,
+ PANEL_STATE_HIDDEN_RIGHT = 5
+} PanelState;
+
+typedef enum {
+ PANEL_ANIMATION_SLOW = 0,
+ PANEL_ANIMATION_MEDIUM = 1,
+ PANEL_ANIMATION_FAST = 2
+} PanelAnimationSpeed;
+
+typedef enum {
+ PANEL_BACK_NONE = 0,
+ PANEL_BACK_COLOR = 1,
+ PANEL_BACK_IMAGE = 2
+} PanelBackgroundType;
+
+typedef enum {
+ PANEL_MATECONF_TOPLEVELS,
+ PANEL_MATECONF_OBJECTS,
+ PANEL_MATECONF_APPLETS
+} PanelMateConfKeyType;
+
+typedef enum {
+ PANEL_OBJECT_DRAWER,
+ PANEL_OBJECT_MENU,
+ PANEL_OBJECT_LAUNCHER,
+ PANEL_OBJECT_APPLET,
+ PANEL_OBJECT_ACTION,
+ PANEL_OBJECT_MENU_BAR,
+ PANEL_OBJECT_SEPARATOR,
+ /* The following two are for backwards compatibility with 2.0.x */
+ PANEL_OBJECT_LOGOUT,
+ PANEL_OBJECT_LOCK
+} PanelObjectType;
+
+typedef enum {
+ PANEL_ACTION_NONE = 0,
+ PANEL_ACTION_LOCK,
+ PANEL_ACTION_LOGOUT,
+ PANEL_ACTION_RUN,
+ PANEL_ACTION_SEARCH,
+ PANEL_ACTION_FORCE_QUIT,
+ PANEL_ACTION_CONNECT_SERVER,
+ PANEL_ACTION_SHUTDOWN,
+ /* compatibility with MATE < 2.13.90 */
+ PANEL_ACTION_SCREENSHOT,
+ PANEL_ACTION_LAST
+} PanelActionButtonType;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_ENUMS_H__ */
diff --git a/mate-panel/panel-force-quit.c b/mate-panel/panel-force-quit.c
new file mode 100644
index 00000000..fabad1ac
--- /dev/null
+++ b/mate-panel/panel-force-quit.c
@@ -0,0 +1,316 @@
+/*
+ * panel-force-quit.c:
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-force-quit.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include "panel-icon-names.h"
+#include "panel-stock-icons.h"
+
+static GdkFilterReturn popup_filter (GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ GtkWidget *popup);
+
+static Atom wm_state_atom = None;
+
+static GtkWidget *
+display_popup_window (GdkScreen *screen)
+{
+ GtkWidget *retval;
+ GtkWidget *vbox;
+ GtkWidget *image;
+ GtkWidget *frame;
+ GtkWidget *label;
+ int screen_width, screen_height;
+ GtkAllocation allocation;
+
+ retval = gtk_window_new (GTK_WINDOW_POPUP);
+ atk_object_set_role (gtk_widget_get_accessible (retval), ATK_ROLE_ALERT);
+ gtk_window_set_screen (GTK_WINDOW (retval), screen);
+ gtk_window_stick (GTK_WINDOW (retval));
+ gtk_widget_add_events (retval, GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+ gtk_container_add (GTK_CONTAINER (retval), frame);
+ gtk_widget_show (frame);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_widget_show (vbox);
+
+ image = gtk_image_new_from_icon_name (PANEL_ICON_FORCE_QUIT,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), image, TRUE, TRUE, 4);
+ gtk_widget_show (image);
+
+ label = gtk_label_new (_("Click on a window to force the application to quit. "
+ "To cancel press <ESC>."));
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+ gtk_widget_show (label);
+
+ gtk_widget_realize (retval);
+
+ screen_width = gdk_screen_get_width (screen);
+ screen_height = gdk_screen_get_height (screen);
+
+ gtk_widget_get_allocation (retval, &allocation);
+
+ gtk_window_move (GTK_WINDOW (retval),
+ (screen_width - allocation.width) / 2,
+ (screen_height - allocation.height) / 2);
+
+ gtk_widget_show (GTK_WIDGET (retval));
+
+ return retval;
+}
+
+static void
+remove_popup (GtkWidget *popup)
+{
+ GdkWindow *root;
+
+ root = gdk_screen_get_root_window (
+ gtk_window_get_screen (GTK_WINDOW (popup)));
+ gdk_window_remove_filter (root, (GdkFilterFunc) popup_filter, popup);
+
+ gtk_widget_destroy (popup);
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+}
+
+static gboolean
+wm_state_set (Display *display,
+ Window window)
+{
+ gulong nitems;
+ gulong bytes_after;
+ gulong *prop;
+ Atom ret_type = None;
+ int ret_format;
+ int result;
+
+ gdk_error_trap_push ();
+ result = XGetWindowProperty (display, window, wm_state_atom,
+ 0, G_MAXLONG, False, wm_state_atom,
+ &ret_type, &ret_format, &nitems,
+ &bytes_after, (gpointer) &prop);
+
+ if (gdk_error_trap_pop ())
+ return FALSE;
+
+ if (result != Success)
+ return FALSE;
+
+ XFree (prop);
+
+ if (ret_type != wm_state_atom)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Window
+find_managed_window (Display *display,
+ Window window)
+{
+ Window root;
+ Window parent;
+ Window *kids = NULL;
+ Window retval;
+ guint nkids;
+ int i, result;
+
+ if (wm_state_set (display, window))
+ return window;
+
+ gdk_error_trap_push ();
+ result = XQueryTree (display, window, &root, &parent, &kids, &nkids);
+ if (gdk_error_trap_pop () || !result)
+ return None;
+
+ retval = None;
+
+ for (i = 0; i < nkids; i++) {
+ if (wm_state_set (display, kids [i])) {
+ retval = kids [i];
+ break;
+ }
+
+ retval = find_managed_window (display, kids [i]);
+ if (retval != None)
+ break;
+ }
+
+ if (kids)
+ XFree (kids);
+
+ return retval;
+}
+
+static void
+kill_window_response (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ Display *display;
+ Window window = (Window) user_data;
+
+ display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (dialog)));
+
+ gdk_error_trap_push ();
+ XKillClient (display, window);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+/* From marco */
+static void
+kill_window_question (gpointer window)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("Force this application to exit?"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you choose to force an application "
+ "to exit, unsaved changes in any open documents "
+ "in it might get lost."));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ PANEL_STOCK_FORCE_QUIT,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CANCEL);
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Force Quit"));
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (kill_window_response), window);
+
+ gtk_widget_show (dialog);
+}
+
+static void
+handle_button_press_event (GtkWidget *popup,
+ XKeyEvent *event)
+{
+ Window window;
+
+ remove_popup (popup);
+
+ if (event->subwindow == None)
+ return;
+
+ if (wm_state_atom == None)
+ wm_state_atom = XInternAtom (event->display, "WM_STATE", FALSE);
+
+ window = find_managed_window (event->display, event->subwindow);
+
+ if (window != None) {
+ if (!gdk_xid_table_lookup_for_display (gdk_x11_lookup_xdisplay (event->display), window))
+ kill_window_question ((gpointer) window);
+ }
+}
+
+static GdkFilterReturn
+popup_filter (GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ GtkWidget *popup)
+{
+ XEvent *xevent = (XEvent *) gdk_xevent;
+
+ switch (xevent->type) {
+ case ButtonPress:
+ handle_button_press_event (popup, &xevent->xkey);
+ return GDK_FILTER_REMOVE;
+ case KeyPress:
+ if (xevent->xkey.keycode == XKeysymToKeycode (xevent->xany.display, XK_Escape)) {
+ remove_popup (popup);
+ return GDK_FILTER_REMOVE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+void
+panel_force_quit (GdkScreen *screen,
+ guint time)
+{
+ GdkGrabStatus status;
+ GdkCursor *cross;
+ GtkWidget *popup;
+ GdkWindow *root;
+
+ popup = display_popup_window (screen);
+
+ root = gdk_screen_get_root_window (screen);
+
+ gdk_window_add_filter (root, (GdkFilterFunc) popup_filter, popup);
+
+ cross = gdk_cursor_new (GDK_CROSS);
+ status = gdk_pointer_grab (root, FALSE, GDK_BUTTON_PRESS_MASK,
+ NULL, cross, time);
+ gdk_cursor_unref (cross);
+ if (status != GDK_GRAB_SUCCESS) {
+ g_warning ("Pointer grab failed\n");
+ remove_popup (popup);
+ return;
+ }
+
+ status = gdk_keyboard_grab (root, FALSE, time);
+ if (status != GDK_GRAB_SUCCESS) {
+ g_warning ("Keyboard grab failed\n");
+ remove_popup (popup);
+ return;
+ }
+
+ gdk_flush ();
+}
diff --git a/mate-panel/panel-force-quit.h b/mate-panel/panel-force-quit.h
new file mode 100644
index 00000000..ac5be19e
--- /dev/null
+++ b/mate-panel/panel-force-quit.h
@@ -0,0 +1,41 @@
+/*
+ * panel-force-quit.h
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_FORCE_QUIT_H__
+#define __PANEL_FORCE_QUIT_H__
+
+#include <gdk/gdk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_force_quit (GdkScreen *screen,
+ guint time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_FORCE_QUIT_H__ */
diff --git a/mate-panel/panel-frame.c b/mate-panel/panel-frame.c
new file mode 100644
index 00000000..1716784e
--- /dev/null
+++ b/mate-panel/panel-frame.c
@@ -0,0 +1,328 @@
+/*
+ * panel-frame.c: A frame which only draws certain edges.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-frame.h"
+
+#include "panel-typebuiltins.h"
+
+G_DEFINE_TYPE (PanelFrame, panel_frame, GTK_TYPE_BIN)
+
+enum {
+ PROP_0,
+ PROP_EDGES
+};
+
+static void
+panel_frame_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ PanelFrame *frame = (PanelFrame *) widget;
+ GtkBin *bin = (GtkBin *) widget;
+ GtkStyle *style;
+ GtkWidget *child;
+ int border_width;
+
+ style = gtk_widget_get_style (widget);
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+ requisition->width = 1;
+ requisition->height = 1;
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_request (child, requisition);
+
+ requisition->width += border_width;
+ requisition->height += border_width;
+
+ if (frame->edges & PANEL_EDGE_TOP)
+ requisition->height += style->xthickness;
+ if (frame->edges & PANEL_EDGE_BOTTOM)
+ requisition->height += style->xthickness;
+ if (frame->edges & PANEL_EDGE_LEFT)
+ requisition->width += style->ythickness;
+ if (frame->edges & PANEL_EDGE_RIGHT)
+ requisition->width += style->ythickness;
+}
+
+static void
+panel_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ PanelFrame *frame = (PanelFrame *) widget;
+ GtkBin *bin = (GtkBin *) widget;
+ GtkStyle *style;
+ GtkAllocation child_allocation;
+ GtkAllocation child_allocation_current;
+ GtkWidget *child;
+ int border_width;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ style = gtk_widget_get_style (widget);
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+ child_allocation.x = allocation->x + border_width;
+ child_allocation.y = allocation->y + border_width;
+ child_allocation.width = allocation->width - 2 * border_width;
+ child_allocation.height = allocation->height - 2 * border_width;
+
+ if (frame->edges & PANEL_EDGE_LEFT) {
+ child_allocation.x += style->xthickness;
+ child_allocation.width -= style->xthickness;
+ }
+
+ if (frame->edges & PANEL_EDGE_TOP) {
+ child_allocation.y += style->ythickness;
+ child_allocation.height -= style->ythickness;
+ }
+
+ if (frame->edges & PANEL_EDGE_RIGHT)
+ child_allocation.width -= style->xthickness;
+
+ if (frame->edges & PANEL_EDGE_BOTTOM)
+ child_allocation.height -= style->ythickness;
+
+ child = gtk_bin_get_child (bin);
+ gtk_widget_get_allocation (child, &child_allocation_current);
+
+ if (gtk_widget_get_mapped (widget) &&
+ (child_allocation.x != child_allocation_current.x ||
+ child_allocation.y != child_allocation_current.y ||
+ child_allocation.width != child_allocation_current.width ||
+ child_allocation.height != child_allocation_current.height))
+ gdk_window_invalidate_rect (gtk_widget_get_window (widget), allocation, FALSE);
+
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_allocate (child, &child_allocation);
+}
+
+void
+panel_frame_draw (GtkWidget *widget,
+ PanelFrameEdge edges)
+{
+ GdkWindow *window;
+ GtkStyle *style;
+ GtkStateType state;
+ GtkAllocation allocation;
+ GdkGC *dark, *light, *black;
+ int x, y, width, height;
+ int xthickness, ythickness;
+
+ if (edges == PANEL_EDGE_NONE)
+ return;
+
+ window = gtk_widget_get_window (widget);
+ style = gtk_widget_get_style (widget);
+ state = gtk_widget_get_state (widget);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ dark = style->dark_gc [state];
+ light = style->light_gc [state];
+ black = style->black_gc;
+
+ xthickness = style->xthickness;
+ ythickness = style->ythickness;
+
+ x = allocation.x;
+ y = allocation.y;
+ width = allocation.width;
+ height = allocation.height;
+
+ /* Copied from gtk_default_draw_shadow() */
+
+ if (edges & PANEL_EDGE_BOTTOM && ythickness > 0) {
+ if (ythickness > 1) {
+ gdk_draw_line (window, dark,
+ x, y + height - 2,
+ x + width - 1, y + height - 2);
+ gdk_draw_line (window, black,
+ x, y + height - 1,
+ x + width - 1, y + height - 1);
+ } else
+ gdk_draw_line (window, dark,
+ x, y + height - 1,
+ x + width - 1, y + height - 1);
+ }
+
+ if (edges & PANEL_EDGE_RIGHT && xthickness > 0) {
+ if (xthickness > 1) {
+ gdk_draw_line (window, dark,
+ x + width - 2, y,
+ x + width - 2, y + height - 1);
+
+ gdk_draw_line (window, black,
+ x + width - 1, y,
+ x + width - 1, y + height - 1);
+ } else
+ gdk_draw_line (window, dark,
+ x + width - 1, y,
+ x + width - 1, y + height - 1);
+ }
+
+ if (edges & PANEL_EDGE_TOP && ythickness > 0) {
+ gdk_draw_line (window, light,
+ x, y, x + width - 1, y);
+
+ if (ythickness > 1)
+ gdk_draw_line (window,
+ style->bg_gc [state],
+ x, y + 1, x + width - 1, y + 1);
+ }
+
+ if (edges & PANEL_EDGE_LEFT && xthickness > 0) {
+ gdk_draw_line (window, light,
+ x, y, x, y + height - 1);
+
+ if (xthickness > 1)
+ gdk_draw_line (window,
+ style->bg_gc [state],
+ x + 1, y, x + 1, y + height - 1);
+ }
+}
+
+static gboolean panel_frame_expose(GtkWidget* widget, GdkEventExpose* event)
+{
+ PanelFrame *frame = (PanelFrame *) widget;
+ gboolean retval = FALSE;
+
+ if (!gtk_widget_is_drawable (widget))
+ return retval;
+
+ if (GTK_WIDGET_CLASS (panel_frame_parent_class)->expose_event)
+ {
+ retval = GTK_WIDGET_CLASS (panel_frame_parent_class)->expose_event (widget, event);
+ }
+
+ panel_frame_draw (widget, frame->edges);
+
+ return retval;
+}
+
+static void
+panel_frame_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelFrame *frame;
+
+ g_return_if_fail (PANEL_IS_FRAME (object));
+
+ frame = PANEL_FRAME (object);
+
+ switch (prop_id) {
+ case PROP_EDGES:
+ panel_frame_set_edges (frame, g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_frame_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelFrame *frame;
+
+ g_return_if_fail (PANEL_IS_FRAME (object));
+
+ frame = PANEL_FRAME (object);
+
+ switch (prop_id) {
+ case PROP_EDGES:
+ g_value_set_enum (value, frame->edges);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_frame_class_init (PanelFrameClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+
+ gobject_class->set_property = panel_frame_set_property;
+ gobject_class->get_property = panel_frame_get_property;
+
+ widget_class->size_request = panel_frame_size_request;
+ widget_class->size_allocate = panel_frame_size_allocate;
+ widget_class->expose_event = panel_frame_expose;
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_EDGES,
+ g_param_spec_enum (
+ "edges",
+ "Edges",
+ "Which edges to draw",
+ PANEL_TYPE_FRAME_EDGE,
+ PANEL_EDGE_NONE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+panel_frame_init (PanelFrame *frame)
+{
+ frame->edges = PANEL_EDGE_NONE;
+}
+
+GtkWidget *
+panel_frame_new (PanelFrameEdge edges)
+{
+ return g_object_new (PANEL_TYPE_FRAME, "edges", edges, NULL);
+}
+
+void
+panel_frame_set_edges (PanelFrame *frame,
+ PanelFrameEdge edges)
+{
+ g_return_if_fail (PANEL_IS_FRAME (frame));
+
+ if (frame->edges == edges)
+ return;
+
+ frame->edges = edges;
+
+ gtk_widget_queue_resize (GTK_WIDGET (frame));
+
+ g_object_notify (G_OBJECT (frame), "edges");
+}
+
+PanelFrameEdge
+panel_frame_get_edges (PanelFrame *frame)
+{
+ g_return_val_if_fail (PANEL_IS_FRAME (frame), 0);
+
+ return frame->edges;
+}
diff --git a/mate-panel/panel-frame.h b/mate-panel/panel-frame.h
new file mode 100644
index 00000000..bffef745
--- /dev/null
+++ b/mate-panel/panel-frame.h
@@ -0,0 +1,69 @@
+/*
+ * panel-frame.h: A frame which only draws certain edges.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_FRAME_H__
+#define __PANEL_FRAME_H__
+
+#include <gtk/gtk.h>
+#include "panel-enums.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_FRAME (panel_frame_get_type ())
+#define PANEL_FRAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_FRAME, PanelFrame))
+#define PANEL_FRAME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_FRAME, PanelFrameClass))
+#define PANEL_IS_FRAME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_FRAME))
+#define PANEL_IS_FRAME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_FRAME))
+#define PANEL_FRAME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_FRAME, PanelFrameClass))
+
+typedef struct _PanelFrame PanelFrame;
+typedef struct _PanelFrameClass PanelFrameClass;
+
+struct _PanelFrame {
+ GtkBin bin_instance;
+
+ PanelFrameEdge edges;
+};
+
+struct _PanelFrameClass {
+ GtkBinClass bin_class;
+};
+
+GType panel_frame_get_type (void) G_GNUC_CONST;
+GtkWidget *panel_frame_new (PanelFrameEdge edges);
+
+void panel_frame_set_edges (PanelFrame *toplevel,
+ PanelFrameEdge edges);
+PanelFrameEdge panel_frame_get_edges (PanelFrame *toplevel);
+
+void panel_frame_draw (GtkWidget *widget,
+ PanelFrameEdge edges);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_FRAME_H__ */
diff --git a/mate-panel/panel-general.schemas.in b/mate-panel/panel-general.schemas.in
new file mode 100644
index 00000000..1bfc2c7a
--- /dev/null
+++ b/mate-panel/panel-general.schemas.in
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<mateconfschemafile>
+
+ <schemalist>
+
+ <schema>
+ <key>/schemas/apps/panel/general/enable_program_list</key>
+ <applyto>/apps/panel/general/enable_program_list</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable program list in "Run Application" dialog</short>
+ <long>
+ If true, the "Known Applications" listing in the "Run
+ Application" dialog is made available. Whether or not
+ the listing is expanded when the dialog is shown is
+ controlled by the show_program_list key.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/general/show_program_list</key>
+ <applyto>/apps/panel/general/show_program_list</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Expand program list in "Run Application" dialog</short>
+ <long>
+ If true, the "Known Applications" listing in the "Run
+ Application" dialog is expanded when the dialog is opened.
+ This key is only relevant if the enable_program_list key
+ is true.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/general/enable_autocompletion</key>
+ <applyto>/apps/panel/general/enable_autocompletion</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable autocompletion in "Run Application" dialog</short>
+ <long>
+ If true, autocompletion in the "Run Application" dialog is
+ made available.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/general/toplevel_id_list</key>
+ <applyto>/apps/panel/general/toplevel_id_list</applyto>
+ <owner>panel</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Panel ID list</short>
+ <long>
+ A list of panel IDs. Each ID identifies an individual
+ toplevel panel. The settings for each of these panels are
+ stored in /apps/panel/toplevels/$(id).
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/general/applet_id_list</key>
+ <applyto>/apps/panel/general/applet_id_list</applyto>
+ <owner>panel</owner>
+ <list_type>string</list_type>
+ <type>list</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Panel applet ID list</short>
+ <long>
+ A list of panel applet IDs. Each ID identifies an
+ individual panel applet. The settings for each of
+ these applets are stored in
+ /apps/panel/applets/$(id).
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/general/object_id_list</key>
+ <applyto>/apps/panel/general/object_id_list</applyto>
+ <owner>panel</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Panel object ID list</short>
+ <long>
+ A list of panel object IDs. Each ID identifies an individual
+ panel object (e.g. a launcher, action button or menu
+ button/bar). The settings for each of these objects are
+ stored in
+ /apps/panel/objects/$(id).
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/general/profiles_migrated</key>
+ <applyto>/apps/panel/general/profiles_migrated</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Old profiles configuration migrated</short>
+ <long>
+ A boolean flag to indicate whether the user's previous
+ configuration in /apps/panel/profiles/default has been
+ copied to the new location in /apps/panel.
+ </long>
+ </locale>
+ </schema>
+
+ </schemalist>
+
+</mateconfschemafile>
diff --git a/mate-panel/panel-global.schemas.in b/mate-panel/panel-global.schemas.in
new file mode 100644
index 00000000..f99c5b28
--- /dev/null
+++ b/mate-panel/panel-global.schemas.in
@@ -0,0 +1,276 @@
+<?xml version="1.0"?>
+<mateconfschemafile>
+
+<!--
+Panel Global Config Schema File - work in progress
+-->
+
+ <schemalist>
+
+ <schema>
+ <key>/schemas/apps/panel/global/tooltips_enabled</key>
+ <applyto>/apps/panel/global/tooltips_enabled</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable tooltips</short>
+ <long>If true, tooltips are shown for objects in panels.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/keep_menus_in_memory</key>
+ <applyto>/apps/panel/global/keep_menus_in_memory</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/enable_animations</key>
+ <applyto>/apps/panel/global/enable_animations</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable animations</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/panel_minimized_size</key>
+ <applyto>/apps/panel/global/panel_minimized_size</applyto>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>3</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/panel_show_delay</key>
+ <applyto>/apps/panel/global/panel_show_delay</applyto>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>300</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/panel_animation_speed</key>
+ <applyto>/apps/panel/global/panel_animation_speed</applyto>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>panel-speed-medium</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/panel_hide_delay</key>
+ <applyto>/apps/panel/global/panel_hide_delay</applyto>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>500</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/enable_key_bindings</key>
+ <applyto>/apps/panel/global/enable_key_bindings</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/menu_key</key>
+ <applyto>/apps/panel/global/menu_key</applyto>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;F1</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/run_key</key>
+ <applyto>/apps/panel/global/run_key</applyto>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;F2</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/screenshot_key</key>
+ <applyto>/apps/panel/global/screenshot_key</applyto>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>Print</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/window_screenshot_key</key>
+ <applyto>/apps/panel/global/window_screenshot_key</applyto>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Print</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long></long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/drawer_autoclose</key>
+ <applyto>/apps/panel/global/drawer_autoclose</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Autoclose drawer</short>
+ <long>If true, a drawer will automatically be closed
+ when the user clicks a launcher in it.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/confirm_panel_remove</key>
+ <applyto>/apps/panel/global/confirm_panel_remove</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Confirm panel removal</short>
+ <long>If true, a dialog is shown asking for confirmation
+ if the user wants to remove a panel.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/highlight_launchers_on_mouseover</key>
+ <applyto>/apps/panel/global/highlight_launchers_on_mouseover</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Highlight launchers on mouseover</short>
+ <long>If true, a launcher is highlighted when the user
+ moves the pointer over it.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/locked_down</key>
+ <applyto>/apps/panel/global/locked_down</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Complete panel lockdown</short>
+ <long>If true, the panel will not allow any changes to
+ the configuration of the panel. Individual applets
+ may need to be locked down separately however.
+ The panel must be restarted for this to take effect.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/disabled_applets</key>
+ <applyto>/apps/panel/global/disabled_applets</applyto>
+ <owner>panel</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Applet IIDs to disable from loading</short>
+ <long>A list of applet IIDs that the panel will ignore. This way you
+ can disable certain applets from loading or showing up in the menu.
+ For example to disable the mini-commander applet add 'OAFIID:MATE_MiniCommanderApplet'
+ to this list. The panel must be restarted for this to take effect.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/disable_lock_screen</key>
+ <applyto>/apps/panel/global/disable_lock_screen</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Deprecated</short>
+ <long>This key is deprecated as it cannot be used to implement proper
+ lockdown. The /desktop/mate/lockdown/disable_lock_screen key
+ should be used instead.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/disable_log_out</key>
+ <applyto>/apps/panel/global/disable_log_out</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Disable Logging Out</short>
+ <long>If true, the panel will not allow a user to log out,
+ by removing access to the log out menu entries.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/global/disable_force_quit</key>
+ <applyto>/apps/panel/global/disable_force_quit</applyto>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Disable Force Quit</short>
+ <long>If true, the panel will not allow a user to force
+ an application to quit by removing access to the
+ force quit button.
+ </long>
+ </locale>
+ </schema>
+
+ </schemalist>
+
+</mateconfschemafile>
diff --git a/mate-panel/panel-globals.h b/mate-panel/panel-globals.h
new file mode 100644
index 00000000..fe83c237
--- /dev/null
+++ b/mate-panel/panel-globals.h
@@ -0,0 +1,41 @@
+/*
+ * panel-globals.h: panel global variables
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_GLOBALS_H__
+#define __PANEL_GLOBALS_H__
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern GSList *panels;
+extern GSList *panel_list;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_GLOBALS_H__ */
diff --git a/mate-panel/panel-icon-names.h b/mate-panel/panel-icon-names.h
new file mode 100644
index 00000000..4c948b76
--- /dev/null
+++ b/mate-panel/panel-icon-names.h
@@ -0,0 +1,40 @@
+#ifndef PANEL_ICON_NAMES_H
+#define PANEL_ICON_NAMES_H
+
+#define PANEL_ICON_BOOKMARKS "user-bookmarks"
+#define PANEL_ICON_BURNER "caja-cd-burner"
+#define PANEL_ICON_COMPUTER "computer"
+#define PANEL_ICON_DESKTOP "user-desktop"
+#define PANEL_ICON_DRAWER "mate-panel-drawer"
+#define PANEL_ICON_FILESYSTEM "drive-harddisk"
+#define PANEL_ICON_FOLDER "folder"
+#define PANEL_ICON_FOLDER_DOCUMENTS "folder-documents"
+#define PANEL_ICON_FOLDER_DOWNLOAD "folder-download"
+#define PANEL_ICON_FOLDER_MUSIC "folder-music"
+#define PANEL_ICON_FOLDER_PICTURES "folder-pictures"
+#define PANEL_ICON_FOLDER_PUBLIC_SHARE "folder-publicshare"
+#define PANEL_ICON_FOLDER_TEMPLATES "folder-templates"
+#define PANEL_ICON_FOLDER_VIDEOS "folder-videos"
+#define PANEL_ICON_FONTS "preferences-desktop-font"
+#define PANEL_ICON_FORCE_QUIT "mate-panel-force-quit"
+#define PANEL_ICON_HOME "user-home"
+#define PANEL_ICON_LAUNCHER "mate-panel-launcher"
+#define PANEL_ICON_LOCKSCREEN "system-lock-screen"
+#define PANEL_ICON_LOGOUT "system-log-out"
+#define PANEL_ICON_MAIN_MENU "start-here"
+#define PANEL_ICON_NETWORK "network-workgroup"
+#define PANEL_ICON_NETWORK_SERVER "network-server"
+#define PANEL_ICON_PANEL "mate-panel"
+#define PANEL_ICON_RECENT "document-open-recent"
+#define PANEL_ICON_REMOTE "applications-internet"
+#define PANEL_ICON_REMOVABLE_MEDIA "drive-removable-media"
+#define PANEL_ICON_RUN "system-run"
+#define PANEL_ICON_SEPARATOR "mate-panel-separator"
+#define PANEL_ICON_SAVED_SEARCH "folder-saved-search"
+#define PANEL_ICON_SEARCHTOOL "system-search"
+#define PANEL_ICON_SHUTDOWN "system-shutdown"
+#define PANEL_ICON_THEME "preferences-desktop-theme"
+#define PANEL_ICON_TRASH "user-trash"
+#define PANEL_ICON_UNKNOWN "image-missing"
+
+#endif /* PANEL_ICON_NAMES_H */
diff --git a/mate-panel/panel-lockdown.c b/mate-panel/panel-lockdown.c
new file mode 100644
index 00000000..e484b016
--- /dev/null
+++ b/mate-panel/panel-lockdown.c
@@ -0,0 +1,442 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Matt Keenan <[email protected]>
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-lockdown.h"
+
+#include <string.h>
+#include "panel-mateconf.h"
+
+#define N_LISTENERS 6
+
+#define PANEL_GLOBAL_LOCKDOWN_DIR "/apps/panel/global"
+#define DESKTOP_MATE_LOCKDOWN_DIR "/desktop/mate/lockdown"
+#define PANEL_GLOBAL_LOCKED_DOWN_KEY PANEL_GLOBAL_LOCKDOWN_DIR "/locked_down"
+#define DISABLE_COMMAND_LINE_KEY DESKTOP_MATE_LOCKDOWN_DIR "/disable_command_line"
+#define DISABLE_LOCK_SCREEN_KEY DESKTOP_MATE_LOCKDOWN_DIR "/disable_lock_screen"
+#define DISABLE_LOG_OUT_KEY PANEL_GLOBAL_LOCKDOWN_DIR "/disable_log_out"
+#define DISABLE_FORCE_QUIT_KEY PANEL_GLOBAL_LOCKDOWN_DIR "/disable_force_quit"
+#define DISABLED_APPLETS_KEY PANEL_GLOBAL_LOCKDOWN_DIR "/disabled_applets"
+
+typedef struct {
+ guint initialized : 1;
+
+ guint locked_down : 1;
+ guint disable_command_line : 1;
+ guint disable_lock_screen : 1;
+ guint disable_log_out : 1;
+ guint disable_force_quit : 1;
+
+ GSList *disabled_applets;
+
+ guint listeners [N_LISTENERS];
+
+ GSList *closures;
+} PanelLockdown;
+
+static PanelLockdown panel_lockdown = { 0, };
+
+
+static inline void
+panel_lockdown_invoke_closures (PanelLockdown *lockdown)
+{
+ GSList *l;
+
+ for (l = lockdown->closures; l; l = l->next)
+ g_closure_invoke (l->data, NULL, 0, NULL, NULL);
+}
+
+static void
+locked_down_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelLockdown *lockdown)
+{
+ if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ lockdown->locked_down = mateconf_value_get_bool (entry->value);
+
+ panel_lockdown_invoke_closures (lockdown);
+}
+
+static void
+disable_command_line_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelLockdown *lockdown)
+{
+ if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ lockdown->disable_command_line = mateconf_value_get_bool (entry->value);
+
+ panel_lockdown_invoke_closures (lockdown);
+}
+
+static void
+disable_lock_screen_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelLockdown *lockdown)
+{
+ if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ lockdown->disable_lock_screen = mateconf_value_get_bool (entry->value);
+
+ panel_lockdown_invoke_closures (lockdown);
+}
+
+static void
+disable_log_out_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelLockdown *lockdown)
+{
+ if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ lockdown->disable_log_out = mateconf_value_get_bool (entry->value);
+
+ panel_lockdown_invoke_closures (lockdown);
+}
+
+static void
+disable_force_quit_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelLockdown *lockdown)
+{
+ if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL)
+ return;
+
+ lockdown->disable_force_quit = mateconf_value_get_bool (entry->value);
+
+ panel_lockdown_invoke_closures (lockdown);
+}
+
+static void
+disabled_applets_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelLockdown *lockdown)
+{
+ GSList *l;
+
+ if (!entry->value || entry->value->type != MATECONF_VALUE_LIST ||
+ mateconf_value_get_list_type (entry->value) != MATECONF_VALUE_STRING)
+ return;
+
+ for (l = lockdown->disabled_applets; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (lockdown->disabled_applets);
+ lockdown->disabled_applets = NULL;
+
+ for (l = mateconf_value_get_list (entry->value); l; l = l->next) {
+ const char *iid = mateconf_value_get_string (l->data);
+
+ lockdown->disabled_applets =
+ g_slist_prepend (lockdown->disabled_applets,
+ g_strdup (iid));
+ }
+
+ panel_lockdown_invoke_closures (lockdown);
+}
+
+static gboolean
+panel_lockdown_load_bool (PanelLockdown *lockdown,
+ MateConfClient *client,
+ const char *key,
+ MateConfClientNotifyFunc notify_func,
+ int listener)
+{
+ GError *error = NULL;
+ gboolean retval;
+
+ retval = mateconf_client_get_bool (client, key, &error);
+ if (error) {
+ g_warning ("Error getting value of '%s': %s\n",
+ key, error->message);
+ retval = FALSE;
+ }
+
+ lockdown->listeners [listener] =
+ mateconf_client_notify_add (client,
+ key,
+ notify_func,
+ lockdown,
+ NULL, NULL);
+
+ return retval;
+}
+
+static GSList *
+panel_lockdown_load_disabled_applets (PanelLockdown *lockdown,
+ MateConfClient *client,
+ int listener)
+{
+ GSList *retval;
+
+ retval = mateconf_client_get_list (client,
+ DISABLED_APPLETS_KEY,
+ MATECONF_VALUE_STRING,
+ NULL);
+
+ lockdown->listeners [listener] =
+ mateconf_client_notify_add (client,
+ DISABLED_APPLETS_KEY,
+ (MateConfClientNotifyFunc) disabled_applets_notify,
+ lockdown,
+ NULL, NULL);
+
+ return retval;
+}
+
+void
+panel_lockdown_init (void)
+{
+ MateConfClient *client;
+ int i = 0;
+
+ client = panel_mateconf_get_client ();
+
+ mateconf_client_add_dir (client,
+ DESKTOP_MATE_LOCKDOWN_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ mateconf_client_add_dir (client,
+ PANEL_GLOBAL_LOCKDOWN_DIR,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ panel_lockdown.locked_down =
+ panel_lockdown_load_bool (&panel_lockdown,
+ client,
+ PANEL_GLOBAL_LOCKED_DOWN_KEY,
+ (MateConfClientNotifyFunc) locked_down_notify,
+ i++);
+
+ panel_lockdown.disable_command_line =
+ panel_lockdown_load_bool (&panel_lockdown,
+ client,
+ DISABLE_COMMAND_LINE_KEY,
+ (MateConfClientNotifyFunc) disable_command_line_notify,
+ i++);
+
+ panel_lockdown.disable_lock_screen =
+ panel_lockdown_load_bool (&panel_lockdown,
+ client,
+ DISABLE_LOCK_SCREEN_KEY,
+ (MateConfClientNotifyFunc) disable_lock_screen_notify,
+ i++);
+
+ panel_lockdown.disable_log_out =
+ panel_lockdown_load_bool (&panel_lockdown,
+ client,
+ DISABLE_LOG_OUT_KEY,
+ (MateConfClientNotifyFunc) disable_log_out_notify,
+ i++);
+
+ panel_lockdown.disable_force_quit =
+ panel_lockdown_load_bool (&panel_lockdown,
+ client,
+ DISABLE_FORCE_QUIT_KEY,
+ (MateConfClientNotifyFunc) disable_force_quit_notify,
+ i++);
+
+ panel_lockdown.disabled_applets =
+ panel_lockdown_load_disabled_applets (&panel_lockdown,
+ client,
+ i++);
+
+ g_assert (i == N_LISTENERS);
+
+ panel_lockdown.initialized = TRUE;
+}
+
+void
+panel_lockdown_finalize (void)
+{
+ MateConfClient *client;
+ GSList *l;
+ int i;
+
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ client = panel_mateconf_get_client ();
+
+ for (l = panel_lockdown.disabled_applets; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (panel_lockdown.disabled_applets);
+ panel_lockdown.disabled_applets = NULL;
+
+ for (i = 0; i < N_LISTENERS; i++) {
+ if (panel_lockdown.listeners [i])
+ mateconf_client_notify_remove (client,
+ panel_lockdown.listeners [i]);
+ panel_lockdown.listeners [i] = 0;
+ }
+
+ mateconf_client_remove_dir (client,
+ PANEL_GLOBAL_LOCKDOWN_DIR,
+ NULL);
+
+ mateconf_client_remove_dir (client,
+ DESKTOP_MATE_LOCKDOWN_DIR,
+ NULL);
+
+ for (l = panel_lockdown.closures; l; l = l->next)
+ g_closure_unref (l->data);
+ g_slist_free (panel_lockdown.closures);
+ panel_lockdown.closures = NULL;
+
+ panel_lockdown.initialized = FALSE;
+}
+
+gboolean
+panel_lockdown_get_locked_down (void)
+{
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ return panel_lockdown.locked_down;
+}
+
+gboolean
+panel_lockdown_get_disable_command_line (void)
+{
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ return panel_lockdown.disable_command_line;
+}
+
+gboolean
+panel_lockdown_get_disable_lock_screen (void)
+{
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ return panel_lockdown.disable_lock_screen;
+}
+
+gboolean
+panel_lockdown_get_disable_log_out (void)
+{
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ return panel_lockdown.disable_log_out;
+}
+
+gboolean
+panel_lockdown_get_disable_force_quit (void)
+{
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ return panel_lockdown.disable_force_quit;
+}
+
+gboolean
+panel_lockdown_is_applet_disabled (const char *iid)
+{
+ GSList *l;
+
+ g_assert (panel_lockdown.initialized != FALSE);
+
+ for (l = panel_lockdown.disabled_applets; l; l = l->next)
+ if (!strcmp (l->data, iid))
+ return TRUE;
+
+ return FALSE;
+}
+
+static GClosure *
+panel_lockdown_notify_find (GSList *closures,
+ GCallback callback_func,
+ gpointer user_data)
+{
+ GSList *l;
+
+ for (l = closures; l; l = l->next) {
+ GCClosure *cclosure = l->data;
+ GClosure *closure = l->data;
+
+ if (closure->data == user_data &&
+ cclosure->callback == callback_func)
+ return closure;
+ }
+
+ return NULL;
+}
+
+static void
+marshal_user_data (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ GCClosure *cclosure = (GCClosure*) closure;
+
+ g_return_if_fail (cclosure->callback != NULL);
+ g_return_if_fail (n_param_values == 0);
+
+ ((void (*) (gpointer *))cclosure->callback) (closure->data);
+}
+
+void
+panel_lockdown_notify_add (GCallback callback_func,
+ gpointer user_data)
+{
+ GClosure *closure;
+
+ g_assert (panel_lockdown_notify_find (panel_lockdown.closures,
+ callback_func,
+ user_data) == NULL);
+
+ closure = g_cclosure_new (callback_func, user_data, NULL);
+ g_closure_set_marshal (closure, marshal_user_data);
+
+ panel_lockdown.closures = g_slist_append (panel_lockdown.closures,
+ closure);
+}
+
+void
+panel_lockdown_notify_remove (GCallback callback_func,
+ gpointer user_data)
+{
+ GClosure *closure;
+
+ closure = panel_lockdown_notify_find (panel_lockdown.closures,
+ callback_func,
+ user_data);
+
+ g_assert (closure != NULL);
+
+ panel_lockdown.closures = g_slist_remove (panel_lockdown.closures,
+ closure);
+
+ g_closure_unref (closure);
+}
diff --git a/mate-panel/panel-lockdown.h b/mate-panel/panel-lockdown.h
new file mode 100644
index 00000000..eaf31fb9
--- /dev/null
+++ b/mate-panel/panel-lockdown.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Matt Keenan <[email protected]>
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_LOCKDOWN_H__
+#define __PANEL_LOCKDOWN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_lockdown_init (void);
+void panel_lockdown_finalize (void);
+
+gboolean panel_lockdown_get_locked_down (void);
+gboolean panel_lockdown_get_disable_command_line (void);
+gboolean panel_lockdown_get_disable_lock_screen (void);
+gboolean panel_lockdown_get_disable_log_out (void);
+gboolean panel_lockdown_get_disable_force_quit (void);
+
+gboolean panel_lockdown_is_applet_disabled (const char *iid);
+
+void panel_lockdown_notify_add (GCallback callback_func,
+ gpointer user_data);
+void panel_lockdown_notify_remove (GCallback callback_func,
+ gpointer user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_LOCKDOWN_H__ */
diff --git a/mate-panel/panel-marshal.list b/mate-panel/panel-marshal.list
new file mode 100644
index 00000000..7893b881
--- /dev/null
+++ b/mate-panel/panel-marshal.list
@@ -0,0 +1,3 @@
+BOOLEAN:VOID
+VOID:STRING,STRING
+VOID:STRING,POINTER
diff --git a/mate-panel/panel-mateconf.c b/mate-panel/panel-mateconf.c
new file mode 100644
index 00000000..974ddb4b
--- /dev/null
+++ b/mate-panel/panel-mateconf.c
@@ -0,0 +1,351 @@
+/*
+ * panel-mateconf.c: panel mateconf utility methods
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ * Glynn Foster <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-mateconf.h"
+
+#include <string.h>
+#include <glib.h>
+#include <mateconf/mateconf-client.h>
+
+#include <libpanel-util/panel-cleanup.h>
+
+#undef PANEL_MATECONF_DEBUG
+
+MateConfClient *
+panel_mateconf_get_client (void)
+{
+ static MateConfClient *panel_mateconf_client = NULL;
+
+ if (!panel_mateconf_client) {
+ panel_mateconf_client = mateconf_client_get_default ();
+ panel_cleanup_register (panel_cleanup_unref_and_nullify,
+ &panel_mateconf_client);
+ }
+
+ return panel_mateconf_client;
+}
+
+/*
+ * panel_mateconf_sprintf:
+ * @format: the format string. See sprintf() documentation.
+ * @...: the arguments to be inserted.
+ *
+ * This is a version of sprintf using a static buffer which is
+ * intended for use in generating the full mateconf key for all panel
+ * config keys.
+ * Note, you should not free the return value from this function and
+ * you should realize that the return value will get overwritten or
+ * freed by a subsequent call to this function.
+ *
+ * Return Value: a pointer to the static string buffer.
+ */
+const char *
+panel_mateconf_sprintf (const char *format,
+ ...)
+{
+ static char *buffer = NULL;
+ static int buflen = 128;
+ va_list args;
+ int len;
+
+ if (!buffer)
+ buffer = g_new (char, buflen);
+
+ va_start (args, format);
+ len = g_vsnprintf (buffer, buflen, format, args);
+
+ if (len >= buflen) {
+ int i;
+
+ /* Round up length to the nearest power of 2 */
+ for (i = 0; len != 1; i++, len >>= 1);
+
+ buflen = len << (i + 1);
+ g_assert (buflen > 0);
+
+ g_free (buffer);
+ buffer = g_new (char, buflen);
+
+ va_start (args, format);
+ len = g_vsnprintf (buffer, buflen, format, args);
+
+ g_assert (len < buflen);
+ }
+
+ va_end (args);
+
+ return buffer;
+}
+
+const char *
+panel_mateconf_key_type_to_id_list (PanelMateConfKeyType type)
+{
+ char *retval;
+
+ switch (type) {
+ case PANEL_MATECONF_TOPLEVELS:
+ retval = "toplevel_id_list";
+ break;
+ case PANEL_MATECONF_APPLETS:
+ retval = "applet_id_list";
+ break;
+ case PANEL_MATECONF_OBJECTS:
+ retval = "object_id_list";
+ break;
+ default:
+ retval = NULL;
+ g_assert_not_reached ();
+ break;
+ }
+
+ return retval;
+}
+
+const char *
+panel_mateconf_global_key (const char *key)
+{
+ return panel_mateconf_sprintf ("/apps/panel/global/%s", key);
+}
+
+const char *
+panel_mateconf_general_key (const char *key)
+{
+ return panel_mateconf_sprintf (PANEL_CONFIG_DIR "/general/%s", key);
+}
+
+const char *
+panel_mateconf_full_key (PanelMateConfKeyType type,
+ const char *id,
+ const char *key)
+{
+ char *subdir = NULL;
+
+ switch (type) {
+ case PANEL_MATECONF_TOPLEVELS:
+ subdir = "toplevels";
+ break;
+ case PANEL_MATECONF_OBJECTS:
+ subdir = "objects";
+ break;
+ case PANEL_MATECONF_APPLETS:
+ subdir = "applets";
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return panel_mateconf_sprintf (PANEL_CONFIG_DIR "/%s/%s/%s",
+ subdir, id, key);
+}
+
+const char *
+panel_mateconf_basename (const char *key)
+{
+ char *retval;
+
+ g_return_val_if_fail (key != NULL, NULL);
+
+ retval = strrchr (key, '/');
+
+ return retval ? retval + 1 : NULL;
+}
+
+char *
+panel_mateconf_dirname (const char *key)
+{
+ char *retval;
+ int len;
+
+ g_return_val_if_fail (key != NULL, NULL);
+
+ retval = strrchr (key, '/');
+ g_assert (retval != NULL);
+
+ len = retval - key;
+ g_assert (len > 0);
+
+ retval = g_new0 (char, len + 1);
+ memcpy (retval, key, len);
+
+ return retval;
+}
+
+static void
+panel_notify_object_dead (guint notify_id)
+{
+ MateConfClient *client;
+
+ client = panel_mateconf_get_client ();
+
+ mateconf_client_notify_remove (client, notify_id);
+}
+
+guint
+panel_mateconf_notify_add_while_alive (const char *key,
+ MateConfClientNotifyFunc notify_func,
+ GObject *alive_object)
+{
+ MateConfClient *client;
+ guint notify_id;
+
+ g_return_val_if_fail (G_IS_OBJECT (alive_object), 0);
+
+ client = panel_mateconf_get_client ();
+
+ notify_id = mateconf_client_notify_add (client, key, notify_func,
+ alive_object, NULL, NULL);
+
+ if (notify_id > 0)
+ g_object_weak_ref (alive_object,
+ (GWeakNotify) panel_notify_object_dead,
+ GUINT_TO_POINTER (notify_id));
+
+ return notify_id;
+}
+
+void
+panel_mateconf_copy_dir (MateConfClient *client,
+ const char *src_dir,
+ const char *dest_dir)
+{
+ GSList *list, *l;
+
+ list = mateconf_client_all_entries (client, src_dir, NULL);
+ for (l = list; l; l = l->next) {
+ MateConfEntry *entry = l->data;
+ const char *key;
+ char *tmp;
+
+ tmp = g_path_get_basename (mateconf_entry_get_key (entry));
+ key = panel_mateconf_sprintf ("%s/%s", dest_dir, tmp);
+ g_free (tmp);
+
+ mateconf_engine_associate_schema (client->engine,
+ key,
+ mateconf_entry_get_schema_name (entry),
+ NULL);
+
+ if (!mateconf_entry_get_is_default (entry) && entry->value)
+ mateconf_client_set (client, key, entry->value, NULL);
+
+ mateconf_entry_unref (entry);
+ }
+ g_slist_free (list);
+
+ list = mateconf_client_all_dirs (client, src_dir, NULL);
+ for (l = list; l; l = l->next) {
+ char *subdir = l->data;
+ char *src_subdir;
+ char *dest_subdir;
+ char *tmp;
+
+ tmp = g_path_get_basename (subdir);
+ src_subdir = mateconf_concat_dir_and_key (src_dir, tmp);
+ dest_subdir = mateconf_concat_dir_and_key (dest_dir, tmp);
+ g_free (tmp);
+
+ panel_mateconf_copy_dir (client, src_subdir, dest_subdir);
+
+ g_free (src_subdir);
+ g_free (dest_subdir);
+ g_free (subdir);
+ }
+
+ g_slist_free (list);
+}
+
+void
+panel_mateconf_associate_schemas_in_dir (MateConfClient *client,
+ const char *profile_dir,
+ const char *schema_dir)
+{
+ GSList *list, *l;
+
+#ifdef PANEL_MATECONF_DEBUG
+ g_print ("associating schemas in %s to %s\n", schema_dir, profile_dir);
+#endif
+
+ list = mateconf_client_all_entries (client, schema_dir, NULL);
+ for (l = list; l; l = l->next) {
+ MateConfEntry *entry = l->data;
+ const char *key;
+ char *tmp;
+
+ tmp = g_path_get_basename (mateconf_entry_get_key (entry));
+
+ key = panel_mateconf_sprintf ("%s/%s", profile_dir, tmp);
+
+ g_free (tmp);
+
+ mateconf_engine_associate_schema (
+ client->engine, key, mateconf_entry_get_key (entry), NULL);
+
+ mateconf_entry_unref (entry);
+ }
+
+ g_slist_free (list);
+
+ list = mateconf_client_all_dirs (client, schema_dir, NULL);
+ for (l = list; l; l = l->next) {
+ char *subdir = l->data;
+ char *prefs_subdir;
+ char *schema_subdir;
+ char *tmp;
+
+ tmp = g_path_get_basename (subdir);
+
+ prefs_subdir = g_strdup_printf ("%s/%s", profile_dir, tmp);
+ schema_subdir = g_strdup_printf ("%s/%s", schema_dir, tmp);
+
+ panel_mateconf_associate_schemas_in_dir (
+ client, prefs_subdir, schema_subdir);
+
+ g_free (prefs_subdir);
+ g_free (schema_subdir);
+ g_free (subdir);
+ g_free (tmp);
+ }
+
+ g_slist_free (list);
+}
+
+gint
+panel_mateconf_value_strcmp (gconstpointer a,
+ gconstpointer b)
+{
+ const char *str_a;
+ const char *str_b;
+
+ if (a == b || !a || !b)
+ return 0;
+
+ str_a = mateconf_value_get_string (a);
+ str_b = mateconf_value_get_string (b);
+
+ return strcmp (str_a, str_b);
+}
diff --git a/mate-panel/panel-mateconf.h b/mate-panel/panel-mateconf.h
new file mode 100644
index 00000000..80c49fa5
--- /dev/null
+++ b/mate-panel/panel-mateconf.h
@@ -0,0 +1,76 @@
+/*
+ * panel-mateconf.h: panel mateconf utility methods
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ * Glynn Foster <[email protected]>
+ */
+
+#ifndef __PANEL_MATECONF_H__
+#define __PANEL_MATECONF_H__
+
+#include <mateconf/mateconf-client.h>
+
+#include "panel-enums.h"
+
+#define PANEL_CONFIG_DIR "/apps/panel"
+#define PANEL_SCHEMAS_DIR "/schemas/apps/panel"
+#define PANEL_DEFAULTS_DIR "/apps/panel/default_setup"
+#define PANEL_OLD_CONFIG_DIR "/apps/panel/profiles/default"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MateConfClient *panel_mateconf_get_client (void);
+
+const char *panel_mateconf_sprintf (const char *format, ...) G_GNUC_PRINTF (1, 2);
+const char *panel_mateconf_basename (const char *key);
+char *panel_mateconf_dirname (const char *key);
+const char *panel_mateconf_global_key (const char *key);
+const char *panel_mateconf_general_key (const char *key);
+const char *panel_mateconf_full_key (PanelMateConfKeyType type,
+ const char *id,
+ const char *key);
+const char *panel_mateconf_key_type_to_id_list (PanelMateConfKeyType type);
+
+guint panel_mateconf_notify_add (const char *key,
+ MateConfClientNotifyFunc notify_func,
+ gpointer user_data);
+guint panel_mateconf_notify_add_while_alive (const char *key,
+ MateConfClientNotifyFunc notify_func,
+ GObject *alive_object);
+
+void panel_mateconf_copy_dir (MateConfClient *client,
+ const char *src_dir,
+ const char *dest_dir);
+
+void panel_mateconf_associate_schemas_in_dir (MateConfClient *client,
+ const char *profile_dir,
+ const char *schema_dir);
+
+gint panel_mateconf_value_strcmp (gconstpointer a,
+ gconstpointer b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_MATECONF_H__ */
diff --git a/mate-panel/panel-menu-bar.c b/mate-panel/panel-menu-bar.c
new file mode 100644
index 00000000..0ea27331
--- /dev/null
+++ b/mate-panel/panel-menu-bar.c
@@ -0,0 +1,474 @@
+/*
+ * panel-menu-bar.c: panel Applications/Places/Desktop menu bar
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ * Vincent Untz <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-menu-bar.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-launch.h>
+#include <libpanel-util/panel-show.h>
+
+#include "panel-util.h"
+#include "panel-background.h"
+#include "panel-action-button.h"
+#include "applet.h"
+#include "menu.h"
+#include "panel-menu-items.h"
+#include "panel-globals.h"
+#include "panel-profile.h"
+#include "panel-lockdown.h"
+#include "panel-stock-icons.h"
+#include "panel-typebuiltins.h"
+#include "panel-icon-names.h"
+
+G_DEFINE_TYPE (PanelMenuBar, panel_menu_bar, GTK_TYPE_MENU_BAR)
+
+#define PANEL_MENU_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_MENU_BAR, PanelMenuBarPrivate))
+
+struct _PanelMenuBarPrivate {
+ AppletInfo* info;
+ PanelWidget* panel;
+
+ GtkWidget* applications_menu;
+ GtkWidget* applications_item;
+ GtkWidget* places_item;
+ GtkWidget* desktop_item;
+
+ PanelOrientation orientation;
+};
+
+enum {
+ PROP_0,
+ PROP_ORIENTATION,
+};
+
+static void panel_menu_bar_update_text_gravity(PanelMenuBar* menubar);
+
+static gboolean panel_menu_bar_reinit_tooltip(GtkWidget* widget, PanelMenuBar* menubar)
+{
+ g_object_set(menubar->priv->applications_item, "has-tooltip", TRUE, NULL);
+ g_object_set(menubar->priv->places_item, "has-tooltip", TRUE, NULL);
+ g_object_set(menubar->priv->desktop_item, "has-tooltip", TRUE, NULL);
+
+ return FALSE;
+}
+
+static gboolean panel_menu_bar_hide_tooltip_and_focus(GtkWidget* widget, PanelMenuBar* menubar)
+{
+ /* remove focus that would be drawn on the currently focused child of
+ * the toplevel. See bug#308632. */
+ gtk_window_set_focus(GTK_WINDOW(menubar->priv->panel->toplevel), NULL);
+
+ g_object_set(widget, "has-tooltip", FALSE, NULL);
+
+ return FALSE;
+}
+
+static void panel_menu_bar_setup_tooltip(PanelMenuBar* menubar)
+{
+ panel_util_set_tooltip_text(menubar->priv->applications_item, _("Browse and run installed applications"));
+ panel_util_set_tooltip_text(menubar->priv->places_item, _("Access documents, folders and network places"));
+ panel_util_set_tooltip_text(menubar->priv->desktop_item, _("Change desktop appearance and behavior, get help, or log out"));
+
+ //FIXME: this doesn't handle the right-click case. Sigh.
+ /* Hide tooltip if a menu is activated */
+ g_signal_connect(menubar->priv->applications_item, "activate", G_CALLBACK (panel_menu_bar_hide_tooltip_and_focus), menubar);
+ g_signal_connect(menubar->priv->places_item, "activate", G_CALLBACK (panel_menu_bar_hide_tooltip_and_focus), menubar);
+ g_signal_connect(menubar->priv->desktop_item, "activate", G_CALLBACK (panel_menu_bar_hide_tooltip_and_focus), menubar);
+
+ /* Reset tooltip when the menu bar is not used */
+ g_signal_connect(GTK_MENU_SHELL (menubar), "deactivate", G_CALLBACK (panel_menu_bar_reinit_tooltip), menubar);
+}
+
+static void panel_menu_bar_init(PanelMenuBar* menubar)
+{
+ GtkWidget* image;
+
+ menubar->priv = PANEL_MENU_BAR_GET_PRIVATE(menubar);
+
+ menubar->priv->info = NULL;
+
+
+ menubar->priv->applications_menu = create_applications_menu("mate-applications.menu", NULL, TRUE);
+
+ menubar->priv->applications_item = panel_image_menu_item_new();
+ gtk_menu_item_set_label(GTK_MENU_ITEM(menubar->priv->applications_item), _("Applications"));
+ image = gtk_image_new_from_icon_name(PANEL_ICON_MAIN_MENU, panel_menu_bar_icon_get_size());
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menubar->priv->applications_item), image);
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar->priv->applications_item), menubar->priv->applications_menu);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menubar->priv->applications_item);
+
+ menubar->priv->places_item = panel_place_menu_item_new(FALSE);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menubar->priv->places_item);
+
+ menubar->priv->desktop_item = panel_desktop_menu_item_new(FALSE, TRUE);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menubar->priv->desktop_item);
+
+ panel_menu_bar_setup_tooltip(menubar);
+
+ panel_menu_bar_update_text_gravity(menubar);
+ g_signal_connect(menubar, "screen-changed", G_CALLBACK(panel_menu_bar_update_text_gravity), NULL);
+}
+
+static void panel_menu_bar_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
+{
+ PanelMenuBar* menubar;
+
+ g_return_if_fail(PANEL_IS_MENU_BAR(object));
+
+ menubar = PANEL_MENU_BAR (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum(value, menubar->priv->orientation);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void panel_menu_bar_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
+{
+ PanelMenuBar* menubar;
+
+ g_return_if_fail (PANEL_IS_MENU_BAR (object));
+
+ menubar = PANEL_MENU_BAR(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ panel_menu_bar_set_orientation(menubar, g_value_get_enum(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void panel_menu_bar_parent_set(GtkWidget* widget, GtkWidget* previous_parent)
+{
+ PanelMenuBar* menubar = PANEL_MENU_BAR(widget);
+ GtkWidget* parent;
+
+ parent = gtk_widget_get_parent(widget);
+
+ g_assert(!parent || PANEL_IS_WIDGET(parent));
+
+ menubar->priv->panel = (PanelWidget*) parent;
+
+ if (menubar->priv->applications_menu)
+ {
+ mate_panel_applet_menu_set_recurse(GTK_MENU(menubar->priv->applications_menu), "menu_panel", menubar->priv->panel);
+ }
+
+ if (menubar->priv->places_item)
+ {
+ panel_place_menu_item_set_panel(menubar->priv->places_item, menubar->priv->panel);
+ }
+
+ if (menubar->priv->desktop_item)
+ {
+ panel_desktop_menu_item_set_panel(menubar->priv->desktop_item, menubar->priv->panel);
+ }
+}
+
+static void panel_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
+{
+ GtkAllocation old_allocation;
+ GtkAllocation widget_allocation;
+ PanelBackground* background;
+
+ gtk_widget_get_allocation(widget, &widget_allocation);
+
+ old_allocation.x = widget_allocation.x;
+ old_allocation.y = widget_allocation.y;
+ old_allocation.width = widget_allocation.width;
+ old_allocation.height = widget_allocation.height;
+
+ GTK_WIDGET_CLASS(panel_menu_bar_parent_class)->size_allocate (widget, allocation);
+
+ if (old_allocation.x == allocation->x && old_allocation.y == allocation->y && old_allocation.width == allocation->width && old_allocation.height == allocation->height)
+ {
+ return;
+ }
+
+ background = &PANEL_MENU_BAR(widget)->priv->panel->background;
+
+ if (background->type == PANEL_BACK_NONE || (background->type == PANEL_BACK_COLOR && !background->has_alpha))
+ {
+ return;
+ }
+
+ panel_menu_bar_change_background(PANEL_MENU_BAR(widget));
+}
+
+static void panel_menu_bar_class_init(PanelMenuBarClass* klass)
+{
+ GObjectClass* gobject_class = (GObjectClass*) klass;
+ GtkWidgetClass* widget_class = (GtkWidgetClass*) klass;
+
+ gobject_class->get_property = panel_menu_bar_get_property;
+ gobject_class->set_property = panel_menu_bar_set_property;
+
+ widget_class->parent_set = panel_menu_bar_parent_set;
+ widget_class->size_allocate = panel_menu_bar_size_allocate;
+
+ g_type_class_add_private(klass, sizeof(PanelMenuBarPrivate));
+
+ g_object_class_install_property(gobject_class, PROP_ORIENTATION, g_param_spec_enum("orientation", "Orientation", "The PanelMenuBar orientation", PANEL_TYPE_ORIENTATION, PANEL_ORIENTATION_TOP, G_PARAM_READWRITE));
+
+ gtk_rc_parse_string (
+ "style \"panel-menubar-style\"\n"
+ "{\n"
+ " GtkMenuBar::shadow-type = none\n"
+ " GtkMenuBar::internal-padding = 0\n"
+ "}\n"
+ "class \"PanelMenuBar\" style \"panel-menubar-style\"");
+}
+
+static gboolean panel_menu_bar_on_expose(GtkWidget* widget, GdkEventExpose* event, gpointer data)
+{
+ PanelMenuBar* menubar = data;
+
+ if (gtk_widget_has_focus(GTK_WIDGET(menubar)))
+ {
+ gtk_paint_focus(gtk_widget_get_style(widget), gtk_widget_get_window(widget), gtk_widget_get_state(GTK_WIDGET(menubar)), NULL, widget, "menubar-applet", 0, 0, -1, -1);
+ }
+
+ return FALSE;
+}
+
+static void panel_menu_bar_load(PanelWidget* panel, gboolean locked, int position, gboolean exactpos, const char* id)
+{
+ PanelMenuBar* menubar;
+
+ g_return_if_fail (panel != NULL);
+
+ menubar = g_object_new(PANEL_TYPE_MENU_BAR, NULL);
+
+ menubar->priv->info = mate_panel_applet_register(GTK_WIDGET(menubar), NULL, NULL, panel, locked, position, exactpos, PANEL_OBJECT_MENU_BAR, id);
+
+ if (!menubar->priv->info)
+ {
+ gtk_widget_destroy(GTK_WIDGET(menubar));
+ return;
+ }
+
+ mate_panel_applet_add_callback(menubar->priv->info, "help", GTK_STOCK_HELP, _("_Help"), NULL);
+
+ /* Menu editors */
+ if (panel_is_program_in_path("alacarte") || panel_is_program_in_path("matemenu-simple-editor"))
+ {
+ mate_panel_applet_add_callback (menubar->priv->info, "edit", NULL, _("_Edit Menus"), NULL);
+ }
+
+ g_signal_connect_after(menubar, "focus-in-event", G_CALLBACK(gtk_widget_queue_draw), menubar);
+ g_signal_connect_after(menubar, "focus-out-event", G_CALLBACK(gtk_widget_queue_draw), menubar);
+ g_signal_connect_after(menubar, "expose-event", G_CALLBACK(panel_menu_bar_on_expose), menubar);
+
+ gtk_widget_set_can_focus(GTK_WIDGET(menubar), TRUE);
+
+ panel_widget_set_applet_expandable(panel, GTK_WIDGET(menubar), FALSE, TRUE);
+}
+
+void panel_menu_bar_load_from_mateconf(PanelWidget* panel, gboolean locked, int position, gboolean exactpos, const char* id)
+{
+ panel_menu_bar_load(panel, locked, position, exactpos, id);
+}
+
+void panel_menu_bar_create(PanelToplevel* toplevel, int position)
+{
+ char* id;
+
+ id = panel_profile_prepare_object(PANEL_OBJECT_MENU_BAR, toplevel, position, FALSE);
+ panel_profile_add_to_list(PANEL_MATECONF_OBJECTS, id);
+ g_free(id);
+}
+
+void panel_menu_bar_invoke_menu(PanelMenuBar* menubar, const char* callback_name)
+{
+ GdkScreen* screen;
+
+ g_return_if_fail(PANEL_IS_MENU_BAR(menubar));
+ g_return_if_fail(callback_name != NULL);
+
+ screen = gtk_widget_get_screen(GTK_WIDGET(menubar));
+
+ if (!strcmp(callback_name, "help"))
+ {
+ panel_show_help(screen, "user-guide", "menubar", NULL);
+
+ }
+ else if (!strcmp(callback_name, "edit"))
+ {
+ GError* error = NULL;
+
+ panel_launch_desktop_file_with_fallback("alacarte.desktop", "alacarte", screen, &error);
+
+ if (error)
+ {
+ g_error_free(error);
+ panel_launch_desktop_file_with_fallback("matemenu-simple-editor.desktop", "matemenu-simple-editor", screen, NULL);
+ }
+ }
+}
+
+void panel_menu_bar_popup_menu(PanelMenuBar* menubar, guint32 activate_time)
+{
+ GtkMenu* menu;
+ GtkMenuShell* menu_shell;
+
+ g_return_if_fail(PANEL_IS_MENU_BAR(menubar));
+
+ menu = GTK_MENU(menubar->priv->applications_menu);
+
+ /*
+ * We need to call _gtk_menu_shell_activate() here as is done in
+ * window_key_press_handler in gtkmenubar.c which pops up menu
+ * when F10 is pressed.
+ *
+ * As that function is private its code is replicated here.
+ */
+ menu_shell = GTK_MENU_SHELL(menubar);
+
+ if (!menu_shell->active)
+ {
+ gtk_grab_add(GTK_WIDGET(menu_shell));
+
+ menu_shell->have_grab = TRUE;
+ menu_shell->active = TRUE;
+ }
+
+ gtk_menu_shell_select_item(menu_shell, gtk_menu_get_attach_widget(menu));
+}
+
+void panel_menu_bar_change_background(PanelMenuBar* menubar)
+{
+ panel_background_change_background_on_widget(&menubar->priv->panel->background, GTK_WIDGET(menubar));
+}
+
+static void set_item_text_gravity(GtkWidget* item)
+{
+ GtkWidget* label;
+ PangoLayout* layout;
+ PangoContext* context;
+
+ label = gtk_bin_get_child(GTK_BIN(item));
+ layout = gtk_label_get_layout(GTK_LABEL(label));
+ context = pango_layout_get_context(layout);
+ pango_context_set_base_gravity(context, PANGO_GRAVITY_AUTO);
+}
+
+static void panel_menu_bar_update_text_gravity(PanelMenuBar* menubar)
+{
+ set_item_text_gravity(menubar->priv->applications_item);
+ set_item_text_gravity(menubar->priv->places_item);
+ set_item_text_gravity(menubar->priv->desktop_item);
+}
+
+static void set_item_text_angle_and_alignment(GtkWidget* item, double text_angle, float xalign, float yalign)
+{
+ GtkWidget *label;
+
+ label = gtk_bin_get_child (GTK_BIN (item));
+
+ gtk_label_set_angle (GTK_LABEL (label), text_angle);
+
+ gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign);
+}
+
+static void panel_menu_bar_update_orientation(PanelMenuBar* menubar)
+{
+ GtkPackDirection pack_direction;
+ double text_angle;
+ float text_xalign;
+ float text_yalign;
+
+ pack_direction = GTK_PACK_DIRECTION_LTR;
+ text_angle = 0.0;
+ text_xalign = 0.0;
+ text_yalign = 0.5;
+
+ switch (menubar->priv->orientation)
+ {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ pack_direction = GTK_PACK_DIRECTION_BTT;
+ text_angle = 90.0;
+ text_xalign = 0.5;
+ text_yalign = 0.0;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ pack_direction = GTK_PACK_DIRECTION_TTB;
+ text_angle = 270.0;
+ text_xalign = 0.5;
+ text_yalign = 0.0;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ gtk_menu_bar_set_pack_direction(GTK_MENU_BAR(menubar), pack_direction);
+ gtk_menu_bar_set_child_pack_direction(GTK_MENU_BAR(menubar), pack_direction);
+
+ set_item_text_angle_and_alignment(menubar->priv->applications_item, text_angle, text_xalign, text_yalign);
+ set_item_text_angle_and_alignment(menubar->priv->places_item, text_angle, text_xalign, text_yalign);
+ set_item_text_angle_and_alignment(menubar->priv->desktop_item, text_angle, text_xalign, text_yalign);
+}
+
+void panel_menu_bar_set_orientation(PanelMenuBar* menubar, PanelOrientation orientation)
+{
+ g_return_if_fail(PANEL_IS_MENU_BAR(menubar));
+
+ if (menubar->priv->orientation == orientation)
+ {
+ return;
+ }
+
+ menubar->priv->orientation = orientation;
+
+ panel_menu_bar_update_orientation(menubar);
+
+ g_object_notify(G_OBJECT(menubar), "orientation");
+}
+
+PanelOrientation panel_menu_bar_get_orientation(PanelMenuBar* menubar)
+{
+ g_return_val_if_fail(PANEL_IS_MENU_BAR(menubar), 0);
+
+ return menubar->priv->orientation;
+}
diff --git a/mate-panel/panel-menu-bar.h b/mate-panel/panel-menu-bar.h
new file mode 100644
index 00000000..43672da9
--- /dev/null
+++ b/mate-panel/panel-menu-bar.h
@@ -0,0 +1,83 @@
+/*
+ * panel-menu-bar.h: panel Applications/Places/Desktop menu bar
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_MENU_BAR_H__
+#define __PANEL_MENU_BAR_H__
+
+#include <gtk/gtk.h>
+#include "panel-widget.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_MENU_BAR (panel_menu_bar_get_type ())
+#define PANEL_MENU_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_MENU_BAR, PanelMenuBar))
+#define PANEL_MENU_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_MENU_BAR, PanelMenuBarClass))
+#define PANEL_IS_MENU_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_MENU_BAR))
+#define PANEL_IS_MENU_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_MENU_BAR))
+#define PANEL_MENU_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_MENU_BAR, PanelMenuBarClass))
+
+typedef struct _PanelMenuBar PanelMenuBar;
+typedef struct _PanelMenuBarClass PanelMenuBarClass;
+typedef struct _PanelMenuBarPrivate PanelMenuBarPrivate;
+
+struct _PanelMenuBar{
+ GtkMenuBar menubar;
+
+ PanelMenuBarPrivate *priv;
+};
+
+struct _PanelMenuBarClass {
+ GtkMenuBarClass menubar_class;
+};
+
+GType panel_menu_bar_get_type (void) G_GNUC_CONST;
+
+void panel_menu_bar_create (PanelToplevel *toplevel,
+ int position);
+
+void panel_menu_bar_load_from_mateconf (PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id);
+
+void panel_menu_bar_invoke_menu (PanelMenuBar *menubar,
+ const char *callback_name);
+
+void panel_menu_bar_popup_menu (PanelMenuBar *menubar,
+ guint32 activate_time);
+
+void panel_menu_bar_change_background (PanelMenuBar *menubar);
+
+void panel_menu_bar_set_orientation (PanelMenuBar *menubar,
+ PanelOrientation orientation);
+PanelOrientation panel_menu_bar_get_orientation (PanelMenuBar *menubar);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_MENU_BAR_H__ */
diff --git a/mate-panel/panel-menu-button.c b/mate-panel/panel-menu-button.c
new file mode 100644
index 00000000..f173d0b5
--- /dev/null
+++ b/mate-panel/panel-menu-button.c
@@ -0,0 +1,1194 @@
+/*
+ * panel-menu-button.c: panel menu button
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-menu-button.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <matemenu-tree.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-launch.h>
+#include <libpanel-util/panel-show.h>
+
+#include "applet.h"
+#include "panel-widget.h"
+#include "panel-util.h"
+#include "panel-profile.h"
+#include "panel-globals.h"
+#include "menu.h"
+#include "panel-lockdown.h"
+#include "panel-a11y.h"
+#include "panel-icon-names.h"
+
+G_DEFINE_TYPE (PanelMenuButton, panel_menu_button, BUTTON_TYPE_WIDGET)
+
+#define PANEL_MENU_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_MENU_BUTTON, PanelMenuButtonPrivate))
+
+enum {
+ PROP_0,
+ PROP_MENU_PATH,
+ PROP_CUSTOM_ICON,
+ PROP_TOOLTIP,
+ PROP_USE_MENU_PATH,
+ PROP_USE_CUSTOM_ICON,
+ PROP_DND_ENABLED
+};
+
+typedef enum {
+ FIRST_MENU,
+ APPLICATIONS_MENU,
+#define DEFAULT_MENU APPLICATIONS_MENU
+ SETTINGS_MENU,
+ LAST_MENU
+} MenuPathRoot;
+
+typedef struct {
+ MenuPathRoot root_id;
+ char* scheme;
+ char* filename;
+} MenuPathRootItem;
+
+static MenuPathRootItem root_items[] = {
+ {APPLICATIONS_MENU, "mate-applications", "mate-applications.menu"},
+ {SETTINGS_MENU, "mate-settings", "mate-settings.menu"}
+};
+
+struct _PanelMenuButtonPrivate {
+ PanelToplevel *toplevel;
+ guint mateconf_notify;
+ char *applet_id;
+
+ GtkWidget *menu;
+
+ char *menu_path;
+ char *custom_icon;
+ char *tooltip;
+
+ MenuPathRoot path_root;
+ guint use_menu_path : 1;
+ guint use_custom_icon : 1;
+ guint dnd_enabled : 1;
+};
+
+static void panel_menu_button_disconnect_from_mateconf (PanelMenuButton *button);
+static void panel_menu_button_recreate_menu (PanelMenuButton *button);
+static void panel_menu_button_set_icon (PanelMenuButton *button);
+
+static AtkObject *panel_menu_button_get_accessible (GtkWidget *widget);
+
+static const char *
+panel_menu_path_root_to_filename (MenuPathRoot path_root)
+{
+ const char *retval;
+ int i;
+
+ retval = NULL;
+
+ for (i = 0; i < G_N_ELEMENTS (root_items); i++) {
+ if (root_items [i].root_id == path_root) {
+ retval = root_items [i].filename;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static const char *
+panel_menu_filename_to_scheme (const char *filename)
+{
+ const char *retval;
+ int i;
+
+ retval = NULL;
+
+ if (!filename)
+ return retval;
+
+ for (i = 0; i < G_N_ELEMENTS (root_items); i++) {
+ if (root_items [i].filename &&
+ !strncmp (filename, root_items [i].filename,
+ strlen (root_items [i].filename))) {
+ retval = root_items [i].scheme;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static MenuPathRoot
+panel_menu_scheme_to_path_root (const char *scheme)
+{
+ MenuPathRoot retval;
+ int i;
+
+ retval = LAST_MENU;
+
+ if (!scheme)
+ return retval;
+
+ for (i = 0; i < G_N_ELEMENTS (root_items); i++) {
+ if (root_items [i].scheme &&
+ !strncmp (scheme, root_items [i].scheme,
+ strlen (root_items [i].scheme))) {
+ retval = root_items [i].root_id;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static void
+panel_menu_button_init (PanelMenuButton *button)
+{
+ button->priv = PANEL_MENU_BUTTON_GET_PRIVATE (button);
+
+ button->priv->applet_id = NULL;
+ button->priv->toplevel = NULL;
+ button->priv->mateconf_notify = 0;
+
+ button->priv->menu_path = NULL;
+ button->priv->custom_icon = NULL;
+ button->priv->tooltip = NULL;
+
+ button->priv->path_root = LAST_MENU;
+ button->priv->use_menu_path = FALSE;
+ button->priv->use_custom_icon = FALSE;
+}
+
+static void
+panel_menu_button_finalize (GObject *object)
+{
+ PanelMenuButton *button = PANEL_MENU_BUTTON (object);
+
+ panel_lockdown_notify_remove (G_CALLBACK (panel_menu_button_recreate_menu),
+ button);
+
+ panel_menu_button_disconnect_from_mateconf (button);
+
+ if (button->priv->menu) {
+ /* detaching the menu will kill our reference */
+ gtk_menu_detach (GTK_MENU (button->priv->menu));
+ button->priv->menu = NULL;
+ }
+
+ g_free (button->priv->applet_id);
+ button->priv->applet_id = NULL;
+
+ g_free (button->priv->menu_path);
+ button->priv->menu_path = NULL;
+
+ g_free (button->priv->custom_icon);
+ button->priv->custom_icon = NULL;
+
+ g_free (button->priv->tooltip);
+ button->priv->tooltip = NULL;
+
+ G_OBJECT_CLASS (panel_menu_button_parent_class)->finalize (object);
+}
+
+static void
+panel_menu_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelMenuButton *button;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (object));
+
+ button = PANEL_MENU_BUTTON (object);
+
+ switch (prop_id) {
+ case PROP_MENU_PATH:
+ g_value_set_string (value, button->priv->menu_path);
+ break;
+ case PROP_CUSTOM_ICON:
+ g_value_set_string (value, button->priv->custom_icon);
+ break;
+ case PROP_TOOLTIP:
+ g_value_set_string (value, button->priv->tooltip);
+ break;
+ case PROP_USE_MENU_PATH:
+ g_value_set_boolean (value, button->priv->use_menu_path);
+ break;
+ case PROP_USE_CUSTOM_ICON:
+ g_value_set_boolean (value, button->priv->use_custom_icon);
+ break;
+ case PROP_DND_ENABLED:
+ g_value_set_boolean (value, button->priv->dnd_enabled);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_menu_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelMenuButton *button;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (object));
+
+ button = PANEL_MENU_BUTTON (object);
+
+ switch (prop_id) {
+ case PROP_MENU_PATH:
+ panel_menu_button_set_menu_path (button, g_value_get_string (value));
+ break;
+ case PROP_CUSTOM_ICON:
+ panel_menu_button_set_custom_icon (button, g_value_get_string (value));
+ break;
+ case PROP_TOOLTIP:
+ panel_menu_button_set_tooltip (button, g_value_get_string (value));
+ break;
+ case PROP_USE_MENU_PATH:
+ panel_menu_button_set_use_menu_path (button, g_value_get_boolean (value));
+ break;
+ case PROP_USE_CUSTOM_ICON:
+ panel_menu_button_set_use_custom_icon (button, g_value_get_boolean (value));
+ break;
+ case PROP_DND_ENABLED:
+ panel_menu_button_set_dnd_enabled (button, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_menu_button_associate_panel (PanelMenuButton *button)
+{
+ PanelWidget *panel_widget = NULL;
+
+ if (!button->priv->menu)
+ return;
+
+ if (button->priv->toplevel)
+ panel_widget = panel_toplevel_get_panel_widget (button->priv->toplevel);
+
+ mate_panel_applet_menu_set_recurse (GTK_MENU (button->priv->menu), "menu_panel", panel_widget);
+}
+
+static void
+panel_menu_button_parent_set (GtkWidget *widget,
+ GtkWidget *previous_parent)
+{
+ PanelMenuButton *button = PANEL_MENU_BUTTON (widget);
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (widget);
+ g_return_if_fail (!parent || PANEL_IS_WIDGET (parent));
+
+ if (parent)
+ button->priv->toplevel = PANEL_WIDGET (parent)->toplevel;
+ else
+ button->priv->toplevel = NULL;
+
+ panel_menu_button_associate_panel (button);
+ panel_menu_button_set_icon (button);
+
+ if (GTK_WIDGET_CLASS (panel_menu_button_parent_class)->parent_set)
+ GTK_WIDGET_CLASS (panel_menu_button_parent_class)->parent_set (widget, previous_parent);
+}
+
+static void
+panel_menu_button_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ char *drag_data;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (widget));
+
+ drag_data = g_strdup_printf ("MENU:%d", panel_find_applet_index (widget));
+
+ gtk_selection_data_set (
+ selection_data, gtk_selection_data_get_target (selection_data),
+ 8, (guchar *) drag_data, strlen (drag_data));
+
+ g_free (drag_data);
+}
+
+static void
+panel_menu_button_menu_deactivated (PanelMenuButton *button)
+{
+ panel_toplevel_pop_autohide_disabler (button->priv->toplevel);
+
+ GTK_BUTTON (button)->in_button = FALSE;
+ button_widget_set_ignore_leave (BUTTON_WIDGET (button), FALSE);
+}
+
+static void
+panel_menu_button_menu_detacher (PanelMenuButton *button)
+{
+ /*
+ * just in case someone still owns a reference to the
+ * menu (the menu may be up or some such other nonsense)
+ */
+ g_signal_handlers_disconnect_by_func (button->priv->menu,
+ G_CALLBACK (panel_menu_button_menu_deactivated),
+ button);
+
+ button->priv->menu = NULL;
+}
+
+static GtkWidget *
+panel_menu_button_create_menu (PanelMenuButton *button)
+{
+ PanelWidget *panel_widget;
+
+ if (button->priv->menu)
+ return button->priv->menu;
+
+ if (!button->priv->toplevel)
+ return NULL;
+
+ panel_widget = panel_toplevel_get_panel_widget (button->priv->toplevel);
+
+ if (button->priv->use_menu_path &&
+ button->priv->path_root > FIRST_MENU &&
+ button->priv->path_root < LAST_MENU) {
+ const char *filename;
+
+ filename = panel_menu_path_root_to_filename (button->priv->path_root);
+ button->priv->menu = create_applications_menu (filename,
+ button->priv->menu_path,
+ TRUE);
+ } else
+ button->priv->menu = create_main_menu (panel_widget);
+
+ gtk_menu_attach_to_widget (GTK_MENU (button->priv->menu),
+ GTK_WIDGET (button),
+ (GtkMenuDetachFunc) panel_menu_button_menu_detacher);
+
+ panel_menu_button_associate_panel (button);
+
+ g_signal_connect_swapped (button->priv->menu, "deactivate",
+ G_CALLBACK (panel_menu_button_menu_deactivated),
+ button);
+
+ return button->priv->menu;
+}
+
+static void
+panel_menu_button_recreate_menu (PanelMenuButton *button)
+{
+ if (button->priv->menu)
+ gtk_widget_destroy (button->priv->menu);
+ button->priv->menu = NULL;
+}
+
+void
+panel_menu_button_popup_menu (PanelMenuButton *button,
+ guint n_button,
+ guint32 activate_time)
+{
+ GdkScreen *screen;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ panel_menu_button_create_menu (button);
+
+ panel_toplevel_push_autohide_disabler (button->priv->toplevel);
+
+ button_widget_set_ignore_leave (BUTTON_WIDGET (button), TRUE);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (button->priv->toplevel));
+ gtk_menu_set_screen (GTK_MENU (button->priv->menu), screen);
+
+ gtk_menu_popup (GTK_MENU (button->priv->menu),
+ NULL,
+ NULL,
+ (GtkMenuPositionFunc) mate_panel_applet_position_menu,
+ GTK_WIDGET (button),
+ n_button,
+ activate_time);
+}
+
+static void
+panel_menu_button_pressed (GtkButton *gtk_button)
+{
+ PanelMenuButton *button;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (gtk_button));
+
+ button = PANEL_MENU_BUTTON (gtk_button);
+
+ if (GTK_BUTTON_CLASS (panel_menu_button_parent_class)->pressed)
+ GTK_BUTTON_CLASS (panel_menu_button_parent_class)->pressed (gtk_button);
+
+ panel_menu_button_popup_menu (button, 0, gtk_get_current_event_time());
+}
+
+static void
+panel_menu_button_clicked (GtkButton *gtk_button)
+{
+ PanelMenuButton *button;
+ GdkEvent *event;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (gtk_button));
+
+ button = PANEL_MENU_BUTTON (gtk_button);
+
+ if (GTK_BUTTON_CLASS (panel_menu_button_parent_class)->clicked)
+ GTK_BUTTON_CLASS (panel_menu_button_parent_class)->clicked (gtk_button);
+
+ if ((event = gtk_get_current_event ())) {
+ panel_menu_button_popup_menu (button,
+ event->button.button,
+ event->button.time);
+ gdk_event_free (event);
+ } else {
+ panel_menu_button_popup_menu (button, 1, GDK_CURRENT_TIME);
+ }
+}
+
+static void
+panel_menu_button_class_init (PanelMenuButtonClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+ GtkButtonClass *button_class = (GtkButtonClass *) klass;
+
+ gobject_class->finalize = panel_menu_button_finalize;
+ gobject_class->get_property = panel_menu_button_get_property;
+ gobject_class->set_property = panel_menu_button_set_property;
+
+ widget_class->parent_set = panel_menu_button_parent_set;
+ widget_class->drag_data_get = panel_menu_button_drag_data_get;
+ widget_class->get_accessible = panel_menu_button_get_accessible;
+
+ button_class->clicked = panel_menu_button_clicked;
+ button_class->pressed = panel_menu_button_pressed;
+
+ g_type_class_add_private (klass, sizeof (PanelMenuButtonPrivate));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_MENU_PATH,
+ g_param_spec_string ("menu-path",
+ "Menu Path",
+ "The path from which to construct the menu",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_CUSTOM_ICON,
+ g_param_spec_string ("custom-icon",
+ "Custom Icon",
+ "The custom icon for the menu",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_TOOLTIP,
+ g_param_spec_string ("tooltip",
+ "Tooltip",
+ "Tooltip displayed for the menu",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_USE_MENU_PATH,
+ g_param_spec_boolean ("use-menu-path",
+ "Use Menu Path",
+ "Use the path specified by the menu-path property",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_USE_CUSTOM_ICON,
+ g_param_spec_boolean ("use-custom-icon",
+ "Use Custom Icon",
+ "Use the icon specified by the custom-icon property",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_DND_ENABLED,
+ g_param_spec_boolean ("dnd-enabled",
+ "Drag and drop enabled",
+ "Whether or not drag and drop is enabled on the widget",
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+static void
+panel_menu_button_mateconf_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelMenuButton *button)
+{
+ MateConfValue *value;
+ const char *key;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+
+ value = entry->value;
+
+ if (!strcmp (key, "menu_path")) {
+ if (value && value->type == MATECONF_VALUE_STRING)
+ panel_menu_button_set_menu_path (button,
+ mateconf_value_get_string (value));
+ } else if (!strcmp (key, "custom_icon")) {
+ if (value && value->type == MATECONF_VALUE_STRING)
+ panel_menu_button_set_custom_icon (button,
+ mateconf_value_get_string (value));
+ } else if (!strcmp (key, "tooltip")) {
+ if (value && value->type == MATECONF_VALUE_STRING)
+ panel_menu_button_set_tooltip (button,
+ mateconf_value_get_string (value));
+ } else if (!strcmp (key, "use_menu_path")) {
+ if (value && value->type == MATECONF_VALUE_BOOL)
+ panel_menu_button_set_use_menu_path (button,
+ mateconf_value_get_bool (value));
+ } else if (!strcmp (key, "use_custom_icon")) {
+ if (value && value->type == MATECONF_VALUE_BOOL)
+ panel_menu_button_set_use_custom_icon (button,
+ mateconf_value_get_bool (value));
+ }
+}
+
+static void
+panel_menu_button_connect_to_mateconf (PanelMenuButton *button)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/objects/%s",
+ button->priv->applet_id);
+ mateconf_client_add_dir (client, key, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ button->priv->mateconf_notify =
+ mateconf_client_notify_add (client, key,
+ (MateConfClientNotifyFunc) panel_menu_button_mateconf_notify,
+ button, NULL, NULL);
+}
+
+static void
+panel_menu_button_disconnect_from_mateconf (PanelMenuButton *button)
+{
+ MateConfClient *client;
+ const char *key;
+
+ if (!button->priv->mateconf_notify)
+ return;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/objects/%s",
+ button->priv->applet_id);
+
+ mateconf_client_notify_remove (client, button->priv->mateconf_notify);
+ button->priv->mateconf_notify = 0;
+
+ mateconf_client_remove_dir (client, key, NULL);
+}
+
+static void
+panel_menu_button_load (const char *menu_path,
+ gboolean use_menu_path,
+ const char *custom_icon,
+ gboolean use_custom_icon,
+ const char *tooltip,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id)
+{
+ PanelMenuButton *button;
+ AppletInfo *info;
+
+ g_return_if_fail (panel != NULL);
+
+ button = g_object_new (PANEL_TYPE_MENU_BUTTON,
+ "menu-path", menu_path,
+ "custom-icon", custom_icon,
+ "tooltip", tooltip,
+ "use-menu-path", use_menu_path,
+ "use-custom-icon", use_custom_icon,
+ "has-arrow", TRUE,
+ NULL);
+
+ info = mate_panel_applet_register (GTK_WIDGET (button), NULL, NULL,
+ panel, locked, position, exactpos,
+ PANEL_OBJECT_MENU, id);
+ if (!info) {
+ gtk_widget_destroy (GTK_WIDGET (button));
+ return;
+ }
+
+ button->priv->applet_id = g_strdup (info->id);
+
+ mate_panel_applet_add_callback (info, "help", GTK_STOCK_HELP, _("_Help"), NULL);
+
+ if (panel_is_program_in_path ("alacarte") ||
+ panel_is_program_in_path ("matemenu-simple-editor"))
+ mate_panel_applet_add_callback (info, "edit", NULL,
+ _("_Edit Menus"), NULL);
+
+ panel_widget_set_applet_expandable (panel, GTK_WIDGET (button), FALSE, TRUE);
+ panel_widget_set_applet_size_constrained (panel, GTK_WIDGET (button), TRUE);
+
+ panel_menu_button_connect_to_mateconf (button);
+
+ panel_lockdown_notify_add (G_CALLBACK (panel_menu_button_recreate_menu),
+ button);
+}
+
+static char *
+panel_menu_button_get_icon (PanelMenuButton *button)
+{
+ MateMenuTreeDirectory *directory;
+ char *retval;
+
+ retval = NULL;
+
+ if (button->priv->use_custom_icon &&
+ button->priv->custom_icon)
+ retval = g_strdup (button->priv->custom_icon);
+
+ if (!retval &&
+ button->priv->use_menu_path &&
+ button->priv->menu_path &&
+ panel_menu_button_create_menu (button)) {
+ directory = g_object_get_data (G_OBJECT (button->priv->menu),
+ "panel-menu-tree-directory");
+
+ if (!directory) {
+ MateMenuTree *tree;
+
+ if ((tree = g_object_get_data (G_OBJECT (button->priv->menu),
+ "panel-menu-tree"))) {
+ directory = matemenu_tree_get_directory_from_path (tree,
+ button->priv->menu_path);
+ g_object_set_data_full (G_OBJECT (button->priv->menu),
+ "panel-menu-tree-directory",
+ directory,
+ (GDestroyNotify) matemenu_tree_item_unref);
+ }
+ }
+
+ if (directory)
+ retval = g_strdup (matemenu_tree_directory_get_icon (directory));
+ }
+
+ if (!retval)
+ retval = g_strdup (PANEL_ICON_MAIN_MENU);
+
+ return retval;
+}
+
+static void
+panel_menu_button_set_icon (PanelMenuButton *button)
+{
+ char *icon_path;
+
+ icon_path = panel_menu_button_get_icon (button);
+ button_widget_set_icon_name (BUTTON_WIDGET (button), icon_path);
+
+ g_free (icon_path);
+}
+
+static const char *
+split_menu_uri (const char *menu_uri,
+ char **menu_scheme)
+{
+ char *p;
+
+ if (!menu_uri)
+ return NULL;
+
+ p = strchr (menu_uri, ':');
+
+ if (!p || p == menu_uri)
+ return NULL;
+
+ if (menu_scheme)
+ *menu_scheme = g_strndup (menu_uri, p - menu_uri);
+
+ if (*(++p) != '/')
+ return NULL;
+
+ while (*p != '\0' && *(p + 1) == '/') p++;
+
+ return p;
+}
+
+void
+panel_menu_button_set_menu_path (PanelMenuButton *button,
+ const char *menu_uri)
+{
+ const char *menu_path;
+ char *scheme;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ scheme = NULL;
+ menu_path = split_menu_uri (menu_uri, &scheme);
+
+ if (!scheme)
+ return;
+
+ button->priv->path_root = panel_menu_scheme_to_path_root (scheme);
+ g_free (scheme);
+
+ if (!button->priv->menu_path && (!menu_path || !menu_path [0]))
+ return;
+
+ if (button->priv->menu_path && menu_path &&
+ !strcmp (button->priv->menu_path, menu_path))
+ return;
+
+ g_free (button->priv->menu_path);
+ button->priv->menu_path = NULL;
+
+ button->priv->menu_path = g_strdup (menu_path);
+
+ if (button->priv->menu)
+ gtk_menu_detach (GTK_MENU (button->priv->menu));
+ button->priv->menu = NULL;
+
+ panel_menu_button_set_icon (button);
+}
+
+void
+panel_menu_button_set_custom_icon (PanelMenuButton *button,
+ const char *custom_icon)
+{
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ g_free (button->priv->custom_icon);
+ button->priv->custom_icon = NULL;
+
+ if (custom_icon && custom_icon [0])
+ button->priv->custom_icon = g_strdup (custom_icon);
+
+ panel_menu_button_set_icon (button);
+}
+
+void
+panel_menu_button_set_tooltip (PanelMenuButton *button,
+ const char *tooltip)
+{
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ g_free (button->priv->tooltip);
+ button->priv->tooltip = NULL;
+
+ if (tooltip && tooltip [0]) {
+ button->priv->tooltip = g_strdup (tooltip);
+ panel_util_set_tooltip_text (GTK_WIDGET (button), tooltip);
+ }
+}
+
+void
+panel_menu_button_set_use_menu_path (PanelMenuButton *button,
+ gboolean use_menu_path)
+{
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ use_menu_path = use_menu_path != FALSE;
+
+ if (button->priv->use_menu_path == use_menu_path)
+ return;
+
+ button->priv->use_menu_path = use_menu_path;
+
+ if (button->priv->menu)
+ gtk_menu_detach (GTK_MENU (button->priv->menu));
+ button->priv->menu = NULL;
+
+ panel_menu_button_set_icon (button);
+}
+
+gboolean
+panel_menu_button_get_use_menu_path (PanelMenuButton *button)
+{
+ g_return_val_if_fail (PANEL_IS_MENU_BUTTON (button), FALSE);
+
+ return button->priv->use_menu_path;
+}
+
+void
+panel_menu_button_set_use_custom_icon (PanelMenuButton *button,
+ gboolean use_custom_icon)
+{
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ button->priv->use_custom_icon = use_custom_icon != FALSE;
+
+ panel_menu_button_set_icon (button);
+}
+
+void
+panel_menu_button_load_from_mateconf (PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id)
+{
+ MateConfClient *client;
+ const char *key;
+ char *menu_path;
+ char *custom_icon;
+ char *tooltip;
+ gboolean use_menu_path;
+ gboolean use_custom_icon;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "menu_path");
+ menu_path = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "custom_icon");
+ custom_icon = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "tooltip");
+ tooltip = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "use_menu_path");
+ use_menu_path = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "use_custom_icon");
+ use_custom_icon = mateconf_client_get_bool (client, key, NULL);
+
+ panel_menu_button_load (menu_path,
+ use_menu_path,
+ custom_icon,
+ use_custom_icon,
+ tooltip,
+ panel,
+ locked,
+ position,
+ exactpos,
+ id);
+
+ g_free (menu_path);
+ g_free (custom_icon);
+ g_free (tooltip);
+}
+
+gboolean
+panel_menu_button_create (PanelToplevel *toplevel,
+ int position,
+ const char *filename,
+ const char *menu_path,
+ gboolean use_menu_path,
+ const char *tooltip)
+{
+ MateConfClient *client;
+ const char *scheme;
+ const char *key;
+ char *id;
+
+ client = panel_mateconf_get_client ();
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_MENU, toplevel, position, FALSE);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "use_menu_path");
+ mateconf_client_set_bool (client, key, use_menu_path, NULL);
+
+ scheme = panel_menu_filename_to_scheme (filename);
+
+ if (filename && !scheme) {
+ g_warning ("Failed to find menu scheme for %s\n", filename);
+ g_free (id);
+ return FALSE;
+ }
+
+ if (use_menu_path && menu_path && menu_path [0] && scheme) {
+ char *menu_uri;
+
+ menu_uri = g_strconcat (scheme, ":", menu_path, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "menu_path");
+ mateconf_client_set_string (client, key, menu_uri, NULL);
+
+ g_free (menu_uri);
+ }
+
+ if (tooltip && tooltip [0]) {
+ key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "tooltip");
+ mateconf_client_set_string (client, key, tooltip, NULL);
+ }
+
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+ g_free (id);
+
+ return TRUE;
+}
+
+void
+panel_menu_button_invoke_menu (PanelMenuButton *button,
+ const char *callback_name)
+{
+ GdkScreen *screen;
+
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+ g_return_if_fail (callback_name != NULL);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (button));
+
+ if (!strcmp (callback_name, "help")) {
+ panel_show_help (screen, "user-guide", "gospanel-37", NULL);
+
+ } else if (!strcmp (callback_name, "edit")) {
+ GError *error = NULL;
+
+ panel_launch_desktop_file_with_fallback ("alacarte.desktop",
+ "alacarte",
+ screen, &error);
+ if (error) {
+ g_error_free (error);
+ panel_launch_desktop_file_with_fallback (
+ "matemenu-simple-editor.desktop",
+ "matemenu-simple-editor",
+ screen, NULL);
+ }
+ }
+}
+
+void
+panel_menu_button_set_dnd_enabled (PanelMenuButton *button,
+ gboolean dnd_enabled)
+{
+ g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
+
+ dnd_enabled = dnd_enabled != FALSE;
+
+ if (button->priv->dnd_enabled == dnd_enabled)
+ return;
+
+ if (dnd_enabled) {
+ static GtkTargetEntry dnd_targets [] = {
+ { "application/x-mate-panel-applet-internal", 0, 0 }
+ };
+ char *icon;
+
+ gtk_widget_set_has_window (GTK_WIDGET (button), TRUE);
+ gtk_drag_source_set (GTK_WIDGET (button), GDK_BUTTON1_MASK,
+ dnd_targets, 1,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+ icon = panel_menu_button_get_icon (button);
+ if (icon != NULL) {
+ gtk_drag_source_set_icon_name (GTK_WIDGET (button),
+ icon);
+ g_free (icon);
+ }
+
+ gtk_widget_set_has_window (GTK_WIDGET (button), FALSE);
+ } else
+ gtk_drag_source_unset (GTK_WIDGET (button));
+}
+
+/*
+ * An AtkObject implementation for PanelMenuButton.
+ * We need all this just so we can create the menu in ref_child()
+ *
+ * See http://bugzilla.gnome.org/show_bug.cgi?id=138535 for details
+ *
+ * If we ever remove the on-demand creation of the menu, we should
+ * can just remove all this again
+ */
+
+#define PANEL_IS_MENU_BUTTON_ACCESSIBLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), panel_menu_button_accessible_get_type ()))
+
+static GType panel_menu_button_accessible_get_type (void);
+static gpointer parent_accessible_class = NULL;
+
+static int
+panel_menu_button_accessible_get_n_children (AtkObject *obj)
+{
+ g_return_val_if_fail (PANEL_IS_MENU_BUTTON_ACCESSIBLE (obj), 0);
+
+#if GTK_CHECK_VERSION (2, 21, 0)
+ return gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)) ? 1 : 0;
+#else
+ return GTK_ACCESSIBLE (obj)->widget ? 1 : 0;
+#endif
+}
+
+static AtkObject *
+panel_menu_button_accessible_ref_child (AtkObject *obj,
+ int index)
+{
+ PanelMenuButton *button;
+ GtkWidget *menu;
+
+ g_return_val_if_fail (PANEL_IS_MENU_BUTTON_ACCESSIBLE (obj), NULL);
+
+ if (index != 0)
+ return NULL;
+
+#if GTK_CHECK_VERSION (2, 21, 0)
+ if (!(button = PANEL_MENU_BUTTON (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)))))
+#else
+ if (!(button = PANEL_MENU_BUTTON (GTK_ACCESSIBLE (obj)->widget)))
+#endif
+ return NULL;
+
+ if (!(menu = panel_menu_button_create_menu (button)))
+ return NULL;
+ /*
+ * This ensures that the menu is populated with all menu items
+ */
+ g_signal_emit_by_name (menu, "show", NULL);
+
+ return g_object_ref (gtk_widget_get_accessible (menu));
+}
+
+static const gchar* panel_menu_button_accessible_get_name(AtkObject* obj)
+{
+ const char* name;
+
+ name = ATK_OBJECT_CLASS(parent_accessible_class)->get_name(obj);
+
+ if (name == NULL)
+ {
+ name = _("Main Menu");
+ }
+
+ return name;
+}
+
+static void
+panel_menu_button_accessible_class_init (AtkObjectClass *klass)
+{
+ klass->get_n_children = panel_menu_button_accessible_get_n_children;
+ klass->ref_child = panel_menu_button_accessible_ref_child;
+ klass->get_name = panel_menu_button_accessible_get_name;
+
+ parent_accessible_class = g_type_class_peek_parent (klass);
+}
+
+static GType
+panel_menu_button_accessible_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo type_info = { 0 };
+ GType accessible_parent_type;
+
+ type_info.class_init =
+ (GClassInitFunc) panel_menu_button_accessible_class_init;
+
+ accessible_parent_type =
+ panel_a11y_query_accessible_parent_type (PANEL_TYPE_MENU_BUTTON,
+ &type_info);
+
+ type = g_type_register_static (accessible_parent_type,
+ "PanelMenuButtonAccessible",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+static AtkObject *
+panel_menu_button_accessible_new (GObject *obj)
+{
+ AtkObject *accessible;
+
+ g_return_val_if_fail (PANEL_IS_MENU_BUTTON (obj), NULL);
+
+ accessible = g_object_new (panel_menu_button_accessible_get_type (), NULL);
+ atk_object_initialize (accessible, obj);
+
+ return accessible;
+}
+
+static void
+panel_menu_button_accessible_factory_class_init (AtkObjectFactoryClass *klass)
+{
+ klass->create_accessible = panel_menu_button_accessible_new;
+ klass->get_accessible_type = panel_menu_button_accessible_get_type;
+}
+
+static GType
+panel_menu_button_accessible_factory_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (AtkObjectFactoryClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) panel_menu_button_accessible_factory_class_init,
+ NULL,
+ NULL,
+ sizeof (AtkObjectFactory),
+ 0,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY,
+ "PanelMenuButtonAccessibleFactory",
+ &info, 0);
+ }
+
+ return type;
+}
+
+static AtkObject *
+panel_menu_button_get_accessible (GtkWidget *widget)
+{
+ static gboolean first_time = TRUE;
+
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ if (first_time && panel_a11y_get_is_a11y_enabled (widget))
+ atk_registry_set_factory_type (atk_get_default_registry (),
+ PANEL_TYPE_MENU_BUTTON,
+ panel_menu_button_accessible_factory_get_type ());
+
+ first_time = FALSE;
+
+ return GTK_WIDGET_CLASS (panel_menu_button_parent_class)->get_accessible (widget);
+}
diff --git a/mate-panel/panel-menu-button.h b/mate-panel/panel-menu-button.h
new file mode 100644
index 00000000..c6c9d564
--- /dev/null
+++ b/mate-panel/panel-menu-button.h
@@ -0,0 +1,98 @@
+/*
+ * panel-menu-button.h: panel menu button
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_MENU_BUTTON_H__
+#define __PANEL_MENU_BUTTON_H__
+
+#include <gtk/gtk.h>
+#include "button-widget.h"
+#include "panel-widget.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_MENU_BUTTON (panel_menu_button_get_type ())
+#define PANEL_MENU_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_MENU_BUTTON, PanelMenuButton))
+#define PANEL_MENU_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_MENU_BUTTON, PanelMenuButtonClass))
+#define PANEL_IS_MENU_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_MENU_BUTTON))
+#define PANEL_IS_MENU_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_MENU_BUTTON))
+#define PANEL_MENU_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_MENU_BUTTON, PanelMenuButtonClass))
+
+typedef struct _PanelMenuButton PanelMenuButton;
+typedef struct _PanelMenuButtonClass PanelMenuButtonClass;
+typedef struct _PanelMenuButtonPrivate PanelMenuButtonPrivate;
+
+struct _PanelMenuButton {
+ ButtonWidget button;
+
+ PanelMenuButtonPrivate *priv;
+};
+
+struct _PanelMenuButtonClass {
+ ButtonWidgetClass button_class;
+};
+
+GType panel_menu_button_get_type (void) G_GNUC_CONST;
+
+gboolean panel_menu_button_create (PanelToplevel *toplevel,
+ int position,
+ const char *filename,
+ const char *menu_path,
+ gboolean use_menu_path,
+ const char *tooltip);
+
+void panel_menu_button_set_menu_path (PanelMenuButton *button,
+ const char *menu_path);
+void panel_menu_button_set_custom_icon (PanelMenuButton *button,
+ const char *custom_icon);
+void panel_menu_button_set_tooltip (PanelMenuButton *button,
+ const char *tooltip);
+void panel_menu_button_set_use_menu_path (PanelMenuButton *button,
+ gboolean use_menu_path);
+gboolean panel_menu_button_get_use_menu_path (PanelMenuButton *button);
+void panel_menu_button_set_use_custom_icon (PanelMenuButton *button,
+ gboolean use_custom_icon);
+
+void panel_menu_button_load_from_mateconf (PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id);
+
+void panel_menu_button_invoke_menu (PanelMenuButton *button,
+ const char *callback_name);
+
+void panel_menu_button_popup_menu (PanelMenuButton *button,
+ guint n_button,
+ guint32 activate_time);
+
+void panel_menu_button_set_dnd_enabled (PanelMenuButton *button,
+ gboolean dnd_enabled);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_MENU_BUTTON_H__ */
diff --git a/mate-panel/panel-menu-items.c b/mate-panel/panel-menu-items.c
new file mode 100644
index 00000000..7f790676
--- /dev/null
+++ b/mate-panel/panel-menu-items.c
@@ -0,0 +1,1618 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ *
+ * Based on code from panel-menu-bar.c
+ */
+
+/*
+ * TODO:
+ * + drag and drop loses icon for URIs
+ * + drag and drop of bookmarks/network places/removable media should create
+ * a menu button
+ * + if a menu is open and gets updated, it should reappear and not just
+ * disappear
+ */
+
+#include <config.h>
+
+#include "panel-menu-items.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-launch.h>
+#include <libpanel-util/panel-show.h>
+
+#include "menu.h"
+#include "panel-action-button.h"
+#include "panel-globals.h"
+#include "panel-icon-names.h"
+#include "panel-lockdown.h"
+#include "panel-recent.h"
+#include "panel-stock-icons.h"
+#include "panel-util.h"
+
+#define BOOKMARKS_FILENAME ".gtk-bookmarks"
+#define DESKTOP_IS_HOME_DIR_DIR "/apps/caja/preferences"
+#define DESKTOP_IS_HOME_DIR_KEY "/apps/caja/preferences/desktop_is_home_dir"
+#define NAMES_DIR "/apps/caja/desktop"
+#define HOME_NAME_KEY "/apps/caja/desktop/home_icon_name"
+#define COMPUTER_NAME_KEY "/apps/caja/desktop/computer_icon_name"
+#define MAX_ITEMS_OR_SUBMENU 5
+#define MAX_BOOKMARK_ITEMS 100
+
+G_DEFINE_TYPE(PanelPlaceMenuItem, panel_place_menu_item, GTK_TYPE_IMAGE_MENU_ITEM)
+G_DEFINE_TYPE(PanelDesktopMenuItem, panel_desktop_menu_item, GTK_TYPE_IMAGE_MENU_ITEM)
+
+#define PANEL_PLACE_MENU_ITEM_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((o), PANEL_TYPE_PLACE_MENU_ITEM, PanelPlaceMenuItemPrivate))
+#define PANEL_DESKTOP_MENU_ITEM_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((o), PANEL_TYPE_DESKTOP_MENU_ITEM, PanelDesktopMenuItemPrivate))
+
+struct _PanelPlaceMenuItemPrivate {
+ GtkWidget *menu;
+ PanelWidget *panel;
+
+ GtkRecentManager *recent_manager;
+
+ GFileMonitor *bookmarks_monitor;
+
+ GVolumeMonitor *volume_monitor;
+ gulong drive_changed_id;
+ gulong drive_connected_id;
+ gulong drive_disconnected_id;
+ gulong volume_added_id;
+ gulong volume_changed_id;
+ gulong volume_removed_id;
+ gulong mount_added_id;
+ gulong mount_changed_id;
+ gulong mount_removed_id;
+
+ guint use_image : 1;
+};
+
+struct _PanelDesktopMenuItemPrivate {
+ GtkWidget *menu;
+ PanelWidget *panel;
+
+ guint use_image : 1;
+ guint append_lock_logout : 1;
+};
+
+static void activate_uri_on_screen(const char* uri, GdkScreen* screen)
+{
+ panel_show_uri(screen, uri, gtk_get_current_event_time(), NULL);
+}
+
+static void
+activate_uri (GtkWidget *menuitem,
+ const char *uri)
+{
+ activate_uri_on_screen (uri, menuitem_to_screen (menuitem));
+}
+
+static void
+activate_path (GtkWidget *menuitem,
+ const char *path)
+{
+ char *uri;
+
+ uri = g_filename_to_uri (path, NULL, NULL);
+ activate_uri_on_screen (uri, menuitem_to_screen (menuitem));
+ g_free (uri);
+}
+
+static void
+activate_home_uri (GtkWidget *menuitem,
+ gpointer data)
+{
+ activate_path (menuitem, g_get_home_dir ());
+}
+
+static void
+activate_desktop_uri (GtkWidget *menuitem,
+ gpointer data)
+{
+ activate_path (menuitem,
+ g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
+}
+
+static void
+panel_menu_items_append_from_desktop (GtkWidget *menu,
+ char *path,
+ char *force_name,
+ gboolean use_icon)
+{
+ GKeyFile *key_file;
+ gboolean loaded;
+ GtkWidget *item;
+ char *path_freeme;
+ char *full_path;
+ char *uri;
+ char *type;
+ gboolean is_application;
+ char *tryexec;
+ char *icon;
+ char *name;
+ char *comment;
+
+ path_freeme = NULL;
+
+ key_file = g_key_file_new ();
+
+ if (g_path_is_absolute (path)) {
+ loaded = g_key_file_load_from_file (key_file, path,
+ G_KEY_FILE_NONE, NULL);
+ full_path = path;
+ } else {
+ char *lookup_file;
+ char *desktop_path;
+
+ if (!g_str_has_suffix (path, ".desktop")) {
+ desktop_path = g_strconcat (path, ".desktop", NULL);
+ } else {
+ desktop_path = path;
+ }
+
+ lookup_file = g_strconcat ("applications", G_DIR_SEPARATOR_S,
+ desktop_path, NULL);
+ loaded = g_key_file_load_from_data_dirs (key_file, lookup_file,
+ &path_freeme,
+ G_KEY_FILE_NONE,
+ NULL);
+ full_path = path_freeme;
+ g_free (lookup_file);
+
+ if (desktop_path != path)
+ g_free (desktop_path);
+ }
+
+ if (!loaded) {
+ g_key_file_free (key_file);
+ if (path_freeme)
+ g_free (path_freeme);
+ return;
+ }
+
+ /* For Application desktop files, respect TryExec */
+ type = panel_key_file_get_string (key_file, "Type");
+ if (!type) {
+ g_key_file_free (key_file);
+ if (path_freeme)
+ g_free (path_freeme);
+ return;
+ }
+ is_application = (strcmp (type, "Application") == 0);
+ g_free (type);
+
+ if (is_application) {
+ tryexec = panel_key_file_get_string (key_file, "TryExec");
+ if (tryexec) {
+ char *prog;
+
+ prog = g_find_program_in_path (tryexec);
+ g_free (tryexec);
+
+ if (!prog) {
+ /* FIXME: we could add some file monitor magic,
+ * so that the menu items appears when the
+ * program appears, but that's really complex
+ * for not a huge benefit */
+ g_key_file_free (key_file);
+ if (path_freeme)
+ g_free (path_freeme);
+ return;
+ }
+
+ g_free (prog);
+ }
+ }
+
+ /* Now, simply build the menu item */
+ icon = panel_key_file_get_locale_string (key_file, "Icon");
+ comment = panel_key_file_get_locale_string (key_file, "Comment");
+
+ if (PANEL_GLIB_STR_EMPTY (force_name))
+ name = panel_key_file_get_locale_string (key_file, "Name");
+ else
+ name = g_strdup (force_name);
+
+ if (use_icon) {
+ item = panel_image_menu_item_new ();
+ } else {
+ item = gtk_image_menu_item_new ();
+ }
+
+ setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
+ icon, NULL, NULL, name);
+
+ panel_util_set_tooltip_text (item, comment);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect_data (item, "activate",
+ G_CALLBACK (panel_menu_item_activate_desktop_file),
+ g_strdup (full_path),
+ (GClosureNotify) g_free, 0);
+ g_signal_connect (G_OBJECT (item), "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+
+ uri = g_filename_to_uri (full_path, NULL, NULL);
+
+ setup_uri_drag (item, uri, icon);
+ g_free (uri);
+
+ g_key_file_free (key_file);
+
+ if (icon)
+ g_free (icon);
+
+ if (name)
+ g_free (name);
+
+ if (comment)
+ g_free (comment);
+
+ if (path_freeme)
+ g_free (path_freeme);
+}
+
+static void
+panel_menu_items_append_place_item (const char *icon_name,
+ GIcon *gicon,
+ const char *title,
+ const char *tooltip,
+ GtkWidget *menu,
+ GCallback callback,
+ const char *uri)
+{
+ GtkWidget *item;
+ char *user_data;
+
+ item = panel_image_menu_item_new ();
+ setup_menu_item_with_icon (item,
+ panel_menu_icon_get_size (),
+ icon_name, NULL, gicon,
+ title);
+
+ panel_util_set_tooltip_text (item, tooltip);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ user_data = g_strdup (uri);
+ g_signal_connect_data (item, "activate", callback, user_data,
+ (GClosureNotify) g_free, 0);
+
+ g_signal_connect (G_OBJECT (item), "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+
+ setup_uri_drag (item, uri, icon_name);
+}
+
+static GtkWidget *
+panel_menu_items_create_action_item_full (PanelActionButtonType action_type,
+ const char *label,
+ const char *tooltip)
+{
+ GtkWidget *item;
+
+ if (panel_action_get_is_disabled (action_type))
+ return NULL;
+
+ item = gtk_image_menu_item_new ();
+ setup_menu_item_with_icon (item,
+ panel_menu_icon_get_size (),
+ panel_action_get_icon_name (action_type),
+ NULL, NULL,
+ label ? label : panel_action_get_text (action_type));
+
+ panel_util_set_tooltip_text (item,
+ tooltip ?
+ tooltip :
+ panel_action_get_tooltip (action_type));
+
+ g_signal_connect (item, "activate",
+ panel_action_get_invoke (action_type), NULL);
+ g_signal_connect (G_OBJECT (item), "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+ setup_internal_applet_drag (item, action_type);
+
+ return item;
+}
+
+static GtkWidget *
+panel_menu_items_create_action_item (PanelActionButtonType action_type)
+{
+ return panel_menu_items_create_action_item_full (action_type,
+ NULL, NULL);
+}
+
+static void
+panel_place_menu_item_append_gtk_bookmarks (GtkWidget *menu)
+{
+ typedef struct {
+ char *full_uri;
+ char *label;
+ } PanelBookmark;
+
+ GtkWidget *add_menu;
+ char *filename;
+ GIOChannel *io_channel;
+ GHashTable *table;
+ int i;
+ GSList *lines = NULL;
+ GSList *add_bookmarks, *l;
+ PanelBookmark *bookmark;
+
+ filename = g_build_filename (g_get_home_dir (),
+ BOOKMARKS_FILENAME, NULL);
+
+ io_channel = g_io_channel_new_file (filename, "r", NULL);
+ g_free (filename);
+
+ if (!io_channel)
+ return;
+
+ /* We use a hard limit to avoid having users shooting their
+ * own feet, and to avoid crashing the system if a misbehaving
+ * application creates a big bookmars file.
+ */
+ for (i = 0; i < MAX_BOOKMARK_ITEMS; i++) {
+ char *contents;
+ gsize length;
+ gsize terminator_pos;
+ GIOStatus status;
+
+ status = g_io_channel_read_line (io_channel, &contents, &length, &terminator_pos, NULL);
+
+ if (status != G_IO_STATUS_NORMAL)
+ break;
+
+ if (length == 0)
+ break;
+
+ /* Clear the line terminator (\n), if any */
+ if (terminator_pos > 0)
+ contents[terminator_pos] = '\0';
+
+ lines = g_slist_prepend (lines, contents);
+ }
+
+ g_io_channel_shutdown (io_channel, FALSE, NULL);
+ g_io_channel_unref (io_channel);
+
+ if (!lines)
+ return;
+
+ lines = g_slist_reverse (lines);
+
+ table = g_hash_table_new (g_str_hash, g_str_equal);
+ add_bookmarks = NULL;
+
+ for (l = lines; l; l = l->next) {
+ char *line = (char*) l->data;
+
+ if (line[0] && !g_hash_table_lookup (table, line)) {
+ GFile *file;
+ char *space;
+ char *label;
+ gboolean keep;
+
+ g_hash_table_insert (table, line, line);
+
+ space = strchr (line, ' ');
+ if (space) {
+ *space = '\0';
+ label = g_strdup (space + 1);
+ } else {
+ label = NULL;
+ }
+
+ keep = FALSE;
+
+ if (g_str_has_prefix (line, "x-caja-search:"))
+ keep = TRUE;
+
+ if (!keep) {
+ file = g_file_new_for_uri (line);
+ keep = !g_file_is_native (file) ||
+ g_file_query_exists (file, NULL);
+ g_object_unref (file);
+ }
+
+ if (!keep) {
+ if (label)
+ g_free (label);
+ continue;
+ }
+
+ bookmark = g_malloc (sizeof (PanelBookmark));
+ bookmark->full_uri = g_strdup (line);
+ bookmark->label = label;
+ add_bookmarks = g_slist_prepend (add_bookmarks, bookmark);
+ }
+ }
+
+ g_hash_table_destroy (table);
+ g_slist_foreach (lines, (GFunc) g_free, NULL);
+ g_slist_free (lines);
+
+ add_bookmarks = g_slist_reverse (add_bookmarks);
+
+ if (g_slist_length (add_bookmarks) <= MAX_ITEMS_OR_SUBMENU) {
+ add_menu = menu;
+ } else {
+ GtkWidget *item;
+
+ item = gtk_image_menu_item_new ();
+ setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
+ PANEL_ICON_BOOKMARKS, NULL, NULL,
+ _("Bookmarks"));
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ add_menu = create_empty_menu ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), add_menu);
+ }
+
+ for (l = add_bookmarks; l; l = l->next) {
+ char *display_name;
+ char *tooltip;
+ char *label;
+ char *icon;
+ GFile *file;
+ GIcon *gicon;
+
+ bookmark = l->data;
+
+ file = g_file_new_for_uri (bookmark->full_uri);
+ display_name = g_file_get_parse_name (file);
+ g_object_unref (file);
+ /* Translators: %s is a URI */
+ tooltip = g_strdup_printf (_("Open '%s'"), display_name);
+ g_free (display_name);
+
+ label = NULL;
+ if (bookmark->label) {
+ label = g_strdup (g_strstrip (bookmark->label));
+ if (!label [0]) {
+ g_free (label);
+ label = NULL;
+ }
+ }
+
+ if (!label) {
+ label = panel_util_get_label_for_uri (bookmark->full_uri);
+
+ if (!label) {
+ g_free (tooltip);
+ g_free (bookmark->full_uri);
+ if (bookmark->label)
+ g_free (bookmark->label);
+ g_free (bookmark);
+ continue;
+ }
+ }
+
+ icon = panel_util_get_icon_for_uri (bookmark->full_uri);
+ /*FIXME: we should probably get a GIcon if possible, so that we
+ * have customized icons for cd-rom, eg */
+ if (!icon)
+ icon = g_strdup (PANEL_ICON_FOLDER);
+
+ gicon = g_themed_icon_new_with_default_fallbacks (icon);
+
+ //FIXME: drag and drop will be broken for x-caja-search uris
+ panel_menu_items_append_place_item (icon, gicon,
+ label,
+ tooltip,
+ add_menu,
+ G_CALLBACK (activate_uri),
+ bookmark->full_uri);
+
+ g_free (icon);
+ g_object_unref (gicon);
+ g_free (tooltip);
+ g_free (label);
+ g_free (bookmark->full_uri);
+ if (bookmark->label)
+ g_free (bookmark->label);
+ g_free (bookmark);
+ }
+
+ g_slist_free (add_bookmarks);
+}
+
+static void
+drive_poll_for_media_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GdkScreen *screen;
+ GError *error;
+ char *primary;
+ char *name;
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (G_DRIVE (source_object),
+ res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ screen = GDK_SCREEN (user_data);
+
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to scan %s for media changes"),
+ name);
+ g_free (name);
+ panel_error_dialog (NULL, screen,
+ "cannot_scan_drive", TRUE,
+ primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ //FIXME: should we mount the volume and activate the root of the new
+ //mount?
+}
+
+static void
+panel_menu_item_rescan_drive (GtkWidget *menuitem,
+ GDrive *drive)
+{
+ g_drive_poll_for_media (drive, NULL,
+ drive_poll_for_media_cb,
+ menuitem_to_screen (menuitem));
+}
+
+static void
+panel_menu_item_append_drive (GtkWidget *menu,
+ GDrive *drive)
+{
+ GtkWidget *item;
+ GIcon *icon;
+ char *title;
+ char *tooltip;
+
+ icon = g_drive_get_icon (drive);
+ title = g_drive_get_name (drive);
+
+ item = panel_image_menu_item_new ();
+ setup_menu_item_with_icon (item,
+ panel_menu_icon_get_size (),
+ NULL, NULL, icon,
+ title);
+ g_object_unref (icon);
+
+ tooltip = g_strdup_printf (_("Rescan %s"), title);
+ panel_util_set_tooltip_text (item, tooltip);
+ g_free (tooltip);
+
+ g_free (title);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ g_signal_connect_data (item, "activate",
+ G_CALLBACK (panel_menu_item_rescan_drive),
+ g_object_ref (drive),
+ (GClosureNotify) g_object_unref, 0);
+
+ g_signal_connect (G_OBJECT (item), "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+}
+
+typedef struct {
+ GdkScreen *screen;
+ GMountOperation *mount_op;
+} PanelVolumeMountData;
+
+static void
+volume_mount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PanelVolumeMountData *mount_data = user_data;
+ GError *error;
+
+ error = NULL;
+ if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) {
+ char *primary;
+ char *name;
+
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_volume_get_name (G_VOLUME (source_object));
+ primary = g_strdup_printf (_("Unable to mount %s"),
+ name);
+ g_free (name);
+
+ panel_error_dialog (NULL, mount_data->screen,
+ "cannot_mount_volume", TRUE,
+ primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ } else {
+ GMount *mount;
+ GFile *root;
+ char *rooturi;
+
+ mount = g_volume_get_mount (G_VOLUME (source_object));
+ root = g_mount_get_root (mount);
+ rooturi = g_file_get_uri (root);
+ activate_uri_on_screen (rooturi, mount_data->screen);
+ g_object_unref (mount);
+ g_object_unref (root);
+ g_free (rooturi);
+ }
+
+ g_object_unref (mount_data->mount_op);
+ g_slice_free (PanelVolumeMountData, mount_data);
+}
+
+static void
+panel_menu_item_mount_volume (GtkWidget *menuitem,
+ GVolume *volume)
+{
+ PanelVolumeMountData *mount_data;
+
+ mount_data = g_slice_new (PanelVolumeMountData);
+ mount_data->screen = menuitem_to_screen (menuitem);
+ mount_data->mount_op = gtk_mount_operation_new (NULL);
+ gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_data->mount_op),
+ mount_data->screen);
+
+ g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_data->mount_op, NULL,
+ volume_mount_cb, mount_data);
+}
+
+static void
+panel_menu_item_append_volume (GtkWidget *menu,
+ GVolume *volume)
+{
+ GtkWidget *item;
+ GIcon *icon;
+ char *title;
+ char *tooltip;
+
+ icon = g_volume_get_icon (volume);
+ title = g_volume_get_name (volume);
+
+ item = panel_image_menu_item_new ();
+ setup_menu_item_with_icon (item,
+ panel_menu_icon_get_size (),
+ NULL, NULL, icon,
+ title);
+ g_object_unref (icon);
+
+ tooltip = g_strdup_printf (_("Mount %s"), title);
+ panel_util_set_tooltip_text (item, tooltip);
+ g_free (tooltip);
+
+ g_free (title);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ g_signal_connect_data (item, "activate",
+ G_CALLBACK (panel_menu_item_mount_volume),
+ g_object_ref (volume),
+ (GClosureNotify) g_object_unref, 0);
+
+ g_signal_connect (G_OBJECT (item), "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+}
+
+static void
+panel_menu_item_append_mount (GtkWidget *menu,
+ GMount *mount)
+{
+ GFile *root;
+ GIcon *icon;
+ char *display_name;
+ char *activation_uri;
+
+ icon = g_mount_get_icon (mount);
+ display_name = g_mount_get_name (mount);
+
+ root = g_mount_get_root (mount);
+ activation_uri = g_file_get_uri (root);
+ g_object_unref (root);
+
+ panel_menu_items_append_place_item (NULL, icon,
+ display_name,
+ display_name, //FIXME tooltip
+ menu,
+ G_CALLBACK (activate_uri),
+ activation_uri);
+
+ g_object_unref (icon);
+ g_free (display_name);
+ g_free (activation_uri);
+}
+
+typedef enum {
+ PANEL_GIO_DRIVE,
+ PANEL_GIO_VOLUME,
+ PANEL_GIO_MOUNT
+} PanelGioItemType;
+
+typedef struct {
+ PanelGioItemType type;
+ union {
+ GDrive *drive;
+ GVolume *volume;
+ GMount *mount;
+ } u;
+} PanelGioItem;
+
+/* this is loosely based on update_places() from caja-places-sidebar.c */
+static void
+panel_place_menu_item_append_local_gio (PanelPlaceMenuItem *place_item,
+ GtkWidget *menu)
+{
+ GList *l;
+ GList *ll;
+ GList *drives;
+ GDrive *drive;
+ GList *volumes;
+ GVolume *volume;
+ GList *mounts;
+ GMount *mount;
+ GSList *items;
+ GSList *sl;
+ PanelGioItem *item;
+ GtkWidget *add_menu;
+
+ items = NULL;
+
+ /* first go through all connected drives */
+ drives = g_volume_monitor_get_connected_drives (place_item->priv->volume_monitor);
+ for (l = drives; l != NULL; l = l->next) {
+ drive = l->data;
+
+ volumes = g_drive_get_volumes (drive);
+ if (volumes != NULL) {
+ for (ll = volumes; ll != NULL; ll = ll->next) {
+ volume = ll->data;
+ mount = g_volume_get_mount (volume);
+ item = g_slice_new (PanelGioItem);
+ if (mount != NULL) {
+ item->type = PANEL_GIO_MOUNT;
+ item->u.mount = mount;
+ } else {
+ /* Do show the unmounted volumes; this
+ * is so the user can mount it (in case
+ * automounting is off).
+ *
+ * Also, even if automounting is
+ * enabled, this gives a visual cue
+ * that the user should remember to
+ * yank out the media if he just
+ * unmounted it.
+ */
+ item->type = PANEL_GIO_VOLUME;
+ item->u.volume = g_object_ref (volume);
+ }
+ items = g_slist_prepend (items, item);
+ g_object_unref (volume);
+ }
+ g_list_free (volumes);
+ } else {
+ if (g_drive_is_media_removable (drive) &&
+ !g_drive_is_media_check_automatic (drive)) {
+ /* If the drive has no mountable volumes and we
+ * cannot detect media change.. we display the
+ * drive so the user can manually poll the
+ * drive by clicking on it..."
+ *
+ * This is mainly for drives like floppies
+ * where media detection doesn't work.. but
+ * it's also for human beings who like to turn
+ * off media detection in the OS to save
+ * battery juice.
+ */
+ item = g_slice_new (PanelGioItem);
+ item->type = PANEL_GIO_DRIVE;
+ item->u.drive = g_object_ref (drive);
+ items = g_slist_prepend (items, item);
+ }
+ }
+ g_object_unref (drive);
+ }
+ g_list_free (drives);
+
+ /* add all volumes that is not associated with a drive */
+ volumes = g_volume_monitor_get_volumes (place_item->priv->volume_monitor);
+ for (l = volumes; l != NULL; l = l->next) {
+ volume = l->data;
+ drive = g_volume_get_drive (volume);
+ if (drive != NULL) {
+ g_object_unref (volume);
+ g_object_unref (drive);
+ continue;
+ }
+ mount = g_volume_get_mount (volume);
+ item = g_slice_new (PanelGioItem);
+ if (mount != NULL) {
+ item->type = PANEL_GIO_MOUNT;
+ item->u.mount = mount;
+ } else {
+ /* see comment above in why we add an icon for an
+ * unmounted mountable volume */
+ item->type = PANEL_GIO_VOLUME;
+ item->u.volume = g_object_ref (volume);
+ }
+ items = g_slist_prepend (items, item);
+ g_object_unref (volume);
+ }
+ g_list_free (volumes);
+
+ /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
+ mounts = g_volume_monitor_get_mounts (place_item->priv->volume_monitor);
+ for (l = mounts; l != NULL; l = l->next) {
+ GFile *root;
+
+ mount = l->data;
+
+ if (g_mount_is_shadowed (mount)) {
+ g_object_unref (mount);
+ continue;
+ }
+
+ volume = g_mount_get_volume (mount);
+ if (volume != NULL) {
+ g_object_unref (volume);
+ g_object_unref (mount);
+ continue;
+ }
+
+ root = g_mount_get_root (mount);
+ if (!g_file_is_native (root)) {
+ g_object_unref (root);
+ g_object_unref (mount);
+ continue;
+ }
+ g_object_unref (root);
+
+ item = g_slice_new (PanelGioItem);
+ item->type = PANEL_GIO_MOUNT;
+ item->u.mount = mount;
+ items = g_slist_prepend (items, item);
+ }
+ g_list_free (mounts);
+
+ /* now that we have everything, add the items inline or in a submenu */
+ items = g_slist_reverse (items);
+
+ if (g_slist_length (items) <= MAX_ITEMS_OR_SUBMENU) {
+ add_menu = menu;
+ } else {
+ GtkWidget *item;
+
+ item = gtk_image_menu_item_new ();
+ setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
+ PANEL_ICON_REMOVABLE_MEDIA,
+ NULL, NULL,
+ _("Removable Media"));
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ add_menu = create_empty_menu ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), add_menu);
+ }
+
+ for (sl = items; sl; sl = sl->next) {
+ item = sl->data;
+ switch (item->type) {
+ case PANEL_GIO_DRIVE:
+ panel_menu_item_append_drive (add_menu, item->u.drive);
+ g_object_unref (item->u.drive);
+ break;
+ case PANEL_GIO_VOLUME:
+ panel_menu_item_append_volume (add_menu, item->u.volume);
+ g_object_unref (item->u.volume);
+ break;
+ case PANEL_GIO_MOUNT:
+ panel_menu_item_append_mount (add_menu, item->u.mount);
+ g_object_unref (item->u.mount);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ g_slice_free (PanelGioItem, item);
+ }
+
+ g_slist_free (items);
+}
+
+/* this is loosely based on update_places() from caja-places-sidebar.c */
+static void
+panel_place_menu_item_append_remote_gio (PanelPlaceMenuItem *place_item,
+ GtkWidget *menu)
+{
+ GtkWidget *add_menu;
+ GList *mounts, *l;
+ GMount *mount;
+ GSList *add_mounts, *sl;
+
+ /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
+ mounts = g_volume_monitor_get_mounts (place_item->priv->volume_monitor);
+ add_mounts = NULL;
+
+ for (l = mounts; l; l = l->next) {
+ GVolume *volume;
+ GFile *root;
+
+ mount = l->data;
+
+ if (g_mount_is_shadowed (mount)) {
+ g_object_unref (mount);
+ continue;
+ }
+
+ volume = g_mount_get_volume (mount);
+ if (volume != NULL) {
+ g_object_unref (volume);
+ g_object_unref (mount);
+ continue;
+ }
+
+ root = g_mount_get_root (mount);
+ if (g_file_is_native (root)) {
+ g_object_unref (root);
+ g_object_unref (mount);
+ continue;
+ }
+ g_object_unref (root);
+
+
+ add_mounts = g_slist_prepend (add_mounts, mount);
+ }
+ add_mounts = g_slist_reverse (add_mounts);
+
+ if (g_slist_length (add_mounts) <= MAX_ITEMS_OR_SUBMENU) {
+ add_menu = menu;
+ } else {
+ GtkWidget *item;
+
+ item = panel_image_menu_item_new ();
+ setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
+ PANEL_ICON_NETWORK_SERVER,
+ NULL, NULL,
+ _("Network Places"));
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ add_menu = create_empty_menu ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), add_menu);
+ }
+
+ for (sl = add_mounts; sl; sl = sl->next) {
+ mount = sl->data;
+ panel_menu_item_append_mount (add_menu, mount);
+ g_object_unref (mount);
+ }
+
+ g_slist_free (add_mounts);
+ g_list_free (mounts);
+}
+
+
+static GtkWidget *
+panel_place_menu_item_create_menu (PanelPlaceMenuItem *place_item)
+{
+ GtkWidget *places_menu;
+ GtkWidget *item;
+ char *mateconf_name;
+ char *name;
+ char *uri;
+ GFile *file;
+
+ places_menu = panel_create_menu ();
+
+ file = g_file_new_for_path (g_get_home_dir ());
+ uri = g_file_get_uri (file);
+ name = panel_util_get_label_for_uri (uri);
+ g_object_unref (file);
+
+ panel_menu_items_append_place_item (PANEL_ICON_HOME, NULL,
+ name,
+ _("Open your personal folder"),
+ places_menu,
+ G_CALLBACK (activate_home_uri),
+ uri);
+ g_free (name);
+ g_free (uri);
+
+ if (!mateconf_client_get_bool (panel_mateconf_get_client (),
+ DESKTOP_IS_HOME_DIR_KEY,
+ NULL)) {
+ file = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
+ uri = g_file_get_uri (file);
+ g_object_unref (file);
+
+ panel_menu_items_append_place_item (
+ PANEL_ICON_DESKTOP, NULL,
+ /* Translators: Desktop is used here as in
+ * "Desktop Folder" (this is not the Desktop
+ * environment). */
+ C_("Desktop Folder", "Desktop"),
+ _("Open the contents of your desktop in a folder"),
+ places_menu,
+ G_CALLBACK (activate_desktop_uri),
+ /* FIXME: if the dir changes, we'd need to update the drag data since the uri is not the same */
+ uri);
+ g_free (uri);
+ }
+
+ panel_place_menu_item_append_gtk_bookmarks (places_menu);
+ add_menu_separator (places_menu);
+
+ mateconf_name = mateconf_client_get_string (panel_mateconf_get_client (),
+ COMPUTER_NAME_KEY,
+ NULL);
+ panel_menu_items_append_from_desktop (places_menu,
+ "caja-computer.desktop",
+ mateconf_name,
+ TRUE);
+ if (mateconf_name)
+ g_free (mateconf_name);
+
+ panel_place_menu_item_append_local_gio (place_item, places_menu);
+ add_menu_separator (places_menu);
+
+ panel_menu_items_append_from_desktop (places_menu,
+ "network-scheme.desktop",
+ NULL,
+ TRUE);
+ panel_place_menu_item_append_remote_gio (place_item, places_menu);
+
+ if (panel_is_program_in_path ("caja-connect-server")) {
+ item = panel_menu_items_create_action_item (PANEL_ACTION_CONNECT_SERVER);
+ if (item != NULL)
+ gtk_menu_shell_append (GTK_MENU_SHELL (places_menu),
+ item);
+ }
+
+ add_menu_separator (places_menu);
+
+ panel_menu_items_append_from_desktop (places_menu,
+ "mate-search-tool.desktop",
+ NULL,
+ FALSE);
+
+ panel_recent_append_documents_menu (places_menu,
+ place_item->priv->recent_manager);
+
+ return places_menu;
+}
+
+static void
+panel_place_menu_item_recreate_menu (GtkWidget *widget)
+{
+ PanelPlaceMenuItem *place_item;
+
+ place_item = PANEL_PLACE_MENU_ITEM (widget);
+
+ if (place_item->priv->menu) {
+ gtk_widget_destroy (place_item->priv->menu);
+ place_item->priv->menu = panel_place_menu_item_create_menu (place_item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (place_item),
+ place_item->priv->menu);
+ mate_panel_applet_menu_set_recurse (GTK_MENU (place_item->priv->menu),
+ "menu_panel",
+ place_item->priv->panel);
+ }
+}
+
+static void
+panel_place_menu_item_key_changed (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ GtkWidget *place_item)
+{
+ panel_place_menu_item_recreate_menu (place_item);
+}
+
+static void
+panel_place_menu_item_gtk_bookmarks_changed (GFileMonitor *handle,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data)
+{
+ panel_place_menu_item_recreate_menu (GTK_WIDGET (user_data));
+}
+
+static void
+panel_place_menu_item_drives_changed (GVolumeMonitor *monitor,
+ GDrive *drive,
+ GtkWidget *place_menu)
+{
+ panel_place_menu_item_recreate_menu (place_menu);
+}
+
+static void
+panel_place_menu_item_volumes_changed (GVolumeMonitor *monitor,
+ GVolume *volume,
+ GtkWidget *place_menu)
+{
+ panel_place_menu_item_recreate_menu (place_menu);
+}
+
+static void
+panel_place_menu_item_mounts_changed (GVolumeMonitor *monitor,
+ GMount *mount,
+ GtkWidget *place_menu)
+{
+ panel_place_menu_item_recreate_menu (place_menu);
+}
+
+static void
+panel_desktop_menu_item_append_menu (GtkWidget *menu,
+ gpointer data)
+{
+ PanelDesktopMenuItem *parent;
+ gboolean add_separator;
+ GList *children;
+ GList *last;
+
+ parent = PANEL_DESKTOP_MENU_ITEM (data);
+
+ add_separator = FALSE;
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ last = g_list_last (children);
+
+ if (last != NULL)
+ add_separator = !GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
+
+ g_list_free (children);
+
+ if (add_separator)
+ add_menu_separator (menu);
+
+ panel_menu_items_append_from_desktop (menu, "yelp.desktop", NULL, FALSE);
+ panel_menu_items_append_from_desktop (menu, "mate-about.desktop", NULL, FALSE);
+
+ if (parent->priv->append_lock_logout)
+ panel_menu_items_append_lock_logout (menu);
+}
+
+static GtkWidget *
+panel_desktop_menu_item_create_menu (PanelDesktopMenuItem *desktop_item)
+{
+ GtkWidget *desktop_menu;
+
+ desktop_menu = create_applications_menu ("mate-settings.menu", NULL, FALSE);
+
+ g_object_set_data (G_OBJECT (desktop_menu),
+ "panel-menu-append-callback",
+ panel_desktop_menu_item_append_menu);
+ g_object_set_data (G_OBJECT (desktop_menu),
+ "panel-menu-append-callback-data",
+ desktop_item);
+
+ return desktop_menu;
+}
+
+static void
+panel_desktop_menu_item_recreate_menu (PanelDesktopMenuItem *desktop_item)
+{
+ if (desktop_item->priv->menu) {
+ gtk_widget_destroy (desktop_item->priv->menu);
+ desktop_item->priv->menu = panel_desktop_menu_item_create_menu (desktop_item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (desktop_item),
+ desktop_item->priv->menu);
+ mate_panel_applet_menu_set_recurse (GTK_MENU (desktop_item->priv->menu),
+ "menu_panel",
+ desktop_item->priv->panel);
+ }
+}
+
+static void
+panel_place_menu_item_finalize (GObject *object)
+{
+ PanelPlaceMenuItem *menuitem = (PanelPlaceMenuItem *) object;
+
+ mateconf_client_remove_dir (panel_mateconf_get_client (),
+ DESKTOP_IS_HOME_DIR_DIR,
+ NULL);
+ mateconf_client_remove_dir (panel_mateconf_get_client (),
+ NAMES_DIR,
+ NULL);
+
+ if (menuitem->priv->bookmarks_monitor != NULL) {
+ g_file_monitor_cancel (menuitem->priv->bookmarks_monitor);
+ g_object_unref (menuitem->priv->bookmarks_monitor);
+ }
+ menuitem->priv->bookmarks_monitor = NULL;
+
+ if (menuitem->priv->drive_changed_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->drive_changed_id);
+ menuitem->priv->drive_changed_id = 0;
+
+ if (menuitem->priv->drive_connected_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->drive_connected_id);
+ menuitem->priv->drive_connected_id = 0;
+
+ if (menuitem->priv->drive_disconnected_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->drive_disconnected_id);
+ menuitem->priv->drive_disconnected_id = 0;
+
+ if (menuitem->priv->volume_added_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->volume_added_id);
+ menuitem->priv->volume_added_id = 0;
+
+ if (menuitem->priv->volume_changed_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->volume_changed_id);
+ menuitem->priv->volume_changed_id = 0;
+
+ if (menuitem->priv->volume_removed_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->volume_removed_id);
+ menuitem->priv->volume_removed_id = 0;
+
+ if (menuitem->priv->mount_added_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->mount_added_id);
+ menuitem->priv->mount_added_id = 0;
+
+ if (menuitem->priv->mount_changed_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->mount_changed_id);
+ menuitem->priv->mount_changed_id = 0;
+
+ if (menuitem->priv->mount_removed_id)
+ g_signal_handler_disconnect (menuitem->priv->volume_monitor,
+ menuitem->priv->mount_removed_id);
+ menuitem->priv->mount_removed_id = 0;
+
+ if (menuitem->priv->volume_monitor != NULL)
+ g_object_unref (menuitem->priv->volume_monitor);
+ menuitem->priv->volume_monitor = NULL;
+
+ G_OBJECT_CLASS (panel_place_menu_item_parent_class)->finalize (object);
+}
+
+static void
+panel_desktop_menu_item_finalize (GObject *object)
+{
+ PanelDesktopMenuItem *menuitem = (PanelDesktopMenuItem *) object;
+
+ if (menuitem->priv->append_lock_logout)
+ panel_lockdown_notify_remove (G_CALLBACK (panel_desktop_menu_item_recreate_menu),
+ menuitem);
+ G_OBJECT_CLASS (panel_desktop_menu_item_parent_class)->finalize (object);
+}
+
+static void
+panel_place_menu_item_init (PanelPlaceMenuItem *menuitem)
+{
+ GFile *bookmark;
+ char *bookmarks_filename;
+ GError *error;
+
+ menuitem->priv = PANEL_PLACE_MENU_ITEM_GET_PRIVATE (menuitem);
+
+ mateconf_client_add_dir (panel_mateconf_get_client (),
+ DESKTOP_IS_HOME_DIR_DIR,
+ MATECONF_CLIENT_PRELOAD_NONE,
+ NULL);
+ mateconf_client_add_dir (panel_mateconf_get_client (),
+ NAMES_DIR,
+ MATECONF_CLIENT_PRELOAD_NONE,
+ NULL);
+
+ panel_mateconf_notify_add_while_alive (HOME_NAME_KEY,
+ (MateConfClientNotifyFunc) panel_place_menu_item_key_changed,
+ G_OBJECT (menuitem));
+ panel_mateconf_notify_add_while_alive (DESKTOP_IS_HOME_DIR_KEY,
+ (MateConfClientNotifyFunc) panel_place_menu_item_key_changed,
+ G_OBJECT (menuitem));
+ panel_mateconf_notify_add_while_alive (COMPUTER_NAME_KEY,
+ (MateConfClientNotifyFunc) panel_place_menu_item_key_changed,
+ G_OBJECT (menuitem));
+
+ menuitem->priv->recent_manager = gtk_recent_manager_get_default ();
+
+ bookmarks_filename = g_build_filename (g_get_home_dir (),
+ BOOKMARKS_FILENAME, NULL);
+ bookmark = g_file_new_for_path (bookmarks_filename);
+
+ error = NULL;
+ menuitem->priv->bookmarks_monitor = g_file_monitor_file
+ (bookmark,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (error) {
+ g_warning ("Failed to add file monitor for %s: %s\n",
+ bookmarks_filename, error->message);
+ g_error_free (error);
+ } else {
+ g_signal_connect (G_OBJECT (menuitem->priv->bookmarks_monitor),
+ "changed",
+ (GCallback) panel_place_menu_item_gtk_bookmarks_changed,
+ menuitem);
+ }
+
+ g_object_unref (bookmark);
+ g_free (bookmarks_filename);
+
+ menuitem->priv->volume_monitor = g_volume_monitor_get ();
+
+ menuitem->priv->drive_changed_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "drive-changed",
+ G_CALLBACK (panel_place_menu_item_drives_changed),
+ menuitem);
+ menuitem->priv->drive_connected_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "drive-connected",
+ G_CALLBACK (panel_place_menu_item_drives_changed),
+ menuitem);
+ menuitem->priv->drive_disconnected_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "drive-disconnected",
+ G_CALLBACK (panel_place_menu_item_drives_changed),
+ menuitem);
+ menuitem->priv->volume_added_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "volume-added",
+ G_CALLBACK (panel_place_menu_item_volumes_changed),
+ menuitem);
+ menuitem->priv->volume_changed_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "volume-changed",
+ G_CALLBACK (panel_place_menu_item_volumes_changed),
+ menuitem);
+ menuitem->priv->volume_removed_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "volume-removed",
+ G_CALLBACK (panel_place_menu_item_volumes_changed),
+ menuitem);
+ menuitem->priv->mount_added_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "mount-added",
+ G_CALLBACK (panel_place_menu_item_mounts_changed),
+ menuitem);
+ menuitem->priv->mount_changed_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "mount-changed",
+ G_CALLBACK (panel_place_menu_item_mounts_changed),
+ menuitem);
+ menuitem->priv->mount_removed_id = g_signal_connect (menuitem->priv->volume_monitor,
+ "mount-removed",
+ G_CALLBACK (panel_place_menu_item_mounts_changed),
+ menuitem);
+
+}
+
+static void
+panel_desktop_menu_item_init (PanelDesktopMenuItem *menuitem)
+{
+ menuitem->priv = PANEL_DESKTOP_MENU_ITEM_GET_PRIVATE (menuitem);
+}
+
+static void
+panel_place_menu_item_class_init (PanelPlaceMenuItemClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ gobject_class->finalize = panel_place_menu_item_finalize;
+
+ g_type_class_add_private (klass, sizeof (PanelPlaceMenuItemPrivate));
+}
+
+static void
+panel_desktop_menu_item_class_init (PanelDesktopMenuItemClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ gobject_class->finalize = panel_desktop_menu_item_finalize;
+
+ g_type_class_add_private (klass, sizeof (PanelDesktopMenuItemPrivate));
+}
+
+GtkWidget* panel_place_menu_item_new(gboolean use_image)
+{
+ PanelPlaceMenuItem* menuitem;
+ GtkWidget* image;
+
+ menuitem = g_object_new(PANEL_TYPE_PLACE_MENU_ITEM, NULL);
+
+ if (use_image)
+ {
+ image = gtk_image_new_from_icon_name(PANEL_ICON_FOLDER, panel_menu_icon_get_size());
+ }
+ else
+ {
+ image = NULL;
+ }
+
+ setup_menuitem(GTK_WIDGET(menuitem), image ? panel_menu_icon_get_size() : GTK_ICON_SIZE_INVALID, image, _("Places"));
+
+ menuitem->priv->use_image = use_image;
+
+ menuitem->priv->menu = panel_place_menu_item_create_menu(menuitem);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menuitem->priv->menu);
+
+ return GTK_WIDGET(menuitem);
+}
+
+GtkWidget *
+panel_desktop_menu_item_new (gboolean use_image,
+ gboolean append_lock_logout)
+{
+ PanelDesktopMenuItem *menuitem;
+ GtkWidget *image;
+
+ menuitem = g_object_new (PANEL_TYPE_DESKTOP_MENU_ITEM, NULL);
+
+ if (use_image)
+ image = gtk_image_new_from_icon_name ("computer",
+ panel_menu_icon_get_size ());
+ else
+ image = NULL;
+
+ setup_menuitem (GTK_WIDGET (menuitem),
+ image ? panel_menu_icon_get_size () : GTK_ICON_SIZE_INVALID,
+ image,
+ _("System"));
+
+ menuitem->priv->use_image = use_image;
+
+ menuitem->priv->append_lock_logout = append_lock_logout;
+ if (append_lock_logout)
+ panel_lockdown_notify_add (G_CALLBACK (panel_desktop_menu_item_recreate_menu),
+ menuitem);
+
+ menuitem->priv->menu = panel_desktop_menu_item_create_menu (menuitem);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
+ menuitem->priv->menu);
+
+ return GTK_WIDGET (menuitem);
+}
+
+void
+panel_place_menu_item_set_panel (GtkWidget *item,
+ PanelWidget *panel)
+{
+ PanelPlaceMenuItem *place_item;
+
+ place_item = PANEL_PLACE_MENU_ITEM (item);
+
+ place_item->priv->panel = panel;
+ mate_panel_applet_menu_set_recurse (GTK_MENU (place_item->priv->menu),
+ "menu_panel", panel);
+}
+
+void
+panel_desktop_menu_item_set_panel (GtkWidget *item,
+ PanelWidget *panel)
+{
+ PanelDesktopMenuItem *desktop_item;
+
+ desktop_item = PANEL_DESKTOP_MENU_ITEM (item);
+
+ desktop_item->priv->panel = panel;
+ mate_panel_applet_menu_set_recurse (GTK_MENU (desktop_item->priv->menu),
+ "menu_panel", panel);
+}
+
+void
+panel_menu_items_append_lock_logout (GtkWidget *menu)
+{
+ gboolean separator_inserted;
+ GList *children;
+ GList *last;
+ GtkWidget *item;
+ const char *translate;
+ char *label;
+ char *tooltip;
+
+ separator_inserted = FALSE;
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ last = g_list_last (children);
+ if (last != NULL) {
+ separator_inserted = GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
+ }
+ g_list_free (children);
+
+ if (panel_lock_screen_action_available("lock"))
+ {
+ item = panel_menu_items_create_action_item(PANEL_ACTION_LOCK);
+
+ if (item != NULL)
+ {
+ if (!separator_inserted)
+ {
+ add_menu_separator(menu);
+ separator_inserted = TRUE;
+ }
+
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ }
+ }
+
+ if (panel_lockdown_get_disable_log_out ())
+ return;
+ /* Below this, we only have log out/shutdown items */
+
+ /* Translators: translate "1" (msgctxt: "panel:showusername") to anything
+ * but "1" if "Log Out %s" doesn't make any sense in your
+ * language (where %s is a username).
+ */
+ translate = C_("panel:showusername", "1");
+ if (strcmp (translate, "1") == 0) {
+ const char *user_name;
+
+ user_name = g_get_real_name ();
+ if (!user_name || !user_name [0])
+ user_name = g_get_user_name ();
+
+ /* keep those strings in sync with the ones in
+ * panel-action-button.c */
+ /* Translators: this string is used ONLY if you translated
+ * "1" (msgctxt: "panel:showusername") to "1" */
+ label = g_strdup_printf (_("Log Out %s..."),
+ g_get_user_name ());
+ /* Translators: this string is used ONLY if you translated
+ * "1" (msgctxt: "panel:showusername") to "1" */
+ tooltip = g_strdup_printf (_("Log out %s of this session to "
+ "log in as a different user"),
+ user_name);
+ } else {
+ label = NULL;
+ tooltip = NULL;
+ }
+
+ item = panel_menu_items_create_action_item_full (PANEL_ACTION_LOGOUT,
+ label, tooltip);
+ g_free (label);
+ g_free (tooltip);
+
+ if (item != NULL) {
+ if (!separator_inserted) {
+ add_menu_separator (menu);
+ separator_inserted = TRUE;
+ }
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+
+ item = panel_menu_items_create_action_item (PANEL_ACTION_SHUTDOWN);
+ if (item != NULL) {
+ if (!separator_inserted)
+ add_menu_separator (menu);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+}
+
+void
+panel_menu_item_activate_desktop_file (GtkWidget *menuitem,
+ const char *path)
+{
+ panel_launch_desktop_file (path, menuitem_to_screen (menuitem), NULL);
+}
diff --git a/mate-panel/panel-menu-items.h b/mate-panel/panel-menu-items.h
new file mode 100644
index 00000000..8f20801a
--- /dev/null
+++ b/mate-panel/panel-menu-items.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2005 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+
+#ifndef __PANEL_MENU_ITEMS_H__
+#define __PANEL_MENU_ITEMS_H__
+
+#include <gtk/gtk.h>
+#include "panel-widget.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_PLACE_MENU_ITEM (panel_place_menu_item_get_type ())
+#define PANEL_PLACE_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_PLACE_MENU_ITEM, PanelPlaceMenuItem))
+#define PANEL_PLACE_MENU_ITEM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_PLACE_MENU_ITEM, PanelPlaceMenuItemClass))
+#define PANEL_IS_PLACE_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_PLACE_MENU_ITEM))
+#define PANEL_IS_PLACE_MENU_ITEM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_PLACE_MENU_ITEM))
+#define PANEL_PLACE_MENU_ITEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_PLACE_MENU_ITEM, PanelPlaceMenuItemClass))
+
+typedef struct _PanelPlaceMenuItem PanelPlaceMenuItem;
+typedef struct _PanelPlaceMenuItemClass PanelPlaceMenuItemClass;
+typedef struct _PanelPlaceMenuItemPrivate PanelPlaceMenuItemPrivate;
+
+struct _PanelPlaceMenuItem {
+ GtkImageMenuItem menuitem;
+
+ PanelPlaceMenuItemPrivate *priv;
+};
+
+struct _PanelPlaceMenuItemClass {
+ GtkImageMenuItemClass menuitem_class;
+};
+
+GType panel_place_menu_item_get_type (void) G_GNUC_CONST;
+
+
+
+#define PANEL_TYPE_DESKTOP_MENU_ITEM (panel_desktop_menu_item_get_type ())
+#define PANEL_DESKTOP_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_DESKTOP_MENU_ITEM, PanelDesktopMenuItem))
+#define PANEL_DESKTOP_MENU_ITEM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_DESKTOP_MENU_ITEM, PanelDesktopMenuItemClass))
+#define PANEL_IS_DESKTOP_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_DESKTOP_MENU_ITEM))
+#define PANEL_IS_DESKTOP_MENU_ITEM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_DESKTOP_MENU_ITEM))
+#define PANEL_DESKTOP_MENU_ITEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_DESKTOP_MENU_ITEM, PanelDesktopMenuItemClass))
+
+typedef struct _PanelDesktopMenuItem PanelDesktopMenuItem;
+typedef struct _PanelDesktopMenuItemClass PanelDesktopMenuItemClass;
+typedef struct _PanelDesktopMenuItemPrivate PanelDesktopMenuItemPrivate;
+
+struct _PanelDesktopMenuItem{
+ GtkImageMenuItem menuitem;
+
+ PanelDesktopMenuItemPrivate *priv;
+};
+
+struct _PanelDesktopMenuItemClass {
+ GtkImageMenuItemClass menuitem_class;
+};
+
+GType panel_desktop_menu_item_get_type (void) G_GNUC_CONST;
+
+
+GtkWidget* panel_place_menu_item_new(gboolean use_image);
+GtkWidget* panel_desktop_menu_item_new(gboolean use_image, gboolean append_lock_logout);
+
+void panel_place_menu_item_set_panel (GtkWidget *item,
+ PanelWidget *panel);
+void panel_desktop_menu_item_set_panel (GtkWidget *item,
+ PanelWidget *panel);
+
+void panel_menu_items_append_lock_logout (GtkWidget *menu);
+void panel_menu_item_activate_desktop_file (GtkWidget *menuitem,
+ const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_MENU_ITEMS_H__ */
diff --git a/mate-panel/panel-modules.c b/mate-panel/panel-modules.c
new file mode 100644
index 00000000..01c06087
--- /dev/null
+++ b/mate-panel/panel-modules.c
@@ -0,0 +1,86 @@
+/*
+ * panel-modules.c
+ *
+ * Copyright (C) 2010 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+
+#include <libmate-panel-applet-private/mate-panel-applets-manager-dbus.h>
+
+#include "mate-panel-applets-manager.h"
+
+#include "panel-modules.h"
+
+static void
+panel_modules_ensure_extension_points_registered (void)
+{
+ static gboolean registered_extensions = FALSE;
+ GIOExtensionPoint *ep;
+
+ if (!registered_extensions) {
+ registered_extensions = TRUE;
+
+ ep = g_io_extension_point_register (MATE_PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME);
+ g_io_extension_point_set_required_type (ep, PANEL_TYPE_APPLETS_MANAGER);
+ }
+ }
+
+void
+panel_modules_ensure_loaded (void)
+{
+ static gboolean loaded_dirs = FALSE;
+ const char *module_path;
+
+ panel_modules_ensure_extension_points_registered ();
+
+ if (!loaded_dirs) {
+ GList *modules;
+ loaded_dirs = TRUE;
+
+ /* We load the modules explicitly instead of using scan_all
+ * so that we can leak a reference to them. This prevents them
+ * from getting unloaded later (something they aren't designed
+ * to cope with) */
+ modules = g_io_modules_load_all_in_directory (PANEL_MODULES_DIR);
+ g_list_free (modules);
+
+ module_path = g_getenv ("MATE_PANEL_EXTRA_MODULES");
+
+ if (module_path) {
+ gchar **paths;
+ int i;
+
+ paths = g_strsplit (module_path, ":", 0);
+
+ for (i = 0; paths[i] != NULL; i++) {
+ modules = g_io_modules_load_all_in_directory (paths[i]);
+ g_list_free (modules);
+ }
+
+ g_strfreev (paths);
+ }
+
+ mate_panel_applets_manager_dbus_get_type ();
+ }
+}
diff --git a/mate-panel/panel-modules.h b/mate-panel/panel-modules.h
new file mode 100644
index 00000000..02ddd045
--- /dev/null
+++ b/mate-panel/panel-modules.h
@@ -0,0 +1,30 @@
+/*
+ * panel-modules.h
+ *
+ * Copyright (C) 2010 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.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef __PANEL_MODULES_H__
+#define __PANEL_MODULES_H__
+
+void panel_modules_ensure_loaded (void);
+
+#endif /* __PANEL_MODULES_H__ */
diff --git a/mate-panel/panel-multiscreen.c b/mate-panel/panel-multiscreen.c
new file mode 100644
index 00000000..eef3ed72
--- /dev/null
+++ b/mate-panel/panel-multiscreen.c
@@ -0,0 +1,784 @@
+/*
+ * panel-multiscreen.c: Multi-screen and Xinerama support for the panel.
+ *
+ * Copyright (C) 2001 George Lebl <[email protected]>
+ * 2002 Sun Microsystems 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
+ *
+ * Authors: George Lebl <[email protected]>,
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+#include <gdk/gdkx.h>
+
+#include "panel-multiscreen.h"
+
+#include <string.h>
+
+#if defined(HAVE_CRT_EXTERNS_H) && defined(HAVE__NSGETENVIRON)
+#include <crt_externs.h> /* for _NSGetEnviron */
+#define environ (*_NSGetEnviron())
+#else
+extern char **environ;
+#endif
+
+static int screens = 0;
+static int *monitors = NULL;
+static GdkRectangle **geometries = NULL;
+static gboolean initialized = FALSE;
+static gboolean have_randr = FALSE;
+static gboolean have_randr_1_3 = FALSE;
+static guint reinit_id = 0;
+
+#ifdef HAVE_RANDR
+static gboolean
+_panel_multiscreen_output_should_be_first (Display *xdisplay,
+ RROutput output,
+ XRROutputInfo *info,
+ RROutput primary)
+{
+ if (primary)
+ return output == primary;
+
+ if (have_randr_1_3) {
+ Atom connector_type_atom;
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems;
+ unsigned long bytes_after;
+ unsigned char *prop;
+ char *connector_type;
+ gboolean retval;
+
+ connector_type_atom = XInternAtom (xdisplay, "ConnectorType", False);
+
+ if (XRRGetOutputProperty (xdisplay, output, connector_type_atom,
+ 0, 100, False, False, None,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop) == Success) {
+ if (actual_type == XA_ATOM && nitems == 1 && actual_format == 32) {
+ connector_type = XGetAtomName (xdisplay, prop[0]);
+ retval = g_strcmp0 (connector_type, "Panel") == 0;
+ XFree (connector_type);
+ return retval;
+ }
+ }
+ }
+
+ /* Pre-1.3 fallback:
+ * "LVDS" is the oh-so-intuitive name that X gives to laptop LCDs.
+ * It can actually be LVDS0, LVDS-0, Lvds, etc.
+ */
+ return (g_ascii_strncasecmp (info->name, "LVDS", strlen ("LVDS")) == 0);
+}
+#endif
+
+static gboolean
+panel_multiscreen_get_randr_monitors_for_screen (GdkScreen *screen,
+ int *monitors_ret,
+ GdkRectangle **geometries_ret)
+{
+#ifdef HAVE_RANDR
+ Display *xdisplay;
+ Window xroot;
+ XRRScreenResources *resources;
+ RROutput primary;
+ GArray *geometries;
+ int i;
+ gboolean driver_is_pre_randr_1_2;
+
+ if (!have_randr)
+ return FALSE;
+
+ /* GTK+ 2.14.x uses the Xinerama API, instead of RANDR, to get the
+ * monitor geometries. It does this to avoid calling
+ * XRRGetScreenResources(), which is slow as it re-detects all the
+ * monitors --- note that XRRGetScreenResourcesCurrent() had not been
+ * introduced yet. Using Xinerama in GTK+ has the bad side effect that
+ * gdk_screen_get_monitor_plug_name() will return NULL, as Xinerama
+ * does not provide that information, unlike RANDR.
+ *
+ * Here we need to identify the output names, so that we can put the
+ * built-in LCD in a laptop *before* all other outputs. This is so
+ * that mate-panel will normally prefer to appear on the "native"
+ * display rather than on an external monitor.
+ *
+ * To get the output names and geometries, we will not use
+ * gdk_screen_get_n_monitors() and friends, but rather we will call
+ * XRR*() directly.
+ *
+ * See https://bugzilla.novell.com/show_bug.cgi?id=479684 for this
+ * particular bug, and and
+ * http://bugzilla.gnome.org/show_bug.cgi?id=562944 for a more
+ * long-term solution.
+ */
+
+ xdisplay = GDK_SCREEN_XDISPLAY (screen);
+ xroot = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+
+#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
+ if (have_randr_1_3) {
+ resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
+ if (resources->noutput == 0) {
+ /* This might happen if nothing tried to get randr
+ * resources from the server before, so we need an
+ * active probe. See comment #27 in
+ * https://bugzilla.gnome.org/show_bug.cgi?id=597101 */
+ XRRFreeScreenResources (resources);
+ resources = XRRGetScreenResources (xdisplay, xroot);
+ }
+ } else
+ resources = XRRGetScreenResources (xdisplay, xroot);
+#else
+ resources = XRRGetScreenResources (xdisplay, xroot);
+#endif
+
+ if (!resources)
+ return FALSE;
+
+ primary = None;
+#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
+ if (have_randr_1_3)
+ primary = XRRGetOutputPrimary (xdisplay, xroot);
+#endif
+
+ geometries = g_array_sized_new (FALSE, FALSE,
+ sizeof (GdkRectangle),
+ resources->noutput);
+
+ driver_is_pre_randr_1_2 = FALSE;
+
+ for (i = 0; i < resources->noutput; i++) {
+ XRROutputInfo *output;
+
+ output = XRRGetOutputInfo (xdisplay, resources,
+ resources->outputs[i]);
+
+ /* Drivers before RANDR 1.2 return "default" for the output
+ * name */
+ if (g_strcmp0 (output->name, "default") == 0)
+ driver_is_pre_randr_1_2 = TRUE;
+
+ if (output->connection != RR_Disconnected &&
+ output->crtc != 0) {
+ XRRCrtcInfo *crtc;
+ GdkRectangle rect;
+
+ crtc = XRRGetCrtcInfo (xdisplay, resources,
+ output->crtc);
+
+ rect.x = crtc->x;
+ rect.y = crtc->y;
+ rect.width = crtc->width;
+ rect.height = crtc->height;
+
+ XRRFreeCrtcInfo (crtc);
+
+ if (_panel_multiscreen_output_should_be_first (xdisplay,
+ resources->outputs[i],
+ output, primary))
+ g_array_prepend_vals (geometries, &rect, 1);
+ else
+ g_array_append_vals (geometries, &rect, 1);
+ }
+
+ XRRFreeOutputInfo (output);
+ }
+
+ XRRFreeScreenResources (resources);
+
+ if (driver_is_pre_randr_1_2) {
+ /* Drivers before RANDR 1.2 don't provide useful info about
+ * outputs */
+ g_array_free (geometries, TRUE);
+ return FALSE;
+ }
+
+ if (geometries->len == 0) {
+ /* This can happen in at least one case:
+ * https://bugzilla.novell.com/show_bug.cgi?id=543876 where all
+ * monitors appear disconnected (possibly because the screen
+ * is behing a KVM switch) -- see comment #8.
+ * There might be other cases too, so we stay on the safe side.
+ */
+ g_array_free (geometries, TRUE);
+ return FALSE;
+ }
+
+ *monitors_ret = geometries->len;
+ *geometries_ret = (GdkRectangle *) g_array_free (geometries, FALSE);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+static void
+panel_multiscreen_get_gdk_monitors_for_screen (GdkScreen *screen,
+ int *monitors_ret,
+ GdkRectangle **geometries_ret)
+{
+ int num_monitors;
+ GdkRectangle *geometries;
+ int i;
+
+ num_monitors = gdk_screen_get_n_monitors (screen);
+ geometries = g_new (GdkRectangle, num_monitors);
+
+ for (i = 0; i < num_monitors; i++)
+ gdk_screen_get_monitor_geometry (screen, i, &(geometries[i]));
+
+ *monitors_ret = num_monitors;
+ *geometries_ret = geometries;
+}
+
+static void
+panel_multiscreen_get_raw_monitors_for_screen (GdkScreen *screen,
+ int *monitors_ret,
+ GdkRectangle **geometries_ret)
+{
+ gboolean res;
+
+ *monitors_ret = 0;
+ *geometries_ret = NULL;
+
+ res = panel_multiscreen_get_randr_monitors_for_screen (screen,
+ monitors_ret,
+ geometries_ret);
+ if (res && *monitors_ret > 0)
+ return;
+
+ panel_multiscreen_get_gdk_monitors_for_screen (screen,
+ monitors_ret,
+ geometries_ret);
+}
+
+static inline gboolean
+rectangle_overlaps (GdkRectangle *a,
+ GdkRectangle *b)
+{
+ return gdk_rectangle_intersect (a, b, NULL);
+}
+
+static long
+pixels_in_rectangle (GdkRectangle *r)
+{
+ return (long) (r->width * r->height);
+}
+
+static void
+panel_multiscreen_compress_overlapping_monitors (int *num_monitors_inout,
+ GdkRectangle **geometries_inout)
+{
+ int num_monitors;
+ GdkRectangle *geometries;
+ int i;
+
+ num_monitors = *num_monitors_inout;
+ geometries = *geometries_inout;
+
+ /* http://bugzilla.gnome.org/show_bug.cgi?id=530969
+ * https://bugzilla.novell.com/show_bug.cgi?id=310208
+ * and many other such bugs...
+ *
+ * RANDR sometimes gives us monitors that overlap (i.e. outputs whose
+ * bounding rectangles overlap). This is sometimes right and sometimes
+ * wrong:
+ *
+ * * Right - two 1024x768 outputs at the same offset (0, 0) that show
+ * the same thing. Think "laptop plus projector with the same
+ * resolution".
+ *
+ * * Wrong - one 1280x1024 output ("laptop internal LCD") and another
+ * 1024x768 output ("external monitor"), both at offset (0, 0).
+ * There is no way for the monitor with the small resolution to
+ * show the complete image from the laptop's LCD, unless one uses
+ * panning (but nobody wants panning, right!?).
+ *
+ * With overlapping monitors, we may end up placing the panel with
+ * respect to the "wrong" one. This is always wrong, as the panel
+ * appears "in the middle of the screen" of the monitor with the
+ * smaller resolution, instead of at the edge.
+ *
+ * Our strategy is to find the subsets of overlapping monitors, and
+ * "compress" each such set to being like if there were a single
+ * monitor with the biggest resolution of each of that set's monitors.
+ * Say we have four monitors
+ *
+ * A, B, C, D
+ *
+ * where B and D overlap. In that case, we'll generate a new list that
+ * looks like
+ *
+ * A, MAX(B, D), C
+ *
+ * with three monitors.
+ *
+ * NOTE FOR THE FUTURE: We could avoid most of this mess if we had a
+ * concept of a "primary monitor". Also, we could look at each
+ * output's name or properties to see if it is the built-in LCD in a
+ * laptop. However, with GTK+ 2.14.x we don't get output names, since
+ * it gets the list outputs from Xinerama, not RANDR (and Xinerama
+ * doesn't provide output names).
+ */
+
+ for (i = 0; i < num_monitors; i++) {
+ long max_pixels;
+ int j;
+
+ max_pixels = pixels_in_rectangle (&geometries[i]);
+
+ j = i + 1;
+
+ while (j < num_monitors) {
+ if (rectangle_overlaps (&geometries[i],
+ &geometries[j])) {
+ long pixels;
+
+ pixels = pixels_in_rectangle (&geometries[j]);
+ if (pixels > max_pixels) {
+ max_pixels = pixels;
+ /* keep the maximum */
+ geometries[i] = geometries[j];
+ }
+
+ /* Shift the remaining monitors to the left */
+ if (num_monitors - j - 1 > 0)
+ memmove (&geometries[j],
+ &geometries[j + 1],
+ sizeof (geometries[0]) * (num_monitors - j - 1));
+
+ num_monitors--;
+ g_assert (num_monitors > 0);
+ } else
+ j++;
+ }
+ }
+
+ *num_monitors_inout = num_monitors;
+ *geometries_inout = geometries;
+}
+
+static void
+panel_multiscreen_get_monitors_for_screen (GdkScreen *screen,
+ int *monitors_ret,
+ GdkRectangle **geometries_ret)
+{
+ panel_multiscreen_get_raw_monitors_for_screen (screen,
+ monitors_ret,
+ geometries_ret);
+ panel_multiscreen_compress_overlapping_monitors (monitors_ret,
+ geometries_ret);
+}
+
+static gboolean
+panel_multiscreen_reinit_idle (gpointer data)
+{
+ panel_multiscreen_reinit ();
+ reinit_id = 0;
+
+ return FALSE;
+}
+
+static void
+panel_multiscreen_queue_reinit (void)
+{
+ if (reinit_id)
+ return;
+
+ reinit_id = g_idle_add (panel_multiscreen_reinit_idle, NULL);
+}
+
+static void
+panel_multiscreen_init_randr (GdkDisplay *display)
+{
+#ifdef HAVE_RANDR
+ Display *xdisplay;
+ int event_base, error_base;
+#endif
+
+ have_randr = FALSE;
+ have_randr_1_3 = FALSE;
+
+#ifdef HAVE_RANDR
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+ /* We don't remember the event/error bases, as we expect to get "screen
+ * changed" events from GdkScreen instead.
+ */
+
+ if (XRRQueryExtension (xdisplay, &event_base, &error_base)) {
+ int major, minor;
+
+ XRRQueryVersion (xdisplay, &major, &minor);
+ if ((major == 1 && minor >= 2) || major > 1)
+ have_randr = TRUE;
+
+ if ((major == 1 && minor >= 3) || major > 1)
+ have_randr_1_3 = TRUE;
+ }
+#endif
+}
+
+void
+panel_multiscreen_init (void)
+{
+ GdkDisplay *display;
+ int i;
+
+ if (initialized)
+ return;
+
+ display = gdk_display_get_default ();
+ screens = gdk_display_get_n_screens (display);
+
+ panel_multiscreen_init_randr (display);
+
+ monitors = g_new0 (int, screens);
+ geometries = g_new0 (GdkRectangle *, screens);
+
+ for (i = 0; i < screens; i++) {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (display, i);
+
+ /* We connect to both signals to be on the safe side, but in
+ * theory, it should be enough to only connect to
+ * monitors-changed. Since we'll likely get two signals, we do
+ * the real callback in the idle loop. */
+ g_signal_connect (screen, "size-changed",
+ G_CALLBACK (panel_multiscreen_queue_reinit), NULL);
+ g_signal_connect (screen, "monitors-changed",
+ G_CALLBACK (panel_multiscreen_queue_reinit), NULL);
+
+ panel_multiscreen_get_monitors_for_screen (screen,
+ &(monitors[i]),
+ &(geometries[i]));
+ }
+
+ initialized = TRUE;
+}
+
+void
+panel_multiscreen_reinit (void)
+{
+ GdkDisplay *display;
+ GList *toplevels, *l;
+ int new_screens;
+ int i;
+
+ if (monitors)
+ g_free (monitors);
+
+ if (geometries) {
+ int j;
+
+ for (j = 0; j < screens; j++)
+ g_free (geometries[j]);
+ g_free (geometries);
+ }
+
+ display = gdk_display_get_default ();
+ /* Don't use the screens variable since in the future, we might
+ * want to call this function when a screen appears/disappears. */
+ new_screens = gdk_display_get_n_screens (display);
+
+ for (i = 0; i < new_screens; i++) {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (display, i);
+ g_signal_handlers_disconnect_by_func (screen,
+ panel_multiscreen_queue_reinit,
+ NULL);
+ }
+
+ initialized = FALSE;
+ panel_multiscreen_init ();
+
+ toplevels = gtk_window_list_toplevels ();
+
+ for (l = toplevels; l; l = l->next)
+ gtk_widget_queue_resize (l->data);
+
+ g_list_free (toplevels);
+}
+
+int
+panel_multiscreen_screens (void)
+{
+ return screens;
+}
+
+int
+panel_multiscreen_monitors (GdkScreen *screen)
+{
+ int n_screen;
+
+ n_screen = gdk_screen_get_number (screen);
+
+ g_return_val_if_fail (n_screen >= 0 && n_screen < screens, 1);
+
+ return monitors [n_screen];
+}
+
+int
+panel_multiscreen_x (GdkScreen *screen,
+ int monitor)
+{
+ int n_screen;
+
+ n_screen = gdk_screen_get_number (screen);
+
+ g_return_val_if_fail (n_screen >= 0 && n_screen < screens, 0);
+ g_return_val_if_fail (monitor >= 0 && monitor < monitors [n_screen], 0);
+
+ return geometries [n_screen][monitor].x;
+}
+
+int
+panel_multiscreen_y (GdkScreen *screen,
+ int monitor)
+{
+ int n_screen;
+
+ n_screen = gdk_screen_get_number (screen);
+
+ g_return_val_if_fail (n_screen >= 0 && n_screen < screens, 0);
+ g_return_val_if_fail (monitor >= 0 && monitor < monitors [n_screen], 0);
+
+ return geometries [n_screen][monitor].y;
+}
+
+int
+panel_multiscreen_width (GdkScreen *screen,
+ int monitor)
+{
+ int n_screen;
+
+ n_screen = gdk_screen_get_number (screen);
+
+ g_return_val_if_fail (n_screen >= 0 && n_screen < screens, 0);
+ g_return_val_if_fail (monitor >= 0 && monitor < monitors [n_screen], 0);
+
+ return geometries [n_screen][monitor].width;
+}
+
+int
+panel_multiscreen_height (GdkScreen *screen,
+ int monitor)
+{
+ int n_screen;
+
+ n_screen = gdk_screen_get_number (screen);
+
+ g_return_val_if_fail (n_screen >= 0 && n_screen < screens, 0);
+ g_return_val_if_fail (monitor >= 0 && monitor < monitors [n_screen], 0);
+
+ return geometries [n_screen][monitor].height;
+}
+
+int
+panel_multiscreen_locate_widget_monitor (GtkWidget *widget)
+{
+ GtkWidget *toplevel;
+ int retval = -1;
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (!toplevel)
+ return -1;
+
+ g_object_get (toplevel, "monitor", &retval, NULL);
+
+ return retval;
+}
+
+static int
+axis_distance (int p, int axis_start, int axis_size)
+{
+ if (p >= axis_start && p < axis_start + axis_size)
+ return 0;
+ else if (p < axis_start)
+ return (axis_start - p);
+ else
+ return (p - (axis_start + axis_size - 1));
+}
+
+/* The panel can't use gdk_screen_get_monitor_at_point() since it has its own
+ * view of which monitors are present. Look at get_monitors_for_screen() above
+ * to see why. */
+int
+panel_multiscreen_get_monitor_at_point (GdkScreen *screen,
+ int x,
+ int y)
+{
+ int n_screen;
+ int i;
+ int n_monitors;
+ GdkRectangle *geoms;
+ int min_dist_squared;
+ int closest_monitor;
+
+ /* not -1 as callers expect a real monitor */
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+ n_screen = gdk_screen_get_number (screen);
+
+ n_monitors = monitors[n_screen];
+ geoms = geometries[n_screen];
+
+ min_dist_squared = G_MAXINT32;
+ closest_monitor = 0;
+
+ for (i = 0; i < n_monitors; i++) {
+ int dist_x, dist_y;
+ int dist_squared;
+
+ dist_x = axis_distance (x, geoms[i].x, geoms[i].width);
+ dist_y = axis_distance (y, geoms[i].y, geoms[i].height);
+
+ if (dist_x == 0 && dist_y == 0)
+ return i;
+
+ dist_squared = dist_x * dist_x + dist_y * dist_y;
+
+ if (dist_squared < min_dist_squared) {
+ min_dist_squared = dist_squared;
+ closest_monitor = i;
+ }
+ }
+
+ return closest_monitor;
+}
+
+typedef struct {
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+} MonitorBounds;
+
+static inline void
+get_monitor_bounds (int n_screen,
+ int n_monitor,
+ MonitorBounds *bounds)
+{
+ g_assert (n_screen >= 0 && n_screen < screens);
+ g_assert (n_monitor >= 0 || n_monitor < monitors [n_screen]);
+ g_assert (bounds != NULL);
+
+ bounds->x0 = geometries [n_screen][n_monitor].x;
+ bounds->y0 = geometries [n_screen][n_monitor].y;
+ bounds->x1 = bounds->x0 + geometries [n_screen][n_monitor].width;
+ bounds->y1 = bounds->y0 + geometries [n_screen][n_monitor].height;
+}
+
+/* determines whether a given monitor is along the visible
+ * edge of the logical screen.
+ */
+void
+panel_multiscreen_is_at_visible_extreme (GdkScreen *screen,
+ int n_monitor,
+ gboolean *leftmost,
+ gboolean *rightmost,
+ gboolean *topmost,
+ gboolean *bottommost)
+{
+ MonitorBounds monitor;
+ int n_screen, i;
+
+ n_screen = gdk_screen_get_number (screen);
+
+ *leftmost = TRUE;
+ *rightmost = TRUE;
+ *topmost = TRUE;
+ *bottommost = TRUE;
+
+ g_return_if_fail (n_screen >= 0 && n_screen < screens);
+ g_return_if_fail (n_monitor >= 0 && n_monitor < monitors [n_screen]);
+
+ get_monitor_bounds (n_screen, n_monitor, &monitor);
+
+ /* go through each monitor and try to find one either right,
+ * below, above, or left of the specified monitor
+ */
+
+ for (i = 0; i < monitors [n_screen]; i++) {
+ MonitorBounds iter;
+
+ if (i == n_monitor) continue;
+
+ get_monitor_bounds (n_screen, i, &iter);
+
+ if ((iter.y0 >= monitor.y0 && iter.y0 < monitor.y1) ||
+ (iter.y1 > monitor.y0 && iter.y1 <= monitor.y1)) {
+ if (iter.x0 < monitor.x0)
+ *leftmost = FALSE;
+ if (iter.x1 > monitor.x1)
+ *rightmost = FALSE;
+ }
+
+ if ((iter.x0 >= monitor.x0 && iter.x0 < monitor.x1) ||
+ (iter.x1 > monitor.x0 && iter.x1 <= monitor.x1)) {
+ if (iter.y0 < monitor.y0)
+ *topmost = FALSE;
+ if (iter.y1 > monitor.y1)
+ *bottommost = FALSE;
+ }
+ }
+}
+
+char **
+panel_make_environment_for_screen (GdkScreen *screen,
+ char **envp)
+{
+ char **retval = NULL;
+ char *display_name;
+ int display_index = -1;
+ int i, env_len;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ if (envp == NULL)
+ envp = environ;
+
+ for (env_len = 0; envp[env_len]; env_len++)
+ if (strncmp (envp[env_len], "DISPLAY", strlen ("DISPLAY")) == 0)
+ display_index = env_len;
+
+ retval = g_new (char *, env_len + 1);
+ retval[env_len] = NULL;
+
+ display_name = gdk_screen_make_display_name (screen);
+
+ for (i = 0; i < env_len; i++)
+ if (i == display_index)
+ retval[i] = g_strconcat ("DISPLAY=", display_name, NULL);
+ else
+ retval[i] = g_strdup (envp[i]);
+
+ g_assert (i == env_len);
+
+ g_free (display_name);
+
+ return retval;
+}
diff --git a/mate-panel/panel-multiscreen.h b/mate-panel/panel-multiscreen.h
new file mode 100644
index 00000000..dd31b89b
--- /dev/null
+++ b/mate-panel/panel-multiscreen.h
@@ -0,0 +1,58 @@
+/*
+ * panel-multiscreen.h: Multi-screen and Xinerama support for the panel.
+ *
+ * Copyright (C) 2001 George Lebl <[email protected]>
+ * 2002 Sun Microsystems 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
+ *
+ * Authors: George Lebl <[email protected]>,
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_MULTISCREEN_H__
+#define __PANEL_MULTISCREEN_H__
+
+#include <gtk/gtk.h>
+
+void panel_multiscreen_init (void);
+void panel_multiscreen_reinit (void);
+
+int panel_multiscreen_screens (void);
+int panel_multiscreen_monitors (GdkScreen *screen);
+
+int panel_multiscreen_x (GdkScreen *screen,
+ int monitor);
+int panel_multiscreen_y (GdkScreen *screen,
+ int monitor);
+int panel_multiscreen_width (GdkScreen *screen,
+ int monitor);
+int panel_multiscreen_height (GdkScreen *screen,
+ int monitor);
+int panel_multiscreen_locate_widget_monitor (GtkWidget *widget);
+int panel_multiscreen_get_monitor_at_point (GdkScreen *screen,
+ int x,
+ int y);
+void panel_multiscreen_is_at_visible_extreme (GdkScreen *screen,
+ int monitor,
+ gboolean *leftmost,
+ gboolean *rightmost,
+ gboolean *topmost,
+ gboolean *bottommost);
+char **panel_make_environment_for_screen (GdkScreen *screen,
+ char **envp);
+
+#endif /* __PANEL_MULTISCREEN_H__ */
diff --git a/mate-panel/panel-object.schemas.in b/mate-panel/panel-object.schemas.in
new file mode 100644
index 00000000..2039ee57
--- /dev/null
+++ b/mate-panel/panel-object.schemas.in
@@ -0,0 +1,247 @@
+<?xml version="1.0"?>
+<mateconfschemafile>
+
+ <schemalist>
+
+ <!-- Applies to all object types -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/object_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>menu-object</default>
+ <locale name="C">
+ <short>Panel object type</short>
+ <long>
+ The type of this panel object. Possible values are
+ "drawer-object", "menu-object", "launcher-object",
+ "matecomponent-applet", "action-applet" and "menu-bar".
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/toplevel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Toplevel panel containing object</short>
+ <long>
+ The identifier of the toplevel panel which contains this object.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/position</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>Object's position on the panel</short>
+ <long>
+ The position of this panel object. The position is specified
+ by the number of pixels from the left (or top if vertical)
+ panel edge.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/panel_right_stick</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Interpret position relative to bottom/right edge</short>
+ <long>
+ If true, the position of the object is interpreted relative
+ to the right (or bottom if vertical) edge of the panel.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/locked</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Lock the object to the panel</short>
+ <long>
+ If true, the user may not move the applet without first unlocking
+ the object using the "Unlock" menuitem.
+ </long>
+ </locale>
+ </schema>
+
+
+ <!-- Applies to applets -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/matecomponent_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Applet MateComponent IID</short>
+ <long>
+ This key is deprecated, following the migration to a new library for
+ applets. The MateComponent implementation ID of the applet - e.g.
+ "OAFIID:MATE_ClockApplet". This key is only relevant if the
+ object_type key is "matecomponent-applet".
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/applet_iid</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Applet IID</short>
+ <long>
+ The implementation ID of the applet - e.g.
+ "ClockAppletFactory::ClockApplet". This key is only
+ relevant if the object_type key is "matecomponent-applet".
+ </long>
+ </locale>
+ </schema>
+
+ <!-- Applies to drawers -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/attached_toplevel_id</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Panel attached to drawer</short>
+ <long>
+ The identifier of the panel attached to this drawer. This
+ key is only relevant if the object_type key is "drawer-object".
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/tooltip</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Tooltip displayed for drawer or menu</short>
+ <long>
+ The text to display in a tooltip for this drawer or this menu. This
+ key is only relevant if the object_type key is "drawer-object" or
+ "menu-object".
+ </long>
+ </locale>
+ </schema>
+
+ <!-- Applies to drawers and menu buttons -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/use_custom_icon</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Use custom icon for object's button</short>
+ <long>
+ If true, the custom_icon key is used as a custom icon for
+ the button. If false, the custom_icon key is ignored.
+ This key is only relevant if the object_type key is
+ "menu-object" or "drawer-object".
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/custom_icon</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Icon used for object's button</short>
+ <long>
+ The location of the image file used as the icon for the
+ object's button. This key is only relevant if the
+ object_type key is "drawer-object" or "menu-object" and
+ the use_custom_icon key is true.
+ </long>
+ </locale>
+ </schema>
+
+ <!-- Applies to menu buttons -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/use_menu_path</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Use custom path for menu contents</short>
+ <long>
+ If true, the menu_path key is used as the path from which
+ the menu contents should be constructed. If false, the
+ menu_path key is ignored. This key is only relevant
+ if the object_type key is "menu-object".
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/objects/menu_path</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>applications:/</default>
+ <locale name="C">
+ <short>Menu content path</short>
+ <long>
+ The path from which the menu contents is contructed. This
+ key is only relevant if the use_menu_path key is true and
+ the object_type key is "menu-object".
+ </long>
+ </locale>
+ </schema>
+
+ <!-- Applies to launchers -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/launcher_location</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Launcher location</short>
+ <long>
+ The location of the .desktop file describing the launcher.
+ This key is only relevant if the object_type key is
+ "launcher-object".
+ </long>
+ </locale>
+ </schema>
+
+ <!-- Applies to action buttons -->
+
+ <schema>
+ <key>/schemas/apps/panel/objects/action_type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>lock</default>
+ <locale name="C">
+ <short>Action button type</short>
+ <long>
+ The action type this button represents. Possible values are
+ "lock", "logout", "run", "search" and "screenshot". This
+ key is only relevant if the object_type key is "action-applet".
+ </long>
+ </locale>
+ </schema>
+
+ </schemalist>
+
+</mateconfschemafile>
diff --git a/mate-panel/panel-profile.c b/mate-panel/panel-profile.c
new file mode 100644
index 00000000..52cb353b
--- /dev/null
+++ b/mate-panel/panel-profile.c
@@ -0,0 +1,2647 @@
+/*
+ * panel-profile.c:
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-profile.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <libpanel-util/panel-list.h>
+
+#include "applet.h"
+#include "panel-compatibility.h"
+#include "panel-mateconf.h"
+#include "panel.h"
+#include "panel-widget.h"
+#include "panel-util.h"
+#include "panel-multiscreen.h"
+#include "panel-toplevel.h"
+#include "panel-lockdown.h"
+
+typedef struct {
+ GdkScreen *screen;
+ int monitor;
+ int size;
+ int x;
+ int x_right;
+ gboolean x_centered;
+ int y;
+ int y_bottom;
+ gboolean y_centered;
+ PanelOrientation orientation;
+
+ guint screen_changed : 1;
+ guint monitor_changed : 1;
+ guint size_changed : 1;
+ guint x_changed : 1;
+ guint x_right_changed : 1;
+ guint x_centered_changed : 1;
+ guint y_changed : 1;
+ guint y_bottom_changed : 1;
+ guint y_centered_changed : 1;
+ guint orientation_changed : 1;
+} ToplevelLocationChange;
+
+typedef const char *(*PanelProfileGetIdFunc) (gpointer object);
+typedef gboolean (*PanelProfileOnLoadQueue) (const char *id);
+typedef void (*PanelProfileLoadFunc) (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ const char *id);
+typedef void (*PanelProfileDestroyFunc) (const char *id);
+
+static MateConfEnumStringPair panel_orientation_map [] = {
+ { PANEL_ORIENTATION_TOP, "top" },
+ { PANEL_ORIENTATION_BOTTOM, "bottom" },
+ { PANEL_ORIENTATION_LEFT, "left" },
+ { PANEL_ORIENTATION_RIGHT, "right" },
+ { 0, NULL }
+};
+
+static MateConfEnumStringPair panel_animation_speed_map [] = {
+ { PANEL_ANIMATION_SLOW, "slow" },
+ { PANEL_ANIMATION_MEDIUM, "medium" },
+ { PANEL_ANIMATION_FAST, "fast" },
+ { 0, NULL }
+};
+
+static MateConfEnumStringPair panel_background_type_map [] = {
+ { PANEL_BACK_NONE, "gtk" },
+ { PANEL_BACK_COLOR, "color" },
+ { PANEL_BACK_IMAGE, "image" },
+ { 0, NULL }
+};
+
+static MateConfEnumStringPair panel_object_type_map [] = {
+ { PANEL_OBJECT_DRAWER, "drawer-object" },
+ { PANEL_OBJECT_MENU, "menu-object" },
+ { PANEL_OBJECT_LAUNCHER, "launcher-object" },
+ { PANEL_OBJECT_APPLET, "matecomponent-applet" },
+ { PANEL_OBJECT_ACTION, "action-applet" },
+ { PANEL_OBJECT_MENU_BAR, "menu-bar" },
+ { PANEL_OBJECT_SEPARATOR, "separator" },
+ /* The following two are for backwards compatibility with 2.0.x */
+ { PANEL_OBJECT_LOCK, "lock-object" },
+ { PANEL_OBJECT_LOGOUT, "logout-object" },
+ { 0, NULL }
+};
+
+static GQuark toplevel_id_quark = 0;
+static GQuark queued_changes_quark = 0;
+static GQuark commit_timeout_quark = 0;
+
+static void panel_profile_object_id_list_update (MateConfClient *client,
+ MateConfValue *value,
+ PanelMateConfKeyType type);
+
+gboolean
+panel_profile_map_orientation_string (const char *str,
+ PanelOrientation *orientation)
+{
+ int mapped;
+
+ g_return_val_if_fail (orientation != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_orientation_map, str, &mapped))
+ return FALSE;
+
+ *orientation = mapped;
+
+ return TRUE;
+}
+
+const char *
+panel_profile_map_orientation (PanelOrientation orientation)
+{
+ return mateconf_enum_to_string (panel_orientation_map, orientation);
+}
+
+gboolean
+panel_profile_map_speed_string (const char *str,
+ PanelAnimationSpeed *speed)
+{
+ int mapped;
+
+ g_return_val_if_fail (speed != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_animation_speed_map, str, &mapped))
+ return FALSE;
+
+ *speed = mapped;
+
+ return TRUE;
+}
+
+gboolean
+panel_profile_map_background_type_string (const char *str,
+ PanelBackgroundType *background_type)
+{
+ int mapped;
+
+ g_return_val_if_fail (background_type != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_background_type_map, str, &mapped))
+ return FALSE;
+
+ *background_type = mapped;
+
+ return TRUE;
+}
+
+const char *
+panel_profile_map_background_type (PanelBackgroundType background_type)
+{
+ return mateconf_enum_to_string (panel_background_type_map, background_type);
+}
+
+gboolean
+panel_profile_map_object_type_string (const char *str,
+ PanelObjectType *object_type)
+{
+ int mapped;
+
+ g_return_val_if_fail (object_type != NULL, FALSE);
+
+ if (!str)
+ return FALSE;
+
+ if (!mateconf_string_to_enum (panel_object_type_map, str, &mapped))
+ return FALSE;
+
+ *object_type = mapped;
+
+ return TRUE;
+}
+
+static void
+panel_profile_set_toplevel_id (PanelToplevel *toplevel,
+ const char *id)
+{
+ if (!toplevel_id_quark)
+ toplevel_id_quark = g_quark_from_static_string ("panel-toplevel-id");
+
+ g_object_set_qdata_full (G_OBJECT (toplevel),
+ toplevel_id_quark,
+ g_strdup (id),
+ g_free);
+}
+
+const char *
+panel_profile_get_toplevel_id (PanelToplevel *toplevel)
+{
+ if (!toplevel_id_quark)
+ return NULL;
+
+ return g_object_get_qdata (G_OBJECT (toplevel), toplevel_id_quark);
+}
+
+PanelToplevel *
+panel_profile_get_toplevel_by_id (const char *toplevel_id)
+{
+ GSList *toplevels, *l;
+
+ if (!toplevel_id || !toplevel_id [0])
+ return NULL;
+
+ toplevels = panel_toplevel_list_toplevels ();
+ for (l = toplevels; l; l = l->next)
+ if (!strcmp (panel_profile_get_toplevel_id (l->data), toplevel_id))
+ return l->data;
+
+ return NULL;
+}
+
+char *
+panel_profile_find_new_id (PanelMateConfKeyType type)
+{
+ MateConfClient *client;
+ GSList *l, *existing_ids;
+ const char *key;
+ char *retval = NULL;
+ char *prefix;
+ char *dir;
+ int i;
+
+ client = panel_mateconf_get_client ();
+
+ switch (type) {
+ case PANEL_MATECONF_TOPLEVELS:
+ prefix = "panel";
+ dir = "toplevels";
+ break;
+ case PANEL_MATECONF_OBJECTS:
+ prefix = "object";
+ dir = "objects";
+ break;
+ case PANEL_MATECONF_APPLETS:
+ prefix = "applet";
+ dir = "applets";
+ break;
+ default:
+ prefix = dir = NULL;
+ g_assert_not_reached ();
+ break;
+ }
+
+ key = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/%s", dir);
+ existing_ids = mateconf_client_all_dirs (client, key, NULL);
+
+ for (i = 0; !retval; i++) {
+ retval = g_strdup_printf ("%s_%d", prefix, i);
+
+ for (l = existing_ids; l; l = l->next)
+ if (!strcmp (panel_mateconf_basename (l->data), retval)) {
+ g_free (retval);
+ retval = NULL;
+ break;
+ }
+ }
+
+ g_assert (retval != NULL);
+
+ for (l = existing_ids; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (existing_ids);
+
+ return retval;
+}
+
+static void
+panel_profile_set_queued_changes (PanelToplevel *toplevel,
+ MateConfChangeSet *changes)
+{
+ if (!queued_changes_quark)
+ queued_changes_quark = g_quark_from_static_string ("panel-queued-changes");
+
+ g_object_set_qdata_full (G_OBJECT (toplevel),
+ queued_changes_quark,
+ changes,
+ (GDestroyNotify) mateconf_change_set_unref);
+}
+
+static MateConfChangeSet *
+panel_profile_get_queued_changes (GObject *object)
+{
+ if (!queued_changes_quark)
+ return NULL;
+
+ return g_object_get_qdata (object, queued_changes_quark);
+}
+
+static void
+panel_profile_remove_commit_timeout (guint timeout)
+{
+ g_source_remove (timeout);
+}
+
+static void
+panel_profile_set_commit_timeout (PanelToplevel *toplevel,
+ guint timeout)
+{
+ GDestroyNotify destroy_notify;
+
+ if (!commit_timeout_quark)
+ commit_timeout_quark = g_quark_from_static_string ("panel-queued-timeout");
+
+ if (timeout)
+ destroy_notify = (GDestroyNotify) panel_profile_remove_commit_timeout;
+ else
+ destroy_notify = NULL;
+
+ g_object_set_qdata_full (G_OBJECT (toplevel),
+ commit_timeout_quark,
+ GUINT_TO_POINTER (timeout),
+ destroy_notify);
+}
+
+static guint
+panel_profile_get_commit_timeout (GObject *object)
+{
+ if (!commit_timeout_quark)
+ return 0;
+
+ return GPOINTER_TO_UINT (g_object_get_qdata (object, commit_timeout_quark));
+}
+
+static const char *
+panel_profile_get_toplevel_key (PanelToplevel *toplevel,
+ const char *key)
+{
+ const char *id;
+
+ id = panel_profile_get_toplevel_id (toplevel);
+
+ return panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS, id, key);
+}
+
+#define TOPLEVEL_IS_WRITABLE_FUNC(k, p, s) \
+ gboolean \
+ panel_profile_is_writable_##p##_##s (PanelToplevel *toplevel) \
+ { \
+ MateConfClient *client; \
+ const char *key; \
+ client = panel_mateconf_get_client (); \
+ key = panel_profile_get_toplevel_key (toplevel, k); \
+ return mateconf_client_key_is_writable (client, key, NULL); \
+ }
+
+void
+panel_profile_set_background_type (PanelToplevel *toplevel,
+ PanelBackgroundType background_type)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/type");
+ mateconf_client_set_string (client,
+ key,
+ panel_profile_map_background_type (background_type),
+ NULL);
+}
+
+PanelBackgroundType
+panel_profile_get_background_type (PanelToplevel *toplevel)
+{
+ PanelBackgroundType background_type;
+ MateConfClient *client;
+ const char *key;
+ char *str;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/type");
+ str = mateconf_client_get_string (client, key, NULL);
+
+ if (!str || !panel_profile_map_background_type_string (str, &background_type))
+ background_type = PANEL_BACK_NONE;
+
+ g_free (str);
+
+ return background_type;
+}
+
+TOPLEVEL_IS_WRITABLE_FUNC ("background/type", background, type)
+
+void
+panel_profile_set_background_color (PanelToplevel *toplevel,
+ PanelColor *color)
+{
+ panel_profile_set_background_gdk_color (toplevel, &color->gdk);
+ panel_profile_set_background_opacity (toplevel, color->alpha);
+}
+
+void
+panel_profile_get_background_color (PanelToplevel *toplevel,
+ PanelColor *color)
+{
+ panel_profile_get_background_gdk_color (toplevel, &(color->gdk));
+ color->alpha = panel_profile_get_background_opacity (toplevel);
+}
+
+TOPLEVEL_IS_WRITABLE_FUNC ("background/color", background, color)
+
+void
+panel_profile_set_background_gdk_color (PanelToplevel *toplevel,
+ GdkColor *gdk_color)
+{
+ MateConfClient *client;
+ const char *key;
+ char *color_str;
+
+ client = panel_mateconf_get_client ();
+
+ color_str = g_strdup_printf ("#%02x%02x%02x",
+ gdk_color->red / 256,
+ gdk_color->green / 256,
+ gdk_color->blue / 256);
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/color");
+ mateconf_client_set_string (client, key, color_str, NULL);
+
+ g_free (color_str);
+}
+
+void
+panel_profile_get_background_gdk_color (PanelToplevel *toplevel,
+ GdkColor *gdk_color)
+{
+ MateConfClient *client;
+ const char *key;
+ char *color_str;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/color");
+ color_str = mateconf_client_get_string (client, key, NULL);
+ if (!color_str || !gdk_color_parse (color_str, gdk_color)) {
+ gdk_color->red = 0;
+ gdk_color->green = 0;
+ gdk_color->blue = 0;
+ }
+
+ g_free (color_str);
+}
+
+void
+panel_profile_set_background_opacity (PanelToplevel *toplevel,
+ guint16 opacity)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/opacity");
+ mateconf_client_set_int (client, key, opacity, NULL);
+}
+
+guint16
+panel_profile_get_background_opacity (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+ guint16 opacity;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/opacity");
+ opacity = mateconf_client_get_int (client, key, NULL);
+
+ return opacity;
+}
+
+TOPLEVEL_IS_WRITABLE_FUNC ("background/opacity", background, opacity)
+
+void
+panel_profile_set_background_image (PanelToplevel *toplevel,
+ const char *image)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/image");
+
+ if (image && image [0])
+ mateconf_client_set_string (client, key, image, NULL);
+ else
+ mateconf_client_unset (client, key, NULL);
+}
+
+char *
+panel_profile_get_background_image (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+ char *retval;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "background/image");
+ retval = mateconf_client_get_string (client, key, NULL);
+
+ return retval;
+}
+
+TOPLEVEL_IS_WRITABLE_FUNC ("background/image", background, image)
+
+void
+panel_profile_set_toplevel_name (PanelToplevel *toplevel,
+ const char *name)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "name");
+
+ if (name && name [0])
+ mateconf_client_set_string (client, key, name, NULL);
+ else
+ mateconf_client_unset (client, key, NULL);
+}
+
+char *
+panel_profile_get_toplevel_name (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+ char *retval;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "name");
+ retval = mateconf_client_get_string (client, key, NULL);
+
+ return retval;
+}
+
+TOPLEVEL_IS_WRITABLE_FUNC ("name", toplevel, name)
+
+void
+panel_profile_set_toplevel_orientation (PanelToplevel *toplevel,
+ PanelOrientation orientation)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "orientation");
+ mateconf_client_set_string (client,
+ key,
+ panel_profile_map_orientation (orientation),
+ NULL);
+}
+
+PanelOrientation
+panel_profile_get_toplevel_orientation (PanelToplevel *toplevel)
+{
+ PanelOrientation orientation;
+ MateConfClient *client;
+ const char *key;
+ char *str;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "orientation");
+ str = mateconf_client_get_string (client, key, NULL);
+
+ if (!panel_profile_map_orientation_string (str, &orientation))
+ orientation = panel_toplevel_get_orientation (toplevel);
+
+ g_free (str);
+
+ return orientation;
+}
+
+TOPLEVEL_IS_WRITABLE_FUNC ("orientation", toplevel, orientation)
+
+#define TOPLEVEL_GET_SET_FUNCS(k, p, t, s, a) \
+ void \
+ panel_profile_set_##p##_##s (PanelToplevel *toplevel, a s) \
+ { \
+ MateConfClient *client; \
+ const char *key; \
+ client = panel_mateconf_get_client (); \
+ key = panel_profile_get_toplevel_key (toplevel, k); \
+ mateconf_client_set_##t (client, key, s, NULL); \
+ } \
+ a \
+ panel_profile_get_##p##_##s (PanelToplevel *toplevel) \
+ { \
+ MateConfClient *client; \
+ const char *key; \
+ a retval; \
+ client = panel_mateconf_get_client (); \
+ key = panel_profile_get_toplevel_key (toplevel, k); \
+ retval = mateconf_client_get_##t (client, key, NULL); \
+ return retval; \
+ } \
+ TOPLEVEL_IS_WRITABLE_FUNC(k, p, s)
+
+TOPLEVEL_GET_SET_FUNCS ("size", toplevel, int, size, int)
+TOPLEVEL_GET_SET_FUNCS ("expand", toplevel, bool, expand, gboolean)
+TOPLEVEL_GET_SET_FUNCS ("auto_hide", toplevel, bool, auto_hide, gboolean)
+TOPLEVEL_GET_SET_FUNCS ("enable_buttons", toplevel, bool, enable_buttons, gboolean)
+TOPLEVEL_GET_SET_FUNCS ("enable_arrows", toplevel, bool, enable_arrows, gboolean)
+TOPLEVEL_GET_SET_FUNCS ("background/fit", background, bool, fit, gboolean)
+TOPLEVEL_GET_SET_FUNCS ("background/stretch", background, bool, stretch, gboolean)
+TOPLEVEL_GET_SET_FUNCS ("background/rotate", background, bool, rotate, gboolean)
+
+static const char *
+panel_profile_get_attached_object_key (PanelToplevel *toplevel,
+ const char *key)
+{
+ GtkWidget *attach_widget;
+ const char *id;
+
+ attach_widget = panel_toplevel_get_attach_widget (toplevel);
+
+ id = mate_panel_applet_get_id_by_widget (attach_widget);
+
+ if (!id)
+ return NULL;
+
+ return panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, key);
+}
+
+void
+panel_profile_set_attached_custom_icon (PanelToplevel *toplevel,
+ const char *custom_icon)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_attached_object_key (toplevel, "use_custom_icon");
+ if (key)
+ mateconf_client_set_bool (client, key, custom_icon != NULL, NULL);
+
+ key = panel_profile_get_attached_object_key (toplevel, "custom_icon");
+ if (key)
+ mateconf_client_set_string (client, key, sure_string (custom_icon), NULL);
+}
+
+char *
+panel_profile_get_attached_custom_icon (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_attached_object_key (toplevel, "use_custom_icon");
+ if (!key || !mateconf_client_get_bool (client, key, NULL))
+ return NULL;
+
+ key = panel_profile_get_attached_object_key (toplevel, "custom_icon");
+
+ return key ? mateconf_client_get_string (client, key, NULL) : NULL;
+}
+
+gboolean
+panel_profile_is_writable_attached_custom_icon (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_attached_object_key (toplevel, "use_custom_icon");
+ if (!key)
+ return TRUE;
+
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ key = panel_profile_get_attached_object_key (toplevel, "custom_icon");
+
+ return key ? mateconf_client_key_is_writable (client, key, NULL) : TRUE;
+}
+
+void
+panel_profile_set_attached_tooltip (PanelToplevel *toplevel,
+ const char *tooltip)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_attached_object_key (toplevel, "tooltip");
+ if (key)
+ mateconf_client_set_string (client, key, tooltip, NULL);
+}
+
+char *
+panel_profile_get_attached_tooltip (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_attached_object_key (toplevel, "tooltip");
+
+ return key ? mateconf_client_get_string (client, key, NULL) : NULL;
+}
+
+gboolean
+panel_profile_is_writable_attached_tooltip (PanelToplevel *toplevel)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_attached_object_key (toplevel, "tooltip");
+
+ return key ? mateconf_client_key_is_writable (client, key, NULL) : TRUE;
+}
+
+static PanelBackgroundType
+get_background_type (MateConfClient *client,
+ const char *toplevel_dir)
+{
+ PanelBackgroundType background_type;
+ GError *error = NULL;
+ const char *key;
+ char *type_str;
+
+ key = panel_mateconf_sprintf ("%s/background/type", toplevel_dir);
+ type_str = mateconf_client_get_string (client, key, &error);
+ if (error) {
+ g_warning (_("Error reading MateConf string value '%s': %s"),
+ key, error->message);
+ g_error_free (error);
+ return PANEL_BACK_NONE;
+ }
+
+ if (!type_str || !panel_profile_map_background_type_string (type_str, &background_type))
+ background_type = PANEL_BACK_NONE;
+
+ g_free (type_str);
+
+ return background_type;
+}
+
+static void
+get_background_color (MateConfClient *client,
+ const char *toplevel_dir,
+ PanelColor *color)
+{
+ GError *error;
+ const char *key;
+ char *color_str;
+
+ error = NULL;
+ key = panel_mateconf_sprintf ("%s/background/color", toplevel_dir);
+ color_str = mateconf_client_get_string (client, key, &error);
+ if (error) {
+ g_warning (_("Error reading MateConf string value '%s': %s"),
+ key, error->message);
+ g_error_free (error);
+ } else if (!color_str || !gdk_color_parse (color_str, &(color->gdk))) {
+ color->gdk.red = 0;
+ color->gdk.green = 0;
+ color->gdk.blue = 0;
+ }
+
+ g_free (color_str);
+
+ error = NULL;
+ key = panel_mateconf_sprintf ("%s/background/opacity", toplevel_dir);
+ color->alpha = mateconf_client_get_int (client, key, &error);
+ if (error) {
+ g_warning (_("Error reading MateConf integer value '%s': %s"),
+ key, error->message);
+ g_error_free (error);
+ color->alpha = 65535; /* fallback to fully opaque */
+ }
+}
+
+static char *
+get_background_image (MateConfClient *client,
+ const char *toplevel_dir,
+ gboolean *fit,
+ gboolean *stretch,
+ gboolean *rotate)
+{
+ const char *key;
+ GError *error = NULL;
+ char *image;
+
+ key = panel_mateconf_sprintf ("%s/background/image", toplevel_dir);
+ image = mateconf_client_get_string (client, key, &error);
+ if (error) {
+ g_warning (_("Error reading MateConf string value '%s': %s"),
+ key, error->message);
+ g_error_free (error);
+ }
+
+ key = panel_mateconf_sprintf ("%s/background/fit", toplevel_dir);
+ *fit = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/background/stretch", toplevel_dir);
+ *stretch = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/background/rotate", toplevel_dir);
+ *rotate = mateconf_client_get_bool (client, key, NULL);
+
+ return image;
+}
+
+static void
+panel_profile_load_background (PanelToplevel *toplevel,
+ MateConfClient *client,
+ const char *toplevel_dir)
+{
+ PanelWidget *panel_widget;
+ PanelBackground *background;
+ PanelBackgroundType background_type;
+ PanelColor color;
+ char *image;
+ gboolean fit;
+ gboolean stretch;
+ gboolean rotate;
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+ background = &panel_widget->background;
+
+ background_type = get_background_type (client, toplevel_dir);
+
+ get_background_color (client, toplevel_dir, &color);
+
+ image = get_background_image (client, toplevel_dir, &fit, &stretch, &rotate);
+
+ panel_background_set (background,
+ background_type,
+ &color,
+ image,
+ fit,
+ stretch,
+ rotate);
+
+ g_free (image);
+}
+
+static gboolean
+panel_profile_commit_toplevel_changes (PanelToplevel *toplevel)
+{
+ MateConfChangeSet *queued_changes;
+
+ queued_changes = panel_profile_get_queued_changes (G_OBJECT (toplevel));
+ if (queued_changes)
+ mateconf_client_commit_change_set (
+ panel_mateconf_get_client (),
+ queued_changes, FALSE, NULL);
+
+ panel_profile_set_queued_changes (toplevel, NULL);
+ panel_profile_set_commit_timeout (toplevel, 0);
+
+ return FALSE;
+}
+
+static void
+panel_profile_queue_toplevel_location_change (PanelToplevel *toplevel,
+ ToplevelLocationChange *change)
+{
+ MateConfChangeSet *queued_changes;
+ guint commit_timeout;
+
+ queued_changes = panel_profile_get_queued_changes (G_OBJECT (toplevel));
+ if (!queued_changes) {
+ queued_changes = mateconf_change_set_new ();
+ panel_profile_set_queued_changes (toplevel, queued_changes);
+ }
+
+ if (change->screen_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "screen"),
+ gdk_screen_get_number (change->screen));
+
+ if (change->monitor_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "monitor"),
+ change->monitor);
+
+ if (change->size_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "size"),
+ change->size);
+
+ if (change->orientation_changed)
+ mateconf_change_set_set_string (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "orientation"),
+ mateconf_enum_to_string (panel_orientation_map, change->orientation));
+
+ if (!panel_toplevel_get_expand (toplevel)) {
+ if (change->x_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "x"),
+ change->x);
+
+ if (change->x_right_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "x_right"),
+ change->x_right);
+
+ if (change->x_centered_changed)
+ mateconf_change_set_set_bool (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "x_centered"),
+ change->x_centered);
+
+ if (change->y_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "y"),
+ change->y);
+
+ if (change->y_bottom_changed)
+ mateconf_change_set_set_int (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "y_bottom"),
+ change->y_bottom);
+
+ if (change->y_centered_changed)
+ mateconf_change_set_set_bool (
+ queued_changes,
+ panel_profile_get_toplevel_key (toplevel, "y_centered"),
+ change->y_centered);
+ }
+
+ commit_timeout = panel_profile_get_commit_timeout (G_OBJECT (toplevel));
+ if (!commit_timeout) {
+ commit_timeout =
+ g_timeout_add (500,
+ (GSourceFunc) panel_profile_commit_toplevel_changes,
+ toplevel);
+ panel_profile_set_commit_timeout (toplevel, commit_timeout);
+ }
+}
+
+#define TOPLEVEL_LOCATION_CHANGED_HANDLER(c) \
+ static void \
+ panel_profile_toplevel_##c##_changed (PanelToplevel *toplevel) \
+ { \
+ ToplevelLocationChange change = { NULL }; \
+ change.c##_changed = TRUE; \
+ change.c = panel_toplevel_get_##c (toplevel); \
+ panel_profile_queue_toplevel_location_change (toplevel, &change); \
+ }
+
+TOPLEVEL_LOCATION_CHANGED_HANDLER(monitor)
+TOPLEVEL_LOCATION_CHANGED_HANDLER(size)
+TOPLEVEL_LOCATION_CHANGED_HANDLER(orientation)
+TOPLEVEL_LOCATION_CHANGED_HANDLER(x_centered)
+TOPLEVEL_LOCATION_CHANGED_HANDLER(y_centered)
+
+#define TOPLEVEL_POSITION_CHANGED_HANDLER(c) \
+ static void \
+ panel_profile_toplevel_##c##_changed (PanelToplevel *toplevel) \
+ { \
+ ToplevelLocationChange change = { NULL }; \
+ int x, y, x_right, y_bottom; \
+ change.c##_changed = TRUE; \
+ panel_toplevel_get_position (toplevel, \
+ &x, &x_right, \
+ &y, &y_bottom); \
+ change.c = c; \
+ panel_profile_queue_toplevel_location_change (toplevel, &change); \
+ }
+
+TOPLEVEL_POSITION_CHANGED_HANDLER(x)
+TOPLEVEL_POSITION_CHANGED_HANDLER(x_right)
+TOPLEVEL_POSITION_CHANGED_HANDLER(y)
+TOPLEVEL_POSITION_CHANGED_HANDLER(y_bottom)
+
+static void
+panel_profile_toplevel_screen_changed (PanelToplevel *toplevel)
+{
+ ToplevelLocationChange change = { NULL };
+
+ change.screen_changed = TRUE;
+ change.screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+
+ panel_profile_queue_toplevel_location_change (toplevel, &change);
+}
+
+static void
+panel_profile_connect_to_toplevel (PanelToplevel *toplevel)
+{
+ g_signal_connect (toplevel, "notify::screen",
+ G_CALLBACK (panel_profile_toplevel_screen_changed), NULL);
+ g_signal_connect (toplevel, "notify::monitor",
+ G_CALLBACK (panel_profile_toplevel_monitor_changed), NULL);
+ g_signal_connect (toplevel, "notify::size",
+ G_CALLBACK (panel_profile_toplevel_size_changed), NULL);
+ g_signal_connect (toplevel, "notify::x",
+ G_CALLBACK (panel_profile_toplevel_x_changed), NULL);
+ g_signal_connect (toplevel, "notify::x-right",
+ G_CALLBACK (panel_profile_toplevel_x_right_changed), NULL);
+ g_signal_connect (toplevel, "notify::x-centered",
+ G_CALLBACK (panel_profile_toplevel_x_centered_changed), NULL);
+ g_signal_connect (toplevel, "notify::y",
+ G_CALLBACK (panel_profile_toplevel_y_changed), NULL);
+ g_signal_connect (toplevel, "notify::y-bottom",
+ G_CALLBACK (panel_profile_toplevel_y_bottom_changed), NULL);
+ g_signal_connect (toplevel, "notify::y-centered",
+ G_CALLBACK (panel_profile_toplevel_y_centered_changed), NULL);
+ g_signal_connect (toplevel, "notify::orientation",
+ G_CALLBACK (panel_profile_toplevel_orientation_changed), NULL);
+}
+
+static void
+set_name_from_string (PanelToplevel *toplevel,
+ const char *str)
+{
+ if (!str)
+ return;
+
+ panel_toplevel_set_name (toplevel, str);
+}
+
+static void
+set_orientation_from_string (PanelToplevel *toplevel,
+ const char *str)
+{
+ PanelOrientation orientation;
+
+ if (!str || !panel_profile_map_orientation_string (str, &orientation))
+ return;
+
+ panel_toplevel_set_orientation (toplevel, orientation);
+}
+
+static void
+set_animation_speed_from_string (PanelToplevel *toplevel,
+ const char *str)
+{
+ PanelAnimationSpeed animation_speed;
+
+ if (!str || !panel_profile_map_speed_string (str, &animation_speed))
+ return;
+
+ panel_toplevel_set_animation_speed (toplevel, animation_speed);
+}
+
+static void
+panel_profile_toplevel_change_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelToplevel *toplevel)
+{
+ MateConfValue *value;
+ const char *key;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+
+ if (!(value = mateconf_entry_get_value (entry)))
+ return;
+
+#define UPDATE_STRING(k, n) \
+ if (!strcmp (key, k)) { \
+ if (value->type == MATECONF_VALUE_STRING) \
+ set_##n##_from_string (toplevel, \
+ mateconf_value_get_string (value)); \
+ }
+
+#define UPDATE_INT(k, n) \
+ if (!strcmp (key, k)) { \
+ if (value->type == MATECONF_VALUE_INT) \
+ panel_toplevel_set_##n (toplevel, \
+ mateconf_value_get_int (value)); \
+ }
+
+#define UPDATE_BOOL(k, n) \
+ if (!strcmp (key, k)) { \
+ if (value->type == MATECONF_VALUE_BOOL) \
+ panel_toplevel_set_##n (toplevel, \
+ mateconf_value_get_bool (value)); \
+ }
+
+#define UPDATE_POS(k, n, n2) \
+ if (!strcmp (key, k)) { \
+ if (value->type == MATECONF_VALUE_INT) { \
+ int x, x_right, y, y_bottom; \
+ panel_toplevel_get_position (toplevel, &x, &x_right, \
+ &y, &y_bottom); \
+ panel_toplevel_set_##n ( \
+ toplevel, \
+ mateconf_value_get_int (value), \
+ n2, \
+ panel_toplevel_get_##n##_centered (toplevel)); \
+ } \
+ }
+
+#define UPDATE_POS2(k, n, n2) \
+ if (!strcmp (key, k)) { \
+ if (value->type == MATECONF_VALUE_INT) { \
+ int x, x_right, y, y_bottom; \
+ panel_toplevel_get_position (toplevel, &x, &x_right, \
+ &y, &y_bottom); \
+ panel_toplevel_set_##n ( \
+ toplevel, \
+ n, \
+ mateconf_value_get_int (value), \
+ panel_toplevel_get_##n##_centered (toplevel)); \
+ } \
+ }
+
+#define UPDATE_CENTERED(k, n, n2) \
+ if (!strcmp (key, k)) { \
+ if (value->type == MATECONF_VALUE_BOOL) { \
+ int x, x_right, y, y_bottom; \
+ panel_toplevel_get_position (toplevel, &x, &x_right, \
+ &y, &y_bottom); \
+ panel_toplevel_set_##n ( \
+ toplevel, n, n2, mateconf_value_get_bool (value)); \
+ } \
+ }
+
+ if (!strcmp (key, "screen")) {
+ if (value->type == MATECONF_VALUE_INT) {
+ GdkScreen *screen;
+
+ screen = gdk_display_get_screen (
+ gdk_display_get_default (),
+ mateconf_value_get_int (value));
+ if (screen)
+ gtk_window_set_screen (GTK_WINDOW (toplevel), screen);
+ else
+ /* Make sure to set the key back to an actual
+ * available screen so it will get loaded on
+ * next startup.
+ */
+ panel_profile_toplevel_screen_changed (toplevel);
+ }
+
+ }
+ else UPDATE_INT ("monitor", monitor)
+ else UPDATE_STRING ("name", name)
+ else UPDATE_BOOL ("expand", expand)
+ else UPDATE_STRING ("orientation", orientation)
+ else UPDATE_INT ("size", size)
+ else UPDATE_POS ("x", x, x_right)
+ else UPDATE_POS ("y", y, y_bottom)
+ else UPDATE_POS2 ("x_right", x, x_right)
+ else UPDATE_POS2 ("y_bottom", y, y_bottom)
+ else UPDATE_CENTERED ("x_centered", x, x_right)
+ else UPDATE_CENTERED ("y_centered", y, y_bottom)
+ else UPDATE_BOOL ("auto_hide", auto_hide)
+ else UPDATE_BOOL ("enable_animations", animate)
+ else UPDATE_BOOL ("enable_buttons", enable_buttons)
+ else UPDATE_BOOL ("enable_arrows", enable_arrows)
+ else UPDATE_INT ("hide_delay", hide_delay)
+ else UPDATE_INT ("unhide_delay", unhide_delay)
+ else UPDATE_INT ("auto_hide_size", auto_hide_size)
+ else UPDATE_STRING ("animation_speed", animation_speed)
+}
+
+static void
+panel_profile_background_change_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelToplevel *toplevel)
+{
+ PanelWidget *panel_widget;
+ PanelBackground *background;
+ MateConfValue *value;
+ const char *key;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+
+ if (!(value = mateconf_entry_get_value (entry)))
+ return;
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+ background = &panel_widget->background;
+
+ if (!strcmp (key, "type")) {
+ if (value->type == MATECONF_VALUE_STRING) {
+ PanelBackgroundType background_type;
+
+ if (panel_profile_map_background_type_string (
+ mateconf_value_get_string (value),
+ &background_type)) {
+ panel_background_set_type (background, background_type);
+ panel_toplevel_update_edges (toplevel);
+ }
+ }
+ } else if (!strcmp (key, "color")) {
+ if (value->type == MATECONF_VALUE_STRING) {
+ GdkColor gdk_color;
+ const char *str;
+
+ str = mateconf_value_get_string (value);
+
+ if (gdk_color_parse (str, &gdk_color))
+ panel_background_set_gdk_color (background, &gdk_color);
+ }
+ } else if (!strcmp (key, "opacity")) {
+ if (value->type == MATECONF_VALUE_INT)
+ panel_background_set_opacity (background,
+ mateconf_value_get_int (value));
+ } else if (!strcmp (key, "image")) {
+ if (value->type == MATECONF_VALUE_STRING)
+ panel_background_set_image (background,
+ mateconf_value_get_string (value));
+ } else if (!strcmp (key, "fit")) {
+ if (value->type == MATECONF_VALUE_BOOL)
+ panel_background_set_fit (background,
+ mateconf_value_get_bool (value));
+ } else if (!strcmp (key, "stretch")) {
+ if (value->type == MATECONF_VALUE_BOOL)
+ panel_background_set_stretch (background,
+ mateconf_value_get_bool (value));
+ } else if (!strcmp (key, "rotate")) {
+ if (value->type == MATECONF_VALUE_BOOL)
+ panel_background_set_rotate (background,
+ mateconf_value_get_bool (value));
+ }
+}
+
+static void
+panel_profile_disconnect_toplevel (PanelToplevel *toplevel,
+ gpointer data)
+{
+ MateConfClient *client;
+ guint notify_id = GPOINTER_TO_UINT (data);
+
+ client = panel_mateconf_get_client ();
+
+ mateconf_client_notify_remove (client, notify_id);
+}
+
+guint
+panel_profile_toplevel_notify_add (PanelToplevel *toplevel,
+ const char *key,
+ MateConfClientNotifyFunc func,
+ gpointer data)
+{
+ MateConfClient *client;
+ const char *tmp;
+ guint retval;
+
+ client = panel_mateconf_get_client ();
+
+ if (!key)
+ tmp = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/toplevels/%s",
+ panel_profile_get_toplevel_id (toplevel));
+ else
+ tmp = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/toplevels/%s/%s",
+ panel_profile_get_toplevel_id (toplevel),
+ key);
+
+ retval = mateconf_client_notify_add (client, tmp, func, data, NULL, NULL);
+
+ return retval;
+}
+
+static void
+panel_profile_save_id_list (PanelMateConfKeyType type,
+ GSList *list,
+ gboolean resave)
+{
+ MateConfClient *client;
+ const char *key;
+ const char *id_list;
+
+ g_assert (!(resave && list != NULL));
+
+ client = panel_mateconf_get_client ();
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ key = panel_mateconf_general_key (id_list);
+ if (resave)
+ list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+ else {
+ /* Make sure the elements in the list appear only once. We only
+ * do it when we save a list with new elements. */
+ list = panel_g_slist_make_unique (list,
+ (GCompareFunc) strcmp,
+ TRUE);
+ }
+
+ mateconf_client_set_list (client, key, MATECONF_VALUE_STRING, list, NULL);
+
+ g_slist_foreach (list, (GFunc) g_free, NULL);
+ g_slist_free (list);
+}
+
+static inline void
+panel_profile_save_other_id_lists (PanelMateConfKeyType type)
+{
+ if (type != PANEL_MATECONF_TOPLEVELS)
+ panel_profile_save_id_list (PANEL_MATECONF_TOPLEVELS, NULL, TRUE);
+
+ if (type != PANEL_MATECONF_OBJECTS)
+ panel_profile_save_id_list (PANEL_MATECONF_OBJECTS, NULL, TRUE);
+
+ if (type != PANEL_MATECONF_APPLETS)
+ panel_profile_save_id_list (PANEL_MATECONF_APPLETS, NULL, TRUE);
+}
+
+void
+panel_profile_add_to_list (PanelMateConfKeyType type,
+ const char *id)
+{
+ MateConfClient *client;
+ GSList *list;
+ const char *key;
+ const char *id_list;
+ char *new_id;
+
+ client = panel_mateconf_get_client ();
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ key = panel_mateconf_general_key (id_list);
+ list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ new_id = id ? g_strdup (id) : panel_profile_find_new_id (type);
+
+ list = g_slist_append (list, new_id);
+
+ panel_profile_save_id_list (type, list, FALSE);
+ panel_profile_save_other_id_lists (type);
+}
+
+void
+panel_profile_remove_from_list (PanelMateConfKeyType type,
+ const char *id)
+{
+ MateConfClient *client;
+ GSList *list, *l;
+ const char *key;
+ const char *id_list;
+
+ client = panel_mateconf_get_client ();
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ key = panel_mateconf_general_key (id_list);
+ list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ /* Remove all occurrence of id and not just the first. We're more solid
+ * this way (see bug #137308 for example). */
+ l = list;
+ while (l) {
+ GSList *next;
+
+ next = l->next;
+
+ if (!strcmp (id, l->data)) {
+ g_free (l->data);
+ list = g_slist_delete_link (list, l);
+ }
+
+ l = next;
+ }
+
+ panel_profile_save_id_list (type, list, FALSE);
+ panel_profile_save_other_id_lists (type);
+}
+
+static gboolean
+panel_profile_id_list_is_writable (PanelMateConfKeyType type)
+{
+ MateConfClient *client;
+ const char *key;
+ const char *id_list;
+
+ client = panel_mateconf_get_client ();
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ key = panel_mateconf_general_key (id_list);
+ return mateconf_client_key_is_writable (client, key, NULL);
+}
+
+gboolean
+panel_profile_id_lists_are_writable (void)
+{
+ return
+ panel_profile_id_list_is_writable (PANEL_MATECONF_TOPLEVELS) &&
+ panel_profile_id_list_is_writable (PANEL_MATECONF_APPLETS) &&
+ panel_profile_id_list_is_writable (PANEL_MATECONF_OBJECTS);
+}
+
+static gboolean
+panel_profile_find_empty_spot (GdkScreen *screen,
+ PanelOrientation *orientation,
+ int *monitor)
+{
+ GSList *li;
+ int i;
+ int *filled_spots;
+ gboolean found_a_spot = FALSE;
+
+ *monitor = 0;
+ *orientation = PANEL_ORIENTATION_TOP;
+
+ filled_spots = g_new0 (int, panel_multiscreen_monitors (screen));
+
+ for (li = panel_toplevel_list_toplevels (); li != NULL; li = li->next) {
+ PanelToplevel *toplevel = li->data;
+ GdkScreen *toplevel_screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+ int toplevel_monitor = panel_toplevel_get_monitor (toplevel);
+
+ if (toplevel_screen != screen ||
+ panel_toplevel_get_is_attached (toplevel) ||
+ toplevel_monitor < 0)
+ continue;
+
+ filled_spots[toplevel_monitor] |= panel_toplevel_get_orientation (toplevel);
+ }
+
+ for (i = 0; i < panel_multiscreen_monitors (screen); i++) {
+ /* These are ordered based on "priority" of the
+ orientation when picking it */
+ if ( ! (filled_spots[i] & PANEL_ORIENTATION_TOP)) {
+ *orientation = PANEL_ORIENTATION_TOP;
+ *monitor = i;
+ found_a_spot = TRUE;
+ break;
+ } else if ( ! (filled_spots[i] & PANEL_ORIENTATION_BOTTOM)) {
+ *orientation = PANEL_ORIENTATION_BOTTOM;
+ *monitor = i;
+ found_a_spot = TRUE;
+ break;
+ } else if ( ! (filled_spots[i] & PANEL_ORIENTATION_RIGHT)) {
+ *orientation = PANEL_ORIENTATION_RIGHT;
+ *monitor = i;
+ found_a_spot = TRUE;
+ break;
+ } else if ( ! (filled_spots[i] & PANEL_ORIENTATION_LEFT)) {
+ *orientation = PANEL_ORIENTATION_LEFT;
+ *monitor = i;
+ found_a_spot = TRUE;
+ break;
+ }
+ }
+
+ g_free (filled_spots);
+
+ return found_a_spot;
+}
+
+void
+panel_profile_create_toplevel (GdkScreen *screen)
+{
+ MateConfClient *client;
+ const char *key;
+ char *id;
+ char *dir;
+ PanelOrientation orientation;
+ int monitor;
+
+ g_return_if_fail (screen != NULL);
+
+ client = panel_mateconf_get_client ();
+
+ id = panel_profile_find_new_id (PANEL_MATECONF_TOPLEVELS);
+
+ dir = g_strdup_printf (PANEL_CONFIG_DIR "/toplevels/%s", id);
+ panel_mateconf_associate_schemas_in_dir (client, dir, PANEL_SCHEMAS_DIR "/toplevels");
+ g_free (dir);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS, id, "screen");
+ mateconf_client_set_int (client, key, gdk_screen_get_number (screen), NULL);
+
+ if (panel_profile_find_empty_spot (screen, &orientation, &monitor)) {
+ key = panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS, id, "monitor");
+ mateconf_client_set_int (client, key, monitor, NULL);
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS, id, "orientation");
+ mateconf_client_set_string (client, key, panel_profile_map_orientation (orientation), NULL);
+ }
+
+ panel_profile_add_to_list (PANEL_MATECONF_TOPLEVELS, id);
+
+ g_free (id);
+}
+
+static void
+panel_profile_delete_toplevel_objects (const char *toplevel_id,
+ PanelMateConfKeyType key_type)
+{
+ MateConfClient *client;
+ const char *key;
+ GSList *new_list = NULL,*list, *l;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_general_key (panel_mateconf_key_type_to_id_list (key_type));
+ list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ for (l = list; l; l = l->next) {
+ char *id = l->data;
+ char *parent_toplevel_id;
+
+ key = panel_mateconf_full_key (key_type, id, "toplevel_id");
+ parent_toplevel_id = mateconf_client_get_string (client, key, NULL);
+
+ if (parent_toplevel_id && !strcmp (toplevel_id, parent_toplevel_id)) {
+ g_free (id);
+ g_free (parent_toplevel_id);
+ continue;
+ }
+
+ new_list = g_slist_prepend (new_list, id);
+
+ g_free (parent_toplevel_id);
+ }
+ g_slist_free (list);
+
+ key = panel_mateconf_general_key (panel_mateconf_key_type_to_id_list (key_type));
+ mateconf_client_set_list (client, key, MATECONF_VALUE_STRING, new_list, NULL);
+
+ for (l = new_list; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (new_list);
+}
+
+void
+panel_profile_delete_toplevel (PanelToplevel *toplevel)
+{
+ const char *toplevel_id;
+
+ toplevel_id = panel_profile_get_toplevel_id (toplevel);
+
+ panel_profile_delete_toplevel_objects (toplevel_id, PANEL_MATECONF_OBJECTS);
+ panel_profile_delete_toplevel_objects (toplevel_id, PANEL_MATECONF_APPLETS);
+
+ panel_profile_remove_from_list (PANEL_MATECONF_TOPLEVELS, toplevel_id);
+}
+
+static GdkScreen *
+get_toplevel_screen (MateConfClient *client,
+ const char *toplevel_dir)
+{
+ GError *error = NULL;
+ GdkDisplay *display;
+ const char *key;
+ int screen_n;
+
+ key = panel_mateconf_sprintf ("%s/screen", toplevel_dir);
+ screen_n = mateconf_client_get_int (client, key, &error);
+ if (error) {
+ g_warning (_("Error reading MateConf integer value '%s': %s"),
+ key, error->message);
+ g_error_free (error);
+ return gdk_screen_get_default ();
+ }
+
+ display = gdk_display_get_default ();
+
+ if (screen_n < 0 || screen_n >= gdk_display_get_n_screens (display)) {
+#if 0
+ g_warning (_("Panel '%s' is set to be displayed on screen %d which "
+ "is not currently available. Not loading this panel."),
+ toplevel_dir, screen_n);
+#endif
+ return NULL;
+ }
+
+ return gdk_display_get_screen (display, screen_n);
+}
+
+PanelToplevel *
+panel_profile_load_toplevel (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ const char *toplevel_id)
+{
+ PanelToplevel *toplevel;
+ GdkScreen *screen;
+ GError *error;
+ const char *key;
+ char *toplevel_dir;
+ guint notify_id;
+
+ if (!toplevel_id || !toplevel_id [0])
+ return NULL;
+
+ toplevel_dir = g_strdup_printf ("%s/toplevels/%s", profile_dir, toplevel_id);
+
+ if (!mateconf_client_dir_exists (client, toplevel_dir, NULL))
+ panel_mateconf_associate_schemas_in_dir (
+ client, toplevel_dir, PANEL_SCHEMAS_DIR "/toplevels");
+
+ mateconf_client_add_dir (client,
+ toplevel_dir,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ key = panel_mateconf_sprintf ("%s/background", toplevel_dir);
+ mateconf_client_add_dir (client,
+ key,
+ MATECONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ if (!(screen = get_toplevel_screen (client, toplevel_dir))) {
+ mateconf_client_remove_dir (client, key, NULL);
+ mateconf_client_remove_dir (client, toplevel_dir, NULL);
+ g_free (toplevel_dir);
+ return NULL;
+ }
+
+ toplevel = g_object_new (PANEL_TYPE_TOPLEVEL,
+ "screen", screen,
+ NULL);
+
+#define GET_INT(k, fn) \
+ { \
+ int val; \
+ error = NULL; \
+ key = panel_mateconf_sprintf ("%s/" k, toplevel_dir); \
+ val = mateconf_client_get_int (client, key, &error); \
+ if (!error) \
+ panel_toplevel_set_##fn (toplevel, val); \
+ else { \
+ g_warning (_("Error reading MateConf integer value '%s': %s"), \
+ key, error->message); \
+ g_error_free (error); \
+ } \
+ }
+
+#define GET_BOOL(k, fn) \
+ { \
+ gboolean val; \
+ error = NULL; \
+ key = panel_mateconf_sprintf ("%s/" k, toplevel_dir); \
+ val = mateconf_client_get_bool (client, key, &error); \
+ if (!error) \
+ panel_toplevel_set_##fn (toplevel, val); \
+ else { \
+ g_warning (_("Error reading MateConf boolean value '%s': %s"), \
+ key, error->message); \
+ g_error_free (error); \
+ } \
+ }
+
+#define GET_STRING(k, fn) \
+ { \
+ char *val; \
+ error = NULL; \
+ key = panel_mateconf_sprintf ("%s/" k, toplevel_dir); \
+ val = mateconf_client_get_string (client, key, &error); \
+ if (!error && val) { \
+ set_##fn##_from_string (toplevel, val); \
+ g_free (val); \
+ } else if (error) { \
+ g_warning (_("Error reading MateConf string value '%s': %s"), \
+ key, error->message); \
+ g_error_free (error); \
+ } \
+ }
+
+ GET_STRING ("name", name);
+ GET_INT ("monitor", monitor);
+ GET_BOOL ("expand", expand);
+ GET_STRING ("orientation", orientation);
+ GET_INT ("size", size);
+ GET_BOOL ("auto_hide", auto_hide);
+ GET_BOOL ("enable_animations", animate);
+ GET_BOOL ("enable_buttons", enable_buttons);
+ GET_BOOL ("enable_arrows", enable_arrows);
+ GET_INT ("hide_delay", hide_delay);
+ GET_INT ("unhide_delay", unhide_delay);
+ GET_INT ("auto_hide_size", auto_hide_size);
+ GET_STRING ("animation_speed", animation_speed);
+
+#define GET_POSITION(a, b, c, fn) \
+ { \
+ gboolean centered; \
+ int position; \
+ int position2; \
+ key = panel_mateconf_sprintf ("%s/" c, toplevel_dir); \
+ centered = mateconf_client_get_bool (client, key, &error); \
+ if (!error) { \
+ key = panel_mateconf_sprintf ("%s/" a, toplevel_dir); \
+ position = mateconf_client_get_int (client, key, &error); \
+ } \
+ if (!error) { \
+ MateConfValue *value; \
+ key = panel_mateconf_sprintf ("%s/" b, toplevel_dir); \
+ /* we need to do this since the key was added in 2.19 and \
+ * the default value returned when the key is not set \
+ * (for people coming from older versions) is 0, which \
+ * is not what we want. */ \
+ value = mateconf_client_get_without_default (client, key, &error);\
+ if (value && value->type == MATECONF_VALUE_INT) \
+ position2 = mateconf_value_get_int (value); \
+ else \
+ position2 = -1; \
+ \
+ if (value) \
+ mateconf_value_free (value); \
+ } \
+ if (!error) \
+ panel_toplevel_set_##fn (toplevel, position, position2, \
+ centered); \
+ else { \
+ g_warning (_("Error reading MateConf integer value '%s': %s"), \
+ key, error->message); \
+ g_error_free (error); \
+ } \
+ }
+
+ GET_POSITION ("x", "x_right", "x_centered", x);
+ GET_POSITION ("y", "y_bottom", "y_centered", y);
+
+ panel_profile_load_background (toplevel, client, toplevel_dir);
+
+ panel_profile_set_toplevel_id (toplevel, toplevel_id);
+
+ panel_profile_connect_to_toplevel (toplevel);
+
+ notify_id = panel_profile_toplevel_notify_add (
+ toplevel,
+ NULL,
+ (MateConfClientNotifyFunc) panel_profile_toplevel_change_notify,
+ toplevel);
+ g_signal_connect (toplevel, "destroy",
+ G_CALLBACK (panel_profile_disconnect_toplevel),
+ GUINT_TO_POINTER (notify_id));
+
+ notify_id = panel_profile_toplevel_notify_add (
+ toplevel,
+ "background",
+ (MateConfClientNotifyFunc) panel_profile_background_change_notify,
+ toplevel);
+ g_signal_connect (toplevel, "destroy",
+ G_CALLBACK (panel_profile_disconnect_toplevel),
+ GUINT_TO_POINTER (notify_id));
+
+ g_free (toplevel_dir);
+
+ panel_setup (toplevel);
+
+ return toplevel;
+}
+
+static void
+panel_profile_load_and_show_toplevel (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ const char *toplevel_id)
+{
+ PanelToplevel *toplevel;
+ const char *id_list;
+ const char *key;
+ MateConfValue *value;
+ gboolean loading_queued_applets;
+
+ toplevel = panel_profile_load_toplevel (client, profile_dir, type, toplevel_id);
+ if (!toplevel)
+ return;
+
+ gtk_widget_show (GTK_WIDGET (toplevel));
+
+ loading_queued_applets = FALSE;
+
+ /* reload list of objects to get those that might be on the new
+ * toplevel */
+ id_list = panel_mateconf_key_type_to_id_list (PANEL_MATECONF_OBJECTS);
+ key = panel_mateconf_sprintf ("%s/general/%s", profile_dir, id_list);
+ value = mateconf_client_get (client, key, NULL);
+ if (value) {
+ panel_profile_object_id_list_update (client, value,
+ PANEL_MATECONF_OBJECTS);
+ loading_queued_applets = TRUE;
+ mateconf_value_free (value);
+ }
+
+ id_list = panel_mateconf_key_type_to_id_list (PANEL_MATECONF_APPLETS);
+ key = panel_mateconf_sprintf ("%s/general/%s", profile_dir, id_list);
+ value = mateconf_client_get (client, key, NULL);
+ if (value) {
+ panel_profile_object_id_list_update (client, value,
+ PANEL_MATECONF_APPLETS);
+ loading_queued_applets = TRUE;
+ mateconf_value_free (value);
+ }
+
+ if (!loading_queued_applets)
+ mate_panel_applet_load_queued_applets (FALSE);
+}
+
+static void
+panel_profile_load_and_show_toplevel_startup (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ const char *toplevel_id)
+{
+ PanelToplevel *toplevel;
+
+ toplevel = panel_profile_load_toplevel (client, profile_dir, type, toplevel_id);
+ if (toplevel)
+ gtk_widget_show (GTK_WIDGET (toplevel));
+}
+
+static void
+panel_profile_destroy_toplevel (const char *id)
+{
+ PanelToplevel *toplevel;
+
+ if (!(toplevel = panel_profile_get_toplevel_by_id (id)))
+ return;
+
+ gtk_widget_destroy (GTK_WIDGET (toplevel));
+}
+
+char *
+panel_profile_prepare_object_with_id (PanelObjectType object_type,
+ const char *toplevel_id,
+ int position,
+ gboolean right_stick)
+{
+ PanelMateConfKeyType key_type;
+ MateConfClient *client;
+ const char *key;
+ char *id;
+ char *dir;
+
+ key_type = (object_type == PANEL_OBJECT_APPLET) ? PANEL_MATECONF_APPLETS : PANEL_MATECONF_OBJECTS;
+
+ client = panel_mateconf_get_client ();
+
+ id = panel_profile_find_new_id (key_type);
+
+ dir = g_strdup_printf (PANEL_CONFIG_DIR "/%s/%s",
+ (key_type == PANEL_MATECONF_APPLETS) ? "applets" : "objects",
+ id);
+ panel_mateconf_associate_schemas_in_dir (client, dir, PANEL_SCHEMAS_DIR "/objects");
+
+ key = panel_mateconf_full_key (key_type, id, "object_type");
+ mateconf_client_set_string (client,
+ key,
+ mateconf_enum_to_string (panel_object_type_map, object_type),
+ NULL);
+
+ key = panel_mateconf_full_key (key_type, id, "toplevel_id");
+ mateconf_client_set_string (client, key, toplevel_id, NULL);
+
+ key = panel_mateconf_full_key (key_type, id, "position");
+ mateconf_client_set_int (client, key, position, NULL);
+
+ key = panel_mateconf_full_key (key_type, id, "panel_right_stick");
+ mateconf_client_set_bool (client, key, right_stick, NULL);
+
+ g_free (dir);
+
+ return id;
+}
+
+char *
+panel_profile_prepare_object (PanelObjectType object_type,
+ PanelToplevel *toplevel,
+ int position,
+ gboolean right_stick)
+{
+ return panel_profile_prepare_object_with_id (object_type,
+ panel_profile_get_toplevel_id (toplevel),
+ position,
+ right_stick);
+}
+
+void
+panel_profile_delete_object (AppletInfo *applet_info)
+{
+ PanelMateConfKeyType type;
+ const char *id;
+
+ type = (applet_info->type) == PANEL_OBJECT_APPLET ? PANEL_MATECONF_APPLETS :
+ PANEL_MATECONF_OBJECTS;
+ id = mate_panel_applet_get_id (applet_info);
+
+ panel_profile_remove_from_list (type, id);
+}
+
+static void
+panel_profile_load_object (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ const char *id)
+{
+ PanelObjectType object_type;
+ char *object_dir;
+ const char *key;
+ char *type_string;
+ char *toplevel_id;
+ int position;
+ gboolean right_stick;
+ gboolean locked;
+
+ object_dir = g_strdup_printf ("%s/%s/%s",
+ profile_dir,
+ type == PANEL_MATECONF_OBJECTS ? "objects" : "applets",
+ id);
+
+ mateconf_client_add_dir (client, object_dir, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ key = panel_mateconf_sprintf ("%s/object_type", object_dir);
+ type_string = mateconf_client_get_string (client, key, NULL);
+
+ if (!panel_profile_map_object_type_string (type_string, &object_type)) {
+ g_free (type_string);
+ mateconf_client_remove_dir (client, object_dir, NULL);
+ g_free (object_dir);
+ return;
+ }
+
+ key = panel_mateconf_sprintf ("%s/position", object_dir);
+ position = mateconf_client_get_int (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/toplevel_id", object_dir);
+ toplevel_id = mateconf_client_get_string (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/panel_right_stick", object_dir);
+ right_stick = mateconf_client_get_bool (client, key, NULL);
+
+ key = panel_mateconf_sprintf ("%s/locked", object_dir);
+ locked = mateconf_client_get_bool (client, key, NULL);
+
+ mate_panel_applet_queue_applet_to_load (id,
+ object_type,
+ toplevel_id,
+ position,
+ right_stick,
+ locked);
+
+ g_free (toplevel_id);
+ g_free (type_string);
+ g_free (object_dir);
+}
+
+static void
+panel_profile_destroy_object (const char *id)
+{
+ AppletInfo *info;
+
+ info = mate_panel_applet_get_by_id (id);
+
+ mate_panel_applet_clean (info);
+}
+
+static void
+panel_profile_delete_dir (MateConfClient *client,
+ PanelMateConfKeyType type,
+ const char *id)
+{
+ const char *key;
+ char *type_str;
+
+ switch (type) {
+ case PANEL_MATECONF_TOPLEVELS:
+ type_str = "toplevels";
+ break;
+ case PANEL_MATECONF_OBJECTS:
+ type_str = "objects";
+ break;
+ case PANEL_MATECONF_APPLETS:
+ type_str = "applets";
+ break;
+ default:
+ type_str = NULL;
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (type == PANEL_MATECONF_TOPLEVELS) {
+ key = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/%s/%s/background",
+ type_str, id);
+ mateconf_client_remove_dir (client, key, NULL);
+ }
+
+ key = panel_mateconf_sprintf (PANEL_CONFIG_DIR "/%s/%s",
+ type_str, id);
+ mateconf_client_remove_dir (client, key, NULL);
+
+ mateconf_client_recursive_unset (client,
+ key,
+ MATECONF_UNSET_INCLUDING_SCHEMA_NAMES,
+ NULL);
+}
+
+static gboolean
+panel_profile_object_exists (GSList *list,
+ const char *id,
+ PanelProfileGetIdFunc get_id_func)
+{
+ GSList *l;
+
+ if (!list || !id)
+ return FALSE;
+
+ for (l = list; l; l = l->next) {
+ const char *check_id;
+
+ check_id = get_id_func (l->data);
+ g_assert (check_id != NULL);
+
+ if (!strcmp (check_id, id))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+panel_profile_id_exists (GSList *id_list,
+ const char *id)
+{
+ GSList *l;
+
+ if (!id_list || !id)
+ return FALSE;
+
+ for (l = id_list; l; l = l->next) {
+ const char *check_id = mateconf_value_get_string (l->data);
+
+ if (!strcmp (id, check_id))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+panel_profile_load_added_ids (MateConfClient *client,
+ PanelMateConfKeyType type,
+ GSList *list,
+ GSList *id_list,
+ PanelProfileGetIdFunc get_id_func,
+ PanelProfileLoadFunc load_handler,
+ PanelProfileOnLoadQueue on_load_queue)
+{
+ GSList *added_ids = NULL;
+ GSList *l;
+
+ for (l = id_list; l; l = l->next) {
+ const char *id = mateconf_value_get_string (l->data);
+
+ if (!panel_profile_object_exists (list, id, get_id_func) &&
+ (on_load_queue == NULL || !on_load_queue (id)))
+ added_ids = g_slist_prepend (added_ids, g_strdup (id));
+ }
+
+ for (l = added_ids; l; l = l->next) {
+ char *id;
+ id = (char *) l->data;
+
+ if (id && id[0])
+ load_handler (client, PANEL_CONFIG_DIR, type, id);
+
+ g_free (l->data);
+ l->data = NULL;
+ }
+
+ g_slist_free (added_ids);
+}
+
+static void
+panel_profile_delete_removed_ids (MateConfClient *client,
+ PanelMateConfKeyType type,
+ GSList *list,
+ GSList *id_list,
+ PanelProfileGetIdFunc get_id_func,
+ PanelProfileDestroyFunc destroy_handler)
+{
+ GSList *removed_ids = NULL;
+ GSList *l;
+
+ for (l = list; l; l = l->next) {
+ const char *id;
+
+ id = get_id_func (l->data);
+
+ if (!panel_profile_id_exists (id_list, id))
+ removed_ids = g_slist_prepend (removed_ids, g_strdup (id));
+ }
+
+ for (l = removed_ids; l; l = l->next) {
+ const char *id = l->data;
+
+ panel_profile_delete_dir (client, type, id);
+ destroy_handler (id);
+
+ g_free (l->data);
+ l->data = NULL;
+ }
+ g_slist_free (removed_ids);
+}
+
+static void
+panel_profile_toplevel_id_list_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry)
+{
+ MateConfValue *value;
+ GSList *l, *existing_toplevels;
+ GSList *toplevel_ids;
+
+ if (!(value = mateconf_entry_get_value (entry)))
+ return;
+
+ if (value->type != MATECONF_VALUE_LIST ||
+ mateconf_value_get_list_type (value) != MATECONF_VALUE_STRING) {
+ mateconf_value_free (value);
+ return;
+ }
+
+ toplevel_ids = g_slist_copy (mateconf_value_get_list (value));
+ toplevel_ids = panel_g_slist_make_unique (toplevel_ids,
+ panel_mateconf_value_strcmp,
+ FALSE);
+
+ existing_toplevels = NULL;
+ for (l = panel_toplevel_list_toplevels (); l; l = l->next) {
+ PanelToplevel *toplevel = l->data;
+
+ /* Attached toplevels aren't on the id list */
+ if (panel_toplevel_get_is_attached (toplevel))
+ continue;
+
+ existing_toplevels = g_slist_prepend (existing_toplevels, toplevel);
+ }
+
+ panel_profile_load_added_ids (client,
+ PANEL_MATECONF_TOPLEVELS,
+ existing_toplevels,
+ toplevel_ids,
+ (PanelProfileGetIdFunc) panel_profile_get_toplevel_id,
+ (PanelProfileLoadFunc) panel_profile_load_and_show_toplevel,
+ (PanelProfileOnLoadQueue) NULL);
+
+ panel_profile_delete_removed_ids (client,
+ PANEL_MATECONF_TOPLEVELS,
+ existing_toplevels,
+ toplevel_ids,
+ (PanelProfileGetIdFunc) panel_profile_get_toplevel_id,
+ (PanelProfileDestroyFunc) panel_profile_destroy_toplevel);
+
+ g_slist_free (existing_toplevels);
+ g_slist_free (toplevel_ids);
+}
+
+static void
+panel_profile_object_id_list_update (MateConfClient *client,
+ MateConfValue *value,
+ PanelMateConfKeyType type)
+{
+ GSList *existing_applets;
+ GSList *sublist = NULL, *l;
+ GSList *object_ids;
+
+ if (value->type != MATECONF_VALUE_LIST ||
+ mateconf_value_get_list_type (value) != MATECONF_VALUE_STRING) {
+ mateconf_value_free (value);
+ return;
+ }
+
+ object_ids = g_slist_copy (mateconf_value_get_list (value));
+ object_ids = panel_g_slist_make_unique (object_ids,
+ panel_mateconf_value_strcmp,
+ FALSE);
+
+ existing_applets = mate_panel_applet_list_applets ();
+
+ for (l = existing_applets; l; l = l->next) {
+ AppletInfo *info = l->data;
+
+ if ((type == PANEL_MATECONF_APPLETS && info->type == PANEL_OBJECT_APPLET) ||
+ (type == PANEL_MATECONF_OBJECTS && info->type != PANEL_OBJECT_APPLET))
+ sublist = g_slist_prepend (sublist, info);
+ }
+
+ panel_profile_load_added_ids (client,
+ type,
+ sublist,
+ object_ids,
+ (PanelProfileGetIdFunc) mate_panel_applet_get_id,
+ (PanelProfileLoadFunc) panel_profile_load_object,
+ (PanelProfileOnLoadQueue) mate_panel_applet_on_load_queue);
+
+ panel_profile_delete_removed_ids (client,
+ type,
+ sublist,
+ object_ids,
+ (PanelProfileGetIdFunc) mate_panel_applet_get_id,
+ (PanelProfileDestroyFunc) panel_profile_destroy_object);
+
+ g_slist_free (sublist);
+ g_slist_free (object_ids);
+
+ mate_panel_applet_load_queued_applets (FALSE);
+}
+
+static void
+panel_profile_object_id_list_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ MateConfValue *value;
+ PanelMateConfKeyType type = GPOINTER_TO_INT (data);
+
+ if (!(value = mateconf_entry_get_value (entry)))
+ return;
+
+ panel_profile_object_id_list_update (client, value, type);
+}
+
+static void
+panel_profile_load_list (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ PanelProfileLoadFunc load_handler,
+ MateConfClientNotifyFunc notify_handler)
+{
+
+ const char *key;
+ GSList *list;
+ GSList *l;
+ const char *id_list;
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ key = panel_mateconf_sprintf ("%s/general/%s", profile_dir, id_list);
+
+ mateconf_client_notify_add (client, key, notify_handler,
+ GINT_TO_POINTER (type),
+ NULL, NULL);
+
+ list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+ list = panel_g_slist_make_unique (list,
+ (GCompareFunc) strcmp,
+ TRUE);
+
+ for (l = list; l; l = l->next) {
+ char *id;
+ id = (char *) l->data;
+
+ if (id && id[0])
+ load_handler (client, profile_dir, type, id);
+
+ g_free (l->data);
+ l->data = NULL;
+ }
+ g_slist_free (list);
+}
+
+static GSList *
+panel_profile_copy_defaults_for_screen (MateConfClient *client,
+ const char *profile_dir,
+ int screen_n,
+ PanelMateConfKeyType type)
+{
+ GSList *default_ids, *l;
+ GSList *new_ids = NULL;
+ const char *key;
+ const char *id_list, *type_str;
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ switch (type) {
+ case PANEL_MATECONF_TOPLEVELS:
+ type_str = "toplevels";
+ break;
+ case PANEL_MATECONF_OBJECTS:
+ type_str = "objects";
+ break;
+ case PANEL_MATECONF_APPLETS:
+ type_str = "applets";
+ break;
+ default:
+ type_str = NULL;
+ g_assert_not_reached ();
+ break;
+ }
+
+ key = panel_mateconf_sprintf (PANEL_DEFAULTS_DIR "/general/%s", id_list);
+ default_ids = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ for (l = default_ids; l; l = l->next) {
+ char *default_id = l->data;
+ char *new_id;
+ char *src_dir;
+ char *dest_dir;
+
+ new_id = g_strdup_printf ("%s_screen%d", default_id, screen_n);
+
+ src_dir = g_strdup_printf (PANEL_DEFAULTS_DIR "/%s/%s", type_str, default_id);
+ dest_dir = g_strdup_printf ("%s/%s/%s", profile_dir, type_str, new_id);
+
+ panel_mateconf_copy_dir (client, src_dir, dest_dir);
+
+ new_ids = g_slist_prepend (new_ids, new_id);
+
+ g_free (src_dir);
+ g_free (dest_dir);
+ g_free (l->data);
+ }
+ g_slist_free (default_ids);
+
+ return new_ids;
+}
+
+static void
+panel_profile_append_new_ids (MateConfClient *client,
+ PanelMateConfKeyType type,
+ GSList *new_ids)
+{
+ GSList *list, *l;
+ const char *key;
+ const char *id_list;
+
+ id_list = panel_mateconf_key_type_to_id_list (type);
+
+ key = panel_mateconf_general_key (id_list);
+ list = mateconf_client_get_list (client, key, MATECONF_VALUE_STRING, NULL);
+
+ for (l = new_ids; l; l = l->next)
+ list = g_slist_append (list, l->data);
+
+ g_slist_free (new_ids);
+
+ mateconf_client_set_list (client, key, MATECONF_VALUE_STRING, list, NULL);
+
+ for (l = list; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (list);
+}
+
+static void
+panel_profile_copy_default_objects_for_screen (MateConfClient *client,
+ const char *profile_dir,
+ int screen_n,
+ PanelMateConfKeyType type)
+{
+ GSList *new_objects, *l, *next;
+
+ new_objects = panel_profile_copy_defaults_for_screen (client, profile_dir, screen_n, type);
+
+ for (l = new_objects; l; l = next) {
+ char *object_id = l->data;
+ const char *key;
+ char *toplevel_id;
+ char *new_toplevel_id;
+
+ next = l->next;
+
+ key = panel_mateconf_full_key (type, object_id, "toplevel_id");
+ toplevel_id = mateconf_client_get_string (client, key, NULL);
+ if (!toplevel_id) {
+ new_objects = g_slist_remove_link (new_objects, l);
+ g_free (l->data);
+ g_slist_free_1 (l);
+ continue;
+ }
+
+ new_toplevel_id = g_strdup_printf ("%s_screen%d", toplevel_id, screen_n);
+ mateconf_client_set_string (client, key, new_toplevel_id, NULL);
+
+ g_free (toplevel_id);
+ g_free (new_toplevel_id);
+ }
+
+ panel_profile_append_new_ids (client, type, new_objects);
+}
+
+/* FIXME:
+ * We might want to do something more sophisticated like hardcode
+ * the default panel setup as the fallback panels.
+ */
+static GSList *
+panel_profile_create_fallback_toplevel_list (MateConfClient *client,
+ const char *profile_dir)
+{
+ char *id;
+ char *dir;
+
+ id = panel_profile_find_new_id (PANEL_MATECONF_TOPLEVELS);
+
+ dir = g_strdup_printf ("%s/toplevels/%s", profile_dir, id);
+ panel_mateconf_associate_schemas_in_dir (client, dir, PANEL_SCHEMAS_DIR "/toplevels");
+ g_free (dir);
+
+ return g_slist_prepend (NULL, id);
+}
+
+static void
+panel_profile_load_defaults_on_screen (MateConfClient *client,
+ const char *profile_dir,
+ GdkScreen *screen)
+{
+ GSList *new_toplevels, *l;
+ int screen_n;
+
+ screen_n = gdk_screen_get_number (screen);
+
+ new_toplevels = panel_profile_copy_defaults_for_screen (
+ client, profile_dir, screen_n, PANEL_MATECONF_TOPLEVELS);
+ if (!new_toplevels) {
+ g_warning ("Failed to load default panel configuration. panel-default-setup.entries "
+ "hasn't been installed using mateconftool-2 --load ?\n");
+ new_toplevels = panel_profile_create_fallback_toplevel_list (client, profile_dir);
+ }
+
+ for (l = new_toplevels; l; l = l->next) {
+ char *toplevel_id = l->data;
+ const char *key;
+
+ key = panel_mateconf_full_key (PANEL_MATECONF_TOPLEVELS,
+ toplevel_id,
+ "screen");
+ mateconf_client_set_int (client, key, screen_n, NULL);
+ }
+
+ panel_profile_append_new_ids (client, PANEL_MATECONF_TOPLEVELS, new_toplevels);
+
+ panel_profile_copy_default_objects_for_screen (
+ client, profile_dir, screen_n, PANEL_MATECONF_OBJECTS);
+ panel_profile_copy_default_objects_for_screen (
+ client, profile_dir, screen_n, PANEL_MATECONF_APPLETS);
+}
+
+static void
+panel_profile_ensure_toplevel_per_screen (MateConfClient *client,
+ const char *profile_dir)
+{
+ GSList *toplevels;
+ GSList *empty_screens = NULL;
+ GSList *l;
+ GdkDisplay *display;
+ int n_screens, i;
+
+ toplevels = panel_toplevel_list_toplevels ();
+
+ 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);
+
+ for (l = toplevels; l; l = l->next)
+ if (gtk_window_get_screen (l->data) == screen)
+ break;
+
+ if (!l)
+ empty_screens = g_slist_prepend (empty_screens, screen);
+ }
+
+ for (l = empty_screens; l; l = l->next)
+ panel_profile_load_defaults_on_screen (client, profile_dir, l->data);
+
+ g_slist_free (empty_screens);
+}
+
+void
+panel_profile_load (void)
+{
+ MateConfClient *client;
+
+ client = panel_mateconf_get_client ();
+
+ mateconf_client_add_dir (client, PANEL_CONFIG_DIR "/general", MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ panel_compatibility_maybe_copy_old_config (client);
+
+ panel_compatibility_migrate_panel_id_list (client);
+
+ panel_profile_load_list (client,
+ PANEL_CONFIG_DIR,
+ PANEL_MATECONF_TOPLEVELS,
+ panel_profile_load_and_show_toplevel_startup,
+ (MateConfClientNotifyFunc) panel_profile_toplevel_id_list_notify);
+ panel_profile_load_list (client,
+ PANEL_CONFIG_DIR,
+ PANEL_MATECONF_OBJECTS,
+ panel_profile_load_object,
+ (MateConfClientNotifyFunc) panel_profile_object_id_list_notify);
+ panel_profile_load_list (client,
+ PANEL_CONFIG_DIR,
+ PANEL_MATECONF_APPLETS,
+ panel_profile_load_object,
+ (MateConfClientNotifyFunc) panel_profile_object_id_list_notify);
+
+ panel_profile_ensure_toplevel_per_screen (client, PANEL_CONFIG_DIR);
+
+ mate_panel_applet_load_queued_applets (TRUE);
+}
+
+static gboolean
+get_program_listing_setting (const char *setting)
+{
+ MateConfClient *client;
+ const char *key;
+ gboolean retval;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_general_key (setting);
+ retval = mateconf_client_get_bool (client, key, NULL);
+
+ return retval;
+}
+
+gboolean
+panel_profile_get_show_program_list (void)
+{
+ return get_program_listing_setting ("show_program_list");
+}
+
+gboolean
+panel_profile_get_enable_program_list (void)
+{
+ return get_program_listing_setting ("enable_program_list");
+}
+
+gboolean
+panel_profile_get_enable_autocompletion (void)
+{
+ return get_program_listing_setting ("enable_autocompletion");
+}
+
+void
+panel_profile_set_show_program_list (gboolean show_program_list)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_general_key ("show_program_list");
+ mateconf_client_set_bool (client, key, show_program_list, NULL);
+}
+
+gboolean
+panel_profile_is_writable_show_program_list (void)
+{
+ MateConfClient *client;
+ const char *key;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_mateconf_general_key ("show_program_list");
+ return mateconf_client_key_is_writable (client, key, NULL);
+}
+
+gboolean
+panel_profile_can_be_moved_freely (PanelToplevel *toplevel)
+{
+ const char *key;
+ MateConfClient *client;
+
+ if (panel_lockdown_get_locked_down () ||
+ !panel_profile_is_writable_toplevel_orientation (toplevel))
+ return FALSE;
+
+ client = panel_mateconf_get_client ();
+
+ key = panel_profile_get_toplevel_key (toplevel, "screen");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ key = panel_profile_get_toplevel_key (toplevel, "monitor");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ /* For expanded panels we don't really have to check
+ x and y */
+ if (panel_toplevel_get_expand (toplevel))
+ return TRUE;
+
+ key = panel_profile_get_toplevel_key (toplevel, "x");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+ key = panel_profile_get_toplevel_key (toplevel, "x_right");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+ key = panel_profile_get_toplevel_key (toplevel, "x_centered");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ key = panel_profile_get_toplevel_key (toplevel, "y");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+ key = panel_profile_get_toplevel_key (toplevel, "y_bottom");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+ key = panel_profile_get_toplevel_key (toplevel, "y_centered");
+ if (!mateconf_client_key_is_writable (client, key, NULL))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/mate-panel/panel-profile.h b/mate-panel/panel-profile.h
new file mode 100644
index 00000000..4191ef67
--- /dev/null
+++ b/mate-panel/panel-profile.h
@@ -0,0 +1,188 @@
+/*
+ * panel-profile.h:
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_PROFILE_H__
+#define __PANEL_PROFILE_H__
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <mateconf/mateconf-client.h>
+
+#include "panel-toplevel.h"
+#include "panel-enums.h"
+#include "panel-types.h"
+#include "applet.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_profile_load (void);
+
+const char *panel_profile_get_toplevel_id (PanelToplevel *toplevel);
+PanelToplevel *panel_profile_get_toplevel_by_id (const char *toplevel_id);
+char *panel_profile_find_new_id (PanelMateConfKeyType type);
+
+
+gboolean panel_profile_get_show_program_list (void);
+void panel_profile_set_show_program_list (gboolean show_program_list);
+gboolean panel_profile_is_writable_show_program_list (void);
+gboolean panel_profile_get_enable_program_list (void);
+gboolean panel_profile_get_enable_autocompletion (void);
+
+
+void panel_profile_add_to_list (PanelMateConfKeyType type,
+ const char *id);
+void panel_profile_remove_from_list (PanelMateConfKeyType type,
+ const char *id);
+gboolean panel_profile_id_lists_are_writable (void);
+void panel_profile_create_toplevel (GdkScreen *screen);
+PanelToplevel *panel_profile_load_toplevel (MateConfClient *client,
+ const char *profile_dir,
+ PanelMateConfKeyType type,
+ const char *toplevel_id);
+void panel_profile_delete_toplevel (PanelToplevel *toplevel);
+char *panel_profile_prepare_object (PanelObjectType object_type,
+ PanelToplevel *toplevel,
+ int position,
+ gboolean right_stick);
+char *panel_profile_prepare_object_with_id (PanelObjectType object_type,
+ const char *toplevel_id,
+ int position,
+ gboolean right_stick);
+void panel_profile_delete_object (AppletInfo *applet_info);
+
+
+void panel_profile_set_toplevel_name (PanelToplevel *toplevel,
+ const char *name);
+char *panel_profile_get_toplevel_name (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_name (PanelToplevel *toplevel);
+
+void panel_profile_set_toplevel_orientation (PanelToplevel *toplevel,
+ PanelOrientation orientation);
+PanelOrientation
+ panel_profile_get_toplevel_orientation (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_orientation (PanelToplevel *toplevel);
+
+void panel_profile_set_toplevel_size (PanelToplevel *toplevel,
+ int size);
+int panel_profile_get_toplevel_size (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_size (PanelToplevel *toplevel);
+
+void panel_profile_set_toplevel_expand (PanelToplevel *toplevel,
+ gboolean expand);
+gboolean panel_profile_get_toplevel_expand (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_expand (PanelToplevel *toplevel);
+
+void panel_profile_set_toplevel_auto_hide (PanelToplevel *toplevel,
+ gboolean auto_hide);
+gboolean panel_profile_get_toplevel_auto_hide (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_auto_hide (PanelToplevel *toplevel);
+
+void panel_profile_set_toplevel_enable_buttons (PanelToplevel *toplevel,
+ gboolean enable_buttons);
+gboolean panel_profile_get_toplevel_enable_buttons (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_enable_buttons (PanelToplevel *toplevel);
+
+void panel_profile_set_toplevel_enable_arrows (PanelToplevel *toplevel,
+ gboolean enable_arrows);
+gboolean panel_profile_get_toplevel_enable_arrows (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_toplevel_enable_arrows (PanelToplevel *toplevel);
+
+/* We don't set this in the panel, so there is no set accessor */
+void panel_profile_set_background_type (PanelToplevel *toplevel,
+ PanelBackgroundType background_type);
+PanelBackgroundType
+ panel_profile_get_background_type (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_background_type (PanelToplevel *toplevel);
+
+void panel_profile_set_background_color (PanelToplevel *toplevel,
+ PanelColor *color);
+void panel_profile_get_background_color (PanelToplevel *toplevel,
+ PanelColor *color);
+gboolean panel_profile_is_writable_background_color (PanelToplevel *toplevel);
+
+void panel_profile_set_background_gdk_color (PanelToplevel *toplevel,
+ GdkColor *gdk_color);
+void panel_profile_get_background_gdk_color (PanelToplevel *toplevel,
+ GdkColor *gdk_color);
+
+void panel_profile_set_background_opacity (PanelToplevel *toplevel,
+ guint16 opacity);
+guint16 panel_profile_get_background_opacity (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_background_opacity (PanelToplevel *toplevel);
+
+void panel_profile_set_background_image (PanelToplevel *toplevel,
+ const char *image);
+char *panel_profile_get_background_image (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_background_image (PanelToplevel *toplevel);
+
+void panel_profile_set_background_fit (PanelToplevel *toplevel,
+ gboolean fit);
+gboolean panel_profile_get_background_fit (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_background_fit (PanelToplevel *toplevel);
+
+void panel_profile_set_background_stretch (PanelToplevel *toplevel,
+ gboolean stretch);
+gboolean panel_profile_get_background_stretch (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_background_stretch (PanelToplevel *toplevel);
+
+void panel_profile_set_background_rotate (PanelToplevel *toplevel,
+ gboolean rotate);
+gboolean panel_profile_get_background_rotate (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_background_rotate (PanelToplevel *toplevel);
+
+void panel_profile_set_attached_custom_icon (PanelToplevel *toplevel,
+ const char *custom_icon);
+char *panel_profile_get_attached_custom_icon (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_attached_custom_icon (PanelToplevel *toplevel);
+void panel_profile_set_attached_tooltip (PanelToplevel *toplevel,
+ const char *custom_icon);
+char *panel_profile_get_attached_tooltip (PanelToplevel *toplevel);
+gboolean panel_profile_is_writable_attached_tooltip (PanelToplevel *toplevel);
+
+guint panel_profile_toplevel_notify_add (PanelToplevel *toplevel,
+ const char *key,
+ MateConfClientNotifyFunc func,
+ gpointer data);
+
+const char *panel_profile_map_orientation (PanelOrientation orientation);
+const char *panel_profile_map_background_type (PanelBackgroundType background_type);
+gboolean panel_profile_map_orientation_string (const char *str,
+ PanelOrientation *orientation);
+gboolean panel_profile_map_speed_string (const char *str,
+ PanelAnimationSpeed *speed);
+gboolean panel_profile_map_background_type_string (const char *str,
+ PanelBackgroundType *background_type);
+gboolean panel_profile_map_object_type_string (const char *str,
+ PanelObjectType *object_type);
+
+/* all keys relevant to moving are writable */
+gboolean panel_profile_can_be_moved_freely (PanelToplevel *toplevel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_PROFILE_H__ */
diff --git a/mate-panel/panel-properties-dialog.c b/mate-panel/panel-properties-dialog.c
new file mode 100644
index 00000000..0a5df0a1
--- /dev/null
+++ b/mate-panel/panel-properties-dialog.c
@@ -0,0 +1,999 @@
+/*
+ * panel-properties-dialog.c:
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-properties-dialog.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-gtk.h>
+#include <libpanel-util/panel-icon-chooser.h>
+#include <libpanel-util/panel-show.h>
+
+#include "nothing.h"
+#include "panel-profile.h"
+#include "panel-mateconf.h"
+#include "panel-util.h"
+#include "panel-globals.h"
+#include "panel-icon-names.h"
+
+typedef struct {
+ PanelToplevel *toplevel;
+
+ GtkWidget *properties_dialog;
+
+ GtkWidget *general_table;
+ GtkWidget *general_vbox;
+ GtkWidget *orientation_combo;
+ GtkWidget *orientation_label;
+ GtkWidget *size_widgets;
+ GtkWidget *size_spin;
+ GtkWidget *size_label;
+ GtkWidget *size_label_pixels;
+ GtkWidget *icon_align;
+ GtkWidget *icon_chooser;
+ GtkWidget *icon_label;
+ GtkWidget *expand_toggle;
+ GtkWidget *autohide_toggle;
+ GtkWidget *hidebuttons_toggle;
+ GtkWidget *arrows_toggle;
+ GtkWidget *default_radio;
+ GtkWidget *color_radio;
+ GtkWidget *image_radio;
+ GtkWidget *color_widgets;
+ GtkWidget *image_widgets;
+ GtkWidget *color_button;
+ GtkWidget *color_label;
+ GtkWidget *image_chooser;
+ GtkWidget *opacity_scale;
+ GtkWidget *opacity_label;
+ GtkWidget *opacity_legend;
+
+ GtkWidget *writability_warn_general;
+ GtkWidget *writability_warn_background;
+
+ guint toplevel_notify;
+ guint background_notify;
+
+ /* FIXME: This is a workaround for GTK+ bug #327243 */
+ int selection_emitted;
+} PanelPropertiesDialog;
+
+static GQuark panel_properties_dialog_quark = 0;
+
+static void
+panel_properties_dialog_free (PanelPropertiesDialog *dialog)
+{
+ MateConfClient *client;
+
+ client = panel_mateconf_get_client ();
+
+ if (dialog->toplevel_notify)
+ mateconf_client_notify_remove (client, dialog->toplevel_notify);
+ dialog->toplevel_notify = 0;
+
+ if (dialog->background_notify)
+ mateconf_client_notify_remove (client, dialog->background_notify);
+ dialog->background_notify = 0;
+
+ if (dialog->properties_dialog)
+ gtk_widget_destroy (dialog->properties_dialog);
+ dialog->properties_dialog = NULL;
+
+ g_free (dialog);
+}
+
+enum {
+ COLUMN_TEXT,
+ COLUMN_ITEM,
+ NUMBER_COLUMNS
+};
+
+typedef struct {
+ const char *name;
+ PanelOrientation orientation;
+} OrientationComboItem;
+
+static OrientationComboItem orientation_items [] = {
+ { NC_("Orientation", "Top"), PANEL_ORIENTATION_TOP },
+ { NC_("Orientation", "Bottom"), PANEL_ORIENTATION_BOTTOM },
+ { NC_("Orientation", "Left"), PANEL_ORIENTATION_LEFT },
+ { NC_("Orientation", "Right"), PANEL_ORIENTATION_RIGHT }
+};
+
+static void
+panel_properties_dialog_orientation_changed (PanelPropertiesDialog *dialog,
+ GtkComboBox *combo_box)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ OrientationComboItem *item;
+
+ g_assert (dialog->orientation_combo == GTK_WIDGET (combo_box));
+
+ if (!gtk_combo_box_get_active_iter (combo_box, &iter))
+ return;
+
+ model = gtk_combo_box_get_model (combo_box);
+ gtk_tree_model_get (model, &iter, COLUMN_ITEM, &item, -1);
+ if (item == NULL)
+ return;
+
+ panel_profile_set_toplevel_orientation (dialog->toplevel,
+ item->orientation);
+}
+
+static void
+panel_properties_dialog_setup_orientation_combo (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ PanelOrientation orientation;
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ int i;
+
+ dialog->orientation_combo = PANEL_GTK_BUILDER_GET (gui, "orientation_combo");
+ g_return_if_fail (dialog->orientation_combo != NULL);
+ dialog->orientation_label = PANEL_GTK_BUILDER_GET (gui, "orientation_label");
+ g_return_if_fail (dialog->orientation_label != NULL);
+
+ orientation = panel_profile_get_toplevel_orientation (dialog->toplevel);
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (dialog->orientation_combo),
+ GTK_TREE_MODEL (model));
+
+ for (i = 0; i < G_N_ELEMENTS (orientation_items); i++) {
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_TEXT, g_dpgettext2 (NULL, "Orientation", orientation_items [i].name),
+ COLUMN_ITEM, &(orientation_items [i]),
+ -1);
+ if (orientation == orientation_items [i].orientation)
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->orientation_combo),
+ &iter);
+ }
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (dialog->orientation_combo),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (dialog->orientation_combo),
+ renderer, "text", COLUMN_TEXT, NULL);
+
+ g_signal_connect_swapped (dialog->orientation_combo, "changed",
+ G_CALLBACK (panel_properties_dialog_orientation_changed),
+ dialog);
+
+ if (! panel_profile_is_writable_toplevel_orientation (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->orientation_combo, FALSE);
+ gtk_widget_set_sensitive (dialog->orientation_label, FALSE);
+ gtk_widget_show (dialog->writability_warn_general);
+ }
+}
+
+static void
+panel_properties_dialog_size_changed (PanelPropertiesDialog *dialog,
+ GtkSpinButton *spin_button)
+{
+ panel_profile_set_toplevel_size (dialog->toplevel,
+ gtk_spin_button_get_value_as_int (spin_button));
+}
+
+static void
+panel_properties_dialog_setup_size_spin (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ dialog->size_widgets = PANEL_GTK_BUILDER_GET (gui, "size_widgets");
+ g_return_if_fail (dialog->size_widgets != NULL);
+ dialog->size_spin = PANEL_GTK_BUILDER_GET (gui, "size_spin");
+ g_return_if_fail (dialog->size_spin != NULL);
+ dialog->size_label = PANEL_GTK_BUILDER_GET (gui, "size_label");
+ g_return_if_fail (dialog->size_label != NULL);
+ dialog->size_label_pixels = PANEL_GTK_BUILDER_GET (gui, "size_label_pixels");
+ g_return_if_fail (dialog->size_label_pixels != NULL);
+
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->size_spin),
+ panel_toplevel_get_minimum_size (dialog->toplevel),
+ panel_toplevel_get_maximum_size (dialog->toplevel));
+
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->size_spin),
+ panel_profile_get_toplevel_size (dialog->toplevel));
+
+ g_signal_connect_swapped (dialog->size_spin, "value_changed",
+ G_CALLBACK (panel_properties_dialog_size_changed),
+ dialog);
+
+ if ( ! panel_profile_is_writable_toplevel_size (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->size_spin, FALSE);
+ gtk_widget_set_sensitive (dialog->size_label, FALSE);
+ gtk_widget_set_sensitive (dialog->size_label_pixels, FALSE);
+ gtk_widget_show (dialog->writability_warn_general);
+ }
+}
+
+static void
+panel_properties_dialog_icon_changed (PanelIconChooser *chooser,
+ const char *icon,
+ PanelPropertiesDialog *dialog)
+{
+ panel_profile_set_attached_custom_icon (dialog->toplevel, icon);
+}
+
+static void
+panel_properties_dialog_setup_icon_chooser (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ char *custom_icon;
+
+ dialog->icon_align = PANEL_GTK_BUILDER_GET (gui, "icon_align");
+ g_return_if_fail (dialog->icon_align != NULL);
+
+ dialog->icon_chooser = panel_icon_chooser_new (NULL);
+ panel_icon_chooser_set_fallback_icon_name (PANEL_ICON_CHOOSER (dialog->icon_chooser),
+ PANEL_ICON_DRAWER);
+ gtk_widget_show (dialog->icon_chooser);
+ gtk_container_add (GTK_CONTAINER (dialog->icon_align),
+ dialog->icon_chooser);
+
+ dialog->icon_label = PANEL_GTK_BUILDER_GET (gui, "icon_label");
+ g_return_if_fail (dialog->icon_label != NULL);
+
+ custom_icon = panel_profile_get_attached_custom_icon (dialog->toplevel);
+ panel_icon_chooser_set_icon (PANEL_ICON_CHOOSER (dialog->icon_chooser),
+ custom_icon);
+ g_free (custom_icon);
+
+ g_signal_connect (dialog->icon_chooser, "changed",
+ G_CALLBACK (panel_properties_dialog_icon_changed), dialog);
+
+ if (!panel_profile_is_writable_attached_custom_icon (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->icon_chooser, FALSE);
+ gtk_widget_set_sensitive (dialog->icon_label, FALSE);
+ gtk_widget_show (dialog->writability_warn_general);
+ }
+}
+
+/* Note: this is only for toggle buttons on the general page, if needed for togglebuttons
+ elsewhere you must make this respect the writability warning thing for the right page */
+#define SETUP_TOGGLE_BUTTON(wid, n, p) \
+ static void \
+ panel_properties_dialog_##n (PanelPropertiesDialog *dialog, \
+ GtkToggleButton *n) \
+ { \
+ panel_profile_set_toplevel_##p (dialog->toplevel, \
+ gtk_toggle_button_get_active (n)); \
+ } \
+ static void \
+ panel_properties_dialog_setup_##n (PanelPropertiesDialog *dialog, \
+ GtkBuilder *gui) \
+ { \
+ dialog->n = PANEL_GTK_BUILDER_GET (gui, wid); \
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->n), \
+ panel_profile_get_toplevel_##p (dialog->toplevel)); \
+ g_signal_connect_swapped (dialog->n, "toggled", \
+ G_CALLBACK (panel_properties_dialog_##n), dialog); \
+ if ( ! panel_profile_is_writable_toplevel_##p (dialog->toplevel)) { \
+ gtk_widget_set_sensitive (dialog->n, FALSE); \
+ gtk_widget_show (dialog->writability_warn_general); \
+ } \
+ }
+
+SETUP_TOGGLE_BUTTON ("expand_toggle", expand_toggle, expand)
+SETUP_TOGGLE_BUTTON ("autohide_toggle", autohide_toggle, auto_hide)
+SETUP_TOGGLE_BUTTON ("hidebuttons_toggle", hidebuttons_toggle, enable_buttons)
+SETUP_TOGGLE_BUTTON ("arrows_toggle", arrows_toggle, enable_arrows)
+
+static void
+panel_properties_dialog_color_changed (PanelPropertiesDialog *dialog,
+ GtkColorButton *color_button)
+{
+ GdkColor color;
+
+ g_assert (dialog->color_button == GTK_WIDGET (color_button));
+
+ gtk_color_button_get_color (color_button, &color);
+ panel_profile_set_background_gdk_color (dialog->toplevel, &color);
+}
+
+static void
+panel_properties_dialog_setup_color_button (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ PanelColor color;
+
+ dialog->color_button = PANEL_GTK_BUILDER_GET (gui, "color_button");
+ g_return_if_fail (dialog->color_button != NULL);
+ dialog->color_label = PANEL_GTK_BUILDER_GET (gui, "color_label");
+ g_return_if_fail (dialog->color_label != NULL);
+
+ panel_profile_get_background_color (dialog->toplevel, &color);
+
+ gtk_color_button_set_color (GTK_COLOR_BUTTON (dialog->color_button),
+ &(color.gdk));
+
+ g_signal_connect_swapped (dialog->color_button, "color_set",
+ G_CALLBACK (panel_properties_dialog_color_changed),
+ dialog);
+
+ if ( ! panel_profile_is_writable_background_color (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->color_button, FALSE);
+ gtk_widget_set_sensitive (dialog->color_label, FALSE);
+ gtk_widget_show (dialog->writability_warn_background);
+ }
+}
+
+static void
+panel_properties_dialog_image_changed (PanelPropertiesDialog *dialog)
+{
+ char *image;
+
+ image = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog->image_chooser));
+
+ /* FIXME: This is an ugly workaround for GTK+ bug #327243.
+ * FIXME: Note that GTK+ 2.12 and file-set signal might help. */
+ if (!dialog->selection_emitted < 2 && !image) {
+ dialog->selection_emitted++;
+ return;
+ }
+ panel_profile_set_background_image (dialog->toplevel, image);
+
+ g_free (image);
+}
+
+static void
+panel_properties_dialog_setup_image_chooser (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ char *image;
+
+ dialog->image_chooser = PANEL_GTK_BUILDER_GET (gui, "image_chooser");
+ panel_gtk_file_chooser_add_image_preview (GTK_FILE_CHOOSER (dialog->image_chooser));
+
+ image = panel_profile_get_background_image (dialog->toplevel);
+
+ if (PANEL_GLIB_STR_EMPTY (image))
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog->image_chooser));
+ else
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog->image_chooser),
+ image);
+
+ if (image)
+ g_free (image);
+
+ dialog->selection_emitted = 0;
+ g_signal_connect_swapped (dialog->image_chooser, "selection-changed",
+ G_CALLBACK (panel_properties_dialog_image_changed),
+ dialog);
+
+ if ( ! panel_profile_is_writable_background_image (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->image_chooser, FALSE);
+ gtk_widget_show (dialog->writability_warn_background);
+ }
+}
+
+static void
+panel_properties_dialog_opacity_changed (PanelPropertiesDialog *dialog)
+{
+ gdouble percentage;
+ guint16 opacity;
+
+ percentage = gtk_range_get_value (GTK_RANGE (dialog->opacity_scale));
+
+ if (percentage >= 98)
+ percentage = 100;
+ else if (percentage <= 2)
+ percentage = 0;
+
+ opacity = (percentage / 100) * 65535;
+
+ panel_profile_set_background_opacity (dialog->toplevel, opacity);
+}
+
+static void
+panel_properties_dialog_setup_opacity_scale (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ guint16 opacity;
+ gdouble percentage;
+
+ dialog->opacity_scale = PANEL_GTK_BUILDER_GET (gui, "opacity_scale");
+ g_return_if_fail (dialog->opacity_scale != NULL);
+ dialog->opacity_label = PANEL_GTK_BUILDER_GET (gui, "opacity_label");
+ g_return_if_fail (dialog->opacity_label != NULL);
+ dialog->opacity_legend = PANEL_GTK_BUILDER_GET (gui, "opacity_legend");
+ g_return_if_fail (dialog->opacity_legend != NULL);
+
+ opacity = panel_profile_get_background_opacity (dialog->toplevel);
+
+ percentage = (opacity * 100.0) / 65535;
+
+ gtk_range_set_value (GTK_RANGE (dialog->opacity_scale), percentage);
+
+ g_signal_connect_swapped (dialog->opacity_scale, "value_changed",
+ G_CALLBACK (panel_properties_dialog_opacity_changed),
+ dialog);
+
+ if ( ! panel_profile_is_writable_background_opacity (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->opacity_scale, FALSE);
+ gtk_widget_set_sensitive (dialog->opacity_label, FALSE);
+ gtk_widget_set_sensitive (dialog->opacity_legend, FALSE);
+ gtk_widget_show (dialog->writability_warn_background);
+ }
+}
+
+static void
+panel_properties_dialog_upd_sensitivity (PanelPropertiesDialog *dialog,
+ PanelBackgroundType background_type)
+{
+ gtk_widget_set_sensitive (dialog->color_widgets,
+ background_type == PANEL_BACK_COLOR);
+ gtk_widget_set_sensitive (dialog->image_widgets,
+ background_type == PANEL_BACK_IMAGE);
+}
+
+static void
+panel_properties_dialog_background_toggled (PanelPropertiesDialog *dialog,
+ GtkWidget *radio)
+{
+ PanelBackgroundType background_type = PANEL_BACK_NONE;
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)))
+ return;
+
+ if (radio == dialog->default_radio)
+ background_type = PANEL_BACK_NONE;
+
+ else if (radio == dialog->color_radio)
+ background_type = PANEL_BACK_COLOR;
+
+ else if (radio == dialog->image_radio)
+ background_type = PANEL_BACK_IMAGE;
+
+ panel_properties_dialog_upd_sensitivity (dialog, background_type);
+
+ panel_profile_set_background_type (dialog->toplevel, background_type);
+}
+
+static void
+panel_properties_dialog_setup_background_radios (PanelPropertiesDialog *dialog,
+ GtkBuilder *gui)
+{
+ PanelBackgroundType background_type;
+ GtkWidget *active_radio;
+
+ dialog->default_radio = PANEL_GTK_BUILDER_GET (gui, "default_radio");
+ dialog->color_radio = PANEL_GTK_BUILDER_GET (gui, "color_radio");
+ dialog->image_radio = PANEL_GTK_BUILDER_GET (gui, "image_radio");
+ dialog->color_widgets = PANEL_GTK_BUILDER_GET (gui, "color_widgets");
+ dialog->image_widgets = PANEL_GTK_BUILDER_GET (gui, "image_widgets");
+
+ background_type = panel_profile_get_background_type (dialog->toplevel);
+ switch (background_type) {
+ case PANEL_BACK_NONE:
+ active_radio = dialog->default_radio;
+ break;
+ case PANEL_BACK_COLOR:
+ active_radio = dialog->color_radio;
+ break;
+ case PANEL_BACK_IMAGE:
+ active_radio = dialog->image_radio;
+ break;
+ default:
+ active_radio = NULL;
+ g_assert_not_reached ();
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (active_radio), TRUE);
+
+ panel_properties_dialog_upd_sensitivity (dialog, background_type);
+
+ g_signal_connect_swapped (dialog->default_radio, "toggled",
+ G_CALLBACK (panel_properties_dialog_background_toggled),
+ dialog);
+ g_signal_connect_swapped (dialog->color_radio, "toggled",
+ G_CALLBACK (panel_properties_dialog_background_toggled),
+ dialog);
+ g_signal_connect_swapped (dialog->image_radio, "toggled",
+ G_CALLBACK (panel_properties_dialog_background_toggled),
+ dialog);
+
+ if ( ! panel_profile_is_writable_background_type (dialog->toplevel)) {
+ gtk_widget_set_sensitive (dialog->default_radio, FALSE);
+ gtk_widget_set_sensitive (dialog->color_radio, FALSE);
+ gtk_widget_set_sensitive (dialog->image_radio, FALSE);
+ gtk_widget_show (dialog->writability_warn_background);
+ }
+}
+
+static void
+panel_properties_update_arrows_toggle_visible (PanelPropertiesDialog *dialog,
+ GtkToggleButton *toggle)
+{
+ if (gtk_toggle_button_get_active (toggle))
+ gtk_widget_set_sensitive (dialog->arrows_toggle,
+ panel_profile_is_writable_toplevel_enable_arrows (dialog->toplevel));
+ else
+ gtk_widget_set_sensitive (dialog->arrows_toggle, FALSE);
+}
+
+static void
+panel_properties_dialog_response (PanelPropertiesDialog *dialog,
+ int response,
+ GtkWidget *properties_dialog)
+{
+ char *help_id;
+
+ switch (response) {
+ case GTK_RESPONSE_CLOSE:
+ gtk_widget_destroy (properties_dialog);
+ break;
+ case GTK_RESPONSE_HELP:
+ if (panel_toplevel_get_is_attached (dialog->toplevel)) {
+ help_id = "gospanel-550";
+ } else {
+ help_id = "gospanel-28";
+ }
+ panel_show_help (gtk_window_get_screen (GTK_WINDOW (properties_dialog)),
+ "user-guide", help_id, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+panel_properties_dialog_destroy (PanelPropertiesDialog *dialog)
+{
+ panel_toplevel_pop_autohide_disabler (PANEL_TOPLEVEL (dialog->toplevel));
+ g_object_set_qdata (G_OBJECT (dialog->toplevel),
+ panel_properties_dialog_quark,
+ NULL);
+}
+
+static void
+panel_properties_dialog_update_orientation (PanelPropertiesDialog *dialog,
+ MateConfValue *value)
+{
+ PanelOrientation orientation;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ OrientationComboItem *item;
+ int max_size;
+ int spin_size;
+ int profile_size;
+
+ if (!value || value->type != MATECONF_VALUE_STRING)
+ return;
+
+ if (!panel_profile_map_orientation_string (mateconf_value_get_string (value), &orientation))
+ return;
+
+ /* change the maximum size of the panel */
+ //TODO: we should also do this when the monitor size changes
+ max_size = panel_toplevel_get_maximum_size (dialog->toplevel);
+ spin_size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->size_spin));
+ profile_size = panel_profile_get_toplevel_size (dialog->toplevel);
+
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->size_spin),
+ panel_toplevel_get_minimum_size (dialog->toplevel),
+ max_size);
+
+ if (spin_size > max_size)
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->size_spin),
+ max_size);
+ else if (spin_size != profile_size)
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->size_spin),
+ MIN (profile_size, max_size));
+
+ /* update the orientation combo box */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->orientation_combo));
+
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ return;
+
+ do {
+ gtk_tree_model_get (model, &iter, COLUMN_ITEM, &item, -1);
+ if (item != NULL && item->orientation == orientation) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->orientation_combo),
+ &iter);
+ return;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+panel_properties_dialog_update_size (PanelPropertiesDialog *dialog,
+ MateConfValue *value)
+{
+ if (!value || value->type != MATECONF_VALUE_INT)
+ return;
+
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->size_spin),
+ mateconf_value_get_int (value));
+}
+
+static void
+panel_properties_dialog_toplevel_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelPropertiesDialog *dialog)
+{
+ MateConfValue *value;
+ const char *key;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+ if (!key)
+ return;
+
+ value = mateconf_entry_get_value (entry);
+
+#define UPDATE_TOGGLE(p, n) \
+ if (!strcmp (key, p)) { \
+ if (value && value->type == MATECONF_VALUE_BOOL) { \
+ gboolean val = mateconf_value_get_bool (value); \
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->n)) != val) \
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->n), val); \
+ } \
+ }
+
+ if (!strcmp (key, "orientation"))
+ panel_properties_dialog_update_orientation (dialog, value);
+ else if (!strcmp (key, "size"))
+ panel_properties_dialog_update_size (dialog, value);
+ else UPDATE_TOGGLE ("expand", expand_toggle)
+ else UPDATE_TOGGLE ("auto_hide", autohide_toggle)
+ else UPDATE_TOGGLE ("enable_buttons", hidebuttons_toggle)
+ else UPDATE_TOGGLE ("enable_arrows", arrows_toggle)
+}
+
+static void
+panel_properties_dialog_update_background_type (PanelPropertiesDialog *dialog,
+ MateConfValue *value)
+{
+ PanelBackgroundType background_type;
+ GtkWidget *active_radio;
+
+ if (!value || value->type != MATECONF_VALUE_STRING)
+ return;
+
+ if (!panel_profile_map_background_type_string (mateconf_value_get_string (value),
+ &background_type))
+ return;
+
+ switch (background_type) {
+ case PANEL_BACK_NONE:
+ active_radio = dialog->default_radio;
+ break;
+ case PANEL_BACK_COLOR:
+ active_radio = dialog->color_radio;
+ break;
+ case PANEL_BACK_IMAGE:
+ active_radio = dialog->image_radio;
+ break;
+ default:
+ active_radio = NULL;
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (active_radio), TRUE);
+}
+
+static void
+panel_properties_dialog_update_background_color (PanelPropertiesDialog *dialog,
+ MateConfValue *value)
+{
+ GdkColor new_color = { 0, };
+ GdkColor old_color;
+
+ if (!value || value->type != MATECONF_VALUE_STRING)
+ return;
+
+ if (!gdk_color_parse (mateconf_value_get_string (value), &new_color))
+ return;
+
+ gtk_color_button_get_color (GTK_COLOR_BUTTON (dialog->color_button),
+ &old_color);
+
+ if (old_color.red != new_color.red ||
+ old_color.green != new_color.green ||
+ old_color.blue != new_color.blue)
+ gtk_color_button_set_color (GTK_COLOR_BUTTON (dialog->color_button),
+ &new_color);
+}
+
+static void
+panel_properties_dialog_update_background_opacity (PanelPropertiesDialog *dialog,
+ MateConfValue *value)
+{
+ gdouble percentage;
+
+ if (!value || value->type != MATECONF_VALUE_INT)
+ return;
+
+ percentage = ((gdouble) (mateconf_value_get_int (value) * 100)) / 65535;
+
+ if ((int) gtk_range_get_value (GTK_RANGE (dialog->opacity_scale)) != (int) percentage)
+ gtk_range_set_value (GTK_RANGE (dialog->opacity_scale), percentage);
+}
+
+static void
+panel_properties_dialog_update_background_image (PanelPropertiesDialog *dialog,
+ MateConfValue *value)
+{
+ const char *text;
+ char *old_text;
+
+ if (!value || value->type != MATECONF_VALUE_STRING)
+ return;
+
+ text = mateconf_value_get_string (value);
+ old_text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog->image_chooser));
+
+ if (PANEL_GLIB_STR_EMPTY (text) && old_text)
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog->image_chooser));
+ else if (!PANEL_GLIB_STR_EMPTY (text) &&
+ (!old_text || strcmp (text, old_text)))
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog->image_chooser),
+ text);
+
+ if (old_text)
+ g_free (old_text);
+}
+
+static void
+panel_properties_dialog_background_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelPropertiesDialog *dialog)
+{
+ MateConfValue *value;
+ const char *key;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+ if (!key)
+ return;
+
+ value = mateconf_entry_get_value (entry);
+
+ if (!strcmp (key, "type"))
+ panel_properties_dialog_update_background_type (dialog, value);
+ else if (!strcmp (key, "color"))
+ panel_properties_dialog_update_background_color (dialog, value);
+ else if (!strcmp (key, "opacity"))
+ panel_properties_dialog_update_background_opacity (dialog, value);
+ else if (!strcmp (key, "image"))
+ panel_properties_dialog_update_background_image (dialog, value);
+}
+
+static void
+panel_properties_dialog_remove_orientation_combo (PanelPropertiesDialog *dialog)
+{
+ GtkContainer *container = GTK_CONTAINER (dialog->general_table);
+ GtkTable *table = GTK_TABLE (dialog->general_table);
+
+ g_object_ref (dialog->size_label);
+ g_object_ref (dialog->size_widgets);
+ g_object_ref (dialog->icon_label);
+ g_object_ref (dialog->icon_align);
+
+ gtk_container_remove (container, dialog->orientation_label);
+ gtk_container_remove (container, dialog->orientation_combo);
+ gtk_container_remove (container, dialog->size_label);
+ gtk_container_remove (container, dialog->size_widgets);
+ gtk_container_remove (container, dialog->icon_label);
+ gtk_container_remove (container, dialog->icon_align);
+
+ gtk_table_attach_defaults (table, dialog->size_label, 0, 1, 1, 2);
+ gtk_table_attach_defaults (table, dialog->size_widgets, 1, 2, 1, 2);
+ gtk_table_attach_defaults (table, dialog->icon_label, 0, 1, 2, 3);
+ gtk_table_attach_defaults (table, dialog->icon_align, 1, 2, 2, 3);
+
+ dialog->orientation_label = NULL;
+ dialog->orientation_combo = NULL;
+ g_object_unref (dialog->size_label);
+ g_object_unref (dialog->size_widgets);
+ g_object_unref (dialog->icon_label);
+ g_object_unref (dialog->icon_align);
+
+ gtk_table_resize (table, 3, 2);
+}
+
+static void
+panel_properties_dialog_remove_icon_chooser (PanelPropertiesDialog *dialog)
+{
+ GtkContainer *container = GTK_CONTAINER (dialog->general_table);
+
+ gtk_container_remove (container, dialog->icon_label);
+ gtk_container_remove (container, dialog->icon_align);
+
+ dialog->icon_label = NULL;
+ dialog->icon_align = NULL;
+ dialog->icon_chooser = NULL;
+
+ gtk_table_resize (GTK_TABLE (dialog->general_table), 3, 2);
+}
+
+static void
+panel_properties_dialog_remove_toggles (PanelPropertiesDialog *dialog)
+{
+ GtkContainer *container = GTK_CONTAINER (dialog->general_vbox);
+
+ gtk_container_remove (container, dialog->autohide_toggle);
+ gtk_container_remove (container, dialog->expand_toggle);
+
+ dialog->autohide_toggle = NULL;
+ dialog->expand_toggle = NULL;
+}
+
+static void
+panel_properties_dialog_update_for_attached (PanelPropertiesDialog *dialog,
+ gboolean attached)
+{
+ if (!attached)
+ panel_properties_dialog_remove_icon_chooser (dialog);
+ else {
+ gtk_window_set_title (GTK_WINDOW (dialog->properties_dialog),
+ _("Drawer Properties"));
+ panel_properties_dialog_remove_toggles (dialog);
+ panel_properties_dialog_remove_orientation_combo (dialog);
+ }
+}
+
+static PanelPropertiesDialog *
+panel_properties_dialog_new (PanelToplevel *toplevel,
+ GtkBuilder *gui)
+{
+ PanelPropertiesDialog *dialog;
+
+ dialog = g_new0 (PanelPropertiesDialog, 1);
+
+ g_object_set_qdata_full (G_OBJECT (toplevel),
+ panel_properties_dialog_quark,
+ dialog,
+ (GDestroyNotify) panel_properties_dialog_free);
+
+ dialog->toplevel = toplevel;
+
+ dialog->properties_dialog = PANEL_GTK_BUILDER_GET (gui, "panel_properties_dialog");
+ g_signal_connect_swapped (dialog->properties_dialog, "response",
+ G_CALLBACK (panel_properties_dialog_response), dialog);
+ g_signal_connect_swapped (dialog->properties_dialog, "destroy",
+ G_CALLBACK (panel_properties_dialog_destroy), dialog);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog->properties_dialog),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)));
+
+ dialog->writability_warn_general = PANEL_GTK_BUILDER_GET (gui, "writability_warn_general");
+ dialog->writability_warn_background = PANEL_GTK_BUILDER_GET (gui, "writability_warn_background");
+
+ dialog->general_vbox = PANEL_GTK_BUILDER_GET (gui, "general_vbox");
+ dialog->general_table = PANEL_GTK_BUILDER_GET (gui, "general_table");
+
+ panel_properties_dialog_setup_orientation_combo (dialog, gui);
+ panel_properties_dialog_setup_size_spin (dialog, gui);
+ panel_properties_dialog_setup_icon_chooser (dialog, gui);
+ panel_properties_dialog_setup_expand_toggle (dialog, gui);
+ panel_properties_dialog_setup_autohide_toggle (dialog, gui);
+ panel_properties_dialog_setup_hidebuttons_toggle (dialog, gui);
+ panel_properties_dialog_setup_arrows_toggle (dialog, gui);
+
+ panel_properties_update_arrows_toggle_visible (
+ dialog, GTK_TOGGLE_BUTTON (dialog->hidebuttons_toggle));
+ g_signal_connect_swapped (dialog->hidebuttons_toggle, "toggled",
+ G_CALLBACK (panel_properties_update_arrows_toggle_visible),
+ dialog);
+
+ dialog->toplevel_notify =
+ panel_profile_toplevel_notify_add (
+ dialog->toplevel,
+ NULL,
+ (MateConfClientNotifyFunc) panel_properties_dialog_toplevel_notify,
+ dialog);
+
+ panel_properties_dialog_setup_color_button (dialog, gui);
+ panel_properties_dialog_setup_image_chooser (dialog, gui);
+ panel_properties_dialog_setup_opacity_scale (dialog, gui);
+ panel_properties_dialog_setup_background_radios (dialog, gui);
+
+ dialog->background_notify =
+ panel_profile_toplevel_notify_add (
+ dialog->toplevel,
+ "background",
+ (MateConfClientNotifyFunc) panel_properties_dialog_background_notify,
+ dialog);
+
+ panel_properties_dialog_update_for_attached (dialog,
+ panel_toplevel_get_is_attached (dialog->toplevel));
+
+ panel_toplevel_push_autohide_disabler (dialog->toplevel);
+ panel_widget_register_open_dialog (panel_toplevel_get_panel_widget (dialog->toplevel),
+ dialog->properties_dialog);
+
+ g_signal_connect (dialog->properties_dialog, "event",
+ G_CALLBACK (config_event),
+ PANEL_GTK_BUILDER_GET (gui, "notebook"));
+
+ gtk_widget_show (dialog->properties_dialog);
+
+ return dialog;
+}
+
+void
+panel_properties_dialog_present (PanelToplevel *toplevel)
+{
+ PanelPropertiesDialog *dialog;
+ GtkBuilder *gui;
+ GError *error;
+
+ if (!panel_properties_dialog_quark)
+ panel_properties_dialog_quark =
+ g_quark_from_static_string ("panel-properties-dialog");
+
+ dialog = g_object_get_qdata (G_OBJECT (toplevel), panel_properties_dialog_quark);
+ if (dialog) {
+ gtk_window_set_screen (GTK_WINDOW (dialog->properties_dialog),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)));
+ gtk_window_present (GTK_WINDOW (dialog->properties_dialog));
+ return;
+ }
+
+ gui = gtk_builder_new ();
+ gtk_builder_set_translation_domain (gui, GETTEXT_PACKAGE);
+
+ error = NULL;
+ gtk_builder_add_from_file (gui,
+ BUILDERDIR "/panel-properties-dialog.ui",
+ &error);
+
+ if (error) {
+ char *secondary;
+
+ secondary = g_strdup_printf (_("Unable to load file '%s': %s."),
+ BUILDERDIR"/panel-properties-dialog.ui",
+ error->message);
+ panel_error_dialog (GTK_WINDOW (toplevel),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)),
+ "cannot_display_properties_dialog", TRUE,
+ _("Could not display properties dialog"),
+ secondary);
+ g_free (secondary);
+ g_error_free (error);
+ g_object_unref (gui);
+
+ return;
+ }
+
+ dialog = panel_properties_dialog_new (toplevel, gui);
+
+ g_object_unref (gui);
+}
diff --git a/mate-panel/panel-properties-dialog.h b/mate-panel/panel-properties-dialog.h
new file mode 100644
index 00000000..31323619
--- /dev/null
+++ b/mate-panel/panel-properties-dialog.h
@@ -0,0 +1,40 @@
+/*
+ * panel-properties-dialog.h:
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_PROPERTIES_DIALOG_H__
+#define __PANEL_PROPERTIES_DIALOG_H__
+
+#include "panel-toplevel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_properties_dialog_present (PanelToplevel *toplevel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_PROPERTIES_DIALOG_H__ */
diff --git a/mate-panel/panel-properties-dialog.ui b/mate-panel/panel-properties-dialog.ui
new file mode 100644
index 00000000..34feae70
--- /dev/null
+++ b/mate-panel/panel-properties-dialog.ui
@@ -0,0 +1,769 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="panel_properties_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Panel Properties</property>
+ <property name="resizable">False</property>
+ <property name="window_position">center</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="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <child>
+ <object class="GtkVBox" id="general_vbox">
+ <property name="visible">True</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="writability_warn_general">
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-warning</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label19">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Some of these properties are locked down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="general_table">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkAlignment" id="icon_align">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xscale">0</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="icon_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">_Icon:</property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="size_widgets">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSpinButton" id="size_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment2</property>
+ <property name="climb_rate">1</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="size_label_pixels">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">pixels</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="size_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Size:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">size_spin</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="orientation_combo">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="orientation_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Orientation:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">orientation_combo</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="expand_toggle">
+ <property name="label" translatable="yes">E_xpand</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="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="autohide_toggle">
+ <property name="label" translatable="yes">_Autohide</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="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="hidebuttons_toggle">
+ <property name="label" translatable="yes">Show hide _buttons</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="draw_indicator">True</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="hbox3">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="no"> </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="arrows_toggle">
+ <property name="label" translatable="yes">Arro_ws on hide buttons</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="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="fill">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="writability_warn_background">
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-warning</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label20">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Some of these properties are locked down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="default_radio">
+ <property name="label" translatable="yes">_None (use system theme)</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="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="color_radio">
+ <property name="label" translatable="yes">Solid c_olor</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="draw_indicator">True</property>
+ <property name="group">default_radio</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="color_widgets">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="table3">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkColorButton" id="color_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="title" translatable="yes">Pick a color</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="opacity_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">S_tyle:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">opacity_scale</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHScale" id="opacity_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="draw_value">False</property>
+ <accessibility>
+ <relation type="labelled-by" target="opacity_label"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="color_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Co_lor:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">color_button</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="opacity_legend">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">&lt;small&gt;Transparent&lt;/small&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">&lt;small&gt;Opaque&lt;/small&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="image_radio">
+ <property name="label" translatable="yes">Background _image:</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="draw_indicator">True</property>
+ <property name="group">default_radio</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="image_widgets">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="image_chooser">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Select background</property>
+ </object>
+ <packing>
+ <property name="position">1</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="expand">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Background</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</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>
+ <child>
+ <object class="GtkButton" id="helpbutton1">
+ <property name="label">gtk-help</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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="closebutton1">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_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">helpbutton1</action-widget>
+ <action-widget response="-7">closebutton1</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkDialog" id="image_details_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Image Background Details</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="tile_radio">
+ <property name="label" translatable="yes">_Tile</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="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="scale_radio">
+ <property name="label" translatable="yes">_Scale</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="draw_indicator">True</property>
+ <property name="group">tile_radio</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="stretch_radio">
+ <property name="label" translatable="yes">St_retch</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="draw_indicator">True</property>
+ <property name="group">tile_radio</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">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="rotate_toggle">
+ <property name="label" translatable="yes">Rotate image when panel is _vertical</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="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="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkButton" id="helpbutton2">
+ <property name="label">gtk-help</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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="closebutton2">
+ <property name="label">gtk-close</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="-7">closebutton2</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="value">33.75</property>
+ <property name="upper">100</property>
+ <property name="step_increment">5</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="value">12</property>
+ <property name="lower">12</property>
+ <property name="upper">120</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">12</property>
+ </object>
+</interface>
diff --git a/mate-panel/panel-recent.c b/mate-panel/panel-recent.c
new file mode 100644
index 00000000..3c5e94f3
--- /dev/null
+++ b/mate-panel/panel-recent.c
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * panel-recent.c
+ *
+ * Copyright (C) 2002 James Willcox <[email protected]>
+ *
+ * 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.
+ *
+ * Authors:
+ * James Willcox <[email protected]>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-show.h>
+
+#include "menu.h"
+#include "panel-util.h"
+#include "panel-globals.h"
+#include "panel-recent.h"
+#include "panel-stock-icons.h"
+#include "panel-multiscreen.h"
+#include "panel-icon-names.h"
+
+static gboolean
+show_uri (const char *uri, const char *mime_type, GdkScreen *screen,
+ GError **error)
+{
+ return panel_show_uri_force_mime_type (screen, uri, mime_type,
+ gtk_get_current_event_time (),
+ error);
+}
+
+
+static void
+recent_documents_activate_cb (GtkRecentChooser *chooser,
+ gpointer data)
+{
+ GtkRecentInfo *recent_info;
+ const char *uri;
+ const char *mime_type;
+ GdkScreen *screen;
+ GError *error = NULL;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (chooser));
+
+ recent_info = gtk_recent_chooser_get_current_item (chooser);
+ uri = gtk_recent_info_get_uri (recent_info);
+ mime_type = gtk_recent_info_get_mime_type (recent_info);
+ //FIXME gtk_recent_info_get_application_info() could be useful
+
+ if (show_uri (uri, mime_type, screen, &error) != TRUE) {
+ char *uri_utf8;
+
+ uri_utf8 = g_filename_to_utf8 (uri, -1, NULL, NULL, NULL);
+ //FIXME this could fail... Maybe we want gtk_recent_info_get_display_name()
+
+ if (error) {
+ char *primary;
+ primary = g_strdup_printf (_("Could not open recently used document \"%s\""),
+ uri_utf8);
+ panel_error_dialog (NULL, screen,
+ "cannot_open_recent_doc", TRUE,
+ primary, error->message);
+ g_free (primary);
+ g_error_free (error);
+ } else {
+ char *primary;
+ char *secondary;
+ primary = g_strdup_printf (_("Could not open recently used document \"%s\""),
+ uri_utf8);
+ secondary = g_strdup_printf (_("An unknown error occurred while trying to open \"%s\"."),
+ uri_utf8);
+ panel_error_dialog (NULL, screen,
+ "cannot_open_recent_doc", TRUE,
+ primary, secondary);
+ g_free (primary);
+ g_free (secondary);
+ }
+
+ g_free (uri_utf8);
+ }
+
+ /* we can unref it only after having used the data we fetched from it */
+ gtk_recent_info_unref (recent_info);
+}
+
+static void
+panel_recent_manager_changed_cb (GtkRecentManager *manager,
+ GtkWidget *menu_item)
+{
+ int size;
+
+ g_object_get (manager, "size", &size, NULL);
+
+ gtk_widget_set_sensitive (menu_item, size > 0);
+}
+
+static GtkWidget *clear_recent_dialog = NULL;
+
+static void
+clear_dialog_response (GtkWidget *widget,
+ int response,
+ GtkRecentManager *manager)
+{
+ if (response == GTK_RESPONSE_ACCEPT)
+ gtk_recent_manager_purge_items (manager, NULL);
+
+ gtk_widget_destroy (widget);
+}
+
+static void
+recent_documents_clear_cb (GtkMenuItem *menuitem,
+ GtkRecentManager *manager)
+{
+ gpointer tmp;
+
+ if (clear_recent_dialog != NULL) {
+ gtk_window_set_screen (GTK_WINDOW (clear_recent_dialog),
+ gtk_widget_get_screen (GTK_WIDGET (menuitem)));
+ gtk_window_present (GTK_WINDOW (clear_recent_dialog));
+ return;
+ }
+
+ clear_recent_dialog = gtk_message_dialog_new (NULL,
+ 0 /* flags */,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("Clear the Recent Documents list?"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (clear_recent_dialog),
+ _("If you clear the Recent Documents list, you clear the following:\n"
+ "\342\200\242 All items from the Places \342\206\222 Recent Documents menu item.\n"
+ "\342\200\242 All items from the recent documents list in all applications."));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (clear_recent_dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ PANEL_STOCK_CLEAR, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (clear_recent_dialog), 6);
+
+ gtk_window_set_title (GTK_WINDOW (clear_recent_dialog),
+ _("Clear Recent Documents"));
+
+ gtk_dialog_set_default_response (GTK_DIALOG (clear_recent_dialog),
+ GTK_RESPONSE_ACCEPT);
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (clear_recent_dialog),
+ FALSE);
+
+ g_signal_connect (clear_recent_dialog, "response",
+ G_CALLBACK (clear_dialog_response), manager);
+
+ g_signal_connect (clear_recent_dialog, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &clear_recent_dialog);
+
+ tmp = &clear_recent_dialog;
+ g_object_add_weak_pointer (G_OBJECT (clear_recent_dialog), tmp);
+
+ gtk_window_set_screen (GTK_WINDOW (clear_recent_dialog),
+ gtk_widget_get_screen (GTK_WIDGET (menuitem)));
+ gtk_widget_show (clear_recent_dialog);
+}
+
+void
+panel_recent_append_documents_menu (GtkWidget *top_menu,
+ GtkRecentManager *manager)
+{
+ GtkWidget *recent_menu;
+ GtkWidget *menu_item;
+ int size;
+
+ menu_item = gtk_image_menu_item_new ();
+ setup_menu_item_with_icon (menu_item,
+ panel_menu_icon_get_size (),
+ PANEL_ICON_RECENT,
+ NULL, NULL,
+ _("Recent Documents"));
+ recent_menu = gtk_recent_chooser_menu_new_for_manager (manager);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), recent_menu);
+
+ g_signal_connect (G_OBJECT (recent_menu), "button_press_event",
+ G_CALLBACK (menu_dummy_button_press_event), NULL);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
+ gtk_widget_show_all (menu_item);
+
+ gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (recent_menu),
+ FALSE);
+ gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER (recent_menu),
+ TRUE);
+ gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (recent_menu),
+ GTK_RECENT_SORT_MRU);
+
+ g_signal_connect (GTK_RECENT_CHOOSER (recent_menu),
+ "item-activated",
+ G_CALLBACK (recent_documents_activate_cb),
+ NULL);
+
+ //FIXME this is not possible with GtkRecent...: egg_recent_view_gtk_set_icon_size (view, panel_menu_icon_get_size ());
+
+ g_signal_connect_object (manager, "changed",
+ G_CALLBACK (panel_recent_manager_changed_cb),
+ menu_item, 0);
+
+ size = 0;
+ g_object_get (manager, "size", &size, NULL);
+ gtk_widget_set_sensitive (menu_item, size > 0);
+
+ add_menu_separator (recent_menu);
+
+ menu_item = gtk_image_menu_item_new ();
+ setup_menu_item_with_icon (menu_item,
+ panel_menu_icon_get_size (),
+ NULL,
+ GTK_STOCK_CLEAR, NULL,
+ _("Clear Recent Documents..."));
+ panel_util_set_tooltip_text (menu_item,
+ _("Clear all items from the recent documents list"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (recent_menu), menu_item);
+
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (recent_documents_clear_cb),
+ manager);
+}
diff --git a/mate-panel/panel-recent.h b/mate-panel/panel-recent.h
new file mode 100644
index 00000000..7f1b5d7d
--- /dev/null
+++ b/mate-panel/panel-recent.h
@@ -0,0 +1,41 @@
+/*
+ * panel-recent.h
+ *
+ * Copyright (C) 2002 James Willcox <[email protected]>
+ *
+ * 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.
+ *
+ * Authors:
+ * James Willcox <[email protected]>
+ */
+
+#ifndef __PANEL_RECENT_H__
+#define __PANEL_RECENT_H__
+
+#include "gtk/gtk.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_recent_append_documents_menu (GtkWidget *menu,
+ GtkRecentManager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_RECENT_H__ */
diff --git a/mate-panel/panel-reset.c b/mate-panel/panel-reset.c
new file mode 100644
index 00000000..9c53c458
--- /dev/null
+++ b/mate-panel/panel-reset.c
@@ -0,0 +1,46 @@
+/*
+ * panel-reset.c
+ *
+ * Copyright (C) 2010 Perberos <[email protected]>
+ *
+ * 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 __PANEL_RESET_C__
+#define __PANEL_RESET_C__
+
+#include <stdlib.h>
+#include "panel-reset.h"
+
+void panel_reset()
+{
+ /* En teoria, al hacer `mate-panel --reset` se podria correr este comando
+ * para que se reestablesca la configuracion por defecto del panel. O se
+ * borre para que pueda elegir una nueva. Esto ultimo solo si se desarrolla
+ * el dialogo de seleccion de configuracion inicial.
+ *
+ * La configuracion no se borra a travez de los archivos, por que hacer esto
+ * no hace que el demonio de configuracion se actualice. Obligando que se
+ * deba cerrar sesion antes de volver a abrir el panel.
+ * Es por eso que se eliminan las entradas a travez de mate-conf.
+ */
+ system("mateconftool-2 --recursive-unset /apps/panel"); // unix like
+
+ /* TODO: send a dbus message to mate-panel, if active, to reload the panel
+ * configuration */
+}
+
+#endif /* !__PANEL_RESET_C__ */
diff --git a/mate-panel/panel-reset.h b/mate-panel/panel-reset.h
new file mode 100644
index 00000000..0d88aa44
--- /dev/null
+++ b/mate-panel/panel-reset.h
@@ -0,0 +1,37 @@
+/*
+ * panel-reset.h
+ *
+ * Copyright (C) 2010 Perberos <[email protected]>
+ *
+ * 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 __PANEL_RESET_H__
+#define __PANEL_RESET_H__
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void panel_reset();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !__PANEL_RESET_H__ */
diff --git a/mate-panel/panel-run-dialog.c b/mate-panel/panel-run-dialog.c
new file mode 100644
index 00000000..866751da
--- /dev/null
+++ b/mate-panel/panel-run-dialog.c
@@ -0,0 +1,2041 @@
+/*
+ * panel-run-dialog.c:
+ *
+ * Copyright (C) 2003 Frank Worsley <[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.
+
+ * Authors:
+ * Frank Worsley <[email protected]>
+ *
+ * Based on code by:
+ * Havoc Pennington <[email protected]>
+ * George Lebl <[email protected]>
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-run-dialog.h"
+
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdkkeysyms.h>
+#include <mateconf/mateconf-client.h>
+#include <matemenu-tree.h>
+
+#define MATE_DESKTOP_USE_UNSTABLE_API
+#include <libmate/mate-desktop-utils.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-gtk.h>
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-show.h>
+
+#include "nothing.h"
+#include "panel-mateconf.h"
+#include "panel-util.h"
+#include "panel-globals.h"
+#include "panel-enums.h"
+#include "panel-profile.h"
+#include "panel-stock-icons.h"
+#include "panel-multiscreen.h"
+#include "menu.h"
+#include "panel-lockdown.h"
+#include "panel-xutils.h"
+#include "panel-icon-names.h"
+
+typedef struct {
+ GtkWidget *run_dialog;
+
+ GtkWidget *main_box;
+ GtkWidget *program_list_box;
+
+ GtkWidget *combobox;
+ GtkWidget *pixmap;
+ GtkWidget *run_button;
+ GtkWidget *file_button;
+ GtkWidget *list_expander;
+ GtkWidget *terminal_checkbox;
+ GtkWidget *program_label;
+ GtkWidget *program_list;
+
+ long changed_id;
+
+ GtkListStore *program_list_store;
+
+ GHashTable *dir_hash;
+ GList *possible_executables;
+ GList *completion_items;
+ GCompletion *completion;
+
+ GSList *add_icon_paths;
+ int add_icons_idle_id;
+ int add_items_idle_id;
+ int find_command_idle_id;
+ int content_notify_id;
+ gboolean use_program_list;
+ gboolean completion_started;
+
+ char *icon_path;
+ char *desktop_path;
+ char *item_name;
+} PanelRunDialog;
+
+enum {
+ COLUMN_ICON,
+ COLUMN_ICON_FILE,
+ COLUMN_NAME,
+ COLUMN_COMMENT,
+ COLUMN_PATH,
+ COLUMN_EXEC,
+ COLUMN_VISIBLE,
+ NUM_COLUMNS
+};
+
+static PanelRunDialog *static_dialog = NULL;
+
+static void panel_run_dialog_disconnect_pixmap (PanelRunDialog *dialog);
+
+#define PANEL_RUN_HISTORY_KEY "/apps/mate-settings/mate-panel/history-mate-run"
+#define PANEL_RUN_MAX_HISTORY 10
+
+static GtkTreeModel *
+_panel_run_get_recent_programs_list (void)
+{
+ GtkListStore *list;
+ GSList *mateconf_items;
+ GSList *command;
+ int i = 0;
+
+ list = gtk_list_store_new (1, G_TYPE_STRING);
+
+ mateconf_items = mateconf_client_get_list (panel_mateconf_get_client (),
+ PANEL_RUN_HISTORY_KEY,
+ MATECONF_VALUE_STRING, NULL);
+
+ for (command = mateconf_items;
+ command && i < PANEL_RUN_MAX_HISTORY;
+ command = command->next) {
+ GtkTreeIter iter;
+ gtk_list_store_prepend (list, &iter);
+ gtk_list_store_set (list, &iter, 0, command->data, -1);
+ i++;
+ }
+
+ g_slist_free (mateconf_items);
+
+ return GTK_TREE_MODEL (list);
+}
+
+static void
+_panel_run_save_recent_programs_list (GtkComboBoxEntry *entry,
+ char *lastcommand)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GSList *mateconf_items = NULL;
+ int i = 0;
+
+ mateconf_items = g_slist_prepend (mateconf_items, lastcommand);
+ i++;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (entry));
+
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ char *command;
+
+ do {
+ gtk_tree_model_get (model, &iter, 0, &command, -1);
+
+ if (strcmp (command, lastcommand) == 0)
+ continue;
+
+ mateconf_items = g_slist_prepend (mateconf_items, command);
+ i++;
+ } while (gtk_tree_model_iter_next (model, &iter) &&
+ i < PANEL_RUN_MAX_HISTORY);
+ }
+
+ mateconf_client_set_list (panel_mateconf_get_client (),
+ PANEL_RUN_HISTORY_KEY,
+ MATECONF_VALUE_STRING, mateconf_items,
+ NULL);
+
+ g_slist_free (mateconf_items);
+}
+
+static void
+panel_run_dialog_destroy (PanelRunDialog *dialog)
+{
+ GList *l;
+
+ dialog->changed_id = 0;
+
+ g_object_unref (dialog->program_list_box);
+
+ g_slist_foreach (dialog->add_icon_paths, (GFunc) gtk_tree_path_free, NULL);
+ g_slist_free (dialog->add_icon_paths);
+ dialog->add_icon_paths = NULL;
+
+ g_free (dialog->icon_path);
+ dialog->icon_path = NULL;
+ g_free (dialog->desktop_path);
+ dialog->desktop_path = NULL;
+ g_free (dialog->item_name);
+ dialog->item_name = NULL;
+
+ if (dialog->add_icons_idle_id)
+ g_source_remove (dialog->add_icons_idle_id);
+ dialog->add_icons_idle_id = 0;
+
+ if (dialog->add_items_idle_id)
+ g_source_remove (dialog->add_items_idle_id);
+ dialog->add_items_idle_id = 0;
+
+ if (dialog->find_command_idle_id)
+ g_source_remove (dialog->find_command_idle_id);
+ dialog->find_command_idle_id = 0;
+
+ if (dialog->content_notify_id)
+ mateconf_client_notify_remove (panel_mateconf_get_client (),
+ dialog->content_notify_id);
+ dialog->content_notify_id = 0;
+
+ if (dialog->dir_hash)
+ g_hash_table_destroy (dialog->dir_hash);
+ dialog->dir_hash = NULL;
+
+ for (l = dialog->possible_executables; l; l = l->next)
+ g_free (l->data);
+ g_list_free (dialog->possible_executables);
+ dialog->possible_executables = NULL;
+
+ for (l = dialog->completion_items; l; l = l->next)
+ g_free (l->data);
+ g_list_free (dialog->completion_items);
+ dialog->completion_items = NULL;
+
+ if (dialog->completion)
+ g_completion_free (dialog->completion);
+ dialog->completion = NULL;
+
+ panel_run_dialog_disconnect_pixmap (dialog);
+
+ g_free (dialog);
+}
+
+static void
+panel_run_dialog_set_default_icon (PanelRunDialog *dialog, gboolean set_drag)
+{
+ gtk_image_set_from_icon_name (GTK_IMAGE (dialog->pixmap),
+ PANEL_ICON_RUN,
+ GTK_ICON_SIZE_DIALOG);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog->run_dialog),
+ PANEL_ICON_RUN);
+
+ if (set_drag)
+ gtk_drag_source_set_icon_name (dialog->run_dialog,
+ PANEL_ICON_LAUNCHER);
+}
+
+static void
+panel_run_dialog_set_icon (PanelRunDialog *dialog,
+ const char *icon_path,
+ gboolean force)
+{
+ GdkPixbuf *pixbuf = NULL;
+
+ if (!force && icon_path && dialog->icon_path &&
+ !strcmp (icon_path, dialog->icon_path))
+ return;
+
+ g_free (dialog->icon_path);
+ dialog->icon_path = NULL;
+
+ if (icon_path) {
+ GdkScreen *screen;
+ GtkSettings *settings;
+ int size;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (dialog->pixmap));
+ settings = gtk_settings_get_for_screen (screen);
+ gtk_icon_size_lookup_for_settings (settings,
+ GTK_ICON_SIZE_DIALOG,
+ &size, NULL);
+
+ pixbuf = panel_load_icon (gtk_icon_theme_get_default (),
+ icon_path,
+ size,
+ size,
+ size,
+ NULL);
+ }
+
+ if (pixbuf) {
+ dialog->icon_path = g_strdup (icon_path);
+
+ /* Don't bother scaling the image if it's too small.
+ * Scaled looks worse than a smaller image.
+ */
+ gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->pixmap), pixbuf);
+
+ //FIXME: it'd be better to set an icon of the correct size,
+ //(ditto for the drag icon?)
+ gtk_window_set_icon (GTK_WINDOW (dialog->run_dialog), pixbuf);
+
+ gtk_drag_source_set_icon_pixbuf (dialog->run_dialog, pixbuf);
+ g_object_unref (pixbuf);
+ } else {
+ panel_run_dialog_set_default_icon (dialog, TRUE);
+ }
+}
+
+static gboolean
+command_is_executable (const char *command,
+ int *argcp,
+ char ***argvp)
+{
+ gboolean result;
+ char **argv;
+ char *path;
+ int argc;
+
+ result = g_shell_parse_argv (command, &argc, &argv, NULL);
+
+ if (!result)
+ return FALSE;
+
+ path = g_find_program_in_path (argv[0]);
+
+ if (!path) {
+ g_strfreev (argv);
+ return FALSE;
+ }
+
+ /* If we pass an absolute path to g_find_program it just returns
+ * that absolute path without checking if it is executable. Also
+ * make sure its a regular file so we don't try to launch
+ * directories or device nodes.
+ */
+ if (!g_file_test (path, G_FILE_TEST_IS_EXECUTABLE) ||
+ !g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
+ g_free (path);
+ g_strfreev (argv);
+ return FALSE;
+ }
+
+ g_free (path);
+
+ if (argcp)
+ *argcp = argc;
+ if (argvp)
+ *argvp = argv;
+
+ return TRUE;
+}
+
+static gboolean
+panel_run_dialog_launch_command (PanelRunDialog *dialog,
+ const char *command,
+ const char *locale_command)
+{
+ GdkScreen *screen;
+ gboolean result;
+ GError *error = NULL;
+ char **argv;
+ int argc;
+
+ if (!command_is_executable (locale_command, &argc, &argv))
+ return FALSE;
+
+ screen = gtk_window_get_screen (GTK_WINDOW (dialog->run_dialog));
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->terminal_checkbox)))
+ mate_desktop_prepend_terminal_to_vector (&argc, &argv);
+
+ result = gdk_spawn_on_screen (screen,
+ NULL, /* working directory */
+ argv,
+ NULL, /* envp */
+ G_SPAWN_SEARCH_PATH,
+ NULL, /* child setup func */
+ NULL, /* user data */
+ NULL, /* child pid */
+ &error);
+
+ if (!result) {
+ char *primary;
+
+ primary = g_markup_printf_escaped (_("Could not run command '%s'"),
+ command);
+ panel_error_dialog (GTK_WINDOW (dialog->run_dialog), NULL,
+ "cannot_spawn_command", TRUE,
+ primary, error->message);
+ g_free (primary);
+
+ g_error_free (error);
+ }
+
+ g_strfreev (argv);
+
+ return result;
+}
+
+static void
+panel_run_dialog_execute (PanelRunDialog *dialog)
+{
+ GError *error;
+ gboolean result;
+ char *command;
+ char *disk;
+ char *scheme;
+
+ command = gtk_combo_box_get_active_text (GTK_COMBO_BOX (dialog->combobox));
+ command = g_strchug (command);
+
+ if (!command || !command [0]) {
+ g_free (command);
+ return;
+ }
+
+ /* evil eggies, do not translate! */
+ if (!strcmp (command, "free the fish")) {
+ start_screen_check ();
+
+ g_free (command);
+ gtk_widget_destroy (dialog->run_dialog);
+ return;
+ } else if (!strcmp (command, "gegls from outer space")) {
+ start_geginv ();
+
+ g_free (command);
+ gtk_widget_destroy (dialog->run_dialog);
+ return;
+ }
+
+ error = NULL;
+ disk = g_locale_from_utf8 (command, -1, NULL, NULL, &error);
+
+ if (!disk || error) {
+ char *primary;
+
+ primary = g_strdup_printf (_("Could not convert '%s' from UTF-8"),
+ command);
+ panel_error_dialog (GTK_WINDOW (dialog->run_dialog), NULL,
+ "cannot_convert_command_from_utf8", TRUE,
+ primary, error->message);
+ g_free (primary);
+
+ g_error_free (error);
+ return;
+ }
+
+ result = FALSE;
+
+ scheme = g_uri_parse_scheme (disk);
+ /* if it's an absolute path or not a URI, it's possibly an executable,
+ * so try it before displaying it */
+ if (g_path_is_absolute (disk) || !scheme)
+ result = panel_run_dialog_launch_command (dialog, command, disk);
+
+ if (!result) {
+ GFile *file;
+ char *uri;
+ GdkScreen *screen;
+
+ file = panel_util_get_file_optional_homedir (command);
+ uri = g_file_get_uri (file);
+ g_object_unref (file);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (dialog->run_dialog));
+ result = panel_show_uri (screen, uri,
+ gtk_get_current_event_time (), NULL);
+
+ g_free (uri);
+ }
+
+ if (result) {
+ /* only save working commands in history */
+ _panel_run_save_recent_programs_list
+ (GTK_COMBO_BOX_ENTRY (dialog->combobox), command);
+
+ /* only close the dialog if we successfully showed or launched
+ * something */
+ gtk_widget_destroy (dialog->run_dialog);
+ }
+
+ g_free (command);
+ g_free (disk);
+ g_free (scheme);
+}
+
+static void
+panel_run_dialog_response (PanelRunDialog *dialog,
+ int response,
+ GtkWidget *run_dialog)
+{
+
+ dialog->completion_started = FALSE;
+
+ switch (response) {
+ case GTK_RESPONSE_OK:
+ panel_run_dialog_execute (dialog);
+ break;
+ case GTK_RESPONSE_CANCEL:
+ gtk_widget_destroy (dialog->run_dialog);
+ break;
+ case GTK_RESPONSE_HELP:
+ panel_show_help (gtk_window_get_screen (GTK_WINDOW (run_dialog)),
+ "user-guide", "gospanel-23", NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+/* only quote the string if really needed */
+static char *
+quote_string (const char *s)
+{
+ const char *p;
+
+ for (p = s; *p != '\0'; p++) {
+ if ((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') ||
+ strchr ("-_./=:", *p) != NULL)
+ ;
+ else
+ return g_shell_quote (s);
+ }
+
+ return g_strdup (s);
+}
+
+static void
+panel_run_dialog_append_file_utf8 (PanelRunDialog *dialog,
+ const char *file)
+{
+ char *text;
+ char *quoted, *temp;
+ GtkWidget *entry;
+
+ /* Don't allow filenames beginning with '-' */
+ if (!file || !file[0] || file[0] == '-')
+ return;
+
+ quoted = quote_string (file);
+ entry = gtk_bin_get_child (GTK_BIN (dialog->combobox));
+ text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (dialog->combobox));
+ if (text && text [0]) {
+ temp = g_strconcat (text, " ", quoted, NULL);
+ gtk_entry_set_text (GTK_ENTRY (entry), temp);
+ g_free (temp);
+ } else
+ gtk_entry_set_text (GTK_ENTRY (entry), quoted);
+
+ g_free (text);
+ g_free (quoted);
+}
+
+static void
+panel_run_dialog_append_file (PanelRunDialog *dialog,
+ const char *file)
+{
+ char *utf8_file;
+
+ if (!file)
+ return;
+
+ utf8_file = g_filename_to_utf8 (file, -1, NULL, NULL, NULL);
+
+ if (utf8_file)
+ panel_run_dialog_append_file_utf8 (dialog, utf8_file);
+
+ g_free (utf8_file);
+}
+
+static gboolean
+fuzzy_command_match (const char *cmd1,
+ const char *cmd2,
+ gboolean *fuzzy)
+{
+ char **tokens;
+ char *word1, *word2;
+
+ g_return_val_if_fail (cmd1 && cmd2, TRUE);
+
+ *fuzzy = FALSE;
+
+ if (!strcmp (cmd1, cmd2))
+ return TRUE;
+
+ /* find basename of exec from desktop item.
+ strip of all arguments after the initial command */
+ tokens = g_strsplit (cmd1, " ", -1);
+ if (!tokens || !tokens [0]) {
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ word1 = g_path_get_basename (tokens [0]);
+ g_strfreev (tokens);
+
+ /* same for the user command */
+ tokens = g_strsplit (cmd2, " ", -1);
+ word2 = g_path_get_basename (tokens [0]);
+ if (!tokens || !tokens [0]) {
+ g_free (word1);
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ g_strfreev (tokens);
+
+ if (!strcmp (word1, word2)) {
+ g_free (word1);
+ g_free (word2);
+ *fuzzy = TRUE;
+ return TRUE;
+ }
+
+ g_free (word1);
+ g_free (word2);
+
+ return FALSE;
+}
+
+static gboolean
+panel_run_dialog_make_all_list_visible (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gtk_list_store_set (GTK_LIST_STORE (model), iter,
+ COLUMN_VISIBLE, TRUE,
+ -1);
+
+ return FALSE;
+}
+
+static gboolean
+panel_run_dialog_find_command_idle (PanelRunDialog *dialog)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ char *text;
+ char *found_icon;
+ char *found_name;
+ gboolean fuzzy;
+
+ model = GTK_TREE_MODEL (dialog->program_list_store);
+ path = gtk_tree_path_new_first ();
+
+ if (!path || !gtk_tree_model_get_iter (model, &iter, path)) {
+ if (path)
+ gtk_tree_path_free (path);
+
+ panel_run_dialog_set_icon (dialog, NULL, FALSE);
+
+ dialog->find_command_idle_id = 0;
+ return FALSE;
+ }
+
+ text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (dialog->combobox));
+ found_icon = NULL;
+ found_name = NULL;
+ fuzzy = FALSE;
+
+ do {
+ char *exec = NULL;
+ char *icon = NULL;
+ char *name = NULL;
+ char *comment = NULL;
+
+ gtk_tree_model_get (model, &iter,
+ COLUMN_EXEC, &exec,
+ COLUMN_ICON_FILE, &icon,
+ COLUMN_NAME, &name,
+ COLUMN_COMMENT, &comment,
+ -1);
+
+ if (!fuzzy && exec && icon &&
+ fuzzy_command_match (text, exec, &fuzzy)) {
+ g_free (found_icon);
+ g_free (found_name);
+
+ found_icon = g_strdup (icon);
+ found_name = g_strdup (name);
+
+ gtk_list_store_set (dialog->program_list_store,
+ &iter,
+ COLUMN_VISIBLE, TRUE,
+ -1);
+ } else if (panel_g_utf8_strstrcase (exec, text) != NULL ||
+ panel_g_utf8_strstrcase (name, text) != NULL ||
+ panel_g_utf8_strstrcase (comment, text) != NULL) {
+ gtk_list_store_set (dialog->program_list_store,
+ &iter,
+ COLUMN_VISIBLE, TRUE,
+ -1);
+ } else {
+ gtk_list_store_set (dialog->program_list_store,
+ &iter,
+ COLUMN_VISIBLE, FALSE,
+ -1);
+ }
+
+ g_free (exec);
+ g_free (icon);
+ g_free (name);
+ g_free (comment);
+
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ if (gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->program_list)),
+ &iter, path))
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dialog->program_list),
+ path, NULL, FALSE, 0, 0);
+
+ gtk_tree_path_free (path);
+
+ panel_run_dialog_set_icon (dialog, found_icon, FALSE);
+ //FIXME update dialog->program_label
+
+ g_free (found_icon);
+ g_free (text);
+
+ g_free (dialog->item_name);
+ dialog->item_name = found_name;
+
+ dialog->find_command_idle_id = 0;
+ return FALSE;
+}
+
+static gboolean
+panel_run_dialog_add_icon_idle (PanelRunDialog *dialog)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GdkPixbuf *pixbuf;
+ char *file;
+ int icon_height;
+ gboolean long_operation = FALSE;
+
+ do {
+ if (!dialog->add_icon_paths) {
+ dialog->add_icons_idle_id = 0;
+ return FALSE;
+ }
+
+ path = dialog->add_icon_paths->data;
+ dialog->add_icon_paths->data = NULL;
+ dialog->add_icon_paths = g_slist_delete_link (dialog->add_icon_paths,
+ dialog->add_icon_paths);
+
+ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->program_list_store),
+ &iter,
+ path)) {
+ gtk_tree_path_free (path);
+ continue;
+ }
+
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (GTK_TREE_MODEL (dialog->program_list_store), &iter,
+ COLUMN_ICON_FILE, &file, -1);
+
+ if (!gtk_icon_size_lookup (panel_menu_icon_get_size (), NULL, &icon_height)) {
+ icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
+ }
+
+ pixbuf = panel_make_menu_icon (gtk_icon_theme_get_default (), file, NULL, icon_height, &long_operation);
+ if (pixbuf) {
+ gtk_list_store_set (dialog->program_list_store, &iter, COLUMN_ICON, pixbuf, -1);
+ g_object_unref (pixbuf);
+ }
+ g_free (file);
+
+ /* don't go back into the main loop if this wasn't very hard to do */
+ } while (!long_operation);
+
+ return TRUE;
+}
+
+static int
+compare_applications (MateMenuTreeEntry *a,
+ MateMenuTreeEntry *b)
+{
+ return g_utf8_collate (matemenu_tree_entry_get_display_name (a),
+ matemenu_tree_entry_get_display_name (b));
+}
+
+static GSList *get_all_applications_from_dir (MateMenuTreeDirectory *directory,
+ GSList *list);
+
+static GSList *
+get_all_applications_from_alias (MateMenuTreeAlias *alias,
+ GSList *list)
+{
+ MateMenuTreeItem *aliased_item;
+
+ aliased_item = matemenu_tree_alias_get_item (alias);
+
+ switch (matemenu_tree_item_get_type (aliased_item)) {
+ case MATEMENU_TREE_ITEM_ENTRY:
+ list = g_slist_append (list, matemenu_tree_item_ref (aliased_item));
+ break;
+
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ list = get_all_applications_from_dir (MATEMENU_TREE_DIRECTORY (aliased_item),
+ list);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (aliased_item);
+
+ return list;
+}
+
+static GSList *
+get_all_applications_from_dir (MateMenuTreeDirectory *directory,
+ GSList *list)
+{
+ GSList *items;
+ GSList *l;
+
+ items = matemenu_tree_directory_get_contents (directory);
+
+ for (l = items; l; l = l->next) {
+ switch (matemenu_tree_item_get_type (l->data)) {
+ case MATEMENU_TREE_ITEM_ENTRY:
+ list = g_slist_append (list, matemenu_tree_item_ref (l->data));
+ break;
+
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ list = get_all_applications_from_dir (l->data, list);
+ break;
+
+ case MATEMENU_TREE_ITEM_ALIAS:
+ list = get_all_applications_from_alias (l->data, list);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (l->data);
+ }
+
+ g_slist_free (items);
+
+ return list;
+}
+
+static GSList* get_all_applications(void)
+{
+ MateMenuTree* tree;
+ MateMenuTreeDirectory* root;
+ GSList* retval;
+
+ tree = matemenu_tree_lookup("mate-applications.menu", MATEMENU_TREE_FLAGS_NONE);
+ matemenu_tree_set_sort_key(tree, MATEMENU_TREE_SORT_DISPLAY_NAME);
+
+ root = matemenu_tree_get_root_directory(tree);
+
+ retval = get_all_applications_from_dir(root, NULL);
+
+ matemenu_tree_item_unref(root);
+ matemenu_tree_unref(tree);
+
+ retval = g_slist_sort(retval, (GCompareFunc) compare_applications);
+
+ return retval;
+}
+
+static gboolean
+panel_run_dialog_add_items_idle (PanelRunDialog *dialog)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *model_filter;
+ GSList *all_applications;
+ GSList *l;
+ GSList *next;
+ const char *prev_name;
+
+ /* create list store */
+ dialog->program_list_store = gtk_list_store_new (NUM_COLUMNS,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN);
+
+ all_applications = get_all_applications ();
+
+ /* Strip duplicates */
+ prev_name = NULL;
+ for (l = all_applications; l; l = next) {
+ MateMenuTreeEntry *entry = l->data;
+ const char *entry_name;
+
+ next = l->next;
+
+ entry_name = matemenu_tree_entry_get_display_name (entry);
+ if (prev_name && entry_name && strcmp (entry_name, prev_name) == 0) {
+ matemenu_tree_item_unref (entry);
+
+ all_applications = g_slist_delete_link (all_applications, l);
+ } else {
+ prev_name = entry_name;
+ }
+ }
+
+ for (l = all_applications; l; l = l->next) {
+ MateMenuTreeEntry *entry = l->data;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ gtk_list_store_append (dialog->program_list_store, &iter);
+ gtk_list_store_set (dialog->program_list_store, &iter,
+ COLUMN_ICON, NULL,
+ COLUMN_ICON_FILE, matemenu_tree_entry_get_icon (entry),
+ COLUMN_NAME, matemenu_tree_entry_get_display_name (entry),
+ COLUMN_COMMENT, matemenu_tree_entry_get_comment (entry),
+ COLUMN_EXEC, matemenu_tree_entry_get_exec (entry),
+ COLUMN_PATH, matemenu_tree_entry_get_desktop_file_path (entry),
+ COLUMN_VISIBLE, TRUE,
+ -1);
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->program_list_store), &iter);
+ if (path != NULL)
+ dialog->add_icon_paths = g_slist_prepend (dialog->add_icon_paths, path);
+
+ matemenu_tree_item_unref (entry);
+ }
+ g_slist_free (all_applications);
+
+ model_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->program_list_store),
+ NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (model_filter),
+ COLUMN_VISIBLE);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->program_list),
+ model_filter);
+ //FIXME use the same search than the fuzzy one?
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (dialog->program_list),
+ COLUMN_NAME);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "pixbuf", COLUMN_ICON,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "text", COLUMN_NAME,
+ NULL);
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->program_list), column);
+
+ dialog->add_icon_paths = g_slist_reverse (dialog->add_icon_paths);
+
+ if (!dialog->add_icons_idle_id)
+ dialog->add_icons_idle_id =
+ g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc) panel_run_dialog_add_icon_idle,
+ dialog, NULL);
+
+ dialog->add_items_idle_id = 0;
+ return FALSE;
+}
+
+static char *
+remove_parameters (const char *exec)
+{
+ GString *str;
+ char *retval, *p;
+
+ str = g_string_new (exec);
+
+ while ((p = strstr (str->str, "%"))) {
+ switch (p [1]) {
+ case '%':
+ g_string_erase (str, p - str->str, 1);
+ break;
+ case 'U':
+ case 'F':
+ case 'N':
+ case 'D':
+ case 'f':
+ case 'u':
+ case 'd':
+ case 'n':
+ case 'm':
+ case 'i':
+ case 'c':
+ case 'k':
+ case 'v':
+ g_string_erase (str, p - str->str, 2);
+ break;
+ default:
+ break;
+ }
+ }
+
+ retval = str->str;
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+static void
+program_list_selection_changed (GtkTreeSelection *selection,
+ PanelRunDialog *dialog)
+{
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+ char *temp;
+ char *path, *stripped;
+ gboolean terminal;
+ GKeyFile *key_file;
+ GtkWidget *entry;
+
+ if (!gtk_tree_selection_get_selected (selection, &filter_model,
+ &filter_iter))
+ return;
+
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter, &filter_iter);
+
+ path = NULL;
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter,
+ COLUMN_PATH, &path,
+ -1);
+
+ if (!path)
+ return;
+
+ key_file = g_key_file_new ();
+
+ if (!g_key_file_load_from_file (key_file, path,
+ G_KEY_FILE_NONE, NULL)) {
+ g_key_file_free (key_file);
+ g_free (path);
+ return;
+ }
+
+ dialog->use_program_list = TRUE;
+ if (dialog->desktop_path)
+ g_free (dialog->desktop_path);
+ dialog->desktop_path = g_strdup (path);
+ if (dialog->item_name)
+ g_free (dialog->item_name);
+ dialog->item_name = NULL;
+
+ /* Order is important here. We have to set the text first so that the
+ * drag source is enabled, otherwise the drag icon can't be set by
+ * panel_run_dialog_set_icon.
+ */
+ entry = gtk_bin_get_child (GTK_BIN (dialog->combobox));
+ temp = panel_key_file_get_string (key_file, "Exec");
+ if (temp) {
+ stripped = remove_parameters (temp);
+ gtk_entry_set_text (GTK_ENTRY (entry), stripped);
+ g_free (stripped);
+ } else {
+ temp = panel_key_file_get_string (key_file, "URL");
+ gtk_entry_set_text (GTK_ENTRY (entry), sure_string (temp));
+ }
+ g_free (temp);
+
+ temp = panel_key_file_get_locale_string (key_file, "Icon");
+ panel_run_dialog_set_icon (dialog, temp, FALSE);
+ g_free (temp);
+
+ temp = panel_key_file_get_locale_string (key_file, "Comment");
+ //FIXME: if sure_string () == "", we should display "Will run..." as in entry_changed()
+ gtk_label_set_text (GTK_LABEL (dialog->program_label),
+ sure_string (temp));
+ g_free (temp);
+
+ terminal = panel_key_file_get_boolean (key_file, "Terminal", FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->terminal_checkbox),
+ terminal);
+
+ g_key_file_free (key_file);
+
+ g_free (path);
+}
+
+static void
+program_list_selection_activated (GtkTreeView *view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ PanelRunDialog *dialog)
+{
+ GtkTreeSelection *selection;
+
+ /* update the entry with the info from the selection */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list));
+ program_list_selection_changed (selection, dialog);
+
+ /* now launch the command */
+ gtk_dialog_response (GTK_DIALOG (dialog->run_dialog), GTK_RESPONSE_OK);
+}
+
+
+static void
+panel_run_dialog_setup_program_list (PanelRunDialog *dialog,
+ GtkBuilder *gui)
+{
+ GtkTreeSelection *selection;
+
+ dialog->program_list = PANEL_GTK_BUILDER_GET (gui, "program_list");
+ dialog->program_list_box = PANEL_GTK_BUILDER_GET (gui, "program_list_box");
+ dialog->program_label = PANEL_GTK_BUILDER_GET (gui, "program_label");
+ dialog->main_box = PANEL_GTK_BUILDER_GET (gui, "main_box");
+
+ /* Ref the box so it doesn't get destroyed when it is
+ * removed from the visible area of the dialog box.
+ */
+ g_object_ref (dialog->program_list_box);
+
+ if (panel_profile_get_enable_program_list ()) {
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (program_list_selection_changed),
+ dialog);
+
+ g_signal_connect (dialog->program_list, "row-activated",
+ G_CALLBACK (program_list_selection_activated),
+ dialog);
+
+ /* start loading the list of applications */
+ dialog->add_items_idle_id =
+ g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc) panel_run_dialog_add_items_idle,
+ dialog, NULL);
+ }
+}
+
+static void
+panel_run_dialog_update_content (PanelRunDialog *dialog,
+ gboolean show_list)
+{
+ if (!panel_profile_get_enable_program_list ()) {
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (dialog->list_expander);
+ if (parent)
+ gtk_container_remove (GTK_CONTAINER (parent),
+ dialog->list_expander);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog->run_dialog), FALSE);
+ gtk_widget_grab_focus (dialog->combobox);
+
+ } else if (show_list) {
+ gtk_window_resize (GTK_WINDOW (dialog->run_dialog), 100, 300);
+ gtk_window_set_resizable (GTK_WINDOW (dialog->run_dialog), TRUE);
+ gtk_widget_grab_focus (dialog->program_list);
+
+ } else if (!show_list) {
+ gtk_window_set_resizable (GTK_WINDOW (dialog->run_dialog), FALSE);
+ gtk_widget_grab_focus (dialog->combobox);
+ }
+}
+
+static void
+panel_run_dialog_content_notify (MateConfClient *client,
+ int notify_id,
+ MateConfEntry *entry,
+ PanelRunDialog *dialog)
+{
+ panel_run_dialog_update_content (dialog, mateconf_value_get_bool (entry->value));
+}
+
+static void
+list_expander_toggled (GtkExpander *expander,
+ GParamSpec *pspec,
+ PanelRunDialog *dialog)
+{
+ panel_profile_set_show_program_list (gtk_expander_get_expanded (expander));
+}
+
+static void
+panel_run_dialog_setup_list_expander (PanelRunDialog *dialog,
+ GtkBuilder *gui)
+{
+ MateConfClient *client;
+ const char *key;
+
+ dialog->list_expander = PANEL_GTK_BUILDER_GET (gui, "list_expander");
+
+ if (panel_profile_get_enable_program_list ()) {
+ gtk_expander_set_expanded (GTK_EXPANDER (dialog->list_expander),
+ panel_profile_get_show_program_list ());
+
+ if ( ! panel_profile_is_writable_show_program_list ())
+ gtk_widget_set_sensitive (dialog->list_expander, FALSE);
+
+ g_signal_connect (dialog->list_expander, "notify::expanded",
+ G_CALLBACK (list_expander_toggled),
+ dialog);
+
+ client = panel_mateconf_get_client ();
+ key = panel_mateconf_general_key ("show_program_list");
+
+ dialog->content_notify_id =
+ mateconf_client_notify_add (client, key,
+ (MateConfClientNotifyFunc) panel_run_dialog_content_notify,
+ dialog, NULL, NULL);
+
+ if (!dialog->content_notify_id)
+ g_warning ("error setting up content change notification");
+ }
+}
+
+static void
+file_button_browse_response (GtkWidget *chooser,
+ gint response,
+ PanelRunDialog *dialog)
+{
+ char *file;
+
+ if (response == GTK_RESPONSE_OK) {
+ file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+ panel_run_dialog_append_file (dialog, file);
+ g_free (file);
+ }
+
+ gtk_widget_destroy (chooser);
+
+ gtk_widget_grab_focus (dialog->combobox);
+}
+
+static void
+file_button_clicked (GtkButton *button,
+ PanelRunDialog *dialog)
+{
+ GtkWidget *chooser;
+
+ chooser = gtk_file_chooser_dialog_new (_("Choose a file to append to the command..."),
+ GTK_WINDOW (dialog->run_dialog),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
+ g_get_home_dir ());
+
+ gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
+
+ g_signal_connect (chooser, "response",
+ G_CALLBACK (file_button_browse_response), dialog);
+
+ gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static void
+panel_run_dialog_setup_file_button (PanelRunDialog *dialog,
+ GtkBuilder *gui)
+{
+ dialog->file_button = PANEL_GTK_BUILDER_GET (gui, "file_button");
+
+ g_signal_connect (dialog->file_button, "clicked",
+ G_CALLBACK (file_button_clicked),
+ dialog);
+}
+
+static GList *
+fill_files_from (const char *dirname,
+ const char *dirprefix,
+ char prefix,
+ GList *existing_items)
+{
+ GList *list;
+ DIR *dir;
+ struct dirent *dent;
+
+ list = NULL;
+ dir = opendir (dirname);
+
+ if (!dir)
+ return list;
+
+ while ((dent = readdir (dir))) {
+ char *file;
+ char *item;
+ const char *suffix;
+
+ if (!dent->d_name ||
+ dent->d_name [0] != prefix)
+ continue;
+
+ file = g_build_filename (dirname, dent->d_name, NULL);
+
+ suffix = NULL;
+ if (
+#ifdef HAVE_STRUCT_DIRENT_D_TYPE
+ /* don't use g_file_test at first so we don't stat() */
+ dent->d_type == DT_DIR ||
+ (dent->d_type == DT_LNK &&
+ g_file_test (file, G_FILE_TEST_IS_DIR))
+#else
+ g_file_test (file, G_FILE_TEST_IS_DIR)
+#endif
+ )
+ suffix = "/";
+
+ g_free (file);
+
+ item = g_build_filename (dirprefix, dent->d_name, suffix, NULL);
+
+ list = g_list_prepend (list, item);
+ }
+
+ closedir (dir);
+
+ return list;
+}
+
+static GList *
+fill_possible_executables (void)
+{
+ GList *list;
+ const char *path;
+ char **pathv;
+ int i;
+
+ list = NULL;
+ path = g_getenv ("PATH");
+
+ if (!path || !path [0])
+ return list;
+
+ pathv = g_strsplit (path, ":", 0);
+
+ for (i = 0; pathv [i]; i++) {
+ const char *file;
+ char *filename;
+ GDir *dir;
+
+ dir = g_dir_open (pathv [i], 0, NULL);
+
+ if (!dir)
+ continue;
+
+ while ((file = g_dir_read_name (dir))) {
+ filename = g_build_filename (pathv [i], file, NULL);
+ list = g_list_prepend (list, filename);
+ }
+
+ g_dir_close (dir);
+ }
+
+ g_strfreev (pathv);
+
+ return list;
+}
+
+static GList *
+fill_executables (GList *possible_executables,
+ GList *existing_items,
+ char prefix)
+{
+ GList *list;
+ GList *l;
+
+ list = NULL;
+
+ for (l = possible_executables; l; l = l->next) {
+ const char *filename;
+ char *basename;
+
+ filename = l->data;
+ basename = g_path_get_basename (filename);
+
+ if (basename [0] == prefix &&
+ g_file_test (filename, G_FILE_TEST_IS_REGULAR) &&
+ g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE)) {
+
+ if (g_list_find_custom (existing_items, basename,
+ (GCompareFunc) strcmp)) {
+ g_free (basename);
+ return NULL;
+ }
+
+ list = g_list_prepend (list, basename);
+ } else {
+ g_free (basename);
+ }
+ }
+
+ return list;
+}
+
+static void
+panel_run_dialog_update_completion (PanelRunDialog *dialog,
+ const char *text)
+{
+ GList *list;
+ GList *executables;
+ char prefix;
+ char *buf;
+ char *dirname;
+ char *dirprefix;
+ char *key;
+
+ g_assert (text != NULL && *text != '\0' && !g_ascii_isspace (*text));
+
+ list = NULL;
+ executables = NULL;
+
+ if (!dialog->completion) {
+ dialog->completion = g_completion_new (NULL);
+ dialog->possible_executables = fill_possible_executables ();
+ dialog->dir_hash = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free, NULL);
+ }
+
+ buf = g_path_get_basename (text);
+ prefix = buf[0];
+ g_free (buf);
+ if (prefix == '/' || prefix == '.')
+ return;
+
+ if (text [0] == '/') {
+ /* complete against absolute path */
+ dirname = g_path_get_dirname (text);
+ dirprefix = g_strdup (dirname);
+ } else {
+ /* complete against relative path and executable name */
+ if (!strchr (text, '/')) {
+ executables = fill_executables (dialog->possible_executables,
+ dialog->completion_items,
+ text [0]);
+ dirprefix = g_strdup ("");
+ } else {
+ dirprefix = g_path_get_dirname (text);
+ }
+
+ dirname = g_build_filename (g_get_home_dir (), dirprefix, NULL);
+ }
+
+ key = g_strdup_printf ("%s%c%c", dirprefix, G_DIR_SEPARATOR, prefix);
+
+ if (!g_hash_table_lookup (dialog->dir_hash, key)) {
+ g_hash_table_insert (dialog->dir_hash, key, dialog);
+
+ list = fill_files_from (dirname, dirprefix, prefix,
+ dialog->completion_items);
+ } else {
+ g_free (key);
+ }
+
+ list = g_list_concat (list, executables);
+
+ g_free (dirname);
+ g_free (dirprefix);
+
+ if (list == NULL)
+ return;
+
+ g_completion_add_items (dialog->completion, list);
+
+ dialog->completion_items = g_list_concat (dialog->completion_items,
+ list);
+}
+
+static gboolean
+entry_event (GtkEditable *entry,
+ GdkEventKey *event,
+ PanelRunDialog *dialog)
+{
+ GtkTreeSelection *selection;
+ char *prefix;
+ char *nospace_prefix;
+ char *nprefix;
+ char *temp;
+ int pos, tmp;
+
+ if (event->type != GDK_KEY_PRESS)
+ return FALSE;
+
+ /* if user typed something we're not using the list anymore */
+ dialog->use_program_list = FALSE;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list));
+ gtk_tree_selection_unselect_all (selection);
+
+ if (!panel_profile_get_enable_autocompletion ())
+ return FALSE;
+
+ /* tab completion */
+ if (event->keyval == GDK_Tab) {
+ gtk_editable_get_selection_bounds (entry, &pos, &tmp);
+
+ if (dialog->completion_started &&
+ pos != tmp &&
+ pos != 1 &&
+ tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) {
+ gtk_editable_select_region (entry, 0, 0);
+ gtk_editable_set_position (entry, -1);
+
+ return TRUE;
+ }
+ } else if (event->length > 0) {
+
+ gtk_editable_get_selection_bounds (entry, &pos, &tmp);
+
+ if (dialog->completion_started &&
+ pos != tmp &&
+ pos != 0 &&
+ tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) {
+ temp = gtk_editable_get_chars (entry, 0, pos);
+ prefix = g_strconcat (temp, event->string, NULL);
+ g_free (temp);
+ } else if (pos == tmp &&
+ tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) {
+ prefix = g_strconcat (gtk_entry_get_text (GTK_ENTRY (entry)),
+ event->string, NULL);
+ } else {
+ return FALSE;
+ }
+
+ nospace_prefix = prefix;
+ while (*nospace_prefix != '\0' &&
+ g_ascii_isspace (*nospace_prefix))
+ nospace_prefix++;
+ if (*nospace_prefix == '\0')
+ return FALSE;
+
+ panel_run_dialog_update_completion (dialog, nospace_prefix);
+
+ if (!dialog->completion) {
+ g_free (prefix);
+ return FALSE;
+ }
+
+ pos = strlen (prefix);
+ nprefix = NULL;
+
+ g_completion_complete_utf8 (dialog->completion, nospace_prefix,
+ &nprefix);
+
+ if (nprefix) {
+ int insertpos;
+ insertpos = 0;
+
+ temp = g_strndup (prefix, nospace_prefix - prefix);
+ g_free (prefix);
+
+ prefix = g_strconcat (temp, nprefix, NULL);
+
+ g_signal_handler_block (dialog->combobox,
+ dialog->changed_id);
+ gtk_editable_delete_text (entry, 0, -1);
+ g_signal_handler_unblock (dialog->combobox,
+ dialog->changed_id);
+
+ gtk_editable_insert_text (entry,
+ prefix, strlen (prefix),
+ &insertpos);
+
+ gtk_editable_set_position (entry, pos);
+ gtk_editable_select_region (entry, pos, -1);
+
+ dialog->completion_started = TRUE;
+
+ g_free (temp);
+ g_free (nprefix);
+ g_free (prefix);
+
+ return TRUE;
+ }
+
+ g_free (prefix);
+ }
+
+ return FALSE;
+}
+
+static void
+combobox_changed (GtkComboBox *combobox,
+ PanelRunDialog *dialog)
+{
+ char *text;
+ char *start;
+ char *msg;
+
+ text = gtk_combo_box_get_active_text (combobox);
+
+ start = text;
+ while (*start != '\0' && g_ascii_isspace (*start))
+ start++;
+
+ /* update item name to use for dnd */
+ if (!dialog->use_program_list) {
+ if (dialog->desktop_path) {
+ g_free (dialog->desktop_path);
+ dialog->desktop_path = NULL;
+ }
+ if (dialog->item_name) {
+ g_free (dialog->item_name);
+ dialog->item_name = NULL;
+ }
+ }
+
+ /* desensitize run button if no text entered */
+ if (!start || !start [0]) {
+ g_free (text);
+
+ gtk_widget_set_sensitive (dialog->run_button, FALSE);
+ gtk_drag_source_unset (dialog->run_dialog);
+
+ if (panel_profile_get_enable_program_list ())
+ gtk_label_set_text (GTK_LABEL (dialog->program_label),
+ _("Select an application to view its description."));
+
+ panel_run_dialog_set_default_icon (dialog, FALSE);
+
+ if (dialog->find_command_idle_id) {
+ g_source_remove (dialog->find_command_idle_id);
+ dialog->find_command_idle_id = 0;
+ }
+
+ if (panel_profile_get_enable_program_list ()) {
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->program_list_store),
+ panel_run_dialog_make_all_list_visible,
+ NULL);
+
+ path = gtk_tree_path_new_first ();
+ if (gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->program_list)),
+ &iter, path))
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dialog->program_list),
+ path, NULL,
+ FALSE, 0, 0);
+ gtk_tree_path_free (path);
+ }
+
+ return;
+ }
+
+ gtk_widget_set_sensitive (dialog->run_button, TRUE);
+ gtk_drag_source_set (dialog->run_dialog,
+ GDK_BUTTON1_MASK,
+ NULL, 0,
+ GDK_ACTION_COPY);
+ gtk_drag_source_add_uri_targets (dialog->run_dialog);
+
+ if (panel_profile_get_enable_program_list () &&
+ !dialog->use_program_list) {
+ msg = g_strdup_printf (_("Will run command: '%s'"),
+ start);
+ gtk_label_set_text (GTK_LABEL (dialog->program_label), msg);
+ g_free (msg);
+ }
+
+ /* look up icon for the command */
+ if (panel_profile_get_enable_program_list () &&
+ !dialog->use_program_list &&
+ !dialog->find_command_idle_id)
+ dialog->find_command_idle_id =
+ g_idle_add_full (G_PRIORITY_LOW,
+ (GSourceFunc) panel_run_dialog_find_command_idle,
+ dialog, NULL);
+
+ g_free (text);
+}
+
+static void
+entry_drag_data_received (GtkEditable *entry,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ PanelRunDialog *dialog)
+{
+ char **uris;
+ char *file;
+ int i;
+
+ if (gtk_selection_data_get_format (selection_data) != 8 || gtk_selection_data_get_length (selection_data) == 0) {
+ g_warning (_("URI list dropped on run dialog had wrong format (%d) or length (%d)\n"),
+ gtk_selection_data_get_format (selection_data),
+ gtk_selection_data_get_length (selection_data));
+ return;
+ }
+
+ uris = g_uri_list_extract_uris ((const char *)gtk_selection_data_get_data (selection_data));
+
+ if (!uris) {
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ return;
+ }
+
+ for (i = 0; uris [i]; i++) {
+ if (!uris [i] || !uris [i][0])
+ continue;
+
+ file = g_filename_from_uri (uris [i], NULL, NULL);
+
+ /* FIXME: I assume the file is in utf8 encoding if coming from a URI? */
+ if (file) {
+ panel_run_dialog_append_file_utf8 (dialog, file);
+ g_free (file);
+ } else
+ panel_run_dialog_append_file_utf8 (dialog, uris [i]);
+ }
+
+ g_strfreev (uris);
+ gtk_drag_finish (context, TRUE, FALSE, time);
+}
+
+static void
+panel_run_dialog_setup_entry (PanelRunDialog *dialog,
+ GtkBuilder *gui)
+{
+ GdkScreen *screen;
+ int width_request;
+ GtkWidget *entry;
+
+ dialog->combobox = PANEL_GTK_BUILDER_GET (gui, "comboboxentry");
+
+ entry = gtk_bin_get_child (GTK_BIN (dialog->combobox));
+ gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (dialog->combobox),
+ _panel_run_get_recent_programs_list ());
+ gtk_combo_box_entry_set_text_column
+ (GTK_COMBO_BOX_ENTRY (dialog->combobox), 0);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (dialog->run_dialog));
+
+ /* 1/4 the width of the first monitor should be a good value */
+ width_request = panel_multiscreen_width (screen, 0) / 4;
+ g_object_set (G_OBJECT (dialog->combobox),
+ "width_request", width_request,
+ NULL);
+
+ g_signal_connect (entry, "key-press-event",
+ G_CALLBACK (entry_event), dialog);
+
+ dialog->changed_id = g_signal_connect (dialog->combobox, "changed",
+ G_CALLBACK (combobox_changed),
+ dialog);
+
+ gtk_drag_dest_unset (dialog->combobox);
+
+ gtk_drag_dest_set (dialog->combobox,
+ GTK_DEST_DEFAULT_MOTION|GTK_DEST_DEFAULT_HIGHLIGHT,
+ NULL, 0,
+ GDK_ACTION_COPY);
+ gtk_drag_dest_add_uri_targets (dialog->combobox);
+
+ g_signal_connect (dialog->combobox, "drag_data_received",
+ G_CALLBACK (entry_drag_data_received), dialog);
+}
+
+static char *
+panel_run_dialog_create_desktop_file (PanelRunDialog *dialog)
+{
+ GKeyFile *key_file;
+ gboolean exec = FALSE;
+ char *text;
+ char *name;
+ char *disk;
+ char *scheme;
+ char *save_uri;
+
+ text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (dialog->combobox));
+
+ if (!text || !text [0]) {
+ g_free (text);
+ return NULL;
+ }
+
+ key_file = panel_key_file_new_desktop ();
+ disk = g_locale_from_utf8 (text, -1, NULL, NULL, NULL);
+
+ scheme = g_uri_parse_scheme (disk);
+ /* if it's an absolute path or not a URI, it's possibly an executable */
+ if (g_path_is_absolute (disk) || !scheme)
+ exec = command_is_executable (disk, NULL, NULL);
+ g_free (scheme);
+
+ if (exec) {
+ panel_key_file_set_string (key_file, "Type", "Application");
+ panel_key_file_set_string (key_file, "Exec", text);
+ name = g_strdup (text);
+ } else {
+ GFile *file;
+ char *uri;
+
+ file = panel_util_get_file_optional_homedir (disk);
+ uri = g_file_get_uri (file);
+ g_object_unref (file);
+
+ panel_key_file_set_string (key_file, "Type", "Link");
+ panel_key_file_set_string (key_file, "URL", uri);
+ name = uri;
+ }
+
+ g_free (disk);
+
+ panel_key_file_set_locale_string (key_file, "Name",
+ (dialog->item_name) ?
+ dialog->item_name : text);
+
+ panel_key_file_set_boolean (key_file, "Terminal",
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->terminal_checkbox)));
+
+ if (dialog->icon_path)
+ panel_key_file_set_locale_string (key_file, "Icon",
+ dialog->icon_path);
+ else
+ panel_key_file_set_locale_string (key_file, "Icon",
+ PANEL_ICON_LAUNCHER);
+
+ save_uri = panel_make_unique_desktop_uri (g_get_tmp_dir (), name);
+ disk = g_filename_from_uri (save_uri, NULL, NULL);
+
+ if (!disk || !panel_key_file_to_file (key_file, disk, NULL)) {
+ g_free (save_uri);
+ save_uri = NULL;
+ }
+
+ g_key_file_free (key_file);
+ g_free (disk);
+ g_free (name);
+ g_free (text);
+
+ return save_uri;
+}
+
+static void
+pixmap_drag_data_get (GtkWidget *run_dialog,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ PanelRunDialog *dialog)
+{
+ char *uri;
+
+ if (dialog->use_program_list && dialog->desktop_path)
+ uri = g_filename_to_uri (dialog->desktop_path, NULL, NULL);
+ else
+ uri = panel_run_dialog_create_desktop_file (dialog);
+
+ if (uri) {
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8,
+ (unsigned char *) uri, strlen (uri));
+ g_free (uri);
+ }
+}
+
+static void
+panel_run_dialog_style_set (GtkWidget *widget,
+ GtkStyle *prev_style,
+ PanelRunDialog *dialog)
+{
+ if (dialog->icon_path) {
+ char *icon_path;
+
+ icon_path = g_strdup (dialog->icon_path);
+ panel_run_dialog_set_icon (dialog, icon_path, TRUE);
+ g_free (icon_path);
+ }
+}
+
+static void
+panel_run_dialog_screen_changed (GtkWidget *widget,
+ GdkScreen *prev_screen,
+ PanelRunDialog *dialog)
+{
+ if (dialog->icon_path) {
+ char *icon_path;
+
+ icon_path = g_strdup (dialog->icon_path);
+ panel_run_dialog_set_icon (dialog, icon_path, TRUE);
+ g_free (icon_path);
+ }
+}
+
+static void
+panel_run_dialog_setup_pixmap (PanelRunDialog *dialog,
+ GtkBuilder *gui)
+{
+ dialog->pixmap = PANEL_GTK_BUILDER_GET (gui, "icon_pixmap");
+
+ g_signal_connect (dialog->pixmap, "style-set",
+ G_CALLBACK (panel_run_dialog_style_set),
+ dialog);
+ g_signal_connect (dialog->pixmap, "screen-changed",
+ G_CALLBACK (panel_run_dialog_screen_changed),
+ dialog);
+
+ g_signal_connect (dialog->run_dialog, "drag_data_get",
+ G_CALLBACK (pixmap_drag_data_get),
+ dialog);
+}
+
+static PanelRunDialog *
+panel_run_dialog_new (GdkScreen *screen,
+ GtkBuilder *gui,
+ guint32 activate_time)
+{
+ PanelRunDialog *dialog;
+
+ dialog = g_new0 (PanelRunDialog, 1);
+
+ dialog->run_dialog = PANEL_GTK_BUILDER_GET (gui, "panel_run_dialog");
+
+ g_signal_connect_swapped (dialog->run_dialog, "response",
+ G_CALLBACK (panel_run_dialog_response), dialog);
+
+ g_signal_connect_swapped (dialog->run_dialog, "destroy",
+ G_CALLBACK (panel_run_dialog_destroy), dialog);
+
+ dialog->run_button = PANEL_GTK_BUILDER_GET (gui, "run_button");
+ dialog->terminal_checkbox = PANEL_GTK_BUILDER_GET (gui, "terminal_checkbox");
+
+ panel_run_dialog_setup_pixmap (dialog, gui);
+ panel_run_dialog_setup_entry (dialog, gui);
+ panel_run_dialog_setup_file_button (dialog, gui);
+ panel_run_dialog_setup_program_list (dialog, gui);
+ panel_run_dialog_setup_list_expander (dialog, gui);
+
+ panel_run_dialog_set_default_icon (dialog, FALSE);
+
+ panel_run_dialog_update_content (dialog, panel_profile_get_show_program_list ());
+
+ gtk_widget_set_sensitive (dialog->run_button, FALSE);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog->run_dialog),
+ GTK_RESPONSE_OK);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog->run_dialog), screen);
+
+ gtk_widget_grab_focus (dialog->combobox);
+ gtk_widget_realize (dialog->run_dialog);
+ gdk_x11_window_set_user_time (gtk_widget_get_window (dialog->run_dialog),
+ activate_time);
+ gtk_widget_show (dialog->run_dialog);
+
+ return dialog;
+}
+
+static void
+panel_run_dialog_disconnect_pixmap (PanelRunDialog *dialog)
+{
+ g_signal_handlers_disconnect_by_func (dialog->pixmap,
+ G_CALLBACK (panel_run_dialog_style_set),
+ dialog);
+ g_signal_handlers_disconnect_by_func (dialog->pixmap,
+ G_CALLBACK (panel_run_dialog_screen_changed),
+ dialog);
+}
+
+static void
+panel_run_dialog_static_dialog_destroyed (PanelRunDialog *dialog)
+{
+ /* just reset the static dialog to NULL for next time */
+ static_dialog = NULL;
+}
+
+void
+panel_run_dialog_present (GdkScreen *screen,
+ guint32 activate_time)
+{
+ GtkBuilder *gui;
+ GError *error;
+
+ if (panel_lockdown_get_disable_command_line ())
+ return;
+
+ if (static_dialog) {
+ gtk_window_set_screen (GTK_WINDOW (static_dialog->run_dialog), screen);
+ gtk_window_present_with_time (GTK_WINDOW (static_dialog->run_dialog),
+ activate_time);
+ gtk_widget_grab_focus (static_dialog->combobox);
+ return;
+ }
+
+ gui = gtk_builder_new ();
+ gtk_builder_set_translation_domain (gui, GETTEXT_PACKAGE);
+
+ error = NULL;
+ gtk_builder_add_from_file (gui,
+ BUILDERDIR "/panel-run-dialog.ui",
+ &error);
+
+ if (error) {
+ char *secondary;
+
+ secondary = g_strdup_printf (_("Unable to load file '%s': %s."),
+ BUILDERDIR"/panel-run-dialog.ui",
+ error->message);
+ panel_error_dialog (NULL, screen, "cannot_display_run_dialog",
+ TRUE,
+ _("Could not display run dialog"),
+ secondary);
+ g_free (secondary);
+ g_error_free (error);
+ g_object_unref (gui);
+
+ return;
+ }
+
+ static_dialog = panel_run_dialog_new (screen, gui, activate_time);
+
+ g_signal_connect_swapped (static_dialog->run_dialog, "destroy",
+ G_CALLBACK (panel_run_dialog_static_dialog_destroyed),
+ static_dialog);
+
+ g_object_unref (gui);
+}
diff --git a/mate-panel/panel-run-dialog.h b/mate-panel/panel-run-dialog.h
new file mode 100644
index 00000000..fcd3c244
--- /dev/null
+++ b/mate-panel/panel-run-dialog.h
@@ -0,0 +1,41 @@
+/*
+ * panel-run-dialog.h:
+ *
+ * Copyright (C) 2003 Frank Worsley <[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.
+
+ * Authors:
+ * Frank Worsley <[email protected]>
+ */
+
+#ifndef __PANEL_RUN_DIALOG_H__
+#define __PANEL_RUN_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_run_dialog_present (GdkScreen *screen,
+ guint32 activate_time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_RUN_DIALOG_H__ */
diff --git a/mate-panel/panel-run-dialog.ui b/mate-panel/panel-run-dialog.ui
new file mode 100644
index 00000000..d2bb2a86
--- /dev/null
+++ b/mate-panel/panel-run-dialog.ui
@@ -0,0 +1,270 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="panel_run_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Run Application</property>
+ <property name="resizable">False</property>
+ <property name="window_position">center</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="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkVBox" id="main_box">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="entry_box">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkImage" id="icon_pixmap">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="stock">gtk-missing-image</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="icon_pixmap-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes">Command icon</property>
+ <property name="AtkObject::accessible-description" translatable="yes">The icon of the command to be run.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">10</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkComboBoxEntry" id="comboboxentry">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="terminal_checkbox">
+ <property name="label" translatable="yes">Run in _terminal</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="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="terminal_checkbox-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes">Select this box to run the command in a terminal window.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="file_button">
+ <property name="label" translatable="yes">Run with _file...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="file_button-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes">Click this button to browse for a file whose name to append to the command string.</property>
+ </object>
+ </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>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkExpander" id="list_expander">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="expanded">True</property>
+ <child>
+ <object class="GtkVBox" id="program_list_box">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <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="program_list">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="program_list-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes">List of known applications</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="program_label">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">Select an application to view its description.</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">Show list of known _applications</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <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>
+ <child>
+ <object class="GtkButton" id="help_button">
+ <property name="label">gtk-help</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">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label">gtk-cancel</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>
+ <child>
+ <object class="GtkButton" id="run_button">
+ <property name="label" translatable="yes">_Run</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="image">run_button_image</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="run_button-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes">Click this button to run the selected application or the command in the command entry field.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</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">help_button</action-widget>
+ <action-widget response="-6">cancel_button</action-widget>
+ <action-widget response="-5">run_button</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkImage" id="run_button_image">
+ <property name="visible">True</property>
+ <property name="stock">gtk-execute</property>
+ </object>
+</interface>
diff --git a/mate-panel/panel-separator.c b/mate-panel/panel-separator.c
new file mode 100644
index 00000000..9a8e7186
--- /dev/null
+++ b/mate-panel/panel-separator.c
@@ -0,0 +1,250 @@
+/*
+ * panel-separator.c: panel "Separator" module
+ *
+ * Copyright (C) 2005 Carlos Garcia Campos <[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.
+ *
+ * Authors:
+ * Carlos Garcia Campos <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-separator.h"
+#include "panel-background.h"
+#include "panel-profile.h"
+
+#define SEPARATOR_SIZE 10
+
+#define PANEL_SEPARATOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_SEPARATOR, PanelSeparatorPrivate))
+
+struct _PanelSeparatorPrivate {
+ AppletInfo *info;
+ PanelWidget *panel;
+
+ GtkOrientation orientation;
+};
+
+G_DEFINE_TYPE (PanelSeparator, panel_separator, GTK_TYPE_EVENT_BOX)
+
+static void
+panel_separator_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ PanelSeparator *separator;
+ GdkWindow *window;
+ GtkStyle *style;
+ GtkAllocation allocation;
+
+ separator = PANEL_SEPARATOR (widget);
+
+ window = gtk_widget_get_window (widget);
+ style = gtk_widget_get_style (widget);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ if (separator->priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
+ gtk_paint_vline (style, window,
+ gtk_widget_get_state (widget),
+ area, widget, "separator",
+ style->xthickness,
+ allocation.height - style->xthickness,
+ (allocation.width - style->xthickness) / 2);
+ } else {
+ gtk_paint_hline (style, window,
+ gtk_widget_get_state (widget),
+ area, widget, "separator",
+ style->ythickness,
+ allocation.width - style->ythickness,
+ (allocation.height - style->ythickness) / 2);
+ }
+}
+
+static gboolean panel_separator_expose_event(GtkWidget* widget, GdkEventExpose* event)
+{
+ if (gtk_widget_is_drawable(widget))
+ {
+ GTK_WIDGET_CLASS(panel_separator_parent_class)->expose_event(widget, event);
+
+ panel_separator_paint(widget, &event->area);
+ }
+
+ return FALSE;
+}
+
+static void
+panel_separator_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ PanelSeparator *separator;
+ int size;
+
+ separator = PANEL_SEPARATOR (widget);
+
+ size = panel_toplevel_get_size (separator->priv->panel->toplevel);
+
+ if (separator->priv->orientation == GTK_ORIENTATION_VERTICAL) {
+ requisition->width = size;
+ requisition->height = SEPARATOR_SIZE;
+ } else {
+ requisition->width = SEPARATOR_SIZE;
+ requisition->height = size;
+ }
+}
+
+static void
+panel_separator_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkAllocation old_allocation;
+ GtkAllocation widget_allocation;
+ PanelBackground *background;
+
+ gtk_widget_get_allocation (widget, &widget_allocation);
+
+ old_allocation.x = widget_allocation.x;
+ old_allocation.y = widget_allocation.y;
+ old_allocation.width = widget_allocation.width;
+ old_allocation.height = widget_allocation.height;
+
+ GTK_WIDGET_CLASS (panel_separator_parent_class)->size_allocate (widget, allocation);
+
+ if (old_allocation.x == allocation->x &&
+ old_allocation.y == allocation->y &&
+ old_allocation.width == allocation->width &&
+ old_allocation.height == allocation->height)
+ return;
+
+ background = &PANEL_SEPARATOR (widget)->priv->panel->background;
+
+ if (background->type == PANEL_BACK_NONE ||
+ (background->type == PANEL_BACK_COLOR && !background->has_alpha))
+ return;
+
+ panel_separator_change_background (PANEL_SEPARATOR (widget));
+}
+
+static void
+panel_separator_parent_set (GtkWidget *widget,
+ GtkWidget *previous_parent)
+{
+ PanelSeparator *separator;
+ GtkWidget *parent;
+
+ separator = PANEL_SEPARATOR (widget);
+
+ parent = gtk_widget_get_parent (widget);
+ g_assert (!parent || PANEL_IS_WIDGET (parent));
+
+ separator->priv->panel = (PanelWidget *) parent;
+}
+
+static void
+panel_separator_class_init (PanelSeparatorClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->expose_event = panel_separator_expose_event;
+ widget_class->size_request = panel_separator_size_request;
+ widget_class->size_allocate = panel_separator_size_allocate;
+ widget_class->parent_set = panel_separator_parent_set;
+
+ g_type_class_add_private (klass, sizeof (PanelSeparatorPrivate));
+}
+
+static void
+panel_separator_init (PanelSeparator *separator)
+{
+ separator->priv = PANEL_SEPARATOR_GET_PRIVATE (separator);
+
+ separator->priv->info = NULL;
+ separator->priv->panel = NULL;
+ separator->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+}
+
+void
+panel_separator_set_orientation (PanelSeparator *separator,
+ PanelOrientation orientation)
+{
+ GtkOrientation orient = GTK_ORIENTATION_HORIZONTAL;
+
+ g_return_if_fail (PANEL_IS_SEPARATOR (separator));
+
+ switch (orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ orient = GTK_ORIENTATION_HORIZONTAL;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ case PANEL_ORIENTATION_LEFT:
+ orient = GTK_ORIENTATION_VERTICAL;
+ break;
+ }
+
+ if (orient == separator->priv->orientation)
+ return;
+
+ separator->priv->orientation = orient;
+
+ gtk_widget_queue_draw (GTK_WIDGET (separator));
+}
+
+void
+panel_separator_load_from_mateconf (PanelWidget *panel,
+ gboolean locked,
+ int position,
+ const char *id)
+{
+ PanelSeparator *separator;
+
+ separator = g_object_new (PANEL_TYPE_SEPARATOR, NULL);
+
+ separator->priv->info = mate_panel_applet_register (GTK_WIDGET (separator),
+ NULL, NULL,
+ panel, locked, position,
+ TRUE,
+ PANEL_OBJECT_SEPARATOR,
+ id);
+
+ if (!separator->priv->info) {
+ gtk_widget_destroy (GTK_WIDGET (separator));
+ return;
+ }
+
+ panel_widget_set_applet_expandable (panel, GTK_WIDGET (separator),
+ FALSE, TRUE);
+ panel_widget_set_applet_size_constrained (panel,
+ GTK_WIDGET (separator), TRUE);
+}
+
+void
+panel_separator_create (PanelToplevel *toplevel,
+ int position)
+{
+ char *id;
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_SEPARATOR,
+ toplevel, position, FALSE);
+ panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id);
+ g_free (id);
+}
+
+void
+panel_separator_change_background (PanelSeparator *separator)
+{
+ panel_background_change_background_on_widget (&separator->priv->panel->background,
+ GTK_WIDGET (separator));
+}
diff --git a/mate-panel/panel-separator.h b/mate-panel/panel-separator.h
new file mode 100644
index 00000000..a7c699b8
--- /dev/null
+++ b/mate-panel/panel-separator.h
@@ -0,0 +1,71 @@
+/*
+ * panel-separator.h: panel "Separator" module
+ *
+ * Copyright (C) 2005 Carlos Garcia Campos <[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.
+ *
+ * Authors:
+ * Carlos Garcia Campos <[email protected]>
+ */
+
+#ifndef PANEL_SEPARATOR_H
+#define PANEL_SEPARATOR_H
+
+#include "applet.h"
+#include "panel-widget.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_SEPARATOR (panel_separator_get_type ())
+#define PANEL_SEPARATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_SEPARATOR, PanelSeparator))
+#define PANEL_SEPARATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_SEPARATOR, PanelSeparatorClass))
+#define PANEL_IS_SEPARATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_SEPARATOR))
+#define PANEL_IS_SEPARATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_SEPARATOR))
+#define PANEL_SEPARATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_SEPARATOR, PanelSeparatorClass))
+
+typedef struct _PanelSeparator PanelSeparator;
+typedef struct _PanelSeparatorClass PanelSeparatorClass;
+typedef struct _PanelSeparatorPrivate PanelSeparatorPrivate;
+
+struct _PanelSeparator {
+ GtkEventBox parent;
+
+ PanelSeparatorPrivate *priv;
+};
+
+struct _PanelSeparatorClass {
+ GtkEventBoxClass parent_class;
+};
+
+GType panel_separator_get_type (void) G_GNUC_CONST;
+void panel_separator_create (PanelToplevel *toplevel,
+ int position);
+void panel_separator_load_from_mateconf (PanelWidget *panel_widget,
+ gboolean locked,
+ gint position,
+ const char *id);
+void panel_separator_set_orientation (PanelSeparator *separator,
+ PanelOrientation orientation);
+void panel_separator_change_background (PanelSeparator *separator);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_SEPARATOR_H */
diff --git a/mate-panel/panel-session.c b/mate-panel/panel-session.c
new file mode 100644
index 00000000..1175b3dc
--- /dev/null
+++ b/mate-panel/panel-session.c
@@ -0,0 +1,80 @@
+/*
+ * panel-session.c: panel session management routines
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <gdk/gdk.h>
+
+#include <libegg/eggsmclient.h>
+
+#include "panel-shell.h"
+
+#include "panel-session.h"
+
+static gboolean do_not_restart = FALSE;
+
+static void
+panel_session_handle_quit (EggSMClient *client,
+ gpointer data)
+{
+ panel_shell_quit ();
+}
+
+void
+panel_session_do_not_restart (void)
+{
+ do_not_restart = TRUE;
+
+ if (egg_sm_client_get_mode () != EGG_SM_CLIENT_MODE_DISABLED)
+ egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_NO_RESTART);
+}
+
+void
+panel_session_init (void)
+{
+ EggSMClientMode mode;
+ EggSMClient *client;
+
+ /* Explicitly tell the session manager we're ready -- we don't do it
+ * before. Note: this depends on setting the mode to DISABLED early
+ * during startup. */
+
+ if (do_not_restart || getenv ("MATE_PANEL_DEBUG"))
+ mode = EGG_SM_CLIENT_MODE_NO_RESTART;
+ else
+ mode = EGG_SM_CLIENT_MODE_NORMAL;
+
+ egg_sm_client_set_mode (mode);
+
+ client = egg_sm_client_get ();
+
+ g_signal_connect (client, "quit",
+ G_CALLBACK (panel_session_handle_quit), NULL);
+
+ /* We don't want the WM to try and save/restore our
+ * window position */
+ gdk_set_sm_client_id (NULL);
+}
diff --git a/mate-panel/panel-session.h b/mate-panel/panel-session.h
new file mode 100644
index 00000000..528d9059
--- /dev/null
+++ b/mate-panel/panel-session.h
@@ -0,0 +1,39 @@
+/*
+ * panel-session.h: panel session management routines
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_SESSION_H__
+#define __PANEL_SESSION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void panel_session_init (void);
+void panel_session_do_not_restart (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_SESSION_H__ */
diff --git a/mate-panel/panel-shell.c b/mate-panel/panel-shell.c
new file mode 100644
index 00000000..d54da4b9
--- /dev/null
+++ b/mate-panel/panel-shell.c
@@ -0,0 +1,164 @@
+/*
+ * panel-shell.c: panel shell interface implementation
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2010 Carlos Garcia Campos <[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.
+ *
+ * Authors:
+ * Jacob Berkman <[email protected]>
+ * Colin Walters <[email protected]>
+ * Vincent Untz <[email protected]>
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include <libpanel-util/panel-cleanup.h>
+
+#include "panel-profile.h"
+#include "panel-session.h"
+
+#include "panel-shell.h"
+
+#define PANEL_DBUS_SERVICE "org.mate.Panel"
+
+static GDBusConnection *dbus_connection = NULL;
+
+static void
+panel_shell_on_name_lost (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ /* We lost our DBus name, and there is something replacing us.
+ * Tell the SM not to restart us automatically, then exit. */
+ g_printerr ("Panel leaving: a new panel shell is starting.\n");
+
+ panel_session_do_not_restart ();
+ panel_shell_quit ();
+}
+
+static void
+panel_shell_cleanup (gpointer data)
+{
+ if (dbus_connection != NULL) {
+ g_object_unref (dbus_connection);
+ dbus_connection = NULL;
+ }
+}
+
+gboolean
+panel_shell_register (gboolean replace)
+{
+ GBusNameOwnerFlags flags;
+ guint32 request_name_reply;
+ GVariant *result;
+ gboolean retval = FALSE;
+ GError *error = NULL;
+
+ if (dbus_connection != NULL)
+ return TRUE;
+
+ panel_cleanup_register (PANEL_CLEAN_FUNC (panel_shell_cleanup), NULL);
+
+ /* There isn't a sync version of g_bus_own_name, so we have to requeste
+ * the name manually here. There's no ui yet so it's safe to use this
+ * sync api */
+ dbus_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (dbus_connection == NULL) {
+ g_warning ("Cannot register the panel shell: %s", error->message);
+ goto register_out;
+ }
+
+ flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
+ if (replace)
+ flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
+
+ result = g_dbus_connection_call_sync (dbus_connection,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "RequestName",
+ g_variant_new ("(su)",
+ PANEL_DBUS_SERVICE,
+ flags),
+ G_VARIANT_TYPE ("(u)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (!result) {
+ g_warning ("Cannot register the panel shell: %s",
+ error->message);
+ g_error_free (error);
+
+ goto register_out;
+ }
+
+ g_variant_get (result, "(u)", &request_name_reply);
+ g_variant_unref (result);
+
+ switch (request_name_reply) {
+ case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */
+ case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */
+ retval = TRUE;
+ g_dbus_connection_signal_subscribe (dbus_connection,
+ "org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameLost",
+ "/org/freedesktop/DBus",
+ PANEL_DBUS_SERVICE,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ (GDBusSignalCallback)panel_shell_on_name_lost,
+ NULL, NULL);
+ break;
+ case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */
+ case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */
+ g_printerr ("Cannot register the panel shell: there is "
+ "already one running.\n");
+ break;
+ default:
+ g_warning ("Cannot register the panel shell: unhandled "
+ "reply %u from RequestName", request_name_reply);
+ }
+
+register_out:
+
+ if (!retval) {
+ panel_session_do_not_restart ();
+ panel_shell_cleanup (NULL);
+ }
+
+ return retval;
+}
+
+void
+panel_shell_quit (void)
+{
+ GSList *toplevels_to_destroy, *l;
+
+ toplevels_to_destroy = g_slist_copy (panel_toplevel_list_toplevels ());
+ for (l = toplevels_to_destroy; l; l = l->next)
+ gtk_widget_destroy (l->data);
+ g_slist_free (toplevels_to_destroy);
+
+ gtk_main_quit ();
+}
diff --git a/mate-panel/panel-shell.h b/mate-panel/panel-shell.h
new file mode 100644
index 00000000..a779c815
--- /dev/null
+++ b/mate-panel/panel-shell.h
@@ -0,0 +1,37 @@
+/*
+ * panel-shell.h: panel shell interface implementation
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 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 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.
+ *
+ * Authors:
+ * Jacob Berkman <[email protected]>
+ * Colin Walters <[email protected]>
+ * Vincent Untz <[email protected]>
+ */
+
+#ifndef __PANEL_SHELL_H__
+#define __PANEL_SHELL_H__
+
+#include <glib.h>
+
+gboolean panel_shell_register (gboolean replace);
+void panel_shell_quit (void);
+
+#endif /* __PANEL_SHELL_H__ */
diff --git a/mate-panel/panel-stock-icons.c b/mate-panel/panel-stock-icons.c
new file mode 100644
index 00000000..f7621a77
--- /dev/null
+++ b/mate-panel/panel-stock-icons.c
@@ -0,0 +1,141 @@
+/*
+ * panel-stock-icons.c panel stock icons registration
+ *
+ * Copyright (C) 2002 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include "config.h"
+
+#include "panel-stock-icons.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "panel-icon-names.h"
+
+static GtkIconSize panel_menu_icon_size = 0;
+static GtkIconSize panel_menu_bar_icon_size = 0;
+
+GtkIconSize
+panel_menu_icon_get_size (void)
+{
+ return panel_menu_icon_size;
+}
+
+GtkIconSize
+panel_menu_bar_icon_get_size (void)
+{
+ return panel_menu_bar_icon_size;
+}
+
+typedef struct {
+ char *stock_id;
+ char *icon;
+} PanelStockIcon;
+
+static PanelStockIcon stock_icons [] = {
+ { PANEL_STOCK_FORCE_QUIT, PANEL_ICON_FORCE_QUIT }
+};
+
+static void
+panel_init_stock_icons (GtkIconFactory *factory)
+{
+ GtkIconSource *source;
+ int i;
+
+
+ source = gtk_icon_source_new ();
+
+ for (i = 0; i < G_N_ELEMENTS (stock_icons); i++) {
+ GtkIconSet *set;
+
+ gtk_icon_source_set_icon_name (source, stock_icons [i].icon);
+
+ set = gtk_icon_set_new ();
+ gtk_icon_set_add_source (set, source);
+
+ gtk_icon_factory_add (factory, stock_icons [i].stock_id, set);
+ gtk_icon_set_unref (set);
+ }
+
+ gtk_icon_source_free (source);
+
+}
+
+typedef struct {
+ char *stock_id;
+ char *stock_icon_id;
+ char *label;
+} PanelStockItem;
+
+static PanelStockItem stock_items [] = {
+ { PANEL_STOCK_EXECUTE, GTK_STOCK_EXECUTE, N_("_Run") },
+ { PANEL_STOCK_FORCE_QUIT, PANEL_STOCK_FORCE_QUIT, N_("_Force quit") },
+ { PANEL_STOCK_CLEAR, GTK_STOCK_CLEAR, N_("C_lear") },
+ { PANEL_STOCK_DONT_DELETE, GTK_STOCK_CANCEL, N_("D_on't Delete") }
+};
+
+static void
+panel_init_stock_items (GtkIconFactory *factory)
+{
+ GtkStockItem *items;
+ int i;
+
+ items = g_new (GtkStockItem, G_N_ELEMENTS (stock_items));
+
+ for (i = 0; i < G_N_ELEMENTS (stock_items); i++) {
+ GtkIconSet *icon_set;
+
+ items [i].stock_id = g_strdup (stock_items [i].stock_id);
+ items [i].label = g_strdup (stock_items [i].label);
+ items [i].modifier = 0;
+ items [i].keyval = 0;
+ items [i].translation_domain = g_strdup (GETTEXT_PACKAGE);
+
+ /* FIXME: does this take into account the theme? */
+ icon_set = gtk_icon_factory_lookup_default (stock_items [i].stock_icon_id);
+ gtk_icon_factory_add (factory, stock_items [i].stock_id, icon_set);
+ }
+
+ gtk_stock_add_static (items, G_N_ELEMENTS (stock_items));
+}
+
+void
+panel_init_stock_icons_and_items (void)
+{
+ GtkIconFactory *factory;
+
+ panel_menu_icon_size = gtk_icon_size_register ("panel-menu",
+ PANEL_DEFAULT_MENU_ICON_SIZE,
+ PANEL_DEFAULT_MENU_ICON_SIZE);
+
+ panel_menu_bar_icon_size = gtk_icon_size_register ("panel-foobar",
+ PANEL_DEFAULT_MENU_BAR_ICON_SIZE,
+ PANEL_DEFAULT_MENU_BAR_ICON_SIZE);
+
+ factory = gtk_icon_factory_new ();
+ gtk_icon_factory_add_default (factory);
+
+ panel_init_stock_icons (factory);
+ panel_init_stock_items (factory);
+
+ g_object_unref (factory);
+}
diff --git a/mate-panel/panel-stock-icons.h b/mate-panel/panel-stock-icons.h
new file mode 100644
index 00000000..cb6085f4
--- /dev/null
+++ b/mate-panel/panel-stock-icons.h
@@ -0,0 +1,60 @@
+/*
+ * panel-stock-icons.h: panel stock icons registration
+ *
+ * Copyright (C) 2002 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_STOCK_ICONS_H__
+#define __PANEL_STOCK_ICONS_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* themeable size - "panel-menu" -- This is used for the icons in the menus */
+#define PANEL_DEFAULT_MENU_ICON_SIZE 24
+/* themeable size - "panel-foobar" -- This is only used for the icon of the
+ * Applications item in the menu bar */
+#define PANEL_DEFAULT_MENU_BAR_ICON_SIZE 24
+
+/* stock icons */
+#define PANEL_STOCK_FORCE_QUIT "mate-panel-force-quit"
+
+/* stock items - no point in theme the icons one these,
+ * they use stock gtk icons and just modify the text
+ * for the stock item.
+ */
+#define PANEL_STOCK_EXECUTE "panel-execute"
+#define PANEL_STOCK_CLEAR "panel-clear"
+#define PANEL_STOCK_DONT_DELETE "panel-dont-delete"
+
+void panel_init_stock_icons_and_items (void);
+GtkIconSize panel_menu_icon_get_size (void);
+GtkIconSize panel_menu_bar_icon_get_size (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_STOCK_ICONS_H__ */
diff --git a/mate-panel/panel-struts.c b/mate-panel/panel-struts.c
new file mode 100644
index 00000000..b75bf704
--- /dev/null
+++ b/mate-panel/panel-struts.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2003,2004 Rob Adams
+ *
+ * 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-struts.h"
+
+#include "panel-multiscreen.h"
+#include "panel-xutils.h"
+
+
+typedef struct {
+ PanelToplevel *toplevel;
+
+ GdkScreen *screen;
+ int monitor;
+
+ PanelOrientation orientation;
+ GdkRectangle geometry;
+ int strut_size;
+ int strut_start;
+ int strut_end;
+
+ GdkRectangle allocated_geometry;
+ int allocated_strut_size;
+ int allocated_strut_start;
+ int allocated_strut_end;
+} PanelStrut;
+
+
+static GSList *panel_struts_list = NULL;
+
+
+static inline PanelStrut *
+panel_struts_find_strut (PanelToplevel *toplevel)
+{
+ GSList *l;
+
+ for (l = panel_struts_list; l; l = l->next) {
+ PanelStrut *strut = l->data;
+
+ if (strut->toplevel == toplevel)
+ break;
+ }
+
+ return l ? l->data : NULL;
+}
+
+static void
+panel_struts_get_monitor_geometry (GdkScreen *screen,
+ int monitor,
+ int *x,
+ int *y,
+ int *width,
+ int *height)
+{
+ *x = panel_multiscreen_x (screen, monitor);
+ *y = panel_multiscreen_y (screen, monitor);
+ *width = panel_multiscreen_width (screen, monitor);
+ *height = panel_multiscreen_height (screen, monitor);
+}
+
+static PanelStrut *
+panel_struts_intersect (GSList *struts,
+ GdkRectangle *geometry,
+ int skip)
+{
+ GSList *l;
+ int i;
+
+ i = 0;
+ for (l = struts; l; l = l->next) {
+ PanelStrut *strut = l->data;
+ int x1, y1, x2, y2;
+
+ x1 = MAX (strut->allocated_geometry.x, geometry->x);
+ y1 = MAX (strut->allocated_geometry.y, geometry->y);
+
+ x2 = MIN (strut->allocated_geometry.x + strut->allocated_geometry.width,
+ geometry->x + geometry->width);
+ y2 = MIN (strut->allocated_geometry.y + strut->allocated_geometry.height,
+ geometry->y + geometry->height);
+
+ if (x2 - x1 > 0 && y2 - y1 > 0 && ++i > skip)
+ break;
+ }
+
+ return l ? l->data : NULL;
+}
+
+static int
+panel_struts_allocation_overlapped (PanelStrut *strut,
+ PanelStrut *overlap,
+ GdkRectangle *geometry,
+ gboolean *moved_down,
+ int skip)
+{
+ int overlap_x1, overlap_y1, overlap_x2, overlap_y2;
+
+ overlap_x1 = overlap->allocated_geometry.x;
+ overlap_y1 = overlap->allocated_geometry.y;
+ overlap_x2 = overlap->allocated_geometry.x + overlap->allocated_geometry.width;
+ overlap_y2 = overlap->allocated_geometry.y + overlap->allocated_geometry.height;
+
+ if (strut->orientation == overlap->orientation) {
+ int old_x, old_y;
+
+ old_x = geometry->x;
+ old_y = geometry->y;
+
+ switch (strut->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ geometry->y = overlap_y2;
+ strut->allocated_strut_size += geometry->y - old_y;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ geometry->y = overlap_y1 - geometry->height;
+ strut->allocated_strut_size += old_y - geometry->y;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ geometry->x = overlap_x2;
+ strut->allocated_strut_size += geometry->x - old_x;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ geometry->x = overlap_x1 - geometry->width;
+ strut->allocated_strut_size += old_x - geometry->x;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ } else {
+ if (strut->orientation & PANEL_HORIZONTAL_MASK ||
+ overlap->orientation & PANEL_VERTICAL_MASK)
+ return ++skip;
+
+ switch (overlap->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ geometry->y = overlap_y2;
+ *moved_down = TRUE;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ if (!*moved_down)
+ geometry->y = overlap_y1 - geometry->height;
+ else if (overlap_y1 > geometry->y)
+ geometry->height = overlap_y1 - geometry->y;
+ else
+ return ++skip;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ strut->allocated_strut_start = geometry->y;
+ strut->allocated_strut_end = geometry->y + geometry->height - 1;
+ }
+
+ return skip;
+}
+
+static gboolean
+panel_struts_allocate_struts (PanelToplevel *toplevel,
+ GdkScreen *screen,
+ int monitor)
+{
+ GSList *allocated = NULL;
+ GSList *l;
+ gboolean toplevel_changed = FALSE;
+
+ for (l = panel_struts_list; l; l = l->next) {
+ PanelStrut *strut = l->data;
+ PanelStrut *overlap;
+ GdkRectangle geometry;
+ int monitor_x, monitor_y;
+ int monitor_width, monitor_height;
+ gboolean moved_down;
+ int skip;
+
+ if (strut->screen != screen || strut->monitor != monitor)
+ continue;
+
+ panel_struts_get_monitor_geometry (strut->screen, strut->monitor,
+ &monitor_x, &monitor_y,
+ &monitor_width, &monitor_height);
+
+ strut->allocated_strut_size = strut->strut_size;
+ strut->allocated_strut_start = strut->strut_start;
+ strut->allocated_strut_end = strut->strut_end;
+
+ geometry = strut->geometry;
+
+ moved_down = FALSE;
+ skip = 0;
+ while ((overlap = panel_struts_intersect (allocated, &geometry, skip)))
+ skip = panel_struts_allocation_overlapped (
+ strut, overlap, &geometry, &moved_down, skip);
+
+ if (strut->orientation & PANEL_VERTICAL_MASK) {
+ if (geometry.y < monitor_y) {
+ geometry.height = geometry.y + geometry.height - monitor_y;
+ geometry.y = monitor_y;
+ }
+
+ if (geometry.y + geometry.height > monitor_y + monitor_height)
+ geometry.height = monitor_y + monitor_height - geometry.y;
+ }
+
+ if (strut->allocated_geometry.x != geometry.x ||
+ strut->allocated_geometry.y != geometry.y ||
+ strut->allocated_geometry.width != geometry.width ||
+ strut->allocated_geometry.height != geometry.height) {
+ strut->allocated_geometry = geometry;
+
+ if (strut->toplevel == toplevel)
+ toplevel_changed = TRUE;
+ else
+ gtk_widget_queue_resize (GTK_WIDGET (strut->toplevel));
+ }
+
+ allocated = g_slist_append (allocated, strut);
+ }
+
+ g_slist_free (allocated);
+
+ return toplevel_changed;
+}
+
+void
+panel_struts_set_window_hint (PanelToplevel *toplevel)
+{
+ GtkWidget *widget;
+ PanelStrut *strut;
+ int strut_size;
+ int monitor_x, monitor_y, monitor_width, monitor_height;
+ int screen_width, screen_height;
+ int leftmost, rightmost, topmost, bottommost;
+
+ widget = GTK_WIDGET (toplevel);
+
+ if (!gtk_widget_get_realized (widget))
+ return;
+
+ if (!(strut = panel_struts_find_strut (toplevel))) {
+ panel_struts_unset_window_hint (toplevel);
+ return;
+ }
+
+ strut_size = strut->allocated_strut_size;
+
+ screen_width = gdk_screen_get_width (strut->screen);
+ screen_height = gdk_screen_get_height (strut->screen);
+
+ panel_struts_get_monitor_geometry (strut->screen,
+ strut->monitor,
+ &monitor_x,
+ &monitor_y,
+ &monitor_width,
+ &monitor_height);
+
+ panel_multiscreen_is_at_visible_extreme (strut->screen,
+ strut->monitor,
+ &leftmost,
+ &rightmost,
+ &topmost,
+ &bottommost);
+
+ switch (strut->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ if (monitor_y > 0)
+ strut_size += monitor_y;
+ if (!topmost) strut_size = 0;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ if (monitor_y + monitor_height < screen_height)
+ strut_size += screen_height - (monitor_y + monitor_height);
+ if (!bottommost) strut_size = 0;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ if (leftmost && monitor_x > 0)
+ strut_size += monitor_x;
+ if (!leftmost) strut_size = 0;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ if (monitor_x + monitor_width < screen_width)
+ strut_size += screen_width - (monitor_x + monitor_width);
+ if (!rightmost) strut_size = 0;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ panel_xutils_set_strut (gtk_widget_get_window (widget),
+ strut->orientation,
+ strut_size,
+ strut->allocated_strut_start,
+ strut->allocated_strut_end);
+}
+
+void
+panel_struts_unset_window_hint (PanelToplevel *toplevel)
+{
+ if (!gtk_widget_get_realized (GTK_WIDGET (toplevel)))
+ return;
+
+ panel_xutils_set_strut (gtk_widget_get_window (GTK_WIDGET (toplevel)), 0, 0, 0, 0);
+}
+
+static inline int
+orientation_to_order (PanelOrientation orientation)
+{
+ switch (orientation) {
+ case PANEL_ORIENTATION_TOP:
+ return 1;
+ case PANEL_ORIENTATION_BOTTOM:
+ return 2;
+ case PANEL_ORIENTATION_LEFT:
+ return 3;
+ case PANEL_ORIENTATION_RIGHT:
+ return 4;
+ default:
+ g_assert_not_reached ();
+ return -1;
+ }
+}
+
+static inline int
+get_toplevel_depth (PanelToplevel *toplevel)
+{
+ int depth = 0;
+
+ while ((toplevel = panel_toplevel_get_attach_toplevel (toplevel)))
+ depth++;
+
+ return depth;
+}
+
+/* Sort in order of
+ * 1) screen
+ * 2) monitor
+ * 3) depth (for drawers)
+ * 4) top, bottom, left, right
+ * 5) strut_start ascending
+ * 6) strut_end descending
+ */
+static int
+panel_struts_compare (const PanelStrut *s1,
+ const PanelStrut *s2)
+{
+ int s1_depth;
+ int s2_depth;
+
+ if (s1->screen != s2->screen)
+ return gdk_screen_get_number (s1->screen) -
+ gdk_screen_get_number (s2->screen);
+
+ if (s1->monitor != s2->monitor)
+ return s1->monitor - s2->monitor;
+
+ s1_depth = get_toplevel_depth (s1->toplevel);
+ s2_depth = get_toplevel_depth (s2->toplevel);
+ if (s1_depth != s2_depth)
+ return s2_depth - s1_depth;
+
+ if (s1->orientation != s2->orientation)
+ return orientation_to_order (s1->orientation) -
+ orientation_to_order (s2->orientation);
+
+ if (s1->strut_start != s2->strut_start)
+ return s1->strut_start - s2->strut_start;
+
+ if (s1->strut_end != s2->strut_end)
+ return s2->strut_end - s1->strut_end;
+
+ return 0;
+}
+
+gboolean
+panel_struts_register_strut (PanelToplevel *toplevel,
+ GdkScreen *screen,
+ int monitor,
+ PanelOrientation orientation,
+ int strut_size,
+ int strut_start,
+ int strut_end)
+{
+ PanelStrut *strut;
+ gboolean new_strut = FALSE;
+ int monitor_x, monitor_y, monitor_width, monitor_height;
+
+ if (!(strut = panel_struts_find_strut (toplevel))) {
+ strut = g_new0 (PanelStrut, 1);
+ new_strut = TRUE;
+
+ } else if (strut->toplevel == toplevel &&
+ strut->orientation == orientation &&
+ strut->screen == screen &&
+ strut->monitor == monitor &&
+ strut->strut_size == strut_size &&
+ strut->strut_start == strut_start &&
+ strut->strut_end == strut_end)
+ return FALSE;
+
+ strut->toplevel = toplevel;
+ strut->orientation = orientation;
+ strut->screen = screen;
+ strut->monitor = monitor;
+ strut->strut_size = strut_size;
+ strut->strut_start = strut_start;
+ strut->strut_end = strut_end;
+
+ panel_struts_get_monitor_geometry (screen, monitor,
+ &monitor_x, &monitor_y,
+ &monitor_width, &monitor_height);
+
+ switch (strut->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ strut->geometry.x = strut->strut_start;
+ strut->geometry.y = monitor_y;
+ strut->geometry.width = strut->strut_end - strut->strut_start + 1;
+ strut->geometry.height = strut->strut_size;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ strut->geometry.x = strut->strut_start;
+ strut->geometry.y = monitor_y + monitor_height - strut->strut_size;
+ strut->geometry.width = strut->strut_end - strut->strut_start + 1;
+ strut->geometry.height = strut->strut_size;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ strut->geometry.x = monitor_x;
+ strut->geometry.y = strut->strut_start;
+ strut->geometry.width = strut->strut_size;
+ strut->geometry.height = strut->strut_end - strut->strut_start + 1;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ strut->geometry.x = monitor_x + monitor_width - strut->strut_size;
+ strut->geometry.y = strut->strut_start;
+ strut->geometry.width = strut->strut_size;
+ strut->geometry.height = strut->strut_end - strut->strut_start + 1;
+ break;
+ }
+
+ if (new_strut)
+ panel_struts_list = g_slist_append (panel_struts_list, strut);
+
+ panel_struts_list = g_slist_sort (panel_struts_list,
+ (GCompareFunc) panel_struts_compare);
+
+ return panel_struts_allocate_struts (toplevel, screen, monitor);
+}
+
+void
+panel_struts_unregister_strut (PanelToplevel *toplevel)
+{
+ PanelStrut *strut;
+ GdkScreen *screen;
+ int monitor;
+
+ if (!(strut = panel_struts_find_strut (toplevel)))
+ return;
+
+ screen = strut->screen;
+ monitor = strut->monitor;
+
+ panel_struts_list = g_slist_remove (panel_struts_list, strut);
+ g_free (strut);
+
+ panel_struts_allocate_struts (toplevel, screen, monitor);
+}
+
+gboolean
+panel_struts_update_toplevel_geometry (PanelToplevel *toplevel,
+ int *x,
+ int *y,
+ int *width,
+ int *height)
+{
+ PanelStrut *strut;
+
+ g_return_val_if_fail (x != NULL, FALSE);
+ g_return_val_if_fail (y != NULL, FALSE);
+
+ if (!(strut = panel_struts_find_strut (toplevel)))
+ return FALSE;
+
+ *x += strut->allocated_geometry.x - strut->geometry.x;
+ *y += strut->allocated_geometry.y - strut->geometry.y;
+
+ if (width != NULL && *width != -1)
+ *width += strut->allocated_geometry.width - strut->geometry.width;
+ if (height != NULL && *height != -1)
+ *height += strut->allocated_geometry.height - strut->geometry.height;
+
+ return TRUE;
+}
diff --git a/mate-panel/panel-struts.h b/mate-panel/panel-struts.h
new file mode 100644
index 00000000..e7ef420d
--- /dev/null
+++ b/mate-panel/panel-struts.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003 Sun Microsystems, 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_STRUTS_H__
+#define __PANEL_STRUTS_H__
+
+#include <glib.h>
+#include "panel-toplevel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean panel_struts_register_strut (PanelToplevel *toplevel,
+ GdkScreen *screen,
+ int monitor,
+ PanelOrientation orientation,
+ int strut_size,
+ int strut_start,
+ int strut_end);
+
+void panel_struts_unregister_strut (PanelToplevel *toplevel);
+
+void panel_struts_set_window_hint (PanelToplevel *toplevel);
+void panel_struts_unset_window_hint (PanelToplevel *toplevel);
+
+gboolean panel_struts_update_toplevel_geometry (PanelToplevel *toplevel,
+ int *x,
+ int *y,
+ int *w,
+ int *h);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_STRUTS_H__ */
diff --git a/mate-panel/panel-test-applets.c b/mate-panel/panel-test-applets.c
new file mode 100644
index 00000000..ed844c89
--- /dev/null
+++ b/mate-panel/panel-test-applets.c
@@ -0,0 +1,388 @@
+/*
+ * panel-test-applets.c:
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ *
+ * Copyright 2002 Sun Microsystems, Inc.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf.h>
+
+#include <libpanel-util/panel-cleanup.h>
+
+#include <libmate-panel-applet-private/mate-panel-applet-container.h>
+#include <libmate-panel-applet-private/mate-panel-applets-manager-dbus.h>
+
+#include "panel-modules.h"
+
+G_GNUC_UNUSED void on_execute_button_clicked (GtkButton *button, gpointer dummy);
+
+static GtkWidget *win = NULL;
+static GtkWidget *applet_combo = NULL;
+static GtkWidget *prefs_dir_entry = NULL;
+static GtkWidget *orient_combo = NULL;
+static GtkWidget *size_combo = NULL;
+
+static char *cli_iid = NULL;
+static char *cli_prefs_dir = NULL;
+static char *cli_size = NULL;
+static char *cli_orient = NULL;
+
+static const GOptionEntry options [] = {
+ { "iid", 0, 0, G_OPTION_ARG_STRING, &cli_iid, N_("Specify an applet IID to load"), NULL},
+ { "prefs-dir", 0, 0, G_OPTION_ARG_STRING, &cli_prefs_dir, N_("Specify a mateconf location in which the applet preferences should be stored"), NULL},
+ { "size", 0, 0, G_OPTION_ARG_STRING, &cli_size, N_("Specify the initial size of the applet (xx-small, medium, large etc.)"), NULL},
+ { "orient", 0, 0, G_OPTION_ARG_STRING, &cli_orient, N_("Specify the initial orientation of the applet (top, bottom, left or right)"), NULL},
+ { NULL}
+};
+
+enum {
+ COLUMN_TEXT,
+ COLUMN_ITEM,
+ NUMBER_COLUMNS
+};
+
+typedef struct {
+ const char *name;
+ guint value;
+} ComboItem;
+
+static ComboItem orient_items [] = {
+ { NC_("Orientation", "Top"), PANEL_ORIENTATION_TOP },
+ { NC_("Orientation", "Bottom"), PANEL_ORIENTATION_BOTTOM },
+ { NC_("Orientation", "Left"), PANEL_ORIENTATION_LEFT },
+ { NC_("Orientation", "Right"), PANEL_ORIENTATION_RIGHT }
+};
+
+
+static ComboItem size_items [] = {
+ { NC_("Size", "XX Small"), 12 },
+ { NC_("Size", "X Small"), 24 },
+ { NC_("Size", "Small"), 36 },
+ { NC_("Size", "Medium"), 48 },
+ { NC_("Size", "Large"), 64 },
+ { NC_("Size", "X Large"), 80 },
+ { NC_("Size", "XX Large"), 128 }
+};
+
+static guint
+get_combo_value (GtkWidget *combo_box)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ guint value;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box), &iter))
+ return 0;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ gtk_tree_model_get (model, &iter, COLUMN_ITEM, &value, -1);
+
+ return value;
+}
+
+static gchar *
+get_combo_applet_id (GtkWidget *combo_box)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ char *value;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box), &iter))
+ return NULL;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ gtk_tree_model_get (model, &iter, COLUMN_ITEM, &value, -1);
+
+ return value;
+}
+
+static void
+applet_broken_cb (GtkWidget *container,
+ GtkWidget *window)
+{
+ gtk_widget_destroy (window);
+}
+
+static void
+applet_activated_cb (GObject *source_object,
+ GAsyncResult *res,
+ GtkWidget *applet_window)
+{
+ GError *error = NULL;
+
+ if (!mate_panel_applet_container_add_finish (MATE_PANEL_APPLET_CONTAINER (source_object),
+ res, &error)) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (applet_window),
+ GTK_DIALOG_MODAL|
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Failed to load applet %s"),
+ error->message); // FIXME
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ return;
+ }
+
+ gtk_widget_show (applet_window);
+}
+
+static void
+load_applet_into_window (const char *title,
+ const char *prefs_key,
+ guint size,
+ guint orientation)
+{
+ GtkWidget *container;
+ GtkWidget *applet_window;
+ GVariantBuilder builder;
+
+ container = mate_panel_applet_container_new ();
+
+ applet_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ //FIXME: we could set the window icon with the applet icon
+ gtk_window_set_title (GTK_WINDOW (applet_window), title);
+ gtk_container_add (GTK_CONTAINER (applet_window), container);
+ gtk_widget_show (container);
+
+ g_signal_connect (container, "applet-broken",
+ G_CALLBACK (applet_broken_cb),
+ applet_window);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}",
+ "prefs-key", g_variant_new_string (prefs_key));
+ g_variant_builder_add (&builder, "{sv}",
+ "size", g_variant_new_uint32 (size));
+ g_variant_builder_add (&builder, "{sv}",
+ "orient", g_variant_new_uint32 (orientation));
+ mate_panel_applet_container_add (MATE_PANEL_APPLET_CONTAINER (container),
+ title, NULL,
+ (GAsyncReadyCallback)applet_activated_cb,
+ applet_window,
+ g_variant_builder_end (&builder));
+}
+
+static void
+load_applet_from_command_line (void)
+{
+ guint size = 24, orient = PANEL_ORIENTATION_TOP;
+ gint i;
+
+ g_assert (cli_iid != NULL);
+
+ if (cli_size || cli_orient) {
+ if (cli_size) {
+ for (i = 0; i < G_N_ELEMENTS (size_items); i++) {
+ if (strcmp (g_dpgettext2 (NULL, "Size", size_items[i].name), cli_size) == 0) {
+ size = size_items[i].value;
+ break;
+ }
+ }
+ }
+
+ if (cli_orient) {
+ for (i = 0; i < G_N_ELEMENTS (orient_items); i++) {
+ if (strcmp (g_dpgettext2 (NULL, "Orientation", orient_items[i].name), cli_orient) == 0) {
+ orient = orient_items[i].value;
+ break;
+ }
+ }
+ }
+ }
+
+ g_print ("Loading %s\n", cli_iid);
+
+ load_applet_into_window (cli_iid, cli_prefs_dir, size, orient);
+}
+
+G_GNUC_UNUSED void
+on_execute_button_clicked (GtkButton *button,
+ gpointer dummy)
+{
+ char *title;
+
+ title = get_combo_applet_id (applet_combo);
+
+ load_applet_into_window (title,
+ gtk_entry_get_text (GTK_ENTRY (prefs_dir_entry)),
+ get_combo_value (size_combo),
+ get_combo_value (orient_combo));
+ g_free (title);
+}
+
+static void
+setup_combo (GtkWidget *combo_box,
+ ComboItem *items,
+ const char *context,
+ int nb_items)
+{
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ int i;
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_INT);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box),
+ GTK_TREE_MODEL (model));
+
+
+ for (i = 0; i < nb_items; i++) {
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_TEXT, g_dpgettext2 (NULL, context, items [i].name),
+ COLUMN_ITEM, items [i].value,
+ -1);
+ }
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box),
+ renderer, "text", COLUMN_TEXT, NULL);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+}
+
+static void
+setup_options (void)
+{
+ MatePanelAppletsManager *manager;
+ GList *applet_list, *l;
+ int i;
+ char *prefs_dir;
+ char *unique_key;
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (applet_combo),
+ GTK_TREE_MODEL (model));
+
+ manager = g_object_new (PANEL_TYPE_APPLETS_MANAGER_DBUS, NULL);
+ applet_list = MATE_PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applets (manager);
+ for (l = applet_list, i = 1; l; l = g_list_next (l), i++) {
+ MatePanelAppletInfo *info = (MatePanelAppletInfo *)l->data;
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_TEXT, g_strdup (mate_panel_applet_info_get_name (info)),
+ COLUMN_ITEM, g_strdup (mate_panel_applet_info_get_iid (info)),
+ -1);
+ }
+ g_list_free (applet_list);
+ g_object_unref (manager);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (applet_combo),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (applet_combo),
+ renderer, "text", COLUMN_TEXT, NULL);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (applet_combo), 0);
+
+ setup_combo (size_combo, size_items, "Size",
+ G_N_ELEMENTS (size_items));
+ setup_combo (orient_combo, orient_items, "Orientation",
+ G_N_ELEMENTS (orient_items));
+
+ unique_key = mateconf_unique_key ();
+ prefs_dir = g_strdup_printf ("/tmp/%s", unique_key);
+ g_free (unique_key);
+ gtk_entry_set_text (GTK_ENTRY (prefs_dir_entry), prefs_dir);
+ g_free (prefs_dir);
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkBuilder *builder;
+ char *uifile;
+ char *applets_dir;
+ GError *error;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ error = NULL;
+ if (!gtk_init_with_args (&argc, &argv,
+ "", (GOptionEntry *) options, GETTEXT_PACKAGE,
+ &error)) {
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ } else
+ g_printerr ("Cannot initiliaze GTK+.\n");
+
+ return 1;
+ }
+
+ panel_modules_ensure_loaded ();
+
+ if (g_file_test ("../libmate-panel-applet", G_FILE_TEST_IS_DIR)) {
+ applets_dir = g_strdup_printf ("%s:../libmate-panel-applet", MATE_PANEL_APPLETS_DIR);
+ g_setenv ("MATE_PANEL_APPLETS_DIR", applets_dir, FALSE);
+ g_free (applets_dir);
+ }
+
+ if (cli_iid) {
+ load_applet_from_command_line ();
+ gtk_main ();
+ panel_cleanup_do ();
+
+ return 0;
+ }
+
+ builder = gtk_builder_new ();
+ gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+
+ uifile = BUILDERDIR "/panel-test-applets.ui";
+ gtk_builder_add_from_file (builder, uifile, &error);
+
+ if (error) {
+ g_warning ("Error loading \"%s\": %s", uifile, error->message);
+ g_error_free (error);
+ panel_cleanup_do ();
+
+ return 1;
+ }
+
+ gtk_builder_connect_signals (builder, NULL);
+
+ win = GTK_WIDGET (gtk_builder_get_object (builder,
+ "toplevel"));
+ applet_combo = GTK_WIDGET (gtk_builder_get_object (builder,
+ "applet-combo"));
+ prefs_dir_entry = GTK_WIDGET (gtk_builder_get_object (builder,
+ "prefs-dir-entry"));
+ orient_combo = GTK_WIDGET (gtk_builder_get_object (builder,
+ "orient-combo"));
+ size_combo = GTK_WIDGET (gtk_builder_get_object (builder,
+ "size-combo"));
+ g_object_unref (builder);
+
+ setup_options ();
+
+ gtk_widget_show (win);
+
+ gtk_main ();
+
+ panel_cleanup_do ();
+
+ return 0;
+}
diff --git a/mate-panel/panel-test-applets.ui b/mate-panel/panel-test-applets.ui
new file mode 100644
index 00000000..05916cf5
--- /dev/null
+++ b/mate-panel/panel-test-applets.ui
@@ -0,0 +1,203 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="toplevel">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes" comments="This is an utility to easily test various applets">Test applet utility</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <property name="has_separator">False</property>
+ <signal name="destroy" handler="gtk_main_quit"/>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkTable" id="table2">
+ <property name="visible">True</property>
+ <property name="border_width">2</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">4</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="size-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Size:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">size-combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="applet-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Applet:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">applet-combo</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="orient-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Orientation:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">orient-combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="prefs-label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Prefs Dir:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">prefs-dir-entry</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="prefs-dir-entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="applet-combo">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="orient-combo">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="size-combo">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHSeparator" id="hseparator2">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <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="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok-button">
+ <property name="label">gtk-execute</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>
+ <signal name="clicked" handler="on_execute_button_clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <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="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="gtk_main_quit"/>
+ </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="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">ok-button</action-widget>
+ <action-widget response="-7">button1</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/mate-panel/panel-toplevel.c b/mate-panel/panel-toplevel.c
new file mode 100644
index 00000000..043e2e26
--- /dev/null
+++ b/mate-panel/panel-toplevel.c
@@ -0,0 +1,5298 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * panel-toplevel.c: The panel's toplevel window object.
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2004 Rob Adams
+ *
+ * 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+
+#include "panel-toplevel.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+
+#include "panel-profile.h"
+#include "panel-frame.h"
+#include "panel-xutils.h"
+#include "panel-multiscreen.h"
+#include "panel-a11y.h"
+#include "panel-typebuiltins.h"
+#include "panel-marshal.h"
+#include "panel-widget.h"
+#include "panel-bindings.h"
+#include "panel-struts.h"
+#include "panel-config-global.h"
+#include "panel-lockdown.h"
+
+G_DEFINE_TYPE (PanelToplevel, panel_toplevel, GTK_TYPE_WINDOW)
+
+#define PANEL_TOPLEVEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_TOPLEVEL, PanelToplevelPrivate))
+
+#define DEFAULT_SIZE 48
+#define DEFAULT_AUTO_HIDE_SIZE 1
+#define DEFAULT_HIDE_DELAY 300
+#define DEFAULT_UNHIDE_DELAY 100
+#define DEFAULT_DND_THRESHOLD 8
+#define MINIMUM_WIDTH 100
+#define MAXIMUM_SIZE_SCREEN_RATIO 5
+#define SNAP_TOLERANCE_FACTOR 6
+#define DEFAULT_ARROW_SIZE 20
+#define HANDLE_SIZE 10
+#define N_ATTACH_TOPLEVEL_SIGNALS 5
+#define N_ATTACH_WIDGET_SIGNALS 5
+
+typedef enum {
+ PANEL_GRAB_OP_NONE,
+ PANEL_GRAB_OP_MOVE,
+ PANEL_GRAB_OP_RESIZE,
+ PANEL_GRAB_OP_RESIZE_UP,
+ PANEL_GRAB_OP_RESIZE_DOWN,
+ PANEL_GRAB_OP_RESIZE_LEFT,
+ PANEL_GRAB_OP_RESIZE_RIGHT
+} PanelGrabOpType;
+
+struct _PanelToplevelPrivate {
+ gboolean expand;
+ PanelOrientation orientation;
+ int size;
+
+ /* relative to the monitor origin */
+ int x;
+ int y;
+ /* relative to the bottom right corner, -1 to ignore and use x, y*/
+ int x_right;
+ int y_bottom;
+
+ int monitor;
+ /* this is used when the configured monitor is missing. We keep it so
+ * we can move the toplevel to the right monitor when it becomes
+ * available */
+ int configured_monitor;
+
+ int hide_delay;
+ int unhide_delay;
+ int auto_hide_size;
+ PanelAnimationSpeed animation_speed;
+
+ int snap_tolerance;
+ GtkSettings *gtk_settings;
+
+ PanelState state;
+
+ char *name;
+ char *description;
+
+ guint hide_timeout;
+ guint unhide_timeout;
+
+ GdkRectangle geometry;
+ PanelFrameEdge edges;
+
+ int original_width;
+ int original_height;
+
+ PanelGrabOpType grab_op;
+
+ /* The offset within the panel from which the panel
+ * drag was initiated relative to the screen origin.
+ */
+ int drag_offset_x;
+ int drag_offset_y;
+
+ /* Saved state before for cancelled grab op */
+ int orig_monitor;
+ int orig_x;
+ int orig_y;
+ int orig_x_right;
+ int orig_y_bottom;
+ int orig_size;
+ int orig_orientation;
+
+ /* relative to the monitor origin */
+ int animation_end_x;
+ int animation_end_y;
+ int animation_end_width;
+ int animation_end_height;
+ GTimeVal animation_start_time;
+ GTimeVal animation_end_time;
+ guint animation_timeout;
+
+ PanelWidget *panel_widget;
+ PanelFrame *inner_frame;
+ GtkWidget *table;
+ GtkWidget *hide_button_top;
+ GtkWidget *hide_button_bottom;
+ GtkWidget *hide_button_left;
+ GtkWidget *hide_button_right;
+
+ PanelToplevel *attach_toplevel;
+ gulong attach_toplevel_signals [N_ATTACH_TOPLEVEL_SIGNALS];
+ GtkWidget *attach_widget;
+ gulong attach_widget_signals [N_ATTACH_WIDGET_SIGNALS];
+ gint n_autohide_disablers;
+
+ guint auto_hide : 1;
+ guint animate : 1;
+ guint buttons_enabled : 1;
+ guint arrows_enabled : 1;
+
+ /* The co-ordinates are relative to center screen */
+ guint x_centered : 1;
+ guint y_centered : 1;
+
+ /* The panel is not lined up with th screen edge */
+ guint floating : 1;
+
+ /* We are currently animating a hide/show */
+ guint animating : 1;
+
+ /* This is a keyboard initiated grab operation */
+ guint grab_is_keyboard : 1;
+
+ /* The x-y co-ordinates temporarily specify the panel center.
+ * This is used when the panel is rotating, because the width/height
+ * of the toplevel might change, so we need to compute new values for
+ * those. */
+ guint position_centered : 1;
+
+ /* The toplevel is "attached" to another widget */
+ guint attached : 1;
+
+ /* Hidden temporarily because the attach_toplevel was hidden */
+ guint attach_hidden : 1;
+
+ /* More saved grab op state */
+ guint orig_x_centered : 1;
+ guint orig_y_centered : 1;
+
+ /* flag to see if we have already done geometry updating,
+ if not then we're still loading and can ignore many things */
+ guint updated_geometry_initial : 1;
+ /* flag to see if we have done the initial animation */
+ guint initial_animation_done : 1;
+};
+
+enum {
+ HIDE_SIGNAL,
+ UNHIDE_SIGNAL,
+ POPUP_PANEL_MENU_SIGNAL,
+ TOGGLE_EXPAND_SIGNAL,
+ EXPAND_SIGNAL,
+ UNEXPAND_SIGNAL,
+ TOGGLE_HIDDEN_SIGNAL,
+ BEGIN_MOVE_SIGNAL,
+ BEGIN_RESIZE_SIGNAL,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_EXPAND,
+ PROP_ORIENTATION,
+ PROP_SIZE,
+ PROP_X,
+ PROP_X_RIGHT,
+ PROP_X_CENTERED,
+ PROP_Y,
+ PROP_Y_BOTTOM,
+ PROP_Y_CENTERED,
+ PROP_MONITOR,
+ PROP_AUTOHIDE,
+ PROP_HIDE_DELAY,
+ PROP_UNHIDE_DELAY,
+ PROP_AUTOHIDE_SIZE,
+ PROP_ANIMATE,
+ PROP_ANIMATION_SPEED,
+ PROP_BUTTONS_ENABLED,
+ PROP_ARROWS_ENABLED
+};
+
+static guint toplevel_signals[LAST_SIGNAL] = {0};
+static GSList* toplevel_list = NULL;
+
+static void panel_toplevel_calculate_animation_end_geometry(PanelToplevel *toplevel);
+
+static void panel_toplevel_update_monitor(PanelToplevel* toplevel);
+static void panel_toplevel_set_monitor_internal(PanelToplevel* toplevel, int monitor, gboolean force_resize);
+
+
+GSList* panel_toplevel_list_toplevels(void)
+{
+ return toplevel_list;
+}
+
+/* Is this the last un-attached toplevel? */
+gboolean panel_toplevel_is_last_unattached(PanelToplevel* toplevel)
+{
+ GSList* l;
+
+ if (panel_toplevel_get_is_attached(toplevel))
+ {
+ return FALSE;
+ }
+
+ for (l = toplevel_list; l; l = l->next)
+ {
+ PanelToplevel* t = l->data;
+
+ if (t != toplevel && !panel_toplevel_get_is_attached(t))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+static GdkScreen* panel_toplevel_get_screen_geometry(PanelToplevel* toplevel, int* width, int* height)
+{
+ GdkScreen* screen;
+
+ g_return_val_if_fail(PANEL_IS_TOPLEVEL (toplevel), NULL);
+ g_return_val_if_fail(width != NULL && height != NULL, NULL);
+
+ screen = gtk_window_get_screen(GTK_WINDOW(toplevel));
+
+ *width = gdk_screen_get_width(screen);
+ *height = gdk_screen_get_height(screen);
+
+ return screen;
+}
+
+static GdkScreen* panel_toplevel_get_monitor_geometry(PanelToplevel* toplevel, int* x, int* y, int* width, int* height)
+{
+ GdkScreen* screen;
+
+ g_return_val_if_fail(PANEL_IS_TOPLEVEL(toplevel), NULL);
+ g_return_val_if_fail(width != NULL && height != NULL, NULL);
+
+ screen = gtk_window_get_screen(GTK_WINDOW(toplevel));
+
+ if (x) *x = panel_multiscreen_x(screen, toplevel->priv->monitor);
+ if (y) *y = panel_multiscreen_y(screen, toplevel->priv->monitor);
+
+ if (width)
+ {
+ *width = panel_multiscreen_width(screen, toplevel->priv->monitor);
+ }
+
+ if (height)
+ {
+ *height = panel_multiscreen_height(screen, toplevel->priv->monitor);
+ }
+
+ return screen;
+}
+
+static GdkCursorType panel_toplevel_grab_op_cursor(PanelToplevel* toplevel, PanelGrabOpType grab_op)
+{
+ GdkCursorType retval = -1;
+
+ switch (grab_op) {
+ case PANEL_GRAB_OP_MOVE:
+ case PANEL_GRAB_OP_RESIZE:
+ if (toplevel->priv->grab_is_keyboard)
+ retval = GDK_CROSS;
+ else
+ retval = GDK_FLEUR;
+ break;
+ break;
+ case PANEL_GRAB_OP_RESIZE_UP:
+ retval = GDK_TOP_SIDE;
+ break;
+ case PANEL_GRAB_OP_RESIZE_DOWN:
+ retval = GDK_BOTTOM_SIDE;
+ break;
+ case PANEL_GRAB_OP_RESIZE_LEFT:
+ retval = GDK_LEFT_SIDE;
+ break;
+ case PANEL_GRAB_OP_RESIZE_RIGHT:
+ retval = GDK_RIGHT_SIDE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return retval;
+}
+
+static void panel_toplevel_init_resize_drag_offsets(PanelToplevel* toplevel, PanelGrabOpType grab_op)
+{
+ toplevel->priv->drag_offset_x = 0;
+ toplevel->priv->drag_offset_y = 0;
+
+ switch (grab_op) {
+ case PANEL_GRAB_OP_RESIZE_DOWN:
+ toplevel->priv->drag_offset_y = toplevel->priv->geometry.y;
+ break;
+ case PANEL_GRAB_OP_RESIZE_UP:
+ toplevel->priv->drag_offset_y =
+ toplevel->priv->geometry.y + toplevel->priv->geometry.height;
+ break;
+ case PANEL_GRAB_OP_RESIZE_RIGHT:
+ toplevel->priv->drag_offset_x = toplevel->priv->geometry.x;
+ break;
+ case PANEL_GRAB_OP_RESIZE_LEFT:
+ toplevel->priv->drag_offset_x =
+ toplevel->priv->geometry.x + toplevel->priv->geometry.width;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void panel_toplevel_warp_pointer(PanelToplevel* toplevel)
+{
+ GtkWidget *widget;
+ GdkRectangle geometry;
+ int x, y;
+
+ widget = GTK_WIDGET (toplevel);
+
+ geometry = toplevel->priv->geometry;
+
+ x = y = 0;
+
+ switch (toplevel->priv->grab_op) {
+ case PANEL_GRAB_OP_MOVE:
+ case PANEL_GRAB_OP_RESIZE:
+ x = (geometry.width / 2);
+ y = (geometry.height / 2);
+ break;
+ case PANEL_GRAB_OP_RESIZE_UP:
+ x = (geometry.width / 2);
+ break;
+ case PANEL_GRAB_OP_RESIZE_DOWN:
+ x = (geometry.width / 2);
+ y = geometry.height;
+ break;
+ case PANEL_GRAB_OP_RESIZE_LEFT:
+ y = (geometry.height / 2);
+ break;
+ case PANEL_GRAB_OP_RESIZE_RIGHT:
+ x = geometry.width;
+ y = (geometry.height / 2);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (toplevel->priv->grab_op == PANEL_GRAB_OP_MOVE ||
+ toplevel->priv->grab_op == PANEL_GRAB_OP_RESIZE) {
+ toplevel->priv->drag_offset_x = x;
+ toplevel->priv->drag_offset_y = y;
+ } else
+ panel_toplevel_init_resize_drag_offsets (toplevel, toplevel->priv->grab_op);
+
+ panel_warp_pointer (gtk_widget_get_window (widget), x, y);
+}
+
+static void panel_toplevel_begin_attached_move(PanelToplevel* toplevel, gboolean is_keyboard, guint32 time_)
+{
+ PanelWidget *attached_panel_widget;
+
+ attached_panel_widget = panel_toplevel_get_panel_widget (toplevel->priv->attach_toplevel);
+
+ panel_widget_applet_drag_start (attached_panel_widget,
+ toplevel->priv->attach_widget,
+ is_keyboard ? PW_DRAG_OFF_CENTER : PW_DRAG_OFF_CURSOR,
+ time_);
+}
+
+static void panel_toplevel_begin_grab_op(PanelToplevel* toplevel, PanelGrabOpType op_type, gboolean grab_keyboard, guint32 time_)
+{
+ GtkWidget *widget;
+ GdkWindow *window;
+ GdkCursorType cursor_type;
+ GdkCursor *cursor;
+
+ if (toplevel->priv->state != PANEL_STATE_NORMAL ||
+ toplevel->priv->grab_op != PANEL_GRAB_OP_NONE)
+ return;
+
+ if (panel_lockdown_get_locked_down ())
+ return;
+
+ /* If any of the position/orientation are not writable,
+ then we can't really move freely */
+ if (op_type == PANEL_GRAB_OP_MOVE &&
+ ! panel_profile_can_be_moved_freely (toplevel))
+ return;
+
+ /* If size is not writable, then we can't resize */
+ if ((op_type == PANEL_GRAB_OP_RESIZE ||
+ op_type == PANEL_GRAB_OP_RESIZE_UP ||
+ op_type == PANEL_GRAB_OP_RESIZE_DOWN ||
+ op_type == PANEL_GRAB_OP_RESIZE_LEFT ||
+ op_type == PANEL_GRAB_OP_RESIZE_RIGHT) &&
+ ! panel_profile_is_writable_toplevel_size (toplevel))
+ return;
+
+ if (toplevel->priv->attached && op_type == PANEL_GRAB_OP_MOVE) {
+ panel_toplevel_begin_attached_move (toplevel, grab_keyboard, time_);
+ return;
+ }
+
+ widget = GTK_WIDGET (toplevel);
+ window = gtk_widget_get_window (widget);
+
+ toplevel->priv->grab_op = op_type;
+ toplevel->priv->grab_is_keyboard = grab_keyboard;
+
+ toplevel->priv->orig_monitor = toplevel->priv->monitor;
+ toplevel->priv->orig_x = toplevel->priv->x;
+ toplevel->priv->orig_x_right = toplevel->priv->x_right;
+ toplevel->priv->orig_x_centered = toplevel->priv->x_centered;
+ toplevel->priv->orig_y = toplevel->priv->y;
+ toplevel->priv->orig_y_bottom = toplevel->priv->y_bottom;
+ toplevel->priv->orig_y_centered = toplevel->priv->y_centered;
+ toplevel->priv->orig_size = toplevel->priv->size;
+ toplevel->priv->orig_orientation = toplevel->priv->orientation;
+
+ gtk_grab_add (widget);
+
+ if (toplevel->priv->grab_is_keyboard)
+ panel_toplevel_warp_pointer (toplevel);
+
+ cursor_type = panel_toplevel_grab_op_cursor (
+ toplevel, toplevel->priv->grab_op);
+
+ cursor = gdk_cursor_new (cursor_type);
+ gdk_pointer_grab (window, FALSE,
+ GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
+ NULL, cursor, time_);
+ gdk_cursor_unref (cursor);
+
+ if (grab_keyboard)
+ gdk_keyboard_grab (window, FALSE, time_);
+}
+
+static void panel_toplevel_end_grab_op (PanelToplevel* toplevel, guint32 time_)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE);
+
+ widget = GTK_WIDGET (toplevel);
+
+ toplevel->priv->grab_op = PANEL_GRAB_OP_NONE;
+ toplevel->priv->grab_is_keyboard = FALSE;
+
+ gtk_grab_remove (widget);
+
+ gdk_pointer_ungrab (time_);
+ gdk_keyboard_ungrab (time_);
+}
+
+static void panel_toplevel_cancel_grab_op(PanelToplevel* toplevel, guint32 time_)
+{
+ panel_toplevel_set_orientation (toplevel, toplevel->priv->orig_orientation);
+ panel_toplevel_set_monitor (toplevel, toplevel->priv->orig_monitor);
+ panel_toplevel_set_size (toplevel, toplevel->priv->orig_size);
+ panel_toplevel_set_x (toplevel,
+ toplevel->priv->orig_x,
+ toplevel->priv->orig_x_right,
+ toplevel->priv->orig_x_centered);
+ panel_toplevel_set_y (toplevel,
+ toplevel->priv->orig_y,
+ toplevel->priv->orig_y_bottom,
+ toplevel->priv->orig_y_centered);
+}
+
+static void panel_toplevel_resize_to_pointer(PanelToplevel* toplevel, int x, int y)
+{
+ int new_size;
+ int new_x, new_y;
+ int new_x_right, new_y_bottom;
+ int new_x_centered, new_y_centered;
+ int monitor_width, monitor_height;
+
+ new_size = toplevel->priv->size;
+ new_x = toplevel->priv->x;
+ new_y = toplevel->priv->y;
+ new_x_right = toplevel->priv->x_right;
+ new_y_bottom = toplevel->priv->y_bottom;
+ new_x_centered = toplevel->priv->x_centered;
+ new_y_centered = toplevel->priv->y_centered;
+
+ panel_toplevel_get_monitor_geometry (toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ switch (toplevel->priv->grab_op) {
+ case PANEL_GRAB_OP_RESIZE_UP:
+ new_size = toplevel->priv->drag_offset_y - y;
+ new_size = CLAMP (new_size, 0, monitor_height / 4);
+ new_y -= (new_size - toplevel->priv->size);
+ if (!toplevel->priv->y_centered && (new_y + new_size / 2) > monitor_height / 2)
+ new_y_bottom = monitor_height - (new_y + new_size);
+ else
+ new_y_bottom = -1;
+ break;
+ case PANEL_GRAB_OP_RESIZE_DOWN:
+ new_size = y - toplevel->priv->drag_offset_y;
+ new_size = CLAMP (new_size, 0, monitor_height / 4);
+ if (!toplevel->priv->y_centered && (new_y + new_size / 2) > monitor_height / 2)
+ new_y_bottom = monitor_height - (new_y + new_size);
+ else
+ new_y_bottom = -1;
+ break;
+ case PANEL_GRAB_OP_RESIZE_LEFT:
+ new_size = toplevel->priv->drag_offset_x - x;
+ new_size = CLAMP (new_size, 0, monitor_width / 4);
+ new_x -= (new_size - toplevel->priv->size);
+ if (!toplevel->priv->x_centered && (new_x + new_size / 2) > monitor_width / 2)
+ new_x_right = monitor_width - (new_x + new_size);
+ else
+ new_x_right = -1;
+ break;
+ case PANEL_GRAB_OP_RESIZE_RIGHT:
+ new_size = x - toplevel->priv->drag_offset_x;
+ new_size = CLAMP (new_size, 0, monitor_width / 4);
+ if (!toplevel->priv->x_centered && (new_x + new_size / 2) > monitor_width / 2)
+ new_x_right = monitor_width - (new_x + new_size);
+ else
+ new_x_right = -1;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (new_size == 0)
+ return;
+
+ panel_toplevel_set_x (toplevel, new_x, new_x_right, new_x_centered);
+ panel_toplevel_set_y (toplevel, new_y, new_y_bottom, new_y_centered);
+ panel_toplevel_set_size (toplevel, new_size);
+}
+
+/* this is called for expanded panels that are dragged around */
+static void panel_toplevel_calc_new_orientation(PanelToplevel* toplevel, int pointer_x, int pointer_y)
+{
+ PanelOrientation new_orientation;
+ GdkScreen *screen;
+ int hborder, vborder;
+ int monitor;
+ int monitor_width, monitor_height;
+ int new_x, new_y;
+
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+
+ monitor = panel_multiscreen_get_monitor_at_point (screen, pointer_x, pointer_y);
+
+ if (toplevel->priv->geometry.height < toplevel->priv->geometry.width)
+ vborder = hborder = (3 * toplevel->priv->geometry.height) >> 1;
+ else
+ vborder = hborder = (3 * toplevel->priv->geometry.width) >> 1;
+
+ new_x = pointer_x - panel_multiscreen_x (screen, monitor);
+ new_y = pointer_y - panel_multiscreen_y (screen, monitor);
+ monitor_width = panel_multiscreen_width (screen, monitor);
+ monitor_height = panel_multiscreen_height (screen, monitor);
+
+ new_orientation = toplevel->priv->orientation;
+
+ switch (toplevel->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ if (new_y > (monitor_height - hborder))
+ new_orientation = PANEL_ORIENTATION_BOTTOM;
+
+ else if (new_y > hborder) {
+ if (new_x > (monitor_width - vborder))
+ new_orientation = PANEL_ORIENTATION_RIGHT;
+ else if (new_x < vborder)
+ new_orientation = PANEL_ORIENTATION_LEFT;
+ }
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ if (new_y < hborder)
+ new_orientation = PANEL_ORIENTATION_TOP;
+
+ else if (new_y < (monitor_height - hborder)) {
+ if (new_x > (monitor_width - vborder))
+ new_orientation = PANEL_ORIENTATION_RIGHT;
+ else if (new_x < vborder)
+ new_orientation = PANEL_ORIENTATION_LEFT;
+ }
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ if (new_x > (monitor_width - vborder))
+ new_orientation = PANEL_ORIENTATION_RIGHT;
+
+ else if (new_x > vborder) {
+ if (new_y > (monitor_height - hborder))
+ new_orientation = PANEL_ORIENTATION_BOTTOM;
+ else if (new_y < hborder)
+ new_orientation = PANEL_ORIENTATION_TOP;
+ }
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ if (new_x < vborder)
+ new_orientation = PANEL_ORIENTATION_LEFT;
+
+ else if (new_x < (monitor_width - vborder)) {
+ if (new_y > (monitor_height - hborder))
+ new_orientation = PANEL_ORIENTATION_BOTTOM;
+ else if (new_y < hborder)
+ new_orientation = PANEL_ORIENTATION_TOP;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ panel_toplevel_set_monitor (toplevel, monitor);
+ panel_toplevel_set_orientation (toplevel, new_orientation);
+}
+
+static void panel_toplevel_move_to(PanelToplevel* toplevel, int new_x, int new_y)
+{
+ GdkScreen *screen;
+ PanelOrientation new_orientation;
+ gboolean x_centered, y_centered;
+ int screen_width, screen_height;
+ int monitor_width, monitor_height;
+ int width, height;
+ int new_monitor;
+ int x, y, x_right, y_bottom;
+ int snap_tolerance;
+
+ screen = panel_toplevel_get_screen_geometry (
+ toplevel, &screen_width, &screen_height);
+
+ width = toplevel->priv->geometry.width;
+ height = toplevel->priv->geometry.height;
+
+ snap_tolerance = toplevel->priv->snap_tolerance;
+
+ new_x = CLAMP (new_x, 0, screen_width - width);
+ new_y = CLAMP (new_y, 0, screen_height - height);
+
+ new_orientation = toplevel->priv->orientation;
+
+ if (new_x <= snap_tolerance &&
+ toplevel->priv->orientation & PANEL_VERTICAL_MASK)
+ new_orientation = PANEL_ORIENTATION_LEFT;
+
+ else if ((new_x + width) >= (screen_width - snap_tolerance) &&
+ toplevel->priv->orientation & PANEL_VERTICAL_MASK)
+ new_orientation = PANEL_ORIENTATION_RIGHT;
+
+ if (new_y <= snap_tolerance &&
+ toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ new_orientation = PANEL_ORIENTATION_TOP;
+
+ else if ((new_y + height) >= (screen_height - snap_tolerance) &&
+ toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ new_orientation = PANEL_ORIENTATION_BOTTOM;
+
+ new_monitor = panel_multiscreen_get_monitor_at_point (screen, new_x, new_y);
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ x_centered = toplevel->priv->x_centered;
+ y_centered = toplevel->priv->y_centered;
+
+ x = new_x - panel_multiscreen_x (screen, new_monitor);
+ y = new_y - panel_multiscreen_y (screen, new_monitor);
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
+ y_centered = FALSE;
+ if (new_y <= snap_tolerance ||
+ new_y + height >= screen_height - snap_tolerance)
+ x_centered = abs (x - ((monitor_width - width) / 2))
+ <= snap_tolerance;
+ else
+ x_centered = FALSE;
+ } else {
+ x_centered = FALSE;
+ if (new_x <= snap_tolerance ||
+ new_x + width >= screen_width - snap_tolerance)
+ y_centered = abs (y - ((monitor_height - height) / 2))
+ <= snap_tolerance;
+ else
+ y_centered = FALSE;
+ }
+
+ if (x_centered)
+ x = (monitor_width - width) / 2;
+ if (y_centered)
+ y = (monitor_height - height) / 2;
+
+ if (!x_centered && (x + width / 2) > monitor_width / 2)
+ x_right = monitor_width - (x + width);
+ else
+ x_right = -1;
+
+ if (!y_centered && (y + height / 2) > monitor_height / 2)
+ y_bottom = monitor_height - (y + height);
+ else
+ y_bottom = -1;
+
+ panel_toplevel_set_monitor (toplevel, new_monitor);
+ panel_toplevel_set_orientation (toplevel, new_orientation);
+ panel_toplevel_set_x (toplevel, x, x_right, x_centered);
+ panel_toplevel_set_y (toplevel, y, y_bottom, y_centered);
+}
+
+static void panel_toplevel_move_to_pointer(PanelToplevel* toplevel, int pointer_x, int pointer_y)
+{
+ int new_x, new_y;
+
+ new_x = pointer_x - toplevel->priv->drag_offset_x;
+ new_y = pointer_y - toplevel->priv->drag_offset_y;
+
+ panel_toplevel_move_to (toplevel, new_x, new_y);
+}
+
+static void panel_toplevel_rotate_to_pointer(PanelToplevel* toplevel, int pointer_x, int pointer_y)
+{
+ int x_diff, y_diff;
+ int x, y;
+ int snap_tolerance;
+
+ x = toplevel->priv->geometry.x;
+ y = toplevel->priv->geometry.y;
+ snap_tolerance = toplevel->priv->snap_tolerance;
+
+ x_diff = pointer_x - (x + toplevel->priv->geometry.width / 2);
+ y_diff = pointer_y - (y + toplevel->priv->geometry.height / 2);
+
+ if (((-y_diff > x_diff + snap_tolerance) && x_diff > 0 && y_diff < 0) ||
+ (( y_diff < x_diff + snap_tolerance) && x_diff < 0 && y_diff < 0))
+ panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_RIGHT);
+
+ else if (((-x_diff < y_diff - snap_tolerance) && x_diff > 0 && y_diff < 0) ||
+ (( x_diff > y_diff - snap_tolerance) && x_diff > 0 && y_diff > 0))
+ panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_BOTTOM);
+
+ else if ((( y_diff > x_diff + snap_tolerance) && x_diff > 0 && y_diff > 0) ||
+ ((-y_diff < x_diff + snap_tolerance) && x_diff < 0 && y_diff > 0))
+ panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_LEFT);
+
+ else if (((-x_diff > y_diff - snap_tolerance) && x_diff < 0 && y_diff > 0) ||
+ (( x_diff < y_diff - snap_tolerance) && x_diff < 0 && y_diff < 0))
+ panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_TOP);
+}
+
+static gboolean panel_toplevel_warp_pointer_increment(PanelToplevel* toplevel, int keyval, int increment)
+{
+ GdkScreen *screen;
+ GdkWindow *root_window;
+ int new_x, new_y;
+
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+ root_window = gdk_screen_get_root_window (screen);
+
+ gdk_window_get_pointer (root_window, &new_x, &new_y, NULL);
+
+ switch (keyval) {
+ case GDK_Up:
+ case GDK_KP_Up:
+ new_y -= increment;
+ break;
+ case GDK_Left:
+ case GDK_KP_Left:
+ new_x -= increment;
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ new_y += increment;
+ break;
+ case GDK_Right:
+ case GDK_KP_Right:
+ new_x += increment;
+ break;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ panel_warp_pointer (root_window, new_x, new_y);
+
+ return TRUE;
+}
+
+static gboolean panel_toplevel_move_keyboard_floating(PanelToplevel* toplevel, GdkEventKey* event)
+{
+#define SMALL_INCREMENT 1
+#define NORMAL_INCREMENT 10
+
+ int increment = NORMAL_INCREMENT;
+
+ if ((event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK)
+ increment = SMALL_INCREMENT;
+
+ return panel_toplevel_warp_pointer_increment (
+ toplevel, event->keyval, increment);
+
+#undef SMALL_INCREMENT
+#undef NORMAL_INCREMENT
+}
+
+static gboolean panel_toplevel_move_keyboard_expanded(PanelToplevel* toplevel, GdkEventKey* event)
+{
+ PanelOrientation new_orientation;
+
+ switch (event->keyval) {
+ case GDK_Up:
+ case GDK_KP_Up:
+ new_orientation = PANEL_ORIENTATION_TOP;
+ break;
+ case GDK_Left:
+ case GDK_KP_Left:
+ new_orientation = PANEL_ORIENTATION_LEFT;
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ new_orientation = PANEL_ORIENTATION_BOTTOM;
+ break;
+ case GDK_Right:
+ case GDK_KP_Right:
+ new_orientation = PANEL_ORIENTATION_RIGHT;
+ break;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ panel_toplevel_set_orientation (toplevel, new_orientation);
+
+ return TRUE;
+}
+
+static gboolean panel_toplevel_initial_resize_keypress(PanelToplevel* toplevel, GdkEventKey* event)
+{
+ PanelGrabOpType grab_op;
+
+ switch (event->keyval) {
+ case GDK_Up:
+ case GDK_KP_Up:
+ if (!(toplevel->priv->orientation & PANEL_HORIZONTAL_MASK))
+ return FALSE;
+ grab_op = PANEL_GRAB_OP_RESIZE_UP;
+ break;
+ case GDK_Left:
+ case GDK_KP_Left:
+ if (!(toplevel->priv->orientation & PANEL_VERTICAL_MASK))
+ return FALSE;
+ grab_op = PANEL_GRAB_OP_RESIZE_LEFT;
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ if (!(toplevel->priv->orientation & PANEL_HORIZONTAL_MASK))
+ return FALSE;
+ grab_op = PANEL_GRAB_OP_RESIZE_DOWN;
+ break;
+ case GDK_Right:
+ case GDK_KP_Right:
+ if (!(toplevel->priv->orientation & PANEL_VERTICAL_MASK))
+ return FALSE;
+ grab_op = PANEL_GRAB_OP_RESIZE_RIGHT;
+ break;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ panel_toplevel_end_grab_op (toplevel, event->time);
+ panel_toplevel_begin_grab_op (toplevel, grab_op, TRUE, event->time);
+
+ return TRUE;
+}
+
+static gboolean panel_toplevel_handle_grab_op_key_event(PanelToplevel* toplevel, GdkEventKey* event)
+{
+ gboolean retval = FALSE;
+
+ switch (event->keyval) {
+ case GDK_Up:
+ case GDK_KP_Up:
+ case GDK_Left:
+ case GDK_KP_Left:
+ case GDK_Down:
+ case GDK_KP_Down:
+ case GDK_Right:
+ case GDK_KP_Right:
+ switch (toplevel->priv->grab_op) {
+ case PANEL_GRAB_OP_MOVE:
+ if (toplevel->priv->expand)
+ retval = panel_toplevel_move_keyboard_expanded (
+ toplevel, event);
+ else
+ retval = panel_toplevel_move_keyboard_floating (
+ toplevel, event);
+ break;
+ case PANEL_GRAB_OP_RESIZE:
+ retval = panel_toplevel_initial_resize_keypress (toplevel, event);
+ break;
+ case PANEL_GRAB_OP_RESIZE_UP:
+ case PANEL_GRAB_OP_RESIZE_DOWN:
+ case PANEL_GRAB_OP_RESIZE_LEFT:
+ case PANEL_GRAB_OP_RESIZE_RIGHT:
+ retval = panel_toplevel_warp_pointer_increment (
+ toplevel, event->keyval, 1);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ break;
+ case GDK_Escape:
+ panel_toplevel_cancel_grab_op (toplevel, event->time);
+ case GDK_Return: /* drop through*/
+ case GDK_KP_Enter:
+ case GDK_space:
+ case GDK_KP_Space:
+ panel_toplevel_end_grab_op (toplevel, event->time);
+ retval = TRUE;
+ default: /* drop through*/
+ break;
+ }
+
+ return retval;
+}
+
+static gboolean panel_toplevel_handle_grab_op_motion_event(PanelToplevel* toplevel, GdkEventMotion* event)
+{
+ switch (toplevel->priv->grab_op) {
+ case PANEL_GRAB_OP_MOVE:
+ if (toplevel->priv->expand)
+ panel_toplevel_calc_new_orientation (
+ toplevel, event->x_root, event->y_root);
+
+ else if ((event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_CONTROL_MASK)
+ panel_toplevel_rotate_to_pointer (
+ toplevel, event->x_root, event->y_root);
+
+ else
+ panel_toplevel_move_to_pointer (
+ toplevel, event->x_root, event->y_root);
+ return TRUE;
+ case PANEL_GRAB_OP_RESIZE_UP:
+ case PANEL_GRAB_OP_RESIZE_DOWN:
+ case PANEL_GRAB_OP_RESIZE_LEFT:
+ case PANEL_GRAB_OP_RESIZE_RIGHT:
+ panel_toplevel_resize_to_pointer (toplevel, event->x_root, event->y_root);
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void panel_toplevel_calc_floating(PanelToplevel* toplevel)
+{
+ int screen_width, screen_height;
+ int monitor_x, monitor_y;
+ int monitor_width, monitor_height;
+ int x, y;
+ int snap_tolerance;
+
+ if (toplevel->priv->expand) {
+ toplevel->priv->floating = FALSE;
+ return;
+ }
+
+ panel_toplevel_get_screen_geometry (toplevel,
+ &screen_width, &screen_height);
+ panel_toplevel_get_monitor_geometry (toplevel, &monitor_x, &monitor_y,
+ &monitor_width, &monitor_height);
+
+ if (toplevel->priv->x_right == -1)
+ x = monitor_x + toplevel->priv->x;
+ else
+ x = monitor_x + (monitor_width - (toplevel->priv->x_right + toplevel->priv->geometry.width));
+ if (toplevel->priv->y_bottom == -1)
+ y = monitor_y + toplevel->priv->y;
+ else
+ y = monitor_y + (monitor_height - (toplevel->priv->y_bottom + toplevel->priv->geometry.height));
+
+ snap_tolerance = toplevel->priv->snap_tolerance;
+
+ //FIXME? everywhere else, snap_tolerance is relative to the monitor,
+ //not the screen
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ toplevel->priv->floating =
+ (y > snap_tolerance) && (y < (screen_height - toplevel->priv->geometry.height - snap_tolerance));
+ else
+ toplevel->priv->floating =
+ (x > snap_tolerance) && (x < (screen_width - toplevel->priv->geometry.width - snap_tolerance));
+}
+
+void panel_toplevel_push_autohide_disabler(PanelToplevel* toplevel)
+{
+ g_return_if_fail (toplevel != NULL);
+
+ if (!toplevel->priv->n_autohide_disablers++)
+ panel_toplevel_queue_auto_hide (toplevel);
+}
+
+void panel_toplevel_pop_autohide_disabler(PanelToplevel* toplevel)
+{
+ g_return_if_fail (toplevel != NULL);
+ g_return_if_fail (toplevel->priv->n_autohide_disablers > 0);
+
+ if (!--toplevel->priv->n_autohide_disablers)
+ panel_toplevel_queue_auto_hide (toplevel);
+}
+
+static gboolean panel_toplevel_get_autohide_disabled(PanelToplevel* toplevel)
+{
+ return toplevel->priv->n_autohide_disablers > 0 ? TRUE : FALSE;
+}
+
+static gboolean panel_toplevel_hide_button_event(PanelToplevel* toplevel, GdkEventButton* event, GtkButton* button)
+{
+ if (event->button == 1)
+ return FALSE;
+
+ return gtk_widget_event (GTK_WIDGET (toplevel), (GdkEvent *) event);
+}
+
+static void panel_toplevel_hide_button_clicked(PanelToplevel* toplevel, GtkButton* button)
+{
+ GtkArrowType arrow_type;
+ gboolean ltr;
+
+ if (toplevel->priv->animating ||
+ toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
+ return;
+
+ ltr = gtk_widget_get_direction (GTK_WIDGET (toplevel)) == GTK_TEXT_DIR_LTR;
+ arrow_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "arrow-type"));
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL) {
+ GtkDirectionType direction = -1;
+
+ switch (arrow_type) {
+ case GTK_ARROW_UP:
+ direction = GTK_DIR_UP;
+ break;
+ case GTK_ARROW_DOWN:
+ direction = GTK_DIR_DOWN;
+ break;
+ case GTK_ARROW_LEFT:
+ direction = ltr ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
+ break;
+ case GTK_ARROW_RIGHT:
+ direction = ltr ? GTK_DIR_RIGHT : GTK_DIR_LEFT;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ panel_toplevel_hide (toplevel, FALSE, direction);
+ } else
+ panel_toplevel_unhide (toplevel);
+}
+
+static GtkWidget *
+panel_toplevel_add_hide_button (PanelToplevel *toplevel,
+ GtkArrowType arrow_type,
+ int left_attach,
+ int right_attach,
+ int top_attach,
+ int bottom_attach)
+{
+ GtkWidget *button;
+ AtkObject *obj;
+ GtkWidget *arrow;
+ int arrow_size;
+
+ button = gtk_button_new ();
+ obj = gtk_widget_get_accessible (button);
+ atk_object_set_name (obj, _("Hide Panel"));
+ gtk_widget_set_can_default (button, FALSE);
+
+ gtk_widget_style_get (GTK_WIDGET (toplevel),
+ "arrow-size", &arrow_size,
+ NULL);
+
+ switch (arrow_type) {
+ case GTK_ARROW_UP:
+ gtk_widget_set_size_request (button, -1, arrow_size);
+ break;
+ case GTK_ARROW_DOWN:
+ gtk_widget_set_size_request (button, -1, arrow_size);
+ break;
+ case GTK_ARROW_LEFT:
+ gtk_widget_set_size_request (button, arrow_size, -1);
+ break;
+ case GTK_ARROW_RIGHT:
+ gtk_widget_set_size_request (button, arrow_size, -1);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ arrow = gtk_arrow_new (arrow_type, GTK_SHADOW_NONE);
+ gtk_misc_set_padding (GTK_MISC (arrow), 0, 0);
+ gtk_container_add (GTK_CONTAINER (button), arrow);
+ gtk_widget_show (arrow);
+
+ g_object_set_data (G_OBJECT (button),
+ "arrow-type",
+ GINT_TO_POINTER (arrow_type));
+
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (panel_toplevel_hide_button_clicked), toplevel);
+ g_signal_connect_swapped (button, "button_press_event",
+ G_CALLBACK (panel_toplevel_hide_button_event), toplevel);
+ g_signal_connect_swapped (button, "button_release_event",
+ G_CALLBACK (panel_toplevel_hide_button_event), toplevel);
+
+ gtk_table_attach (GTK_TABLE (toplevel->priv->table),
+ button,
+ left_attach,
+ right_attach,
+ top_attach,
+ bottom_attach,
+ GTK_FILL,
+ GTK_FILL,
+ 0,
+ 0);
+
+ return button;
+}
+
+static void panel_toplevel_update_buttons_showing(PanelToplevel* toplevel)
+{
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
+ gtk_widget_hide (toplevel->priv->hide_button_top);
+ gtk_widget_hide (toplevel->priv->hide_button_bottom);
+ gtk_widget_show (toplevel->priv->hide_button_left);
+ gtk_widget_show (toplevel->priv->hide_button_right);
+ } else {
+ gtk_widget_show (toplevel->priv->hide_button_top);
+ gtk_widget_show (toplevel->priv->hide_button_bottom);
+ gtk_widget_hide (toplevel->priv->hide_button_left);
+ gtk_widget_hide (toplevel->priv->hide_button_right);
+ }
+
+ if (toplevel->priv->attached) {
+ switch (panel_toplevel_get_orientation (toplevel->priv->attach_toplevel)) {
+ case PANEL_ORIENTATION_TOP:
+ gtk_widget_hide (toplevel->priv->hide_button_top);
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ gtk_widget_hide (toplevel->priv->hide_button_bottom);
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ gtk_widget_hide (toplevel->priv->hide_button_left);
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ gtk_widget_hide (toplevel->priv->hide_button_right);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+}
+
+static void panel_toplevel_update_hide_buttons(PanelToplevel* toplevel)
+{
+ if (toplevel->priv->buttons_enabled)
+ panel_toplevel_update_buttons_showing (toplevel);
+ else {
+ g_object_set (
+ G_OBJECT (toplevel->priv->hide_button_top),
+ "visible", toplevel->priv->state == PANEL_STATE_HIDDEN_DOWN,
+ NULL);
+ g_object_set (
+ G_OBJECT (toplevel->priv->hide_button_bottom),
+ "visible", toplevel->priv->state == PANEL_STATE_HIDDEN_UP,
+ NULL);
+ g_object_set (
+ G_OBJECT (toplevel->priv->hide_button_left),
+ "visible", toplevel->priv->state == PANEL_STATE_HIDDEN_RIGHT,
+ NULL);
+ g_object_set (
+ G_OBJECT (toplevel->priv->hide_button_right),
+ "visible", toplevel->priv->state == PANEL_STATE_HIDDEN_LEFT,
+ NULL);
+ }
+
+ if (toplevel->priv->arrows_enabled) {
+ int arrow_size;
+
+ gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_top)));
+ gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_bottom)));
+ gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_left)));
+ gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_right)));
+
+ gtk_widget_style_get (GTK_WIDGET (toplevel),
+ "arrow-size", &arrow_size,
+ NULL);
+
+ gtk_widget_set_size_request (toplevel->priv->hide_button_top,
+ -1, arrow_size);
+ gtk_widget_set_size_request (toplevel->priv->hide_button_bottom,
+ -1, arrow_size);
+ gtk_widget_set_size_request (toplevel->priv->hide_button_left,
+ arrow_size, -1);
+ gtk_widget_set_size_request (toplevel->priv->hide_button_right,
+ arrow_size, -1);
+ } else {
+ gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_top)));
+ gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_bottom)));
+ gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_left)));
+ gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_right)));
+
+ gtk_widget_set_size_request (toplevel->priv->hide_button_top, -1, -1);
+ gtk_widget_set_size_request (toplevel->priv->hide_button_bottom, -1, -1);
+ gtk_widget_set_size_request (toplevel->priv->hide_button_left, -1, -1);
+ gtk_widget_set_size_request (toplevel->priv->hide_button_right, -1, -1);
+ }
+}
+
+static gboolean panel_toplevel_contains_pointer(PanelToplevel* toplevel)
+{
+ GdkDisplay *display;
+ GdkScreen *screen;
+ GtkWidget *widget;
+ int x, y;
+
+ display = gdk_display_get_default ();
+ widget = GTK_WIDGET (toplevel);
+
+ if (!gtk_widget_get_realized (widget))
+ return FALSE;
+
+ screen = NULL;
+ x = y = -1;
+ gdk_display_get_pointer (display, &screen, &x, &y, NULL);
+
+ if (screen != gtk_window_get_screen (GTK_WINDOW (toplevel)))
+ return FALSE;
+
+ if (x == -1 || y == -1)
+ return FALSE;
+
+ if (x < toplevel->priv->geometry.x || x >= (toplevel->priv->geometry.x + toplevel->priv->geometry.width) ||
+ y < toplevel->priv->geometry.y || y >= (toplevel->priv->geometry.y + toplevel->priv->geometry.height))
+ return FALSE;
+
+ return TRUE;
+}
+
+static inline int panel_toplevel_get_effective_auto_hide_size(PanelToplevel* toplevel)
+{
+ int size;
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ size = CLAMP (toplevel->priv->auto_hide_size,
+ 1, toplevel->priv->original_height / 2);
+ else
+ size = CLAMP (toplevel->priv->auto_hide_size,
+ 1, toplevel->priv->original_width / 2);
+
+ /* paranoia */
+ return (size <= 0) ? DEFAULT_AUTO_HIDE_SIZE : size;
+}
+
+static gboolean panel_toplevel_update_struts(PanelToplevel* toplevel, gboolean end_of_animation)
+{
+ PanelOrientation orientation;
+ GdkScreen *screen;
+ gboolean geometry_changed = FALSE;
+ int strut, strut_start, strut_end;
+ int x, y, width, height;
+ int monitor_x, monitor_y;
+ int monitor_width, monitor_height;
+
+ if (!toplevel->priv->updated_geometry_initial)
+ return FALSE;
+
+ if (toplevel->priv->attached) {
+ panel_struts_unregister_strut (toplevel);
+ panel_struts_set_window_hint (toplevel);
+ return FALSE;
+ }
+
+ /* In the case of the initial animation, we really want the struts to
+ * represent what is at the end of the animation, to avoid desktop
+ * icons jumping around. */
+ if (!toplevel->priv->initial_animation_done) {
+ end_of_animation = TRUE;
+
+ /* We've not started the animation yet, so we have to compute
+ * where we want to end. Note that we don't want to compute
+ * this everytime, since the struts conflict resolution will be
+ * overridden if we do so */
+ if (!toplevel->priv->animating)
+ panel_toplevel_calculate_animation_end_geometry (toplevel);
+ }
+
+ screen = panel_toplevel_get_monitor_geometry (toplevel,
+ &monitor_x,
+ &monitor_y,
+ &monitor_width,
+ &monitor_height);
+
+ if (end_of_animation) {
+ x = toplevel->priv->animation_end_x;
+ y = toplevel->priv->animation_end_y;
+ x += panel_multiscreen_x (screen, toplevel->priv->monitor);
+ y += panel_multiscreen_y (screen, toplevel->priv->monitor);
+ if (toplevel->priv->animation_end_width != -1)
+ width = toplevel->priv->animation_end_width;
+ else
+ width = toplevel->priv->geometry.width;
+ if (toplevel->priv->animation_end_height != -1)
+ height = toplevel->priv->animation_end_height;
+ else
+ height = toplevel->priv->geometry.height;
+ } else {
+ x = toplevel->priv->geometry.x;
+ y = toplevel->priv->geometry.y;
+ width = toplevel->priv->geometry.width;
+ height = toplevel->priv->geometry.height;
+ }
+
+ orientation = toplevel->priv->orientation;
+
+ strut = strut_start = strut_end = 0;
+
+ if (orientation & PANEL_HORIZONTAL_MASK) {
+ if (y <= monitor_y) {
+ orientation = PANEL_ORIENTATION_TOP;
+ strut = y + height - monitor_y;
+ } else if (y >= monitor_y + monitor_height - height) {
+ orientation = PANEL_ORIENTATION_BOTTOM;
+ strut = monitor_y + monitor_height - y;
+ }
+
+ if (strut > 0) {
+ strut_start = MAX (x, monitor_x);
+ strut_end = MIN (x + width, monitor_x + monitor_width) - 1;
+ }
+ } else {
+ if (x <= monitor_x) {
+ orientation = PANEL_ORIENTATION_LEFT;
+ strut = x + width - monitor_x;
+ } else if (x >= monitor_x + monitor_width - width) {
+ orientation = PANEL_ORIENTATION_RIGHT;
+ strut = monitor_x + monitor_width - x;
+ }
+
+ if (strut > 0) {
+ strut_start = MAX (y, monitor_y);
+ strut_end = MIN (y + height, monitor_y + monitor_height) - 1;
+ }
+ }
+
+ if (orientation != toplevel->priv->orientation) {
+ toplevel->priv->orientation = orientation;
+ g_object_notify (G_OBJECT (toplevel), "orientation");
+ }
+
+ if (toplevel->priv->auto_hide && strut > 0)
+ strut = panel_toplevel_get_effective_auto_hide_size (toplevel);
+
+ if (strut > 0)
+ geometry_changed = panel_struts_register_strut (toplevel,
+ screen,
+ toplevel->priv->monitor,
+ orientation,
+ strut,
+ strut_start,
+ strut_end);
+ else
+ panel_struts_unregister_strut (toplevel);
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL ||
+ toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN ||
+ toplevel->priv->animating)
+ panel_struts_set_window_hint (toplevel);
+ else
+ panel_struts_unset_window_hint (toplevel);
+
+ return geometry_changed;
+}
+
+void panel_toplevel_update_edges(PanelToplevel* toplevel)
+{
+ GtkWidget *widget;
+ PanelFrameEdge edges;
+ PanelFrameEdge inner_edges;
+ PanelFrameEdge outer_edges;
+ PanelBackground *background;
+ int monitor_width, monitor_height;
+ int width, height;
+ gboolean inner_frame = FALSE;
+
+ widget = GTK_WIDGET (toplevel);
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ width = toplevel->priv->geometry.width;
+ height = toplevel->priv->geometry.height;
+
+ edges = PANEL_EDGE_NONE;
+
+ background = &toplevel->priv->panel_widget->background;
+
+ /* We don't want any bevels with a color/image background */
+ if (panel_background_effective_type (background) == PANEL_BACK_NONE) {
+ if (toplevel->priv->geometry.y > 0)
+ edges |= PANEL_EDGE_TOP;
+
+ if (toplevel->priv->geometry.x > 0)
+ edges |= PANEL_EDGE_LEFT;
+
+ if (toplevel->priv->geometry.y < (monitor_height - height))
+ edges |= PANEL_EDGE_BOTTOM;
+
+ if (toplevel->priv->geometry.x < (monitor_width - width))
+ edges |= PANEL_EDGE_RIGHT;
+
+ /* There is a conflict in the position algorithm when a
+ * non-expanded centered panel is nearly the size of the
+ * screen. This is similar to the one we have in
+ * panel_toplevel_update_position(). A simple solution is
+ * to keep the bevels in this case. */
+ if (!toplevel->priv->expand &&
+ toplevel->priv->orientation & PANEL_HORIZONTAL_MASK &&
+ toplevel->priv->x_centered)
+ edges |= PANEL_EDGE_LEFT | PANEL_EDGE_RIGHT;
+
+ if (!toplevel->priv->expand &&
+ toplevel->priv->orientation & PANEL_VERTICAL_MASK &&
+ toplevel->priv->y_centered)
+ edges |= PANEL_EDGE_TOP | PANEL_EDGE_BOTTOM;
+
+ if (gtk_widget_get_visible (toplevel->priv->hide_button_left) ||
+ gtk_widget_get_visible (toplevel->priv->hide_button_right)) {
+ inner_frame = TRUE;
+ edges |= PANEL_EDGE_LEFT | PANEL_EDGE_RIGHT;
+ }
+
+ if (gtk_widget_get_visible (toplevel->priv->hide_button_top) ||
+ gtk_widget_get_visible (toplevel->priv->hide_button_bottom)) {
+ inner_frame = TRUE;
+ edges |= PANEL_EDGE_TOP | PANEL_EDGE_BOTTOM;
+ }
+ }
+
+ if (!inner_frame) {
+ inner_edges = PANEL_EDGE_NONE;
+ outer_edges = edges;
+ } else {
+ inner_edges = edges;
+ outer_edges = PANEL_EDGE_NONE;
+ }
+
+ panel_frame_set_edges (toplevel->priv->inner_frame, inner_edges);
+
+ if (toplevel->priv->edges != outer_edges) {
+ toplevel->priv->edges = outer_edges;
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+static const char* panel_toplevel_construct_description(PanelToplevel *toplevel)
+{
+ int orientation, type;
+
+ static const char *description[4][4] = {
+ {
+ /* translators: these string will be shown in MetaCity's switch window
+ * popup when you pass the focus to a panel */
+ N_("Top Expanded Edge Panel"),
+ N_("Top Centered Panel"),
+ N_("Top Floating Panel"),
+ N_("Top Edge Panel"),
+ },
+
+ {
+ N_("Bottom Expanded Edge Panel"),
+ N_("Bottom Centered Panel"),
+ N_("Bottom Floating Panel"),
+ N_("Bottom Edge Panel"),
+ },
+
+ {
+ N_("Left Expanded Edge Panel"),
+ N_("Left Centered Panel"),
+ N_("Left Floating Panel"),
+ N_("Left Edge Panel"),
+ },
+
+ {
+ N_("Right Expanded Edge Panel"),
+ N_("Right Centered Panel"),
+ N_("Right Floating Panel"),
+ N_("Right Edge Panel"),
+ },
+ };
+
+ if (toplevel->priv->attached)
+ return N_("Drawer");
+
+ switch (toplevel->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ orientation = 0;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ orientation = 1;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ orientation = 2;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ orientation = 3;
+ break;
+ default:
+ orientation = 0;
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (toplevel->priv->expand)
+ type = 0;
+ else if (toplevel->priv->x_centered ||
+ toplevel->priv->y_centered)
+ type = 1;
+ else if (toplevel->priv->floating)
+ type = 2;
+ else
+ type = 3;
+
+ return description[orientation][type];
+}
+
+static void panel_toplevel_update_description(PanelToplevel* toplevel)
+{
+ const char *description;
+
+ description = panel_toplevel_construct_description (toplevel);
+
+ if (toplevel->priv->description &&
+ !strcmp (toplevel->priv->description, description))
+ return;
+
+ if (toplevel->priv->description)
+ g_free (toplevel->priv->description);
+ toplevel->priv->description = g_strdup (_(description));
+
+ if (!toplevel->priv->name)
+ gtk_window_set_title (GTK_WINDOW (toplevel),
+ toplevel->priv->description);
+
+ panel_a11y_set_atk_name_desc (
+ GTK_WIDGET (toplevel->priv->panel_widget),
+ toplevel->priv->name ? toplevel->priv->name :
+ _(toplevel->priv->description),
+ _(toplevel->priv->description));
+}
+
+static void panel_toplevel_update_attached_position(PanelToplevel* toplevel, gboolean hidden, int* x, int* y, int* w, int* h)
+{
+ GtkAllocation attach_allocation;
+ PanelOrientation attach_orientation;
+ GdkRectangle toplevel_box;
+ GdkRectangle parent_box;
+ GdkRectangle attach_box;
+ int x_origin = 0, y_origin = 0;
+ int monitor_x, monitor_y;
+ int monitor_width, monitor_height;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (toplevel->priv->attach_toplevel)) ||
+ !gtk_widget_get_realized (toplevel->priv->attach_widget))
+ return;
+
+ gtk_widget_get_allocation (GTK_WIDGET (toplevel->priv->attach_widget), &attach_allocation);
+
+ toplevel_box = toplevel->priv->geometry;
+ parent_box = toplevel->priv->attach_toplevel->priv->geometry;
+ attach_box = attach_allocation;
+
+ if (attach_box.x != -1) {
+ gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (toplevel->priv->attach_widget)),
+ &x_origin, &y_origin);
+
+ attach_box.x += x_origin;
+ attach_box.y += y_origin;
+ } else {
+ /* attach_widget isn't allocated. Put the toplevel
+ * off screen.
+ */
+ attach_box.x = -toplevel_box.width;
+ attach_box.y = -toplevel_box.height;
+ }
+
+ attach_orientation = panel_toplevel_get_orientation (
+ toplevel->priv->attach_toplevel);
+
+ if (attach_orientation & PANEL_HORIZONTAL_MASK)
+ *x = attach_box.x + attach_box.width / 2 - toplevel_box.width / 2;
+ else
+ *y = attach_box.y + attach_box.height / 2 - toplevel_box.height / 2;
+
+ switch (attach_orientation) {
+ case PANEL_ORIENTATION_TOP:
+ *y = parent_box.y;
+ if (!hidden)
+ *y += parent_box.height;
+ else
+ *h = parent_box.height;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ *y = parent_box.y;
+ if (!hidden)
+ *y -= toplevel_box.height;
+ else
+ *h = parent_box.height;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ *x = parent_box.x;
+ if (!hidden)
+ *x += parent_box.width;
+ else
+ *w = parent_box.width;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ *x = parent_box.x;
+ if (!hidden)
+ *x -= toplevel_box.width;
+ else
+ *w = parent_box.width;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ panel_toplevel_get_monitor_geometry (toplevel,
+ &monitor_x,
+ &monitor_y,
+ &monitor_width,
+ &monitor_height);
+
+ *x -= monitor_x;
+ *y -= monitor_y;
+
+ if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
+ *x = CLAMP (*x, 0, monitor_width - toplevel->priv->original_width);
+ else
+ *y = CLAMP (*y, 0, monitor_height - toplevel->priv->original_height);
+}
+
+static void panel_toplevel_update_normal_position(PanelToplevel* toplevel, int* x, int* y, int* w, int* h)
+{
+ int monitor_width, monitor_height;
+ int width, height;
+ int snap_tolerance;
+
+ g_assert (x != NULL && y != NULL);
+
+ if (toplevel->priv->attached) {
+ panel_toplevel_update_attached_position (toplevel, FALSE, x, y, w, h);
+ return;
+ }
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ width = toplevel->priv->original_width;
+ height = toplevel->priv->original_height;
+ snap_tolerance = toplevel->priv->snap_tolerance;
+
+ *x = CLAMP (*x, 0, monitor_width - width);
+ *y = CLAMP (*y, 0, monitor_height - height);
+
+ if (toplevel->priv->x <= snap_tolerance &&
+ toplevel->priv->x_right == -1 &&
+ !toplevel->priv->x_centered)
+ *x = 0;
+ else if (toplevel->priv->x_right != -1 &&
+ toplevel->priv->x_right <= snap_tolerance &&
+ !toplevel->priv->x_centered)
+ *x = monitor_width - width;
+
+ if (toplevel->priv->y <= snap_tolerance &&
+ toplevel->priv->y_bottom == -1 &&
+ !toplevel->priv->y_centered)
+ *y = 0;
+ else if (toplevel->priv->y_bottom != -1 &&
+ toplevel->priv->y_bottom <= snap_tolerance &&
+ !toplevel->priv->y_centered)
+ *y = monitor_height - height;
+}
+
+static void
+panel_toplevel_update_auto_hide_position (PanelToplevel *toplevel,
+ int *x,
+ int *y,
+ int *w,
+ int *h,
+ gboolean for_end_position)
+{
+ int width, height;
+ int monitor_width, monitor_height;
+ int auto_hide_size;
+ int snap_tolerance;
+
+ g_assert (x != NULL && y != NULL);
+
+ if (toplevel->priv->floating) {
+ panel_toplevel_update_normal_position (toplevel, x, y, w, h);
+ return;
+ }
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ width = toplevel->priv->original_width;
+ height = toplevel->priv->original_height;
+ snap_tolerance = toplevel->priv->snap_tolerance;
+
+ /* For the initial animation, we animate from outside the screen, and
+ * so we don't want the toplevel to be visible at all. But when the
+ * request is for the end position, then we give the real result (it's
+ * useful for struts) */
+ if (for_end_position || toplevel->priv->initial_animation_done) {
+ auto_hide_size = panel_toplevel_get_effective_auto_hide_size (toplevel);
+ } else {
+ auto_hide_size = 0;
+ }
+
+ switch (toplevel->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ *y = - (height - auto_hide_size);
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ *y = monitor_height - auto_hide_size;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ *x = - (width - auto_hide_size);
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ *x = monitor_width - auto_hide_size;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
+ if (toplevel->priv->x <= snap_tolerance &&
+ toplevel->priv->x_right == -1 &&
+ !toplevel->priv->x_centered)
+ *x = 0;
+ else if (toplevel->priv->x_right != -1 &&
+ toplevel->priv->x_right <= snap_tolerance &&
+ !toplevel->priv->x_centered)
+ *x = monitor_width - width;
+ } else /* if (toplevel->priv->orientation & PANEL_VERTICAL_MASK) */ {
+ if (toplevel->priv->y <= snap_tolerance &&
+ toplevel->priv->y_bottom == -1 &&
+ !toplevel->priv->y_centered)
+ *y = 0;
+ else if (toplevel->priv->y_bottom != -1 &&
+ toplevel->priv->y_bottom <= snap_tolerance &&
+ !toplevel->priv->y_centered)
+ *y = monitor_height - height;
+ }
+}
+
+/* FIXME: this is wrong for Xinerama. In the Xinerama case
+ * I think if hiding it requires it to go onto the
+ * next monitor then it should just move it on to
+ * the next monitor and set its state back to normal
+ */
+static void
+panel_toplevel_update_hidden_position (PanelToplevel *toplevel,
+ int *x,
+ int *y,
+ int *w,
+ int *h)
+{
+ int width, height;
+ int min_hide_size;
+ int monitor_height, monitor_width;
+ GtkAllocation hide_allocation;
+
+ g_assert (x != NULL && y != NULL);
+
+ g_assert (toplevel->priv->state == PANEL_STATE_HIDDEN_UP ||
+ toplevel->priv->state == PANEL_STATE_HIDDEN_DOWN ||
+ toplevel->priv->state == PANEL_STATE_HIDDEN_LEFT ||
+ toplevel->priv->state == PANEL_STATE_HIDDEN_RIGHT);
+
+ if (toplevel->priv->attached) {
+ panel_toplevel_update_attached_position (toplevel, TRUE, x, y, w, h);
+ return;
+ }
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ width = toplevel->priv->original_width;
+ height = toplevel->priv->original_height;
+
+ //FIXME should find a better default
+ min_hide_size = DEFAULT_AUTO_HIDE_SIZE;
+
+ switch (toplevel->priv->state) {
+ case PANEL_STATE_HIDDEN_UP:
+ gtk_widget_get_allocation (toplevel->priv->hide_button_bottom,
+ &hide_allocation);
+ *y = - (height - MAX (hide_allocation.height, min_hide_size));
+ break;
+ case PANEL_STATE_HIDDEN_DOWN:
+ gtk_widget_get_allocation (toplevel->priv->hide_button_top,
+ &hide_allocation);
+ *y = monitor_height - MAX (hide_allocation.height, min_hide_size);
+ break;
+ case PANEL_STATE_HIDDEN_LEFT:
+ gtk_widget_get_allocation (toplevel->priv->hide_button_right,
+ &hide_allocation);
+ *x = - (width - MAX (hide_allocation.width, min_hide_size));
+ break;
+ case PANEL_STATE_HIDDEN_RIGHT:
+ gtk_widget_get_allocation (toplevel->priv->hide_button_left,
+ &hide_allocation);
+ *x = monitor_width - MAX (hide_allocation.width, min_hide_size);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+/*
+ * This is "almost" like the double sine movement
+ * from the original panel except that it uses
+ * a cubic (twice again). I suppose it looks less
+ * mathematical now :) -- _v_
+ */
+static int
+get_delta (int src,
+ int dest,
+ GTimeVal *start_time,
+ GTimeVal *end_time,
+ GTimeVal *cur_time)
+{
+ double x, s, n, d, percentage;
+
+ s = start_time->tv_sec + ((double)start_time->tv_usec / G_USEC_PER_SEC);
+ n = cur_time->tv_sec + ((double)cur_time->tv_usec / G_USEC_PER_SEC);
+ d = end_time->tv_sec + ((double)end_time->tv_usec / G_USEC_PER_SEC);
+
+ n -= s;
+ d -= s;
+
+ if (abs (dest - src) <= 1 || n >= d)
+ return dest - src;
+
+ /* The cubic is: p(x) = (-2) x^2 (x-1.5) */
+ /* running p(p(x)) to make it more "pronounced",
+ * effectively making it a ninth-degree polynomial */
+
+ x = (double)n/d;
+ x = -2 * (x*x) * (x-1.5);
+ /* run it again */
+ percentage = -2 * (x*x) * (x-1.5);
+
+ percentage = CLAMP (percentage, 0.0, 1.0);
+
+ return ((dest - src) * percentage);
+}
+
+static void
+panel_toplevel_update_animating_position (PanelToplevel *toplevel)
+{
+ GdkScreen *screen;
+ GTimeVal time_val;
+ int deltax, deltay, deltaw = 0, deltah = 0;
+ int monitor_offset_x, monitor_offset_y;
+
+ g_get_current_time (&time_val);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+
+ monitor_offset_x = panel_multiscreen_x (screen, toplevel->priv->monitor);
+ monitor_offset_y = panel_multiscreen_y (screen, toplevel->priv->monitor);
+
+ if (toplevel->priv->animation_end_width != -1)
+ deltaw = get_delta (toplevel->priv->geometry.width,
+ toplevel->priv->animation_end_width,
+ &toplevel->priv->animation_start_time,
+ &toplevel->priv->animation_end_time,
+ &time_val);
+
+ if (toplevel->priv->animation_end_height != -1)
+ deltah = get_delta (toplevel->priv->geometry.height,
+ toplevel->priv->animation_end_height,
+ &toplevel->priv->animation_start_time,
+ &toplevel->priv->animation_end_time,
+ &time_val);
+
+ deltax = get_delta (toplevel->priv->geometry.x - monitor_offset_x,
+ toplevel->priv->animation_end_x,
+ &toplevel->priv->animation_start_time,
+ &toplevel->priv->animation_end_time,
+ &time_val);
+
+ deltay = get_delta (toplevel->priv->geometry.y - monitor_offset_y,
+ toplevel->priv->animation_end_y,
+ &toplevel->priv->animation_start_time,
+ &toplevel->priv->animation_end_time,
+ &time_val);
+
+ if (deltaw != 0 && abs (deltaw) > abs (deltax))
+ deltax = deltaw;
+ if (deltah != 0 && abs (deltah) > abs (deltay))
+ deltay = deltah;
+
+ toplevel->priv->geometry.x += deltax;
+ toplevel->priv->geometry.y += deltay;
+
+ toplevel->priv->geometry.width += deltaw;
+ toplevel->priv->geometry.height += deltah;
+
+ if (toplevel->priv->geometry.x - monitor_offset_x == toplevel->priv->animation_end_x &&
+ toplevel->priv->geometry.y - monitor_offset_y == toplevel->priv->animation_end_y) {
+ toplevel->priv->animating = FALSE;
+ /* Note: it's important to set initial_animation_done to TRUE
+ * as soon as possible (hence, here) since we don't want to
+ * have a wrong value in a size request event */
+ toplevel->priv->initial_animation_done = TRUE;
+
+ if (toplevel->priv->attached && panel_toplevel_get_is_hidden (toplevel))
+ gtk_widget_unmap (GTK_WIDGET (toplevel));
+ else
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL)
+ g_signal_emit (toplevel, toplevel_signals [UNHIDE_SIGNAL], 0);
+ }
+}
+
+static void
+panel_toplevel_update_expanded_position (PanelToplevel *toplevel)
+{
+ GdkScreen *screen;
+ int monitor_width, monitor_height;
+ int screen_width, screen_height;
+ int monitor_x, monitor_y;
+ int x, y;
+ int x_right, y_bottom;
+ int monitor;
+
+ if (!toplevel->priv->expand)
+ return;
+
+ screen = panel_toplevel_get_screen_geometry (toplevel,
+ &screen_width,
+ &screen_height);
+
+ panel_toplevel_get_monitor_geometry (toplevel, &monitor_x, &monitor_y,
+ &monitor_width, &monitor_height);
+
+ x = -1;
+ y = -1;
+ x_right = -1;
+ y_bottom = -1;
+
+ switch (toplevel->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ x = monitor_x;
+ y = monitor_y;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ x = monitor_x;
+ y = monitor_y;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ x = monitor_x;
+ y = monitor_y + monitor_height - toplevel->priv->geometry.height;
+ y_bottom = 0;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ x = monitor_x + monitor_width - toplevel->priv->geometry.width;
+ y = monitor_y;
+ x_right = 0;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ monitor = panel_multiscreen_get_monitor_at_point (screen, x, y);
+
+ panel_toplevel_set_monitor_internal (toplevel, monitor, TRUE);
+
+ x -= panel_multiscreen_x (screen, monitor);
+ y -= panel_multiscreen_y (screen, monitor);
+
+ g_object_freeze_notify (G_OBJECT (toplevel));
+
+ if (toplevel->priv->x != x) {
+ toplevel->priv->x = x;
+ g_object_notify (G_OBJECT (toplevel), "x");
+ }
+
+ if (toplevel->priv->y != y) {
+ toplevel->priv->y = y;
+ g_object_notify (G_OBJECT (toplevel), "y");
+ }
+
+ if (toplevel->priv->x_right != x_right) {
+ toplevel->priv->x_right = x_right;
+ g_object_notify (G_OBJECT (toplevel), "x_right");
+ }
+
+ if (toplevel->priv->y_bottom != y_bottom) {
+ toplevel->priv->y_bottom = y_bottom;
+ g_object_notify (G_OBJECT (toplevel), "y_bottom");
+ }
+
+ g_object_thaw_notify (G_OBJECT (toplevel));
+}
+
+static void
+panel_toplevel_update_position (PanelToplevel *toplevel)
+{
+ PanelBackground *background;
+ GdkScreen *screen;
+ int x, y;
+ int w, h;
+ int screen_width, screen_height;
+ int monitor_width, monitor_height;
+
+ screen = panel_toplevel_get_screen_geometry (
+ toplevel, &screen_width, &screen_height);
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ if (toplevel->priv->animating) {
+ panel_toplevel_update_animating_position (toplevel);
+ return;
+ }
+
+ if (toplevel->priv->position_centered) {
+ toplevel->priv->position_centered = FALSE;
+
+ g_object_freeze_notify (G_OBJECT (toplevel));
+
+ if (!toplevel->priv->x_centered) {
+ int x_right;
+
+ toplevel->priv->x -= toplevel->priv->geometry.width / 2;
+ g_object_notify (G_OBJECT (toplevel), "x");
+
+ if ((toplevel->priv->x + toplevel->priv->geometry.width / 2) > monitor_width / 2)
+ x_right = monitor_width - (toplevel->priv->x + toplevel->priv->geometry.width);
+ else
+ x_right = -1;
+ if (toplevel->priv->x_right != x_right) {
+ toplevel->priv->x_right = x_right;
+ g_object_notify (G_OBJECT (toplevel),
+ "x-right");
+ }
+ }
+
+ if (!toplevel->priv->y_centered) {
+ int y_bottom;
+
+ toplevel->priv->y -= toplevel->priv->geometry.height / 2;
+ g_object_notify (G_OBJECT (toplevel), "y");
+
+ if ((toplevel->priv->y + toplevel->priv->geometry.height / 2) > monitor_height / 2)
+ y_bottom = monitor_height - (toplevel->priv->y + toplevel->priv->geometry.height);
+ else
+ y_bottom = -1;
+ if (toplevel->priv->y_bottom != y_bottom) {
+ toplevel->priv->y_bottom = y_bottom;
+ g_object_notify (G_OBJECT (toplevel),
+ "y-bottom");
+ }
+ }
+
+ g_object_thaw_notify (G_OBJECT (toplevel));
+ }
+
+ panel_toplevel_update_expanded_position (toplevel);
+ panel_toplevel_calc_floating (toplevel); //FIXME should probably be done after panel_toplevel_update_normal_position() too
+
+ if (toplevel->priv->x_right == -1)
+ x = toplevel->priv->x;
+ else
+ x = monitor_width - (toplevel->priv->x_right + toplevel->priv->geometry.width);
+ if (toplevel->priv->y_bottom == -1)
+ y = toplevel->priv->y;
+ else
+ y = monitor_height - (toplevel->priv->y_bottom + toplevel->priv->geometry.height);
+
+ if (!toplevel->priv->expand) {
+ if (toplevel->priv->x_centered)
+ x = (monitor_width - toplevel->priv->geometry.width) / 2;
+ if (toplevel->priv->y_centered)
+ y = (monitor_height - toplevel->priv->geometry.height) / 2;
+ }
+
+ w = h = -1;
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL)
+ panel_toplevel_update_normal_position (toplevel, &x, &y, &w, &h);
+
+ else if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
+ panel_toplevel_update_auto_hide_position (toplevel, &x, &y, &w, &h, FALSE);
+
+ else
+ panel_toplevel_update_hidden_position (toplevel, &x, &y, &w, &h);
+
+ if (w != -1)
+ toplevel->priv->geometry.width = w;
+ if (h != -1)
+ toplevel->priv->geometry.height = h;
+
+ /* This is some kind of snap: there's a possibility of an infinite loop
+ * because of the bevels of the frame that are set in
+ * panel_toplevel_update_edges(). The bevels change the width/height of
+ * the toplevel. The typical loop is:
+ * x = 1 => outer bevel => x = 0 => no outer bevel = > x = 1 => ...
+ * FIXME: maybe the real bug is that we enter into this loop (see bug
+ * #160748 to learn how to reproduce.) */
+ background = &toplevel->priv->panel_widget->background;
+ /* There's no bevels with a color/image background */
+ if (panel_background_effective_type (background) == PANEL_BACK_NONE) {
+ GtkStyle *style;
+ GdkRectangle *geometry;
+ int max_size;
+
+ style = gtk_widget_get_style (GTK_WIDGET (toplevel->priv->inner_frame));
+ geometry = &toplevel->priv->geometry;
+
+ if (x <= style->xthickness && x > 0 &&
+ !toplevel->priv->x_centered)
+ x = 0;
+
+ if (y <= style->ythickness && y > 0 &&
+ !toplevel->priv->y_centered)
+ y = 0;
+
+ max_size = monitor_width - geometry->width - style->xthickness;
+ if (x + style->xthickness >= max_size && x < max_size &&
+ !toplevel->priv->x_centered)
+ x = max_size;
+
+ max_size = monitor_height - geometry->height - style->ythickness;
+ if (y + style->ythickness >= max_size && y < max_size &&
+ !toplevel->priv->y_centered)
+ y = max_size;
+ }
+
+ x += panel_multiscreen_x (screen, toplevel->priv->monitor);
+ y += panel_multiscreen_y (screen, toplevel->priv->monitor);
+
+ toplevel->priv->geometry.x = x;
+ toplevel->priv->geometry.y = y;
+}
+
+static int
+calculate_minimum_height (GtkWidget *widget,
+ PanelOrientation orientation)
+{
+ GtkStyle *style;
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ int focus_width = 0;
+ int focus_pad = 0;
+ int ascent;
+ int descent;
+ int thickness;
+
+ style = gtk_widget_get_style (widget);
+ context = gtk_widget_get_pango_context (widget);
+ metrics = pango_context_get_metrics (context,
+ style->font_desc,
+ pango_context_get_language (context));
+
+ ascent = pango_font_metrics_get_ascent (metrics);
+ descent = pango_font_metrics_get_descent (metrics);
+
+ pango_font_metrics_unref (metrics);
+
+ gtk_widget_style_get (widget,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ NULL);
+
+ thickness = orientation & PANEL_HORIZONTAL_MASK ?
+ style->ythickness :
+ style->xthickness;
+
+ return PANGO_PIXELS (ascent + descent) + 2 * (focus_width + focus_pad + thickness);
+}
+
+static int
+panel_toplevel_update_size_from_hints (PanelToplevel *toplevel,
+ int requisition_size,
+ int monitor_size,
+ int non_panel_widget_size)
+{
+ int nb_size_hints;
+ AppletSizeHints *applets_hints;
+ AppletSizeHintsAlloc *using_hint;
+
+ int i;
+ int total_size;
+ int full_hints;
+
+ total_size = non_panel_widget_size + requisition_size;
+
+ nb_size_hints = toplevel->priv->panel_widget->nb_applets_size_hints;
+ if (nb_size_hints <= 0)
+ return total_size;
+
+ applets_hints = toplevel->priv->panel_widget->applets_hints;
+ using_hint = toplevel->priv->panel_widget->applets_using_hint;
+
+ for (i = 0; i < nb_size_hints; i++) {
+ using_hint[i].index = applets_hints[i].len - 2;
+ using_hint[i].size = applets_hints[i].hints[applets_hints[i].len - 1];
+ total_size += using_hint[i].size;
+ }
+
+ if (total_size > monitor_size)
+ return monitor_size;
+
+ full_hints = 0;
+ while (full_hints != nb_size_hints && total_size < monitor_size) {
+ int bonus;
+ int extra_bonus;
+
+ bonus = (monitor_size - total_size)
+ / (nb_size_hints - full_hints);
+ extra_bonus = (monitor_size - total_size)
+ % (nb_size_hints - full_hints);
+ full_hints = 0;
+
+ for (i = 0; i < nb_size_hints; i++) {
+ int new_size;
+ int current_bonus;
+
+ current_bonus = bonus;
+
+ while (using_hint[i].index > 0 && applets_hints[i].hints[using_hint[i].index - 1] < using_hint[i].size + current_bonus) {
+ new_size = applets_hints[i].hints[using_hint[i].index - 1];
+ current_bonus = using_hint[i].size
+ + current_bonus - new_size;
+ total_size = total_size - using_hint[i].size
+ + new_size;
+
+ using_hint[i].index -= 2;
+ using_hint[i].size = new_size;
+ }
+
+ new_size = MIN (applets_hints[i].hints[using_hint[i].index],
+ using_hint[i].size + current_bonus);
+ if (new_size > using_hint[i].size) {
+ total_size += (new_size - using_hint[i].size);
+ using_hint[i].size = new_size;
+ }
+
+ if (extra_bonus > 0) {
+ new_size = MIN (applets_hints[i].hints[using_hint[i].index],
+ using_hint[i].size + extra_bonus);
+ if (new_size > using_hint[i].size) {
+ total_size += (new_size
+ - using_hint[i].size);
+ extra_bonus -= (new_size
+ - using_hint[i].size);
+ using_hint[i].size = new_size;
+ }
+ }
+
+ if (using_hint[i].size == applets_hints[i].hints[using_hint[i].index])
+ full_hints++;
+ }
+ }
+
+ return total_size;
+}
+
+static void
+panel_toplevel_update_size (PanelToplevel *toplevel,
+ GtkRequisition *requisition)
+{
+ GtkWidget *widget;
+ GtkStyle *style;
+ int monitor_width, monitor_height;
+ int width, height;
+ int minimum_height;
+ int non_panel_widget_size;
+
+ if (toplevel->priv->animating)
+ return;
+
+ widget = GTK_WIDGET (toplevel);
+ style = gtk_widget_get_style (widget);
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ width = requisition->width;
+ height = requisition->height;
+
+ if (!toplevel->priv->expand &&
+ !toplevel->priv->buttons_enabled && !toplevel->priv->attached)
+ non_panel_widget_size = 2 * HANDLE_SIZE;
+ else
+ non_panel_widget_size = 0;
+
+ minimum_height = calculate_minimum_height (GTK_WIDGET (toplevel),
+ toplevel->priv->orientation);
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
+
+ height = MAX (MIN (MAX (height, toplevel->priv->size),
+ panel_toplevel_get_maximum_size (toplevel)),
+ minimum_height);
+
+ if (toplevel->priv->expand)
+ width = monitor_width;
+ else {
+ int max_width;
+
+ if (!toplevel->priv->attached)
+ max_width = monitor_width;
+ else {
+ if (panel_toplevel_get_orientation (toplevel->priv->attach_toplevel) == PANEL_ORIENTATION_LEFT)
+ max_width = monitor_width
+ - toplevel->priv->geometry.x;
+ else
+ max_width = toplevel->priv->geometry.x +
+ toplevel->priv->geometry.width;
+ }
+
+ width = panel_toplevel_update_size_from_hints (
+ toplevel,
+ requisition->width,
+ max_width,
+ non_panel_widget_size);
+ }
+
+ width = MAX (MINIMUM_WIDTH, width);
+ } else {
+ width = MAX (MIN (MAX (width, toplevel->priv->size),
+ panel_toplevel_get_maximum_size (toplevel)),
+ minimum_height);
+
+ if (toplevel->priv->expand)
+ height = monitor_height;
+ else {
+ int max_height;
+
+ if (!toplevel->priv->attached)
+ max_height = monitor_height;
+ else {
+ if (panel_toplevel_get_orientation (toplevel->priv->attach_toplevel) == PANEL_ORIENTATION_TOP)
+ max_height = monitor_height
+ - toplevel->priv->geometry.y;
+ else
+ max_height = toplevel->priv->geometry.y +
+ toplevel->priv->geometry.height;
+ }
+
+ height = panel_toplevel_update_size_from_hints (
+ toplevel,
+ requisition->height,
+ max_height,
+ non_panel_widget_size);
+ }
+
+ height = MAX (MINIMUM_WIDTH, height);
+ }
+
+ if (toplevel->priv->edges & PANEL_EDGE_TOP)
+ height += style->ythickness;
+ if (toplevel->priv->edges & PANEL_EDGE_BOTTOM)
+ height += style->ythickness;
+ if (toplevel->priv->edges & PANEL_EDGE_LEFT)
+ width += style->ythickness;
+ if (toplevel->priv->edges & PANEL_EDGE_RIGHT)
+ width += style->ythickness;
+
+ toplevel->priv->geometry.width = CLAMP (width, 0, monitor_width);
+ toplevel->priv->geometry.height = CLAMP (height, 0, monitor_height);
+ toplevel->priv->original_width = toplevel->priv->geometry.width;
+ toplevel->priv->original_height = toplevel->priv->geometry.height;
+}
+
+static void
+panel_toplevel_update_geometry (PanelToplevel *toplevel,
+ GtkRequisition *requisition)
+{
+ toplevel->priv->updated_geometry_initial = TRUE;
+ panel_toplevel_update_size (toplevel, requisition);
+ panel_toplevel_update_position (toplevel);
+
+ panel_toplevel_update_struts (toplevel, FALSE);
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL ||
+ toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN) {
+ panel_struts_update_toplevel_geometry (toplevel,
+ &toplevel->priv->geometry.x,
+ &toplevel->priv->geometry.y,
+ &toplevel->priv->geometry.width,
+ &toplevel->priv->geometry.height);
+ } else {
+ panel_struts_update_toplevel_geometry (toplevel,
+ &toplevel->priv->geometry.x,
+ &toplevel->priv->geometry.y,
+ NULL, NULL);
+ }
+
+ panel_toplevel_update_edges (toplevel);
+ panel_toplevel_update_description (toplevel);
+}
+
+static void
+panel_toplevel_attach_widget_destroyed (PanelToplevel *toplevel)
+{
+ panel_toplevel_detach (toplevel);
+}
+
+static gboolean
+panel_toplevel_attach_widget_configure (PanelToplevel *toplevel)
+{
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ return FALSE;
+}
+
+static void
+panel_toplevel_update_attach_orientation (PanelToplevel *toplevel)
+{
+ PanelOrientation attach_orientation;
+ PanelOrientation orientation;
+
+ attach_orientation =
+ panel_toplevel_get_orientation (toplevel->priv->attach_toplevel);
+
+ orientation = toplevel->priv->orientation;
+
+ switch (attach_orientation) {
+ case PANEL_ORIENTATION_TOP:
+ orientation = PANEL_ORIENTATION_LEFT;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ orientation = PANEL_ORIENTATION_RIGHT;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ orientation = PANEL_ORIENTATION_TOP;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ orientation = PANEL_ORIENTATION_BOTTOM;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ panel_toplevel_set_orientation (toplevel, orientation);
+}
+
+static void
+panel_toplevel_attach_widget_parent_set (PanelToplevel *toplevel,
+ GtkWidget *previous_parent,
+ GtkWidget *attach_widget)
+{
+ GtkWidget *panel_widget;
+
+ panel_widget = gtk_widget_get_parent (GTK_WIDGET (attach_widget));
+ if (!panel_widget)
+ return;
+
+ g_assert (PANEL_IS_WIDGET (panel_widget));
+
+ toplevel->priv->attach_toplevel = PANEL_WIDGET (panel_widget)->toplevel;
+ panel_toplevel_update_attach_orientation (toplevel);
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+}
+
+static void
+panel_toplevel_attach_toplevel_hiding (PanelToplevel *toplevel)
+{
+ if (!panel_toplevel_get_is_hidden (toplevel)) {
+ panel_toplevel_hide (toplevel, FALSE, -1);
+
+ toplevel->priv->attach_hidden = TRUE;
+ }
+}
+
+static void
+panel_toplevel_attach_toplevel_unhiding (PanelToplevel *toplevel)
+{
+ if (!toplevel->priv->attach_hidden)
+ return;
+
+ toplevel->priv->attach_hidden = FALSE;
+
+ panel_toplevel_unhide (toplevel);
+}
+
+static void
+panel_toplevel_reverse_arrow (PanelToplevel *toplevel,
+ GtkWidget *button)
+{
+ GtkArrowType arrow_type;
+
+ arrow_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "arrow-type"));
+
+ switch (arrow_type) {
+ case GTK_ARROW_UP:
+ arrow_type = GTK_ARROW_DOWN;
+ break;
+ case GTK_ARROW_DOWN:
+ arrow_type = GTK_ARROW_UP;
+ break;
+ case GTK_ARROW_LEFT:
+ arrow_type = GTK_ARROW_RIGHT;
+ break;
+ case GTK_ARROW_RIGHT:
+ arrow_type = GTK_ARROW_LEFT;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ g_object_set_data (G_OBJECT (button), "arrow-type", GINT_TO_POINTER (arrow_type));
+
+ gtk_arrow_set (GTK_ARROW (gtk_bin_get_child (GTK_BIN (button))), arrow_type, GTK_SHADOW_NONE);
+}
+
+static void
+panel_toplevel_reverse_arrows (PanelToplevel *toplevel)
+{
+ panel_toplevel_reverse_arrow (toplevel, toplevel->priv->hide_button_top);
+ panel_toplevel_reverse_arrow (toplevel, toplevel->priv->hide_button_bottom);
+ panel_toplevel_reverse_arrow (toplevel, toplevel->priv->hide_button_left);
+ panel_toplevel_reverse_arrow (toplevel, toplevel->priv->hide_button_right);
+}
+
+static void
+panel_toplevel_disconnect_attached (PanelToplevel *toplevel)
+{
+ int i;
+
+ for (i = 0; i < N_ATTACH_TOPLEVEL_SIGNALS; i++) {
+ if (!toplevel->priv->attach_toplevel_signals [i])
+ continue;
+
+ g_signal_handler_disconnect (
+ toplevel->priv->attach_toplevel,
+ toplevel->priv->attach_toplevel_signals [i]);
+ toplevel->priv->attach_toplevel_signals [i] = 0;
+ }
+
+ for (i = 0; i < N_ATTACH_WIDGET_SIGNALS; i++) {
+ if (!toplevel->priv->attach_widget_signals [i])
+ continue;
+
+ g_signal_handler_disconnect (
+ toplevel->priv->attach_widget,
+ toplevel->priv->attach_widget_signals [i]);
+ toplevel->priv->attach_widget_signals [i] = 0;
+ }
+}
+
+static void
+panel_toplevel_connect_attached (PanelToplevel *toplevel)
+{
+ gulong *signals;
+ int i = 0;
+
+ signals = toplevel->priv->attach_toplevel_signals;
+
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_toplevel, "destroy",
+ G_CALLBACK (panel_toplevel_attach_widget_destroyed), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_toplevel, "notify::orientation",
+ G_CALLBACK (panel_toplevel_update_attach_orientation), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_toplevel, "configure-event",
+ G_CALLBACK (panel_toplevel_attach_widget_configure), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_toplevel, "hiding",
+ G_CALLBACK (panel_toplevel_attach_toplevel_hiding), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_toplevel, "unhiding",
+ G_CALLBACK (panel_toplevel_attach_toplevel_unhiding), toplevel);
+
+ g_assert (i == N_ATTACH_TOPLEVEL_SIGNALS);
+
+ signals = toplevel->priv->attach_widget_signals;
+ i = 0;
+
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_widget, "destroy",
+ G_CALLBACK (panel_toplevel_attach_widget_destroyed), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_widget, "configure-event",
+ G_CALLBACK (panel_toplevel_attach_widget_configure), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_widget, "parent-set",
+ G_CALLBACK (panel_toplevel_attach_widget_parent_set), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_widget, "show",
+ G_CALLBACK (gtk_widget_show), toplevel);
+ signals [i++] = g_signal_connect_swapped (
+ toplevel->priv->attach_widget, "hide",
+ G_CALLBACK (gtk_widget_hide), toplevel);
+
+ g_assert (i == N_ATTACH_WIDGET_SIGNALS);
+}
+
+void
+panel_toplevel_attach_to_widget (PanelToplevel *toplevel,
+ PanelToplevel *attach_toplevel,
+ GtkWidget *attach_widget)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+ g_return_if_fail (PANEL_IS_TOPLEVEL (attach_toplevel));
+ g_return_if_fail (GTK_IS_WIDGET (attach_widget));
+
+ if (toplevel->priv->attached)
+ panel_toplevel_disconnect_attached (toplevel);
+
+ toplevel->priv->attached = TRUE;
+
+ /* Cancelling the initial animation for drawers in
+ * panel_toplevel_initially_hide() is not enough, since this will
+ * happen only when the toplevel is realized, which might be too late
+ * for drawers (since it's realized when the drawer is clicked) */
+ toplevel->priv->initial_animation_done = TRUE;
+
+ toplevel->priv->attach_toplevel = attach_toplevel;
+ toplevel->priv->attach_widget = attach_widget;
+
+ panel_toplevel_connect_attached (toplevel);
+
+ panel_toplevel_reverse_arrows (toplevel);
+ panel_toplevel_set_expand (toplevel, FALSE);
+ panel_toplevel_update_attach_orientation (toplevel);
+ panel_toplevel_update_hide_buttons (toplevel);
+
+ gtk_window_set_screen (GTK_WINDOW (toplevel),
+ gtk_widget_get_screen (GTK_WIDGET (attach_toplevel)));
+ panel_toplevel_set_monitor (toplevel,
+ panel_toplevel_get_monitor (attach_toplevel));
+ if (toplevel->priv->state == PANEL_STATE_NORMAL)
+ panel_toplevel_push_autohide_disabler (toplevel->priv->attach_toplevel);
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+}
+
+void
+panel_toplevel_detach (PanelToplevel *toplevel)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (!toplevel->priv->attached)
+ return;
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL)
+ panel_toplevel_pop_autohide_disabler (toplevel->priv->attach_toplevel);
+
+ panel_toplevel_disconnect_attached (toplevel);
+
+ panel_toplevel_reverse_arrows (toplevel);
+
+ toplevel->priv->attached = FALSE;
+
+ toplevel->priv->attach_toplevel = NULL;
+ toplevel->priv->attach_widget = NULL;
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+}
+
+gboolean
+panel_toplevel_get_is_attached (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->attached;
+}
+
+PanelToplevel *
+panel_toplevel_get_attach_toplevel (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
+
+ return toplevel->priv->attach_toplevel;
+}
+
+GtkWidget *
+panel_toplevel_get_attach_widget (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
+
+ return toplevel->priv->attach_widget;
+}
+
+static gboolean
+panel_toplevel_popup_panel_menu (PanelToplevel *toplevel)
+{
+ gboolean retval = FALSE;
+
+ g_signal_emit_by_name (toplevel, "popup_menu", &retval);
+
+ return retval;
+}
+
+static gboolean
+panel_toplevel_toggle_expand (PanelToplevel *toplevel)
+{
+ panel_toplevel_set_expand (toplevel, !toplevel->priv->expand);
+
+ return TRUE;
+}
+
+static gboolean
+panel_toplevel_expand (PanelToplevel *toplevel)
+{
+ panel_toplevel_set_expand (toplevel, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+panel_toplevel_unexpand (PanelToplevel *toplevel)
+{
+ panel_toplevel_set_expand (toplevel, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+panel_toplevel_toggle_hidden (PanelToplevel *toplevel)
+{
+ if (toplevel->priv->state == PANEL_STATE_NORMAL)
+ panel_toplevel_hide (toplevel, toplevel->priv->auto_hide, -1);
+ else
+ panel_toplevel_unhide (toplevel);
+
+ return FALSE;
+}
+
+static gboolean
+panel_toplevel_begin_move (PanelToplevel *toplevel)
+{
+ if (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE)
+ return FALSE;
+
+ panel_toplevel_begin_grab_op (
+ toplevel, PANEL_GRAB_OP_MOVE, TRUE, GDK_CURRENT_TIME);
+
+ return TRUE;
+}
+
+static gboolean
+panel_toplevel_begin_resize (PanelToplevel *toplevel)
+{
+ if (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE)
+ return FALSE;
+
+ panel_toplevel_begin_grab_op (
+ toplevel, PANEL_GRAB_OP_RESIZE, TRUE, GDK_CURRENT_TIME);
+
+ return TRUE;
+}
+
+static void
+panel_toplevel_move_resize_window (PanelToplevel *toplevel,
+ gboolean move,
+ gboolean resize)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (toplevel);
+
+ g_assert (gtk_widget_get_realized (widget));
+
+ if (move && resize)
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ toplevel->priv->geometry.x,
+ toplevel->priv->geometry.y,
+ toplevel->priv->geometry.width,
+ toplevel->priv->geometry.height);
+ else if (move)
+ gdk_window_move (gtk_widget_get_window (widget),
+ toplevel->priv->geometry.x,
+ toplevel->priv->geometry.y);
+ else if (resize)
+ gdk_window_resize (gtk_widget_get_window (widget),
+ toplevel->priv->geometry.width,
+ toplevel->priv->geometry.height);
+}
+
+static void
+panel_toplevel_initially_hide (PanelToplevel *toplevel)
+{
+ if (!toplevel->priv->attached) {
+ toplevel->priv->initial_animation_done = FALSE;
+
+ /* We start the panel off hidden until all the applets are
+ * loaded, and then finally slide it down when it's ready to be
+ * used */
+ toplevel->priv->state = PANEL_STATE_AUTO_HIDDEN;
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+ } else
+ toplevel->priv->initial_animation_done = TRUE;
+}
+
+static void
+panel_toplevel_realize (GtkWidget *widget)
+{
+ PanelToplevel *toplevel = (PanelToplevel *) widget;
+ GdkWindow *window;
+
+ gtk_window_set_decorated (GTK_WINDOW (widget), FALSE);
+ gtk_window_stick (GTK_WINDOW (widget));
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->realize)
+ GTK_WIDGET_CLASS (panel_toplevel_parent_class)->realize (widget);
+
+ window = gtk_widget_get_window (widget);
+
+ panel_struts_set_window_hint (toplevel);
+ panel_xutils_set_window_type (window, PANEL_XUTILS_TYPE_DOCK);
+
+ gdk_window_set_group (window, window);
+ gdk_window_set_geometry_hints (window, NULL, GDK_HINT_POS);
+
+ panel_toplevel_initially_hide (toplevel);
+
+ panel_toplevel_move_resize_window (toplevel, TRUE, TRUE);
+}
+
+static void
+panel_toplevel_disconnect_timeouts (PanelToplevel *toplevel)
+{
+ if (toplevel->priv->hide_timeout)
+ g_source_remove (toplevel->priv->hide_timeout);
+ toplevel->priv->hide_timeout = 0;
+
+ if (toplevel->priv->unhide_timeout)
+ g_source_remove (toplevel->priv->unhide_timeout);
+ toplevel->priv->unhide_timeout = 0;
+
+ if (toplevel->priv->animation_timeout)
+ g_source_remove (toplevel->priv->animation_timeout);
+ toplevel->priv->animation_timeout = 0;
+}
+
+static void
+panel_toplevel_unrealize (GtkWidget *widget)
+{
+ panel_toplevel_disconnect_timeouts (PANEL_TOPLEVEL (widget));
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->unrealize)
+ GTK_WIDGET_CLASS (panel_toplevel_parent_class)->unrealize (widget);
+}
+
+static void
+panel_toplevel_destroy (GtkObject *widget)
+{
+ PanelToplevel *toplevel = (PanelToplevel *) widget;
+
+ if (toplevel->priv->attached) {
+ panel_toplevel_disconnect_attached (toplevel);
+ toplevel->priv->attached = FALSE;
+
+ toplevel->priv->attach_toplevel = NULL;
+ toplevel->priv->attach_widget = NULL;
+ }
+
+ panel_toplevel_disconnect_timeouts (toplevel);
+
+ if (GTK_OBJECT_CLASS (panel_toplevel_parent_class)->destroy)
+ GTK_OBJECT_CLASS (panel_toplevel_parent_class)->destroy (widget);
+}
+
+static void
+panel_toplevel_check_resize (GtkContainer *container)
+{
+ GtkAllocation allocation;
+ GtkAllocation widget_allocation;
+ GtkRequisition requisition;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (container);
+
+ if (!gtk_widget_get_visible (widget))
+ return;
+
+ requisition.width = -1;
+ requisition.height = -1;
+
+ gtk_widget_size_request (widget, &requisition);
+ gtk_widget_get_allocation (widget, &widget_allocation);
+
+ if (widget_allocation.width != requisition.width ||
+ widget_allocation.height != requisition.height)
+ return;
+
+ allocation = widget_allocation;
+ gtk_widget_size_allocate (widget, &allocation);
+}
+
+static void
+panel_toplevel_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ PanelToplevel *toplevel;
+ GtkBin *bin;
+ GtkWidget *child;
+ GdkRectangle old_geometry;
+ int position_changed = FALSE;
+ int size_changed = FALSE;
+
+ toplevel = PANEL_TOPLEVEL (widget);
+ bin = GTK_BIN (widget);
+
+ /* we get a size request when there are new monitors, so first try to
+ * see if we need to move to a new monitor */
+ panel_toplevel_update_monitor (toplevel);
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_request (child, requisition);
+
+ old_geometry = toplevel->priv->geometry;
+
+ panel_toplevel_update_geometry (toplevel, requisition);
+
+ requisition->width = toplevel->priv->geometry.width;
+ requisition->height = toplevel->priv->geometry.height;
+
+ if (!gtk_widget_get_realized (widget))
+ return;
+
+ if (old_geometry.width != toplevel->priv->geometry.width ||
+ old_geometry.height != toplevel->priv->geometry.height)
+ size_changed = TRUE;
+
+ if (old_geometry.x != toplevel->priv->geometry.x ||
+ old_geometry.y != toplevel->priv->geometry.y)
+ position_changed = TRUE;
+
+ panel_toplevel_move_resize_window (toplevel, position_changed, size_changed);
+}
+
+static void
+panel_toplevel_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ PanelToplevel *toplevel = (PanelToplevel *) widget;
+ GtkBin *bin = (GtkBin *) widget;
+ GtkStyle *style;
+ GtkWidget *child;
+ GtkAllocation challoc;
+ GtkAllocation child_allocation;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (toplevel->priv->expand ||
+ toplevel->priv->buttons_enabled ||
+ toplevel->priv->attached)
+ challoc = *allocation;
+ else {
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
+ challoc.x = HANDLE_SIZE;
+ challoc.y = 0;
+ challoc.width = allocation->width - 2 * HANDLE_SIZE;
+ challoc.height = allocation->height;
+ } else {
+ challoc.x = 0;
+ challoc.y = HANDLE_SIZE;
+ challoc.width = allocation->width;
+ challoc.height = allocation->height - 2 * HANDLE_SIZE;
+ }
+ }
+
+ style = gtk_widget_get_style (widget);
+
+ if (toplevel->priv->edges & PANEL_EDGE_TOP) {
+ challoc.y += style->ythickness;
+ challoc.height -= style->ythickness;
+ }
+
+ if (toplevel->priv->edges & PANEL_EDGE_LEFT) {
+ challoc.x += style->xthickness;
+ challoc.width -= style->xthickness;
+ }
+
+ if (toplevel->priv->edges & PANEL_EDGE_BOTTOM)
+ challoc.height -= style->ythickness;
+
+ if (toplevel->priv->edges & PANEL_EDGE_RIGHT)
+ challoc.width -= style->xthickness;
+
+ challoc.width = MAX (1, challoc.width);
+ challoc.height = MAX (1, challoc.height);
+
+ child = gtk_bin_get_child (bin);
+ gtk_widget_get_allocation (child, &child_allocation);
+
+ if (gtk_widget_get_mapped (widget) &&
+ (challoc.x != child_allocation.x ||
+ challoc.y != child_allocation.y ||
+ challoc.width != child_allocation.width ||
+ challoc.height != child_allocation.height)) {
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (widget, &allocation);
+ gdk_window_invalidate_rect (gtk_widget_get_window (widget), &allocation, FALSE);
+ }
+
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_allocate (child, &challoc);
+}
+
+static gboolean panel_toplevel_expose(GtkWidget* widget, GdkEventExpose* event)
+{
+ PanelToplevel* toplevel = (PanelToplevel*) widget;
+ PanelFrameEdge edges;
+ gboolean retval = FALSE;
+ GdkWindow *window;
+ GtkStyle *style;
+ GtkStateType state;
+ GtkAllocation allocation;
+
+ if (!gtk_widget_is_drawable (widget))
+ return retval;
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->expose_event)
+ retval = GTK_WIDGET_CLASS (panel_toplevel_parent_class)->expose_event (widget, event);
+
+ edges = toplevel->priv->edges;
+ panel_frame_draw (widget, edges);
+
+ if (toplevel->priv->expand ||
+ toplevel->priv->buttons_enabled ||
+ toplevel->priv->attached)
+ return retval;
+
+ window = gtk_widget_get_window (widget);
+ style = gtk_widget_get_style (widget);
+ state = gtk_widget_get_state (widget);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
+ int x, y, width, height;
+ int xthickness, ythickness;
+
+ x = allocation.x;
+ y = allocation.y;
+ width = HANDLE_SIZE;
+ height = allocation.height;
+
+ xthickness = style->xthickness;
+ ythickness = style->ythickness;
+
+ if (edges & PANEL_EDGE_TOP) {
+ y += ythickness;
+ height -= ythickness;
+ }
+ if (edges & PANEL_EDGE_BOTTOM)
+ height -= ythickness;
+ if (edges & PANEL_EDGE_LEFT)
+ x += xthickness;
+
+ gtk_paint_handle (style, window, state,
+ GTK_SHADOW_OUT,
+ &event->area, widget, "handlebox",
+ x, y, width, height,
+ GTK_ORIENTATION_VERTICAL);
+
+ x = allocation.width - HANDLE_SIZE;
+ if (edges & PANEL_EDGE_RIGHT)
+ x -= xthickness;
+
+ gtk_paint_handle (style, window, state,
+ GTK_SHADOW_OUT,
+ &event->area, widget, "handlebox",
+ x, y, width, height,
+ GTK_ORIENTATION_VERTICAL);
+ } else {
+ int x, y, width, height;
+ int xthickness, ythickness;
+
+ x = allocation.x;
+ y = allocation.y;
+ width = allocation.width;
+ height = HANDLE_SIZE;
+
+ xthickness = style->xthickness;
+ ythickness = style->ythickness;
+
+ if (edges & PANEL_EDGE_LEFT) {
+ x += xthickness;
+ width -= xthickness;
+ }
+ if (edges & PANEL_EDGE_RIGHT)
+ width -= xthickness;
+ if (edges & PANEL_EDGE_TOP)
+ y += ythickness;
+
+ gtk_paint_handle (style, window, state,
+ GTK_SHADOW_OUT,
+ &event->area, widget, "handlebox",
+ x, y, width, height,
+ GTK_ORIENTATION_HORIZONTAL);
+
+ y = allocation.height - HANDLE_SIZE;
+ if (edges & PANEL_EDGE_BOTTOM)
+ y -= ythickness;
+
+ gtk_paint_handle (style, window, state,
+ GTK_SHADOW_OUT,
+ &event->area, widget, "handlebox",
+ x, y, width, height,
+ GTK_ORIENTATION_HORIZONTAL);
+ }
+
+ return retval;
+}
+
+static gboolean
+panel_toplevel_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ PanelToplevel *toplevel;
+ GtkWidget *event_widget;
+
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
+
+ toplevel = PANEL_TOPLEVEL (widget);
+
+ if (event->button != 1 && event->button != 2)
+ return FALSE;
+
+ if (toplevel->priv->animating)
+ return FALSE;
+
+ /* Get the mouse-button modifier from marco so that only intentional
+ * moves are considered. We don't this for non-expanded panels since we
+ * only have the handles that the user can grab. */
+ if ((toplevel->priv->expand || toplevel->priv->attached) &&
+ (event->state & GDK_MODIFIER_MASK) != panel_bindings_get_mouse_button_modifier_keymask ())
+ return FALSE;
+
+ gdk_window_get_user_data (event->window, (gpointer)&event_widget);
+ g_assert (GTK_IS_WIDGET (event_widget));
+ gtk_widget_translate_coordinates (event_widget,
+ widget,
+ event->x,
+ event->y,
+ &toplevel->priv->drag_offset_x,
+ &toplevel->priv->drag_offset_y);
+
+ panel_toplevel_begin_grab_op (toplevel, PANEL_GRAB_OP_MOVE, FALSE, event->time);
+
+ return TRUE;
+}
+
+static gboolean
+panel_toplevel_button_release_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ PanelToplevel *toplevel;
+
+ if (event->button != 1 && event->button != 2)
+ return FALSE;
+
+ toplevel = PANEL_TOPLEVEL (widget);
+
+ if (toplevel->priv->grab_op == PANEL_GRAB_OP_NONE)
+ return FALSE;
+
+ if (toplevel->priv->grab_is_keyboard)
+ return FALSE;
+
+ panel_toplevel_end_grab_op (toplevel, event->time);
+
+ return TRUE;
+}
+
+static gboolean
+panel_toplevel_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ PanelToplevel *toplevel = (PanelToplevel *) widget;
+
+ if (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE &&
+ panel_toplevel_handle_grab_op_key_event (toplevel, event))
+ return TRUE;
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->key_press_event)
+ return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->key_press_event (widget, event);
+
+ return FALSE;
+}
+
+static gboolean
+panel_toplevel_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ if (gdk_event_get_screen ((GdkEvent *)event) ==
+ gtk_window_get_screen (GTK_WINDOW (widget)))
+ return panel_toplevel_handle_grab_op_motion_event (
+ PANEL_TOPLEVEL (widget), event);
+ else
+ return FALSE;
+}
+
+static gboolean
+panel_toplevel_animation_timeout (PanelToplevel *toplevel)
+{
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ if (!toplevel->priv->animating) {
+ toplevel->priv->animation_end_x = 0xdead;
+ toplevel->priv->animation_end_y = 0xdead;
+ toplevel->priv->animation_end_width = 0xdead;
+ toplevel->priv->animation_end_height = 0xdead;
+ toplevel->priv->animation_start_time.tv_sec = 0xdead;
+ toplevel->priv->animation_start_time.tv_usec = 0xdead;
+ toplevel->priv->animation_end_time.tv_sec = 0xdead;
+ toplevel->priv->animation_end_time.tv_usec = 0xdead;
+ toplevel->priv->animation_timeout = 0;
+ toplevel->priv->initial_animation_done = TRUE;
+ }
+
+ return toplevel->priv->animating;
+}
+
+static long
+panel_toplevel_get_animation_time (PanelToplevel *toplevel)
+{
+ /* The number of seconds to complete the animation.
+ */
+#define ANIMATION_TIME_FAST 0.4
+#define ANIMATION_TIME_MEDIUM 1.2
+#define ANIMATION_TIME_SLOW 2.0
+
+ long t;
+
+ switch (toplevel->priv->animation_speed) {
+ case PANEL_ANIMATION_SLOW:
+ t = ANIMATION_TIME_SLOW * G_USEC_PER_SEC;
+ break;
+ case PANEL_ANIMATION_MEDIUM:
+ t = ANIMATION_TIME_MEDIUM * G_USEC_PER_SEC;
+ break;
+ case PANEL_ANIMATION_FAST:
+ t = ANIMATION_TIME_FAST * G_USEC_PER_SEC;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return t;
+
+#undef ANIMATION_TIME_FAST
+#undef ANIMATION_TIME_MEDIUM
+#undef ANIMATION_TIME_SLOW
+}
+
+static void
+panel_toplevel_calculate_animation_end_geometry (PanelToplevel *toplevel)
+{
+ GdkScreen *screen;
+ int monitor_width, monitor_height;
+
+ toplevel->priv->animation_end_x = toplevel->priv->x;
+ toplevel->priv->animation_end_y = toplevel->priv->y;
+ toplevel->priv->animation_end_width = -1;
+ toplevel->priv->animation_end_height = -1;
+
+ screen = panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ if (!toplevel->priv->expand) {
+
+ if (toplevel->priv->x_centered)
+ toplevel->priv->animation_end_x =
+ (monitor_width - toplevel->priv->geometry.width) / 2;
+ if (toplevel->priv->y_centered)
+ toplevel->priv->animation_end_y =
+ (monitor_height - toplevel->priv->geometry.height) / 2;
+ }
+
+ /* we consider the toplevels which are in the initial animation stage
+ * as in a normal state */
+ if (toplevel->priv->state == PANEL_STATE_NORMAL ||
+ (!toplevel->priv->initial_animation_done &&
+ !toplevel->priv->auto_hide))
+ panel_toplevel_update_normal_position (toplevel,
+ &toplevel->priv->animation_end_x,
+ &toplevel->priv->animation_end_y,
+ &toplevel->priv->animation_end_width,
+ &toplevel->priv->animation_end_height);
+
+ else if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
+ panel_toplevel_update_auto_hide_position (toplevel,
+ &toplevel->priv->animation_end_x,
+ &toplevel->priv->animation_end_y,
+ &toplevel->priv->animation_end_width,
+ &toplevel->priv->animation_end_height,
+ TRUE);
+ else
+ panel_toplevel_update_hidden_position (toplevel,
+ &toplevel->priv->animation_end_x,
+ &toplevel->priv->animation_end_y,
+ &toplevel->priv->animation_end_width,
+ &toplevel->priv->animation_end_height);
+}
+
+static void
+panel_toplevel_start_animation (PanelToplevel *toplevel)
+{
+ GdkScreen *screen;
+ GtkRequisition requisition;
+ int deltax, deltay, deltaw = 0, deltah = 0;
+ int cur_x = -1, cur_y = -1;
+ long t;
+
+ panel_toplevel_calculate_animation_end_geometry (toplevel);
+
+ toplevel->priv->animating = TRUE;
+
+ panel_toplevel_update_struts (toplevel, TRUE);
+ panel_struts_update_toplevel_geometry (toplevel,
+ &toplevel->priv->animation_end_x,
+ &toplevel->priv->animation_end_y,
+ &toplevel->priv->animation_end_width,
+ &toplevel->priv->animation_end_height);
+ panel_toplevel_update_struts (toplevel, FALSE);
+
+ gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (toplevel)), &cur_x, &cur_y);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (toplevel));
+
+ cur_x -= panel_multiscreen_x (screen, toplevel->priv->monitor);
+ cur_y -= panel_multiscreen_y (screen, toplevel->priv->monitor);
+
+ deltax = toplevel->priv->animation_end_x - cur_x;
+ deltay = toplevel->priv->animation_end_y - cur_y;
+
+ gtk_widget_get_requisition (GTK_WIDGET (toplevel), &requisition);
+
+ if (toplevel->priv->animation_end_width != -1)
+ deltaw = toplevel->priv->animation_end_width - requisition.width;
+
+ if (toplevel->priv->animation_end_height != -1)
+ deltah = toplevel->priv->animation_end_height - requisition.height;
+
+ if (deltax == 0 && deltay == 0 && deltaw == 0 && deltah == 0) {
+ toplevel->priv->animation_end_x = -1;
+ toplevel->priv->animation_end_y = -1;
+ toplevel->priv->animation_end_width = -1;
+ toplevel->priv->animation_end_height = -1;
+ toplevel->priv->animating = FALSE;
+ return;
+ }
+
+ if (toplevel->priv->attached) {
+ /* Re-map unmapped attached toplevels */
+ if (!gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
+ gtk_widget_map (GTK_WIDGET (toplevel));
+
+ gtk_window_present (GTK_WINDOW (toplevel->priv->attach_toplevel));
+ }
+
+ g_get_current_time (&toplevel->priv->animation_start_time);
+
+ t = panel_toplevel_get_animation_time (toplevel);
+ g_get_current_time (&toplevel->priv->animation_end_time);
+ g_time_val_add (&toplevel->priv->animation_end_time, t);
+
+ if (!toplevel->priv->animation_timeout)
+ toplevel->priv->animation_timeout =
+ g_timeout_add (20, (GSourceFunc) panel_toplevel_animation_timeout, toplevel);
+}
+
+void
+panel_toplevel_hide (PanelToplevel *toplevel,
+ gboolean auto_hide,
+ GtkDirectionType direction)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->state != PANEL_STATE_NORMAL)
+ return;
+
+ g_signal_emit (toplevel, toplevel_signals [HIDE_SIGNAL], 0);
+
+ if (toplevel->priv->attach_toplevel)
+ panel_toplevel_pop_autohide_disabler (toplevel->priv->attach_toplevel);
+
+ if (auto_hide)
+ toplevel->priv->state = PANEL_STATE_AUTO_HIDDEN;
+ else {
+ if (direction == -1) {
+ if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
+ direction = GTK_DIR_UP;
+ else
+ direction = GTK_DIR_LEFT;
+ }
+
+ switch (direction) {
+ case GTK_DIR_UP:
+ g_return_if_fail (toplevel->priv->orientation & PANEL_VERTICAL_MASK);
+ toplevel->priv->state = PANEL_STATE_HIDDEN_UP;
+ break;
+ case GTK_DIR_DOWN:
+ g_return_if_fail (toplevel->priv->orientation & PANEL_VERTICAL_MASK);
+ toplevel->priv->state = PANEL_STATE_HIDDEN_DOWN;
+ break;
+ case GTK_DIR_LEFT:
+ g_return_if_fail (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK);
+ toplevel->priv->state = PANEL_STATE_HIDDEN_LEFT;
+ break;
+ case GTK_DIR_RIGHT:
+ g_return_if_fail (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK);
+ toplevel->priv->state = PANEL_STATE_HIDDEN_RIGHT;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ panel_toplevel_update_hide_buttons (toplevel);
+ }
+
+ if (toplevel->priv->animate && gtk_widget_get_realized (GTK_WIDGET (toplevel)))
+ panel_toplevel_start_animation (toplevel);
+ else if (toplevel->priv->attached)
+ gtk_widget_hide (GTK_WIDGET (toplevel));
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+}
+
+static gboolean
+panel_toplevel_auto_hide_timeout_handler (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ if (panel_toplevel_get_autohide_disabled (toplevel)) {
+ toplevel->priv->hide_timeout = 0;
+ return FALSE;
+ }
+
+ /* keep coming back until the animation has finished.
+ * FIXME: we should really remove the timeout/idle
+ * completely and re-instate it when the
+ * animation has finished.
+ */
+ if (toplevel->priv->animating)
+ return TRUE;
+
+ panel_toplevel_hide (toplevel, TRUE, -1);
+
+ toplevel->priv->hide_timeout = 0;
+
+ return FALSE;
+}
+
+void
+panel_toplevel_unhide (PanelToplevel *toplevel)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->state == PANEL_STATE_NORMAL)
+ return;
+
+ toplevel->priv->state = PANEL_STATE_NORMAL;
+
+ panel_toplevel_update_hide_buttons (toplevel);
+
+ if (toplevel->priv->attach_toplevel)
+ panel_toplevel_push_autohide_disabler (toplevel->priv->attach_toplevel);
+
+ if (toplevel->priv->animate && gtk_widget_get_realized (GTK_WIDGET (toplevel)))
+ panel_toplevel_start_animation (toplevel);
+ else if (toplevel->priv->attached)
+ gtk_widget_show (GTK_WIDGET (toplevel));
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ if (!toplevel->priv->animate)
+ g_signal_emit (toplevel, toplevel_signals [UNHIDE_SIGNAL], 0);
+}
+
+static gboolean
+panel_toplevel_auto_unhide_timeout_handler (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ /* keep coming back until the animation has finished.
+ * FIXME: we should really remove the timeout/idle
+ * completely and re-instate it when the
+ * animation has finished.
+ */
+ if (toplevel->priv->animating)
+ return TRUE;
+
+ if (!toplevel->priv->animate)
+ toplevel->priv->initial_animation_done = TRUE;
+
+ /* initial animation for auto-hidden panels: we need to unhide and hide
+ * again to get at the right size */
+ if (!toplevel->priv->initial_animation_done &&
+ toplevel->priv->auto_hide) {
+ toplevel->priv->unhide_timeout = 0;
+ panel_toplevel_unhide (toplevel);
+ panel_toplevel_hide (toplevel, TRUE, -1);
+ return FALSE;
+ }
+
+ if (!panel_toplevel_contains_pointer (toplevel) &&
+ toplevel->priv->auto_hide) {
+ toplevel->priv->unhide_timeout = 0;
+ return FALSE;
+ }
+
+ panel_toplevel_unhide (toplevel);
+
+ toplevel->priv->unhide_timeout = 0;
+
+ return FALSE;
+}
+
+void
+panel_toplevel_queue_auto_hide (PanelToplevel *toplevel)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (!toplevel->priv->auto_hide ||
+ panel_toplevel_contains_pointer (toplevel) ||
+ panel_toplevel_get_autohide_disabled (toplevel))
+ return;
+
+ if (toplevel->priv->unhide_timeout)
+ g_source_remove (toplevel->priv->unhide_timeout);
+ toplevel->priv->unhide_timeout = 0;
+
+ if (toplevel->priv->hide_timeout ||
+ toplevel->priv->state != PANEL_STATE_NORMAL)
+ return;
+
+ if (toplevel->priv->hide_delay > 0)
+ toplevel->priv->hide_timeout =
+ g_timeout_add (toplevel->priv->hide_delay,
+ (GSourceFunc) panel_toplevel_auto_hide_timeout_handler,
+ toplevel);
+ else
+ toplevel->priv->hide_timeout =
+ g_idle_add ((GSourceFunc) panel_toplevel_auto_hide_timeout_handler,
+ toplevel);
+}
+
+void
+panel_toplevel_queue_auto_unhide (PanelToplevel *toplevel)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->unhide_timeout)
+ return;
+
+ if (toplevel->priv->hide_timeout)
+ g_source_remove (toplevel->priv->hide_timeout);
+ toplevel->priv->hide_timeout = 0;
+
+ if (toplevel->priv->state != PANEL_STATE_AUTO_HIDDEN)
+ return;
+
+ if (toplevel->priv->unhide_delay > 0)
+ toplevel->priv->unhide_timeout =
+ g_timeout_add (toplevel->priv->unhide_delay,
+ (GSourceFunc) panel_toplevel_auto_unhide_timeout_handler,
+ toplevel);
+ else
+ toplevel->priv->unhide_timeout =
+ g_idle_add ((GSourceFunc) panel_toplevel_auto_unhide_timeout_handler,
+ toplevel);
+}
+
+void
+panel_toplevel_queue_initial_unhide (PanelToplevel *toplevel)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->initial_animation_done)
+ return;
+
+ if (toplevel->priv->unhide_timeout)
+ return;
+
+ toplevel->priv->unhide_timeout =
+ g_idle_add ((GSourceFunc) panel_toplevel_auto_unhide_timeout_handler,
+ toplevel);
+}
+
+static gboolean
+panel_toplevel_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ PanelToplevel *toplevel;
+
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
+
+ toplevel = PANEL_TOPLEVEL (widget);
+
+ if (toplevel->priv->auto_hide && event->detail != GDK_NOTIFY_INFERIOR)
+ panel_toplevel_queue_auto_unhide (toplevel);
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->enter_notify_event)
+ return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->enter_notify_event (widget, event);
+
+ return FALSE;
+}
+
+static gboolean
+panel_toplevel_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ PanelToplevel *toplevel;
+
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
+
+ toplevel = PANEL_TOPLEVEL (widget);
+
+ if (toplevel->priv->auto_hide && event->detail != GDK_NOTIFY_INFERIOR)
+ panel_toplevel_queue_auto_hide (toplevel);
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->leave_notify_event)
+ return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->leave_notify_event (widget, event);
+
+ return FALSE;
+}
+
+static gboolean
+panel_toplevel_focus_in_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ PanelToplevel *toplevel = PANEL_TOPLEVEL (widget);
+
+ if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
+ panel_toplevel_unhide (toplevel);
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_in_event)
+ return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_in_event (widget, event);
+
+ return FALSE;
+}
+
+static gboolean
+panel_toplevel_focus_out_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ PanelToplevel *toplevel = PANEL_TOPLEVEL (widget);
+
+ /* It appears that sometimes we don't get a leave notify event,
+ but just a focus in/out, so queue the autohide in that case.
+ If the pointer is inside the panel then obviously we won't hide */
+ if (toplevel->priv->auto_hide)
+ panel_toplevel_queue_auto_hide (toplevel);
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_out_event)
+ return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_out_event (widget, event);
+
+ return FALSE;
+}
+
+static void
+panel_toplevel_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ panel_toplevel_update_hide_buttons (PANEL_TOPLEVEL (widget));
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->style_set)
+ GTK_WIDGET_CLASS (panel_toplevel_parent_class)->style_set (widget, previous_style);
+}
+
+static void
+panel_toplevel_drag_threshold_changed (PanelToplevel *toplevel)
+{
+ int threshold;
+
+ threshold = 0;
+ g_object_get (G_OBJECT (toplevel->priv->gtk_settings),
+ "gtk-dnd-drag-threshold", &threshold,
+ NULL);
+
+ if (threshold)
+ toplevel->priv->snap_tolerance = threshold * SNAP_TOLERANCE_FACTOR;
+}
+
+static void
+panel_toplevel_update_gtk_settings (PanelToplevel *toplevel)
+{
+ if (toplevel->priv->gtk_settings)
+ g_signal_handlers_disconnect_by_func (toplevel->priv->gtk_settings,
+ G_CALLBACK (panel_toplevel_drag_threshold_changed),
+ toplevel);
+
+ toplevel->priv->gtk_settings = gtk_widget_get_settings (GTK_WIDGET (toplevel->priv->panel_widget));
+
+ g_signal_connect_swapped (G_OBJECT (toplevel->priv->gtk_settings),
+ "notify::gtk-dnd-drag-threshold",
+ G_CALLBACK (panel_toplevel_drag_threshold_changed),
+ toplevel);
+
+ panel_toplevel_drag_threshold_changed (toplevel);
+}
+
+static void
+panel_toplevel_screen_changed (GtkWidget *widget,
+ GdkScreen *previous_screen)
+{
+ panel_toplevel_update_gtk_settings (PANEL_TOPLEVEL (widget));
+
+ if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->screen_changed)
+ GTK_WIDGET_CLASS (panel_toplevel_parent_class)->screen_changed (widget, previous_screen);
+
+ gtk_widget_queue_resize (widget);
+}
+
+static void
+panel_toplevel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelToplevel *toplevel;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (object));
+
+ toplevel = PANEL_TOPLEVEL (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ panel_toplevel_set_name (toplevel, g_value_get_string (value));
+ break;
+ case PROP_EXPAND:
+ panel_toplevel_set_expand (toplevel, g_value_get_boolean (value));
+ break;
+ case PROP_ORIENTATION:
+ panel_toplevel_set_orientation (toplevel, g_value_get_enum (value));
+ break;
+ case PROP_SIZE:
+ panel_toplevel_set_size (toplevel, g_value_get_int (value));
+ break;
+ case PROP_X:
+ panel_toplevel_set_x (toplevel,
+ g_value_get_int (value),
+ toplevel->priv->x_right,
+ toplevel->priv->x_centered);
+ break;
+ case PROP_X_RIGHT:
+ panel_toplevel_set_x (toplevel,
+ toplevel->priv->x,
+ g_value_get_int (value),
+ toplevel->priv->x_centered);
+ break;
+ case PROP_X_CENTERED:
+ panel_toplevel_set_x (toplevel,
+ toplevel->priv->x,
+ toplevel->priv->x_right,
+ g_value_get_boolean (value));
+ break;
+ case PROP_Y:
+ panel_toplevel_set_y (toplevel,
+ g_value_get_int (value),
+ toplevel->priv->y_bottom,
+ toplevel->priv->y_centered);
+ break;
+ case PROP_Y_BOTTOM:
+ panel_toplevel_set_y (toplevel,
+ toplevel->priv->y,
+ g_value_get_int (value),
+ toplevel->priv->y_centered);
+ break;
+ case PROP_Y_CENTERED:
+ panel_toplevel_set_y (toplevel,
+ toplevel->priv->y,
+ toplevel->priv->y_bottom,
+ g_value_get_boolean (value));
+ break;
+ case PROP_MONITOR:
+ panel_toplevel_set_monitor (toplevel, g_value_get_int (value));
+ break;
+ case PROP_AUTOHIDE:
+ panel_toplevel_set_auto_hide (toplevel, g_value_get_boolean (value));
+ break;
+ case PROP_HIDE_DELAY:
+ panel_toplevel_set_hide_delay (toplevel, g_value_get_int (value));
+ break;
+ case PROP_UNHIDE_DELAY:
+ panel_toplevel_set_unhide_delay (toplevel, g_value_get_int (value));
+ break;
+ case PROP_AUTOHIDE_SIZE:
+ panel_toplevel_set_auto_hide_size (toplevel, g_value_get_int (value));
+ break;
+ case PROP_ANIMATE:
+ panel_toplevel_set_animate (toplevel, g_value_get_boolean (value));
+ break;
+ case PROP_ANIMATION_SPEED:
+ panel_toplevel_set_animation_speed (toplevel, g_value_get_enum (value));
+ break;
+ case PROP_BUTTONS_ENABLED:
+ panel_toplevel_set_enable_buttons (toplevel, g_value_get_boolean (value));
+ break;
+ case PROP_ARROWS_ENABLED:
+ panel_toplevel_set_enable_arrows (toplevel, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_toplevel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelToplevel *toplevel;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (object));
+
+ toplevel = PANEL_TOPLEVEL (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, panel_toplevel_get_name (toplevel));
+ break;
+ case PROP_EXPAND:
+ g_value_set_boolean (value, toplevel->priv->expand);
+ break;
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, toplevel->priv->orientation);
+ break;
+ case PROP_SIZE:
+ g_value_set_int (value, toplevel->priv->size);
+ break;
+ case PROP_X:
+ g_value_set_int (value, toplevel->priv->x);
+ break;
+ case PROP_X_RIGHT:
+ g_value_set_int (value, toplevel->priv->x_right);
+ break;
+ case PROP_X_CENTERED:
+ g_value_set_boolean (value, toplevel->priv->x_centered);
+ break;
+ case PROP_Y:
+ g_value_set_int (value, toplevel->priv->y);
+ break;
+ case PROP_Y_BOTTOM:
+ g_value_set_int (value, toplevel->priv->y_bottom);
+ break;
+ case PROP_Y_CENTERED:
+ g_value_set_boolean (value, toplevel->priv->y_centered);
+ break;
+ case PROP_MONITOR:
+ g_value_set_int (value, toplevel->priv->monitor);
+ break;
+ case PROP_AUTOHIDE:
+ g_value_set_boolean (value, toplevel->priv->auto_hide);
+ break;
+ case PROP_HIDE_DELAY:
+ g_value_set_int (value, toplevel->priv->hide_delay);
+ break;
+ case PROP_UNHIDE_DELAY:
+ g_value_set_int (value, toplevel->priv->unhide_delay);
+ break;
+ case PROP_AUTOHIDE_SIZE:
+ g_value_set_int (value, toplevel->priv->auto_hide_size);
+ break;
+ case PROP_ANIMATE:
+ g_value_set_boolean (value, toplevel->priv->animate);
+ break;
+ case PROP_ANIMATION_SPEED:
+ g_value_set_enum (value, toplevel->priv->animation_speed);
+ break;
+ case PROP_BUTTONS_ENABLED:
+ g_value_set_boolean (value, toplevel->priv->buttons_enabled);
+ break;
+ case PROP_ARROWS_ENABLED:
+ g_value_set_boolean (value, toplevel->priv->arrows_enabled);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_toplevel_finalize (GObject *object)
+{
+ PanelToplevel *toplevel = (PanelToplevel *) object;
+
+ panel_struts_unregister_strut (toplevel);
+
+ toplevel_list = g_slist_remove (toplevel_list, toplevel);
+
+ if (toplevel->priv->gtk_settings) {
+ g_signal_handlers_disconnect_by_func (toplevel->priv->gtk_settings,
+ G_CALLBACK (panel_toplevel_drag_threshold_changed),
+ toplevel);
+ toplevel->priv->gtk_settings = NULL;
+ }
+
+ if (toplevel->priv->attached) {
+ panel_toplevel_disconnect_attached (toplevel);
+
+ toplevel->priv->attached = FALSE;
+
+ toplevel->priv->attach_toplevel = NULL;
+ toplevel->priv->attach_widget = NULL;
+ }
+
+ if (toplevel->priv->description)
+ g_free (toplevel->priv->description);
+ toplevel->priv->description = NULL;
+
+ if (toplevel->priv->name)
+ g_free (toplevel->priv->name);
+ toplevel->priv->name = NULL;
+
+ G_OBJECT_CLASS (panel_toplevel_parent_class)->finalize (object);
+}
+
+static void
+panel_toplevel_class_init (PanelToplevelClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkObjectClass *gtkobject_class = (GtkObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+ GtkContainerClass *container_class = (GtkContainerClass *) klass;
+ GtkBindingSet *binding_set;
+
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gobject_class->set_property = panel_toplevel_set_property;
+ gobject_class->get_property = panel_toplevel_get_property;
+ gobject_class->finalize = panel_toplevel_finalize;
+
+ gtkobject_class->destroy = panel_toplevel_destroy;
+
+ widget_class->realize = panel_toplevel_realize;
+ widget_class->unrealize = panel_toplevel_unrealize;
+ widget_class->size_request = panel_toplevel_size_request;
+ widget_class->size_allocate = panel_toplevel_size_allocate;
+ widget_class->expose_event = panel_toplevel_expose;
+ widget_class->button_press_event = panel_toplevel_button_press_event;
+ widget_class->button_release_event = panel_toplevel_button_release_event;
+ widget_class->key_press_event = panel_toplevel_key_press_event;
+ widget_class->motion_notify_event = panel_toplevel_motion_notify_event;
+ widget_class->enter_notify_event = panel_toplevel_enter_notify_event;
+ widget_class->leave_notify_event = panel_toplevel_leave_notify_event;
+ widget_class->screen_changed = panel_toplevel_screen_changed;
+ widget_class->focus_in_event = panel_toplevel_focus_in_event;
+ widget_class->focus_out_event = panel_toplevel_focus_out_event;
+ widget_class->style_set = panel_toplevel_style_set;
+
+ container_class->check_resize = panel_toplevel_check_resize;
+
+ klass->hiding = NULL;
+ klass->unhiding = NULL;
+ klass->popup_panel_menu = panel_toplevel_popup_panel_menu;
+ klass->toggle_expand = panel_toplevel_toggle_expand;
+ klass->expand = panel_toplevel_expand;
+ klass->unexpand = panel_toplevel_unexpand;
+ klass->toggle_hidden = panel_toplevel_toggle_hidden;
+ klass->begin_move = panel_toplevel_begin_move;
+ klass->begin_resize = panel_toplevel_begin_resize;
+
+ g_type_class_add_private (klass, sizeof (PanelToplevelPrivate));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_NAME,
+ g_param_spec_string (
+ "name",
+ "Name",
+ "The name of this panel",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_EXPAND,
+ g_param_spec_boolean (
+ "expand",
+ "Expand",
+ "Expand to take up the full monitor width/height",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum (
+ "orientation",
+ "Orientation",
+ "The orientation of the panel",
+ PANEL_TYPE_ORIENTATION,
+ PANEL_ORIENTATION_TOP,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_SIZE,
+ g_param_spec_int (
+ "size",
+ "Size",
+ "The height (or width when vertical) of the panel",
+ 0,
+ G_MAXINT,
+ DEFAULT_SIZE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_X,
+ g_param_spec_int (
+ "x",
+ "X position",
+ "The X position of the panel",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_X_RIGHT,
+ g_param_spec_int (
+ "x-right",
+ "X position, from the right",
+ "The X position of the panel, starting from the right of the screen",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_X_CENTERED,
+ g_param_spec_boolean (
+ "x-centered",
+ "X centered",
+ "The x co-ordinate is relative to center screen",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_Y,
+ g_param_spec_int (
+ "y",
+ "Y position",
+ "The Y position of the panel",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_Y_BOTTOM,
+ g_param_spec_int (
+ "y_bottom",
+ "Y position, from the bottom",
+ "The Y position of the panel, starting from the bottom of the screen",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_Y_CENTERED,
+ g_param_spec_boolean (
+ "y-centered",
+ "Y centered",
+ "The y co-ordinate is relative to center screen",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_MONITOR,
+ g_param_spec_int (
+ "monitor",
+ "Xinerama monitor",
+ "The monitor (in terms of Xinerama) which the panel is on",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_AUTOHIDE,
+ g_param_spec_boolean (
+ "auto-hide",
+ "Auto hide",
+ "Automatically hide the panel when the mouse leaves the panel",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_HIDE_DELAY,
+ g_param_spec_int (
+ "hide-delay",
+ "Hide delay",
+ "The number of milliseconds to delay before automatically hiding",
+ 0,
+ G_MAXINT,
+ DEFAULT_HIDE_DELAY,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_UNHIDE_DELAY,
+ g_param_spec_int (
+ "unhide-delay",
+ "Un-hide delay",
+ "The number of milliseconds to delay before automatically un-hiding",
+ 0,
+ G_MAXINT,
+ DEFAULT_UNHIDE_DELAY,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_AUTOHIDE_SIZE,
+ g_param_spec_int (
+ "auto-hide-size",
+ "Auto-hide size",
+ "The number of pixels visible when the panel has been automatically hidden",
+ 1,
+ G_MAXINT,
+ DEFAULT_AUTO_HIDE_SIZE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ANIMATE,
+ g_param_spec_boolean (
+ "animate",
+ "Animate",
+ "Enable hiding/showing animations",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ANIMATION_SPEED,
+ g_param_spec_enum (
+ "animation-speed",
+ "Animation Speed",
+ "The speed at which to animate panel hiding/showing",
+ PANEL_TYPE_ANIMATION_SPEED,
+ PANEL_ANIMATION_MEDIUM,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_BUTTONS_ENABLED,
+ g_param_spec_boolean (
+ "buttons-enabled",
+ "Buttons Enabled",
+ "Enable hide/show buttons",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ARROWS_ENABLED,
+ g_param_spec_boolean (
+ "arrows-enabled",
+ "Arrows Enabled",
+ "Enable arrows on hide/show buttons",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ gtk_widget_class_install_style_property (
+ widget_class,
+ g_param_spec_int (
+ "arrow-size",
+ "Arrow Size",
+ "The size of the arrows on the hide/show buttons",
+ 0,
+ G_MAXINT,
+ DEFAULT_ARROW_SIZE,
+ G_PARAM_READABLE));
+
+ toplevel_signals [HIDE_SIGNAL] =
+ g_signal_new ("hiding",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, hiding),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ toplevel_signals [UNHIDE_SIGNAL] =
+ g_signal_new ("unhiding",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, unhiding),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ toplevel_signals [POPUP_PANEL_MENU_SIGNAL] =
+ g_signal_new ("popup-panel-menu",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, popup_panel_menu),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ toplevel_signals [TOGGLE_EXPAND_SIGNAL] =
+ g_signal_new ("toggle-expand",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, toggle_expand),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ toplevel_signals [EXPAND_SIGNAL] =
+ g_signal_new ("expand",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, expand),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ toplevel_signals [UNEXPAND_SIGNAL] =
+ g_signal_new ("unexpand",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, unexpand),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ toplevel_signals [TOGGLE_HIDDEN_SIGNAL] =
+ g_signal_new ("toggle-hidden",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, toggle_hidden),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ toplevel_signals [BEGIN_MOVE_SIGNAL] =
+ g_signal_new ("begin-move",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, begin_move),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ toplevel_signals [BEGIN_RESIZE_SIGNAL] =
+ g_signal_new ("begin-resize",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelToplevelClass, begin_resize),
+ NULL,
+ NULL,
+ panel_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN,
+ 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_CONTROL_MASK,
+ "popup_panel_menu", 0);
+
+ panel_bindings_set_entries (binding_set);
+}
+
+static void
+panel_toplevel_setup_widgets (PanelToplevel *toplevel)
+{
+ GtkWidget* container;
+
+ toplevel->priv->table = gtk_table_new(3, 3, FALSE);
+
+ toplevel->priv->hide_button_top = panel_toplevel_add_hide_button(toplevel, GTK_ARROW_UP, 1, 2, 0, 1);
+
+ toplevel->priv->hide_button_bottom = panel_toplevel_add_hide_button(toplevel, GTK_ARROW_DOWN, 1, 2, 2, 3);
+
+ toplevel->priv->hide_button_left = panel_toplevel_add_hide_button(toplevel, GTK_ARROW_LEFT, 0, 1, 1, 2);
+
+ toplevel->priv->hide_button_right = panel_toplevel_add_hide_button(toplevel, GTK_ARROW_RIGHT, 2, 3, 1, 2);
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ {
+ gtk_widget_show(toplevel->priv->hide_button_left);
+ gtk_widget_show(toplevel->priv->hide_button_right);
+ }
+ else
+ {
+ gtk_widget_show(toplevel->priv->hide_button_top);
+ gtk_widget_show(toplevel->priv->hide_button_bottom);
+ }
+
+ toplevel->priv->inner_frame = g_object_new(PANEL_TYPE_FRAME, NULL);
+
+ gtk_table_attach (GTK_TABLE (toplevel->priv->table),
+ GTK_WIDGET (toplevel->priv->inner_frame),
+ 1, 2,
+ 1, 2,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+ 0, 0);
+ gtk_widget_show (GTK_WIDGET (toplevel->priv->inner_frame));
+
+ container = panel_widget_new (toplevel,
+ !toplevel->priv->expand,
+ toplevel->priv->orientation & PANEL_HORIZONTAL_MASK ?
+ GTK_ORIENTATION_HORIZONTAL :
+ GTK_ORIENTATION_VERTICAL,
+ toplevel->priv->size);
+
+ toplevel->priv->panel_widget = PANEL_WIDGET(container);
+
+ gtk_container_add(GTK_CONTAINER(toplevel->priv->inner_frame), container);
+ gtk_widget_show(container);
+
+ gtk_container_add(GTK_CONTAINER(toplevel), toplevel->priv->table);
+ gtk_widget_show(toplevel->priv->table);
+}
+
+static void
+panel_toplevel_init (PanelToplevel *toplevel)
+{
+ int i;
+
+ /* This is a hack for the default resize grip on Ubuntu.
+ * Once again, thank you Ubuntu.
+ *
+ * We need to add a --enable-ubuntu for this.
+ */
+ #ifdef UBUNTU
+ gtk_window_set_has_resize_grip(&toplevel->window_instance, FALSE);
+ #endif
+ toplevel->priv = PANEL_TOPLEVEL_GET_PRIVATE (toplevel);
+
+ toplevel->priv->expand = TRUE;
+ toplevel->priv->orientation = PANEL_ORIENTATION_BOTTOM;
+ toplevel->priv->size = DEFAULT_SIZE;
+ toplevel->priv->x = 0;
+ toplevel->priv->y = 0;
+ toplevel->priv->x_right = -1;
+ toplevel->priv->y_bottom = -1;
+ toplevel->priv->monitor = 0;
+ toplevel->priv->configured_monitor = -1;
+ toplevel->priv->hide_delay = DEFAULT_HIDE_DELAY;
+ toplevel->priv->unhide_delay = DEFAULT_UNHIDE_DELAY;
+ toplevel->priv->auto_hide_size = DEFAULT_AUTO_HIDE_SIZE;
+ toplevel->priv->animation_speed = PANEL_ANIMATION_FAST;
+
+ toplevel->priv->snap_tolerance = DEFAULT_DND_THRESHOLD * SNAP_TOLERANCE_FACTOR;
+ toplevel->priv->gtk_settings = NULL;
+
+ toplevel->priv->state = PANEL_STATE_NORMAL;
+
+ toplevel->priv->name = NULL;
+ toplevel->priv->description = NULL;
+
+ toplevel->priv->hide_timeout = 0;
+ toplevel->priv->unhide_timeout = 0;
+
+ toplevel->priv->geometry.x = -1;
+ toplevel->priv->geometry.y = -1;
+ toplevel->priv->geometry.width = -1;
+ toplevel->priv->geometry.height = -1;
+
+ toplevel->priv->original_width = -1;
+ toplevel->priv->original_height = -1;
+
+ toplevel->priv->grab_op = PANEL_GRAB_OP_NONE;
+
+ toplevel->priv->drag_offset_x = 0;
+ toplevel->priv->drag_offset_y = 0;
+
+ toplevel->priv->animation_end_x = 0;
+ toplevel->priv->animation_end_y = 0;
+ toplevel->priv->animation_end_width = 0;
+ toplevel->priv->animation_end_height = 0;
+ toplevel->priv->animation_start_time.tv_sec = 0;
+ toplevel->priv->animation_start_time.tv_usec = 0;
+ toplevel->priv->animation_end_time.tv_sec = 0;
+ toplevel->priv->animation_end_time.tv_usec = 0;
+ toplevel->priv->animation_timeout = 0;
+
+ toplevel->priv->panel_widget = NULL;
+ toplevel->priv->inner_frame = NULL;
+ toplevel->priv->table = NULL;
+ toplevel->priv->hide_button_top = NULL;
+ toplevel->priv->hide_button_bottom = NULL;
+ toplevel->priv->hide_button_left = NULL;
+ toplevel->priv->hide_button_right = NULL;
+
+ toplevel->priv->attach_toplevel = NULL;
+ toplevel->priv->attach_widget = NULL;
+ toplevel->priv->n_autohide_disablers = 0;
+
+ for (i = 0; i < N_ATTACH_TOPLEVEL_SIGNALS; i++)
+ toplevel->priv->attach_toplevel_signals [i] = 0;
+ for (i = 0; i < N_ATTACH_WIDGET_SIGNALS; i++)
+ toplevel->priv->attach_widget_signals [i] = 0;
+
+ toplevel->priv->auto_hide = FALSE;
+ toplevel->priv->buttons_enabled = TRUE;
+ toplevel->priv->arrows_enabled = TRUE;
+ toplevel->priv->x_centered = FALSE;
+ toplevel->priv->y_centered = FALSE;
+ toplevel->priv->animating = FALSE;
+ toplevel->priv->grab_is_keyboard = FALSE;
+ toplevel->priv->position_centered = FALSE;
+ toplevel->priv->attached = FALSE;
+ toplevel->priv->attach_hidden = FALSE;
+ toplevel->priv->updated_geometry_initial = FALSE;
+ toplevel->priv->initial_animation_done = FALSE;
+
+ gtk_widget_add_events (GTK_WIDGET (toplevel),
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ panel_toplevel_setup_widgets (toplevel);
+ panel_toplevel_update_description (toplevel);
+ panel_toplevel_update_gtk_settings (toplevel);
+
+ toplevel_list = g_slist_prepend (toplevel_list, toplevel);
+
+ /* Prevent the window from being deleted via Alt+F4 by accident. This
+ * happens with "alternative" window managers such as Sawfish or XFWM4.
+ */
+ g_signal_connect(GTK_WIDGET(toplevel), "delete-event", G_CALLBACK(gtk_true), NULL);
+}
+
+PanelWidget *
+panel_toplevel_get_panel_widget (PanelToplevel *toplevel)
+{
+
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
+
+ return toplevel->priv->panel_widget;
+}
+
+static void
+panel_toplevel_update_name (PanelToplevel *toplevel)
+{
+ char *title;
+
+ g_assert (toplevel->priv->description != NULL);
+
+ title = toplevel->priv->name ? toplevel->priv->name : toplevel->priv->description;
+
+ gtk_window_set_title (GTK_WINDOW (toplevel), title);
+
+ panel_a11y_set_atk_name_desc (
+ GTK_WIDGET (toplevel->priv->panel_widget),
+ title, toplevel->priv->description);
+}
+
+void
+panel_toplevel_set_name (PanelToplevel *toplevel,
+ const char *name)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (!toplevel->priv->name && (!name || !name [0]))
+ return;
+
+ if (toplevel->priv->name && name && name [0] &&
+ !strcmp (toplevel->priv->name, name))
+ return;
+
+ if (toplevel->priv->name)
+ g_free (toplevel->priv->name);
+ toplevel->priv->name = NULL;
+
+ if (name && name [0])
+ toplevel->priv->name = g_strdup (name);
+
+ panel_toplevel_update_name (toplevel);
+
+ g_object_notify (G_OBJECT (toplevel), "name");
+}
+
+const char* panel_toplevel_get_name(PanelToplevel* toplevel)
+{
+ g_return_val_if_fail(PANEL_IS_TOPLEVEL(toplevel), NULL);
+
+ return toplevel->priv->name;
+}
+
+const char* panel_toplevel_get_description(PanelToplevel* toplevel)
+{
+ g_return_val_if_fail(PANEL_IS_TOPLEVEL(toplevel), NULL);
+
+ return toplevel->priv->description;
+}
+
+void
+panel_toplevel_set_expand (PanelToplevel *toplevel,
+ gboolean expand)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ expand = expand != FALSE;
+
+ if (toplevel->priv->expand == expand)
+ return;
+
+ toplevel->priv->expand = expand;
+
+ if (!toplevel->priv->expand) {
+ switch (toplevel->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ panel_toplevel_set_x (toplevel, 0, -1, TRUE);
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ panel_toplevel_set_x (toplevel, 0, 0, TRUE);
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ panel_toplevel_set_y (toplevel, 0, -1, TRUE);
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ panel_toplevel_set_y (toplevel, 0, 0, TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ panel_widget_set_packed (toplevel->priv->panel_widget, !toplevel->priv->expand);
+
+ g_object_notify (G_OBJECT (toplevel), "expand");
+}
+
+gboolean
+panel_toplevel_get_expand (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), TRUE);
+
+ return toplevel->priv->expand;
+}
+
+gboolean
+panel_toplevel_get_is_floating (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), TRUE);
+
+ return toplevel->priv->floating;
+}
+
+void
+panel_toplevel_set_orientation (PanelToplevel *toplevel,
+ PanelOrientation orientation)
+{
+ gboolean rotate;
+ int monitor_width;
+ int monitor_height;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->orientation == orientation)
+ return;
+
+ g_object_freeze_notify (G_OBJECT (toplevel));
+
+ panel_toplevel_get_monitor_geometry (
+ toplevel, NULL, NULL, &monitor_width, &monitor_height);
+
+ /* Un-snap from center if no longer along screen edge */
+ if (toplevel->priv->x_centered &&
+ (orientation & PANEL_VERTICAL_MASK)) {
+ toplevel->priv->x_centered = FALSE;
+ toplevel->priv->x = (monitor_width - toplevel->priv->geometry.width) / 2;
+ g_object_notify (G_OBJECT (toplevel), "x");
+ g_object_notify (G_OBJECT (toplevel), "x-centered");
+
+ if (toplevel->priv->x_right != -1) {
+ toplevel->priv->x_right = -1;
+ g_object_notify (G_OBJECT (toplevel), "x-right");
+ }
+ }
+
+ if (toplevel->priv->y_centered &&
+ (orientation & PANEL_HORIZONTAL_MASK)) {
+ toplevel->priv->y_centered = FALSE;
+ toplevel->priv->y = (monitor_height - toplevel->priv->geometry.height) / 2;
+ g_object_notify (G_OBJECT (toplevel), "y");
+ g_object_notify (G_OBJECT (toplevel), "y-centered");
+
+ if (toplevel->priv->y_bottom != -1) {
+ toplevel->priv->y_bottom = -1;
+ g_object_notify (G_OBJECT (toplevel), "y-bottom");
+ }
+ }
+
+ rotate = FALSE;
+ if ((orientation & PANEL_HORIZONTAL_MASK) &&
+ (toplevel->priv->orientation & PANEL_VERTICAL_MASK))
+ rotate = TRUE;
+ else if ((orientation & PANEL_VERTICAL_MASK) &&
+ (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK))
+ rotate = TRUE;
+
+ /* rotate around the center */
+ if (rotate && !toplevel->priv->position_centered && !toplevel->priv->expand &&
+ toplevel->priv->updated_geometry_initial) {
+ toplevel->priv->position_centered = TRUE;
+
+ /* x, y temporary refer to the panel center, so we don't care
+ * about x_right, y_bottom. Those will get updated in
+ * panel_toplevel_update_position() accordingly. */
+ if (!toplevel->priv->x_centered) {
+ toplevel->priv->x += toplevel->priv->geometry.width / 2;
+ g_object_notify (G_OBJECT (toplevel), "x");
+ }
+
+ if (!toplevel->priv->y_centered) {
+ toplevel->priv->y += toplevel->priv->geometry.height / 2;
+ g_object_notify (G_OBJECT (toplevel), "y");
+ }
+
+ }
+
+ toplevel->priv->orientation = orientation;
+
+ panel_toplevel_update_hide_buttons (toplevel);
+
+ panel_widget_set_orientation (
+ toplevel->priv->panel_widget,
+ toplevel->priv->orientation & PANEL_HORIZONTAL_MASK ?
+ GTK_ORIENTATION_HORIZONTAL :
+ GTK_ORIENTATION_VERTICAL);
+
+ switch (toplevel->priv->state) {
+ case PANEL_STATE_HIDDEN_UP:
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ toplevel->priv->state = PANEL_STATE_HIDDEN_LEFT;
+ break;
+ case PANEL_STATE_HIDDEN_DOWN:
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ toplevel->priv->state = PANEL_STATE_HIDDEN_RIGHT;
+ break;
+ case PANEL_STATE_HIDDEN_LEFT:
+ if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
+ toplevel->priv->state = PANEL_STATE_HIDDEN_UP;
+ break;
+ case PANEL_STATE_HIDDEN_RIGHT:
+ if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
+ toplevel->priv->state = PANEL_STATE_HIDDEN_DOWN;
+ break;
+ default:
+ break;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ g_object_notify (G_OBJECT (toplevel), "orientation");
+
+ g_object_thaw_notify (G_OBJECT (toplevel));
+}
+
+PanelOrientation
+panel_toplevel_get_orientation (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), GTK_ORIENTATION_HORIZONTAL);
+
+ return toplevel->priv->orientation;
+}
+
+void
+panel_toplevel_set_size (PanelToplevel *toplevel,
+ int size)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+ g_return_if_fail (size >= 0);
+
+ if (toplevel->priv->size == size)
+ return;
+
+ toplevel->priv->size = size;
+
+ panel_widget_set_size (toplevel->priv->panel_widget, toplevel->priv->size);
+
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ g_object_notify (G_OBJECT (toplevel), "size");
+}
+
+int
+panel_toplevel_get_size (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), DEFAULT_SIZE);
+
+ return toplevel->priv->size;
+}
+
+void
+panel_toplevel_set_auto_hide_size (PanelToplevel *toplevel,
+ int auto_hide_size)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->auto_hide_size == auto_hide_size)
+ return;
+
+ toplevel->priv->auto_hide_size = auto_hide_size;
+
+ if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN) {
+ if (panel_toplevel_update_struts (toplevel, FALSE)) {
+ if (toplevel->priv->animate) {
+ panel_toplevel_unhide (toplevel);
+ panel_toplevel_hide (toplevel, TRUE, -1);
+ } else
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+ }
+ }
+
+ g_object_notify (G_OBJECT (toplevel), "auto-hide-size");
+}
+
+int
+panel_toplevel_get_auto_hide_size (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), DEFAULT_AUTO_HIDE_SIZE);
+
+ return toplevel->priv->auto_hide_size;
+}
+
+void
+panel_toplevel_set_x (PanelToplevel *toplevel,
+ int x,
+ int x_right,
+ gboolean x_centered)
+{
+ gboolean changed = FALSE;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ x_centered = x_centered != FALSE;
+
+ g_object_freeze_notify (G_OBJECT (toplevel));
+
+ if (toplevel->priv->x != x) {
+ toplevel->priv->x = x;
+ changed = TRUE;
+ g_object_notify (G_OBJECT (toplevel), "x");
+ }
+
+ if (toplevel->priv->x_right != x_right) {
+ toplevel->priv->x_right = x_right;
+ changed = TRUE;
+ g_object_notify (G_OBJECT (toplevel), "x-right");
+ }
+
+ if (toplevel->priv->x_centered != x_centered) {
+ toplevel->priv->x_centered = x_centered;
+ changed = TRUE;
+ g_object_notify (G_OBJECT (toplevel), "x-centered");
+ }
+
+ if (changed)
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ g_object_thaw_notify (G_OBJECT (toplevel));
+}
+
+void
+panel_toplevel_set_y (PanelToplevel *toplevel,
+ int y,
+ int y_bottom,
+ gboolean y_centered)
+{
+ gboolean changed = FALSE;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ y_centered = y_centered != FALSE;
+
+ g_object_freeze_notify (G_OBJECT (toplevel));
+
+ if (toplevel->priv->y != y) {
+ toplevel->priv->y = y;
+ changed = TRUE;
+ g_object_notify (G_OBJECT (toplevel), "y");
+ }
+
+ if (toplevel->priv->y_bottom != y_bottom) {
+ toplevel->priv->y_bottom = y_bottom;
+ changed = TRUE;
+ g_object_notify (G_OBJECT (toplevel), "y-bottom");
+ }
+
+ if (toplevel->priv->y_centered != y_centered) {
+ toplevel->priv->y_centered = y_centered;
+ changed = TRUE;
+ g_object_notify (G_OBJECT (toplevel), "y-centered");
+ }
+
+ if (changed)
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ g_object_thaw_notify (G_OBJECT (toplevel));
+}
+
+void
+panel_toplevel_get_position (PanelToplevel *toplevel,
+ int *x,
+ int *x_right,
+ int *y,
+ int *y_bottom)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (x)
+ *x = toplevel->priv->x;
+
+ if (y)
+ *y = toplevel->priv->y;
+
+ if (x_right)
+ *x_right = toplevel->priv->x_right;
+
+ if (y_bottom)
+ *y_bottom = toplevel->priv->y_bottom;
+}
+
+gboolean
+panel_toplevel_get_x_centered (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->x_centered;
+}
+
+gboolean
+panel_toplevel_get_y_centered (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->y_centered;
+}
+
+/**
+ * panel_toplevel_set_monitor_internal:
+ *
+ * Sets the monitor of the toplevel, but only the internal state. We need to
+ * make the difference between the internal state and the configuration of the
+ * user because internal constraints might affect the monitor of the toplevel.
+ *
+ * panel_toplevel_set_monitor_internal() won't update the configuration of the
+ * user.
+ **/
+static void
+panel_toplevel_set_monitor_internal (PanelToplevel *toplevel,
+ int monitor,
+ gboolean force_resize)
+{
+ if (toplevel->priv->monitor == monitor)
+ return;
+
+ toplevel->priv->monitor = monitor;
+
+ if (force_resize)
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+}
+
+/**
+ * panel_toplevel_update_monitor:
+ *
+ * Moves the toplevel to its configured monitor or the first one, if needed.
+ * This generally happens when the configured monitor was non-existing before,
+ * and it appeared at runtime, or if it was existing and disappeared.
+ *
+ * This must only be called at the beginning of the size request of the
+ * toplevel because it doesn't queue a size request.
+ **/
+static void
+panel_toplevel_update_monitor (PanelToplevel *toplevel)
+{
+ GdkScreen *screen;
+
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+
+ /* If we were not using the configured monitor, can we use it now? */
+ if ((toplevel->priv->configured_monitor != -1) &&
+ (toplevel->priv->configured_monitor != toplevel->priv->monitor) &&
+ toplevel->priv->configured_monitor < panel_multiscreen_monitors (screen)) {
+ panel_toplevel_set_monitor_internal (toplevel,
+ toplevel->priv->configured_monitor,
+ FALSE);
+
+ /* else, can we still use the monitor we were using? */
+ } else if (toplevel->priv->monitor >= panel_multiscreen_monitors (screen)) {
+ panel_toplevel_set_monitor_internal (toplevel,
+ 0,
+ FALSE);
+ }
+}
+
+void
+panel_toplevel_set_monitor (PanelToplevel *toplevel,
+ int monitor)
+{
+ GdkScreen *screen;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->configured_monitor == monitor)
+ return;
+
+ toplevel->priv->configured_monitor = monitor;
+
+ /* Only use the configured monitor if it's existing. Else, we ignore
+ * the non-existing monitor, and keep the old one. The main use case is
+ * when logging in after having used a multiscreen environment.
+ * We will put the panel on the monitor 0 for this session, and it will
+ * move back to the right monitor next time. */
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+ if (monitor < panel_multiscreen_monitors (screen))
+ panel_toplevel_set_monitor_internal (toplevel, monitor, TRUE);
+
+ g_object_notify (G_OBJECT (toplevel), "monitor");
+}
+
+int
+panel_toplevel_get_monitor (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), -1);
+
+ return toplevel->priv->monitor;
+}
+
+void
+panel_toplevel_set_auto_hide (PanelToplevel *toplevel,
+ gboolean auto_hide)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ auto_hide = auto_hide != FALSE;
+
+ if (toplevel->priv->auto_hide == auto_hide)
+ return;
+
+ toplevel->priv->auto_hide = auto_hide;
+
+ if (toplevel->priv->auto_hide)
+ panel_toplevel_queue_auto_hide (toplevel);
+ else
+ panel_toplevel_queue_auto_unhide (toplevel);
+
+ if (panel_toplevel_update_struts (toplevel, FALSE))
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ g_object_notify (G_OBJECT (toplevel), "auto-hide");
+}
+
+gboolean
+panel_toplevel_get_auto_hide (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->auto_hide;
+}
+
+void
+panel_toplevel_set_hide_delay (PanelToplevel *toplevel,
+ int hide_delay)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->hide_delay == hide_delay)
+ return;
+
+ toplevel->priv->hide_delay = hide_delay;
+
+ g_object_notify (G_OBJECT (toplevel), "hide-delay");
+}
+
+int
+panel_toplevel_get_hide_delay (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), -1);
+
+ return toplevel->priv->hide_delay;
+}
+
+void
+panel_toplevel_set_unhide_delay (PanelToplevel *toplevel,
+ int unhide_delay)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->unhide_delay == unhide_delay)
+ return;
+
+ toplevel->priv->unhide_delay = unhide_delay;
+
+ g_object_notify (G_OBJECT (toplevel), "unhide-delay");
+}
+
+int
+panel_toplevel_get_unhide_delay (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), -1);
+
+ return toplevel->priv->unhide_delay;
+}
+
+void
+panel_toplevel_set_animate (PanelToplevel *toplevel,
+ gboolean animate)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ animate = animate != FALSE;
+
+ if (toplevel->priv->animate == animate)
+ return;
+
+ toplevel->priv->animate = animate;
+
+ g_object_notify (G_OBJECT (toplevel), "animate");
+}
+
+gboolean
+panel_toplevel_get_animate (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->animate;
+}
+
+void
+panel_toplevel_set_animation_speed (PanelToplevel *toplevel,
+ PanelAnimationSpeed animation_speed)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ if (toplevel->priv->animation_speed == animation_speed)
+ return;
+
+ toplevel->priv->animation_speed = animation_speed;
+
+ g_object_notify (G_OBJECT (toplevel), "animation-speed");
+}
+
+PanelAnimationSpeed
+panel_toplevel_get_animation_speed (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), 0);
+
+ return toplevel->priv->animation_speed;
+}
+
+void
+panel_toplevel_set_enable_buttons (PanelToplevel *toplevel,
+ gboolean enable_buttons)
+{
+ enable_buttons = enable_buttons != FALSE;
+
+ if (toplevel->priv->buttons_enabled == enable_buttons)
+ return;
+
+ toplevel->priv->buttons_enabled = enable_buttons;
+
+ panel_toplevel_update_hide_buttons (toplevel);
+
+ g_object_notify (G_OBJECT (toplevel), "buttons-enabled");
+}
+
+gboolean
+panel_toplevel_get_enable_buttons (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->buttons_enabled;
+}
+
+void
+panel_toplevel_set_enable_arrows (PanelToplevel *toplevel,
+ gboolean enable_arrows)
+{
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ enable_arrows = enable_arrows != FALSE;
+
+ if (toplevel->priv->arrows_enabled == enable_arrows)
+ return;
+
+ toplevel->priv->arrows_enabled = enable_arrows;
+
+ panel_toplevel_update_hide_buttons (toplevel);
+
+ g_object_notify (G_OBJECT (toplevel), "arrows-enabled");
+}
+
+gboolean
+panel_toplevel_get_enable_arrows (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ return toplevel->priv->arrows_enabled;
+}
+
+void
+panel_toplevel_rotate (PanelToplevel *toplevel,
+ gboolean clockwise)
+{
+ PanelOrientation orientation;
+
+ /* Relies on PanelOrientation definition:
+ *
+ * typedef enum {
+ * PANEL_ORIENTATION_TOP = 1 << 0,
+ * PANEL_ORIENTATION_RIGHT = 1 << 1,
+ * PANEL_ORIENTATION_BOTTOM = 1 << 2,
+ * PANEL_ORIENTATION_LEFT = 1 << 3
+ * } PanelOrientation;
+ */
+
+ orientation = toplevel->priv->orientation;
+
+ if (clockwise)
+ orientation <<= 1;
+ else
+ orientation >>= 1;
+
+ if (orientation == 0)
+ orientation = PANEL_ORIENTATION_LEFT;
+
+ else if (orientation > PANEL_ORIENTATION_LEFT)
+ orientation = PANEL_ORIENTATION_TOP;
+
+ panel_toplevel_set_orientation (toplevel, orientation);
+}
+
+PanelState
+panel_toplevel_get_state (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), 0);
+
+ return toplevel->priv->state;
+}
+
+gboolean
+panel_toplevel_get_is_hidden (PanelToplevel *toplevel)
+{
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
+
+ if (toplevel->priv->state == PANEL_STATE_HIDDEN_UP ||
+ toplevel->priv->state == PANEL_STATE_HIDDEN_DOWN ||
+ toplevel->priv->state == PANEL_STATE_HIDDEN_LEFT ||
+ toplevel->priv->state == PANEL_STATE_HIDDEN_RIGHT)
+ return TRUE;
+
+ return FALSE;
+}
+
+int
+panel_toplevel_get_minimum_size (PanelToplevel *toplevel)
+{
+ return calculate_minimum_height (GTK_WIDGET (toplevel),
+ toplevel->priv->orientation);
+}
+
+int
+panel_toplevel_get_maximum_size (PanelToplevel *toplevel)
+{
+ int monitor_width, monitor_height;
+
+ panel_toplevel_get_monitor_geometry (toplevel, NULL, NULL,
+ &monitor_width, &monitor_height);
+
+ if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
+ return monitor_height / MAXIMUM_SIZE_SCREEN_RATIO;
+ else
+ return monitor_width / MAXIMUM_SIZE_SCREEN_RATIO;
+}
diff --git a/mate-panel/panel-toplevel.h b/mate-panel/panel-toplevel.h
new file mode 100644
index 00000000..2c08a4aa
--- /dev/null
+++ b/mate-panel/panel-toplevel.h
@@ -0,0 +1,179 @@
+/*
+ * panel-toplevel.h: The panel's toplevel window object.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_TOPLEVEL_H__
+#define __PANEL_TOPLEVEL_H__
+
+#include <gtk/gtk.h>
+
+#include "panel-enums.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We need PanelWidget type but don't want to include
+ the panel-widget.h */
+#ifndef TYPEDEF_PANEL_WIDGET
+typedef struct _PanelWidget PanelWidget;
+#define TYPEDEF_PANEL_WIDGET
+#endif /* TYPEDEF_PANEL_WIDGET */
+
+#define PANEL_TYPE_TOPLEVEL (panel_toplevel_get_type ())
+#define PANEL_TOPLEVEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_TOPLEVEL, PanelToplevel))
+#define PANEL_TOPLEVEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_TOPLEVEL, PanelToplevelClass))
+#define PANEL_IS_TOPLEVEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_TOPLEVEL))
+#define PANEL_IS_TOPLEVEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_TOPLEVEL))
+#define PANEL_TOPLEVEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_TOPLEVEL, PanelToplevelClass))
+
+typedef struct _PanelToplevel PanelToplevel;
+typedef struct _PanelToplevelClass PanelToplevelClass;
+typedef struct _PanelToplevelPrivate PanelToplevelPrivate;
+
+struct _PanelToplevel {
+ GtkWindow window_instance;
+
+ PanelToplevelPrivate *priv;
+};
+
+struct _PanelToplevelClass {
+ GtkWindowClass window_class;
+
+ /* key bindings */
+ gboolean (*popup_panel_menu) (PanelToplevel *toplevel);
+ gboolean (*toggle_expand) (PanelToplevel *toplevel);
+ gboolean (*expand) (PanelToplevel *toplevel);
+ gboolean (*unexpand) (PanelToplevel *toplevel);
+ gboolean (*toggle_hidden) (PanelToplevel *toplevel);
+ gboolean (*begin_move) (PanelToplevel *toplevel);
+ gboolean (*begin_resize) (PanelToplevel *toplevel);
+
+ /* signals */
+ void (*hiding) (PanelToplevel *toplevel);
+ void (*unhiding) (PanelToplevel *toplevel);
+};
+
+GType panel_toplevel_get_type (void) G_GNUC_CONST;
+
+PanelWidget *panel_toplevel_get_panel_widget (PanelToplevel *toplevel);
+
+void panel_toplevel_set_name (PanelToplevel *toplevel,
+ const char *name);
+const char* panel_toplevel_get_name(PanelToplevel* toplevel);
+const char* panel_toplevel_get_description(PanelToplevel* toplevel);
+void panel_toplevel_set_expand (PanelToplevel *toplevel,
+ gboolean expand);
+gboolean panel_toplevel_get_expand (PanelToplevel *toplevel);
+void panel_toplevel_set_orientation (PanelToplevel *toplevel,
+ PanelOrientation orientation);
+PanelOrientation panel_toplevel_get_orientation (PanelToplevel *toplevel);
+void panel_toplevel_set_size (PanelToplevel *toplevel,
+ int size);
+int panel_toplevel_get_size (PanelToplevel *toplevel);
+void panel_toplevel_set_monitor (PanelToplevel *toplevel,
+ int monitor);
+int panel_toplevel_get_monitor (PanelToplevel *toplevel);
+void panel_toplevel_set_auto_hide_size (PanelToplevel *toplevel,
+ int autohide_size);
+int panel_toplevel_get_auto_hide_size (PanelToplevel *toplevel);
+void panel_toplevel_set_x (PanelToplevel *toplevel,
+ int x,
+ int x_right,
+ gboolean x_centered);
+void panel_toplevel_set_y (PanelToplevel *toplevel,
+ int y,
+ int y_bottom,
+ gboolean y_centered);
+void panel_toplevel_get_position (PanelToplevel *toplevel,
+ int *x,
+ int *x_right,
+ int *y,
+ int *y_bottom);
+gboolean panel_toplevel_get_x_centered (PanelToplevel *toplevel);
+gboolean panel_toplevel_get_y_centered (PanelToplevel *toplevel);
+void panel_toplevel_set_monitor (PanelToplevel *toplevel,
+ int monitor);
+int panel_toplevel_get_monitor (PanelToplevel *toplevel);
+
+void panel_toplevel_rotate (PanelToplevel *toplevel,
+ gboolean clockwise);
+
+void panel_toplevel_attach_to_widget (PanelToplevel *toplevel,
+ PanelToplevel *attach_toplevel,
+ GtkWidget *attach_widget);
+void panel_toplevel_detach (PanelToplevel *toplevel);
+gboolean panel_toplevel_get_is_attached (PanelToplevel *toplevel);
+PanelToplevel *panel_toplevel_get_attach_toplevel (PanelToplevel *toplevel);
+GtkWidget *panel_toplevel_get_attach_widget (PanelToplevel *toplevel);
+
+gboolean panel_toplevel_get_is_floating (PanelToplevel *toplevel);
+
+gboolean panel_toplevel_get_is_hidden (PanelToplevel *toplevel);
+PanelState panel_toplevel_get_state (PanelToplevel *toplevel);
+
+void panel_toplevel_hide (PanelToplevel *toplevel,
+ gboolean auto_hide,
+ GtkDirectionType direction);
+void panel_toplevel_unhide (PanelToplevel *toplevel);
+void panel_toplevel_queue_auto_hide (PanelToplevel *toplevel);
+void panel_toplevel_queue_auto_unhide (PanelToplevel *toplevel);
+void panel_toplevel_queue_initial_unhide (PanelToplevel *toplevel);
+void panel_toplevel_push_autohide_disabler (PanelToplevel *toplevel);
+void panel_toplevel_pop_autohide_disabler (PanelToplevel *toplevel);
+
+void panel_toplevel_set_auto_hide (PanelToplevel *toplevel,
+ gboolean autohide);
+gboolean panel_toplevel_get_auto_hide (PanelToplevel *toplevel);
+void panel_toplevel_set_hide_delay (PanelToplevel *toplevel,
+ int hide_delay);
+int panel_toplevel_get_hide_delay (PanelToplevel *toplevel);
+void panel_toplevel_set_unhide_delay (PanelToplevel *toplevel,
+ int unhide_delay);
+int panel_toplevel_get_unhide_delay (PanelToplevel *toplevel);
+
+void panel_toplevel_set_animate (PanelToplevel *toplevel,
+ gboolean animate);
+gboolean panel_toplevel_get_animate (PanelToplevel *toplevel);
+void panel_toplevel_set_animation_speed (PanelToplevel *toplevel,
+ PanelAnimationSpeed animation_speed);
+PanelAnimationSpeed panel_toplevel_get_animation_speed (PanelToplevel *toplevel);
+
+void panel_toplevel_set_enable_buttons (PanelToplevel *toplevel,
+ gboolean enable_buttons);
+gboolean panel_toplevel_get_enable_buttons (PanelToplevel *toplevel);
+void panel_toplevel_set_enable_arrows (PanelToplevel *toplevel,
+ gboolean enable_arrows);
+gboolean panel_toplevel_get_enable_arrows (PanelToplevel *toplevel);
+void panel_toplevel_update_edges (PanelToplevel *toplevel);
+
+gboolean panel_toplevel_is_last_unattached (PanelToplevel *toplevel);
+int panel_toplevel_get_minimum_size (PanelToplevel *toplevel);
+int panel_toplevel_get_maximum_size (PanelToplevel *toplevel);
+GSList *panel_toplevel_list_toplevels (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_TOPLEVEL_H__ */
diff --git a/mate-panel/panel-toplevel.schemas.in b/mate-panel/panel-toplevel.schemas.in
new file mode 100644
index 00000000..90d3ca3f
--- /dev/null
+++ b/mate-panel/panel-toplevel.schemas.in
@@ -0,0 +1,434 @@
+<?xml version="1.0"?>
+<mateconfschemafile>
+
+ <schemalist>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/name</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Name to identify panel</short>
+ <long>
+ This is a human readable name which you can use to identify
+ a panel. Its main purpose is to serve as the panel's window
+ title which is useful when navigating between panels.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/screen</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>X screen where the panel is displayed</short>
+ <long>
+ With a multi-screen setup, you may have panels on each
+ individual screen. This key identifies the current screen
+ the panel is displayed on.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/monitor</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>Xinerama monitor where the panel is displayed</short>
+ <long>
+ In a Xinerama setup, you may have panels on each individual
+ monitor. This key identifies the current monitor the panel
+ is displayed on.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/expand</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Expand to occupy entire screen width</short>
+ <long>
+ If true, the panel will occupy the entire screen width
+ (height if this is a vertical panel). In this mode the panel
+ can only be placed at a screen edge. If false, the panel
+ will only be large enough to accommodate the applets,
+ launchers and buttons on the panel.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/orientation</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>top</default>
+ <locale name="C">
+ <short>Panel orientation</short>
+ <long>
+ The orientation of the panel. Possible values are "top",
+ "bottom", "left", "right". In expanded mode the key
+ specifies which screen edge the panel is on. In un-expanded
+ mode the difference between "top" and "bottom" is less
+ important - both indicate that this is a horizontal panel -
+ but still give a useful hint as to how some panel objects
+ should behave. For example, on a "top" panel a menu button
+ will pop up its menu below the panel, whereas on a "bottom"
+ panel the menu will be popped up above the panel.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/size</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>24</default>
+ <locale name="C">
+ <short>Panel size</short>
+ <long>
+ The height (width for a vertical panel) of the panel. The
+ panel will determine at runtime a minimum size based on
+ the font size and other indicators. The maximum size is
+ fixed at one quarter of the screen height (or width).
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/x</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>X co-ordinate of panel</short>
+ <long>
+ The location of the panel along the x-axis. This key is
+ only relevant in un-expanded mode. In expanded mode this
+ key is ignored and the panel is placed at the screen edge
+ specified by the orientation key.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/y</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>Y co-ordinate of panel</short>
+ <long>
+ The location of the panel along the y-axis. This key is
+ only relevant in un-expanded mode. In expanded mode this
+ key is ignored and the panel is placed at the screen edge
+ specified by the orientation key.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/x_right</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>X co-ordinate of panel, starting from the right of the screen</short>
+ <long>
+ The location of the panel along the x-axis, starting from the right of
+ the screen. If set to -1, the value is ignored and the value of the x
+ key is used. If the value is greater than 0, then the value of the x
+ key is ignored.
+ This key is only relevant in un-expanded mode. In expanded mode this
+ key is ignored and the panel is placed at the screen edge
+ specified by the orientation key.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/y_bottom</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>Y co-ordinate of panel, starting from the bottom of the screen</short>
+ <long>
+ The location of the panel along the y-axis, starting from the bottom of
+ the screen. If set to -1, the value is ignored and the value of the y
+ key is used. If the value is greater than 0, then the value of the y
+ key is ignored.
+ This key is only relevant in un-expanded mode. In expanded mode this
+ key is ignored and the panel is placed at the screen edge
+ specified by the orientation key.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/x_centered</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Center panel on x-axis</short>
+ <long>
+ If true, the x and x_right keys are ignored and the panel is placed at
+ the center of the x-axis of the screen. If the panel is
+ resized it will remain at that position - i.e. the panel
+ will grow on both sides. If false, the x and x_right keys specify
+ the location of the panel.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/y_centered</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Center panel on y-axis</short>
+ <long>
+ If true, the y and y_bottom keys are ignored and the panel is placed at
+ the center of the y-axis of the screen. If the panel is
+ resized it will remain at that position - i.e. the panel
+ will grow on both sides. If false, the y and y_bottom keys specify
+ the location of the panel.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/auto_hide</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Automatically hide panel into corner</short>
+ <long>
+ If true, the panel is automatically hidden into a corner
+ of the screen when the pointer leaves the panel area. Moving the
+ pointer to that corner again will cause the panel to re-appear.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/enable_animations</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable animations</short>
+ <long>
+ If true, hiding and un-hiding of this panel will be animated
+ rather than happening instantly.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/enable_buttons</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Enable hide buttons</short>
+ <long>
+ If true, buttons will be placed on each side of the panel
+ which may be used to move the panel to edge of the screen,
+ leaving only a button showing.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/enable_arrows</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable arrows on hide buttons</short>
+ <long>
+ If true, arrows will be placed on the hide buttons. This
+ key is only relevant if the enable_buttons key is true.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/hide_delay</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>300</default>
+ <locale name="C">
+ <short>Panel autohide delay</short>
+ <long>
+ Specifies the number of milliseconds delay after the pointer
+ leaves the panel area before the panel is automatically hidden.
+ This key is only relevant if the auto_hide key is true.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/unhide_delay</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>100</default>
+ <locale name="C">
+ <short>Panel autounhide delay</short>
+ <long>
+ Specifies the number of milliseconds delay after the pointer
+ enters the panel area before the panel is automatically
+ re-shown. This key is only relevant if the auto_hide key is
+ true.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/auto_hide_size</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>1</default>
+ <locale name="C">
+ <short>Visible pixels when hidden</short>
+ <long>
+ Specifies the number of pixels visible when the panel is
+ automatically hidden into a corner. This key is only
+ relevant if the auto_hide key is true.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/animation_speed</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>fast</default>
+ <locale name="C">
+ <short>Animation speed</short>
+ <long>
+ The speed in which panel animations should occur. Possible
+ values are "slow", "medium" and "fast". This key is only
+ relevant if the enable_animations key is true.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/type</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>gtk</default>
+ <locale name="C">
+ <short>Background type</short>
+ <long>
+ Which type of background should be used for this panel.
+ Possible values are "gtk" - the default GTK+ widget
+ background will be used, "color" - the color key will
+ be used as background color or "image" - the image
+ specified by the image key will be used as background.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/color</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default>#ffffff</default>
+ <locale name="C">
+ <short>Background color</short>
+ <long>
+ Specifies the background color for the panel in #RGB
+ format.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/opacity</key>
+ <owner>panel</owner>
+ <type>int</type>
+ <default>6000</default>
+ <locale name="C">
+ <short>Background color opacity</short>
+ <long>
+ Specifies the opacity of the background color format. If the
+ color is not completely opaque (a value of less than 65535),
+ the color will be composited onto the desktop background
+ image.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/image</key>
+ <owner>panel</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Background image</short>
+ <long>
+ Specifies the file to be used for the background image. If
+ the image contains an alpha channel it will be composited
+ onto the desktop background image.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/fit</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Fit image to panel</short>
+ <long>
+ If true, the image will be scaled (retaining the aspect
+ ratio of the image) to the panel height (if horizontal).
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/stretch</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Stretch image to panel</short>
+ <long>
+ If true, the image will be scaled to the panel dimensions.
+ The aspect ratio of the image will not be maintained.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/panel/toplevels/background/rotate</key>
+ <owner>panel</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Rotate image on vertical panels</short>
+ <long>
+ If true, the background image will be rotated when the panel
+ is oriented vertically.
+ </long>
+ </locale>
+ </schema>
+
+ </schemalist>
+
+</mateconfschemafile>
diff --git a/mate-panel/panel-types.h b/mate-panel/panel-types.h
new file mode 100644
index 00000000..e71549ae
--- /dev/null
+++ b/mate-panel/panel-types.h
@@ -0,0 +1,19 @@
+/*global type definitions*/
+#ifndef PANEL_TYPES_H
+#define PANEL_TYPES_H
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+typedef enum {
+ PANEL_SPEED_SLOW,
+ PANEL_SPEED_MEDIUM,
+ PANEL_SPEED_FAST
+} PanelSpeed;
+
+typedef struct {
+ GdkColor gdk;
+ guint16 alpha;
+} PanelColor;
+
+#endif
diff --git a/mate-panel/panel-util.c b/mate-panel/panel-util.c
new file mode 100644
index 00000000..9148eb0c
--- /dev/null
+++ b/mate-panel/panel-util.c
@@ -0,0 +1,1210 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * MATE panel utils
+ * (C) 1997, 1998, 1999, 2000 The Free Software Foundation
+ * Copyright 2000 Helix Code, Inc.
+ * Copyright 2000,2001 Eazel, Inc.
+ * Copyright 2001 George Lebl
+ * Copyright 2002 Sun Microsystems Inc.
+ *
+ * Authors: George Lebl
+ * Jacob Berkman
+ * Mark McLoughlin
+ */
+
+#include <config.h>
+
+#include "panel-util.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <libpanel-util/panel-error.h>
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-xdg.h>
+
+#include "applet.h"
+#include "nothing.h"
+#include "xstuff.h"
+#include "panel-config-global.h"
+#include "panel-mateconf.h"
+#include "panel-globals.h"
+#include "launcher.h"
+#include "panel-icon-names.h"
+#include "panel-lockdown.h"
+
+char *
+panel_util_make_exec_uri_for_desktop (const char *exec)
+{
+ GString *str;
+ const char *c;
+
+ if (!exec)
+ return g_strdup ("");
+
+ if (!strchr (exec, ' '))
+ return g_strdup (exec);
+
+ str = g_string_new_len (NULL, strlen (exec));
+
+ str = g_string_append_c (str, '"');
+ for (c = exec; *c != '\0'; c++) {
+ /* FIXME: GKeyFile will add an additional backslach so we'll
+ * end up with toto\\" instead of toto\"
+ * We could use g_key_file_set_value(), but then we don't
+ * benefit from the other escaping that glib is doing...
+ */
+ if (*c == '"')
+ str = g_string_append (str, "\\\"");
+ else
+ str = g_string_append_c (str, *c);
+ }
+ str = g_string_append_c (str, '"');
+
+ return g_string_free (str, FALSE);
+}
+
+int
+panel_find_applet_index (GtkWidget *widget)
+{
+ GSList *applet_list, *l;
+ int i;
+
+ applet_list = mate_panel_applet_list_applets ();
+
+ for (i = 0, l = applet_list; l; i++, l = l->next) {
+ AppletInfo *info = l->data;
+
+ if (info->widget == widget)
+ return i;
+ }
+
+ return i;
+}
+
+void
+panel_push_window_busy (GtkWidget *window)
+{
+ int busy = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
+ "Panel:WindowBusy"));
+
+ busy ++;
+
+ if (busy == 1) {
+ GdkWindow *win;
+
+ gtk_widget_set_sensitive (window, FALSE);
+
+ win = gtk_widget_get_window (window);
+ if (win != NULL) {
+ GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
+ gdk_window_set_cursor (win, cursor);
+ gdk_cursor_unref (cursor);
+ gdk_flush ();
+ }
+ }
+
+ g_object_set_data (G_OBJECT (window), "Panel:WindowBusy",
+ GINT_TO_POINTER (busy));
+}
+
+void
+panel_pop_window_busy (GtkWidget *window)
+{
+ int busy = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
+ "Panel:WindowBusy"));
+ busy --;
+
+ if (busy <= 0) {
+ GdkWindow *win;
+
+ gtk_widget_set_sensitive (window, TRUE);
+
+ win = gtk_widget_get_window (window);
+ if (win != NULL)
+ gdk_window_set_cursor (win, NULL);
+
+ g_object_set_data (G_OBJECT (window),
+ "Panel:WindowBusy", NULL);
+ } else {
+ g_object_set_data (G_OBJECT (window), "Panel:WindowBusy",
+ GINT_TO_POINTER (busy));
+ }
+}
+
+gboolean
+panel_is_program_in_path (const char *program)
+{
+ char *tmp = g_find_program_in_path (program);
+ if (tmp != NULL) {
+ g_free (tmp);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static gboolean
+panel_ensure_dir (const char *dirname)
+{
+ char *parsed, *p;
+
+ if (dirname == NULL)
+ return FALSE;
+
+ parsed = g_strdup (dirname);
+
+ if (g_file_test (parsed, G_FILE_TEST_IS_DIR)) {
+ g_free (parsed);
+ return TRUE;
+ }
+
+ p = strchr (parsed, '/');
+ if (p == parsed)
+ p = strchr (p+1, '/');
+
+ while (p != NULL) {
+ *p = '\0';
+ if (g_mkdir (parsed, 0700) != 0 &&
+ errno != EEXIST && errno != ENOSYS) {
+ g_free (parsed);
+ return FALSE;
+ }
+ *p = '/';
+ p = strchr (p+1, '/');
+ }
+
+ if (g_mkdir (parsed, 0700) != 0 &&
+ errno != EEXIST && errno != ENOSYS) {
+ g_free (parsed);
+ return FALSE;
+ }
+
+ g_free (parsed);
+ return TRUE;
+}
+
+gboolean
+panel_is_uri_writable (const char *uri)
+{
+ GFile *file;
+ GFileInfo *info;
+ gboolean retval;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ retval = FALSE;
+
+ file = g_file_new_for_uri (uri);
+
+ if (!g_file_query_exists (file, NULL)) {
+ GFile *parent;
+
+ parent = g_file_get_parent (file);
+ g_object_unref (file);
+
+ if (!g_file_query_exists (parent, NULL)) {
+ g_object_unref (parent);
+ return FALSE;
+ }
+
+ file = parent;
+ }
+
+ info = g_file_query_info (file, "access::*",
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ g_object_unref (file);
+
+ if (info) {
+ retval = g_file_info_get_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+ g_object_unref (info);
+ }
+
+ return retval;
+}
+
+gboolean
+panel_uri_exists (const char *uri)
+{
+ GFile *suri;
+ gboolean ret;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ suri = g_file_new_for_uri (uri);
+ ret = g_file_query_exists (suri, NULL);
+ g_object_unref (suri);
+
+ return ret;
+}
+
+char *
+panel_find_icon (GtkIconTheme *icon_theme,
+ const char *icon_name,
+ gint size)
+{
+ GtkIconInfo *info;
+ char *retval;
+ char *icon_no_extension;
+
+ if (icon_name == NULL || strcmp (icon_name, "") == 0)
+ return NULL;
+
+ if (g_path_is_absolute (icon_name)) {
+ if (g_file_test (icon_name, G_FILE_TEST_EXISTS)) {
+ return g_strdup (icon_name);
+ } else {
+ char *basename;
+
+ basename = g_path_get_basename (icon_name);
+ retval = panel_find_icon (icon_theme, basename,
+ size);
+ g_free (basename);
+
+ return retval;
+ }
+ }
+
+ /* This is needed because some .desktop files have an icon name *and*
+ * an extension as icon */
+ icon_no_extension = panel_xdg_icon_remove_extension (icon_name);
+
+ info = gtk_icon_theme_lookup_icon (icon_theme, icon_no_extension,
+ size, 0);
+
+ g_free (icon_no_extension);
+
+ if (info) {
+ retval = g_strdup (gtk_icon_info_get_filename (info));
+ gtk_icon_info_free (info);
+ } else
+ retval = NULL;
+
+ return retval;
+}
+
+GdkPixbuf *
+panel_load_icon (GtkIconTheme *icon_theme,
+ const char *icon_name,
+ int size,
+ int desired_width,
+ int desired_height,
+ char **error_msg)
+{
+ GdkPixbuf *retval;
+ char *file;
+ GError *error;
+
+ g_return_val_if_fail (error_msg == NULL || *error_msg == NULL, NULL);
+
+ file = panel_find_icon (icon_theme, icon_name, size);
+ if (!file) {
+ if (error_msg)
+ *error_msg = g_strdup_printf (_("Icon '%s' not found"),
+ icon_name);
+
+ return NULL;
+ }
+
+ error = NULL;
+ retval = gdk_pixbuf_new_from_file_at_size (file,
+ desired_width,
+ desired_height,
+ &error);
+ if (error) {
+ if (error_msg)
+ *error_msg = g_strdup (error->message);
+ g_error_free (error);
+ }
+
+ g_free (file);
+
+ return retval;
+}
+
+static char* panel_lock_screen_action_get_command(const char* action)
+{
+ char* command = NULL;
+ gboolean use_gscreensaver = FALSE;
+
+ if (panel_is_program_in_path("mate-screensaver-command") && panel_is_program_in_path("mate-screensaver-preferences"))
+ {
+ use_gscreensaver = TRUE;
+ }
+ else if (!panel_is_program_in_path("xscreensaver-command"))
+ {
+ return NULL;
+ }
+
+ if (strcmp (action, "prefs") == 0)
+ {
+ if (use_gscreensaver)
+ {
+ command = g_strdup ("mate-screensaver-preferences");
+ }
+ else if (panel_is_program_in_path ("xscreensaver-demo"))
+ {
+ command = g_strdup ("xscreensaver-demo");
+ }
+ else
+ {
+ command = NULL;
+ }
+ }
+ else if (strcmp (action, "activate") == 0 || strcmp(action, "lock") == 0)
+ {
+ /* Neither mate-screensaver or xscreensaver allow root
+ * to lock the screen */
+ if (geteuid () == 0)
+ {
+ command = NULL;
+ }
+ else
+ {
+ if (use_gscreensaver)
+ {
+ command = g_strdup_printf("mate-screensaver-command --%s", action);
+ }
+ else
+ {
+ command = g_strdup_printf("xscreensaver-command -%s", action);
+ }
+ }
+ }
+
+ return command;
+}
+
+gboolean
+panel_lock_screen_action_available (const char *action)
+{
+ char *command;
+ gboolean enabled = FALSE;
+
+ g_return_val_if_fail (action != NULL, FALSE);
+
+ if (strcmp (action, "prefs") != 0 &&
+ panel_lockdown_get_disable_lock_screen ())
+ return FALSE;
+
+ command = panel_lock_screen_action_get_command (action);
+ if (command)
+ enabled = TRUE;
+
+ g_free (command);
+
+ return enabled;
+}
+
+void panel_lock_screen_action(GdkScreen* screen, const char* action)
+{
+ GError* error = NULL;
+ char* command = NULL;
+
+ g_return_if_fail(GDK_IS_SCREEN (screen));
+ g_return_if_fail(action != NULL);
+
+ if (strcmp(action, "prefs") != 0 && panel_lockdown_get_disable_lock_screen())
+ {
+ return;
+ }
+
+ command = panel_lock_screen_action_get_command(action);
+
+ if (!command)
+ {
+ return;
+ }
+
+ if (!gdk_spawn_command_line_on_screen(screen, command, &error))
+ {
+ char* primary = g_strdup_printf(_("Could not execute '%s'"), command);
+ panel_error_dialog (NULL, screen, "cannot_exec_screensaver", TRUE, primary, error->message);
+ g_free(primary);
+ g_error_free(error);
+ }
+
+ g_free(command);
+}
+
+void panel_lock_screen(GdkScreen* screen)
+{
+ panel_lock_screen_action(screen, "lock");
+}
+
+
+#define PANEL_LAUNCHER_PERSONAL_PATH "panel2.d/default/launchers"
+
+static char *
+panel_launcher_get_personal_path (void)
+{
+ return g_build_filename (g_get_home_dir (), ".mate2",
+ PANEL_LAUNCHER_PERSONAL_PATH, NULL);
+}
+
+gboolean
+panel_launcher_is_in_personal_path (const char *location)
+{
+ GFile *file;
+ GFile *launchers_dir;
+ char *launchers_path;
+ gboolean retval;
+
+ if (!location)
+ return FALSE;
+
+ launchers_path = panel_launcher_get_personal_path ();
+ launchers_dir = g_file_new_for_path (launchers_path);
+ g_free (launchers_path);
+
+ file = panel_launcher_get_gfile (location);
+
+ retval = g_file_has_prefix (file, launchers_dir);
+
+ g_object_unref (file);
+ g_object_unref (launchers_dir);
+
+ return retval;
+}
+
+GFile *
+panel_launcher_get_gfile (const char *location)
+{
+ char *path;
+ GFile *file;
+
+ if (!g_ascii_strncasecmp (location, "file:", strlen ("file:")))
+ return g_file_new_for_uri (location);
+
+ if (g_path_is_absolute (location))
+ return g_file_new_for_path (location);
+
+ path = panel_make_full_path (NULL, location);
+ file = g_file_new_for_path (path);
+ g_free (path);
+
+ return file;
+}
+
+char *
+panel_launcher_get_uri (const char *location)
+{
+ char *path;
+ char *uri;
+
+ if (!g_ascii_strncasecmp (location, "file:", strlen ("file:")))
+ return g_strdup (location);
+
+ if (!g_path_is_absolute (location))
+ path = panel_make_full_path (NULL, location);
+ else
+ path = g_strdup (location);
+
+ uri = g_filename_to_uri (path, NULL, NULL);
+ g_free (path);
+
+ return uri;
+}
+
+char *
+panel_launcher_get_filename (const char *location)
+{
+ GFile *file;
+ GFile *launchers_dir;
+ char *launchers_path;
+ char *retval;
+
+ if (!g_path_is_absolute (location) &&
+ g_ascii_strncasecmp (location, "file:", strlen ("file:")))
+ /* this is not a local URI */
+ return NULL;
+
+ launchers_path = panel_launcher_get_personal_path ();
+ launchers_dir = g_file_new_for_path (launchers_path);
+ g_free (launchers_path);
+
+ file = panel_launcher_get_gfile (location);
+
+ retval = g_file_get_relative_path (launchers_dir, file);
+
+ g_object_unref (file);
+ g_object_unref (launchers_dir);
+
+ return retval;
+}
+
+char *
+panel_make_full_path (const char *dir,
+ const char *filename)
+{
+ char *retval;
+ char *freeme = NULL;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ if (!dir) {
+ freeme = panel_launcher_get_personal_path ();
+ dir = freeme;
+ }
+
+ /* Make sure the launcher directory exists */
+ if (!g_file_test (dir, G_FILE_TEST_EXISTS))
+ panel_ensure_dir (dir);
+
+ retval = g_build_filename (dir, filename, NULL);
+
+ g_free (freeme);
+
+ return retval;
+}
+
+char *
+panel_make_unique_desktop_path_from_name (const char *dir,
+ const char *name)
+{
+ int num = 1;
+ char *path = NULL;
+#ifndef NAME_MAX
+/* sigh: some OS don't have NAME_MAX (which is POSIX). */
+#ifdef MAXNAMLEN
+#define NAME_MAX MAXNAMLEN
+#else
+#define NAME_MAX 255
+#endif
+#endif
+ char filename[NAME_MAX];
+
+/* g_file_set_contents() use "%s.XXXXXX"
+ * FIXME: waiting for http://bugzilla.gnome.org/show_bug.cgi?id=437977 */
+#define LENGTH_FOR_TMPFILE_EXT 7
+
+ g_snprintf (filename,
+ sizeof (filename) - strlen (".desktop") - LENGTH_FOR_TMPFILE_EXT,
+ "%s", name);
+ g_strlcat (filename, ".desktop", sizeof (filename));
+ path = panel_make_full_path (dir, filename);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free (path);
+
+ while (TRUE) {
+ char *buf;
+
+ buf = g_strdup_printf ("-%d.desktop", num);
+ g_snprintf (filename,
+ sizeof (filename) - strlen (buf) - LENGTH_FOR_TMPFILE_EXT,
+ "%s", name);
+ g_strlcat (filename, buf, sizeof (filename));
+ g_free (buf);
+
+ path = panel_make_full_path (dir, filename);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free (path);
+
+ num++;
+ }
+
+ return NULL;
+}
+
+char *
+panel_make_unique_desktop_uri (const char *dir,
+ const char *source)
+{
+ char *name, *p;
+ char *uri;
+ char *path = NULL;
+
+ /* Accept NULL source. Using an emptry string makes our life easier
+ * than keeping NULL. */
+ if (!source)
+ source = "";
+
+ /* source may be an exec string, a path, or a URI. We truncate
+ * it at the first space (to get just the command name if it's
+ * an exec string), strip the path/URI, and remove the suffix
+ * if it's ".desktop".
+ */
+ name = g_strndup (source, strcspn (source, " "));
+ p = strrchr (name, '/');
+ while (p && !*(p + 1)) {
+ *p = '\0';
+ p = strrchr (name, '/');
+ }
+ if (p)
+ memmove (name, p + 1, strlen (p + 1) + 1);
+ p = strrchr (name, '.');
+ if (p && !strcmp (p, ".desktop")) {
+ *p = '\0';
+
+ /* also remove the -%d that might be at the end of the name */
+ p = strrchr (name, '-');
+ if (p) {
+ char *end;
+ strtol ((p + 1), &end, 10);
+ if (!*end)
+ *p = '\0';
+ }
+ }
+
+ if (name[0] == '\0') {
+ g_free (name);
+ name = g_strdup (_("file"));
+ }
+
+ path = panel_make_unique_desktop_path_from_name (dir, name);
+ g_free (name);
+
+ uri = g_filename_to_uri (path, NULL, NULL);
+ g_free (path);
+
+ return uri;
+}
+
+GdkPixbuf *
+panel_util_cairo_rgbdata_to_pixbuf (unsigned char *data,
+ int width,
+ int height)
+{
+ GdkPixbuf *retval;
+ unsigned char *dstptr;
+ unsigned char *srcptr;
+ int align;
+
+ g_assert (width > 0 && height > 0);
+
+ if (!data)
+ return NULL;
+
+ retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+ if (!retval)
+ return NULL;
+
+ dstptr = gdk_pixbuf_get_pixels (retval);
+ srcptr = data;
+ align = gdk_pixbuf_get_rowstride (retval) - (width * 3);
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+/* cairo == 00RRGGBB */
+#define CAIRO_RED 2
+#define CAIRO_GREEN 1
+#define CAIRO_BLUE 0
+#else
+/* cairo == BBGGRR00 */
+#define CAIRO_RED 1
+#define CAIRO_GREEN 2
+#define CAIRO_BLUE 3
+#endif
+
+ while (height--) {
+ int x = width;
+ while (x--) {
+ /* pixbuf == BBGGRR */
+ dstptr[0] = srcptr[CAIRO_RED];
+ dstptr[1] = srcptr[CAIRO_GREEN];
+ dstptr[2] = srcptr[CAIRO_BLUE];
+
+ dstptr += 3;
+ srcptr += 4;
+ }
+
+ dstptr += align;
+ }
+#undef CAIRO_RED
+#undef CAIRO_GREEN
+#undef CAIRO_BLUE
+
+ return retval;
+}
+
+char *
+guess_icon_from_exec (GtkIconTheme *icon_theme,
+ GKeyFile *key_file)
+{
+ char *exec;
+ char *icon_name;
+ char *path;
+
+ exec = panel_key_file_get_string (key_file, "Exec");
+ if (!exec || !exec [0]) {
+ g_free (exec);
+ return NULL;
+ }
+
+ icon_name = g_path_get_basename (exec);
+ g_free (exec);
+
+ path = panel_find_icon (icon_theme, icon_name, 48);
+ if (!path) {
+ g_free (icon_name);
+ return NULL;
+ }
+
+ return icon_name;
+}
+
+static GFile *
+panel_util_get_gfile_root (GFile *file)
+{
+ GFile *parent;
+ GFile *parent_old;
+
+ /* search for the root on the URI */
+ parent_old = g_object_ref (file);
+ parent = g_file_get_parent (file);
+ while (parent != NULL) {
+ g_object_unref (parent_old);
+ parent_old = parent;
+ parent = g_file_get_parent (parent);
+ }
+
+ return parent_old;
+}
+
+static char *
+panel_util_get_icon_name_from_g_icon (GIcon *gicon)
+{
+ const char * const *names;
+ GtkIconTheme *icon_theme;
+ int i;
+
+ if (!G_IS_THEMED_ICON (gicon))
+ return NULL;
+
+ names = g_themed_icon_get_names (G_THEMED_ICON (gicon));
+ icon_theme = gtk_icon_theme_get_default ();
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (gtk_icon_theme_has_icon (icon_theme, names[i]))
+ return g_strdup (names[i]);
+ }
+
+ return NULL;
+}
+
+static char *
+panel_util_get_file_display_name_if_mount (GFile *file)
+{
+ GFile *compare;
+ GVolumeMonitor *monitor;
+ GList *mounts, *l;
+ char *ret;
+
+ ret = NULL;
+
+ /* compare with all mounts */
+ monitor = g_volume_monitor_get ();
+ mounts = g_volume_monitor_get_mounts (monitor);
+ for (l = mounts; l != NULL; l = l->next) {
+ GMount *mount;
+ mount = G_MOUNT (l->data);
+ compare = g_mount_get_root (mount);
+ if (!ret && g_file_equal (file, compare))
+ ret = g_mount_get_name (mount);
+ g_object_unref (mount);
+ }
+ g_list_free (mounts);
+ g_object_unref (monitor);
+
+ return ret;
+}
+
+#define HOME_NAME_KEY "/apps/caja/desktop/home_icon_name"
+static char *
+panel_util_get_file_display_for_common_files (GFile *file)
+{
+ GFile *compare;
+
+ compare = g_file_new_for_path (g_get_home_dir ());
+ if (g_file_equal (file, compare)) {
+ char *mateconf_name;
+
+ g_object_unref (compare);
+
+ mateconf_name = mateconf_client_get_string (panel_mateconf_get_client (),
+ HOME_NAME_KEY,
+ NULL);
+ if (PANEL_GLIB_STR_EMPTY (mateconf_name)) {
+ g_free (mateconf_name);
+ return g_strdup (_("Home Folder"));
+ } else {
+ return mateconf_name;
+ }
+ }
+ g_object_unref (compare);
+
+ compare = g_file_new_for_path ("/");
+ if (g_file_equal (file, compare)) {
+ g_object_unref (compare);
+ /* Translators: this is the same string as the one found in
+ * caja */
+ return g_strdup (_("File System"));
+ }
+ g_object_unref (compare);
+
+ return NULL;
+}
+
+static char *
+panel_util_get_file_description (GFile *file)
+{
+ GFileInfo *info;
+ char *ret;
+
+ ret = NULL;
+
+ info = g_file_query_info (file, "standard::description",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL);
+
+ if (info) {
+ ret = g_strdup (g_file_info_get_attribute_string (info,
+ G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION));
+ g_object_unref (info);
+ }
+
+ return ret;
+}
+
+static char *
+panel_util_get_file_display_name (GFile *file,
+ gboolean use_fallback)
+{
+ GFileInfo *info;
+ char *ret;
+
+ ret = NULL;
+
+ info = g_file_query_info (file, "standard::display-name",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL);
+
+ if (info) {
+ ret = g_strdup (g_file_info_get_display_name (info));
+ g_object_unref (info);
+ }
+
+ if (!ret && use_fallback) {
+ /* can happen with URI schemes non supported by gvfs */
+ char *basename;
+
+ basename = g_file_get_basename (file);
+ ret = g_filename_display_name (basename);
+ g_free (basename);
+ }
+
+ return ret;
+}
+
+static char *
+panel_util_get_file_icon_name_if_mount (GFile *file)
+{
+ GFile *compare;
+ GVolumeMonitor *monitor;
+ GList *mounts, *l;
+ char *ret;
+
+ ret = NULL;
+
+ /* compare with all mounts */
+ monitor = g_volume_monitor_get ();
+ mounts = g_volume_monitor_get_mounts (monitor);
+ for (l = mounts; l != NULL; l = l->next) {
+ GMount *mount;
+ mount = G_MOUNT (l->data);
+ compare = g_mount_get_root (mount);
+ if (!ret && g_file_equal (file, compare)) {
+ GIcon *gicon;
+ gicon = g_mount_get_icon (mount);
+ ret = panel_util_get_icon_name_from_g_icon (gicon);
+ g_object_unref (gicon);
+ }
+ g_object_unref (mount);
+ }
+ g_list_free (mounts);
+ g_object_unref (monitor);
+
+ return ret;
+}
+
+/* TODO: convert this to a simple call to g_file_query_info? */
+static const char *
+panel_util_get_icon_for_uri_known_folders (const char *uri)
+{
+ const char *icon;
+ char *path;
+ int len;
+
+ icon = NULL;
+
+ if (!g_str_has_prefix (uri, "file:"))
+ return NULL;
+
+ path = g_filename_from_uri (uri, NULL, NULL);
+
+ /* Sanity check. We may be given a broken URI. */
+ if (path == NULL)
+ return NULL;
+
+ len = strlen (path);
+ if (path[len] == '/')
+ path[len] = '\0';
+
+ if (strcmp (path, "/") == 0)
+ icon = PANEL_ICON_FILESYSTEM;
+ else if (strcmp (path, g_get_home_dir ()) == 0)
+ icon = PANEL_ICON_HOME;
+ else if (strcmp (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)) == 0)
+ icon = PANEL_ICON_DESKTOP;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS)) == 0)
+ icon = PANEL_ICON_FOLDER_DOCUMENTS;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD)) == 0)
+ icon = PANEL_ICON_FOLDER_DOWNLOAD;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_MUSIC)) == 0)
+ icon = PANEL_ICON_FOLDER_MUSIC;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)) == 0)
+ icon = PANEL_ICON_FOLDER_PICTURES;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_PUBLIC_SHARE)) == 0)
+ icon = PANEL_ICON_FOLDER_PUBLIC_SHARE;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES)) == 0)
+ icon = PANEL_ICON_FOLDER_TEMPLATES;
+ else if (g_strcmp0 (path,
+ g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS)) == 0)
+ icon = PANEL_ICON_FOLDER_VIDEOS;
+
+ g_free (path);
+
+ return icon;
+}
+
+/* This is based on caja_compute_title_for_uri() and
+ * caja_file_get_display_name_nocopy() */
+char *
+panel_util_get_label_for_uri (const char *text_uri)
+{
+ GFile *file;
+ char *label;
+ GFile *root;
+ char *root_display;
+
+ /* Here's what we do:
+ * + x-caja-search: URI
+ * + check if the URI is a mount
+ * + if file: URI:
+ * - check for known file: URI
+ * - check for description of the GFile
+ * - use display name of the GFile
+ * + else:
+ * - check for description of the GFile
+ * - if the URI is a root: "root displayname"
+ * - else: "root displayname: displayname"
+ */
+
+ label = NULL;
+
+ //FIXME: see caja_query_to_readable_string() to have a nice name
+ if (g_str_has_prefix (text_uri, "x-caja-search:"))
+ return g_strdup (_("Search"));
+
+ file = g_file_new_for_uri (text_uri);
+
+ label = panel_util_get_file_display_name_if_mount (file);
+ if (label) {
+ g_object_unref (file);
+ return label;
+ }
+
+ if (g_str_has_prefix (text_uri, "file:")) {
+ label = panel_util_get_file_display_for_common_files (file);
+ if (!label)
+ label = panel_util_get_file_description (file);
+ if (!label)
+ label = panel_util_get_file_display_name (file, TRUE);
+ g_object_unref (file);
+
+ return label;
+ }
+
+ label = panel_util_get_file_description (file);
+ if (label) {
+ g_object_unref (file);
+ return label;
+ }
+
+ root = panel_util_get_gfile_root (file);
+ root_display = panel_util_get_file_description (root);
+ if (!root_display)
+ root_display = panel_util_get_file_display_name (root, FALSE);
+ if (!root_display)
+ /* can happen with URI schemes non supported by gvfs */
+ root_display = g_file_get_uri_scheme (root);
+
+ if (g_file_equal (file, root))
+ label = root_display;
+ else {
+ char *displayname;
+
+ displayname = panel_util_get_file_display_name (file, TRUE);
+ /* Translators: the first string is the name of a gvfs
+ * method, and the second string is a path. For
+ * example, "Trash: some-directory". It means that the
+ * directory called "some-directory" is in the trash.
+ */
+ label = g_strdup_printf (_("%1$s: %2$s"),
+ root_display, displayname);
+ g_free (root_display);
+ g_free (displayname);
+ }
+
+ g_object_unref (root);
+ g_object_unref (file);
+
+ return label;
+}
+
+/* FIXME: we probably want to return a GIcon, that would be built with
+ * g_themed_icon_new_with_default_fallbacks() since we can get an icon like
+ * "folder-music", where "folder" is the safe fallback. */
+char *
+panel_util_get_icon_for_uri (const char *text_uri)
+{
+ const char *icon;
+ GFile *file;
+ GFileInfo *info;
+ GIcon *gicon;
+ char *retval;
+
+ /* Here's what we do:
+ * + check for known file: URI
+ * + x-caja-search: URI
+ * + override burn: URI icon
+ * + check if the URI is a mount
+ * + override trash: URI icon for subfolders
+ * + check for application/x-mate-saved-search mime type and override
+ * icon of the GFile
+ * + use icon of the GFile
+ */
+
+ /* this only checks file: URI */
+ icon = panel_util_get_icon_for_uri_known_folders (text_uri);
+ if (icon)
+ return g_strdup (icon);
+
+ if (g_str_has_prefix (text_uri, "x-caja-search:"))
+ return g_strdup (PANEL_ICON_SAVED_SEARCH);
+ /* gvfs doesn't give us a nice icon, so overriding */
+ if (g_str_has_prefix (text_uri, "burn:"))
+ return g_strdup (PANEL_ICON_BURNER);
+
+ file = g_file_new_for_uri (text_uri);
+
+ retval = panel_util_get_file_icon_name_if_mount (file);
+ if (retval)
+ return retval;
+
+ /* gvfs doesn't give us a nice icon for subfolders of the trash, so
+ * overriding */
+ if (g_str_has_prefix (text_uri, "trash:")) {
+ GFile *root;
+
+ root = panel_util_get_gfile_root (file);
+ g_object_unref (file);
+ file = root;
+ }
+
+ info = g_file_query_info (file, "standard::icon",
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ g_object_unref (file);
+
+ if (!info)
+ return NULL;
+
+ gicon = g_file_info_get_icon (info);
+ retval = panel_util_get_icon_name_from_g_icon (gicon);
+ g_object_unref (info);
+
+ return retval;
+}
+
+static gboolean
+panel_util_query_tooltip_cb (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ const char *text)
+{
+ if (!panel_global_config_get_tooltips_enabled ())
+ return FALSE;
+
+ gtk_tooltip_set_text (tooltip, text);
+ return TRUE;
+}
+
+void
+panel_util_set_tooltip_text (GtkWidget *widget,
+ const char *text)
+{
+ g_signal_handlers_disconnect_matched (widget,
+ G_SIGNAL_MATCH_FUNC,
+ 0, 0, NULL,
+ panel_util_query_tooltip_cb,
+ NULL);
+
+ if (PANEL_GLIB_STR_EMPTY (text)) {
+ g_object_set (widget, "has-tooltip", FALSE, NULL);
+ return;
+ }
+
+ g_object_set (widget, "has-tooltip", TRUE, NULL);
+ g_signal_connect_data (widget, "query-tooltip",
+ G_CALLBACK (panel_util_query_tooltip_cb),
+ g_strdup (text), (GClosureNotify) g_free, 0);
+}
+
+/* This is similar to what g_file_new_for_commandline_arg() does, but
+ * we end up with something relative to $HOME instead of the current working
+ * directory */
+GFile *
+panel_util_get_file_optional_homedir (const char *location)
+{
+ GFile *file;
+ char *path;
+ char *scheme;
+
+ if (g_path_is_absolute (location))
+ return g_file_new_for_path (location);
+
+ scheme = g_uri_parse_scheme (location);
+ if (scheme) {
+ file = g_file_new_for_uri (location);
+ g_free (scheme);
+ return file;
+ }
+
+ path = g_build_filename (g_get_home_dir (), location, NULL);
+ file = g_file_new_for_path (path);
+ g_free (path);
+
+ return file;
+}
diff --git a/mate-panel/panel-util.h b/mate-panel/panel-util.h
new file mode 100644
index 00000000..364e8b57
--- /dev/null
+++ b/mate-panel/panel-util.h
@@ -0,0 +1,72 @@
+#ifndef PANEL_UTIL_H
+#define PANEL_UTIL_H
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define sure_string(s) ((const char *)((s)!=NULL?(s):""))
+
+char * panel_util_make_exec_uri_for_desktop (const char *exec);
+
+int panel_find_applet_index (GtkWidget *widget);
+
+void panel_push_window_busy (GtkWidget *window);
+void panel_pop_window_busy (GtkWidget *window);
+
+gboolean panel_is_program_in_path (const char *program);
+
+gboolean panel_is_uri_writable (const char *uri);
+gboolean panel_uri_exists (const char *uri);
+
+void panel_lock_screen (GdkScreen *screen);
+void panel_lock_screen_action (GdkScreen *screen,
+ const char *action);
+gboolean panel_lock_screen_action_available (const char *action);
+
+char * panel_find_icon (GtkIconTheme *icon_theme,
+ const char *icon_name,
+ int size);
+GdkPixbuf * panel_load_icon (GtkIconTheme *icon_theme,
+ const char *icon_name,
+ int size,
+ int desired_width,
+ int desired_height,
+ char **error_msg);
+
+GFile *panel_launcher_get_gfile (const char *location);
+char *panel_launcher_get_uri (const char *location);
+char *panel_launcher_get_filename (const char *location);
+gboolean panel_launcher_is_in_personal_path (const char *location);
+
+char *panel_make_full_path (const char *dir,
+ const char *filename);
+char *panel_make_unique_desktop_path_from_name (const char *dir,
+ const char *name);
+char *panel_make_unique_desktop_uri (const char *dir,
+ const char *source);
+
+GdkPixbuf *panel_util_cairo_rgbdata_to_pixbuf (unsigned char *data,
+ int width,
+ int height);
+
+char *guess_icon_from_exec (GtkIconTheme *icon_theme,
+ GKeyFile *key_file);
+
+const char *panel_util_get_vfs_method_display_name (const char *method);
+char *panel_util_get_label_for_uri (const char *text_uri);
+char *panel_util_get_icon_for_uri (const char *text_uri);
+
+void panel_util_set_tooltip_text (GtkWidget *widget,
+ const char *text);
+
+GFile *panel_util_get_file_optional_homedir (const char *location);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_UTIL_H */
diff --git a/mate-panel/panel-widget.c b/mate-panel/panel-widget.c
new file mode 100644
index 00000000..1800a7b5
--- /dev/null
+++ b/mate-panel/panel-widget.c
@@ -0,0 +1,3010 @@
+/* Mate panel: panel widget
+ * (C) 1997,1998,1999,2000 the Free Software Foundation
+ * (C) 2000 Eazel, Inc.
+ *
+ * Authors: George Lebl
+ */
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <libpanel-util/panel-list.h>
+
+#include "applet.h"
+#include "panel-widget.h"
+#include "button-widget.h"
+#include "panel.h"
+#include "panel-util.h"
+#include "panel-marshal.h"
+#include "panel-typebuiltins.h"
+#include "mate-panel-applet-frame.h"
+#include "panel-globals.h"
+#include "panel-profile.h"
+#include "panel-lockdown.h"
+
+#define MOVE_INCREMENT 1
+
+typedef enum {
+ PANEL_SWITCH_MOVE = 0,
+ PANEL_FREE_MOVE,
+ PANEL_PUSH_MOVE
+} PanelMovementType;
+
+G_DEFINE_TYPE (PanelWidget, panel_widget, GTK_TYPE_FIXED);
+
+enum {
+ SIZE_CHANGE_SIGNAL,
+ BACK_CHANGE_SIGNAL,
+ APPLET_MOVE_SIGNAL,
+ APPLET_ADDED_SIGNAL,
+ APPLET_REMOVED_SIGNAL,
+ PUSH_MOVE_SIGNAL,
+ SWITCH_MOVE_SIGNAL,
+ FREE_MOVE_SIGNAL,
+ TAB_MOVE_SIGNAL,
+ END_MOVE_SIGNAL,
+ POPUP_PANEL_MENU_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint panel_widget_signals [LAST_SIGNAL] = {0};
+
+/*define for some debug output*/
+#undef PANEL_WIDGET_DEBUG
+
+static gboolean mate_panel_applet_in_drag = FALSE;
+static GtkWidget *saved_focus_widget = NULL;
+
+static void panel_widget_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void panel_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void panel_widget_cadd (GtkContainer *container,
+ GtkWidget *widget);
+static void panel_widget_cremove (GtkContainer *container,
+ GtkWidget *widget);
+static void panel_widget_destroy (GtkObject *obj);
+static void panel_widget_finalize (GObject *obj);
+static void panel_widget_realize (GtkWidget *widget);
+static void panel_widget_unrealize (GtkWidget *panel);
+static void panel_widget_state_changed (GtkWidget *widget,
+ GtkStateType previous_state);
+static void panel_widget_style_set (GtkWidget *widget,
+ GtkStyle *previous_style);
+
+static void panel_widget_background_changed (PanelBackground *background,
+ PanelWidget *panel);
+
+static void panel_widget_push_move_applet (PanelWidget *panel,
+ GtkDirectionType dir);
+static void panel_widget_switch_move_applet (PanelWidget *panel,
+ GtkDirectionType dir);
+static void panel_widget_free_move_applet (PanelWidget *panel,
+ GtkDirectionType dir);
+static void panel_widget_tab_move (PanelWidget *panel,
+ gboolean next);
+static void panel_widget_end_move (PanelWidget *panel);
+static gboolean panel_widget_real_focus (GtkWidget *widget,
+ GtkDirectionType direction);
+
+static gboolean panel_widget_push_applet_right (PanelWidget *panel,
+ GList *list,
+ int push);
+static gboolean panel_widget_push_applet_left (PanelWidget *panel,
+ GList *list,
+ int push);
+
+/************************
+ convenience functions
+ ************************/
+static int
+applet_data_compare (AppletData *ad1, AppletData *ad2)
+{
+ return ad1->pos - ad2->pos;
+}
+
+static void
+emit_applet_moved (PanelWidget *panel_widget,
+ AppletData *applet)
+{
+ g_signal_emit (panel_widget,
+ panel_widget_signals [APPLET_MOVE_SIGNAL], 0,
+ applet->applet);
+}
+
+/************************
+ widget core
+ ************************/
+
+static void
+add_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ gboolean next)
+{
+ gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
+ "tab_move", 1,
+ G_TYPE_BOOLEAN, next);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
+ "tab_move", 1,
+ G_TYPE_BOOLEAN, next);
+}
+
+static void
+add_move_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ const gchar *name)
+{
+ gtk_binding_entry_add_signal (binding_set, GDK_Up, modifiers,
+ name, 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
+ gtk_binding_entry_add_signal (binding_set, GDK_Down, modifiers,
+ name, 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
+ gtk_binding_entry_add_signal (binding_set, GDK_Left, modifiers,
+ name, 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
+ gtk_binding_entry_add_signal (binding_set, GDK_Right, modifiers,
+ name, 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
+}
+
+static void
+add_all_move_bindings (PanelWidget *panel)
+{
+ GtkWidgetClass *class;
+ GtkBindingSet *binding_set;
+ GtkWidget *focus_widget;
+
+ class = GTK_WIDGET_GET_CLASS (panel);
+
+ binding_set = gtk_binding_set_by_class (class);
+
+ add_move_bindings (binding_set, GDK_SHIFT_MASK, "push_move");
+ add_move_bindings (binding_set, GDK_CONTROL_MASK, "switch_move");
+ add_move_bindings (binding_set, GDK_MOD1_MASK, "free_move");
+ add_move_bindings (binding_set, 0, "free_move");
+
+ add_tab_bindings (binding_set, 0, TRUE);
+ add_tab_bindings (binding_set, GDK_SHIFT_MASK, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Escape, 0,
+ "end_move", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Enter, 0,
+ "end_move", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Return, 0,
+ "end_move", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Space, 0,
+ "end_move", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_space, 0,
+ "end_move", 0);
+
+ focus_widget = gtk_window_get_focus (GTK_WINDOW (panel->toplevel));
+ if (GTK_IS_SOCKET (focus_widget)) {
+ /*
+ * If the focus widget is a GtkSocket, i.e. the
+ * focus is in an applet in another process then
+ * key bindings do not work. We get around this by
+ * by setting the focus to the PanelWidget for the
+ * duration of the move.
+ */
+ gtk_widget_set_can_focus (GTK_WIDGET (panel), TRUE);
+ gtk_widget_grab_focus (GTK_WIDGET (panel));
+ saved_focus_widget = focus_widget;
+ }
+}
+
+static void
+panel_widget_force_grab_focus (GtkWidget *widget)
+{
+ gboolean can_focus = gtk_widget_get_can_focus (widget);
+ /*
+ * This follows what gtk_socket_claim_focus() does
+ */
+ if (!can_focus)
+ gtk_widget_set_can_focus (widget, TRUE);
+ gtk_widget_grab_focus (widget);
+ if (!can_focus)
+ gtk_widget_set_can_focus (widget, FALSE);
+}
+
+static void
+panel_widget_reset_saved_focus (PanelWidget *panel)
+{
+ if (saved_focus_widget) {
+ gtk_widget_set_can_focus (GTK_WIDGET (panel), FALSE);
+ panel_widget_force_grab_focus (saved_focus_widget);
+ saved_focus_widget = NULL;
+ }
+}
+
+static void
+remove_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ gboolean next)
+{
+ gtk_binding_entry_remove (binding_set, GDK_Tab, modifiers);
+ gtk_binding_entry_remove (binding_set, GDK_KP_Tab, modifiers);
+}
+
+static void
+remove_move_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers)
+{
+ gtk_binding_entry_remove (binding_set, GDK_Up, modifiers);
+ gtk_binding_entry_remove (binding_set, GDK_Down, modifiers);
+ gtk_binding_entry_remove (binding_set, GDK_Left, modifiers);
+ gtk_binding_entry_remove (binding_set, GDK_Right, modifiers);
+}
+
+static void
+remove_all_move_bindings (PanelWidget *panel)
+{
+ GtkWidgetClass *class;
+ GtkBindingSet *binding_set;
+
+ class = GTK_WIDGET_GET_CLASS (panel);
+
+ binding_set = gtk_binding_set_by_class (class);
+
+ panel_widget_reset_saved_focus (panel);
+
+ remove_move_bindings (binding_set, GDK_SHIFT_MASK);
+ remove_move_bindings (binding_set, GDK_CONTROL_MASK);
+ remove_move_bindings (binding_set, GDK_MOD1_MASK);
+ remove_move_bindings (binding_set, 0);
+ remove_tab_bindings (binding_set, 0, TRUE);
+ remove_tab_bindings (binding_set, GDK_SHIFT_MASK, FALSE);
+
+ gtk_binding_entry_remove (binding_set, GDK_Escape, 0);
+ gtk_binding_entry_remove (binding_set, GDK_KP_Enter, 0);
+ gtk_binding_entry_remove (binding_set, GDK_Return, 0);
+ gtk_binding_entry_remove (binding_set, GDK_KP_Space, 0);
+ gtk_binding_entry_remove (binding_set, GDK_space, 0);
+}
+
+static void
+panel_widget_class_init (PanelWidgetClass *class)
+{
+ GtkObjectClass *object_class = (GtkObjectClass*) class;
+ GObjectClass *gobject_class = (GObjectClass*) class;
+ GtkWidgetClass *widget_class = (GtkWidgetClass*) class;
+ GtkContainerClass *container_class = (GtkContainerClass*) class;
+
+ panel_widget_signals[SIZE_CHANGE_SIGNAL] =
+ g_signal_new ("size_change",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelWidgetClass, size_change),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ panel_widget_signals[BACK_CHANGE_SIGNAL] =
+ g_signal_new ("back_change",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelWidgetClass, back_change),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ panel_widget_signals[APPLET_MOVE_SIGNAL] =
+ g_signal_new ("applet_move",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelWidgetClass, applet_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER);
+
+ panel_widget_signals[APPLET_ADDED_SIGNAL] =
+ g_signal_new ("applet_added",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelWidgetClass, applet_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER);
+
+ panel_widget_signals[APPLET_REMOVED_SIGNAL] =
+ g_signal_new ("applet_removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelWidgetClass, applet_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER);
+
+ panel_widget_signals[PUSH_MOVE_SIGNAL] =
+ g_signal_new ("push_move",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelWidgetClass, push_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_DIRECTION_TYPE);
+
+ panel_widget_signals[SWITCH_MOVE_SIGNAL] =
+ g_signal_new ("switch_move",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelWidgetClass, switch_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_DIRECTION_TYPE);
+
+ panel_widget_signals[FREE_MOVE_SIGNAL] =
+ g_signal_new ("free_move",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelWidgetClass, free_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_DIRECTION_TYPE);
+
+ panel_widget_signals[TAB_MOVE_SIGNAL] =
+ g_signal_new ("tab_move",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelWidgetClass, tab_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
+ panel_widget_signals[END_MOVE_SIGNAL] =
+ g_signal_new ("end_move",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (PanelWidgetClass, end_move),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ class->size_change = NULL;
+ class->back_change = NULL;
+ class->applet_move = NULL;
+ class->applet_added = NULL;
+ class->applet_removed = NULL;
+ class->push_move = panel_widget_push_move_applet;
+ class->switch_move = panel_widget_switch_move_applet;
+ class->free_move = panel_widget_free_move_applet;
+ class->tab_move = panel_widget_tab_move;
+ class->end_move = panel_widget_end_move;
+
+ object_class->destroy = panel_widget_destroy;
+ gobject_class->finalize = panel_widget_finalize;
+
+ widget_class->size_request = panel_widget_size_request;
+ widget_class->size_allocate = panel_widget_size_allocate;
+ widget_class->realize = panel_widget_realize;
+ widget_class->unrealize = panel_widget_unrealize;
+ widget_class->focus = panel_widget_real_focus;
+ widget_class->state_changed = panel_widget_state_changed;
+ widget_class->style_set = panel_widget_style_set;
+
+ container_class->add = panel_widget_cadd;
+ container_class->remove = panel_widget_cremove;
+}
+
+static void
+remove_panel_from_forbidden(PanelWidget *panel, PanelWidget *r)
+{
+ GSList *list;
+ GtkWidget *parent_panel;
+
+ g_return_if_fail(PANEL_IS_WIDGET(panel));
+ g_return_if_fail(PANEL_IS_WIDGET(r));
+
+ if(!panel->master_widget)
+ return;
+
+ list = g_object_get_data (G_OBJECT(panel->master_widget),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS);
+ if(list) {
+ list = g_slist_remove(list,r);
+ g_object_set_data (G_OBJECT(panel->master_widget),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS,
+ list);
+ }
+ parent_panel = gtk_widget_get_parent (panel->master_widget);
+ if (parent_panel)
+ remove_panel_from_forbidden(PANEL_WIDGET(parent_panel), r);
+}
+
+static void
+add_panel_to_forbidden(PanelWidget *panel, PanelWidget *r)
+{
+ GSList *list;
+ GtkWidget *parent_panel;
+
+ g_return_if_fail(PANEL_IS_WIDGET(panel));
+ g_return_if_fail(PANEL_IS_WIDGET(r));
+
+ if(!panel->master_widget)
+ return;
+
+ list = g_object_get_data (G_OBJECT(panel->master_widget),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS);
+ if(g_slist_find(list,r)==NULL) {
+ list = g_slist_prepend(list,r);
+
+ g_object_set_data (G_OBJECT(panel->master_widget),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS,
+ list);
+ }
+ parent_panel = gtk_widget_get_parent (panel->master_widget);
+ if (parent_panel)
+ add_panel_to_forbidden(PANEL_WIDGET(parent_panel), r);
+}
+
+static void
+run_up_forbidden(PanelWidget *panel,
+ void (*runfunc)(PanelWidget *,PanelWidget *))
+{
+ GList *list;
+
+ g_return_if_fail(PANEL_IS_WIDGET(panel));
+
+ for(list = panel->applet_list;list!=NULL;list = g_list_next(list)) {
+ AppletData *ad = list->data;
+ PanelWidget *p =
+ g_object_get_data (G_OBJECT(ad->applet),
+ MATE_PANEL_APPLET_ASSOC_PANEL_KEY);
+ if(p)
+ run_up_forbidden(p,runfunc);
+ }
+ (*runfunc)(panel,panel);
+}
+
+static void
+panel_widget_reset_focus (GtkContainer *container,
+ GtkWidget *widget)
+{
+ PanelWidget *panel = PANEL_WIDGET (container);
+
+ if (gtk_container_get_focus_child (container) == widget) {
+ GList *children;
+
+ children = gtk_container_get_children (container);
+
+ /* More than one element on the list */
+ if (children && children->next) {
+ GList *l;
+
+ /* There are still object on the panel */
+ for (l = children; l; l = l->next) {
+ GtkWidget *child_widget;
+
+ child_widget = l->data;
+ if (child_widget == widget)
+ break;
+ }
+ if (l) {
+ GtkWidget *next_widget;
+
+ if (l->next)
+ next_widget = l->next->data;
+ else
+ next_widget = l->prev->data;
+
+ gtk_widget_child_focus (next_widget,
+ GTK_DIR_TAB_FORWARD);
+ }
+ } else
+ panel_widget_focus (panel);
+
+ g_list_free (children);
+ }
+}
+
+static void
+panel_widget_cadd (GtkContainer *container,
+ GtkWidget *widget)
+{
+ PanelWidget *p;
+
+ g_return_if_fail (PANEL_IS_WIDGET (container));
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ panel_widget_add (PANEL_WIDGET (container), widget, FALSE, 0, FALSE);
+
+ p = g_object_get_data (G_OBJECT(widget),
+ MATE_PANEL_APPLET_ASSOC_PANEL_KEY);
+ if (p) {
+ panel_toplevel_attach_to_widget (p->toplevel,
+ PANEL_WIDGET (container)->toplevel,
+ widget);
+ run_up_forbidden (p, add_panel_to_forbidden);
+ }
+}
+
+static void
+panel_widget_cremove (GtkContainer *container, GtkWidget *widget)
+{
+ AppletData *ad;
+ PanelWidget *p;
+ PanelWidget *panel;
+
+ g_return_if_fail (PANEL_IS_WIDGET (container));
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ panel = PANEL_WIDGET (container);
+
+ ad = g_object_get_data (G_OBJECT (widget), MATE_PANEL_APPLET_DATA);
+ p = g_object_get_data (G_OBJECT (widget),
+ MATE_PANEL_APPLET_ASSOC_PANEL_KEY);
+
+ if (p != NULL) {
+ panel_toplevel_detach (p->toplevel);
+ run_up_forbidden (p, remove_panel_from_forbidden);
+ }
+
+ panel_widget_reset_focus (container, widget);
+
+ if(panel->currently_dragged_applet == ad)
+ panel_widget_applet_drag_end(panel);
+
+ g_object_ref (widget);
+ if (GTK_CONTAINER_CLASS (panel_widget_parent_class)->remove)
+ (* GTK_CONTAINER_CLASS (panel_widget_parent_class)->remove) (container,
+ widget);
+ if (ad)
+ panel->applet_list = g_list_remove (panel->applet_list, ad);
+
+ g_signal_emit (G_OBJECT (container),
+ panel_widget_signals[APPLET_REMOVED_SIGNAL],
+ 0, widget);
+ g_object_unref (widget);
+}
+
+
+/*get the list item of the data on the position pos*/
+static GList *
+get_applet_list_pos (PanelWidget *panel,
+ int pos)
+{
+ GList *l;
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), NULL);
+
+ for (l = panel->applet_list; l; l = l->next) {
+ AppletData *ad = l->data;
+
+ if (ad->pos <= pos) {
+ if (ad->pos + ad->cells > pos)
+ return l;
+ } else
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*tells us if an applet is "stuck" on the right side*/
+int
+panel_widget_is_applet_stuck (PanelWidget *panel_widget,
+ GtkWidget *widget)
+{
+ AppletData *applet;
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel_widget), FALSE);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ applet = g_object_get_data (G_OBJECT (widget), MATE_PANEL_APPLET_DATA);
+ if (applet) {
+ GList *applet_list, *l;
+ int end_pos = -1;
+
+ applet_list = g_list_find (panel_widget->applet_list, applet);
+
+ for (l = applet_list; l; l = l->next) {
+ applet = l->data;
+
+ if (end_pos != -1 && applet->pos != end_pos)
+ break;
+
+ end_pos = applet->pos + applet->cells;
+ if (end_pos >= panel_widget->size)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static int
+get_size_from_hints (AppletData *ad, int cells)
+{
+ int i;
+
+ for (i = 0; i < ad->size_hints_len; i += 2) {
+ if (cells > ad->size_hints[i]) {
+ /* Clip to top */
+ cells = ad->size_hints[i];
+ break;
+ }
+ if (cells <= ad->size_hints[i] &&
+ cells >= ad->size_hints[i+1]) {
+ /* Keep cell size */
+ break;
+ }
+ }
+
+ return MAX (cells, ad->min_cells);
+}
+
+static void
+panel_widget_jump_applet_right (PanelWidget *panel,
+ GList *list,
+ GList *next,
+ int pos)
+{
+ AppletData *ad;
+ AppletData *nad = NULL;
+
+ ad = list->data;
+ if (next)
+ nad = next->data;
+
+ if (pos >= panel->size)
+ return;
+
+ if (!nad || nad->constrained >= pos + ad->min_cells)
+ goto jump_right;
+
+ if (!panel_widget_push_applet_right (panel, next, pos + ad->min_cells - nad->constrained)) {
+ panel_widget_jump_applet_right (panel,
+ list,
+ next->next,
+ nad->constrained + nad->min_cells);
+ return;
+ }
+
+ jump_right:
+ ad->pos = ad->constrained = pos;
+ panel->applet_list = g_list_remove_link (panel->applet_list, list);
+ panel->applet_list = panel_g_list_insert_before (panel->applet_list, next, list);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+}
+
+static void
+panel_widget_switch_applet_right (PanelWidget *panel,
+ GList *list)
+{
+ AppletData *ad;
+ AppletData *nad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (ad->constrained + ad->min_cells >= panel->size)
+ return;
+
+ if (list->next)
+ nad = list->next->data;
+
+ if (!nad || nad->constrained >= ad->constrained + ad->min_cells + MOVE_INCREMENT) {
+ ad->pos = ad->constrained += MOVE_INCREMENT;
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+ return;
+ }
+
+ if (nad->locked) {
+ panel_widget_jump_applet_right (panel,
+ list,
+ list->next->next,
+ nad->constrained + nad->min_cells);
+ return;
+ }
+
+ nad->constrained = nad->pos = ad->constrained;
+ ad->constrained = ad->pos = ad->constrained + nad->min_cells;
+ panel->applet_list = panel_g_list_swap_next (panel->applet_list, list);
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ emit_applet_moved (panel, ad);
+ emit_applet_moved (panel, nad);
+}
+
+static void
+panel_widget_jump_applet_left (PanelWidget *panel,
+ GList *list,
+ GList *prev,
+ int pos)
+{
+ AppletData *ad;
+ AppletData *pad = NULL;
+
+ ad = list->data;
+ if (prev)
+ pad = prev->data;
+
+ if (pos < 0)
+ return;
+
+ if (!pad || pad->constrained + pad->min_cells <= pos)
+ goto jump_left;
+
+ if (!panel_widget_push_applet_left (panel, prev, pad->constrained + pad->min_cells - pos)) {
+ panel_widget_jump_applet_left (panel,
+ list,
+ prev->prev,
+ pad->constrained - ad->min_cells);
+ return;
+ }
+
+ jump_left:
+ ad->pos = ad->constrained = pos;
+ panel->applet_list = g_list_remove_link (panel->applet_list, list);
+ panel->applet_list = panel_g_list_insert_after (panel->applet_list, prev, list);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+}
+
+static void
+panel_widget_switch_applet_left (PanelWidget *panel,
+ GList *list)
+{
+ AppletData *ad;
+ AppletData *pad = NULL;
+
+ ad = list->data;
+ if (ad->constrained <= 0)
+ return;
+
+ if (list->prev)
+ pad = list->prev->data;
+
+ if (!pad || pad->constrained + pad->min_cells <= ad->constrained - MOVE_INCREMENT) {
+ ad->pos = ad->constrained -= MOVE_INCREMENT;
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+ return;
+ }
+
+ if (pad->locked) {
+ panel_widget_jump_applet_left (panel,
+ list,
+ list->prev->prev,
+ pad->constrained - ad->min_cells);
+ return;
+ }
+
+ ad->constrained = ad->pos = pad->constrained;
+ pad->constrained = pad->pos = ad->constrained + ad->min_cells;
+ panel->applet_list = panel_g_list_swap_prev (panel->applet_list, list);
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ emit_applet_moved (panel, ad);
+ emit_applet_moved (panel, pad);
+}
+
+static gboolean
+panel_widget_try_push_right (PanelWidget *panel,
+ GList *list,
+ int push)
+{
+ AppletData *ad;
+ AppletData *nad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (list->next)
+ nad = list->next->data;
+
+ if (ad->locked)
+ return FALSE;
+
+ if (ad->constrained + ad->min_cells + push >= panel->size)
+ return FALSE;
+
+ if (!nad || nad->constrained >= ad->constrained + ad->min_cells + push)
+ return TRUE;
+
+ return panel_widget_try_push_right (panel, list->next, push);
+}
+
+static int
+panel_widget_get_right_jump_pos (PanelWidget *panel,
+ AppletData *ad,
+ GList *next,
+ int pos)
+{
+ AppletData *nad = NULL;
+
+ if (next)
+ nad = next->data;
+
+ if (!nad || nad->constrained >= pos + ad->min_cells)
+ return pos;
+
+ if (panel_widget_try_push_right (panel, next, pos + ad->min_cells - nad->constrained))
+ return pos;
+
+ return panel_widget_get_right_jump_pos (panel,
+ ad,
+ next->next,
+ nad->constrained + nad->min_cells);
+}
+
+static int
+panel_widget_get_right_switch_pos (PanelWidget *panel,
+ GList *list)
+{
+ AppletData *ad;
+ AppletData *nad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (list->next)
+ nad = list->next->data;
+
+ if (!nad || nad->constrained >= ad->constrained + ad->min_cells + MOVE_INCREMENT)
+ return ad->constrained + MOVE_INCREMENT;
+
+ if (nad->locked)
+ return panel_widget_get_right_jump_pos (panel,
+ ad,
+ list->next->next,
+ nad->constrained + nad->min_cells);
+
+ return nad->constrained + nad->min_cells - ad->cells;
+}
+
+static gboolean
+panel_widget_try_push_left (PanelWidget *panel,
+ GList *list,
+ int push)
+{
+ AppletData *ad;
+ AppletData *pad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (list->prev)
+ pad = list->prev->data;
+
+ if (ad->locked)
+ return FALSE;
+
+ if (ad->constrained - push < 0)
+ return FALSE;
+
+ if (!pad || pad->constrained + pad->min_cells <= ad->constrained - push)
+ return TRUE;
+
+ return panel_widget_try_push_left (panel, list->prev, push);
+}
+
+static int
+panel_widget_get_left_jump_pos (PanelWidget *panel,
+ AppletData *ad,
+ GList *prev,
+ int pos)
+{
+ AppletData *pad = NULL;
+
+ if (prev)
+ pad = prev->data;
+
+ if (!pad || pad->constrained + pad->min_cells <= pos)
+ return pos;
+
+ if (panel_widget_try_push_left (panel, prev, pad->constrained + pad->min_cells - pos))
+ return pos;
+
+ return panel_widget_get_left_jump_pos (panel,
+ ad,
+ prev->prev,
+ pad->constrained - ad->min_cells);
+}
+
+static int
+panel_widget_get_left_switch_pos (PanelWidget *panel,
+ GList *list)
+{
+ AppletData *ad;
+ AppletData *pad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (list->prev)
+ pad = list->prev->data;
+
+ if (!pad || pad->constrained + pad->min_cells <= ad->constrained - MOVE_INCREMENT)
+ return ad->constrained - MOVE_INCREMENT;
+
+ if (pad->locked)
+ return panel_widget_get_left_jump_pos (panel,
+ ad,
+ list->prev->prev,
+ pad->constrained - ad->min_cells);
+
+ return pad->constrained;
+}
+
+static void
+panel_widget_switch_move (PanelWidget *panel,
+ AppletData *ad,
+ int moveby)
+{
+ GList *list;
+ int finalpos;
+ int pos;
+
+ g_return_if_fail (ad != NULL);
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+ if (moveby == 0)
+ return;
+
+ list = g_list_find (panel->applet_list, ad);
+ g_return_if_fail (list != NULL);
+
+ finalpos = ad->constrained + moveby;
+
+ if (ad->constrained < finalpos) {
+ AppletData *pad;
+
+ if (list->prev) {
+ pad = list->prev->data;
+ if (pad->expand_major)
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ }
+
+ while (ad->constrained < finalpos) {
+ pos = panel_widget_get_right_switch_pos (panel, list);
+
+ if (abs (pos - finalpos) >= abs (ad->constrained - finalpos) ||
+ pos + ad->min_cells > panel->size)
+ break;
+
+ panel_widget_switch_applet_right (panel, list);
+ }
+
+ if (list->prev) {
+ pad = list->prev->data;
+ if (pad->expand_major)
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ }
+ } else {
+ AppletData *nad;
+
+ if (list->next) {
+ nad = list->next->data;
+ if (nad->expand_major)
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ }
+
+ while (ad->constrained > finalpos) {
+ pos = panel_widget_get_left_switch_pos (panel, list);
+
+ if (abs (pos - finalpos) >= abs (ad->constrained - finalpos) || pos < 0)
+ break;
+
+ panel_widget_switch_applet_left (panel, list);
+ }
+
+ }
+}
+
+static int
+panel_widget_push_applet_right (PanelWidget *panel,
+ GList *list,
+ int push)
+{
+ AppletData *ad;
+ AppletData *nad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (ad->constrained + ad->min_cells + push >= panel->size)
+ return FALSE;
+
+ if (ad->locked)
+ return FALSE;
+
+ if (list->next)
+ nad = list->next->data;
+
+ if (!nad || nad->constrained >= ad->constrained + ad->min_cells + push) {
+ ad->pos = ad->constrained += push;
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+ return TRUE;
+ }
+
+ g_assert (list->next != NULL);
+
+ if (!panel_widget_push_applet_right (panel, list->next, push))
+ return FALSE;
+
+ ad->pos = ad->constrained += push;;
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+
+ return TRUE;
+}
+
+static int
+panel_widget_push_applet_left (PanelWidget *panel,
+ GList *list,
+ int push)
+{
+ AppletData *ad;
+ AppletData *pad = NULL;
+
+ g_assert (list != NULL);
+
+ ad = list->data;
+ if (ad->constrained - push < 0)
+ return FALSE;
+
+ if (ad->locked)
+ return FALSE;
+
+ if (list->prev)
+ pad = list->prev->data;
+
+ if (!pad || pad->constrained + pad->min_cells <= ad->constrained - push) {
+ ad->pos = ad->constrained -= push;
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+ return TRUE;
+ }
+
+ g_assert (list->prev != NULL);
+
+ if (!panel_widget_push_applet_left (panel, list->prev, push))
+ return FALSE;
+
+ ad->pos = ad->constrained -= push;
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
+
+ return TRUE;
+}
+
+static void
+panel_widget_push_move (PanelWidget *panel,
+ AppletData *ad,
+ int moveby)
+{
+ AppletData *pad;
+ int finalpos;
+ GList *list;
+
+ g_return_if_fail (ad != NULL);
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+ if (moveby == 0)
+ return;
+
+ list = g_list_find (panel->applet_list, ad);
+ g_return_if_fail (list != NULL);
+
+ finalpos = ad->constrained + moveby;
+
+ if (ad->constrained < finalpos) {
+ while (ad->constrained < finalpos)
+ if (!panel_widget_push_applet_right (panel, list, 1))
+ break;
+
+ if (list->prev) {
+ pad = list->prev->data;
+ if (pad->expand_major)
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+ }
+ } else {
+ while (ad->constrained > finalpos)
+ if (!panel_widget_push_applet_left (panel, list, 1))
+ break;
+ }
+}
+
+
+/*this is a special function and may fail if called improperly, it works
+only under special circumstance when we know there is nothing from
+old_size to panel->size*/
+static void
+panel_widget_right_stick(PanelWidget *panel,int old_size)
+{
+ int i,pos;
+ GList *list,*prev;
+ AppletData *ad;
+
+ g_return_if_fail(PANEL_IS_WIDGET(panel));
+ g_return_if_fail(old_size>=0);
+
+ if(old_size>=panel->size ||
+ panel->packed)
+ return;
+
+ list = get_applet_list_pos(panel,old_size-1);
+
+ if(!list)
+ return;
+
+ pos = panel->size-1;
+
+ ad = list->data;
+ do {
+ i = ad->pos;
+ ad->pos = ad->constrained = pos--;
+ ad->cells = 1;
+ prev = list;
+ list = g_list_previous(list);
+ if(!list)
+ break;
+ ad = list->data;
+ } while(ad->pos + ad->cells == i);
+
+ for (list = prev; list; list = list->next)
+ emit_applet_moved (panel, list->data);
+}
+
+static void
+panel_widget_size_request(GtkWidget *widget, GtkRequisition *requisition)
+{
+ PanelWidget *panel;
+ GList *list;
+ GList *ad_with_hints;
+ gboolean dont_fill;
+
+ g_return_if_fail(PANEL_IS_WIDGET(widget));
+ g_return_if_fail(requisition!=NULL);
+
+ panel = PANEL_WIDGET(widget);
+
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+ requisition->width = 0;
+ requisition->height = panel->sz;
+ } else {
+ requisition->height = 0;
+ requisition->width = panel->sz;
+ }
+
+ ad_with_hints = NULL;
+
+ for(list = panel->applet_list; list!=NULL; list = g_list_next(list)) {
+ AppletData *ad = list->data;
+ GtkRequisition chreq;
+ gtk_widget_size_request(ad->applet,&chreq);
+
+ if (panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+ if (requisition->height < chreq.height && !ad->size_constrained)
+ requisition->height = chreq.height;
+
+ if (panel->packed && ad->expand_major && ad->size_hints)
+ ad_with_hints = g_list_prepend (ad_with_hints,
+ ad);
+
+ else if (panel->packed)
+ requisition->width += chreq.width;
+ } else {
+ if (requisition->width < chreq.width && !ad->size_constrained)
+ requisition->width = chreq.width;
+
+ if (panel->packed && ad->expand_major && ad->size_hints)
+ ad_with_hints = g_list_prepend (ad_with_hints,
+ ad);
+
+ else if (panel->packed)
+ requisition->height += chreq.height;
+ }
+ }
+
+
+ panel->nb_applets_size_hints = 0;
+ if (panel->applets_hints != NULL)
+ g_free (panel->applets_hints);
+ panel->applets_hints = NULL;
+ if (panel->applets_using_hint != NULL)
+ g_free (panel->applets_using_hint);
+ panel->applets_using_hint = NULL;
+
+ if(!panel->packed) {
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+ requisition->width = panel->size;
+ } else {
+ requisition->height = panel->size;
+ }
+ } else {
+ /* put the list in the correct order: this is important
+ * since we'll use this order in the size_allocate() */
+ ad_with_hints = g_list_reverse (ad_with_hints);
+
+ panel->nb_applets_size_hints = g_list_length (ad_with_hints);
+ if (panel->nb_applets_size_hints > 0) {
+ int i;
+ panel->applets_hints = g_new0 (AppletSizeHints, panel->nb_applets_size_hints);
+
+ i = 0;
+ for (list = ad_with_hints;
+ list != NULL;
+ list = g_list_next (list)) {
+ AppletData *ad = list->data;
+
+ panel->applets_hints[i].hints = ad->size_hints;
+ panel->applets_hints[i].len = ad->size_hints_len;
+ i++;
+ }
+
+ panel->applets_using_hint = g_new0 (AppletSizeHintsAlloc, panel->nb_applets_size_hints);
+ }
+ }
+
+ dont_fill = panel->packed && panel->nb_applets_size_hints != 0;
+
+ if (panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+ if (requisition->width < 12 && !dont_fill)
+ requisition->width = 12;
+ if (requisition->height < 12)
+ requisition->height = 12;
+ } else {
+ if (requisition->width < 12)
+ requisition->width = 12;
+ if (requisition->height < 12 && !dont_fill)
+ requisition->height = 12;
+ }
+}
+
+static void
+queue_resize_on_all_applets(PanelWidget *panel)
+{
+ GList *li;
+ for(li = panel->applet_list; li != NULL;
+ li = g_list_next(li)) {
+ AppletData *ad = li->data;
+ gtk_widget_queue_resize (ad->applet);
+ }
+}
+
+static void
+panel_widget_set_background_region (PanelWidget *panel)
+{
+ GtkWidget *widget;
+ int origin_x = -1, origin_y = -1;
+ GtkAllocation allocation;
+
+ widget = GTK_WIDGET (panel);
+
+ if (!gtk_widget_get_realized (widget))
+ return;
+
+ gdk_window_get_origin (gtk_widget_get_window (widget), &origin_x, &origin_y);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ panel_background_change_region (
+ &panel->background, panel->orient,
+ origin_x, origin_y,
+ allocation.width,
+ allocation.height);
+}
+
+static void
+panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
+{
+ PanelWidget *panel;
+ GList *list;
+ int i;
+ int old_size;
+ gboolean ltr;
+
+ g_return_if_fail(PANEL_IS_WIDGET(widget));
+ g_return_if_fail(allocation!=NULL);
+
+ panel = PANEL_WIDGET(widget);
+
+ old_size = panel->size;
+ ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR;
+
+ gtk_widget_set_allocation (widget, allocation);
+ if (gtk_widget_get_realized (widget))
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
+ panel->size = allocation->width;
+ else
+ panel->size = allocation->height;
+ if(old_size<panel->size)
+ panel_widget_right_stick(panel,old_size);
+
+ if (panel->packed) {
+ /* we're assuming the order is the same as the one that was
+ * in size_request() */
+ int applet_using_hint_index = 0;
+
+ i = 0;
+ for(list = panel->applet_list;
+ list!=NULL;
+ list = g_list_next(list)) {
+ AppletData *ad = list->data;
+ GtkAllocation challoc;
+ GtkRequisition chreq;
+ gtk_widget_get_child_requisition(ad->applet,&chreq);
+
+ ad->constrained = i;
+
+ challoc.width = chreq.width;
+ challoc.height = chreq.height;
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+ if (ad->expand_minor)
+ challoc.height = allocation->height;
+
+ if (ad->expand_major && ad->size_hints) {
+ int width = panel->applets_using_hint[applet_using_hint_index].size;
+ applet_using_hint_index++;
+ challoc.width = MIN (width, allocation->width - i);
+ }
+
+ ad->cells = challoc.width;
+ challoc.x = ltr ? ad->constrained : panel->size - ad->constrained - challoc.width;
+ challoc.y = allocation->height / 2 - challoc.height / 2;
+ } else {
+ if (ad->expand_minor)
+ challoc.width = allocation->width;
+
+ if (ad->expand_major && ad->size_hints) {
+ int height = panel->applets_using_hint[applet_using_hint_index].size;
+ applet_using_hint_index++;
+ challoc.height = MIN (height, allocation->height - i);
+ }
+
+ ad->cells = challoc.height;
+ challoc.x = allocation->width / 2 - challoc.width / 2;
+ challoc.y = ad->constrained;
+ }
+ ad->min_cells = ad->cells;
+ gtk_widget_size_allocate(ad->applet,&challoc);
+ i += ad->cells;
+ }
+
+ /* EEEEK, there might be not enough room and we don't handle
+ * it: all the applets at the right well be unusable */
+
+ } else { /*not packed*/
+
+ /* First make sure there's enough room on the left */
+ i = 0;
+ for (list = panel->applet_list;
+ list != NULL;
+ list = g_list_next (list)) {
+ AppletData *ad = list->data;
+ GtkRequisition chreq;
+
+ gtk_widget_get_child_requisition(ad->applet,&chreq);
+
+ if (!ad->expand_major || !ad->size_hints) {
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
+ ad->cells = chreq.width;
+ else
+ ad->cells = chreq.height;
+
+ ad->min_cells = ad->cells;
+ } else {
+ ad->cells = ad->size_hints [ad->size_hints_len - 1];
+ ad->min_cells = ad->size_hints [ad->size_hints_len - 1];
+ }
+
+ ad->constrained = ad->pos;
+
+ if (ad->constrained < i)
+ ad->constrained = i;
+
+ i = ad->constrained + ad->cells;
+ }
+
+ /* Now expand from the right */
+ i = panel->size;
+ for(list = g_list_last(panel->applet_list);
+ list!=NULL;
+ list = g_list_previous(list)) {
+ AppletData *ad = list->data;
+ int cells;
+
+ if (ad->constrained + ad->min_cells > i)
+ ad->constrained = MAX (i - ad->min_cells, 0);
+
+ if (ad->expand_major) {
+ cells = (i - ad->constrained) - 1;
+
+ if (ad->size_hints)
+ cells = get_size_from_hints (ad, cells);
+ cells = MAX (cells, ad->min_cells);
+ cells = MIN (cells, panel->size);
+
+ ad->cells = cells;
+ }
+
+ i = ad->constrained;
+ }
+
+ /* EEEEK, there's not enough room, so shift applets even
+ * at the expense of perhaps running out of room on the
+ * right if there is no free space in the middle */
+ if(i < 0) {
+ i = 0;
+ for(list = panel->applet_list;
+ list!=NULL;
+ list = g_list_next(list)) {
+ AppletData *ad = list->data;
+
+ if (ad->constrained < i)
+ ad->constrained = i;
+
+ i = ad->constrained + ad->cells;
+ }
+ }
+
+ for(list = panel->applet_list;
+ list!=NULL;
+ list = g_list_next(list)) {
+ AppletData *ad = list->data;
+ GtkAllocation challoc;
+ GtkRequisition chreq;
+ gtk_widget_get_child_requisition(ad->applet,&chreq);
+ challoc.width = chreq.width;
+ challoc.height = chreq.height;
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+ challoc.width = ad->cells;
+ if (ad->expand_minor) {
+ challoc.height = allocation->height;
+ }
+ challoc.x = ltr ? ad->constrained : panel->size - ad->constrained - challoc.width;
+ challoc.y = allocation->height / 2 - challoc.height / 2;
+ } else {
+ challoc.height = ad->cells;
+ if (ad->expand_minor) {
+ challoc.width = allocation->width;
+ }
+ challoc.x = allocation->width / 2 - challoc.width / 2;
+ challoc.y = ad->constrained;
+ }
+
+ gtk_widget_size_allocate(ad->applet,&challoc);
+ }
+ }
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
+ panel->thick = allocation->height;
+ else
+ panel->thick = allocation->width;
+
+ panel_widget_set_background_region (panel);
+}
+
+gboolean
+panel_widget_is_cursor(PanelWidget *panel, int overlap)
+{
+ GtkWidget *widget;
+ GtkAllocation allocation;
+ int x,y;
+ int w,h;
+
+ g_return_val_if_fail(PANEL_IS_WIDGET(panel),FALSE);
+
+ widget = panel->drop_widget;
+
+ if(!widget ||
+ !GTK_IS_WIDGET(widget) ||
+ !gtk_widget_get_visible(widget))
+ return FALSE;
+
+ gtk_widget_get_pointer(widget, &x, &y);
+
+ gtk_widget_get_allocation (widget, &allocation);
+ w = allocation.width;
+ h = allocation.height;
+
+ if((x+overlap)>=0 &&
+ (x-overlap)<=w &&
+ (y+overlap)>=0 &&
+ (y-overlap)<=h)
+ return TRUE;
+ return FALSE;
+}
+
+static void
+panel_widget_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ GtkStyle *style;
+ GtkStateType state;
+
+ if (gtk_widget_get_realized (widget)) {
+ style = gtk_widget_get_style (widget);
+ state = gtk_widget_get_state (widget);
+
+ panel_background_set_default_style (
+ &PANEL_WIDGET (widget)->background,
+ &style->bg [state],
+ style->bg_pixmap [state]);
+ }
+}
+
+static void
+panel_widget_state_changed (GtkWidget *widget,
+ GtkStateType previous_state)
+{
+ GtkStyle *style;
+ GtkStateType state;
+
+ if (gtk_widget_get_realized (widget)) {
+ style = gtk_widget_get_style (widget);
+ state = gtk_widget_get_state (widget);
+
+ panel_background_set_default_style (
+ &PANEL_WIDGET (widget)->background,
+ &style->bg [state],
+ style->bg_pixmap [state]);
+ }
+}
+
+static gboolean
+toplevel_configure_event (GtkWidget *widget,
+ GdkEventConfigure *event,
+ PanelWidget *panel)
+{
+ panel_widget_set_background_region (panel);
+
+ return FALSE;
+}
+
+static void
+panel_widget_realize (GtkWidget *widget)
+{
+ PanelWidget *panel = (PanelWidget *) widget;
+ GdkWindow *window;
+ GtkStyle *style;
+ GtkStateType state;
+
+ g_signal_connect (panel->toplevel, "configure-event",
+ G_CALLBACK (toplevel_configure_event), panel);
+
+ GTK_WIDGET_CLASS (panel_widget_parent_class)->realize (widget);
+
+ window = gtk_widget_get_window (widget);
+ style = gtk_widget_get_style (widget);
+ state = gtk_widget_get_state (widget);
+
+ /* For auto-hidden panels with a colored background, we need native
+ * windows to avoid some uglyness on unhide */
+ gdk_window_ensure_native (window);
+
+ panel_background_set_default_style (
+ &panel->background,
+ &style->bg [state],
+ style->bg_pixmap [state]);
+
+ panel_background_realized (&panel->background, window);
+}
+
+static void
+panel_widget_unrealize (GtkWidget *widget)
+{
+ PanelWidget *panel = (PanelWidget *) widget;
+
+ panel_background_unrealized (&panel->background);
+
+ g_signal_handlers_disconnect_by_func (
+ panel->toplevel,
+ G_CALLBACK (toplevel_configure_event),
+ panel);
+
+ GTK_WIDGET_CLASS (panel_widget_parent_class)->unrealize (widget);
+}
+
+static void
+panel_widget_finalize (GObject *obj)
+{
+ PanelWidget *panel;
+
+ g_return_if_fail (PANEL_IS_WIDGET (obj));
+
+ panel = PANEL_WIDGET (obj);
+
+ panel_background_free (&panel->background);
+
+ if (panel->applets_hints != NULL)
+ g_free (panel->applets_hints);
+ panel->applets_hints = NULL;
+ if (panel->applets_using_hint != NULL)
+ g_free (panel->applets_using_hint);
+ panel->applets_using_hint = NULL;
+
+
+ G_OBJECT_CLASS (panel_widget_parent_class)->finalize (obj);
+}
+
+static void
+panel_widget_open_dialog_destroyed (PanelWidget *panel_widget,
+ GtkWidget *dialog)
+{
+ g_return_if_fail (panel_widget->open_dialogs != NULL);
+
+ panel_widget->open_dialogs = g_slist_remove (panel_widget->open_dialogs, dialog);
+}
+
+static void
+panel_widget_destroy_open_dialogs (PanelWidget *panel_widget)
+{
+ GSList *l, *list;
+
+ list = panel_widget->open_dialogs;
+ panel_widget->open_dialogs = NULL;
+
+ for (l = list; l; l = l->next) {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
+ G_CALLBACK (panel_widget_open_dialog_destroyed),
+ panel_widget);
+ gtk_widget_destroy (l->data);
+ }
+ g_slist_free (list);
+
+}
+
+static void
+panel_widget_destroy (GtkObject *obj)
+{
+ PanelWidget *panel;
+
+ g_return_if_fail (PANEL_IS_WIDGET (obj));
+
+ panel = PANEL_WIDGET (obj);
+
+ panels = g_slist_remove (panels, panel);
+
+ panel_widget_destroy_open_dialogs (panel);
+
+ if (panel->master_widget != NULL) {
+ g_object_set_data (G_OBJECT (panel->master_widget),
+ MATE_PANEL_APPLET_ASSOC_PANEL_KEY,
+ NULL);
+ g_object_remove_weak_pointer (G_OBJECT (panel->master_widget),
+ (gpointer *) &panel->master_widget);
+ panel->master_widget = NULL;
+ }
+
+ if (GTK_OBJECT_CLASS (panel_widget_parent_class)->destroy)
+ GTK_OBJECT_CLASS (panel_widget_parent_class)->destroy (obj);
+}
+
+static void
+panel_widget_init (PanelWidget *panel)
+{
+ GtkWidget *widget = (GtkWidget *) panel;
+
+ gtk_widget_set_events (
+ widget,
+ gtk_widget_get_events (widget) | GDK_BUTTON_RELEASE_MASK);
+
+ panel->packed = FALSE;
+ panel->orient = GTK_ORIENTATION_HORIZONTAL;
+ panel->thick = PANEL_MINIMUM_WIDTH;
+ panel->size = G_MAXINT;
+ panel->applet_list = NULL;
+ panel->master_widget = NULL;
+ panel->drop_widget = widget;
+ panel->open_dialogs = NULL;
+
+ panel->nb_applets_size_hints = 0;
+ panel->applets_hints = NULL;
+ panel->applets_using_hint = NULL;
+
+ panel_background_init (&panel->background,
+ (PanelBackgroundChangedNotify) panel_widget_background_changed,
+ panel);
+
+ panels = g_slist_append (panels, panel);
+}
+
+GtkWidget *
+panel_widget_new (PanelToplevel *toplevel,
+ gboolean packed,
+ GtkOrientation orient,
+ int sz)
+{
+ PanelWidget *panel;
+
+ panel = g_object_new (PANEL_TYPE_WIDGET, NULL);
+
+ gtk_widget_set_has_window (GTK_WIDGET (panel), TRUE);
+ gtk_widget_set_can_focus (GTK_WIDGET (panel), TRUE);
+
+ panel->orient = orient;
+ panel->sz = sz;
+
+ panel->packed = packed;
+ if (packed)
+ panel->size = 0;
+ else
+ panel->size = G_MAXINT;
+
+ panel->toplevel = toplevel;
+ panel->drop_widget = GTK_WIDGET (toplevel);
+
+ return GTK_WIDGET (panel);
+}
+
+static guint moving_timeout = 0;
+static gboolean been_moved = FALSE;
+static gboolean repeat_if_outside = FALSE;
+
+static gboolean
+panel_widget_applet_drag_start_no_grab (PanelWidget *panel,
+ GtkWidget *applet,
+ int drag_off)
+{
+ AppletData *ad;
+ AppletInfo *info;
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), FALSE);
+ g_return_val_if_fail (GTK_IS_WIDGET (panel), FALSE);
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ g_return_val_if_fail (ad != NULL, FALSE);
+
+ if (ad->locked)
+ return FALSE;
+
+ /* Check if we can actually move this object in the
+ configuration */
+ info = g_object_get_data (G_OBJECT (applet), "applet_info");
+ if (info != NULL &&
+ ! mate_panel_applet_can_freely_move (info))
+ return FALSE;
+
+ if (moving_timeout != 0) {
+ g_source_remove (moving_timeout);
+ moving_timeout = 0;
+ been_moved = FALSE;
+ }
+
+#ifdef PANEL_WIDGET_DEBUG
+ g_message("Starting drag on a %s at %p\n",
+ g_type_name(G_TYPE_FROM_INSTANCE (applet)), applet);
+#endif
+ panel->currently_dragged_applet = ad;
+ if (drag_off == PW_DRAG_OFF_CURSOR)
+ ad->drag_off = panel_widget_get_cursorloc (panel) - ad->constrained;
+ else if (drag_off == PW_DRAG_OFF_CENTER)
+ ad->drag_off = ad->cells / 2;
+ else
+ ad->drag_off = drag_off;
+
+ add_all_move_bindings (panel);
+
+ mate_panel_applet_in_drag = TRUE;
+
+ return TRUE;
+}
+
+
+static void
+panel_widget_applet_drag_end_no_grab (PanelWidget *panel)
+{
+ g_return_if_fail (panel != NULL);
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+#ifdef PANEL_WIDGET_DEBUG
+ g_message("Ending drag\n");
+#endif
+ panel->currently_dragged_applet = NULL;
+ mate_panel_applet_in_drag = FALSE;
+
+ remove_all_move_bindings (panel);
+ if (moving_timeout != 0) {
+ g_source_remove (moving_timeout);
+ moving_timeout = 0;
+ been_moved = FALSE;
+ }
+}
+
+void
+panel_widget_applet_drag_start (PanelWidget *panel,
+ GtkWidget *applet,
+ int drag_off,
+ guint32 time_)
+{
+ GdkWindow *window;
+
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+ g_return_if_fail (GTK_IS_WIDGET (applet));
+
+#ifdef PANEL_WIDGET_DEBUG
+ g_message("Starting drag [grabbed] on a %s at %p\n",
+ g_type_name(G_TYPE_FROM_INSTANCE(applet)), applet);
+#endif
+
+ if (!panel_widget_applet_drag_start_no_grab (panel, applet, drag_off))
+ return;
+
+ panel_toplevel_push_autohide_disabler (panel->toplevel);
+
+ gtk_grab_add (applet);
+
+ window = gtk_widget_get_window (applet);
+ if (window) {
+ GdkGrabStatus status;
+ GdkCursor *fleur_cursor;
+
+ fleur_cursor = gdk_cursor_new (GDK_FLEUR);
+
+ status = gdk_pointer_grab (window, FALSE,
+ APPLET_EVENT_MASK, NULL,
+ fleur_cursor, time_);
+
+ gdk_cursor_unref (fleur_cursor);
+ gdk_flush ();
+
+ if (status != GDK_GRAB_SUCCESS) {
+ g_warning (G_STRLOC ": failed to grab pointer (errorcode: %d)",
+ status);
+ panel_widget_applet_drag_end (panel);
+ }
+ }
+}
+
+void
+panel_widget_applet_drag_end (PanelWidget *panel)
+{
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+ if (panel->currently_dragged_applet == NULL)
+ return;
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ gtk_grab_remove (panel->currently_dragged_applet->applet);
+ panel_widget_applet_drag_end_no_grab (panel);
+ panel_toplevel_pop_autohide_disabler (panel->toplevel);
+ gdk_flush ();
+}
+
+/*get pos of the cursor location in panel coordinates*/
+int
+panel_widget_get_cursorloc (PanelWidget *panel)
+{
+ int x, y;
+ gboolean rtl;
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
+
+ gtk_widget_get_pointer (GTK_WIDGET (panel), &x, &y);
+ rtl = gtk_widget_get_direction (GTK_WIDGET (panel)) == GTK_TEXT_DIR_RTL;
+
+ if (panel->orient == GTK_ORIENTATION_HORIZONTAL)
+ return (rtl ? panel->size - x : x);
+ else
+ return y;
+}
+
+/*calculates the value to move the applet by*/
+static int
+panel_widget_get_moveby (PanelWidget *panel, int pos, int offset)
+{
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
+
+ return panel_widget_get_cursorloc (panel) - offset - pos;
+}
+
+static GList *
+walk_up_to (int pos, GList *list)
+{
+ AppletData *ad;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ ad = list->data;
+
+ if (ad->constrained <= pos &&
+ ad->constrained + ad->cells > pos)
+ return list;
+ while (list->next != NULL &&
+ ad->constrained + ad->cells <= pos) {
+ list = list->next;
+ ad = list->data;
+ }
+ while (list->prev != NULL &&
+ ad->constrained > pos) {
+ list = list->prev;
+ ad = list->data;
+ }
+ return list;
+}
+
+static GtkWidget *
+is_in_applet (int pos, AppletData *ad)
+{
+ g_return_val_if_fail (ad != NULL, NULL);
+
+ if (ad->constrained <= pos &&
+ ad->constrained + ad->min_cells > pos)
+ return ad->applet;
+ return NULL;
+}
+
+static int
+panel_widget_get_free_spot (PanelWidget *panel,
+ AppletData *ad,
+ int place)
+{
+ int i, e;
+ int start;
+ int right = -1, left = -1;
+ GList *list;
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
+ g_return_val_if_fail (ad != NULL, -1);
+
+ if (ad->constrained >= panel->size)
+ return -1;
+
+ if (panel->applet_list == NULL) {
+ if (place + ad->min_cells > panel->size)
+ return panel->size-ad->min_cells;
+ else
+ return place;
+ }
+
+ list = panel->applet_list;
+
+ start = place - ad->drag_off;
+ if (start < 0)
+ start = 0;
+ for (e = 0, i = start; i < panel->size; i++) {
+ GtkWidget *applet;
+ list = walk_up_to (i, list);
+ applet = is_in_applet (i, list->data);
+ if (applet == NULL ||
+ applet == ad->applet) {
+ e++;
+ if (e >= ad->min_cells) {
+ right = i - e + 1;
+ break;
+ }
+ } else {
+ e = 0;
+ }
+ }
+
+ start = place + ad->drag_off;
+ if (start >= panel->size)
+ start = panel->size - 1;
+ for (e = 0, i = start; i >= 0; i--) {
+ GtkWidget *applet;
+ list = walk_up_to (i, list);
+ applet = is_in_applet (i, list->data);
+ if (applet == NULL ||
+ applet == ad->applet) {
+ e++;
+ if (e >= ad->min_cells) {
+ left = i;
+ break;
+ }
+ } else {
+ e=0;
+ }
+ }
+
+ start = place - ad->drag_off;
+
+ if (left == -1) {
+ if (right == -1)
+ return -1;
+ else
+ return right;
+ } else {
+ if (right == -1)
+ return left;
+ else
+ return abs (left - start) > abs (right - start) ?
+ right : left;
+ }
+}
+
+static void
+panel_widget_nice_move (PanelWidget *panel,
+ AppletData *ad,
+ int pos)
+{
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+ g_return_if_fail (ad != NULL);
+
+ pos = panel_widget_get_free_spot (panel, ad, pos);
+ if (pos < 0 || pos == ad->pos)
+ return;
+
+ ad->pos = ad->constrained = pos;
+
+ panel->applet_list =
+ panel_g_list_resort_item (panel->applet_list, ad,
+ (GCompareFunc)applet_data_compare);
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ emit_applet_moved (panel, ad);
+}
+
+/* schedule to run the below function */
+static void schedule_try_move (PanelWidget *panel, gboolean repeater);
+
+/*find the cursor position and move the applet to that position*/
+static void
+panel_widget_applet_move_to_cursor (PanelWidget *panel)
+{
+ int moveby;
+ int pos;
+ int movement;
+ GtkWidget *applet;
+ GSList *forb;
+ GdkModifierType mods;
+ AppletData *ad;
+
+ g_return_if_fail(PANEL_IS_WIDGET(panel));
+
+ if (panel->currently_dragged_applet == NULL)
+ return;
+
+ ad = panel->currently_dragged_applet;
+
+ pos = ad->constrained;
+
+ applet = ad->applet;
+ g_assert(GTK_IS_WIDGET(applet));
+ forb = g_object_get_data (G_OBJECT(applet),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS);
+
+ if(!panel_widget_is_cursor(panel,10)) {
+ GSList *list;
+
+ for(list=panels;
+ list!=NULL;
+ list=g_slist_next(list)) {
+ PanelWidget *new_panel =
+ PANEL_WIDGET(list->data);
+
+ if (panel != new_panel &&
+ panel_widget_is_cursor (new_panel,10) &&
+ panel_screen_from_panel_widget (panel) ==
+ panel_screen_from_panel_widget (new_panel) &&
+ !g_slist_find (forb, new_panel) &&
+ !panel_lockdown_get_locked_down ()) {
+ pos = panel_widget_get_moveby (new_panel, 0, ad->drag_off);
+
+ if (pos < 0) pos = 0;
+
+ panel_widget_applet_drag_end (panel);
+
+ /*disable reentrancy into this function*/
+ if (!panel_widget_reparent (panel, new_panel, applet, pos)) {
+ panel_widget_applet_drag_start (
+ panel, applet, ad->drag_off, GDK_CURRENT_TIME);
+ continue;
+ }
+
+ panel_widget_applet_drag_start (
+ new_panel, applet, ad->drag_off, GDK_CURRENT_TIME);
+ schedule_try_move (new_panel, TRUE);
+
+ return;
+ }
+ }
+ }
+
+ gdk_window_get_pointer(gtk_widget_get_window (GTK_WIDGET(panel)),
+ NULL,NULL,&mods);
+
+ movement = PANEL_SWITCH_MOVE;
+
+ if (panel->packed) {
+ movement = PANEL_SWITCH_MOVE;
+ } else {
+ if (mods & GDK_CONTROL_MASK)
+ movement = PANEL_SWITCH_MOVE;
+ else if (mods & GDK_SHIFT_MASK)
+ movement = PANEL_PUSH_MOVE;
+ else if (mods & GDK_MOD1_MASK)
+ movement = PANEL_FREE_MOVE;
+ }
+
+ switch (movement) {
+ case PANEL_SWITCH_MOVE:
+ moveby = panel_widget_get_moveby (panel, pos, ad->drag_off);
+ panel_widget_switch_move (panel, ad, moveby);
+ break;
+ case PANEL_FREE_MOVE:
+ panel_widget_nice_move (panel, ad, panel_widget_get_cursorloc (panel));
+ break;
+ case PANEL_PUSH_MOVE:
+ moveby = panel_widget_get_moveby (panel, pos, ad->drag_off);
+ panel_widget_push_move (panel, ad, moveby);
+ break;
+ }
+}
+
+static int
+move_timeout_handler(gpointer data)
+{
+ PanelWidget *panel = data;
+
+ g_return_val_if_fail(PANEL_IS_WIDGET(data),FALSE);
+
+ if(been_moved &&
+ panel->currently_dragged_applet) {
+ panel_widget_applet_move_to_cursor(panel);
+ been_moved = FALSE;
+ return TRUE;
+ }
+ been_moved = FALSE;
+
+ if(panel->currently_dragged_applet && repeat_if_outside) {
+ GtkWidget *widget;
+ GtkAllocation allocation;
+ int x,y;
+ int w,h;
+
+ widget = panel->currently_dragged_applet->applet;
+
+ gtk_widget_get_pointer(widget, &x, &y);
+
+ gtk_widget_get_allocation (widget, &allocation);
+ w = allocation.width;
+ h = allocation.height;
+
+ /* if NOT inside return TRUE, this means we will be
+ * kept inside the timeout until we hit the damn widget
+ * or the drag ends */
+ if(!(x>=0 && x<=w && y>=0 && y<=h))
+ return TRUE;
+ }
+
+ moving_timeout = 0;
+
+ return FALSE;
+}
+
+static void
+schedule_try_move(PanelWidget *panel, gboolean repeater)
+{
+ if (!panel->currently_dragged_applet)
+ return;
+ repeat_if_outside = repeater;
+ if(moving_timeout == 0) {
+ been_moved = FALSE;
+ panel_widget_applet_move_to_cursor(panel);
+ moving_timeout =
+ g_timeout_add (50, move_timeout_handler, panel);
+ } else
+ been_moved = TRUE;
+}
+
+static gboolean
+panel_widget_applet_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkWidget *parent;
+ PanelWidget *panel;
+ guint32 event_time;
+
+ parent = gtk_widget_get_parent (widget);
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
+
+ panel = PANEL_WIDGET (parent);
+
+ /* don't propagate this event */
+ if (panel->currently_dragged_applet) {
+ g_signal_stop_emission (G_OBJECT (widget),
+ g_signal_lookup ("button-press-event",
+ G_OBJECT_TYPE (widget)),
+ 0);
+ return TRUE;
+ }
+
+ /* Begin drag if the middle mouse button is pressed, unless the panel
+ * is locked down or a grab is active (meaning a menu is open) */
+ if (panel_lockdown_get_locked_down () || event->button != 2 ||
+ gtk_grab_get_current() != NULL)
+ return FALSE;
+
+ /* time on sent events seems to be bogus */
+ event_time = event->time;
+ if (event->send_event)
+ event_time = GDK_CURRENT_TIME;
+
+ panel_widget_applet_drag_start (panel, widget, PW_DRAG_OFF_CURSOR, event_time);
+
+ return TRUE;
+}
+
+static gboolean
+panel_widget_applet_button_release_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkWidget *parent;
+ PanelWidget *panel;
+
+ parent = gtk_widget_get_parent (widget);
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
+
+ panel = PANEL_WIDGET (parent);
+
+ /* don't propagate this event */
+ if (panel->currently_dragged_applet) {
+ g_signal_stop_emission (G_OBJECT (widget),
+ g_signal_lookup ("button-release-event",
+ G_OBJECT_TYPE (widget)),
+ 0);
+ panel_widget_applet_drag_end (panel);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+panel_widget_applet_motion_notify_event (GtkWidget *widget,
+ GdkEvent *event)
+{
+ GtkWidget *parent;
+ PanelWidget *panel;
+
+ parent = gtk_widget_get_parent (widget);
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
+
+ if (gdk_event_get_screen (event) != gtk_widget_get_screen (widget))
+ return FALSE;
+
+ panel = PANEL_WIDGET (parent);
+
+ schedule_try_move (panel, FALSE);
+
+ return FALSE;
+}
+
+static gboolean
+panel_widget_applet_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkWidget *parent;
+ PanelWidget *panel;
+
+ parent = gtk_widget_get_parent (widget);
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
+
+ panel = PANEL_WIDGET (parent);
+
+ if (!mate_panel_applet_in_drag)
+ return FALSE;
+
+ return gtk_bindings_activate (GTK_OBJECT (panel),
+ ((GdkEventKey *)event)->keyval,
+ ((GdkEventKey *)event)->state);
+}
+
+static int
+panel_sub_event_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ g_return_val_if_fail(GTK_IS_WIDGET(widget),FALSE);
+ g_return_val_if_fail(event!=NULL,FALSE);
+
+ switch (event->type) {
+ /*pass these to the parent!*/
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_MOTION_NOTIFY: {
+ GdkEventButton *bevent = (GdkEventButton *)event;
+
+ if (bevent->button != 1 || mate_panel_applet_in_drag)
+ return gtk_widget_event (data, event);
+
+ }
+ break;
+ case GDK_KEY_PRESS:
+ if (mate_panel_applet_in_drag)
+ return gtk_widget_event(data, event);
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static void
+bind_applet_events(GtkWidget *widget, gpointer data)
+{
+ g_return_if_fail(GTK_IS_WIDGET(widget));
+
+ /* XXX: This is more or less a hack. We need to be able to
+ * capture events over applets so that we can drag them with
+ * the mouse and such. So we need to force the applet's
+ * widgets to recursively send the events back to their parent
+ * until the event gets to the applet wrapper (the
+ * GtkEventBox) for processing by us.
+ */
+
+ if (gtk_widget_get_has_window (widget))
+ g_signal_connect (G_OBJECT(widget), "event",
+ G_CALLBACK (panel_sub_event_handler),
+ data);
+
+ if (GTK_IS_CONTAINER(widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ bind_applet_events, data);
+}
+
+static void
+panel_widget_applet_destroy (GtkWidget *applet, gpointer data)
+{
+ AppletData *ad;
+ GtkWidget *parent;
+
+ g_return_if_fail (GTK_IS_WIDGET (applet));
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ g_object_set_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA, NULL);
+
+ parent = gtk_widget_get_parent (applet);
+ /*if it wasn't yet removed*/
+ if(parent) {
+ PanelWidget *panel = PANEL_WIDGET (parent);
+
+ if (panel->currently_dragged_applet == ad)
+ panel_widget_applet_drag_end (panel);
+
+ panel->applet_list = g_list_remove (panel->applet_list,ad);
+ }
+
+ g_free (ad->size_hints);
+
+ g_free (ad);
+}
+
+static void
+bind_top_applet_events (GtkWidget *widget)
+{
+ g_return_if_fail(GTK_IS_WIDGET(widget));
+
+ g_signal_connect (G_OBJECT(widget), "destroy",
+ G_CALLBACK (panel_widget_applet_destroy),
+ NULL);
+
+ g_signal_connect (widget, "button-press-event",
+ G_CALLBACK (panel_widget_applet_button_press_event),
+ NULL);
+
+ g_signal_connect (widget, "button-release-event",
+ G_CALLBACK (panel_widget_applet_button_release_event),
+ NULL);
+ g_signal_connect (widget, "motion-notify-event",
+ G_CALLBACK (panel_widget_applet_motion_notify_event),
+ NULL);
+ g_signal_connect (widget, "key-press-event",
+ G_CALLBACK (panel_widget_applet_key_press_event),
+ NULL);
+
+ /* XXX: This is more or less a hack. We need to be able to
+ * capture events over applets so that we can drag them with
+ * the mouse and such. So we need to force the applet's
+ * widgets to recursively send the events back to their parent
+ * until the event gets to the applet wrapper (the
+ * GtkEventBox) for processing by us.
+ */
+
+ if (GTK_IS_CONTAINER(widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ bind_applet_events, widget);
+}
+
+static int
+panel_widget_find_empty_pos(PanelWidget *panel, int pos)
+{
+ int i;
+ int right=-1,left=-1;
+ GList *list;
+
+ g_return_val_if_fail(PANEL_IS_WIDGET(panel),-1);
+
+ if(pos>=panel->size)
+ pos = panel->size-1;
+
+ if (pos <= 0)
+ pos = 0;
+
+ if(!panel->applet_list)
+ return pos;
+
+ list = panel->applet_list;
+
+ for (i = pos; i < panel->size; i++) {
+ list = walk_up_to (i, list);
+ if ( ! is_in_applet (i, list->data)) {
+ right = i;
+ break;
+ }
+ }
+
+ for(i = pos; i >= 0; i--) {
+ list = walk_up_to (i, list);
+ if ( ! is_in_applet (i, list->data)) {
+ left = i;
+ break;
+ }
+ }
+
+ if (left == -1) {
+ if (right == -1)
+ return -1;
+ else
+ return right;
+ } else {
+ if (right == -1)
+ return left;
+ else
+ return abs (left - pos) > abs (right - pos) ?
+ right : left;
+ }
+}
+
+void
+panel_widget_add_forbidden (PanelWidget *panel)
+{
+ g_return_if_fail (panel != NULL);
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+ add_panel_to_forbidden (panel, panel);
+}
+
+int
+panel_widget_add (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean locked,
+ int pos,
+ gboolean insert_at_pos)
+{
+ AppletData *ad = NULL;
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
+ g_return_val_if_fail (GTK_IS_WIDGET (applet), -1);
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+
+ if (ad != NULL)
+ pos = ad->pos;
+
+ if (!insert_at_pos || pos < 0) {
+ if (panel->packed) {
+ if (get_applet_list_pos (panel, pos))
+ /*this is a slight hack so that this applet
+ is inserted AFTER an applet with this pos
+ number*/
+ pos++;
+ } else {
+ int newpos = panel_widget_find_empty_pos (panel, pos);
+ if (newpos >= 0)
+ pos = newpos;
+ else if (get_applet_list_pos (panel, pos))
+ /*this is a slight hack so that this applet
+ is inserted AFTER an applet with this pos
+ number*/
+ pos++;
+ }
+ }
+
+ if(pos==-1) return -1;
+
+ if (ad == NULL) {
+ ad = g_new (AppletData, 1);
+ ad->applet = applet;
+ ad->cells = 1;
+ ad->min_cells = 1;
+ ad->pos = pos;
+ ad->constrained = pos;
+ ad->drag_off = 0;
+ ad->no_die = 0;
+ ad->size_constrained = FALSE;
+ ad->expand_major = FALSE;
+ ad->expand_minor = FALSE;
+ ad->locked = locked;
+ ad->size_hints = NULL;
+ g_object_set_data (G_OBJECT (applet),
+ MATE_PANEL_APPLET_DATA, ad);
+
+ /*this is a completely new applet, which was not yet bound*/
+ bind_top_applet_events (applet);
+ }
+
+ panel->applet_list =
+ g_list_insert_sorted(panel->applet_list,ad,
+ (GCompareFunc)applet_data_compare);
+
+ /*this will get done right on size allocate!*/
+ if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
+ gtk_fixed_put(GTK_FIXED(panel),applet,
+ pos,0);
+ else
+ gtk_fixed_put(GTK_FIXED(panel),applet,
+ 0,pos);
+
+
+ gtk_widget_queue_resize(GTK_WIDGET(panel));
+
+ g_signal_emit (G_OBJECT(panel),
+ panel_widget_signals[APPLET_ADDED_SIGNAL],
+ 0, applet);
+
+ /*NOTE: forbidden list is not updated on addition, use the
+ function above for the panel*/
+
+ return pos;
+}
+
+gboolean
+panel_widget_reparent (PanelWidget *old_panel,
+ PanelWidget *new_panel,
+ GtkWidget *applet,
+ int pos)
+{
+ AppletData *ad;
+ GtkWidget *focus_widget = NULL;
+ AppletInfo* info;
+
+ g_return_val_if_fail(PANEL_IS_WIDGET(old_panel), FALSE);
+ g_return_val_if_fail(PANEL_IS_WIDGET(new_panel), FALSE);
+ g_return_val_if_fail(GTK_IS_WIDGET(applet), FALSE);
+ g_return_val_if_fail(pos>=0, FALSE);
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ g_return_val_if_fail(ad!=NULL, FALSE);
+
+ /* Don't try and reparent to an explicitly hidden panel,
+ * very confusing for the user ...
+ */
+ if (panel_toplevel_get_is_hidden (new_panel->toplevel))
+ return FALSE;
+
+ info = g_object_get_data (G_OBJECT (ad->applet), "applet_info");
+
+ ad->pos = ad->constrained = panel_widget_get_free_spot (new_panel, ad, pos);
+ if (ad->pos == -1)
+ ad->pos = ad->constrained = 0;
+
+ gtk_widget_queue_resize (GTK_WIDGET (new_panel));
+ gtk_widget_queue_resize (GTK_WIDGET (old_panel));
+
+ ad->no_die++;
+
+ panel_widget_reset_saved_focus (old_panel);
+ if (gtk_container_get_focus_child (GTK_CONTAINER (old_panel)) == applet)
+ focus_widget = gtk_window_get_focus (GTK_WINDOW (old_panel->toplevel));
+ gtk_widget_reparent (applet, GTK_WIDGET (new_panel));
+
+ if (info && info->type == PANEL_OBJECT_APPLET)
+ mate_panel_applet_frame_set_panel (MATE_PANEL_APPLET_FRAME (ad->applet), new_panel);
+
+ if (gtk_widget_get_can_focus (GTK_WIDGET (new_panel)))
+ gtk_widget_set_can_focus (GTK_WIDGET (new_panel), FALSE);
+ if (focus_widget) {
+ panel_widget_force_grab_focus (focus_widget);
+ } else {
+ gboolean return_val;
+
+ g_signal_emit_by_name (applet, "focus",
+ GTK_DIR_TAB_FORWARD,
+ &return_val);
+ }
+ gtk_window_present (GTK_WINDOW (new_panel->toplevel));
+
+ gdk_flush();
+
+ ad->no_die--;
+
+ emit_applet_moved (new_panel, ad);
+
+ return TRUE;
+}
+
+void
+panel_widget_set_packed (PanelWidget *panel_widget,
+ gboolean packed)
+{
+ panel_widget->packed = packed;
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel_widget));
+}
+
+void
+panel_widget_set_orientation (PanelWidget *panel_widget,
+ GtkOrientation orientation)
+{
+ panel_widget->orient = orientation;
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel_widget));
+}
+
+void
+panel_widget_set_size (PanelWidget *panel_widget,
+ int size)
+{
+ g_return_if_fail (PANEL_IS_WIDGET (panel_widget));
+
+ if (size == panel_widget->sz)
+ return;
+
+ panel_widget->sz = size;
+
+ queue_resize_on_all_applets (panel_widget);
+
+ g_signal_emit (panel_widget, panel_widget_signals [SIZE_CHANGE_SIGNAL], 0);
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel_widget));
+}
+
+static void
+panel_widget_background_changed (PanelBackground *background,
+ PanelWidget *panel)
+{
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+ panel_toplevel_update_edges (panel->toplevel);
+ g_signal_emit (G_OBJECT (panel),
+ panel_widget_signals [BACK_CHANGE_SIGNAL],
+ 0);
+}
+
+static void
+panel_widget_push_move_applet (PanelWidget *panel,
+ GtkDirectionType dir)
+{
+ AppletData *applet;
+ int increment = 0;
+
+ applet = panel->currently_dragged_applet;
+ g_return_if_fail (applet);
+
+ switch (dir) {
+ case GTK_DIR_LEFT:
+ case GTK_DIR_UP:
+ increment = -MOVE_INCREMENT;
+ break;
+ case GTK_DIR_RIGHT:
+ case GTK_DIR_DOWN:
+ increment = MOVE_INCREMENT;
+ break;
+ default:
+ return;
+ }
+
+ panel_widget_push_move (panel, applet, increment);
+}
+
+static void
+panel_widget_switch_move_applet (PanelWidget *panel,
+ GtkDirectionType dir)
+{
+ AppletData *applet;
+ GList *list;
+
+ applet = panel->currently_dragged_applet;
+ g_return_if_fail (applet != NULL);
+
+ list = g_list_find (panel->applet_list, applet);
+ g_return_if_fail (list != NULL);
+
+ switch (dir) {
+ case GTK_DIR_LEFT:
+ case GTK_DIR_UP:
+ panel_widget_switch_applet_left (panel, list);
+ break;
+ case GTK_DIR_RIGHT:
+ case GTK_DIR_DOWN:
+ panel_widget_switch_applet_right (panel, list);
+ break;
+ default:
+ return;
+ }
+}
+
+static void
+panel_widget_free_move_applet (PanelWidget *panel,
+ GtkDirectionType dir)
+{
+ AppletData *ad;
+ gint increment = MOVE_INCREMENT;
+
+ ad = panel->currently_dragged_applet;
+
+ g_return_if_fail (ad);
+
+ switch (dir) {
+ case GTK_DIR_LEFT:
+ case GTK_DIR_UP:
+ increment = -increment;
+ break;
+ case GTK_DIR_RIGHT:
+ case GTK_DIR_DOWN:
+ break;
+ default:
+ return;
+ }
+
+ panel_widget_nice_move (panel, ad, increment + ad->constrained + ad->drag_off);
+}
+
+static void
+panel_widget_tab_move (PanelWidget *panel,
+ gboolean next)
+{
+ PanelWidget *new_panel = NULL;
+ PanelWidget *previous_panel = NULL;
+ AppletData *ad;
+ GSList *l;
+
+ ad = panel->currently_dragged_applet;
+
+ if (!ad)
+ return;
+
+ for (l = panels; l; l = l->next) {
+ PanelWidget *panel_in_list = l->data;
+
+ if (panel_in_list == panel) {
+ if (next) {
+ if (l->next)
+ new_panel = l->next->data;
+ else
+ new_panel = ((GSList *)panels)->data;
+
+ } else {
+ if (previous_panel)
+ new_panel = previous_panel;
+ else
+ continue;
+ }
+ break;
+ } else {
+ if (!next)
+ previous_panel = panel_in_list;
+ }
+ }
+
+ g_return_if_fail (l != NULL);
+
+ if (!new_panel && previous_panel)
+ new_panel = previous_panel;
+
+ if (new_panel &&
+ (new_panel != panel) &&
+ !panel_lockdown_get_locked_down ())
+ panel_widget_reparent (panel, new_panel, ad->applet, 0);
+}
+
+static void
+panel_widget_end_move (PanelWidget *panel)
+{
+ panel_widget_applet_drag_end (panel);
+}
+
+static gboolean
+panel_widget_real_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ if (gtk_widget_get_can_focus (widget) && gtk_container_get_children (GTK_CONTAINER (widget))) {
+ gtk_widget_set_can_focus (widget, FALSE);
+ }
+ return GTK_WIDGET_CLASS (panel_widget_parent_class)->focus (widget, direction);
+}
+
+void
+panel_widget_focus (PanelWidget *panel_widget)
+{
+ if (panel_toplevel_get_is_attached (panel_widget->toplevel))
+ return;
+
+ /*
+ * Set the focus back on the panel; we unset the focus child so that
+ * the next time focus is inside the panel we do not remember the
+ * previously focused child. We also need to set GTK_CAN_FOCUS flag
+ * on the panel as it is unset when this function is called.
+ */
+ gtk_container_set_focus_child (GTK_CONTAINER (panel_widget), NULL);
+ gtk_widget_set_can_focus (GTK_WIDGET (panel_widget), TRUE);
+ gtk_widget_grab_focus (GTK_WIDGET (panel_widget));
+}
+
+
+PanelOrientation
+panel_widget_get_applet_orientation (PanelWidget *panel)
+{
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), PANEL_ORIENTATION_TOP);
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (panel->toplevel), PANEL_ORIENTATION_TOP);
+
+ return panel_toplevel_get_orientation (panel->toplevel);
+}
+
+void
+panel_widget_set_applet_size_constrained (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean size_constrained)
+{
+ AppletData *ad;
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ if (!ad)
+ return;
+
+ size_constrained = size_constrained != FALSE;
+
+ if (ad->size_constrained == size_constrained)
+ return;
+
+ ad->size_constrained = size_constrained;
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+}
+
+void
+panel_widget_set_applet_expandable (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean major,
+ gboolean minor)
+{
+ AppletData *ad;
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ if (!ad)
+ return;
+
+ major = major != FALSE;
+ minor = minor != FALSE;
+
+ if (ad->expand_major == major && ad->expand_minor == minor)
+ return;
+
+ ad->expand_major = major;
+ ad->expand_minor = minor;
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+}
+
+void
+panel_widget_set_applet_size_hints (PanelWidget *panel,
+ GtkWidget *applet,
+ int *size_hints,
+ int size_hints_len)
+{
+ AppletData *ad;
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ if (!ad)
+ return;
+
+ g_free (ad->size_hints);
+
+ if (size_hints_len > 0 && (size_hints_len % 2 == 0)) {
+ ad->size_hints = size_hints;
+ ad->size_hints_len = size_hints_len;
+ } else {
+ g_free (size_hints);
+ ad->size_hints = NULL;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+}
+
+void
+panel_widget_set_applet_locked (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean locked)
+{
+ AppletData *ad;
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ if (!ad)
+ return;
+
+ ad->locked = locked;
+}
+
+gboolean
+panel_widget_get_applet_locked (PanelWidget *panel,
+ GtkWidget *applet)
+{
+ AppletData *ad;
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ if (!ad)
+ return FALSE;
+
+ return ad->locked;
+}
+
+gboolean
+panel_widget_toggle_applet_locked (PanelWidget *panel,
+ GtkWidget *applet)
+{
+ AppletData *ad;
+
+ ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
+ if (!ad)
+ return FALSE;
+
+ return ad->locked = !ad->locked;
+}
+
+gboolean
+mate_panel_applet_is_in_drag (void)
+{
+ return mate_panel_applet_in_drag;
+}
+
+void
+panel_widget_register_open_dialog (PanelWidget *panel,
+ GtkWidget *dialog)
+{
+ /* the window is for a panel, so it should be shown in the taskbar. See
+ * HIG: An alert should not appear in the panel window list unless it
+ * is, or may be, the only window shown by an application. */
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
+
+ panel->open_dialogs = g_slist_append (panel->open_dialogs,
+ dialog);
+
+ g_signal_connect_object (dialog, "destroy",
+ G_CALLBACK (panel_widget_open_dialog_destroyed),
+ panel,
+ G_CONNECT_SWAPPED);
+}
diff --git a/mate-panel/panel-widget.h b/mate-panel/panel-widget.h
new file mode 100644
index 00000000..c844b217
--- /dev/null
+++ b/mate-panel/panel-widget.h
@@ -0,0 +1,242 @@
+/* Mate panel: panel widget
+ * (C) 1997-1998 the Free Software Foundation
+ *
+ * Authors: George Lebl
+ */
+/* This widget, although slightly written as a general purpose widget, it
+ has MANY interdependencies, which makes it almost impossible to use in
+ anything else but the panel, what it would need is some serious
+ cleaning up*/
+#ifndef PANEL_WIDGET_H
+#define PANEL_WIDGET_H
+
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "button-widget.h"
+#include "panel-types.h"
+#include "panel-background.h"
+#include "panel-toplevel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PANEL_TYPE_WIDGET \
+ (panel_widget_get_type())
+#define PANEL_WIDGET(object) \
+ (G_TYPE_CHECK_INSTANCE_CAST((object), PANEL_TYPE_WIDGET, PanelWidget))
+#define PANEL_WIDGET_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), PANEL_TYPE_WIDGET, PanelWidgetClass))
+#define PANEL_IS_WIDGET(object) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((object), PANEL_TYPE_WIDGET))
+
+#define PANEL_MINIMUM_WIDTH 12
+
+#define MATE_PANEL_APPLET_ASSOC_PANEL_KEY "mate_panel_applet_assoc_panel_key"
+#define MATE_PANEL_APPLET_FORBIDDEN_PANELS "mate_panel_applet_forbidden_panels"
+#define MATE_PANEL_APPLET_DATA "mate_panel_applet_data"
+
+#ifndef TYPEDEF_PANEL_WIDGET
+typedef struct _PanelWidget PanelWidget;
+#define TYPEDEF_PANEL_WIDGET
+#endif /* TYPEDEF_PANEL_WIDGET */
+
+typedef struct _PanelWidgetClass PanelWidgetClass;
+
+typedef struct _AppletRecord AppletRecord;
+typedef struct _AppletData AppletData;
+typedef struct _DNDRecord DNDRecord;
+
+typedef struct _AppletSizeHints AppletSizeHints;
+typedef struct _AppletSizeHintsAlloc AppletSizeHintsAlloc;
+
+struct _AppletSizeHints {
+ int *hints;
+ int len;
+};
+
+struct _AppletSizeHintsAlloc {
+ int index;
+ int size;
+};
+
+struct _AppletData
+{
+ GtkWidget * applet;
+ int pos;
+ int constrained;
+ int cells;
+ int min_cells;
+
+ int drag_off; /* offset on the applet where drag
+ was started */
+
+ int no_die; /* if >0 never send the about to die
+ signal, an int and not a bool for
+ nesting reasons */
+
+ /* Valid size ranges for expanded applets */
+ int * size_hints;
+ int size_hints_len;
+
+ guint size_constrained : 1;
+ guint expand_major : 1;
+ guint expand_minor : 1;
+ guint locked : 1;
+
+};
+
+struct _PanelWidget
+{
+ GtkFixed fixed;
+
+ GList *applet_list;
+
+ GSList *open_dialogs;
+
+ int size;
+ GtkOrientation orient;
+ int sz;
+
+ AppletData *currently_dragged_applet;
+
+ int thick;
+
+ PanelBackground background;
+
+ GtkWidget *master_widget;
+
+ GtkWidget *drop_widget; /* widget that the panel checks for
+ * the cursor on drops usually the
+ * panel widget itself
+ */
+
+ PanelToplevel *toplevel;
+
+ GdkEventKey *key_event;
+
+ /* helpers to get a good size in packed panels with applets using
+ * size hints */
+ int nb_applets_size_hints;
+ AppletSizeHints *applets_hints;
+ AppletSizeHintsAlloc *applets_using_hint;
+
+ guint packed : 1;
+};
+
+struct _PanelWidgetClass
+{
+ GtkFixedClass parent_class;
+
+ void (* size_change) (PanelWidget *panel);
+ void (* back_change) (PanelWidget *panel);
+ void (* applet_move) (PanelWidget *panel,
+ GtkWidget *applet);
+ void (* applet_added) (PanelWidget *panel,
+ GtkWidget *applet);
+ void (* applet_removed) (PanelWidget *panel,
+ GtkWidget *applet);
+ void (* push_move) (PanelWidget *panel,
+ GtkDirectionType dir);
+ void (* switch_move) (PanelWidget *panel,
+ GtkDirectionType dir);
+ void (* free_move) (PanelWidget *panel,
+ GtkDirectionType dir);
+ void (* tab_move) (PanelWidget *panel,
+ gboolean next);
+ void (* end_move) (PanelWidget *panel);
+};
+
+GType panel_widget_get_type (void) G_GNUC_CONST;
+
+GtkWidget * panel_widget_new (PanelToplevel *toplevel,
+ gboolean packed,
+ GtkOrientation orient,
+ int sz);
+/*add an applet to the panel, preferably at position pos, if insert_at_pos
+ is on, we REALLY want to insert at the pos given by pos*/
+int panel_widget_add (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean locked,
+ int pos,
+ gboolean insert_at_pos);
+
+/*needs to be called for drawers after add*/
+void panel_widget_add_forbidden (PanelWidget *panel);
+
+/*move applet to a different panel*/
+int panel_widget_reparent (PanelWidget *old_panel,
+ PanelWidget *new_panel,
+ GtkWidget *applet,
+ int pos);
+
+/* use these for drag_off for special cases */
+#define PW_DRAG_OFF_CURSOR -1
+#define PW_DRAG_OFF_CENTER -2
+
+/*drag*/
+gboolean mate_panel_applet_is_in_drag (void);
+void panel_widget_applet_drag_start (PanelWidget *panel,
+ GtkWidget *applet,
+ int drag_off,
+ guint32 time_);
+void panel_widget_applet_drag_end (PanelWidget *panel);
+
+void panel_widget_set_packed (PanelWidget *panel_widget,
+ gboolean packed);
+void panel_widget_set_orientation (PanelWidget *panel_widget,
+ GtkOrientation orientation);
+void panel_widget_set_size (PanelWidget *panel_widget,
+ int size);
+
+/*draw EVERYTHING (meaning icons)*/
+void panel_widget_draw_all (PanelWidget *panel,
+ GdkRectangle *area);
+/*draw just one icon (applet has to be an icon of course)*/
+void panel_widget_draw_icon (PanelWidget *panel,
+ ButtonWidget *applet);
+
+
+/*tells us if an applet is "stuck" on the right side*/
+int panel_widget_is_applet_stuck (PanelWidget *panel,
+ GtkWidget *applet);
+/*get pos of the cursor location in panel coordinates*/
+int panel_widget_get_cursorloc (PanelWidget *panel);
+
+/*needed for other panel types*/
+gboolean panel_widget_is_cursor (PanelWidget *panel,
+ int overlap);
+/* set the focus on the panel */
+void panel_widget_focus (PanelWidget *panel);
+
+PanelOrientation panel_widget_get_applet_orientation (PanelWidget *panel);
+
+
+void panel_widget_set_applet_size_constrained (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean size_constrained);
+void panel_widget_set_applet_expandable (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean major,
+ gboolean minor);
+void panel_widget_set_applet_size_hints (PanelWidget *panel,
+ GtkWidget *applet,
+ int *size_hints,
+ int size_hints_len);
+
+void panel_widget_set_applet_locked (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean locked);
+gboolean panel_widget_get_applet_locked (PanelWidget *panel,
+ GtkWidget *applet);
+gboolean panel_widget_toggle_applet_locked (PanelWidget *panel,
+ GtkWidget *applet);
+
+void panel_widget_register_open_dialog (PanelWidget *panel,
+ GtkWidget *dialog);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PANEL_WIDGET_H */
diff --git a/mate-panel/panel-xutils.c b/mate-panel/panel-xutils.c
new file mode 100644
index 00000000..4480f193
--- /dev/null
+++ b/mate-panel/panel-xutils.c
@@ -0,0 +1,258 @@
+/*
+ * panel-xutils.c: X related utility methods.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include "config.h"
+
+#include "panel-xutils.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+static Atom net_wm_window_type = None;
+static Atom net_wm_window_type_dock = None;
+static Atom net_wm_window_type_normal = None;
+static Atom net_wm_strut = None;
+static Atom net_wm_strut_partial = None;
+
+void
+panel_xutils_set_window_type (GdkWindow *gdk_window,
+ PanelXUtilsWindowType type)
+{
+ Display *display;
+ Window window;
+ Atom atoms [2];
+ int i = 0;
+
+ g_return_if_fail (GDK_IS_WINDOW (gdk_window));
+
+ display = GDK_WINDOW_XDISPLAY (gdk_window);
+ window = GDK_WINDOW_XWINDOW (gdk_window);
+
+ if (net_wm_window_type == None)
+ net_wm_window_type = XInternAtom (display,
+ "_NET_WM_WINDOW_TYPE",
+ False);
+
+ switch (type) {
+ case PANEL_XUTILS_TYPE_DOCK:
+ if (net_wm_window_type_dock == None)
+ net_wm_window_type_dock = XInternAtom (display,
+ "_NET_WM_WINDOW_TYPE_DOCK",
+ False);
+ atoms [i++] = net_wm_window_type_dock;
+ break;
+ case PANEL_XUTILS_TYPE_NORMAL:
+ if (net_wm_window_type_normal == None)
+ net_wm_window_type_normal = XInternAtom (display,
+ "_NET_WM_WINDOW_TYPE_NORMAL",
+ False);
+ atoms [i++] = net_wm_window_type_normal;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gdk_error_trap_push ();
+ XChangeProperty (display, window, net_wm_window_type,
+ XA_ATOM, 32, PropModeReplace,
+ (guchar *) &atoms, i);
+ gdk_error_trap_pop ();
+}
+
+enum {
+ STRUT_LEFT = 0,
+ STRUT_RIGHT = 1,
+ STRUT_TOP = 2,
+ STRUT_BOTTOM = 3,
+ STRUT_LEFT_START = 4,
+ STRUT_LEFT_END = 5,
+ STRUT_RIGHT_START = 6,
+ STRUT_RIGHT_END = 7,
+ STRUT_TOP_START = 8,
+ STRUT_TOP_END = 9,
+ STRUT_BOTTOM_START = 10,
+ STRUT_BOTTOM_END = 11
+};
+
+void
+panel_xutils_set_strut (GdkWindow *gdk_window,
+ PanelOrientation orientation,
+ guint32 strut,
+ guint32 strut_start,
+ guint32 strut_end)
+ {
+ Display *display;
+ Window window;
+ gulong struts [12] = { 0, };
+
+ g_return_if_fail (GDK_IS_WINDOW (gdk_window));
+
+ display = GDK_WINDOW_XDISPLAY (gdk_window);
+ window = GDK_WINDOW_XWINDOW (gdk_window);
+
+ if (net_wm_strut == None)
+ net_wm_strut = XInternAtom (display, "_NET_WM_STRUT", False);
+ if (net_wm_strut_partial == None)
+ net_wm_strut_partial = XInternAtom (display, "_NET_WM_STRUT_PARTIAL", False);
+
+ switch (orientation) {
+ case PANEL_ORIENTATION_LEFT:
+ struts [STRUT_LEFT] = strut;
+ struts [STRUT_LEFT_START] = strut_start;
+ struts [STRUT_LEFT_END] = strut_end;
+ break;
+ case PANEL_ORIENTATION_RIGHT:
+ struts [STRUT_RIGHT] = strut;
+ struts [STRUT_RIGHT_START] = strut_start;
+ struts [STRUT_RIGHT_END] = strut_end;
+ break;
+ case PANEL_ORIENTATION_TOP:
+ struts [STRUT_TOP] = strut;
+ struts [STRUT_TOP_START] = strut_start;
+ struts [STRUT_TOP_END] = strut_end;
+ break;
+ case PANEL_ORIENTATION_BOTTOM:
+ struts [STRUT_BOTTOM] = strut;
+ struts [STRUT_BOTTOM_START] = strut_start;
+ struts [STRUT_BOTTOM_END] = strut_end;
+ break;
+ }
+
+ gdk_error_trap_push ();
+ XChangeProperty (display, window, net_wm_strut,
+ XA_CARDINAL, 32, PropModeReplace,
+ (guchar *) &struts, 4);
+ XChangeProperty (display, window, net_wm_strut_partial,
+ XA_CARDINAL, 32, PropModeReplace,
+ (guchar *) &struts, 12);
+ gdk_error_trap_pop ();
+}
+
+void
+panel_warp_pointer (GdkWindow *gdk_window,
+ int x,
+ int y)
+{
+ Display *display;
+ Window window;
+
+ g_return_if_fail (GDK_IS_WINDOW (gdk_window));
+
+ display = GDK_WINDOW_XDISPLAY (gdk_window);
+ window = GDK_WINDOW_XWINDOW (gdk_window);
+
+ gdk_error_trap_push ();
+ XWarpPointer (display, None, window, 0, 0, 0, 0, x, y);
+ gdk_error_trap_pop ();
+}
+
+guint
+panel_get_real_modifier_mask (guint mask)
+{
+ guint real_mask;
+ Display *display;
+ int i, min_keycode, max_keycode, keysyms_per_keycode;
+ int max_keycodes_per_modifier;
+ KeySym *keysyms_for_keycodes;
+ XModifierKeymap *modifier_keymap;
+
+ real_mask = mask & ((Mod5Mask << 1) - 1);
+
+ /* Already real */
+ if (mask == real_mask) {
+ return mask;
+ }
+
+ display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ XDisplayKeycodes (display, &min_keycode, &max_keycode);
+ keysyms_for_keycodes = XGetKeyboardMapping (display,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &keysyms_per_keycode);
+
+ modifier_keymap = XGetModifierMapping (display);
+ max_keycodes_per_modifier = modifier_keymap->max_keypermod;
+
+ /* Loop through all the modifiers and find out which "real"
+ * (Mod2..Mod5) modifiers Super, Hyper, and Meta are mapped to.
+ * Note, Mod1 is used by the Alt modifier */
+ for (i = Mod2MapIndex * max_keycodes_per_modifier;
+ i < (Mod5MapIndex + 1) * max_keycodes_per_modifier;
+ i++) {
+ int keycode;
+ int j;
+ KeySym *keysyms_for_keycode;
+ int map_index;
+ int map_mask;
+
+ keycode = modifier_keymap->modifiermap[i];
+
+ /* The array is sparse, there may be some
+ * empty entries. Filter those out
+ * (along with any invalid entries) */
+ if (keycode < min_keycode || keycode > max_keycode)
+ continue;
+
+ keysyms_for_keycode = keysyms_for_keycodes +
+ (keycode - min_keycode) * keysyms_per_keycode;
+
+ map_index = i / max_keycodes_per_modifier;
+
+ g_assert (map_index <= Mod5MapIndex);
+
+ map_mask = 1 << map_index;
+
+ for (j = 0; j < keysyms_per_keycode; j++) {
+ switch (keysyms_for_keycode[j]) {
+ case XK_Super_L:
+ case XK_Super_R:
+ if (mask & GDK_SUPER_MASK)
+ real_mask |= map_mask;
+ break;
+ case XK_Hyper_L:
+ case XK_Hyper_R:
+ if (mask & GDK_HYPER_MASK)
+ real_mask |= map_mask;
+ break;
+ case XK_Meta_L:
+ case XK_Meta_R:
+ if (mask & GDK_META_MASK)
+ real_mask |= map_mask;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ XFreeModifiermap (modifier_keymap);
+ XFree (keysyms_for_keycodes);
+
+ return real_mask;
+}
diff --git a/mate-panel/panel-xutils.h b/mate-panel/panel-xutils.h
new file mode 100644
index 00000000..76c559c8
--- /dev/null
+++ b/mate-panel/panel-xutils.h
@@ -0,0 +1,64 @@
+/*
+ * panel-xutils.h: X related utility methods.
+ *
+ * Copyright (C) 2003 Sun Microsystems, 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#ifndef __PANEL_XUTILS_H__
+#define __PANEL_XUTILS_H__
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <X11/Xlib.h>
+
+#include "panel-enums.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ PANEL_XUTILS_TYPE_NORMAL,
+ PANEL_XUTILS_TYPE_DOCK
+} PanelXUtilsWindowType;
+
+void panel_xutils_set_window_type (GdkWindow *gdk_window,
+ PanelXUtilsWindowType type);
+
+void panel_xutils_set_strut (GdkWindow *gdk_window,
+ PanelOrientation orientation,
+ guint32 strut,
+ guint32 strut_start,
+ guint32 strut_end);
+
+void panel_warp_pointer (GdkWindow *gdk_window,
+ int x,
+ int y);
+
+guint panel_get_real_modifier_mask (guint modifier_mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PANEL_XUTILS_H__ */
diff --git a/mate-panel/panel.c b/mate-panel/panel.c
new file mode 100644
index 00000000..5f2a9666
--- /dev/null
+++ b/mate-panel/panel.c
@@ -0,0 +1,1403 @@
+/* Mate panel: Initialization routines
+ * (C) 1997,1998,1999,2000 the Free Software Foundation
+ * (C) 2000 Eazel, Inc.
+ *
+ * Authors: Federico Mena
+ * Miguel de Icaza
+ * George Lebl
+ */
+
+#include <config.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <libpanel-util/panel-glib.h>
+
+#include "panel.h"
+
+#include "applet.h"
+#include "drawer.h"
+#include "button-widget.h"
+#include "launcher.h"
+#include "panel-context-menu.h"
+#include "panel-util.h"
+#include "panel-config-global.h"
+#include "panel-mateconf.h"
+#include "panel-profile.h"
+#include "mate-panel-applet-frame.h"
+#include "panel-action-button.h"
+#include "panel-menu-bar.h"
+#include "panel-separator.h"
+#include "panel-compatibility.h"
+#include "panel-multiscreen.h"
+#include "panel-toplevel.h"
+#include "panel-menu-button.h"
+#include "panel-globals.h"
+#include "panel-lockdown.h"
+#include "panel-icon-names.h"
+
+enum {
+ TARGET_URL,
+ TARGET_NETSCAPE_URL,
+ TARGET_DIRECTORY,
+ TARGET_COLOR,
+ TARGET_APPLET,
+ TARGET_APPLET_INTERNAL,
+ TARGET_ICON_INTERNAL,
+ TARGET_BGIMAGE,
+ TARGET_BACKGROUND_RESET
+};
+
+/*we call this recursively*/
+static void orient_change_foreach(GtkWidget *w, gpointer data);
+
+void
+orientation_change (AppletInfo *info,
+ PanelWidget *panel)
+{
+ PanelOrientation orientation;
+
+ orientation = panel_widget_get_applet_orientation (panel);
+
+ switch (info->type) {
+ case PANEL_OBJECT_APPLET:
+ mate_panel_applet_frame_change_orientation (
+ MATE_PANEL_APPLET_FRAME (info->widget), orientation);
+ break;
+ case PANEL_OBJECT_MENU:
+ case PANEL_OBJECT_LAUNCHER:
+ case PANEL_OBJECT_ACTION:
+ button_widget_set_orientation (BUTTON_WIDGET (info->widget), orientation);
+ break;
+ case PANEL_OBJECT_MENU_BAR:
+ panel_menu_bar_set_orientation (PANEL_MENU_BAR (info->widget), orientation);
+ break;
+ case PANEL_OBJECT_DRAWER: {
+ Drawer *drawer = info->data;
+ PanelWidget *panel_widget;
+
+ panel_widget = panel_toplevel_get_panel_widget (drawer->toplevel);
+
+ button_widget_set_orientation (BUTTON_WIDGET (info->widget), orientation);
+
+ gtk_widget_queue_resize (GTK_WIDGET (drawer->toplevel));
+ gtk_container_foreach (GTK_CONTAINER (panel_widget),
+ orient_change_foreach,
+ panel_widget);
+ }
+ break;
+ case PANEL_OBJECT_SEPARATOR:
+ panel_separator_set_orientation (PANEL_SEPARATOR (info->widget),
+ orientation);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+orient_change_foreach(GtkWidget *w, gpointer data)
+{
+ AppletInfo *info = g_object_get_data (G_OBJECT (w), "applet_info");
+ PanelWidget *panel = data;
+
+ orientation_change(info,panel);
+}
+
+
+static void
+panel_orient_change (GtkWidget *widget, gpointer data)
+{
+ gtk_container_foreach(GTK_CONTAINER(widget),
+ orient_change_foreach,
+ widget);
+}
+
+/*we call this recursively*/
+static void size_change_foreach(GtkWidget *w, gpointer data);
+
+void
+size_change (AppletInfo *info,
+ PanelWidget *panel)
+{
+ if (info->type == PANEL_OBJECT_APPLET)
+ mate_panel_applet_frame_change_size (
+ MATE_PANEL_APPLET_FRAME (info->widget), panel->sz);
+}
+
+static void
+size_change_foreach(GtkWidget *w, gpointer data)
+{
+ AppletInfo *info = g_object_get_data (G_OBJECT (w), "applet_info");
+ PanelWidget *panel = data;
+
+ size_change(info,panel);
+}
+
+
+static void
+panel_size_change (GtkWidget *widget, gpointer data)
+{
+ gtk_container_foreach(GTK_CONTAINER(widget), size_change_foreach,
+ widget);
+}
+
+void
+back_change (AppletInfo *info,
+ PanelWidget *panel)
+{
+ switch (info->type) {
+ case PANEL_OBJECT_APPLET:
+ mate_panel_applet_frame_change_background (
+ MATE_PANEL_APPLET_FRAME (info->widget), panel->background.type);
+ break;
+ case PANEL_OBJECT_MENU_BAR:
+ panel_menu_bar_change_background (PANEL_MENU_BAR (info->widget));
+ break;
+ case PANEL_OBJECT_SEPARATOR:
+ panel_separator_change_background (PANEL_SEPARATOR (info->widget));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+back_change_foreach (GtkWidget *widget,
+ PanelWidget *panel)
+{
+ AppletInfo *info;
+
+ info = g_object_get_data (G_OBJECT (widget), "applet_info");
+
+ back_change (info, panel);
+}
+
+static void
+panel_back_change (GtkWidget *widget, gpointer data)
+{
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ (GtkCallback) back_change_foreach,
+ widget);
+
+#ifdef FIXME_FOR_NEW_CONFIG
+ /*update the configuration box if it is displayed*/
+ update_config_back(PANEL_WIDGET(widget));
+#endif /* FIXME_FOR_NEW_CONFIG */
+}
+
+static void
+mate_panel_applet_added(GtkWidget *widget, GtkWidget *applet, gpointer data)
+{
+ AppletInfo *info;
+
+ info = g_object_get_data (G_OBJECT (applet), "applet_info");
+
+ orientation_change(info,PANEL_WIDGET(widget));
+ size_change(info,PANEL_WIDGET(widget));
+ back_change(info,PANEL_WIDGET(widget));
+}
+
+static void
+mate_panel_applet_removed(GtkWidget *widget, GtkWidget *applet, gpointer data)
+{
+ PanelToplevel *toplevel;
+ AppletInfo *info;
+
+ toplevel = PANEL_WIDGET (widget)->toplevel;
+ info = g_object_get_data (G_OBJECT (applet), "applet_info");
+
+ if (info->type == PANEL_OBJECT_DRAWER) {
+ Drawer *drawer = info->data;
+
+ if (drawer->toplevel)
+ panel_toplevel_queue_auto_hide (toplevel);
+ }
+}
+
+static gboolean
+deactivate_idle (gpointer data)
+{
+ PanelData *pd = data;
+ pd->deactivate_idle = 0;
+
+ pd->insertion_pos = -1;
+
+ return FALSE;
+}
+
+static void
+context_menu_deactivate (GtkWidget *w,
+ PanelData *pd)
+{
+ if (pd->deactivate_idle == 0)
+ pd->deactivate_idle = g_idle_add (deactivate_idle, pd);
+
+ panel_toplevel_pop_autohide_disabler (PANEL_TOPLEVEL (pd->panel));
+}
+
+static void
+context_menu_show (GtkWidget *w,
+ PanelData *pd)
+{
+ panel_toplevel_push_autohide_disabler (PANEL_TOPLEVEL (pd->panel));
+}
+
+static void
+panel_recreate_context_menu (PanelData *pd)
+{
+ if (pd->menu)
+ g_object_unref (pd->menu);
+ pd->menu = NULL;
+}
+
+static void
+panel_destroy (PanelToplevel *toplevel,
+ PanelData *pd)
+{
+ panel_lockdown_notify_remove (G_CALLBACK (panel_recreate_context_menu),
+ pd);
+
+ if (pd->menu) {
+ g_signal_handlers_disconnect_by_func (pd->menu,
+ context_menu_deactivate,
+ pd);
+ g_object_unref (pd->menu);
+ }
+ pd->menu = NULL;
+
+ pd->panel = NULL;
+
+ if (pd->deactivate_idle != 0)
+ g_source_remove (pd->deactivate_idle);
+ pd->deactivate_idle = 0;
+
+ g_object_set_data (G_OBJECT (toplevel), "PanelData", NULL);
+
+ panel_list = g_slist_remove (panel_list, pd);
+ g_free (pd);
+}
+
+static void
+mate_panel_applet_move(PanelWidget *panel, GtkWidget *widget, gpointer data)
+{
+ AppletInfo *info;
+
+ info = g_object_get_data (G_OBJECT (widget), "applet_info");
+
+ g_return_if_fail (info);
+
+ mate_panel_applet_save_position (info, info->id, FALSE);
+}
+
+static GtkWidget *
+panel_menu_get (PanelWidget *panel, PanelData *pd)
+{
+ if (!pd->menu) {
+ pd->menu = g_object_ref_sink (panel_context_menu_create (panel));
+ g_signal_connect (pd->menu, "deactivate",
+ G_CALLBACK (context_menu_deactivate),
+ pd);
+ g_signal_connect (pd->menu, "show",
+ G_CALLBACK (context_menu_show), pd);
+ }
+
+ return pd->menu;
+}
+
+static GtkWidget *
+make_popup_panel_menu (PanelWidget *panel_widget)
+{
+ PanelData *pd;
+ GtkWidget *menu;
+
+ if (!panel_widget) {
+ PanelToplevel *toplevel;
+
+ toplevel = PANEL_TOPLEVEL (((PanelData *) panel_list->data)->panel);
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+ }
+
+ pd = g_object_get_data (G_OBJECT (panel_widget->toplevel), "PanelData");
+ menu = panel_menu_get (panel_widget, pd);
+ g_object_set_data (G_OBJECT (menu), "menu_panel", panel_widget);
+
+ return menu;
+}
+
+static gboolean
+panel_popup_menu (PanelToplevel *toplevel,
+ guint button,
+ guint32 activate_time)
+{
+ PanelWidget *panel_widget;
+ GtkWidget *menu;
+ PanelData *panel_data;
+ GdkEvent *current_event;
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+ panel_data = g_object_get_data (G_OBJECT (toplevel), "PanelData");
+
+ current_event = gtk_get_current_event ();
+ if (current_event->type == GDK_BUTTON_PRESS)
+ panel_data->insertion_pos = panel_widget_get_cursorloc (panel_widget);
+ else
+ panel_data->insertion_pos = -1;
+
+ menu = make_popup_panel_menu (panel_widget);
+ if (!menu)
+ return FALSE;
+
+ gtk_menu_set_screen (GTK_MENU (menu),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)));
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, activate_time);
+
+ return TRUE;
+}
+
+static gboolean
+panel_popup_menu_signal (PanelToplevel *toplevel)
+{
+ return panel_popup_menu (toplevel, 3, GDK_CURRENT_TIME);
+}
+
+static gboolean
+panel_button_press_event (PanelToplevel *toplevel,
+ GdkEventButton *event)
+{
+ if (event->button != 3)
+ return FALSE;
+
+ return panel_popup_menu (toplevel, event->button, event->time);
+}
+
+static gboolean
+panel_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ /*
+ * If the focus widget is a GtkSocket, i.e. the
+ * focus is in an applet in another process, then key
+ * bindings do not work. We get around this by
+ * activating the key bindings here.
+ */
+ if (GTK_IS_SOCKET (gtk_window_get_focus (GTK_WINDOW (widget))) &&
+ event->keyval == GDK_F10 &&
+ (event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_CONTROL_MASK)
+ return gtk_bindings_activate (GTK_OBJECT (widget),
+ event->keyval,
+ event->state);
+
+ return FALSE;
+}
+
+static gboolean
+set_background_image_from_uri (PanelToplevel *toplevel,
+ const char *uri)
+{
+ char *image;
+
+ if ( ! panel_profile_is_writable_background_type (toplevel) ||
+ ! panel_profile_is_writable_background_image (toplevel))
+ return FALSE;
+
+ if (!(image = g_filename_from_uri (uri, NULL, NULL)))
+ return FALSE;
+
+ panel_profile_set_background_image (toplevel, image);
+ panel_profile_set_background_type (toplevel, PANEL_BACK_IMAGE);
+
+ g_free (image);
+
+ return FALSE;
+}
+
+static gboolean
+set_background_color (PanelToplevel *toplevel,
+ guint16 *dropped)
+{
+ PanelColor color;
+
+ if (!dropped)
+ return FALSE;
+
+ if ( ! panel_profile_is_writable_background_type (toplevel) ||
+ ! panel_profile_is_writable_background_color (toplevel))
+ return FALSE;
+
+ color.gdk.red = dropped [0];
+ color.gdk.green = dropped [1];
+ color.gdk.blue = dropped [2];
+ color.alpha = 65535;
+
+ panel_profile_set_background_color (toplevel, &color);
+ panel_profile_set_background_type (toplevel, PANEL_BACK_COLOR);
+
+ return TRUE;
+}
+
+static gboolean
+drop_url (PanelWidget *panel,
+ int position,
+ const char *url)
+{
+ enum {
+ NETSCAPE_URL_URL,
+ NETSCAPE_URL_NAME
+ };
+ char **netscape_url;
+ char *name;
+ char *comment;
+
+ g_return_val_if_fail (url != NULL, FALSE);
+
+ if (!panel_profile_id_lists_are_writable ())
+ return FALSE;
+
+ netscape_url = g_strsplit (url, "\n", 2);
+ if (!netscape_url ||
+ PANEL_GLIB_STR_EMPTY (netscape_url[NETSCAPE_URL_URL])) {
+ g_strfreev (netscape_url);
+ return FALSE;
+ }
+
+ comment = g_strdup_printf (_("Open URL: %s"),
+ netscape_url[NETSCAPE_URL_URL]);
+
+ if (PANEL_GLIB_STR_EMPTY (netscape_url[NETSCAPE_URL_NAME]))
+ name = netscape_url[NETSCAPE_URL_URL];
+ else
+ name = netscape_url[NETSCAPE_URL_NAME];
+
+ panel_launcher_create_from_info (panel->toplevel, position, FALSE,
+ netscape_url[NETSCAPE_URL_URL],
+ name, comment, PANEL_ICON_REMOTE);
+
+ g_free (comment);
+ g_strfreev (netscape_url);
+
+ return TRUE;
+}
+
+static gboolean
+drop_menu (PanelWidget *panel,
+ int position,
+ const char *menu_filename,
+ const char *menu_path)
+{
+ if (!panel_profile_id_lists_are_writable ())
+ return FALSE;
+
+ return panel_menu_button_create (panel->toplevel,
+ position,
+ menu_filename,
+ menu_path,
+ menu_path != NULL,
+ NULL);
+
+}
+
+static gboolean
+drop_uri (PanelWidget *panel,
+ int position,
+ const char *uri,
+ const char *fallback_icon)
+{
+ char *name;
+ char *comment;
+ char *buf;
+ char *icon;
+ GFile *file;
+
+ if (!panel_profile_id_lists_are_writable ())
+ return FALSE;
+
+ name = panel_util_get_label_for_uri (uri);
+ icon = panel_util_get_icon_for_uri (uri);
+ if (!icon)
+ icon = g_strdup (fallback_icon);
+
+ /* FIXME: we might get icons like "folder-music" that might not exist in
+ * the icon theme. This would usually be okay if we could use fallback
+ * icons (and get "folder" this way). However, this is not possible for
+ * launchers: this could be an application that uses an icon named
+ * folder-magic-app, for which we don't want fallbacks. We just want to
+ * go to hicolor. */
+
+ file = g_file_new_for_uri (uri);
+ buf = g_file_get_parse_name (file);
+ g_object_unref (file);
+ /* Translators: %s is a URI */
+ comment = g_strdup_printf (_("Open '%s'"), buf);
+ g_free (buf);
+
+ panel_launcher_create_from_info (panel->toplevel, position, FALSE,
+ uri, name, comment, icon);
+
+ g_free (name);
+ g_free (comment);
+ g_free (icon);
+
+ return TRUE;
+}
+
+static gboolean
+drop_caja_desktop_uri (PanelWidget *panel,
+ int pos,
+ const char *uri)
+{
+ gboolean success;
+ const char *id;
+ const char *basename;
+
+ if (g_ascii_strncasecmp (uri, "x-caja-desktop:///",
+ strlen ("x-caja-desktop:///")) != 0)
+ return FALSE;
+
+ success = TRUE;
+ id = panel_profile_get_toplevel_id (panel->toplevel);
+ basename = uri + strlen ("x-caja-desktop:///");
+
+ if (strncmp (basename, "trash", strlen ("trash")) == 0)
+ mate_panel_applet_frame_create (panel->toplevel, pos,
+ "OAFIID:MATE_Panel_TrashApplet");
+ else if (strncmp (basename, "home", strlen ("home")) == 0)
+ panel_launcher_create_with_id (id, pos,
+ "caja-home.desktop");
+ else if (strncmp (basename, "computer", strlen ("computer")) == 0)
+ panel_launcher_create_with_id (id, pos,
+ "caja-computer.desktop");
+ else if (strncmp (basename, "network", strlen ("network")) == 0)
+ panel_launcher_create_with_id (id, pos,
+ "caja-scheme.desktop");
+ else
+ success = FALSE;
+
+ return success;
+}
+
+static gboolean
+drop_urilist (PanelWidget *panel,
+ int pos,
+ char *urilist)
+{
+ char **uris;
+ gboolean success;
+ int i;
+
+ uris = g_uri_list_extract_uris (urilist);
+
+ success = TRUE;
+ for (i = 0; uris[i]; i++) {
+ GFile *file;
+ GFileInfo *info;
+ const char *uri;
+
+ uri = uris[i];
+
+ if (g_ascii_strncasecmp (uri, "http:", strlen ("http:")) == 0 ||
+ g_ascii_strncasecmp (uri, "https:", strlen ("https:")) == 0 ||
+ g_ascii_strncasecmp (uri, "ftp:", strlen ("ftp:")) == 0 ||
+ g_ascii_strncasecmp (uri, "gopher:", strlen ("gopher:")) == 0 ||
+ g_ascii_strncasecmp (uri, "ghelp:", strlen ("ghelp:")) == 0 ||
+ g_ascii_strncasecmp (uri, "man:", strlen ("man:")) == 0 ||
+ g_ascii_strncasecmp (uri, "info:", strlen ("info:")) == 0) {
+ /* FIXME: probably do this only on link,
+ * in fact, on link always set up a link,
+ * on copy do all the other stuff. Or something. */
+ if ( ! drop_url (panel, pos, uri))
+ success = FALSE;
+ continue;
+ }
+
+ if (g_ascii_strncasecmp (uri, "x-caja-desktop:",
+ strlen ("x-caja-desktop:")) == 0) {
+ success = drop_caja_desktop_uri (panel, pos, uri);
+ continue;
+ }
+
+ file = g_file_new_for_uri (uri);
+ info = g_file_query_info (file,
+ "standard::type,"
+ "standard::content-type,"
+ "access::can-execute",
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+
+ if (info) {
+ const char *mime;
+ GFileType type;
+ gboolean can_exec;
+
+ mime = g_file_info_get_content_type (info);
+ type = g_file_info_get_file_type (info);
+ can_exec = g_file_info_get_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE);
+
+ if (mime &&
+ g_str_has_prefix (mime, "image")) {
+ if (!set_background_image_from_uri (panel->toplevel, uri))
+ success = FALSE;
+ } else if (mime &&
+ (!strcmp (mime, "application/x-mate-app-info") ||
+ !strcmp (mime, "application/x-desktop") ||
+ !strcmp (mime, "application/x-kde-app-info"))) {
+ if (panel_profile_id_lists_are_writable ())
+ panel_launcher_create (panel->toplevel, pos, uri);
+ else
+ success = FALSE;
+ } else if (type != G_FILE_TYPE_DIRECTORY && can_exec) {
+ char *filename;
+
+ filename = g_file_get_path (file);
+
+ if (panel_profile_id_lists_are_writable ())
+ /* executable and local, so add a
+ * launcher with it */
+ ask_about_launcher (filename, panel,
+ pos, TRUE);
+ else
+ success = FALSE;
+ g_free (filename);
+ } else {
+ if (!drop_uri (panel, pos, uri,
+ PANEL_ICON_UNKNOWN))
+ success = FALSE;
+ }
+ } else {
+ if (!drop_uri (panel, pos, uri, PANEL_ICON_UNKNOWN))
+ success = FALSE;
+ }
+
+ g_object_unref (info);
+ g_object_unref (file);
+ }
+
+ g_strfreev (uris);
+
+ return success;
+}
+
+static gboolean
+drop_internal_icon (PanelWidget *panel,
+ int pos,
+ const char *icon_name,
+ int action)
+{
+ Launcher *old_launcher = NULL;
+
+ if (!icon_name)
+ return FALSE;
+
+ if (!panel_profile_id_lists_are_writable ())
+ return FALSE;
+
+ if (action == GDK_ACTION_MOVE)
+ old_launcher = find_launcher (icon_name);
+
+ if (!panel_launcher_create_copy (panel->toplevel, pos, icon_name))
+ return FALSE;
+
+ if (old_launcher && old_launcher->button) {
+ if (old_launcher->prop_dialog) {
+ g_signal_handler_disconnect (old_launcher->button,
+ old_launcher->destroy_handler);
+ launcher_properties_destroy (old_launcher);
+ }
+ panel_profile_delete_object (old_launcher->info);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+move_applet (PanelWidget *panel, int pos, int applet_index)
+{
+ GSList *applet_list;
+ AppletInfo *info;
+ GtkWidget *parent;
+
+ applet_list = mate_panel_applet_list_applets ();
+
+ info = g_slist_nth_data (applet_list, applet_index);
+
+ if ( ! mate_panel_applet_can_freely_move (info))
+ return FALSE;
+
+ if (pos < 0)
+ pos = 0;
+
+ parent = gtk_widget_get_parent (info->widget);
+
+ if (info != NULL &&
+ info->widget != NULL &&
+ parent != NULL &&
+ PANEL_IS_WIDGET (parent)) {
+ GSList *forb;
+ forb = g_object_get_data (G_OBJECT (info->widget),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS);
+ if ( ! g_slist_find (forb, panel))
+ panel_widget_reparent (PANEL_WIDGET (parent),
+ panel,
+ info->widget,
+ pos);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+drop_internal_applet (PanelWidget *panel, int pos, const char *applet_type,
+ int action)
+{
+ int applet_index = -1;
+ gboolean remove_applet = FALSE;
+ gboolean success = FALSE;
+
+ if (applet_type == NULL)
+ return FALSE;
+
+ if (sscanf (applet_type, "MENU:%d", &applet_index) == 1 ||
+ sscanf (applet_type, "DRAWER:%d", &applet_index) == 1) {
+ if (action != GDK_ACTION_MOVE)
+ g_warning ("Only MOVE supported for menus/drawers");
+ success = move_applet (panel, pos, applet_index);
+
+ } else if (strncmp (applet_type, "MENU:", strlen ("MENU:")) == 0) {
+ const char *menu;
+ const char *menu_path;
+
+ menu = &applet_type[strlen ("MENU:")];
+ menu_path = strchr (menu, '/');
+
+ if (!menu_path) {
+ if (strncmp (menu, "MAIN", strlen ("MAIN")) == 0)
+ success = drop_menu (panel, pos, NULL, NULL);
+ else
+ success = drop_menu (panel, pos, menu, NULL);
+ } else {
+ char *menu_filename;
+
+ menu_filename = g_strndup (menu, menu_path - menu);
+ menu_path++;
+ success = drop_menu (panel, pos,
+ menu_filename, menu_path);
+ g_free (menu_filename);
+ }
+
+ } else if (!strcmp (applet_type, "DRAWER:NEW")) {
+ if (panel_profile_id_lists_are_writable ()) {
+ panel_drawer_create (panel->toplevel, pos, NULL, FALSE, NULL);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+
+ } else if (!strncmp (applet_type, "ACTION:", strlen ("ACTION:"))) {
+ if (panel_profile_id_lists_are_writable ()) {
+ remove_applet = panel_action_button_load_from_drag (
+ panel->toplevel,
+ pos,
+ applet_type,
+ &applet_index);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+
+ } else if (!strcmp (applet_type, "MENUBAR:NEW")) {
+ if (panel_profile_id_lists_are_writable ()) {
+ panel_menu_bar_create (panel->toplevel, pos);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+
+ } else if (!strcmp(applet_type,"SEPARATOR:NEW")) {
+ if (panel_profile_id_lists_are_writable ()) {
+ panel_separator_create (panel->toplevel, pos);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+
+ } else if (!strcmp(applet_type,"LAUNCHER:ASK")) {
+ if (panel_profile_id_lists_are_writable ()) {
+ ask_about_launcher (NULL, panel, pos, TRUE);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+ }
+
+ if (remove_applet &&
+ action == GDK_ACTION_MOVE) {
+ AppletInfo *info;
+ GSList *applet_list;
+
+ applet_list = mate_panel_applet_list_applets ();
+
+ info = g_slist_nth_data (applet_list, applet_index);
+
+ if (info)
+ panel_profile_delete_object (info);
+ }
+
+ return success;
+}
+
+static GtkTargetList *
+get_target_list (void)
+{
+ static GtkTargetEntry drop_types [] = {
+ { "text/uri-list", 0, TARGET_URL },
+ { "x-url/http", 0, TARGET_NETSCAPE_URL },
+ { "x-url/ftp", 0, TARGET_NETSCAPE_URL },
+ { "_NETSCAPE_URL", 0, TARGET_NETSCAPE_URL },
+ { "application/x-panel-directory", 0, TARGET_DIRECTORY },
+ { "application/x-mate-panel-applet-iid", 0, TARGET_APPLET },
+ { "application/x-mate-panel-applet-internal", 0, TARGET_APPLET_INTERNAL },
+ { "application/x-panel-icon-internal", 0, TARGET_ICON_INTERNAL },
+ { "application/x-color", 0, TARGET_COLOR },
+ { "property/bgimage", 0, TARGET_BGIMAGE },
+ { "x-special/mate-reset-background", 0, TARGET_BACKGROUND_RESET },
+ };
+ static GtkTargetList *target_list = NULL;
+
+ if (!target_list) {
+ gint length = sizeof (drop_types) / sizeof (drop_types [0]);
+
+ target_list = gtk_target_list_new (drop_types, length);
+ }
+
+ return target_list;
+}
+
+gboolean
+panel_check_dnd_target_data (GtkWidget *widget,
+ GdkDragContext *context,
+ guint *ret_info,
+ GdkAtom *ret_atom)
+{
+ GList *l;
+
+ g_return_val_if_fail (widget, FALSE);
+
+ if (!PANEL_IS_TOPLEVEL (widget) &&
+ !BUTTON_IS_WIDGET (widget))
+ return FALSE;
+
+ if (!(gdk_drag_context_get_actions (context) & (GDK_ACTION_COPY|GDK_ACTION_MOVE)))
+ return FALSE;
+
+ for (l = gdk_drag_context_list_targets (context); l; l = l->next) {
+ GdkAtom atom;
+ guint info;
+
+ atom = GDK_POINTER_TO_ATOM (l->data);
+
+ if (gtk_target_list_find (get_target_list (), atom, &info)) {
+ if (ret_info)
+ *ret_info = info;
+
+ if (ret_atom)
+ *ret_atom = atom;
+ break;
+ }
+ }
+
+ return l ? TRUE : FALSE;
+}
+
+static void
+do_highlight (GtkWidget *widget, gboolean highlight)
+{
+ gboolean have_drag;
+
+ /* FIXME: what's going on here ? How are we highlighting
+ * the toplevel widget ? I don't think we are ...
+ */
+
+ have_drag = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "have-drag"));
+ if(highlight) {
+ if(!have_drag) {
+ g_object_set_data (G_OBJECT (widget), "have-drag",
+ GINT_TO_POINTER (TRUE));
+ gtk_drag_highlight (widget);
+ }
+ } else {
+ if(have_drag) {
+ g_object_set_data (G_OBJECT (widget),
+ "have-drag", NULL);
+ gtk_drag_unhighlight (widget);
+ }
+ }
+}
+
+gboolean
+panel_check_drop_forbidden (PanelWidget *panel,
+ GdkDragContext *context,
+ guint info,
+ guint time_)
+{
+ if (!panel)
+ return FALSE;
+
+ if (panel_lockdown_get_locked_down ())
+ return FALSE;
+
+ if (info == TARGET_APPLET_INTERNAL) {
+ GtkWidget *source_widget;
+
+ source_widget = gtk_drag_get_source_widget (context);
+
+ if (BUTTON_IS_WIDGET (source_widget)) {
+ GSList *forb;
+
+ forb = g_object_get_data (G_OBJECT (source_widget),
+ MATE_PANEL_APPLET_FORBIDDEN_PANELS);
+
+ if (g_slist_find (forb, panel))
+ return FALSE;
+ }
+ }
+
+ if (info == TARGET_ICON_INTERNAL ||
+ info == TARGET_APPLET_INTERNAL) {
+ if (gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE)
+ gdk_drag_status (context, GDK_ACTION_MOVE, time_);
+ else
+ gdk_drag_status (context,
+ gdk_drag_context_get_suggested_action (context),
+ time_);
+
+ } else if (gdk_drag_context_get_actions (context) & GDK_ACTION_COPY)
+ gdk_drag_status (context, GDK_ACTION_COPY, time_);
+ else
+ gdk_drag_status (context,
+ gdk_drag_context_get_suggested_action (context),
+ time_);
+
+ return TRUE;
+
+}
+
+static gboolean
+drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ PanelToplevel *toplevel;
+ PanelWidget *panel_widget;
+ guint info;
+
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
+
+ if (!panel_check_dnd_target_data (widget, context, &info, NULL))
+ return FALSE;
+
+ toplevel = PANEL_TOPLEVEL (widget);
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+
+ if (!panel_check_drop_forbidden (panel_widget, context, info, time))
+ return FALSE;
+
+ do_highlight (widget, TRUE);
+
+ panel_toplevel_unhide (toplevel);
+
+ return TRUE;
+}
+
+static gboolean
+drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ Launcher *launcher)
+{
+ GdkAtom ret_atom = NULL;
+
+ if (!panel_check_dnd_target_data (widget, context, NULL, &ret_atom))
+ return FALSE;
+
+ gtk_drag_get_data (widget, context, ret_atom, time);
+
+ return TRUE;
+}
+
+static void
+drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ Launcher *launcher)
+{
+ PanelToplevel *toplevel;
+
+ do_highlight (widget, FALSE);
+
+ toplevel = PANEL_TOPLEVEL (widget);
+ panel_toplevel_queue_auto_hide (toplevel);
+}
+
+void
+panel_receive_dnd_data (PanelWidget *panel,
+ guint info,
+ int pos,
+ GtkSelectionData *selection_data,
+ GdkDragContext *context,
+ guint time_)
+{
+ const guchar *data;
+ gboolean success = FALSE;
+
+ if (panel_lockdown_get_locked_down ()) {
+ gtk_drag_finish (context, FALSE, FALSE, time_);
+ return;
+ }
+
+ data = gtk_selection_data_get_data (selection_data);
+
+ switch (info) {
+ case TARGET_URL:
+ success = drop_urilist (panel, pos, (char *)data);
+ break;
+ case TARGET_NETSCAPE_URL:
+ success = drop_url (panel, pos, (char *)data);
+ break;
+ case TARGET_COLOR:
+ success = set_background_color (panel->toplevel, (guint16 *) data);
+ break;
+ case TARGET_BGIMAGE:
+ success = set_background_image_from_uri (panel->toplevel, (char *) data);
+ break;
+ case TARGET_BACKGROUND_RESET:
+ if (panel_profile_is_writable_background_type (panel->toplevel)) {
+ panel_profile_set_background_type (panel->toplevel, PANEL_BACK_NONE);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+ break;
+ case TARGET_DIRECTORY:
+ success = drop_uri (panel, pos, (char *)data,
+ PANEL_ICON_FOLDER);
+ break;
+ case TARGET_APPLET:
+ if (!gtk_selection_data_get_data (selection_data)) {
+ gtk_drag_finish (context, FALSE, FALSE, time_);
+ return;
+ }
+ if (panel_profile_id_lists_are_writable ()) {
+ mate_panel_applet_frame_create (panel->toplevel, pos, (char *) data);
+ success = TRUE;
+ } else {
+ success = FALSE;
+ }
+ break;
+ case TARGET_APPLET_INTERNAL:
+ success = drop_internal_applet (panel, pos, (char *)data,
+ gdk_drag_context_get_selected_action (context));
+ break;
+ case TARGET_ICON_INTERNAL:
+ success = drop_internal_icon (panel, pos, (char *)data,
+ gdk_drag_context_get_selected_action (context));
+ break;
+ default:
+ gtk_drag_finish (context, FALSE, FALSE, time_);
+ return;
+ }
+
+ gtk_drag_finish (context, success, FALSE, time_);
+}
+
+static void
+drag_data_recieved_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ PanelWidget *panel_widget;
+ int pos;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (widget));
+
+ /* we use this only to really find out the info, we already
+ know this is an ok drop site and the info that got passed
+ to us is bogus (it's always 0 in fact) */
+ if (!panel_check_dnd_target_data (widget, context, &info, NULL)) {
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ return;
+ }
+
+ panel_widget = panel_toplevel_get_panel_widget (PANEL_TOPLEVEL (widget));
+
+ pos = panel_widget_get_cursorloc (panel_widget);
+
+ /*
+ * -1 passed to mate_panel_applet_register will turn on
+ * the insert_at_pos flag for panel_widget_add_full,
+ * which will not place it after the first applet.
+ */
+ if(pos < 0)
+ pos = -1;
+ else if(pos > panel_widget->size)
+ pos = panel_widget->size;
+
+ panel_receive_dnd_data (
+ panel_widget, info, pos, selection_data, context, time);
+}
+
+static void
+panel_widget_setup(PanelWidget *panel)
+{
+ g_signal_connect (G_OBJECT(panel),
+ "applet_added",
+ G_CALLBACK(mate_panel_applet_added),
+ NULL);
+ g_signal_connect (G_OBJECT(panel),
+ "applet_removed",
+ G_CALLBACK(mate_panel_applet_removed),
+ NULL);
+ g_signal_connect (G_OBJECT(panel),
+ "applet_move",
+ G_CALLBACK(mate_panel_applet_move),
+ NULL);
+ g_signal_connect (G_OBJECT (panel),
+ "back_change",
+ G_CALLBACK (panel_back_change),
+ NULL);
+ g_signal_connect (G_OBJECT (panel),
+ "size_change",
+ G_CALLBACK (panel_size_change),
+ NULL);
+}
+
+PanelData *
+panel_setup (PanelToplevel *toplevel)
+{
+ PanelWidget *panel_widget;
+ PanelData *pd;
+
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+
+ pd = g_new0 (PanelData,1);
+ pd->menu = NULL;
+ pd->panel = GTK_WIDGET (toplevel);
+ pd->insertion_pos = -1;
+ pd->deactivate_idle = 0;
+
+ panel_list = g_slist_append (panel_list, pd);
+
+ g_object_set_data (G_OBJECT (toplevel), "PanelData", pd);
+
+ panel_lockdown_notify_add (G_CALLBACK (panel_recreate_context_menu),
+ pd);
+
+ panel_widget_setup (panel_widget);
+
+ g_signal_connect (toplevel, "drag_data_received",
+ G_CALLBACK (drag_data_recieved_cb), NULL);
+ g_signal_connect (toplevel, "drag_motion",
+ G_CALLBACK (drag_motion_cb), NULL);
+ g_signal_connect (toplevel, "drag_leave",
+ G_CALLBACK (drag_leave_cb), NULL);
+ g_signal_connect (toplevel, "drag_drop",
+ G_CALLBACK (drag_drop_cb), NULL);
+
+ gtk_drag_dest_set (GTK_WIDGET (toplevel), 0, NULL, 0, 0);
+
+ g_signal_connect (toplevel, "key-press-event",
+ G_CALLBACK (panel_key_press_event), NULL);
+ g_signal_connect (toplevel, "button-press-event",
+ G_CALLBACK (panel_button_press_event), NULL);
+ g_signal_connect (toplevel, "popup-menu",
+ G_CALLBACK (panel_popup_menu_signal), NULL);
+
+ g_signal_connect_swapped (toplevel, "notify::orientation",
+ G_CALLBACK (panel_orient_change), panel_widget);
+
+ g_signal_connect (toplevel, "destroy", G_CALLBACK (panel_destroy), pd);
+
+ return pd;
+}
+
+GdkScreen *
+panel_screen_from_panel_widget (PanelWidget *panel)
+{
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), NULL);
+ g_return_val_if_fail (PANEL_IS_TOPLEVEL (panel->toplevel), NULL);
+
+ return gtk_window_get_screen (GTK_WINDOW (panel->toplevel));
+}
+
+gboolean
+panel_is_applet_right_stick (GtkWidget *applet)
+{
+ GtkWidget *parent;
+ PanelWidget *panel_widget;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (applet), FALSE);
+
+ parent = gtk_widget_get_parent (applet);
+
+ g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
+
+ panel_widget = PANEL_WIDGET (parent);
+
+ if (!panel_toplevel_get_expand (panel_widget->toplevel))
+ return FALSE;
+
+ return panel_widget_is_applet_stuck (panel_widget, applet);
+}
+
+static void
+panel_delete_without_query (PanelToplevel *toplevel)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+
+ if (panel_toplevel_get_is_attached (toplevel) &&
+ panel_widget->master_widget) {
+ AppletInfo *info;
+
+ info = g_object_get_data (G_OBJECT (panel_widget->master_widget),
+ "applet_info");
+
+ panel_profile_delete_object (info);
+ } else
+ panel_profile_delete_toplevel (toplevel);
+}
+
+static void
+panel_deletion_response (GtkWidget *dialog,
+ int response,
+ PanelToplevel *toplevel)
+{
+ if (response == GTK_RESPONSE_OK) {
+ panel_push_window_busy (dialog);
+ panel_delete_without_query (toplevel);
+ panel_pop_window_busy (dialog);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+panel_deletion_destroy_dialog (GtkWidget *widget,
+ PanelToplevel *toplevel)
+{
+ panel_toplevel_pop_autohide_disabler (toplevel);
+ g_object_set_data (G_OBJECT (toplevel), "panel-delete-dialog", NULL);
+}
+
+GtkWidget *
+panel_deletion_dialog (PanelToplevel *toplevel)
+{
+
+ GtkWidget *dialog;
+ char *text1;
+ char *text2;
+
+ if (panel_toplevel_get_is_attached (toplevel)) {
+ text1 = _("Delete this drawer?");
+ text2 = _("When a drawer is deleted, the drawer and its\n"
+ "settings are lost.");
+ } else {
+ text1 = _("Delete this panel?");
+ text2 = _("When a panel is deleted, the panel and its\n"
+ "settings are lost.");
+ }
+
+ dialog = gtk_message_dialog_new (
+ GTK_WINDOW (toplevel),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "%s", text1);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", text2);
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_DELETE, GTK_RESPONSE_OK,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_window_get_screen (GTK_WINDOW (toplevel)));
+
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (panel_deletion_destroy_dialog),
+ toplevel);
+
+ g_object_set_data (G_OBJECT (toplevel), "panel-delete-dialog", dialog);
+ panel_toplevel_push_autohide_disabler (toplevel);
+
+ return dialog;
+}
+
+static void
+panel_query_deletion (PanelToplevel *toplevel)
+{
+ GtkWidget *dialog;
+
+ dialog = g_object_get_data (G_OBJECT (toplevel), "panel-delete-dialog");
+
+ if (dialog) {
+ gtk_window_present (GTK_WINDOW (dialog));
+ return;
+ }
+
+ dialog = panel_deletion_dialog (toplevel);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (panel_deletion_response),
+ toplevel);
+
+ g_signal_connect_object (toplevel, "destroy",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog,
+ G_CONNECT_SWAPPED);
+
+ gtk_widget_show_all (dialog);
+}
+
+void
+panel_delete (PanelToplevel *toplevel)
+{
+ PanelWidget *panel_widget;
+
+ panel_widget = panel_toplevel_get_panel_widget (toplevel);
+
+ if (!panel_global_config_get_confirm_panel_remove () ||
+ !g_list_length (panel_widget->applet_list)) {
+ panel_delete_without_query (toplevel);
+ return;
+ }
+
+ panel_query_deletion (toplevel);
+}
diff --git a/mate-panel/panel.h b/mate-panel/panel.h
new file mode 100644
index 00000000..3cb773a6
--- /dev/null
+++ b/mate-panel/panel.h
@@ -0,0 +1,57 @@
+#ifndef PANEL_H
+#define PANEL_H
+
+#include <gtk/gtk.h>
+#include "panel-toplevel.h"
+#include "panel-widget.h"
+#include "applet.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _PanelData PanelData;
+struct _PanelData {
+ GtkWidget *panel;
+ GtkWidget *menu;
+ int insertion_pos;
+ guint deactivate_idle;
+};
+
+void orientation_change(AppletInfo *info, PanelWidget *panel);
+void size_change(AppletInfo *info, PanelWidget *panel);
+void back_change(AppletInfo *info, PanelWidget *panel);
+
+PanelData *panel_setup (PanelToplevel *toplevel);
+
+GdkScreen *panel_screen_from_panel_widget (PanelWidget *panel);
+
+gboolean panel_is_applet_right_stick (GtkWidget *applet);
+
+
+gboolean panel_check_dnd_target_data (GtkWidget *widget,
+ GdkDragContext *context,
+ guint *ret_info,
+ GdkAtom *ret_atom);
+
+void panel_receive_dnd_data (PanelWidget *panel,
+ guint info,
+ int pos,
+ GtkSelectionData *selection_data,
+ GdkDragContext *context,
+ guint time_);
+
+gboolean panel_check_drop_forbidden (PanelWidget *panel,
+ GdkDragContext *context,
+ guint info,
+ guint time_);
+
+void panel_delete (PanelToplevel *toplevel);
+
+GtkWidget *panel_deletion_dialog (PanelToplevel *toplevel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mate-panel/xstuff.c b/mate-panel/xstuff.c
new file mode 100644
index 00000000..6bcc3396
--- /dev/null
+++ b/mate-panel/xstuff.c
@@ -0,0 +1,736 @@
+/*
+ * MATE panel x stuff
+ *
+ * Copyright (C) 2000, 2001 Eazel, Inc.
+ * 2002 Sun Microsystems Inc.
+ *
+ * Authors: George Lebl <[email protected]>
+ * Mark McLoughlin <[email protected]>
+ *
+ * Contains code from the Window Maker window manager
+ *
+ * Copyright (c) 1997-2002 Alfredo K. Kojima
+
+ */
+#include <config.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "panel-enums.h"
+#include "xstuff.h"
+
+static int (* xstuff_old_xio_error_handler) (Display *) = NULL;
+static int (* xstuff_old_x_error_handler) (Display *, XErrorEvent *);
+static gboolean xstuff_display_is_dead = FALSE;
+
+static Atom
+panel_atom_get (const char *atom_name)
+{
+ static GHashTable *atom_hash;
+ Display *xdisplay;
+ Atom retval;
+
+ g_return_val_if_fail (atom_name != NULL, None);
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ if (!atom_hash)
+ atom_hash = g_hash_table_new_full (
+ g_str_hash, g_str_equal, g_free, NULL);
+
+ retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
+ if (!retval) {
+ retval = XInternAtom (xdisplay, atom_name, FALSE);
+
+ if (retval != None)
+ g_hash_table_insert (atom_hash, g_strdup (atom_name),
+ GUINT_TO_POINTER (retval));
+ }
+
+ return retval;
+}
+
+/* Stolen from deskguide */
+static gpointer
+get_typed_property_data (Display *xdisplay,
+ Window xwindow,
+ Atom property,
+ Atom requested_type,
+ gint *size_p,
+ guint expected_format)
+{
+ static const guint prop_buffer_lengh = 1024 * 1024;
+ unsigned char *prop_data = NULL;
+ Atom type_returned = 0;
+ unsigned long nitems_return = 0, bytes_after_return = 0;
+ int format_returned = 0;
+ gpointer data = NULL;
+ gboolean abort = FALSE;
+
+ g_return_val_if_fail (size_p != NULL, NULL);
+ *size_p = 0;
+
+ gdk_error_trap_push ();
+
+ abort = XGetWindowProperty (xdisplay,
+ xwindow,
+ property,
+ 0, prop_buffer_lengh,
+ False,
+ requested_type,
+ &type_returned, &format_returned,
+ &nitems_return,
+ &bytes_after_return,
+ &prop_data) != Success;
+ if (gdk_error_trap_pop () ||
+ type_returned == None)
+ abort++;
+ if (!abort &&
+ requested_type != AnyPropertyType &&
+ requested_type != type_returned)
+ {
+ g_warning ("%s(): Property has wrong type, probably on crack", G_STRFUNC);
+ abort++;
+ }
+ if (!abort && bytes_after_return)
+ {
+ g_warning ("%s(): Eeek, property has more than %u bytes, stored on harddisk?",
+ G_STRFUNC, prop_buffer_lengh);
+ abort++;
+ }
+ if (!abort && expected_format && expected_format != format_returned)
+ {
+ g_warning ("%s(): Expected format (%u) unmatched (%d), programmer was drunk?",
+ G_STRFUNC, expected_format, format_returned);
+ abort++;
+ }
+ if (!abort && prop_data && nitems_return && format_returned)
+ {
+ switch (format_returned)
+ {
+ case 32:
+ *size_p = nitems_return * 4;
+ if (sizeof (gulong) == 8)
+ {
+ guint32 i, *mem = g_malloc0 (*size_p + 1);
+ gulong *prop_longs = (gulong*) prop_data;
+
+ for (i = 0; i < *size_p / 4; i++)
+ mem[i] = prop_longs[i];
+ data = mem;
+ }
+ break;
+ case 16:
+ *size_p = nitems_return * 2;
+ break;
+ case 8:
+ *size_p = nitems_return;
+ break;
+ default:
+ g_warning ("Unknown property data format with %d bits (extraterrestrial?)",
+ format_returned);
+ break;
+ }
+ if (!data && *size_p)
+ {
+ guint8 *mem = g_malloc (*size_p + 1);
+
+ memcpy (mem, prop_data, *size_p);
+ mem[*size_p] = 0;
+ data = mem;
+ }
+ }
+
+ if (prop_data)
+ XFree (prop_data);
+
+ return data;
+}
+
+gboolean
+xstuff_is_compliant_wm (void)
+{
+ Display *xdisplay;
+ Window root_window;
+ gpointer data;
+ int size;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ root_window = GDK_WINDOW_XWINDOW (
+ gdk_get_default_root_window ());
+
+ /* FIXME this is totally broken; should be using
+ * gdk_net_wm_supports() on particular hints when we rely
+ * on those particular hints
+ */
+ data = get_typed_property_data (
+ xdisplay, root_window,
+ panel_atom_get ("_NET_SUPPORTED"),
+ XA_ATOM, &size, 32);
+
+ if (!data)
+ return FALSE;
+
+ /* Actually checks for some of these */
+ g_free (data);
+ return TRUE;
+}
+
+gboolean
+xstuff_net_wm_supports (const char *hint)
+{
+ return gdk_net_wm_supports (gdk_atom_intern (hint, FALSE));
+}
+
+/* This is such a broken stupid function. */
+void
+xstuff_set_pos_size (GdkWindow *window, int x, int y, int w, int h)
+{
+ XSizeHints size_hints;
+ int old_x, old_y, old_w, old_h;
+
+ old_x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-x"));
+ old_y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-y"));
+ old_w = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-w"));
+ old_h = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-h"));
+
+ if (x == old_x && y == old_y && w == old_w && h == old_h)
+ return;
+
+ /* Do not add USPosition / USSize here, fix the damn WM */
+ size_hints.flags = PPosition | PSize | PMaxSize | PMinSize;
+ size_hints.x = 0; /* window managers aren't supposed to and */
+ size_hints.y = 0; /* don't use these fields */
+ size_hints.width = w;
+ size_hints.height = h;
+ size_hints.min_width = w;
+ size_hints.min_height = h;
+ size_hints.max_width = w;
+ size_hints.max_height = h;
+
+ gdk_error_trap_push ();
+
+ XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ &size_hints);
+
+ gdk_window_move_resize (window, x, y, w, h);
+
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+ g_object_set_data (G_OBJECT (window), "xstuff-cached-x", GINT_TO_POINTER (x));
+ g_object_set_data (G_OBJECT (window), "xstuff-cached-y", GINT_TO_POINTER (y));
+ g_object_set_data (G_OBJECT (window), "xstuff-cached-w", GINT_TO_POINTER (w));
+ g_object_set_data (G_OBJECT (window), "xstuff-cached-h", GINT_TO_POINTER (h));
+}
+
+void
+xstuff_set_wmspec_dock_hints (GdkWindow *window,
+ gboolean autohide)
+{
+ Atom atoms [2] = { None, None };
+
+ if (!autohide)
+ atoms [0] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
+ else {
+ atoms [0] = panel_atom_get ("_MATE_WINDOW_TYPE_AUTOHIDE_PANEL");
+ atoms [1] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
+ }
+
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ panel_atom_get ("_NET_WM_WINDOW_TYPE"),
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) atoms,
+ autohide ? 2 : 1);
+}
+
+void
+xstuff_set_wmspec_strut (GdkWindow *window,
+ int left,
+ int right,
+ int top,
+ int bottom)
+{
+ long vals [4];
+
+ vals [0] = left;
+ vals [1] = right;
+ vals [2] = top;
+ vals [3] = bottom;
+
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ panel_atom_get ("_NET_WM_STRUT"),
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) vals, 4);
+}
+
+void
+xstuff_delete_property (GdkWindow *window, const char *name)
+{
+ Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+ Window xwindow = GDK_WINDOW_XWINDOW (window);
+
+ XDeleteProperty (xdisplay, xwindow,
+ panel_atom_get (name));
+}
+
+/* Zoom animation */
+#define MINIATURIZE_ANIMATION_FRAMES_Z 1
+#define MINIATURIZE_ANIMATION_STEPS_Z 6
+/* the delay per draw */
+#define MINIATURIZE_ANIMATION_DELAY_Z 10
+
+/* zoom factor, steps and delay if composited (factor must be odd) */
+#define ZOOM_FACTOR 5
+#define ZOOM_STEPS 14
+#define ZOOM_DELAY 10
+
+typedef struct {
+ int size;
+ int size_start;
+ int size_end;
+ PanelOrientation orientation;
+ double opacity;
+ GdkPixbuf *pixbuf;
+ guint timeout_id;
+} CompositedZoomData;
+
+static gboolean
+zoom_timeout (GtkWidget *window)
+{
+ gtk_widget_queue_draw (window);
+ return TRUE;
+}
+
+static gboolean
+zoom_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data)
+{
+ CompositedZoomData *zoom;
+
+ zoom = user_data;
+
+ if (zoom->size >= zoom->size_end) {
+ if (zoom->timeout_id)
+ g_source_remove (zoom->timeout_id);
+ zoom->timeout_id = 0;
+
+ g_object_unref (zoom->pixbuf);
+ zoom->pixbuf = NULL;
+
+ g_slice_free (CompositedZoomData, zoom);
+
+ gtk_widget_destroy (widget);
+ } else {
+ GdkPixbuf *scaled;
+ int width, height;
+ int x = 0, y = 0;
+ cairo_t *cr;
+
+ gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
+
+ zoom->size += MAX ((zoom->size_end - zoom->size_start) / ZOOM_STEPS, 1);
+ zoom->opacity -= 1.0 / ((double) ZOOM_STEPS + 1);
+
+ scaled = gdk_pixbuf_scale_simple (zoom->pixbuf,
+ zoom->size, zoom->size,
+ GDK_INTERP_BILINEAR);
+
+ switch (zoom->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ x = (width - gdk_pixbuf_get_width (scaled)) / 2;
+ y = 0;
+ break;
+
+ case PANEL_ORIENTATION_RIGHT:
+ x = width - gdk_pixbuf_get_width (scaled);
+ y = (height - gdk_pixbuf_get_height (scaled)) / 2;
+ break;
+
+ case PANEL_ORIENTATION_BOTTOM:
+ x = (width - gdk_pixbuf_get_width (scaled)) / 2;
+ y = height - gdk_pixbuf_get_height (scaled);
+ break;
+
+ case PANEL_ORIENTATION_LEFT:
+ x = 0;
+ y = (height - gdk_pixbuf_get_height (scaled)) / 2;
+ break;
+ }
+
+
+ cr = gdk_cairo_create (gtk_widget_get_window (widget));
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.0);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, scaled, x, y);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_paint_with_alpha (cr, MAX (zoom->opacity, 0));
+
+ cairo_destroy (cr);
+ g_object_unref (scaled);
+ }
+
+ return FALSE;
+}
+
+static void
+draw_zoom_animation_composited (GdkScreen *gscreen,
+ int x, int y, int w, int h,
+ GdkPixbuf *pixbuf,
+ PanelOrientation orientation)
+{
+ GtkWidget *win;
+ CompositedZoomData *zoom;
+ int wx = 0, wy = 0;
+
+ w += 2;
+ h += 2;
+
+ zoom = g_slice_new (CompositedZoomData);
+ zoom->size = w;
+ zoom->size_start = w;
+ zoom->size_end = w * ZOOM_FACTOR;
+ zoom->orientation = orientation;
+ zoom->opacity = 1.0;
+ zoom->pixbuf = g_object_ref (pixbuf);
+ zoom->timeout_id = 0;
+
+ win = gtk_window_new (GTK_WINDOW_POPUP);
+
+ gtk_window_set_screen (GTK_WINDOW (win), gscreen);
+ gtk_window_set_keep_above (GTK_WINDOW (win), TRUE);
+ gtk_window_set_decorated (GTK_WINDOW (win), FALSE);
+ gtk_widget_set_app_paintable(win, TRUE);
+ gtk_widget_set_colormap (win, gdk_screen_get_rgba_colormap (gscreen));
+
+ gtk_window_set_gravity (GTK_WINDOW (win), GDK_GRAVITY_STATIC);
+ gtk_window_set_default_size (GTK_WINDOW (win),
+ w * ZOOM_FACTOR, h * ZOOM_FACTOR);
+
+ switch (zoom->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ wx = x - w * (ZOOM_FACTOR / 2);
+ wy = y;
+ break;
+
+ case PANEL_ORIENTATION_RIGHT:
+ wx = x - w * (ZOOM_FACTOR - 1);
+ wy = y - h * (ZOOM_FACTOR / 2);
+ break;
+
+ case PANEL_ORIENTATION_BOTTOM:
+ wx = x - w * (ZOOM_FACTOR / 2);
+ wy = y - h * (ZOOM_FACTOR - 1);
+ break;
+
+ case PANEL_ORIENTATION_LEFT:
+ wx = x;
+ wy = y - h * (ZOOM_FACTOR / 2);
+ break;
+ }
+
+ gtk_window_move (GTK_WINDOW (win), wx, wy);
+
+ g_signal_connect (G_OBJECT (win), "expose-event",
+ G_CALLBACK (zoom_expose), zoom);
+
+ /* see doc for gtk_widget_set_app_paintable() */
+ gtk_widget_realize (win);
+ gdk_window_set_back_pixmap (gtk_widget_get_window (win), NULL, FALSE);
+ gtk_widget_show (win);
+
+ zoom->timeout_id = g_timeout_add (ZOOM_DELAY,
+ (GSourceFunc) zoom_timeout,
+ win);
+}
+
+static void
+draw_zoom_animation (GdkScreen *gscreen,
+ int x, int y, int w, int h,
+ int fx, int fy, int fw, int fh,
+ int steps)
+{
+#define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
+ float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
+ int cxi[FRAMES], cyi[FRAMES], cwi[FRAMES], chi[FRAMES];
+ float xstep, ystep, wstep, hstep;
+ int i, j;
+ GC frame_gc;
+ XGCValues gcv;
+ GdkColor color = { 65535, 65535, 65535 };
+ Display *dpy;
+ Window root_win;
+ int screen;
+ int depth;
+
+ dpy = gdk_x11_display_get_xdisplay (gdk_screen_get_display (gscreen));
+ root_win = gdk_x11_drawable_get_xid (gdk_screen_get_root_window (gscreen));
+ screen = gdk_screen_get_number (gscreen);
+ depth = gdk_drawable_get_depth (gdk_screen_get_root_window (gscreen));
+
+ /* frame GC */
+ gdk_colormap_alloc_color (
+ gdk_screen_get_system_colormap (gscreen), &color, FALSE, TRUE);
+ gcv.function = GXxor;
+ /* this will raise the probability of the XORed color being different
+ * of the original color in PseudoColor when not all color cells are
+ * initialized */
+ if (DefaultVisual(dpy, screen)->class==PseudoColor)
+ gcv.plane_mask = (1<<(depth-1))|1;
+ else
+ gcv.plane_mask = AllPlanes;
+ gcv.foreground = color.pixel;
+ if (gcv.foreground == 0)
+ gcv.foreground = 1;
+ gcv.line_width = 1;
+ gcv.subwindow_mode = IncludeInferiors;
+ gcv.graphics_exposures = False;
+
+ frame_gc = XCreateGC(dpy, root_win, GCForeground|GCGraphicsExposures
+ |GCFunction|GCSubwindowMode|GCLineWidth
+ |GCPlaneMask, &gcv);
+
+ xstep = (float)(fx-x)/steps;
+ ystep = (float)(fy-y)/steps;
+ wstep = (float)(fw-w)/steps;
+ hstep = (float)(fh-h)/steps;
+
+ for (j=0; j<FRAMES; j++) {
+ cx[j] = (float)x;
+ cy[j] = (float)y;
+ cw[j] = (float)w;
+ ch[j] = (float)h;
+ cxi[j] = (int)cx[j];
+ cyi[j] = (int)cy[j];
+ cwi[j] = (int)cw[j];
+ chi[j] = (int)ch[j];
+ }
+ XGrabServer(dpy);
+ for (i=0; i<steps; i++) {
+ for (j=0; j<FRAMES; j++) {
+ XDrawRectangle(dpy, root_win, frame_gc, cxi[j], cyi[j], cwi[j], chi[j]);
+ }
+ XFlush(dpy);
+#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
+ usleep(MINIATURIZE_ANIMATION_DELAY_Z);
+#else
+ usleep(10);
+#endif
+ for (j=0; j<FRAMES; j++) {
+ XDrawRectangle(dpy, root_win, frame_gc,
+ cxi[j], cyi[j], cwi[j], chi[j]);
+ if (j<FRAMES-1) {
+ cx[j]=cx[j+1];
+ cy[j]=cy[j+1];
+ cw[j]=cw[j+1];
+ ch[j]=ch[j+1];
+
+ cxi[j]=cxi[j+1];
+ cyi[j]=cyi[j+1];
+ cwi[j]=cwi[j+1];
+ chi[j]=chi[j+1];
+
+ } else {
+ cx[j]+=xstep;
+ cy[j]+=ystep;
+ cw[j]+=wstep;
+ ch[j]+=hstep;
+
+ cxi[j] = (int)cx[j];
+ cyi[j] = (int)cy[j];
+ cwi[j] = (int)cw[j];
+ chi[j] = (int)ch[j];
+ }
+ }
+ }
+
+ for (j=0; j<FRAMES; j++) {
+ XDrawRectangle(dpy, root_win, frame_gc,
+ cxi[j], cyi[j], cwi[j], chi[j]);
+ }
+ XFlush(dpy);
+#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
+ usleep(MINIATURIZE_ANIMATION_DELAY_Z);
+#else
+ usleep(10);
+#endif
+ for (j=0; j<FRAMES; j++) {
+ XDrawRectangle(dpy, root_win, frame_gc,
+ cxi[j], cyi[j], cwi[j], chi[j]);
+ }
+
+ XUngrabServer(dpy);
+ XFreeGC (dpy, frame_gc);
+ gdk_colormap_free_colors (gdk_screen_get_system_colormap (gscreen),
+ &color, 1);
+
+}
+#undef FRAMES
+
+void
+xstuff_zoom_animate (GtkWidget *widget,
+ GdkPixbuf *pixbuf,
+ PanelOrientation orientation,
+ GdkRectangle *opt_rect)
+{
+ GdkScreen *gscreen;
+ GdkRectangle rect, dest;
+ GtkAllocation allocation;
+ int monitor;
+
+ if (opt_rect)
+ rect = *opt_rect;
+ else {
+ gdk_window_get_origin (gtk_widget_get_window (widget), &rect.x, &rect.y);
+ gtk_widget_get_allocation (widget, &allocation);
+ if (!gtk_widget_get_has_window (widget)) {
+ rect.x += allocation.x;
+ rect.y += allocation.y;
+ }
+ rect.height = allocation.height;
+ rect.width = allocation.width;
+ }
+
+ gscreen = gtk_widget_get_screen (widget);
+
+ if (gdk_screen_is_composited (gscreen) && pixbuf)
+ draw_zoom_animation_composited (gscreen,
+ rect.x, rect.y,
+ rect.width, rect.height,
+ pixbuf, orientation);
+ else {
+ monitor = gdk_screen_get_monitor_at_window (gscreen,
+ gtk_widget_get_window (widget));
+ gdk_screen_get_monitor_geometry (gscreen, monitor, &dest);
+
+ draw_zoom_animation (gscreen,
+ rect.x, rect.y, rect.width, rect.height,
+ dest.x, dest.y, dest.width, dest.height,
+ MINIATURIZE_ANIMATION_STEPS_Z);
+ }
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+}
+
+int
+xstuff_get_current_workspace (GdkScreen *screen)
+{
+ Window root_window;
+ Atom type = None;
+ gulong nitems;
+ gulong bytes_after;
+ gulong *num;
+ int format;
+ int result;
+ int retval;
+
+ root_window = gdk_x11_drawable_get_xid (
+ gdk_screen_get_root_window (screen));
+
+ gdk_error_trap_push ();
+ result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen)),
+ root_window,
+ panel_atom_get ("_NET_CURRENT_DESKTOP"),
+ 0, G_MAXLONG,
+ False, XA_CARDINAL, &type, &format, &nitems,
+ &bytes_after, (gpointer) &num);
+ if (gdk_error_trap_pop () || result != Success)
+ return -1;
+
+ if (type != XA_CARDINAL) {
+ XFree (num);
+ return -1;
+ }
+
+ retval = *num;
+
+ XFree (num);
+
+ return retval;
+}
+
+void
+xstuff_grab_key_on_all_screens (int keycode,
+ guint modifiers,
+ gboolean grab)
+{
+ GdkDisplay *display;
+ int n_screens;
+ int i;
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+
+ for (i = 0; i < n_screens; i++) {
+ GdkWindow *root;
+
+ root = gdk_screen_get_root_window (
+ gdk_display_get_screen (display, i));
+
+ if (grab)
+ XGrabKey (gdk_x11_display_get_xdisplay (display),
+ keycode, modifiers,
+ gdk_x11_drawable_get_xid (root),
+ True, GrabModeAsync, GrabModeAsync);
+ else
+ XUngrabKey (gdk_x11_display_get_xdisplay (display),
+ keycode, modifiers,
+ gdk_x11_drawable_get_xid (root));
+ }
+}
+
+static int
+xstuff_xio_error_handler (Display *display)
+{
+ xstuff_display_is_dead = TRUE;
+
+ if (xstuff_old_xio_error_handler)
+ return xstuff_old_xio_error_handler (display);
+
+ return 0;
+}
+
+gboolean
+xstuff_is_display_dead (void)
+{
+ return xstuff_display_is_dead;
+}
+
+static int
+xstuff_x_error_handler (Display *display, XErrorEvent *error)
+{
+ if (!error->error_code)
+ return 0;
+
+ /* If we got a BadDrawable or a BadWindow, we ignore it for now.
+ * FIXME: We need to somehow distinguish real errors from
+ * X-server-induced errors. Keeping a list of windows for which we will
+ * ignore BadDrawables would be a good idea. */
+ if (error->error_code == BadDrawable ||
+ error->error_code == BadWindow)
+ return 0;
+
+ return xstuff_old_x_error_handler (display, error);
+}
+
+void
+xstuff_init (void)
+{
+ xstuff_old_xio_error_handler = XSetIOErrorHandler (xstuff_xio_error_handler);
+ xstuff_old_x_error_handler = XSetErrorHandler (xstuff_x_error_handler);
+}
diff --git a/mate-panel/xstuff.h b/mate-panel/xstuff.h
new file mode 100644
index 00000000..0bd5f92b
--- /dev/null
+++ b/mate-panel/xstuff.h
@@ -0,0 +1,39 @@
+#ifndef __XSTUFF_H__
+#define __XSTUFF_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+void xstuff_delete_property (GdkWindow *window,
+ const char *name);
+gboolean xstuff_is_compliant_wm (void);
+gboolean xstuff_net_wm_supports (const char *hint);
+
+void xstuff_unsetup_desktop_area (void);
+void xstuff_set_pos_size (GdkWindow *window,
+ int x, int y,
+ int w, int h);
+void xstuff_set_wmspec_dock_hints (GdkWindow *window,
+ gboolean autohide);
+void xstuff_set_wmspec_strut (GdkWindow *window,
+ int left,
+ int right,
+ int top,
+ int bottom);
+
+void xstuff_zoom_animate (GtkWidget *widget,
+ GdkPixbuf *pixbuf,
+ PanelOrientation orientation,
+ GdkRectangle *opt_src_rect);
+
+int xstuff_get_current_workspace (GdkScreen *screen);
+
+void xstuff_grab_key_on_all_screens (int keycode,
+ guint modifiers,
+ gboolean grab);
+
+gboolean xstuff_is_display_dead (void);
+
+void xstuff_init (void);
+
+#endif /* __XSTUFF_H__ */