From c51ef797a707f4e2c6f9688d4378f2b0e9898a66 Mon Sep 17 00:00:00 2001 From: Perberos Date: Thu, 1 Dec 2011 22:56:10 -0300 Subject: moving from https://github.com/perberos/mate-desktop-environment --- applets/notification_area/Makefile.am | 112 +++ applets/notification_area/Makefile.in | 964 +++++++++++++++++++++ applets/notification_area/fixedtip.c | 269 ++++++ applets/notification_area/fixedtip.h | 72 ++ applets/notification_area/main.c | 267 ++++++ applets/notification_area/na-marshal.c | 167 ++++ applets/notification_area/na-marshal.h | 36 + applets/notification_area/na-marshal.list | 3 + applets/notification_area/na-tray-child.c | 539 ++++++++++++ applets/notification_area/na-tray-child.h | 75 ++ applets/notification_area/na-tray-manager.c | 859 ++++++++++++++++++ applets/notification_area/na-tray-manager.h | 101 +++ applets/notification_area/na-tray.c | 837 ++++++++++++++++++ applets/notification_area/na-tray.h | 71 ++ .../notification_area/notification-area-menu.xml | 3 + ....NotificationAreaApplet.mate-panel-applet.in.in | 17 + ...applet.NotificationAreaAppletFactory.service.in | 3 + applets/notification_area/testtray.c | 220 +++++ 18 files changed, 4615 insertions(+) create mode 100644 applets/notification_area/Makefile.am create mode 100644 applets/notification_area/Makefile.in create mode 100644 applets/notification_area/fixedtip.c create mode 100644 applets/notification_area/fixedtip.h create mode 100644 applets/notification_area/main.c create mode 100644 applets/notification_area/na-marshal.c create mode 100644 applets/notification_area/na-marshal.h create mode 100644 applets/notification_area/na-marshal.list create mode 100644 applets/notification_area/na-tray-child.c create mode 100644 applets/notification_area/na-tray-child.h create mode 100644 applets/notification_area/na-tray-manager.c create mode 100644 applets/notification_area/na-tray-manager.h create mode 100644 applets/notification_area/na-tray.c create mode 100644 applets/notification_area/na-tray.h create mode 100644 applets/notification_area/notification-area-menu.xml create mode 100644 applets/notification_area/org.mate.panel.NotificationAreaApplet.mate-panel-applet.in.in create mode 100644 applets/notification_area/org.mate.panel.applet.NotificationAreaAppletFactory.service.in create mode 100644 applets/notification_area/testtray.c (limited to 'applets/notification_area') diff --git a/applets/notification_area/Makefile.am b/applets/notification_area/Makefile.am new file mode 100644 index 00000000..8609eff9 --- /dev/null +++ b/applets/notification_area/Makefile.am @@ -0,0 +1,112 @@ +noinst_LTLIBRARIES = libtray.la +noinst_PROGRAMS = testtray + +AM_CPPFLAGS = \ + $(NOTIFICATION_AREA_CFLAGS) \ + $(LIBMATE_PANEL_APPLET_CFLAGS) \ + -I$(srcdir) \ + -I$(srcdir)/../../libmate-panel-applet \ + -I$(top_builddir)/libmate-panel-applet \ + -DMATELOCALEDIR=\""$(datadir)/locale"\" \ + -DG_LOG_DOMAIN=\""notification-area-applet"\" \ + -DNOTIFICATION_AREA_MENU_UI_DIR=\""$(uidir)"\" \ + $(DISABLE_DEPRECATED_CFLAGS) + +AM_CFLAGS = $(WARN_CFLAGS) + +libtray_la_SOURCES = \ + fixedtip.h \ + fixedtip.c \ + na-marshal.c \ + na-marshal.h \ + na-tray.c \ + na-tray.h \ + na-tray-child.c \ + na-tray-child.h \ + na-tray-manager.c \ + na-tray-manager.h + +NOTIFICATION_AREA_SOURCES = main.c + +NOTIFICATION_AREA_LDADD = \ + ../../libmate-panel-applet/libmate-panel-applet-3.la \ + libtray.la \ + $(X_LIBS) \ + $(NOTIFICATION_AREA_LIBS) \ + $(LIBMATE_PANEL_APPLET_LIBS) + + +testtray_SOURCES = testtray.c +testtray_LDADD = \ + libtray.la \ + $(X_LIBS) \ + $(NOTIFICATION_AREA_LIBS) + +if NOTIFICATION_AREA_INPROCESS +APPLET_IN_PROCESS = true +APPLET_LOCATION = $(pkglibdir)/libnotification-area-applet.so + +notification_area_appletlibdir = $(pkglibdir) +notification_area_appletlib_LTLIBRARIES = libnotification-area-applet.la +libnotification_area_applet_la_SOURCES = $(NOTIFICATION_AREA_SOURCES) +libnotification_area_applet_la_LIBADD = $(NOTIFICATION_AREA_LDADD) +libnotification_area_applet_la_LDFLAGS = -module -avoid-version +libnotification_area_applet_la_CFLAGS = $(AM_CFLAGS) +else +APPLET_IN_PROCESS = false +APPLET_LOCATION = $(libexecdir)/notification-area-applet + +libexec_PROGRAMS = notification-area-applet +notification_area_applet_SOURCES = $(NOTIFICATION_AREA_SOURCES) +notification_area_applet_LDADD = $(NOTIFICATION_AREA_LDADD) +notification_area_applet_CFLAGS = $(AM_CFLAGS) +endif + +na-marshal.h: na-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --header --prefix=_na_marshal > $@ + +na-marshal.c: na-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN)echo "#include \"na-marshal.h\"" > $@ && \ + $(GLIB_GENMARSHAL) $< --body --prefix=_na_marshal >> $@ + +BUILT_SOURCES = na-marshal.c na-marshal.h + +appletdir = $(datadir)/mate-panel/applets +applet_in_files = org.mate.panel.NotificationAreaApplet.mate-panel-applet.in +applet_DATA = $(applet_in_files:.mate-panel-applet.in=.mate-panel-applet) + +$(applet_in_files): $(applet_in_files).in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \ + -e "s|\@IN_PROCESS\@|$(APPLET_IN_PROCESS)|" \ + -e "s|\@VERSION\@|$(PACKAGE_VERSION)|" \ + $< > $@ + +@PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE@ + +if !NOTIFICATION_AREA_INPROCESS +servicedir = $(datadir)/dbus-1/services +service_in_files = org.mate.panel.applet.NotificationAreaAppletFactory.service.in +service_DATA = $(service_in_files:.service.in=.service) + +org.mate.panel.applet.NotificationAreaAppletFactory.service: $(service_in_files) + $(AM_V_GEN)sed \ + -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \ + $< > $@ +endif + +uidir = $(datadir)/mate-panel/ui +ui_DATA = notification-area-menu.xml + +EXTRA_DIST = \ + org.mate.panel.NotificationAreaApplet.mate-panel-applet.in.in \ + $(ui_DATA) \ + $(service_in_files) \ + na-marshal.list + +CLEANFILES = \ + $(applet_DATA) \ + $(applet_DATA).in \ + $(service_DATA) + +-include $(top_srcdir)/git.mk diff --git a/applets/notification_area/Makefile.in b/applets/notification_area/Makefile.in new file mode 100644 index 00000000..2f73b378 --- /dev/null +++ b/applets/notification_area/Makefile.in @@ -0,0 +1,964 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = testtray$(EXEEXT) +@NOTIFICATION_AREA_INPROCESS_FALSE@libexec_PROGRAMS = notification-area-applet$(EXEEXT) +subdir = applets/notification_area +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 = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(notification_area_appletlibdir)" \ + "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(appletdir)" \ + "$(DESTDIR)$(servicedir)" "$(DESTDIR)$(uidir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) \ + $(notification_area_appletlib_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = \ + ../../libmate-panel-applet/libmate-panel-applet-3.la \ + libtray.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +@NOTIFICATION_AREA_INPROCESS_TRUE@libnotification_area_applet_la_DEPENDENCIES = \ +@NOTIFICATION_AREA_INPROCESS_TRUE@ $(am__DEPENDENCIES_2) +am__libnotification_area_applet_la_SOURCES_DIST = main.c +am__objects_1 = libnotification_area_applet_la-main.lo +@NOTIFICATION_AREA_INPROCESS_TRUE@am_libnotification_area_applet_la_OBJECTS = \ +@NOTIFICATION_AREA_INPROCESS_TRUE@ $(am__objects_1) +libnotification_area_applet_la_OBJECTS = \ + $(am_libnotification_area_applet_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +libnotification_area_applet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libnotification_area_applet_la_CFLAGS) $(CFLAGS) \ + $(libnotification_area_applet_la_LDFLAGS) $(LDFLAGS) -o $@ +@NOTIFICATION_AREA_INPROCESS_TRUE@am_libnotification_area_applet_la_rpath = \ +@NOTIFICATION_AREA_INPROCESS_TRUE@ -rpath \ +@NOTIFICATION_AREA_INPROCESS_TRUE@ $(notification_area_appletlibdir) +libtray_la_LIBADD = +am_libtray_la_OBJECTS = fixedtip.lo na-marshal.lo na-tray.lo \ + na-tray-child.lo na-tray-manager.lo +libtray_la_OBJECTS = $(am_libtray_la_OBJECTS) +PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) +am__notification_area_applet_SOURCES_DIST = main.c +am__objects_2 = notification_area_applet-main.$(OBJEXT) +@NOTIFICATION_AREA_INPROCESS_FALSE@am_notification_area_applet_OBJECTS = \ +@NOTIFICATION_AREA_INPROCESS_FALSE@ $(am__objects_2) +notification_area_applet_OBJECTS = \ + $(am_notification_area_applet_OBJECTS) +@NOTIFICATION_AREA_INPROCESS_FALSE@notification_area_applet_DEPENDENCIES = \ +@NOTIFICATION_AREA_INPROCESS_FALSE@ $(am__DEPENDENCIES_2) +notification_area_applet_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(notification_area_applet_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_testtray_OBJECTS = testtray.$(OBJEXT) +testtray_OBJECTS = $(am_testtray_OBJECTS) +testtray_DEPENDENCIES = libtray.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(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 = $(libnotification_area_applet_la_SOURCES) \ + $(libtray_la_SOURCES) $(notification_area_applet_SOURCES) \ + $(testtray_SOURCES) +DIST_SOURCES = $(am__libnotification_area_applet_la_SOURCES_DIST) \ + $(libtray_la_SOURCES) \ + $(am__notification_area_applet_SOURCES_DIST) \ + $(testtray_SOURCES) +DATA = $(applet_DATA) $(service_DATA) $(ui_DATA) +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 = libtray.la +AM_CPPFLAGS = \ + $(NOTIFICATION_AREA_CFLAGS) \ + $(LIBMATE_PANEL_APPLET_CFLAGS) \ + -I$(srcdir) \ + -I$(srcdir)/../../libmate-panel-applet \ + -I$(top_builddir)/libmate-panel-applet \ + -DMATELOCALEDIR=\""$(datadir)/locale"\" \ + -DG_LOG_DOMAIN=\""notification-area-applet"\" \ + -DNOTIFICATION_AREA_MENU_UI_DIR=\""$(uidir)"\" \ + $(DISABLE_DEPRECATED_CFLAGS) + +AM_CFLAGS = $(WARN_CFLAGS) +libtray_la_SOURCES = \ + fixedtip.h \ + fixedtip.c \ + na-marshal.c \ + na-marshal.h \ + na-tray.c \ + na-tray.h \ + na-tray-child.c \ + na-tray-child.h \ + na-tray-manager.c \ + na-tray-manager.h + +NOTIFICATION_AREA_SOURCES = main.c +NOTIFICATION_AREA_LDADD = \ + ../../libmate-panel-applet/libmate-panel-applet-3.la \ + libtray.la \ + $(X_LIBS) \ + $(NOTIFICATION_AREA_LIBS) \ + $(LIBMATE_PANEL_APPLET_LIBS) + +testtray_SOURCES = testtray.c +testtray_LDADD = \ + libtray.la \ + $(X_LIBS) \ + $(NOTIFICATION_AREA_LIBS) + +@NOTIFICATION_AREA_INPROCESS_FALSE@APPLET_IN_PROCESS = false +@NOTIFICATION_AREA_INPROCESS_TRUE@APPLET_IN_PROCESS = true +@NOTIFICATION_AREA_INPROCESS_FALSE@APPLET_LOCATION = $(libexecdir)/notification-area-applet +@NOTIFICATION_AREA_INPROCESS_TRUE@APPLET_LOCATION = $(pkglibdir)/libnotification-area-applet.so +@NOTIFICATION_AREA_INPROCESS_TRUE@notification_area_appletlibdir = $(pkglibdir) +@NOTIFICATION_AREA_INPROCESS_TRUE@notification_area_appletlib_LTLIBRARIES = libnotification-area-applet.la +@NOTIFICATION_AREA_INPROCESS_TRUE@libnotification_area_applet_la_SOURCES = $(NOTIFICATION_AREA_SOURCES) +@NOTIFICATION_AREA_INPROCESS_TRUE@libnotification_area_applet_la_LIBADD = $(NOTIFICATION_AREA_LDADD) +@NOTIFICATION_AREA_INPROCESS_TRUE@libnotification_area_applet_la_LDFLAGS = -module -avoid-version +@NOTIFICATION_AREA_INPROCESS_TRUE@libnotification_area_applet_la_CFLAGS = $(AM_CFLAGS) +@NOTIFICATION_AREA_INPROCESS_FALSE@notification_area_applet_SOURCES = $(NOTIFICATION_AREA_SOURCES) +@NOTIFICATION_AREA_INPROCESS_FALSE@notification_area_applet_LDADD = $(NOTIFICATION_AREA_LDADD) +@NOTIFICATION_AREA_INPROCESS_FALSE@notification_area_applet_CFLAGS = $(AM_CFLAGS) +BUILT_SOURCES = na-marshal.c na-marshal.h +appletdir = $(datadir)/mate-panel/applets +applet_in_files = org.mate.panel.NotificationAreaApplet.mate-panel-applet.in +applet_DATA = $(applet_in_files:.mate-panel-applet.in=.mate-panel-applet) +@NOTIFICATION_AREA_INPROCESS_FALSE@servicedir = $(datadir)/dbus-1/services +@NOTIFICATION_AREA_INPROCESS_FALSE@service_in_files = org.mate.panel.applet.NotificationAreaAppletFactory.service.in +@NOTIFICATION_AREA_INPROCESS_FALSE@service_DATA = $(service_in_files:.service.in=.service) +uidir = $(datadir)/mate-panel/ui +ui_DATA = notification-area-menu.xml +EXTRA_DIST = \ + org.mate.panel.NotificationAreaApplet.mate-panel-applet.in.in \ + $(ui_DATA) \ + $(service_in_files) \ + na-marshal.list + +CLEANFILES = \ + $(applet_DATA) \ + $(applet_DATA).in \ + $(service_DATA) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) 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 applets/notification_area/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu applets/notification_area/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 +install-notification_area_appletlibLTLIBRARIES: $(notification_area_appletlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(notification_area_appletlibdir)" || $(MKDIR_P) "$(DESTDIR)$(notification_area_appletlibdir)" + @list='$(notification_area_appletlib_LTLIBRARIES)'; test -n "$(notification_area_appletlibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(notification_area_appletlibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(notification_area_appletlibdir)"; \ + } + +uninstall-notification_area_appletlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(notification_area_appletlib_LTLIBRARIES)'; test -n "$(notification_area_appletlibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(notification_area_appletlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(notification_area_appletlibdir)/$$f"; \ + done + +clean-notification_area_appletlibLTLIBRARIES: + -test -z "$(notification_area_appletlib_LTLIBRARIES)" || rm -f $(notification_area_appletlib_LTLIBRARIES) + @list='$(notification_area_appletlib_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 +libnotification-area-applet.la: $(libnotification_area_applet_la_OBJECTS) $(libnotification_area_applet_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnotification_area_applet_la_LINK) $(am_libnotification_area_applet_la_rpath) $(libnotification_area_applet_la_OBJECTS) $(libnotification_area_applet_la_LIBADD) $(LIBS) +libtray.la: $(libtray_la_OBJECTS) $(libtray_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libtray_la_OBJECTS) $(libtray_la_LIBADD) $(LIBS) +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)" + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +notification-area-applet$(EXEEXT): $(notification_area_applet_OBJECTS) $(notification_area_applet_DEPENDENCIES) + @rm -f notification-area-applet$(EXEEXT) + $(AM_V_CCLD)$(notification_area_applet_LINK) $(notification_area_applet_OBJECTS) $(notification_area_applet_LDADD) $(LIBS) +testtray$(EXEEXT): $(testtray_OBJECTS) $(testtray_DEPENDENCIES) + @rm -f testtray$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testtray_OBJECTS) $(testtray_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fixedtip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnotification_area_applet_la-main.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/na-marshal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/na-tray-child.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/na-tray-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/na-tray.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notification_area_applet-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testtray.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 $@ $< + +libnotification_area_applet_la-main.lo: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnotification_area_applet_la_CFLAGS) $(CFLAGS) -MT libnotification_area_applet_la-main.lo -MD -MP -MF $(DEPDIR)/libnotification_area_applet_la-main.Tpo -c -o libnotification_area_applet_la-main.lo `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnotification_area_applet_la-main.Tpo $(DEPDIR)/libnotification_area_applet_la-main.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='libnotification_area_applet_la-main.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnotification_area_applet_la_CFLAGS) $(CFLAGS) -c -o libnotification_area_applet_la-main.lo `test -f 'main.c' || echo '$(srcdir)/'`main.c + +notification_area_applet-main.o: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(notification_area_applet_CFLAGS) $(CFLAGS) -MT notification_area_applet-main.o -MD -MP -MF $(DEPDIR)/notification_area_applet-main.Tpo -c -o notification_area_applet-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/notification_area_applet-main.Tpo $(DEPDIR)/notification_area_applet-main.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='notification_area_applet-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(notification_area_applet_CFLAGS) $(CFLAGS) -c -o notification_area_applet-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c + +notification_area_applet-main.obj: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(notification_area_applet_CFLAGS) $(CFLAGS) -MT notification_area_applet-main.obj -MD -MP -MF $(DEPDIR)/notification_area_applet-main.Tpo -c -o notification_area_applet-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)/notification_area_applet-main.Tpo $(DEPDIR)/notification_area_applet-main.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='notification_area_applet-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(notification_area_applet_CFLAGS) $(CFLAGS) -c -o notification_area_applet-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-appletDATA: $(applet_DATA) + @$(NORMAL_INSTALL) + test -z "$(appletdir)" || $(MKDIR_P) "$(DESTDIR)$(appletdir)" + @list='$(applet_DATA)'; test -n "$(appletdir)" || 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)$(appletdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(appletdir)" || exit $$?; \ + done + +uninstall-appletDATA: + @$(NORMAL_UNINSTALL) + @list='$(applet_DATA)'; test -n "$(appletdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(appletdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(appletdir)" && rm -f $$files +install-serviceDATA: $(service_DATA) + @$(NORMAL_INSTALL) + test -z "$(servicedir)" || $(MKDIR_P) "$(DESTDIR)$(servicedir)" + @list='$(service_DATA)'; test -n "$(servicedir)" || 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)$(servicedir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(servicedir)" || exit $$?; \ + done + +uninstall-serviceDATA: + @$(NORMAL_UNINSTALL) + @list='$(service_DATA)'; test -n "$(servicedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(servicedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(servicedir)" && rm -f $$files +install-uiDATA: $(ui_DATA) + @$(NORMAL_INSTALL) + test -z "$(uidir)" || $(MKDIR_P) "$(DESTDIR)$(uidir)" + @list='$(ui_DATA)'; test -n "$(uidir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(uidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(uidir)" || exit $$?; \ + done + +uninstall-uiDATA: + @$(NORMAL_UNINSTALL) + @list='$(ui_DATA)'; test -n "$(uidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(uidir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(uidir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(notification_area_appletlibdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(appletdir)" "$(DESTDIR)$(servicedir)" "$(DESTDIR)$(uidir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + clean-notification_area_appletlibLTLIBRARIES 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-appletDATA \ + install-notification_area_appletlibLTLIBRARIES \ + install-serviceDATA install-uiDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-appletDATA uninstall-libexecPROGRAMS \ + uninstall-notification_area_appletlibLTLIBRARIES \ + uninstall-serviceDATA uninstall-uiDATA + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS \ + clean-notification_area_appletlibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-appletDATA install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libexecPROGRAMS install-man \ + install-notification_area_appletlibLTLIBRARIES install-pdf \ + install-pdf-am install-ps install-ps-am install-serviceDATA \ + install-strip install-uiDATA installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-appletDATA uninstall-libexecPROGRAMS \ + uninstall-notification_area_appletlibLTLIBRARIES \ + uninstall-serviceDATA uninstall-uiDATA + + +na-marshal.h: na-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --header --prefix=_na_marshal > $@ + +na-marshal.c: na-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN)echo "#include \"na-marshal.h\"" > $@ && \ + $(GLIB_GENMARSHAL) $< --body --prefix=_na_marshal >> $@ + +$(applet_in_files): $(applet_in_files).in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \ + -e "s|\@IN_PROCESS\@|$(APPLET_IN_PROCESS)|" \ + -e "s|\@VERSION\@|$(PACKAGE_VERSION)|" \ + $< > $@ + +@PANEL_INTLTOOL_MATE_PANEL_APPLET_RULE@ + +@NOTIFICATION_AREA_INPROCESS_FALSE@org.mate.panel.applet.NotificationAreaAppletFactory.service: $(service_in_files) +@NOTIFICATION_AREA_INPROCESS_FALSE@ $(AM_V_GEN)sed \ +@NOTIFICATION_AREA_INPROCESS_FALSE@ -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \ +@NOTIFICATION_AREA_INPROCESS_FALSE@ $< > $@ + +-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/applets/notification_area/fixedtip.c b/applets/notification_area/fixedtip.c new file mode 100644 index 00000000..c32c6bf8 --- /dev/null +++ b/applets/notification_area/fixedtip.c @@ -0,0 +1,269 @@ +/* Marco fixed tooltip routine */ + +/* + * Copyright (C) 2001 Havoc Pennington + * Copyright (C) 2003-2006 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. + */ + +#include "fixedtip.h" + +/* Signals */ +enum +{ + CLICKED, + LAST_SIGNAL +}; + +static guint fixedtip_signals[LAST_SIGNAL] = { 0 }; + +struct _NaFixedTipPrivate +{ + GtkWidget *parent; + GtkWidget *label; + GtkOrientation orientation; +}; + +G_DEFINE_TYPE (NaFixedTip, na_fixed_tip, GTK_TYPE_WINDOW) + +static gboolean +button_press_handler (GtkWidget *fixedtip, + GdkEventButton *event, + gpointer data) +{ + if (event->button == 1 && event->type == GDK_BUTTON_PRESS) + g_signal_emit (fixedtip, fixedtip_signals[CLICKED], 0); + + return FALSE; +} + +static gboolean +expose_handler (GtkWidget *fixedtip) +{ + GtkRequisition req; + + gtk_widget_size_request (fixedtip, &req); + + gtk_paint_flat_box (gtk_widget_get_style (fixedtip), + gtk_widget_get_window (fixedtip), + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, fixedtip, "tooltip", + 0, 0, req.width, req.height); + + return FALSE; +} + +static void +na_fixed_tip_class_init (NaFixedTipClass *class) +{ + fixedtip_signals[CLICKED] = + g_signal_new ("clicked", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaFixedTipClass, clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private (class, sizeof (NaFixedTipPrivate)); +} + +/* Did you already see this code? Yes, it's gtk_tooltips_ force_window() ;-) */ +static void +na_fixed_tip_init (NaFixedTip *fixedtip) +{ + GtkWidget *label; + + fixedtip->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixedtip, NA_TYPE_FIXED_TIP, + NaFixedTipPrivate); + + gtk_window_set_type_hint (GTK_WINDOW (fixedtip), + GDK_WINDOW_TYPE_HINT_TOOLTIP); + + gtk_widget_set_app_paintable (GTK_WIDGET (fixedtip), TRUE); + gtk_window_set_resizable (GTK_WINDOW (fixedtip), FALSE); + gtk_widget_set_name (GTK_WIDGET (fixedtip), "gtk-tooltips"); + gtk_container_set_border_width (GTK_CONTAINER (fixedtip), 4); + + label = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_widget_show (label); + gtk_container_add (GTK_CONTAINER (fixedtip), label); + fixedtip->priv->label = label; + + g_signal_connect (fixedtip, "expose_event", + G_CALLBACK (expose_handler), NULL); + + gtk_widget_add_events (GTK_WIDGET (fixedtip), GDK_BUTTON_PRESS_MASK); + + g_signal_connect (fixedtip, "button_press_event", + G_CALLBACK (button_press_handler), NULL); + + fixedtip->priv->orientation = GTK_ORIENTATION_HORIZONTAL; +} + +static void +na_fixed_tip_position (NaFixedTip *fixedtip) +{ + GdkScreen *screen; + GdkWindow *parent_window; + GtkRequisition req; + int root_x; + int root_y; + int parent_width; + int parent_height; + int screen_width; + int screen_height; + + screen = gtk_widget_get_screen (fixedtip->priv->parent); + parent_window = gtk_widget_get_window (fixedtip->priv->parent); + + gtk_window_set_screen (GTK_WINDOW (fixedtip), screen); + + gtk_widget_size_request (GTK_WIDGET (fixedtip), &req); + + gdk_window_get_origin (parent_window, &root_x, &root_y); + #if GTK_CHECK_VERSION(3, 0, 0) + parent_width = gdk_window_get_width(parent_window); + parent_height = gdk_window_get_height(parent_window); + #else + gdk_drawable_get_size(GDK_DRAWABLE(parent_window), &parent_width, &parent_height); + #endif + + + screen_width = gdk_screen_get_width (screen); + screen_height = gdk_screen_get_height (screen); + + /* pad between panel and message window */ +#define PAD 5 + + if (fixedtip->priv->orientation == GTK_ORIENTATION_VERTICAL) + { + if (root_x <= screen_width / 2) + root_x += parent_width + PAD; + else + root_x -= req.width + PAD; + } + else + { + if (root_y <= screen_height / 2) + root_y += parent_height + PAD; + else + root_y -= req.height + PAD; + } + + /* Push onscreen */ + if ((root_x + req.width) > screen_width) + root_x = screen_width - req.width; + + if ((root_y + req.height) > screen_height) + root_y = screen_height - req.height; + + gtk_window_move (GTK_WINDOW (fixedtip), root_x, root_y); +} + +static void +na_fixed_tip_parent_size_allocated (GtkWidget *parent, + GtkAllocation *allocation, + NaFixedTip *fixedtip) +{ + na_fixed_tip_position (fixedtip); +} + +static void +na_fixed_tip_parent_screen_changed (GtkWidget *parent, + GdkScreen *new_screen, + NaFixedTip *fixedtip) +{ + na_fixed_tip_position (fixedtip); +} + +GtkWidget * +na_fixed_tip_new (GtkWidget *parent, + GtkOrientation orientation) +{ + NaFixedTip *fixedtip; + + g_return_val_if_fail (parent != NULL, NULL); + + fixedtip = g_object_new (NA_TYPE_FIXED_TIP, + "type", GTK_WINDOW_POPUP, + NULL); + + fixedtip->priv->parent = parent; + +#if 0 + //FIXME: would be nice to be able to get the toplevel for the tip, but this + //doesn't work + GtkWidget *toplevel; + + toplevel = gtk_widget_get_toplevel (parent); + /* + if (toplevel && gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel)) + gtk_window_set_transient_for (GTK_WINDOW (fixedtip), GTK_WINDOW (toplevel)); + */ +#endif + + fixedtip->priv->orientation = orientation; + + //FIXME: would be nice to move the tip when the notification area moves + g_signal_connect_object (parent, "size-allocate", + G_CALLBACK (na_fixed_tip_parent_size_allocated), + fixedtip, 0); + g_signal_connect_object (parent, "screen-changed", + G_CALLBACK (na_fixed_tip_parent_screen_changed), + fixedtip, 0); + + na_fixed_tip_position (fixedtip); + + return GTK_WIDGET (fixedtip); +} + +void +na_fixed_tip_set_markup (GtkWidget *widget, + const char *markup_text) +{ + NaFixedTip *fixedtip; + + g_return_if_fail (NA_IS_FIXED_TIP (widget)); + + fixedtip = NA_FIXED_TIP (widget); + + gtk_label_set_markup (GTK_LABEL (fixedtip->priv->label), + markup_text); + + na_fixed_tip_position (fixedtip); +} + +void +na_fixed_tip_set_orientation (GtkWidget *widget, + GtkOrientation orientation) +{ + NaFixedTip *fixedtip; + + g_return_if_fail (NA_IS_FIXED_TIP (widget)); + + fixedtip = NA_FIXED_TIP (widget); + + if (orientation == fixedtip->priv->orientation) + return; + + fixedtip->priv->orientation = orientation; + + na_fixed_tip_position (fixedtip); +} diff --git a/applets/notification_area/fixedtip.h b/applets/notification_area/fixedtip.h new file mode 100644 index 00000000..3b340c07 --- /dev/null +++ b/applets/notification_area/fixedtip.h @@ -0,0 +1,72 @@ +/* Fixed tooltip routine */ + +/* + * Copyright (C) 2001 Havoc Pennington, 2002 Red Hat Inc. + * Copyright (C) 2003-2006 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. + */ + +#ifndef FIXED_TIP_H +#define FIXED_TIP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NA_TYPE_FIXED_TIP (na_fixed_tip_get_type ()) +#define NA_FIXED_TIP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_FIXED_TIP, NaFixedTip)) +#define NA_FIXED_TIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_FIXED_TIP, NaFixedTipClass)) +#define NA_IS_FIXED_TIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_FIXED_TIP)) +#define NA_IS_FIXED_TIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_FIXED_TIP)) +#define NA_FIXED_TIP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_FIXED_TIP, NaFixedTipClass)) + +typedef struct _NaFixedTip NaFixedTip; +typedef struct _NaFixedTipPrivate NaFixedTipPrivate; +typedef struct _NaFixedTipClass NaFixedTipClass; + +struct _NaFixedTip +{ + GtkWindow parent_instance; + + NaFixedTipPrivate *priv; +}; + +struct _NaFixedTipClass +{ + GtkWindowClass parent_class; + + void (* clicked) (NaFixedTip *fixedtip); +}; + +GType na_fixed_tip_get_type (void); + +GtkWidget *na_fixed_tip_new (GtkWidget *parent, + GtkOrientation orientation); + +void na_fixed_tip_set_markup (GtkWidget *widget, + const char *markup_text); + +void na_fixed_tip_set_orientation (GtkWidget *widget, + GtkOrientation orientation); + +#ifdef __cplusplus +} +#endif + +#endif /* FIXED_TIP_H */ diff --git a/applets/notification_area/main.c b/applets/notification_area/main.c new file mode 100644 index 00000000..fc11040f --- /dev/null +++ b/applets/notification_area/main.c @@ -0,0 +1,267 @@ +/* System tray main() */ + +/* + * Copyright (C) 2002 Red Hat, Inc. + * Copyright (C) 2003-2006 Vincent Untz + * Copyright (C) 2011 Perberos + * + * 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 +#include + +#include +#include + +#include +#include + +#include "na-tray-manager.h" +#include "na-tray.h" +#include "fixedtip.h" + +#define NOTIFICATION_AREA_ICON "mate-panel-notification-area" + +typedef struct { + MatePanelApplet* applet; + NaTray* tray; +} AppletData; + +static GtkOrientation get_orientation_from_applet(MatePanelApplet* applet) +{ + GtkOrientation orientation; + + switch (mate_panel_applet_get_orient(applet)) + { + case MATE_PANEL_APPLET_ORIENT_LEFT: + case MATE_PANEL_APPLET_ORIENT_RIGHT: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + case MATE_PANEL_APPLET_ORIENT_DOWN: + default: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + } + + return orientation; +} + +static void help_cb(GtkAction* action, AppletData* data) +{ + GError* error = NULL; + char* uri; + #define NA_HELP_DOC "user-guide" + + uri = g_strdup_printf("ghelp:%s?%s", NA_HELP_DOC, "panels-notification-area"); + + gtk_show_uri(gtk_widget_get_screen(GTK_WIDGET(data->applet)), uri, gtk_get_current_event_time(), &error); + + g_free(uri); + + if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + g_error_free(error); + } + else if(error) + { + GtkWidget* dialog; + char* primary; + + primary = g_markup_printf_escaped (_("Could not display help document '%s'"), NA_HELP_DOC); + dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", primary); + + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", error->message); + + g_error_free(error); + g_free(primary); + + g_signal_connect(dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); + + gtk_window_set_icon_name (GTK_WINDOW (dialog), NOTIFICATION_AREA_ICON); + gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (GTK_WIDGET (data->applet))); + /* we have no parent window */ + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (dialog), _("Error displaying help document")); + + gtk_widget_show (dialog); + } +} + +static void about_cb(GtkAction* action, AppletData* data) +{ + const gchar* authors[] = { + "Havoc Pennington ", + "Anders Carlsson ", + "Vincent Untz ", + NULL + }; + + const char* documenters[] = { + "Sun GNOME Documentation Team ", + NULL + }; + + const char copyright[] = \ + "Copyright \xc2\xa9 2002 Red Hat, Inc.\n" + "Copyright \xc2\xa9 2003-2006 Vincent Untz\n" + "Copyright \xc2\xa9 2011 Perberos"; + + gtk_show_about_dialog(NULL, + "program-name", _("Notification Area"), + "authors", authors, + //"comments", _(comments), + "copyright", copyright, + "documenters", documenters, + "logo-icon-name", NOTIFICATION_AREA_ICON, + "translator-credits", _("translator-credits"), + "version", VERSION, + "website", "http://matsusoft.com.ar/projects/mate/", + NULL); +} + +static const GtkActionEntry menu_actions [] = { + { "SystemTrayHelp", GTK_STOCK_HELP, N_("_Help"), + NULL, NULL, + G_CALLBACK (help_cb) }, + { "SystemTrayAbout", GTK_STOCK_ABOUT, N_("_About"), + NULL, NULL, + G_CALLBACK (about_cb) } +}; + +static void applet_change_background(MatePanelApplet* applet, MatePanelAppletBackgroundType type, GdkColor* color, GdkPixmap* pixmap, AppletData* data) +{ + na_tray_force_redraw(data->tray); +} + + +static void applet_change_orientation(MatePanelApplet* applet, MatePanelAppletOrient orient, AppletData* data) +{ + na_tray_set_orientation(data->tray, get_orientation_from_applet(applet)); +} + +static void applet_destroy(MatePanelApplet* applet, AppletData* data) +{ +} + +static void free_applet_data(AppletData* data) +{ + g_slice_free(AppletData, data); +} + +static void on_applet_realized(GtkWidget* widget, gpointer user_data) +{ + MatePanelApplet* applet; + AppletData* data; + NaTray* tray; + GtkActionGroup* action_group; + gchar* ui_path; + + applet = MATE_PANEL_APPLET(widget); + data = g_object_get_data(G_OBJECT(widget), "system-tray-data"); + + if (data != NULL) + { + return; + } + + tray = na_tray_new_for_screen(gtk_widget_get_screen(GTK_WIDGET(applet)), get_orientation_from_applet(applet)); + + data = g_slice_new(AppletData); + data->applet = applet; + data->tray = tray; + + g_object_set_data_full(G_OBJECT(applet), "system-tray-data", data, (GDestroyNotify) free_applet_data); + + g_signal_connect(applet, "change_orient", G_CALLBACK (applet_change_orientation), data); + g_signal_connect(applet, "change_background", G_CALLBACK (applet_change_background), data); + g_signal_connect(applet, "destroy", G_CALLBACK (applet_destroy), data); + + gtk_container_add(GTK_CONTAINER (applet), GTK_WIDGET (tray)); + gtk_widget_show(GTK_WIDGET(tray)); + + action_group = gtk_action_group_new("ClockApplet Menu Actions"); + gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions(action_group, menu_actions, G_N_ELEMENTS(menu_actions), data); + ui_path = g_build_filename(NOTIFICATION_AREA_MENU_UI_DIR, "notification-area-menu.xml", NULL); + mate_panel_applet_setup_menu_from_file(applet, ui_path, action_group); + g_free(ui_path); + g_object_unref(action_group); + +} + +static inline void force_no_focus_padding(GtkWidget* widget) +{ + static gboolean first_time = TRUE; + + if (first_time) + { + gtk_rc_parse_string ("\n" + " style \"na-tray-style\"\n" + " {\n" + " GtkWidget::focus-line-width=0\n" + " GtkWidget::focus-padding=0\n" + " }\n" + "\n" + " widget \"*.PanelAppletNaTray\" style \"na-tray-style\"\n" + "\n"); + + first_time = FALSE; + } + + /* El widget antes se llamaba na-tray + * + * Issue #27 + */ + gtk_widget_set_name(widget, "PanelAppletNaTray"); +} + +static gboolean applet_factory(MatePanelApplet* applet, const gchar* iid, gpointer user_data) +{ + AtkObject* atko; + + if (!(strcmp (iid, "NotificationArea") == 0 || strcmp (iid, "SystemTrayApplet") == 0)) + { + return FALSE; + } + + /* Defer loading until applet is added to panel so + * gtk_widget_get_screen returns correct information */ + g_signal_connect(GTK_WIDGET(applet), "realize", G_CALLBACK(on_applet_realized), NULL); + + atko = gtk_widget_get_accessible (GTK_WIDGET (applet)); + atk_object_set_name (atko, _("Panel Notification Area")); + + mate_panel_applet_set_flags(applet, MATE_PANEL_APPLET_HAS_HANDLE | MATE_PANEL_APPLET_EXPAND_MINOR); + + mate_panel_applet_set_background_widget(applet, GTK_WIDGET(applet)); + + force_no_focus_padding(GTK_WIDGET(applet)); + + #ifndef NOTIFICATION_AREA_INPROCESS + gtk_window_set_default_icon_name(NOTIFICATION_AREA_ICON); + #endif + + gtk_widget_show_all(GTK_WIDGET(applet)); + return TRUE; +} + +#ifdef NOTIFICATION_AREA_INPROCESS + MATE_PANEL_APPLET_IN_PROCESS_FACTORY("NotificationAreaAppletFactory", PANEL_TYPE_APPLET, "NotificationArea", applet_factory, NULL) +#else + MATE_PANEL_APPLET_OUT_PROCESS_FACTORY("NotificationAreaAppletFactory", PANEL_TYPE_APPLET, "NotificationArea", applet_factory, NULL) +#endif diff --git a/applets/notification_area/na-marshal.c b/applets/notification_area/na-marshal.c new file mode 100644 index 00000000..1f3c2020 --- /dev/null +++ b/applets/notification_area/na-marshal.c @@ -0,0 +1,167 @@ +#include "na-marshal.h" + +#include + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* VOID:OBJECT,OBJECT (na-marshal.list:1) */ +void +_na_marshal_VOID__OBJECT_OBJECT (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_OBJECT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_object (param_values + 2), + data2); +} + +/* VOID:OBJECT,STRING,LONG,LONG (na-marshal.list:2) */ +void +_na_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + glong arg_3, + glong arg_4, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 5); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_string (param_values + 2), + g_marshal_value_peek_long (param_values + 3), + g_marshal_value_peek_long (param_values + 4), + data2); +} + +/* VOID:OBJECT,LONG (na-marshal.list:3) */ +void +_na_marshal_VOID__OBJECT_LONG (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__OBJECT_LONG) (gpointer data1, + gpointer arg_1, + glong arg_2, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_LONG callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__OBJECT_LONG) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_long (param_values + 2), + data2); +} + diff --git a/applets/notification_area/na-marshal.h b/applets/notification_area/na-marshal.h new file mode 100644 index 00000000..07918a11 --- /dev/null +++ b/applets/notification_area/na-marshal.h @@ -0,0 +1,36 @@ + +#ifndef ___na_marshal_MARSHAL_H__ +#define ___na_marshal_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +/* VOID:OBJECT,OBJECT (na-marshal.list:1) */ +extern void _na_marshal_VOID__OBJECT_OBJECT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:OBJECT,STRING,LONG,LONG (na-marshal.list:2) */ +extern void _na_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:OBJECT,LONG (na-marshal.list:3) */ +extern void _na_marshal_VOID__OBJECT_LONG (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +G_END_DECLS + +#endif /* ___na_marshal_MARSHAL_H__ */ + diff --git a/applets/notification_area/na-marshal.list b/applets/notification_area/na-marshal.list new file mode 100644 index 00000000..e3fc3993 --- /dev/null +++ b/applets/notification_area/na-marshal.list @@ -0,0 +1,3 @@ +VOID:OBJECT,OBJECT +VOID:OBJECT,STRING,LONG,LONG +VOID:OBJECT,LONG diff --git a/applets/notification_area/na-tray-child.c b/applets/notification_area/na-tray-child.c new file mode 100644 index 00000000..b946386b --- /dev/null +++ b/applets/notification_area/na-tray-child.c @@ -0,0 +1,539 @@ +/* na-tray-child.c + * Copyright (C) 2002 Anders Carlsson + * Copyright (C) 2003-2006 Vincent Untz + * Copyright (C) 2008 Red Hat, 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. + */ + +#include +#include + +#include "na-tray-child.h" + +#include +#include +#include +#include + +G_DEFINE_TYPE (NaTrayChild, na_tray_child, GTK_TYPE_SOCKET) + +static void +na_tray_child_finalize (GObject *object) +{ + G_OBJECT_CLASS (na_tray_child_parent_class)->finalize (object); +} + +static void +na_tray_child_realize (GtkWidget *widget) +{ + NaTrayChild *child = NA_TRAY_CHILD (widget); + GdkVisual *visual = gtk_widget_get_visual (widget); + GdkWindow *window; + + GTK_WIDGET_CLASS (na_tray_child_parent_class)->realize (widget); + + window = gtk_widget_get_window (widget); + + if (child->has_alpha) + { + /* We have real transparency with an ARGB visual and the Composite + * extension. */ + + /* Set a transparent background */ + GdkColor transparent = { 0, 0, 0, 0 }; /* only pixel=0 matters */ + gdk_window_set_background (window, &transparent); + gdk_window_set_composited (window, TRUE); + + child->parent_relative_bg = FALSE; + } + #if GTK_CHECK_VERSION(3, 0, 0) + else if (visual == gdk_window_get_visual(gdk_window_get_parent(window))) + #else + else if (visual == gdk_drawable_get_visual(GDK_DRAWABLE(gdk_window_get_parent(window)))) + #endif + { + /* Otherwise, if the visual matches the visual of the parent window, we + * can use a parent-relative background and fake transparency. */ + gdk_window_set_back_pixmap (window, NULL, TRUE); + + child->parent_relative_bg = TRUE; + } + else + { + /* Nothing to do; the icon will sit on top of an ugly gray box */ + child->parent_relative_bg = FALSE; + } + + gdk_window_set_composited (window, child->composited); + + gtk_widget_set_app_paintable (GTK_WIDGET (child), + child->parent_relative_bg || child->has_alpha); + + /* Double-buffering will interfere with the parent-relative-background fake + * transparency, since the double-buffer code doesn't know how to fill in the + * background of the double-buffer correctly. + */ + gtk_widget_set_double_buffered (GTK_WIDGET (child), + child->parent_relative_bg); +} + +static void +na_tray_child_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + /* The default handler resets the background according to the new style. + * We either use a transparent background or a parent-relative background + * and ignore the style background. So, just don't chain up. + */ +} + +#if 0 +/* This is adapted from code that was commented out in na-tray-manager.c; the + * code in na-tray-manager.c wouldn't have worked reliably, this will. So maybe + * it can be reenabled. On other hand, things seem to be working fine without + * it. + * + * If reenabling, you need to hook it up in na_tray_child_class_init(). + */ +static void +na_tray_child_size_request (GtkWidget *widget, + GtkRequisition *request) +{ + GTK_WIDGET_CLASS (na_tray_child_parent_class)->size_request (widget, request); + + /* + * Make sure the icons have a meaningful size .. + */ + if ((request->width < 16) || (request->height < 16)) + { + gint nw = MAX (24, request->width); + gint nh = MAX (24, request->height); + g_warning ("Tray icon has requested a size of (%ix%i), resizing to (%ix%i)", + req.width, req.height, nw, nh); + request->width = nw; + request->height = nh; + } +} +#endif + +static void +na_tray_child_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + NaTrayChild *child = NA_TRAY_CHILD (widget); + GtkAllocation widget_allocation; + gboolean moved, resized; + + gtk_widget_get_allocation (widget, &widget_allocation); + + moved = (allocation->x != widget_allocation.x || + allocation->y != widget_allocation.y); + resized = (allocation->width != widget_allocation.width || + allocation->height != widget_allocation.height); + + /* When we are allocating the widget while mapped we need special handling + * for both real and fake transparency. + * + * Real transparency: we need to invalidate and trigger a redraw of the old + * and new areas. (GDK really should handle this for us, but doesn't as of + * GTK+-2.14) + * + * Fake transparency: if the widget moved, we need to force the contents to + * be redrawn with the new offset for the parent-relative background. + */ + if ((moved || resized) && gtk_widget_get_mapped (widget)) + { + if (na_tray_child_has_alpha (child)) + gdk_window_invalidate_rect (gdk_window_get_parent (gtk_widget_get_window (widget)), + &widget_allocation, FALSE); + } + + GTK_WIDGET_CLASS (na_tray_child_parent_class)->size_allocate (widget, + allocation); + + if ((moved || resized) && gtk_widget_get_mapped (widget)) + { + if (na_tray_child_has_alpha (NA_TRAY_CHILD (widget))) + gdk_window_invalidate_rect (gdk_window_get_parent (gtk_widget_get_window (widget)), + &widget_allocation, FALSE); + else if (moved && child->parent_relative_bg) + na_tray_child_force_redraw (child); + } +} + +/* The plug window should completely occupy the area of the child, so we won't + * get an expose event. But in case we do (the plug unmaps itself, say), this + * expose handler draws with real or fake transparency. + */ +static gboolean +na_tray_child_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + NaTrayChild *child = NA_TRAY_CHILD (widget); + GdkWindow *window = gtk_widget_get_window (widget); + + if (na_tray_child_has_alpha (child)) + { + /* Clear to transparent */ + cairo_t *cr = gdk_cairo_create (window); + cairo_set_source_rgba (cr, 0, 0, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + gdk_cairo_region (cr, event->region); + cairo_fill (cr); + cairo_destroy (cr); + } + else if (child->parent_relative_bg) + { + /* Clear to parent-relative pixmap */ + gdk_window_clear_area (window, + event->area.x, event->area.y, + event->area.width, event->area.height); + } + + return FALSE; +} + +static void +na_tray_child_init (NaTrayChild *child) +{ +} + +static void +na_tray_child_class_init (NaTrayChildClass *klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + + gobject_class = (GObjectClass *)klass; + widget_class = (GtkWidgetClass *)klass; + + gobject_class->finalize = na_tray_child_finalize; + widget_class->style_set = na_tray_child_style_set; + widget_class->realize = na_tray_child_realize; + widget_class->size_allocate = na_tray_child_size_allocate; + widget_class->expose_event = na_tray_child_expose_event; +} + +GtkWidget * +na_tray_child_new (GdkScreen *screen, + Window icon_window) +{ + XWindowAttributes window_attributes; + Display *xdisplay; + NaTrayChild *child; + GdkVisual *visual; + gboolean visual_has_alpha; + GdkColormap *colormap; + gboolean new_colormap; + int red_prec, green_prec, blue_prec, depth; + int result; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + g_return_val_if_fail (icon_window != None, NULL); + + xdisplay = GDK_SCREEN_XDISPLAY (screen); + + /* We need to determine the visual of the window we are embedding and create + * the socket in the same visual. + */ + + gdk_error_trap_push (); + result = XGetWindowAttributes (xdisplay, icon_window, + &window_attributes); + gdk_error_trap_pop (); + + if (!result) /* Window already gone */ + return NULL; + + visual = gdk_x11_screen_lookup_visual (screen, + window_attributes.visual->visualid); + if (!visual) /* Icon window is on another screen? */ + return NULL; + + new_colormap = FALSE; + + if (visual == gdk_screen_get_rgb_visual (screen)) + colormap = gdk_screen_get_rgb_colormap (screen); + else if (visual == gdk_screen_get_rgba_visual (screen)) + colormap = gdk_screen_get_rgba_colormap (screen); + else if (visual == gdk_screen_get_system_visual (screen)) + colormap = gdk_screen_get_system_colormap (screen); + else + { + colormap = gdk_colormap_new (visual, FALSE); + new_colormap = TRUE; + } + + child = g_object_new (NA_TYPE_TRAY_CHILD, NULL); + child->icon_window = icon_window; + + gtk_widget_set_colormap (GTK_WIDGET (child), colormap); + + /* We have alpha if the visual has something other than red, green, + * and blue */ + gdk_visual_get_red_pixel_details (visual, NULL, NULL, &red_prec); + gdk_visual_get_green_pixel_details (visual, NULL, NULL, &green_prec); + gdk_visual_get_blue_pixel_details (visual, NULL, NULL, &blue_prec); + depth = gdk_visual_get_depth (visual); + + visual_has_alpha = red_prec + blue_prec + green_prec < depth; + child->has_alpha = (visual_has_alpha && + gdk_display_supports_composite (gdk_screen_get_display (screen))); + + child->composited = child->has_alpha; + + if (new_colormap) + g_object_unref (colormap); + + return GTK_WIDGET (child); +} + +char * +na_tray_child_get_title (NaTrayChild *child) +{ + char *retval = NULL; + GdkDisplay *display; + Atom utf8_string, atom, type; + int result; + int format; + gulong nitems; + gulong bytes_after; + gchar *val; + + g_return_val_if_fail (NA_IS_TRAY_CHILD (child), NULL); + + display = gtk_widget_get_display (GTK_WIDGET (child)); + + utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"); + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"); + + gdk_error_trap_push (); + + result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), + child->icon_window, + atom, + 0, G_MAXLONG, + False, utf8_string, + &type, &format, &nitems, + &bytes_after, (guchar **)&val); + + if (gdk_error_trap_pop () || result != Success) + return NULL; + + if (type != utf8_string || + format != 8 || + nitems == 0) + { + if (val) + XFree (val); + return NULL; + } + + if (!g_utf8_validate (val, nitems, NULL)) + { + XFree (val); + return NULL; + } + + retval = g_strndup (val, nitems); + + XFree (val); + + return retval; +} + +/** + * na_tray_child_has_alpha; + * @child: a #NaTrayChild + * + * Checks if the child has an ARGB visual and real alpha transparence. + * (as opposed to faked alpha transparency with an parent-relative + * background) + * + * Return value: %TRUE if the child has an alpha transparency + */ +gboolean +na_tray_child_has_alpha (NaTrayChild *child) +{ + g_return_val_if_fail (NA_IS_TRAY_CHILD (child), FALSE); + + return child->has_alpha; +} + +/** + * na_tray_child_set_composited; + * @child: a #NaTrayChild + * @composited: %TRUE if the child's window should be redirected + * + * Sets whether the #GdkWindow of the child should be set redirected + * using gdk_window_set_composited(). By default this is based off of + * na_tray_child_has_alpha(), but it may be useful to override it in + * certain circumstances; for example, if the #NaTrayChild is added + * to a parent window and that parent window is composited against the + * background. + */ +void +na_tray_child_set_composited (NaTrayChild *child, + gboolean composited) +{ + g_return_if_fail (NA_IS_TRAY_CHILD (child)); + + if (child->composited == composited) + return; + + child->composited = composited; + if (gtk_widget_get_realized (GTK_WIDGET (child))) + gdk_window_set_composited (gtk_widget_get_window (GTK_WIDGET (child)), + composited); +} + +/* If we are faking transparency with a window-relative background, force a + * redraw of the icon. This should be called if the background changes or if + * the child is shifted with respect to the background. + */ +void +na_tray_child_force_redraw (NaTrayChild *child) +{ + GtkWidget *widget = GTK_WIDGET (child); + + if (gtk_widget_get_mapped (widget) && child->parent_relative_bg) + { +#if 1 + /* Sending an ExposeEvent might cause redraw problems if the + * icon is expecting the server to clear-to-background before + * the redraw. It should be ok for GtkStatusIcon or EggTrayIcon. + */ + Display *xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); + XEvent xev; + GdkWindow *plug_window; + GtkAllocation allocation; + + plug_window = gtk_socket_get_plug_window (GTK_SOCKET (child)); + gtk_widget_get_allocation (widget, &allocation); + + xev.xexpose.type = Expose; + xev.xexpose.window = GDK_WINDOW_XWINDOW (plug_window); + xev.xexpose.x = 0; + xev.xexpose.y = 0; + xev.xexpose.width = allocation.width; + xev.xexpose.height = allocation.height; + xev.xexpose.count = 0; + + gdk_error_trap_push (); + XSendEvent (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)), + xev.xexpose.window, + False, ExposureMask, + &xev); + /* We have to sync to reliably catch errors from the XSendEvent(), + * since that is asynchronous. + */ + XSync (xdisplay, False); + gdk_error_trap_pop (); +#else + /* Hiding and showing is the safe way to do it, but can result in more + * flickering. + */ + gdk_window_hide (widget->window); + gdk_window_show (widget->window); +#endif + } +} + +/* from libwnck/xutils.c, comes as LGPLv2+ */ +static char * +latin1_to_utf8 (const char *latin1) +{ + GString *str; + const char *p; + + str = g_string_new (NULL); + + p = latin1; + while (*p) + { + g_string_append_unichar (str, (gunichar) *p); + ++p; + } + + return g_string_free (str, FALSE); +} + +/* derived from libwnck/xutils.c, comes as LGPLv2+ */ +static void +_get_wmclass (Display *xdisplay, + Window xwindow, + char **res_class, + char **res_name) +{ + XClassHint ch; + + ch.res_name = NULL; + ch.res_class = NULL; + + gdk_error_trap_push (); + XGetClassHint (xdisplay, xwindow, &ch); + gdk_error_trap_pop (); + + if (res_class) + *res_class = NULL; + + if (res_name) + *res_name = NULL; + + if (ch.res_name) + { + if (res_name) + *res_name = latin1_to_utf8 (ch.res_name); + + XFree (ch.res_name); + } + + if (ch.res_class) + { + if (res_class) + *res_class = latin1_to_utf8 (ch.res_class); + + XFree (ch.res_class); + } +} + +/** + * na_tray_child_get_wm_class; + * @child: a #NaTrayChild + * @res_name: return location for a string containing the application name of + * @child, or %NULL + * @res_class: return location for a string containing the application class of + * @child, or %NULL + * + * Fetches the resource associated with @child. + */ +void +na_tray_child_get_wm_class (NaTrayChild *child, + char **res_name, + char **res_class) +{ + GdkDisplay *display; + + g_return_if_fail (NA_IS_TRAY_CHILD (child)); + + display = gtk_widget_get_display (GTK_WIDGET (child)); + + _get_wmclass (GDK_DISPLAY_XDISPLAY (display), + child->icon_window, + res_class, + res_name); +} diff --git a/applets/notification_area/na-tray-child.h b/applets/notification_area/na-tray-child.h new file mode 100644 index 00000000..735770ac --- /dev/null +++ b/applets/notification_area/na-tray-child.h @@ -0,0 +1,75 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* na-tray-child.h + * Copyright (C) 2002 Anders Carlsson + * Copyright (C) 2003-2006 Vincent Untz + * Copyright (C) 2008 Red Hat, 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 __NA_TRAY_CHILD_H__ +#define __NA_TRAY_CHILD_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NA_TYPE_TRAY_CHILD (na_tray_child_get_type ()) +#define NA_TRAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY_CHILD, NaTrayChild)) +#define NA_TRAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY_CHILD, NaTrayChildClass)) +#define NA_IS_TRAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY_CHILD)) +#define NA_IS_TRAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY_CHILD)) +#define NA_TRAY_CHILD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY_CHILD, NaTrayChildClass)) + +typedef struct _NaTrayChild NaTrayChild; +typedef struct _NaTrayChildClass NaTrayChildClass; +typedef struct _NaTrayChildChild NaTrayChildChild; + +struct _NaTrayChild +{ + GtkSocket parent_instance; + Window icon_window; + guint has_alpha : 1; + guint composited : 1; + guint parent_relative_bg : 1; +}; + +struct _NaTrayChildClass +{ + GtkSocketClass parent_class; +}; + +GType na_tray_child_get_type (void); + +GtkWidget *na_tray_child_new (GdkScreen *screen, + Window icon_window); +char *na_tray_child_get_title (NaTrayChild *child); +gboolean na_tray_child_has_alpha (NaTrayChild *child); +void na_tray_child_set_composited (NaTrayChild *child, + gboolean composited); +void na_tray_child_force_redraw (NaTrayChild *child); +void na_tray_child_get_wm_class (NaTrayChild *child, + char **res_name, + char **res_class); + +#ifdef __cplusplus +} +#endif + +#endif /* __NA_TRAY_CHILD_H__ */ diff --git a/applets/notification_area/na-tray-manager.c b/applets/notification_area/na-tray-manager.c new file mode 100644 index 00000000..1c582a62 --- /dev/null +++ b/applets/notification_area/na-tray-manager.c @@ -0,0 +1,859 @@ +/* na-tray-manager.c + * Copyright (C) 2002 Anders Carlsson + * Copyright (C) 2003-2006 Vincent Untz + * + * 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. + * + * Used to be: eggtraymanager.c + */ + +#include +#include +#include + +#include "na-tray-manager.h" + +#include +#include +#if defined (GDK_WINDOWING_X11) +#include +#include +#elif defined (GDK_WINDOWING_WIN32) +#include +#endif +#include + +#include "na-marshal.h" + +/* Signals */ +enum +{ + TRAY_ICON_ADDED, + TRAY_ICON_REMOVED, + MESSAGE_SENT, + MESSAGE_CANCELLED, + LOST_SELECTION, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_ORIENTATION +}; + +typedef struct +{ + long id, len; + long remaining_len; + + long timeout; + char *str; +#ifdef GDK_WINDOWING_X11 + Window window; +#endif +} PendingMessage; + +static guint manager_signals[LAST_SIGNAL]; + +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + +#define SYSTEM_TRAY_ORIENTATION_HORZ 0 +#define SYSTEM_TRAY_ORIENTATION_VERT 1 + +#ifdef GDK_WINDOWING_X11 +static gboolean na_tray_manager_check_running_screen_x11 (GdkScreen *screen); +#endif + +static void na_tray_manager_finalize (GObject *object); +static void na_tray_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void na_tray_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void na_tray_manager_unmanage (NaTrayManager *manager); + +G_DEFINE_TYPE (NaTrayManager, na_tray_manager, G_TYPE_OBJECT) + +static void +na_tray_manager_init (NaTrayManager *manager) +{ + manager->invisible = NULL; + manager->socket_table = g_hash_table_new (NULL, NULL); +} + +static void +na_tray_manager_class_init (NaTrayManagerClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *)klass; + + gobject_class->finalize = na_tray_manager_finalize; + gobject_class->set_property = na_tray_manager_set_property; + gobject_class->get_property = na_tray_manager_get_property; + + g_object_class_install_property (gobject_class, + PROP_ORIENTATION, + g_param_spec_enum ("orientation", + "orientation", + "orientation", + GTK_TYPE_ORIENTATION, + GTK_ORIENTATION_HORIZONTAL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + manager_signals[TRAY_ICON_ADDED] = + g_signal_new ("tray_icon_added", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaTrayManagerClass, tray_icon_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_SOCKET); + + manager_signals[TRAY_ICON_REMOVED] = + g_signal_new ("tray_icon_removed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaTrayManagerClass, tray_icon_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_SOCKET); + manager_signals[MESSAGE_SENT] = + g_signal_new ("message_sent", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaTrayManagerClass, message_sent), + NULL, NULL, + _na_marshal_VOID__OBJECT_STRING_LONG_LONG, + G_TYPE_NONE, 4, + GTK_TYPE_SOCKET, + G_TYPE_STRING, + G_TYPE_LONG, + G_TYPE_LONG); + manager_signals[MESSAGE_CANCELLED] = + g_signal_new ("message_cancelled", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaTrayManagerClass, message_cancelled), + NULL, NULL, + _na_marshal_VOID__OBJECT_LONG, + G_TYPE_NONE, 2, + GTK_TYPE_SOCKET, + G_TYPE_LONG); + manager_signals[LOST_SELECTION] = + g_signal_new ("lost_selection", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NaTrayManagerClass, lost_selection), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +#if defined (GDK_WINDOWING_X11) + /* Nothing */ +#elif defined (GDK_WINDOWING_WIN32) + g_warning ("Port NaTrayManager to Win32"); +#else + g_warning ("Port NaTrayManager to this GTK+ backend"); +#endif +} + +static void +na_tray_manager_finalize (GObject *object) +{ + NaTrayManager *manager; + + manager = NA_TRAY_MANAGER (object); + + na_tray_manager_unmanage (manager); + + g_list_free (manager->messages); + g_hash_table_destroy (manager->socket_table); + + G_OBJECT_CLASS (na_tray_manager_parent_class)->finalize (object); +} + +static void +na_tray_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NaTrayManager *manager = NA_TRAY_MANAGER (object); + + switch (prop_id) + { + case PROP_ORIENTATION: + na_tray_manager_set_orientation (manager, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +na_tray_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NaTrayManager *manager = NA_TRAY_MANAGER (object); + + switch (prop_id) + { + case PROP_ORIENTATION: + g_value_set_enum (value, manager->orientation); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +NaTrayManager * +na_tray_manager_new (void) +{ + NaTrayManager *manager; + + manager = g_object_new (NA_TYPE_TRAY_MANAGER, NULL); + + return manager; +} + +#ifdef GDK_WINDOWING_X11 + +static gboolean +na_tray_manager_plug_removed (GtkSocket *socket, + NaTrayManager *manager) +{ + NaTrayChild *child = NA_TRAY_CHILD (socket); + + g_hash_table_remove (manager->socket_table, + GINT_TO_POINTER (child->icon_window)); + g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child); + + /* This destroys the socket. */ + return FALSE; +} + +static void +na_tray_manager_handle_dock_request (NaTrayManager *manager, + XClientMessageEvent *xevent) +{ + Window icon_window = xevent->data.l[2]; + GtkWidget *child; + + if (g_hash_table_lookup (manager->socket_table, + GINT_TO_POINTER (icon_window))) + { + /* We already got this notification earlier, ignore this one */ + return; + } + + child = na_tray_child_new (manager->screen, icon_window); + if (child == NULL) /* already gone or other error */ + return; + + g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0, + child); + + /* If the child wasn't attached, then destroy it */ + + if (!GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (child)))) + { + gtk_widget_destroy (child); + return; + } + + g_signal_connect (child, "plug_removed", + G_CALLBACK (na_tray_manager_plug_removed), manager); + + gtk_socket_add_id (GTK_SOCKET (child), icon_window); + + if (!gtk_socket_get_plug_window (GTK_SOCKET (child))) + { + /* Embedding failed, we won't get a plug-removed signal */ + g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child); + gtk_widget_destroy (child); + return; + } + + g_hash_table_insert (manager->socket_table, + GINT_TO_POINTER (icon_window), child); + gtk_widget_show (child); +} + +static void +pending_message_free (PendingMessage *message) +{ + g_free (message->str); + g_free (message); +} + +static GdkFilterReturn +na_tray_manager_handle_client_message_message_data (GdkXEvent *xev, + GdkEvent *event, + gpointer data) +{ + XClientMessageEvent *xevent; + NaTrayManager *manager; + GList *p; + int len; + + xevent = (XClientMessageEvent *) xev; + manager = data; + + /* Try to see if we can find the pending message in the list */ + for (p = manager->messages; p; p = p->next) + { + PendingMessage *msg = p->data; + + if (xevent->window == msg->window) + { + /* Append the message */ + len = MIN (msg->remaining_len, 20); + + memcpy ((msg->str + msg->len - msg->remaining_len), + &xevent->data, len); + msg->remaining_len -= len; + + if (msg->remaining_len == 0) + { + GtkSocket *socket; + + socket = g_hash_table_lookup (manager->socket_table, + GINT_TO_POINTER (msg->window)); + + if (socket) + g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0, + socket, msg->str, msg->id, msg->timeout); + + pending_message_free (msg); + manager->messages = g_list_remove_link (manager->messages, p); + g_list_free_1 (p); + } + + break; + } + } + + return GDK_FILTER_REMOVE; +} + +static void +na_tray_manager_handle_begin_message (NaTrayManager *manager, + XClientMessageEvent *xevent) +{ + GtkSocket *socket; + GList *p; + PendingMessage *msg; + long timeout; + long len; + long id; + + socket = g_hash_table_lookup (manager->socket_table, + GINT_TO_POINTER (xevent->window)); + /* we don't know about this tray icon, so ignore the message */ + if (!socket) + return; + + /* Check if the same message is already in the queue and remove it if so */ + for (p = manager->messages; p; p = p->next) + { + PendingMessage *pmsg = p->data; + + if (xevent->window == pmsg->window && + xevent->data.l[4] == pmsg->id) + { + /* Hmm, we found it, now remove it */ + pending_message_free (pmsg); + manager->messages = g_list_remove_link (manager->messages, p); + g_list_free_1 (p); + break; + } + } + + timeout = xevent->data.l[2]; + len = xevent->data.l[3]; + id = xevent->data.l[4]; + + if (len == 0) + { + g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0, + socket, "", id, timeout); + } + else + { + /* Now add the new message to the queue */ + msg = g_new0 (PendingMessage, 1); + msg->window = xevent->window; + msg->timeout = timeout; + msg->len = len; + msg->id = id; + msg->remaining_len = msg->len; + msg->str = g_malloc (msg->len + 1); + msg->str[msg->len] = '\0'; + manager->messages = g_list_prepend (manager->messages, msg); + } +} + +static void +na_tray_manager_handle_cancel_message (NaTrayManager *manager, + XClientMessageEvent *xevent) +{ + GList *p; + GtkSocket *socket; + + /* Check if the message is in the queue and remove it if so */ + for (p = manager->messages; p; p = p->next) + { + PendingMessage *msg = p->data; + + if (xevent->window == msg->window && + xevent->data.l[4] == msg->id) + { + pending_message_free (msg); + manager->messages = g_list_remove_link (manager->messages, p); + g_list_free_1 (p); + break; + } + } + + socket = g_hash_table_lookup (manager->socket_table, + GINT_TO_POINTER (xevent->window)); + + if (socket) + { + g_signal_emit (manager, manager_signals[MESSAGE_CANCELLED], 0, + socket, xevent->data.l[2]); + } +} + +static GdkFilterReturn +na_tray_manager_handle_client_message_opcode (GdkXEvent *xev, + GdkEvent *event, + gpointer data) +{ + XClientMessageEvent *xevent; + NaTrayManager *manager; + + xevent = (XClientMessageEvent *) xev; + manager = data; + + switch (xevent->data.l[1]) + { + case SYSTEM_TRAY_REQUEST_DOCK: + /* Ignore this one since we don't know on which window this was received + * and so we can't know for which screen this is. It will be handled + * in na_tray_manager_window_filter() since we also receive it there */ + break; + + case SYSTEM_TRAY_BEGIN_MESSAGE: + na_tray_manager_handle_begin_message (manager, xevent); + return GDK_FILTER_REMOVE; + + case SYSTEM_TRAY_CANCEL_MESSAGE: + na_tray_manager_handle_cancel_message (manager, xevent); + return GDK_FILTER_REMOVE; + default: + break; + } + + return GDK_FILTER_CONTINUE; +} + +static GdkFilterReturn +na_tray_manager_window_filter (GdkXEvent *xev, + GdkEvent *event, + gpointer data) +{ + XEvent *xevent = (GdkXEvent *)xev; + NaTrayManager *manager = data; + + if (xevent->type == ClientMessage) + { + /* We handle this client message here. See comment in + * na_tray_manager_handle_client_message_opcode() for details */ + if (xevent->xclient.message_type == manager->opcode_atom && + xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) + { + na_tray_manager_handle_dock_request (manager, + (XClientMessageEvent *) xevent); + return GDK_FILTER_REMOVE; + } + } + else if (xevent->type == SelectionClear) + { + g_signal_emit (manager, manager_signals[LOST_SELECTION], 0); + na_tray_manager_unmanage (manager); + } + + return GDK_FILTER_CONTINUE; +} + +#if 0 +//FIXME investigate why this doesn't work +static gboolean +na_tray_manager_selection_clear_event (GtkWidget *widget, + GdkEventSelection *event, + NaTrayManager *manager) +{ + g_signal_emit (manager, manager_signals[LOST_SELECTION], 0); + na_tray_manager_unmanage (manager); + + return FALSE; +} +#endif +#endif + +static void +na_tray_manager_unmanage (NaTrayManager *manager) +{ +#ifdef GDK_WINDOWING_X11 + GdkDisplay *display; + guint32 timestamp; + GtkWidget *invisible; + GdkWindow *window; + + if (manager->invisible == NULL) + return; + + invisible = manager->invisible; + window = gtk_widget_get_window (invisible); + + g_assert (GTK_IS_INVISIBLE (invisible)); + g_assert (gtk_widget_get_realized (invisible)); + g_assert (GDK_IS_WINDOW (window)); + + display = gtk_widget_get_display (invisible); + + if (gdk_selection_owner_get_for_display (display, manager->selection_atom) == + window) + { + timestamp = gdk_x11_get_server_time (window); + gdk_selection_owner_set_for_display (display, + NULL, + manager->selection_atom, + timestamp, + TRUE); + } + + //FIXME: we should also use gdk_remove_client_message_filter when it's + //available + // See bug #351254 + gdk_window_remove_filter (window, + na_tray_manager_window_filter, manager); + + manager->invisible = NULL; /* prior to destroy for reentrancy paranoia */ + gtk_widget_destroy (invisible); + g_object_unref (G_OBJECT (invisible)); +#endif +} + +static void +na_tray_manager_set_orientation_property (NaTrayManager *manager) +{ +#ifdef GDK_WINDOWING_X11 + GdkWindow *window; + GdkDisplay *display; + Atom orientation_atom; + gulong data[1]; + + if (!manager->invisible) + return; + window = gtk_widget_get_window (manager->invisible); + if (!window) + return; + + display = gtk_widget_get_display (manager->invisible); + orientation_atom = gdk_x11_get_xatom_by_name_for_display (display, + "_NET_SYSTEM_TRAY_ORIENTATION"); + + data[0] = manager->orientation == GTK_ORIENTATION_HORIZONTAL ? + SYSTEM_TRAY_ORIENTATION_HORZ : + SYSTEM_TRAY_ORIENTATION_VERT; + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XWINDOW (window), + orientation_atom, + XA_CARDINAL, 32, + PropModeReplace, + (guchar *) &data, 1); +#endif +} + +static void +na_tray_manager_set_visual_property (NaTrayManager *manager) +{ +#ifdef GDK_WINDOWING_X11 + GdkWindow *window; + GdkDisplay *display; + Visual *xvisual; + Atom visual_atom; + gulong data[1]; + + if (!manager->invisible) + return; + window = gtk_widget_get_window (manager->invisible); + if (!window) + return; + + /* The visual property is a hint to the tray icons as to what visual they + * should use for their windows. If the X server has RGBA colormaps, then + * we tell the tray icons to use a RGBA colormap and we'll composite the + * icon onto its parents with real transparency. Otherwise, we just tell + * the icon to use our colormap, and we'll do some hacks with parent + * relative backgrounds to simulate transparency. + */ + + display = gtk_widget_get_display (manager->invisible); + visual_atom = gdk_x11_get_xatom_by_name_for_display (display, + "_NET_SYSTEM_TRAY_VISUAL"); + + if (gdk_screen_get_rgba_visual (manager->screen) != NULL && + gdk_display_supports_composite (display)) + { + xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_rgba_visual (manager->screen)); + } + else + { + /* We actually want the visual of the tray where the icons will + * be embedded. In almost all cases, this will be the same as the visual + * of the screen. + */ + GdkColormap *colormap; + + colormap = gdk_screen_get_default_colormap (manager->screen); + xvisual = GDK_VISUAL_XVISUAL (gdk_colormap_get_visual (colormap)); + } + + data[0] = XVisualIDFromVisual (xvisual); + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XWINDOW (window), + visual_atom, + XA_VISUALID, 32, + PropModeReplace, + (guchar *) &data, 1); +#endif +} + +#ifdef GDK_WINDOWING_X11 + +static gboolean +na_tray_manager_manage_screen_x11 (NaTrayManager *manager, + GdkScreen *screen) +{ + GdkDisplay *display; + Screen *xscreen; + GtkWidget *invisible; + GdkWindow *window; + char *selection_atom_name; + guint32 timestamp; + + g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), FALSE); + g_return_val_if_fail (manager->screen == NULL, FALSE); + + /* If there's already a manager running on the screen + * we can't create another one. + */ +#if 0 + if (na_tray_manager_check_running_screen_x11 (screen)) + return FALSE; +#endif + + manager->screen = screen; + + display = gdk_screen_get_display (screen); + xscreen = GDK_SCREEN_XSCREEN (screen); + + invisible = gtk_invisible_new_for_screen (screen); + gtk_widget_realize (invisible); + + gtk_widget_add_events (invisible, + GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK); + + selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d", + gdk_screen_get_number (screen)); + manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE); + g_free (selection_atom_name); + + manager->invisible = invisible; + g_object_ref (G_OBJECT (manager->invisible)); + + na_tray_manager_set_orientation_property (manager); + na_tray_manager_set_visual_property (manager); + + window = gtk_widget_get_window (invisible); + + timestamp = gdk_x11_get_server_time (window); + + /* Check if we could set the selection owner successfully */ + if (gdk_selection_owner_set_for_display (display, + window, + manager->selection_atom, + timestamp, + TRUE)) + { + XClientMessageEvent xev; + GdkAtom opcode_atom; + GdkAtom message_data_atom; + + xev.type = ClientMessage; + xev.window = RootWindowOfScreen (xscreen); + xev.message_type = gdk_x11_get_xatom_by_name_for_display (display, + "MANAGER"); + + xev.format = 32; + xev.data.l[0] = timestamp; + xev.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, + manager->selection_atom); + xev.data.l[2] = GDK_WINDOW_XWINDOW (window); + xev.data.l[3] = 0; /* manager specific data */ + xev.data.l[4] = 0; /* manager specific data */ + + XSendEvent (GDK_DISPLAY_XDISPLAY (display), + RootWindowOfScreen (xscreen), + False, StructureNotifyMask, (XEvent *)&xev); + + opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE); + manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display, + opcode_atom); + + message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA", + FALSE); + + /* Add a window filter */ +#if 0 + /* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */ + g_signal_connect (invisible, "selection-clear-event", + G_CALLBACK (na_tray_manager_selection_clear_event), + manager); +#endif + /* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */ + gdk_window_add_filter (window, + na_tray_manager_window_filter, manager); + /* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */ + gdk_display_add_client_message_filter (display, opcode_atom, + na_tray_manager_handle_client_message_opcode, + manager); + /* This is for _NET_SYSTEM_TRAY_MESSAGE_DATA */ + gdk_display_add_client_message_filter (display, message_data_atom, + na_tray_manager_handle_client_message_message_data, + manager); + return TRUE; + } + else + { + gtk_widget_destroy (invisible); + g_object_unref (invisible); + manager->invisible = NULL; + + manager->screen = NULL; + + return FALSE; + } +} + +#endif + +gboolean +na_tray_manager_manage_screen (NaTrayManager *manager, + GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + g_return_val_if_fail (manager->screen == NULL, FALSE); + +#ifdef GDK_WINDOWING_X11 + return na_tray_manager_manage_screen_x11 (manager, screen); +#else + return FALSE; +#endif +} + +#ifdef GDK_WINDOWING_X11 + +static gboolean +na_tray_manager_check_running_screen_x11 (GdkScreen *screen) +{ + GdkDisplay *display; + Atom selection_atom; + char *selection_atom_name; + + display = gdk_screen_get_display (screen); + selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d", + gdk_screen_get_number (screen)); + selection_atom = gdk_x11_get_xatom_by_name_for_display (display, + selection_atom_name); + g_free (selection_atom_name); + + if (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), + selection_atom) != None) + return TRUE; + else + return FALSE; +} + +#endif + +gboolean +na_tray_manager_check_running (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + +#ifdef GDK_WINDOWING_X11 + return na_tray_manager_check_running_screen_x11 (screen); +#else + return FALSE; +#endif +} + +void +na_tray_manager_set_orientation (NaTrayManager *manager, + GtkOrientation orientation) +{ + g_return_if_fail (NA_IS_TRAY_MANAGER (manager)); + + if (manager->orientation != orientation) + { + manager->orientation = orientation; + + na_tray_manager_set_orientation_property (manager); + + g_object_notify (G_OBJECT (manager), "orientation"); + } +} + +GtkOrientation +na_tray_manager_get_orientation (NaTrayManager *manager) +{ + g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL); + + return manager->orientation; +} diff --git a/applets/notification_area/na-tray-manager.h b/applets/notification_area/na-tray-manager.h new file mode 100644 index 00000000..be678a28 --- /dev/null +++ b/applets/notification_area/na-tray-manager.h @@ -0,0 +1,101 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* na-tray-manager.h + * Copyright (C) 2002 Anders Carlsson + * Copyright (C) 2003-2006 Vincent Untz + * + * 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. + * + * Used to be: eggtraymanager.h + */ + +#ifndef __NA_TRAY_MANAGER_H__ +#define __NA_TRAY_MANAGER_H__ + +#ifdef GDK_WINDOWING_X11 +#include +#endif +#include + +#include "na-tray-child.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NA_TYPE_TRAY_MANAGER (na_tray_manager_get_type ()) +#define NA_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY_MANAGER, NaTrayManager)) +#define NA_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY_MANAGER, NaTrayManagerClass)) +#define NA_IS_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY_MANAGER)) +#define NA_IS_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY_MANAGER)) +#define NA_TRAY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY_MANAGER, NaTrayManagerClass)) + +typedef struct _NaTrayManager NaTrayManager; +typedef struct _NaTrayManagerClass NaTrayManagerClass; + +struct _NaTrayManager +{ + GObject parent_instance; + +#ifdef GDK_WINDOWING_X11 + GdkAtom selection_atom; + Atom opcode_atom; +#endif + + GtkWidget *invisible; + GdkScreen *screen; + GtkOrientation orientation; + + GList *messages; + GHashTable *socket_table; +}; + +struct _NaTrayManagerClass +{ + GObjectClass parent_class; + + void (* tray_icon_added) (NaTrayManager *manager, + NaTrayChild *child); + void (* tray_icon_removed) (NaTrayManager *manager, + NaTrayChild *child); + + void (* message_sent) (NaTrayManager *manager, + NaTrayChild *child, + const gchar *message, + glong id, + glong timeout); + + void (* message_cancelled) (NaTrayManager *manager, + NaTrayChild *child, + glong id); + + void (* lost_selection) (NaTrayManager *manager); +}; + +GType na_tray_manager_get_type (void); + +gboolean na_tray_manager_check_running (GdkScreen *screen); +NaTrayManager *na_tray_manager_new (void); +gboolean na_tray_manager_manage_screen (NaTrayManager *manager, + GdkScreen *screen); +void na_tray_manager_set_orientation (NaTrayManager *manager, + GtkOrientation orientation); +GtkOrientation na_tray_manager_get_orientation (NaTrayManager *manager); + +#ifdef __cplusplus +} +#endif + +#endif /* __NA_TRAY_MANAGER_H__ */ diff --git a/applets/notification_area/na-tray.c b/applets/notification_area/na-tray.c new file mode 100644 index 00000000..b866e880 --- /dev/null +++ b/applets/notification_area/na-tray.c @@ -0,0 +1,837 @@ +/* + * Copyright (C) 2002 Red Hat, Inc. + * Copyright (C) 2003-2006 Vincent Untz + * Copyright (C) 2007 Christian Persch + * + * 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 +#include + +#include +#include + +#include + +#include "na-tray-manager.h" +#include "fixedtip.h" + +#include "na-tray.h" + +#define ICON_SPACING 1 +#define MIN_BOX_SIZE 3 + +typedef struct +{ + NaTrayManager *tray_manager; + GSList *all_trays; + GHashTable *icon_table; + GHashTable *tip_table; +} TraysScreen; + +struct _NaTrayPrivate +{ + GdkScreen *screen; + TraysScreen *trays_screen; + + GtkWidget *box; + GtkWidget *frame; + + guint idle_redraw_id; + + GtkOrientation orientation; +}; + +typedef struct +{ + char *text; + glong id; + glong timeout; +} IconTipBuffer; + +typedef struct +{ + NaTray *tray; /* tray containing the tray icon */ + GtkWidget *icon; /* tray icon sending the message */ + GtkWidget *fixedtip; + guint source_id; + glong id; /* id of the current message */ + GSList *buffer; /* buffered messages */ +} IconTip; + +enum +{ + PROP_0, + PROP_ORIENTATION, + PROP_SCREEN +}; + +static gboolean initialized = FALSE; +static TraysScreen *trays_screens = NULL; + +static void icon_tip_show_next (IconTip *icontip); + +/* NaBox, an instantiable GtkBox */ + +typedef GtkBox NaBox; +typedef GtkBoxClass NaBoxClass; + +static GType na_box_get_type (void); + +G_DEFINE_TYPE (NaBox, na_box, GTK_TYPE_BOX) + +static void +na_box_init (NaBox *box) +{ +} + +static void +na_box_class_init (NaBoxClass *klass) +{ +} + +/* NaTray */ + +G_DEFINE_TYPE (NaTray, na_tray, GTK_TYPE_BIN) + +static NaTray * +get_tray (TraysScreen *trays_screen) +{ + if (trays_screen->all_trays == NULL) + return NULL; + + return trays_screen->all_trays->data; +} + +const char *ordered_roles[] = { + "keyboard", + "volume", + "bluetooth", + "network", + "battery", + NULL +}; + +const char *wmclass_roles[] = { + "Bluetooth-applet", "bluetooth", + "Mate-volume-control-applet", "volume", + "Nm-applet", "network", + "Mate-power-manager", "battery", + "keyboard", "keyboard", + NULL, +}; + +static const char * +find_role (const char *wmclass) +{ + int i; + + for (i = 0; wmclass_roles[i]; i += 2) + { + if (strcmp (wmclass, wmclass_roles[i]) == 0) + return wmclass_roles[i + 1]; + } + + return NULL; +} + +static int +find_role_position (const char *role) +{ + int i; + + for (i = 0; ordered_roles[i]; i++) + { + if (strcmp (role, ordered_roles[i]) == 0) + break; + } + + return i + 1; +} + +static int +find_icon_position (NaTray *tray, + GtkWidget *icon) +{ + NaTrayPrivate *priv; + int position; + char *class_a; + const char *role; + int role_position; + GList *l, *children; + + /* We insert the icons with a known roles in a specific order (the one + * defined by ordered_roles), and all other icons at the beginning of the box + * (left in LTR). */ + + priv = tray->priv; + position = 0; + + class_a = NULL; + na_tray_child_get_wm_class (NA_TRAY_CHILD (icon), NULL, &class_a); + if (!class_a) + return position; + + role = find_role (class_a); + g_free (class_a); + if (!role) + return position; + + role_position = find_role_position (role); + g_object_set_data (G_OBJECT (icon), "role-position", GINT_TO_POINTER (role_position)); + + children = gtk_container_get_children (GTK_CONTAINER (priv->box)); + for (l = g_list_last (children); l; l = l->prev) + { + GtkWidget *child = l->data; + int rp; + + rp = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), "role-position")); + if (rp == 0 || rp < role_position) + { + position = g_list_index (children, child) + 1; + break; + } + } + g_list_free (children); + + /* should never happen, but it doesn't hurt to be on the safe side */ + if (position < 0) + position = 0; + + return position; +} + +static void +tray_added (NaTrayManager *manager, + GtkWidget *icon, + TraysScreen *trays_screen) +{ + NaTray *tray; + NaTrayPrivate *priv; + int position; + + tray = get_tray (trays_screen); + if (tray == NULL) + return; + + priv = tray->priv; + + g_assert (priv->trays_screen == trays_screen); + + g_hash_table_insert (trays_screen->icon_table, icon, tray); + + position = find_icon_position (tray, icon); + gtk_box_pack_start (GTK_BOX (priv->box), icon, FALSE, FALSE, 0); + gtk_box_reorder_child (GTK_BOX (priv->box), icon, position); + + gtk_widget_show (icon); +} + +static void +tray_removed (NaTrayManager *manager, + GtkWidget *icon, + TraysScreen *trays_screen) +{ + NaTray *tray; + + tray = g_hash_table_lookup (trays_screen->icon_table, icon); + if (tray == NULL) + return; + + g_assert (tray->priv->trays_screen == trays_screen); + + g_hash_table_remove (trays_screen->icon_table, icon); + /* this will also destroy the tip associated to this icon */ + g_hash_table_remove (trays_screen->tip_table, icon); +} + +static void +icon_tip_buffer_free (gpointer data, + gpointer userdata) +{ + IconTipBuffer *buffer; + + buffer = data; + + g_free (buffer->text); + buffer->text = NULL; + + g_free (buffer); +} + +static void +icon_tip_free (gpointer data) +{ + IconTip *icontip; + + if (data == NULL) + return; + + icontip = data; + + if (icontip->fixedtip != NULL) + gtk_widget_destroy (GTK_WIDGET (icontip->fixedtip)); + icontip->fixedtip = NULL; + + if (icontip->source_id != 0) + g_source_remove (icontip->source_id); + icontip->source_id = 0; + + if (icontip->buffer != NULL) + { + g_slist_foreach (icontip->buffer, icon_tip_buffer_free, NULL); + g_slist_free (icontip->buffer); + } + icontip->buffer = NULL; + + g_free (icontip); +} + +static int +icon_tip_buffer_compare (gconstpointer a, + gconstpointer b) +{ + const IconTipBuffer *buffer_a = a; + const IconTipBuffer *buffer_b = b; + + if (buffer_a == NULL || buffer_b == NULL) + return !(buffer_a == buffer_b); + + return buffer_a->id - buffer_b->id; +} + +static void +icon_tip_show_next_clicked (GtkWidget *widget, + gpointer data) +{ + icon_tip_show_next ((IconTip *) data); +} + +static gboolean +icon_tip_show_next_timeout (gpointer data) +{ + IconTip *icontip = (IconTip *) data; + + icon_tip_show_next (icontip); + + return FALSE; +} + +static void +icon_tip_show_next (IconTip *icontip) +{ + IconTipBuffer *buffer; + + if (icontip->buffer == NULL) + { + /* this will also destroy the tip window */ + g_hash_table_remove (icontip->tray->priv->trays_screen->tip_table, + icontip->icon); + return; + } + + if (icontip->source_id != 0) + g_source_remove (icontip->source_id); + icontip->source_id = 0; + + buffer = icontip->buffer->data; + icontip->buffer = g_slist_remove (icontip->buffer, buffer); + + if (icontip->fixedtip == NULL) + { + icontip->fixedtip = na_fixed_tip_new (icontip->icon, + na_tray_get_orientation (icontip->tray)); + + g_signal_connect (icontip->fixedtip, "clicked", + G_CALLBACK (icon_tip_show_next_clicked), icontip); + } + + na_fixed_tip_set_markup (icontip->fixedtip, buffer->text); + + if (!gtk_widget_get_mapped (icontip->fixedtip)) + gtk_widget_show (icontip->fixedtip); + + icontip->id = buffer->id; + + if (buffer->timeout > 0) + icontip->source_id = g_timeout_add_seconds (buffer->timeout, + icon_tip_show_next_timeout, + icontip); + + icon_tip_buffer_free (buffer, NULL); +} + +static void +message_sent (NaTrayManager *manager, + GtkWidget *icon, + const char *text, + glong id, + glong timeout, + TraysScreen *trays_screen) +{ + IconTip *icontip; + IconTipBuffer find_buffer; + IconTipBuffer *buffer; + gboolean show_now; + + icontip = g_hash_table_lookup (trays_screen->tip_table, icon); + + find_buffer.id = id; + if (icontip && + (icontip->id == id || + g_slist_find_custom (icontip->buffer, &find_buffer, + icon_tip_buffer_compare) != NULL)) + /* we already have this message, so ignore it */ + /* FIXME: in an ideal world, we'd remember all the past ids and ignore them + * too */ + return; + + show_now = FALSE; + + if (icontip == NULL) + { + NaTray *tray; + + tray = g_hash_table_lookup (trays_screen->icon_table, icon); + if (tray == NULL) + { + /* We don't know about the icon sending the message, so ignore it. + * But this should never happen since NaTrayManager shouldn't send + * us the message if there's no socket for it. */ + g_critical ("Ignoring a message sent by a tray icon " + "we don't know: \"%s\".\n", text); + return; + } + + icontip = g_new0 (IconTip, 1); + icontip->tray = tray; + icontip->icon = icon; + + g_hash_table_insert (trays_screen->tip_table, icon, icontip); + + show_now = TRUE; + } + + buffer = g_new0 (IconTipBuffer, 1); + + buffer->text = g_strdup (text); + buffer->id = id; + buffer->timeout = timeout; + + icontip->buffer = g_slist_append (icontip->buffer, buffer); + + if (show_now) + icon_tip_show_next (icontip); +} + +static void +message_cancelled (NaTrayManager *manager, + GtkWidget *icon, + glong id, + TraysScreen *trays_screen) +{ + IconTip *icontip; + IconTipBuffer find_buffer; + GSList *cancel_buffer_l; + IconTipBuffer *cancel_buffer; + + icontip = g_hash_table_lookup (trays_screen->tip_table, icon); + if (icontip == NULL) + return; + + if (icontip->id == id) + { + icon_tip_show_next (icontip); + return; + } + + find_buffer.id = id; + cancel_buffer_l = g_slist_find_custom (icontip->buffer, &find_buffer, + icon_tip_buffer_compare); + if (cancel_buffer_l == NULL) + return; + + cancel_buffer = cancel_buffer_l->data; + icon_tip_buffer_free (cancel_buffer, NULL); + + icontip->buffer = g_slist_remove_link (icontip->buffer, cancel_buffer_l); + g_slist_free_1 (cancel_buffer_l); +} + +static void +update_orientation_for_messages (gpointer key, + gpointer value, + gpointer data) +{ + NaTray *tray; + IconTip *icontip; + + if (value == NULL) + return; + + icontip = value; + tray = data; + if (icontip->tray != tray) + return; + + if (icontip->fixedtip) + na_fixed_tip_set_orientation (icontip->fixedtip, tray->priv->orientation); +} + +static void +update_size_and_orientation (NaTray *tray) +{ + NaTrayPrivate *priv = tray->priv; + + gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), priv->orientation); + + /* This only happens when setting the property during object construction */ + if (!priv->trays_screen) + return; + + g_hash_table_foreach (priv->trays_screen->tip_table, + update_orientation_for_messages, tray); + + if (get_tray (priv->trays_screen) == tray) + na_tray_manager_set_orientation (priv->trays_screen->tray_manager, + priv->orientation); + + /* note, you want this larger if the frame has non-NONE relief by default. */ + switch (priv->orientation) + { + case GTK_ORIENTATION_VERTICAL: + /* Give box a min size so the frame doesn't look dumb */ + gtk_widget_set_size_request (priv->box, MIN_BOX_SIZE, -1); + break; + case GTK_ORIENTATION_HORIZONTAL: + gtk_widget_set_size_request (priv->box, -1, MIN_BOX_SIZE); + break; + } +} + +/* Children with alpha channels have been set to be composited by calling + * gdk_window_set_composited(). We need to paint these children ourselves. + */ +static void +na_tray_expose_icon (GtkWidget *widget, + gpointer data) +{ + cairo_t *cr = data; + + if (na_tray_child_has_alpha (NA_TRAY_CHILD (widget))) + { + GtkAllocation allocation; + + gtk_widget_get_allocation (widget, &allocation); + + gdk_cairo_set_source_pixmap (cr, + gtk_widget_get_window (widget), + allocation.x, + allocation.y); + cairo_paint (cr); + } +} + +static void +na_tray_expose_box (GtkWidget *box, + GdkEventExpose *event) +{ + cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (box)); + + gdk_cairo_region (cr, event->region); + cairo_clip (cr); + + gtk_container_foreach (GTK_CONTAINER (box), na_tray_expose_icon, cr); + + cairo_destroy (cr); +} + +static void +na_tray_init (NaTray *tray) +{ + NaTrayPrivate *priv; + + priv = tray->priv = G_TYPE_INSTANCE_GET_PRIVATE (tray, NA_TYPE_TRAY, NaTrayPrivate); + + priv->screen = NULL; + priv->orientation = GTK_ORIENTATION_HORIZONTAL; + + priv->frame = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); + gtk_container_add (GTK_CONTAINER (tray), priv->frame); + gtk_widget_show (priv->frame); + + priv->box = g_object_new (na_box_get_type (), NULL); + g_signal_connect (priv->box, "expose-event", + G_CALLBACK (na_tray_expose_box), tray); + gtk_box_set_spacing (GTK_BOX (priv->box), ICON_SPACING); + gtk_container_add (GTK_CONTAINER (priv->frame), priv->box); + gtk_widget_show (priv->box); +} + +static GObject * +na_tray_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + NaTray *tray; + NaTrayPrivate *priv; + int screen_number; + + object = G_OBJECT_CLASS (na_tray_parent_class)->constructor (type, + n_construct_properties, + construct_params); + tray = NA_TRAY (object); + priv = tray->priv; + + g_assert (priv->screen != NULL); + + if (!initialized) + { + GdkDisplay *display; + int n_screens; + + display = gdk_display_get_default (); + n_screens = gdk_display_get_n_screens (display); + trays_screens = g_new0 (TraysScreen, n_screens); + initialized = TRUE; + } + + screen_number = gdk_screen_get_number (priv->screen); + + if (trays_screens [screen_number].tray_manager == NULL) + { + NaTrayManager *tray_manager; + + tray_manager = na_tray_manager_new (); + + if (na_tray_manager_manage_screen (tray_manager, priv->screen)) + { + trays_screens [screen_number].tray_manager = tray_manager; + + g_signal_connect (tray_manager, "tray_icon_added", + G_CALLBACK (tray_added), + &trays_screens [screen_number]); + g_signal_connect (tray_manager, "tray_icon_removed", + G_CALLBACK (tray_removed), + &trays_screens [screen_number]); + g_signal_connect (tray_manager, "message_sent", + G_CALLBACK (message_sent), + &trays_screens [screen_number]); + g_signal_connect (tray_manager, "message_cancelled", + G_CALLBACK (message_cancelled), + &trays_screens [screen_number]); + + trays_screens [screen_number].icon_table = g_hash_table_new (NULL, + NULL); + trays_screens [screen_number].tip_table = g_hash_table_new_full ( + NULL, + NULL, + NULL, + icon_tip_free); + } + else + { + g_printerr ("System tray didn't get the system tray manager selection for screen %d\n", + screen_number); + g_object_unref (tray_manager); + } + } + + priv->trays_screen = &trays_screens [screen_number]; + trays_screens [screen_number].all_trays = g_slist_append (trays_screens [screen_number].all_trays, + tray); + + update_size_and_orientation (tray); + + return object; +} + +static void +na_tray_dispose (GObject *object) +{ + NaTray *tray = NA_TRAY (object); + NaTrayPrivate *priv = tray->priv; + TraysScreen *trays_screen = priv->trays_screen; + + if (trays_screen != NULL) + { + trays_screen->all_trays = g_slist_remove (trays_screen->all_trays, tray); + + if (trays_screen->all_trays == NULL) + { + /* Make sure we drop the manager selection */ + g_object_unref (trays_screen->tray_manager); + trays_screen->tray_manager = NULL; + + g_hash_table_destroy (trays_screen->icon_table); + trays_screen->icon_table = NULL; + + g_hash_table_destroy (trays_screen->tip_table); + trays_screen->tip_table = NULL; + } + else + { + NaTray *new_tray; + + new_tray = get_tray (trays_screen); + if (new_tray != NULL) + na_tray_manager_set_orientation (trays_screen->tray_manager, + na_tray_get_orientation (new_tray)); + } + } + + priv->trays_screen = NULL; + + if (priv->idle_redraw_id != 0) + { + g_source_remove (priv->idle_redraw_id); + priv->idle_redraw_id = 0; + } + + G_OBJECT_CLASS (na_tray_parent_class)->dispose (object); +} + +static void +na_tray_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NaTray *tray = NA_TRAY (object); + NaTrayPrivate *priv = tray->priv; + + switch (prop_id) + { + case PROP_ORIENTATION: + na_tray_set_orientation (tray, g_value_get_enum (value)); + break; + case PROP_SCREEN: + priv->screen = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +na_tray_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + gtk_widget_size_request (gtk_bin_get_child (GTK_BIN (widget)), requisition); +} + +static void +na_tray_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + gtk_widget_size_allocate (gtk_bin_get_child (GTK_BIN (widget)), allocation); +} + +static void +na_tray_class_init (NaTrayClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gobject_class->constructor = na_tray_constructor; + gobject_class->set_property = na_tray_set_property; + gobject_class->dispose = na_tray_dispose; + + widget_class->size_request = na_tray_size_request; + widget_class->size_allocate = na_tray_size_allocate; + + g_object_class_install_property + (gobject_class, + PROP_ORIENTATION, + g_param_spec_enum ("orientation", "orientation", "orientation", + GTK_TYPE_ORIENTATION, + GTK_ORIENTATION_HORIZONTAL, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property + (gobject_class, + PROP_SCREEN, + g_param_spec_object ("screen", "screen", "screen", + GDK_TYPE_SCREEN, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_type_class_add_private (gobject_class, sizeof (NaTrayPrivate)); +} + +NaTray * +na_tray_new_for_screen (GdkScreen *screen, + GtkOrientation orientation) +{ + return g_object_new (NA_TYPE_TRAY, + "screen", screen, + "orientation", orientation, + NULL); +} + +void +na_tray_set_orientation (NaTray *tray, + GtkOrientation orientation) +{ + NaTrayPrivate *priv = tray->priv; + + if (orientation == priv->orientation) + return; + + priv->orientation = orientation; + + update_size_and_orientation (tray); +} + +GtkOrientation +na_tray_get_orientation (NaTray *tray) +{ + return tray->priv->orientation; +} + +static gboolean +idle_redraw_cb (NaTray *tray) +{ + NaTrayPrivate *priv = tray->priv; + + gtk_container_foreach (GTK_CONTAINER (priv->box), (GtkCallback)na_tray_child_force_redraw, tray); + + priv->idle_redraw_id = 0; + + return FALSE; +} + +void +na_tray_force_redraw (NaTray *tray) +{ + NaTrayPrivate *priv = tray->priv; + + /* Force the icons to redraw their backgrounds. + */ + if (priv->idle_redraw_id == 0) + priv->idle_redraw_id = g_idle_add ((GSourceFunc) idle_redraw_cb, tray); +} diff --git a/applets/notification_area/na-tray.h b/applets/notification_area/na-tray.h new file mode 100644 index 00000000..1154d378 --- /dev/null +++ b/applets/notification_area/na-tray.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* na-tray-tray.h + * Copyright (C) 2002 Anders Carlsson + * Copyright (C) 2003-2006 Vincent Untz + * + * 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. + * + * Used to be: eggtraytray.h + */ + +#ifndef __NA_TRAY_H__ +#define __NA_TRAY_H__ + +#ifdef GDK_WINDOWING_X11 +#include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NA_TYPE_TRAY (na_tray_get_type ()) +#define NA_TRAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY, NaTray)) +#define NA_TRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY, NaTrayClass)) +#define NA_IS_TRAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY)) +#define NA_IS_TRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY)) +#define NA_TRAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY, NaTrayClass)) + +typedef struct _NaTray NaTray; +typedef struct _NaTrayPrivate NaTrayPrivate; +typedef struct _NaTrayClass NaTrayClass; + +struct _NaTray +{ + GtkBin parent_instance; + + NaTrayPrivate *priv; +}; + +struct _NaTrayClass +{ + GtkBinClass parent_class; +}; + +GType na_tray_get_type (void); +NaTray *na_tray_new_for_screen (GdkScreen *screen, + GtkOrientation orientation); +void na_tray_set_orientation (NaTray *tray, + GtkOrientation orientation); +GtkOrientation na_tray_get_orientation (NaTray *tray); +void na_tray_force_redraw (NaTray *tray); + +#ifdef __cplusplus +} +#endif + +#endif /* __NA_TRAY_H__ */ diff --git a/applets/notification_area/notification-area-menu.xml b/applets/notification_area/notification-area-menu.xml new file mode 100644 index 00000000..fdbcc83f --- /dev/null +++ b/applets/notification_area/notification-area-menu.xml @@ -0,0 +1,3 @@ + + + diff --git a/applets/notification_area/org.mate.panel.NotificationAreaApplet.mate-panel-applet.in.in b/applets/notification_area/org.mate.panel.NotificationAreaApplet.mate-panel-applet.in.in new file mode 100644 index 00000000..4c9cc1e0 --- /dev/null +++ b/applets/notification_area/org.mate.panel.NotificationAreaApplet.mate-panel-applet.in.in @@ -0,0 +1,17 @@ +[Applet Factory] +Id=NotificationAreaAppletFactory +InProcess=@IN_PROCESS@ +Location=@LOCATION@ +_Name=Notification Area Factory +_Description=Factory for notification area + +[NotificationArea] +_Name=Notification Area +_Description=Area where notification icons appear +Icon=mate-panel-notification-area +MateComponentId=OAFIID:MATE_NotificationAreaApplet;OAFIID:MATE_SystemTrayApplet; +X-MATE-Bugzilla-Bugzilla=MATE +X-MATE-Bugzilla-Product=mate-panel +X-MATE-Bugzilla-Component=notification area +X-MATE-Bugzilla-Version=@VERSION@ +X-MATE-Bugzilla-OtherBinaries=notification-area-applet diff --git a/applets/notification_area/org.mate.panel.applet.NotificationAreaAppletFactory.service.in b/applets/notification_area/org.mate.panel.applet.NotificationAreaAppletFactory.service.in new file mode 100644 index 00000000..cd7d21c0 --- /dev/null +++ b/applets/notification_area/org.mate.panel.applet.NotificationAreaAppletFactory.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.mate.panel.applet.NotificationAreaAppletFactory +Exec=@LOCATION@ diff --git a/applets/notification_area/testtray.c b/applets/notification_area/testtray.c new file mode 100644 index 00000000..d052bedf --- /dev/null +++ b/applets/notification_area/testtray.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2002 Anders Carlsson + * Copyright (C) 2003-2006 Vincent Untz + * Copyright (C) 2006, 2007 Christian Persch + * + * 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. + */ + +#include "config.h" + +#include +#include +#include +#include "na-tray-manager.h" +#include "na-tray.h" + +#define NOTIFICATION_AREA_ICON "mate-panel-notification-area" + +static guint n_windows = 0; + +typedef struct +{ + GdkScreen *screen; + guint screen_num; + GtkWidget *window; + NaTray *tray; + GtkWidget *box; + GtkLabel *count_label; +} TrayData; + +static void +do_add (GtkWidget *child, guint *n_children) +{ + *n_children += 1; +} + +static void +update_child_count (TrayData *data) +{ + guint n_children = 0; + char text[64]; + + if (!gtk_widget_get_realized (data->window)) + return; + + gtk_container_foreach (GTK_CONTAINER (data->box), (GtkCallback) do_add, &n_children); + + g_snprintf (text, sizeof (text), "%u icons", n_children); + gtk_label_set_text (data->count_label, text); +} + +static void +tray_added_cb (GtkContainer *box, GtkWidget *icon, TrayData *data) +{ + g_print ("[Screen %u tray %p] Child %p added to tray: \"%s\"\n", + data->screen_num, data->tray, icon, "XXX");//na_tray_child_get_title (icon)); + + update_child_count (data); +} + +static void +tray_removed_cb (GtkContainer *box, GtkWidget *icon, TrayData *data) +{ + g_print ("[Screen %u tray %p] Child %p removed from tray\n", + data->screen_num, data->tray, icon); + + update_child_count (data); +} + +static void orientation_changed_cb (GtkComboBox *combo, TrayData *data) +{ + GtkOrientation orientation = (GtkOrientation) gtk_combo_box_get_active (combo); + + g_print ("[Screen %u tray %p] Setting orientation to \"%s\"\n", + data->screen_num, data->tray, orientation == 0 ? "horizontal" : "vertical"); + + na_tray_set_orientation (data->tray, orientation); +} + +static void +maybe_quit (gpointer data, + GObject *zombie) +{ + if (--n_windows == 0) { + gtk_main_quit (); + } +} + +static TrayData *create_tray_on_screen (GdkScreen *screen, gboolean force); + +static void +warning_dialog_response_cb (GtkWidget *dialog, + gint response, + GdkScreen *screen) +{ + if (response == GTK_RESPONSE_YES) { + create_tray_on_screen (screen, TRUE); + } + + gtk_widget_destroy (dialog); +} + +static void +add_tray_cb (GtkWidget *button, TrayData *data) +{ + create_tray_on_screen (data->screen, TRUE); +} + +static TrayData * +create_tray_on_screen (GdkScreen *screen, + gboolean force) +{ + GtkWidget *window, *hbox, *vbox, *button, *combo, *label; + TrayData *data; + + n_windows++; + + if (!force && na_tray_manager_check_running (screen)) { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, + "Override tray manager?"); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + "There is already a tray manager running on screen %d.", + gdk_screen_get_number (screen)); + gtk_window_set_screen (GTK_WINDOW (dialog), screen); + g_signal_connect (dialog, "response", G_CALLBACK (warning_dialog_response_cb), screen); + gtk_window_present (GTK_WINDOW (dialog)); + g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) maybe_quit, NULL); + return NULL; + } + + data = g_new0 (TrayData, 1); + data->screen = screen; + data->screen_num = gdk_screen_get_number (screen); + + data->window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_object_weak_ref (G_OBJECT (window), (GWeakNotify) maybe_quit, NULL); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (window), vbox); + + button = gtk_button_new_with_mnemonic ("_Add another tray"); + g_signal_connect (button, "clicked", G_CALLBACK (add_tray_cb), data); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + label = gtk_label_new_with_mnemonic ("_Orientation:"); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + combo = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "Horizontal"); + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "Vertical"); + g_signal_connect (combo, "changed", + G_CALLBACK (orientation_changed_cb), data); + gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0); + + label = gtk_label_new (NULL); + data->count_label = GTK_LABEL (label); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + data->tray = na_tray_new_for_screen (screen, GTK_ORIENTATION_HORIZONTAL); + gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (data->tray), TRUE, TRUE, 0); + + data->box = gtk_bin_get_child (GTK_BIN (gtk_bin_get_child (GTK_BIN (data->tray)))); + g_signal_connect_after (data->box, "add", G_CALLBACK (tray_added_cb), data); + g_signal_connect_after (data->box, "remove", G_CALLBACK (tray_removed_cb), data); + + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); + + gtk_window_set_screen (GTK_WINDOW (window), screen); + gtk_window_set_default_size (GTK_WINDOW (window), -1, 200); + + /* gtk_window_set_resizable (GTK_WINDOW (window), FALSE); */ + + gtk_widget_show_all (window); + + update_child_count (data); + + return data; +} + +int +main (int argc, char *argv[]) +{ + GdkDisplay *display; + GdkScreen *screen; + int n_screens, i; + + gtk_init (&argc, &argv); + + gtk_window_set_default_icon_name (NOTIFICATION_AREA_ICON); + + display = gdk_display_get_default (); + n_screens = gdk_display_get_n_screens (display); + for (i = 0; i < n_screens; ++i) { + screen = gdk_display_get_screen (display, i); + + create_tray_on_screen (screen, FALSE); + } + + gtk_main (); + + return 0; +} -- cgit v1.2.1