Merging upstream version 0.2.
authorDaniel Baumann <daniel@debian.org>
Fri, 20 Apr 2012 10:11:33 +0000 (12:11 +0200)
committerDaniel Baumann <daniel@debian.org>
Fri, 20 Apr 2012 10:11:33 +0000 (12:11 +0200)
27 files changed:
Makefile.am
Makefile.in
configure
configure.in
data/Learn.directory [new file with mode: 0644]
data/Math.directory [new file with mode: 0644]
data/Play.directory [new file with mode: 0644]
data/Science.directory [new file with mode: 0644]
data/Work.directory [new file with mode: 0644]
data/launcher.menu [new file with mode: 0644]
gtkrc
po/fi.gmo
po/fi.po
po/hu.gmo [new file with mode: 0644]
po/hu.po [new file with mode: 0644]
po/lxlauncher.pot
po/zh_TW.gmo
po/zh_TW.po
src/Makefile.am
src/Makefile.in
src/inotify/inotify-syscalls.h [deleted file]
src/inotify/linux-inotify.h [deleted file]
src/lxlauncher.c
src/misc.c [new file with mode: 0644]
src/misc.h [new file with mode: 0644]
src/vfs-app-desktop.c [deleted file]
src/vfs-app-desktop.h [deleted file]

index 99e0dc1..bb10b18 100644 (file)
@@ -5,9 +5,24 @@ SUBDIRS = src po
 themedir=$(datadir)/lxlauncher
 theme_DATA=gtkrc
 
+datafiledir=$(datadir)/lxlauncher
+datafile_DATA=\
+       data/launcher.menu
+
+directorydir=$(datadir)/desktop-directories
+directory_DATA=\
+       data/WebMail.directory \
+       data/Work.directory \
+       data/Learn.directory \
+       data/Play.directory \
+       data/Science.directory \
+       data/Math.directory
+
 #backgrounddir=$(datadir)/lxlauncher/background
 #background_DATA=
 
 EXTRA_DIST = \
        $(theme_DATA) \
+       $(datafile_DATA) \
+       $(directory_DATA) \
        autogen.sh
index 6b24e28..a95cb3d 100644 (file)
@@ -59,9 +59,12 @@ am__vpath_adj = case $$p in \
     *) f=$$p;; \
   esac;
 am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
-am__installdirs = "$(DESTDIR)$(themedir)"
+am__installdirs = "$(DESTDIR)$(datafiledir)" \
+       "$(DESTDIR)$(directorydir)" "$(DESTDIR)$(themedir)"
+datafileDATA_INSTALL = $(INSTALL_DATA)
+directoryDATA_INSTALL = $(INSTALL_DATA)
 themeDATA_INSTALL = $(INSTALL_DATA)
-DATA = $(theme_DATA)
+DATA = $(datafile_DATA) $(directory_DATA) $(theme_DATA)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
   distclean-recursive maintainer-clean-recursive
 ETAGS = etags
@@ -101,6 +104,8 @@ ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GMENU_CFLAGS = @GMENU_CFLAGS@
+GMENU_LIBS = @GMENU_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
 GREP = @GREP@
@@ -188,11 +193,25 @@ top_srcdir = @top_srcdir@
 SUBDIRS = src po
 themedir = $(datadir)/lxlauncher
 theme_DATA = gtkrc
+datafiledir = $(datadir)/lxlauncher
+datafile_DATA = \
+       data/launcher.menu
+
+directorydir = $(datadir)/desktop-directories
+directory_DATA = \
+       data/Work.directory \
+       data/Learn.directory \
+       data/Play.directory \
+       data/Science.directory \
+       data/Math.directory
+
 
 #backgrounddir=$(datadir)/lxlauncher/background
 #background_DATA=
 EXTRA_DIST = \
        $(theme_DATA) \
+       $(datafile_DATA) \
+       $(directory_DATA) \
        autogen.sh
 
 all: config.h
@@ -249,6 +268,40 @@ $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 
 distclean-hdr:
        -rm -f config.h stamp-h1
+install-datafileDATA: $(datafile_DATA)
+       @$(NORMAL_INSTALL)
+       test -z "$(datafiledir)" || $(MKDIR_P) "$(DESTDIR)$(datafiledir)"
+       @list='$(datafile_DATA)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(datafileDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(datafiledir)/$$f'"; \
+         $(datafileDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(datafiledir)/$$f"; \
+       done
+
+uninstall-datafileDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(datafile_DATA)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(datafiledir)/$$f'"; \
+         rm -f "$(DESTDIR)$(datafiledir)/$$f"; \
+       done
+install-directoryDATA: $(directory_DATA)
+       @$(NORMAL_INSTALL)
+       test -z "$(directorydir)" || $(MKDIR_P) "$(DESTDIR)$(directorydir)"
+       @list='$(directory_DATA)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(directoryDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(directorydir)/$$f'"; \
+         $(directoryDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(directorydir)/$$f"; \
+       done
+
+uninstall-directoryDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(directory_DATA)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(directorydir)/$$f'"; \
+         rm -f "$(DESTDIR)$(directorydir)/$$f"; \
+       done
 install-themeDATA: $(theme_DATA)
        @$(NORMAL_INSTALL)
        test -z "$(themedir)" || $(MKDIR_P) "$(DESTDIR)$(themedir)"
@@ -550,7 +603,7 @@ check: check-recursive
 all-am: Makefile $(DATA) config.h
 installdirs: installdirs-recursive
 installdirs-am:
-       for dir in "$(DESTDIR)$(themedir)"; do \
+       for dir in "$(DESTDIR)$(datafiledir)" "$(DESTDIR)$(directorydir)" "$(DESTDIR)$(themedir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
 install: install-recursive
@@ -596,7 +649,8 @@ info: info-recursive
 
 info-am:
 
-install-data-am: install-themeDATA
+install-data-am: install-datafileDATA install-directoryDATA \
+       install-themeDATA
 
 install-dvi: install-dvi-recursive
 
@@ -632,7 +686,8 @@ ps: ps-recursive
 
 ps-am:
 
-uninstall-am: uninstall-themeDATA
+uninstall-am: uninstall-datafileDATA uninstall-directoryDATA \
+       uninstall-themeDATA
 
 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
        install-strip
@@ -644,13 +699,15 @@ uninstall-am: uninstall-themeDATA
        distclean-generic distclean-hdr distclean-tags distcleancheck \
        distdir distuninstallcheck dvi dvi-am html html-am info \
        info-am install install-am install-data install-data-am \
-       install-dvi install-dvi-am install-exec install-exec-am \
-       install-html install-html-am install-info install-info-am \
-       install-man install-pdf install-pdf-am install-ps \
-       install-ps-am install-strip install-themeDATA installcheck \
-       installcheck-am installdirs installdirs-am maintainer-clean \
+       install-datafileDATA install-directoryDATA install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip install-themeDATA installcheck installcheck-am \
+       installdirs installdirs-am maintainer-clean \
        maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
        pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+       uninstall-datafileDATA uninstall-directoryDATA \
        uninstall-themeDATA
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
index 62b6f14..8fec04d 100755 (executable)
--- a/configure
+++ b/configure
@@ -699,6 +699,8 @@ GTK_CFLAGS
 GTK_LIBS
 SN_CFLAGS
 SN_LIBS
+GMENU_CFLAGS
+GMENU_LIBS
 GETTEXT_PACKAGE
 USE_NLS
 MSGFMT
@@ -732,7 +734,9 @@ PKG_CONFIG
 GTK_CFLAGS
 GTK_LIBS
 SN_CFLAGS
-SN_LIBS'
+SN_LIBS
+GMENU_CFLAGS
+GMENU_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1325,6 +1329,9 @@ Some influential environment variables:
   GTK_LIBS    linker flags for GTK, overriding pkg-config
   SN_CFLAGS   C compiler flags for SN, overriding pkg-config
   SN_LIBS     linker flags for SN, overriding pkg-config
+  GMENU_CFLAGS
+              C compiler flags for GMENU, overriding pkg-config
+  GMENU_LIBS  linker flags for GMENU, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -2085,7 +2092,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=lxlauncher
- VERSION=0.1.6
+ VERSION=0.2
 
 
 cat >>confdefs.h <<_ACEOF
@@ -5568,7 +5575,7 @@ _ACEOF
 fi
 
 
-pkg_modules="gtk+-2.0 >= 2.0.0"
+gtk_modules="gtk+-2.0 >= 2.10.0"
 
 
 if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
@@ -5699,12 +5706,12 @@ if test -n "$PKG_CONFIG"; then
         pkg_cv_GTK_CFLAGS="$GTK_CFLAGS"
     else
         if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$pkg_modules\"") >&5
-  ($PKG_CONFIG --exists --print-errors "$pkg_modules") 2>&5
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gtk_modules\"") >&5
+  ($PKG_CONFIG --exists --print-errors "$gtk_modules") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "$pkg_modules" 2>/dev/null`
+  pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "$gtk_modules" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -5717,12 +5724,12 @@ if test -n "$PKG_CONFIG"; then
         pkg_cv_GTK_LIBS="$GTK_LIBS"
     else
         if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$pkg_modules\"") >&5
-  ($PKG_CONFIG --exists --print-errors "$pkg_modules") 2>&5
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gtk_modules\"") >&5
+  ($PKG_CONFIG --exists --print-errors "$gtk_modules") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "$pkg_modules" 2>/dev/null`
+  pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "$gtk_modules" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -5741,14 +5748,14 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$pkg_modules"`
+               GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$gtk_modules"`
         else
-               GTK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$pkg_modules"`
+               GTK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$gtk_modules"`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GTK_PKG_ERRORS" >&5
 
-       { { echo "$as_me:$LINENO: error: Package requirements ($pkg_modules) were not met:
+       { { echo "$as_me:$LINENO: error: Package requirements ($gtk_modules) were not met:
 
 $GTK_PKG_ERRORS
 
@@ -5759,7 +5766,7 @@ Alternatively, you may set the environment variables GTK_CFLAGS
 and GTK_LIBS to avoid the need to call pkg-config.
 See the pkg-config man page for more details.
 " >&5
-echo "$as_me: error: Package requirements ($pkg_modules) were not met:
+echo "$as_me: error: Package requirements ($gtk_modules) were not met:
 
 $GTK_PKG_ERRORS
 
@@ -5918,6 +5925,121 @@ fi
 
 
 
+gmenu_modules="libgnome-menu >= 2.18.0"
+
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for GMENU" >&5
+echo $ECHO_N "checking for GMENU... $ECHO_C" >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$GMENU_CFLAGS"; then
+        pkg_cv_GMENU_CFLAGS="$GMENU_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gmenu_modules\"") >&5
+  ($PKG_CONFIG --exists --print-errors "$gmenu_modules") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_GMENU_CFLAGS=`$PKG_CONFIG --cflags "$gmenu_modules" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$GMENU_LIBS"; then
+        pkg_cv_GMENU_LIBS="$GMENU_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gmenu_modules\"") >&5
+  ($PKG_CONFIG --exists --print-errors "$gmenu_modules") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_GMENU_LIBS=`$PKG_CONFIG --libs "$gmenu_modules" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               GMENU_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$gmenu_modules"`
+        else
+               GMENU_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$gmenu_modules"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$GMENU_PKG_ERRORS" >&5
+
+       { { echo "$as_me:$LINENO: error: Package requirements ($gmenu_modules) were not met:
+
+$GMENU_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GMENU_CFLAGS
+and GMENU_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+" >&5
+echo "$as_me: error: Package requirements ($gmenu_modules) were not met:
+
+$GMENU_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GMENU_CFLAGS
+and GMENU_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+" >&2;}
+   { (exit 1); exit 1; }; }
+elif test $pkg_failed = untried; then
+       { { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GMENU_CFLAGS
+and GMENU_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details." >&5
+echo "$as_me: error: The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GMENU_CFLAGS
+and GMENU_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+       GMENU_CFLAGS=$pkg_cv_GMENU_CFLAGS
+       GMENU_LIBS=$pkg_cv_GMENU_LIBS
+        { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       :
+fi
+
+
+
 GETTEXT_PACKAGE=lxlauncher
 
 
@@ -5926,7 +6048,7 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-ALL_LINGUAS="zh_TW fi"
+ALL_LINGUAS="zh_TW fi hu"
 # On IRIX 5.3, sys/types and inttypes.h are conflicting.
 
 
@@ -8268,6 +8390,8 @@ GTK_CFLAGS!$GTK_CFLAGS$ac_delim
 GTK_LIBS!$GTK_LIBS$ac_delim
 SN_CFLAGS!$SN_CFLAGS$ac_delim
 SN_LIBS!$SN_LIBS$ac_delim
+GMENU_CFLAGS!$GMENU_CFLAGS$ac_delim
+GMENU_LIBS!$GMENU_LIBS$ac_delim
 GETTEXT_PACKAGE!$GETTEXT_PACKAGE$ac_delim
 USE_NLS!$USE_NLS$ac_delim
 MSGFMT!$MSGFMT$ac_delim
@@ -8277,8 +8401,6 @@ XGETTEXT!$XGETTEXT$ac_delim
 CATALOGS!$CATALOGS$ac_delim
 CATOBJEXT!$CATOBJEXT$ac_delim
 DATADIRNAME!$DATADIRNAME$ac_delim
-GMOFILES!$GMOFILES$ac_delim
-INSTOBJEXT!$INSTOBJEXT$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -8320,6 +8442,8 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+GMOFILES!$GMOFILES$ac_delim
+INSTOBJEXT!$INSTOBJEXT$ac_delim
 INTLLIBS!$INTLLIBS$ac_delim
 PO_IN_DATADIR_TRUE!$PO_IN_DATADIR_TRUE$ac_delim
 PO_IN_DATADIR_FALSE!$PO_IN_DATADIR_FALSE$ac_delim
@@ -8330,7 +8454,7 @@ LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 8; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 10; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
index a872643..d2f9e03 100644 (file)
@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
 
 AC_INIT(configure.in)
-AM_INIT_AUTOMAKE(lxlauncher, 0.1.6)
+AM_INIT_AUTOMAKE(lxlauncher, 0.2)
 AM_CONFIG_HEADER(config.h)
 AM_MAINTAINER_MODE
 
@@ -10,8 +10,8 @@ AC_PROG_CC
 AM_PROG_CC_STDC
 AC_HEADER_STDC
 
-pkg_modules="gtk+-2.0 >= 2.0.0"
-PKG_CHECK_MODULES(GTK, [$pkg_modules])
+gtk_modules="gtk+-2.0 >= 2.10.0"
+PKG_CHECK_MODULES(GTK, [$gtk_modules])
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
 
@@ -20,12 +20,17 @@ PKG_CHECK_MODULES(SN, [$sn_modules])
 AC_SUBST(SN_CFLAGS)
 AC_SUBST(SN_LIBS)
 
+gmenu_modules="libgnome-menu >= 2.18.0"
+PKG_CHECK_MODULES(GMENU, [$gmenu_modules])
+AC_SUBST(GMENU_CFLAGS)
+AC_SUBST(GMENU_LIBS)
+
 GETTEXT_PACKAGE=lxlauncher
 AC_SUBST(GETTEXT_PACKAGE)
 AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package.])
 
 dnl Add the languages which your application supports here.
-ALL_LINGUAS="zh_TW fi"
+ALL_LINGUAS="zh_TW fi hu"
 AM_GLIB_GNU_GETTEXT
 
 AC_OUTPUT([
diff --git a/data/Learn.directory b/data/Learn.directory
new file mode 100644 (file)
index 0000000..cb59297
--- /dev/null
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Learn
+Name[zh_HK]=學習
+Name[zh_TW]=學習
+Icon=applications-science
+Type=Directory
+Encoding=UTF-8
diff --git a/data/Math.directory b/data/Math.directory
new file mode 100644 (file)
index 0000000..c4d70dc
--- /dev/null
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Math
+Name[zh_HK]=數學
+Name[zh_TW]=數學
+Icon=folder
+Type=Directory
+Encoding=UTF-8
diff --git a/data/Play.directory b/data/Play.directory
new file mode 100644 (file)
index 0000000..50906cf
--- /dev/null
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Play
+Name[zh_HK]=娛樂
+Name[zh_TW]=娛樂
+Icon=applications-multimedia
+Type=Directory
+Encoding=UTF-8
diff --git a/data/Science.directory b/data/Science.directory
new file mode 100644 (file)
index 0000000..2c9810b
--- /dev/null
@@ -0,0 +1,44 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Directory
+Icon=applications-science
+Name=Science
+Name[br]=Skiant
+Name[bs]=Nauka
+Name[ca]=Ciència
+Name[cs]=Věda
+Name[cy]=Gwyddoniaeth
+Name[da]=Naturvidenskab
+Name[de]=Wissenschaft
+Name[el]=Επιστήμη
+Name[en_GB]=Science
+Name[eo]=Scienco
+Name[es]=Ciencia
+Name[eu]=Zientzia
+Name[fi]=Tiede
+Name[fr]=Science
+Name[ga]=Eolaíocht
+Name[gl]=Ciencia
+Name[hr]=Znanost
+Name[hu]=Tudományok
+Name[it]=Scienza
+Name[ja]=サイエンス
+Name[kk]=Ғылыми
+Name[lt]=Mokslas
+Name[lv]=Zinātne
+Name[mk]=Наука
+Name[mt]=Xjenza
+Name[nb]=Vitenskap
+Name[nds]=Wetenschap
+Name[pt]=Ciência
+Name[pt_BR]=Ciências
+Name[ro]=Știință
+Name[ru]=Наука
+Name[sr]=Наука и математика
+Name[sr@Latn]=Nauka
+Name[sv]=Vetenskap
+Name[tr]=Bilim
+Name[uk]=Наука
+Name[wa]=Siyinces
+Name[zh_CN]=科学
+Name[zh_TW]=科學
diff --git a/data/Work.directory b/data/Work.directory
new file mode 100644 (file)
index 0000000..c82f14e
--- /dev/null
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Work
+Name[zh_HK]=工作
+Name[zh_TW]=工作
+Icon=applications-office
+Type=Directory
+Encoding=UTF-8
diff --git a/data/launcher.menu b/data/launcher.menu
new file mode 100644 (file)
index 0000000..1d570a2
--- /dev/null
@@ -0,0 +1,168 @@
+<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
+ "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
+<Menu>
+       <Name>Launcher</Name>
+       <Directory>Applications.directory</Directory>
+       <DefaultAppDirs/>
+       <DefaultDirectoryDirs/>
+       <DefaultMergeDirs/>
+       <Layout>
+               <Merge type="menus"/>
+               <Menuname>Internet</Menuname>
+               <Menuname>Work</Menuname>
+               <Menuname>Learn</Menuname>
+               <Menuname>Play</Menuname>
+               <Menuname>Settings</Menuname>
+       </Layout>
+       <Menu>
+               <Name>Internet</Name>
+               <Directory>Internet.directory</Directory>
+               <Include>
+                       <And>
+                               <Category>Network</Category>
+                       </And>
+               </Include>
+               <Menu>
+                       <Name>WebMail</Name>
+                       <Directory>WebMail.directory</Directory>
+                       <Include>
+                               <And>
+                               <Category>X-WebMail</Category>
+                               </And>
+                       </Include>
+               </Menu>
+       </Menu>
+       <Menu>
+               <Name>Work</Name>
+               <Directory>Work.directory</Directory>
+               <Menu>
+                       <Name>Accessories</Name>
+                       <Directory>Accessories.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Utility</Category>
+                                       <Not><Category>Accessibility</Category></Not>
+                                       <Not><Category>System</Category></Not>
+                               </And>
+                       </Include>
+               </Menu>
+               <Menu>
+                       <Name>Graphics</Name>
+                       <Directory>Graphics.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Graphics</Category>
+                                       <Not><Category>Viewer</Category></Not>
+                                       <Not><Category>Utility</Category></Not>
+                               </And>
+                       </Include>
+               </Menu>
+               <Menu>
+                       <Name>Office</Name>
+                       <Directory>Office.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Office</Category>
+                               </And>
+                       </Include>
+               </Menu>
+               <Menu>
+                       <Name>Accessibility</Name>
+                       <Directory>Accessibility.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Accessibility</Category>
+                                       <Not><Category>Settings</Category></Not>
+                               </And>
+                       </Include>
+               </Menu>
+               <Menu>
+                       <Name>Development</Name>
+                       <Directory>Development.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Development</Category>
+                               </And>
+                               <Filename>emacs.desktop</Filename>
+                       </Include>
+               </Menu>
+               <OnlyUnallocated/>
+               <Include>
+                       <And>
+                               <Not><Category>Settings</Category></Not>
+                               <Not><Category>Screensaver</Category></Not>
+                       </And>
+               </Include>
+       </Menu>
+       <Menu>
+               <Name>Learn</Name>
+               <Directory>Learn.directory</Directory>
+               <Include>
+                       <And>
+                               <Category>Education</Category>
+                               <Not><Category>Science</Category></Not>
+                               <Not><Category>Math</Category></Not>
+                               <Not><Category>Languages</Category></Not>
+                       </And>
+               </Include>
+               <Menu>
+                       <Name>Science</Name>
+                       <Directory>Science.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Science</Category>
+                                       <Not><Category>Math</Category></Not>
+                               </And>
+                       </Include>
+               </Menu>
+               <Menu>
+                       <Name>Math</Name>
+                       <Directory>Math.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Math</Category>
+                               </And>
+                       </Include>
+
+               </Menu>
+               <Menu>
+                       <Name>Language</Name>
+                       <Directory>Language.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Languages</Category>
+                               </And>
+                       </Include>
+               </Menu>
+       </Menu>
+       <Menu>
+               <Name>Play</Name>
+               <Directory>Play.directory</Directory>
+               <Menu>
+                       <Name>Games</Name>
+                       <Directory>Games.directory</Directory>
+                       <Include>
+                               <And>
+                                       <Category>Game</Category>
+                                       <Not><Category>Education</Category></Not>
+                               </And>
+                       </Include>
+               </Menu>
+               <Include>
+                       <And>
+                               <Category>AudioVideo</Category>
+                       </And>
+               </Include>
+       </Menu>
+       <Menu>
+               <Name>Settings</Name>
+               <Directory>Settings.directory</Directory>
+               <Include>
+                       <And>
+                               <Category>System</Category>
+                               <Category>Settings</Category>
+                               <Not><Category>Game</Category></Not>
+                       </And>
+               </Include>
+       </Menu>
+</Menu>
diff --git a/gtkrc b/gtkrc
index 92bc20e..2ae1c47 100644 (file)
--- a/gtkrc
+++ b/gtkrc
@@ -16,3 +16,4 @@ widget_class "*<GtkNotebook>" style "launcher-nb"
 widget_class "*<GtkNotebook><GtkHBox><GtkLabel>" style "launcher-nb"
 widget "GtkWindow" style "launcher-bg"
 widget_class "*<ExoWrapTable><GtkButton>*<GtkLabel>" style "launcher-fg"
+widget_class "*<GtkVBox><GtkHBox><GtkLabel>" style "launcher-fg"
index c9ec317..d8cd5f2 100644 (file)
Binary files a/po/fi.gmo and b/po/fi.gmo differ
index 123867c..a8c1fef 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
@@ -5,32 +5,32 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: lxlauncher 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-05-05 14:36+0800\n"
+"POT-Creation-Date: 2008-06-16 00:12+0800\n"
 "PO-Revision-Date: 2008-05-11 12:02+0200\n"
 "Last-Translator: Elias Julkunen <elias.julkunen@gmail.com>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: fi <fi@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/lxlauncher.c:74
-msgid "Internet"
-msgstr "Internet"
+#: src/lxlauncher.c:478
+#, c-format
+msgid "Go back to \"%s\""
+msgstr ""
+
+#~ msgid "Internet"
+#~ msgstr "Internet"
 
-#: src/lxlauncher.c:75
-msgid "Work"
-msgstr "Työskentele"
+#~ msgid "Work"
+#~ msgstr "Työskentele"
 
-#: src/lxlauncher.c:76
-msgid "Learn"
-msgstr "Opi"
+#~ msgid "Learn"
+#~ msgstr "Opi"
 
-#: src/lxlauncher.c:77
-msgid "Play"
-msgstr "Pelaa"
+#~ msgid "Play"
+#~ msgstr "Pelaa"
 
-#: src/lxlauncher.c:78
-msgid "Settings"
-msgstr "Asetukset"
+#~ msgid "Settings"
+#~ msgstr "Asetukset"
diff --git a/po/hu.gmo b/po/hu.gmo
new file mode 100644 (file)
index 0000000..b8e2fca
Binary files /dev/null and b/po/hu.gmo differ
diff --git a/po/hu.po b/po/hu.po
new file mode 100644 (file)
index 0000000..1ad782f
--- /dev/null
+++ b/po/hu.po
@@ -0,0 +1,34 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: lxlauncher\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-06-16 00:12+0800\n"
+"PO-Revision-Date: 2008-05-11 19:15+0100\n"
+"Last-Translator: SZERVÁC Attila <sas@321.hu>\n"
+"Language-Team: Hungarian <debian-l10n-hungarian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
+"X-Poedit-Language: Hungarian\n"
+"X-Poedit-Country: HUNGARY\n"
+
+#: src/lxlauncher.c:478
+#, c-format
+msgid "Go back to \"%s\""
+msgstr ""
+
+#~ msgid "Internet"
+#~ msgstr "Internet"
+
+#~ msgid "Work"
+#~ msgstr "Munka"
+
+#~ msgid "Learn"
+#~ msgstr "Tanulás"
+
+#~ msgid "Play"
+#~ msgstr "Játék"
+
+#~ msgid "Settings"
+#~ msgstr "Beállítások"
index e1b5bba..8eda2e6 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-05-05 14:36+0800\n"
+"POT-Creation-Date: 2008-06-16 00:12+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,22 +16,7 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/lxlauncher.c:74
-msgid "Internet"
-msgstr ""
-
-#: src/lxlauncher.c:75
-msgid "Work"
-msgstr ""
-
-#: src/lxlauncher.c:76
-msgid "Learn"
-msgstr ""
-
-#: src/lxlauncher.c:77
-msgid "Play"
-msgstr ""
-
-#: src/lxlauncher.c:78
-msgid "Settings"
+#: src/lxlauncher.c:478
+#, c-format
+msgid "Go back to \"%s\""
 msgstr ""
index e8b88c3..6222d56 100644 (file)
Binary files a/po/zh_TW.gmo and b/po/zh_TW.gmo differ
index 05aa138..7baf86a 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-05-05 14:36+0800\n"
+"POT-Creation-Date: 2008-06-16 00:12+0800\n"
 "PO-Revision-Date: 2008-05-05 14:32+0800\n"
 "Last-Translator: Hong Jen Yee <pcman.tw@gmail.com>\n"
 "Language-Team: zh_TW <LL@li.org>\n"
@@ -15,22 +15,22 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/lxlauncher.c:74
-msgid "Internet"
-msgstr "網際網路"
+#: src/lxlauncher.c:478
+#, c-format
+msgid "Go back to \"%s\""
+msgstr ""
+
+#~ msgid "Internet"
+#~ msgstr "網際網路"
 
-#: src/lxlauncher.c:75
-msgid "Work"
-msgstr "工作"
+#~ msgid "Work"
+#~ msgstr "工作"
 
-#: src/lxlauncher.c:76
-msgid "Learn"
-msgstr "學習"
+#~ msgid "Learn"
+#~ msgstr "學習"
 
-#: src/lxlauncher.c:77
-msgid "Play"
-msgstr "娛樂"
+#~ msgid "Play"
+#~ msgstr "娛樂"
 
-#: src/lxlauncher.c:78
-msgid "Settings"
-msgstr "設定"
+#~ msgid "Settings"
+#~ msgstr "設定"
index 652e4ec..3dcc300 100644 (file)
@@ -3,20 +3,18 @@
 INCLUDES = \
        -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
        -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-       @GTK_CFLAGS@ @SN_CFLAGS@
+       @GTK_CFLAGS@ @SN_CFLAGS@ @GMENU_CFLAGS@
 
 bin_PROGRAMS = lxlauncher
 
 lxlauncher_SOURCES = \
        lxlauncher.c \
+       misc.c misc.h \
        glib-mem.h \
-       vfs-app-desktop.c vfs-app-desktop.h \
        vfs-utils.c vfs-utils.h \
        vfs-execute.c vfs-execute.h \
        working-area.c working-area.h \
-       exo-wrap-table.c exo-wrap-table.h \
-       inotify/inotify-syscalls.h \
-       inotify/linux-inotify.h
+       exo-wrap-table.c exo-wrap-table.h
 
-lxlauncher_LDADD = @GTK_LIBS@ @SN_LIBS@ $(INTLLIBS)
+lxlauncher_LDADD = @GTK_LIBS@ @SN_LIBS@ @GMENU_LIBS@ $(INTLLIBS)
 
index b55c5f9..811eb5f 100644 (file)
@@ -43,7 +43,7 @@ CONFIG_CLEAN_FILES =
 am__installdirs = "$(DESTDIR)$(bindir)"
 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
-am_lxlauncher_OBJECTS = lxlauncher.$(OBJEXT) vfs-app-desktop.$(OBJEXT) \
+am_lxlauncher_OBJECTS = lxlauncher.$(OBJEXT) misc.$(OBJEXT) \
        vfs-utils.$(OBJEXT) vfs-execute.$(OBJEXT) \
        working-area.$(OBJEXT) exo-wrap-table.$(OBJEXT)
 lxlauncher_OBJECTS = $(am_lxlauncher_OBJECTS)
@@ -84,6 +84,8 @@ ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GMENU_CFLAGS = @GMENU_CFLAGS@
+GMENU_LIBS = @GMENU_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
 GREP = @GREP@
@@ -171,20 +173,18 @@ top_srcdir = @top_srcdir@
 INCLUDES = \
        -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
        -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-       @GTK_CFLAGS@ @SN_CFLAGS@
+       @GTK_CFLAGS@ @SN_CFLAGS@ @GMENU_CFLAGS@
 
 lxlauncher_SOURCES = \
        lxlauncher.c \
+       misc.c misc.h \
        glib-mem.h \
-       vfs-app-desktop.c vfs-app-desktop.h \
        vfs-utils.c vfs-utils.h \
        vfs-execute.c vfs-execute.h \
        working-area.c working-area.h \
-       exo-wrap-table.c exo-wrap-table.h \
-       inotify/inotify-syscalls.h \
-       inotify/linux-inotify.h
+       exo-wrap-table.c exo-wrap-table.h
 
-lxlauncher_LDADD = @GTK_LIBS@ @SN_LIBS@ $(INTLLIBS)
+lxlauncher_LDADD = @GTK_LIBS@ @SN_LIBS@ @GMENU_LIBS@ $(INTLLIBS)
 all: all-am
 
 .SUFFIXES:
@@ -253,7 +253,7 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exo-wrap-table.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxlauncher.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfs-app-desktop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfs-execute.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfs-utils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/working-area.Po@am__quote@
diff --git a/src/inotify/inotify-syscalls.h b/src/inotify/inotify-syscalls.h
deleted file mode 100644 (file)
index 1431d46..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef _LINUX_INOTIFY_SYSCALLS_H
-#define _LINUX_INOTIFY_SYSCALLS_H
-
-#include <sys/syscall.h>
-
-#if defined(__i386__)
-# define __NR_inotify_init     291
-# define __NR_inotify_add_watch        292
-# define __NR_inotify_rm_watch 293
-#elif defined(__x86_64__)
-# define __NR_inotify_init     253
-# define __NR_inotify_add_watch        254
-# define __NR_inotify_rm_watch 255
-#elif defined(__powerpc__) || defined(__powerpc64__)
-# define __NR_inotify_init     275
-# define __NR_inotify_add_watch        276
-# define __NR_inotify_rm_watch 277
-#elif defined (__ia64__)
-# define __NR_inotify_init     1277
-# define __NR_inotify_add_watch        1278
-# define __NR_inotify_rm_watch 1279
-#elif defined (__s390__)
-# define __NR_inotify_init     284
-# define __NR_inotify_add_watch        285
-# define __NR_inotify_rm_watch 286
-#elif defined (__alpha__)
-# define __NR_inotify_init     444
-# define __NR_inotify_add_watch        445
-# define __NR_inotify_rm_watch 446
-#elif defined (__sparc__) || defined (__sparc64__)
-# define __NR_inotify_init     151
-# define __NR_inotify_add_watch        152
-# define __NR_inotify_rm_watch 156
-#elif defined (__arm__)
-# define __NR_inotify_init     316
-# define __NR_inotify_add_watch        317
-# define __NR_inotify_rm_watch 318
-#elif defined (__sh__)
-# define __NR_inotify_init     290
-# define __NR_inotify_add_watch        291
-# define __NR_inotify_rm_watch 292
-#else
-# error "Unsupported architecture!"
-#endif
-
-static inline int inotify_init (void)
-{
-       return syscall (__NR_inotify_init);
-}
-
-static inline int inotify_add_watch (int fd, const char *name, __u32 mask)
-{
-       return syscall (__NR_inotify_add_watch, fd, name, mask);
-}
-
-static inline int inotify_rm_watch (int fd, __u32 wd)
-{
-       return syscall (__NR_inotify_rm_watch, fd, wd);
-}
-
-#endif /* _LINUX_INOTIFY_SYSCALLS_H */
diff --git a/src/inotify/linux-inotify.h b/src/inotify/linux-inotify.h
deleted file mode 100644 (file)
index 93bb3af..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Inode based directory notification for Linux
- *
- * Copyright (C) 2005 John McCutchan
- */
-
-#ifndef _LINUX_INOTIFY_H
-#define _LINUX_INOTIFY_H
-
-#include <linux/types.h>
-
-/*
- * struct inotify_event - structure read from the inotify device for each event
- *
- * When you are watching a directory, you will receive the filename for events
- * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
- */
-struct inotify_event {
-       __s32           wd;             /* watch descriptor */
-       __u32           mask;           /* watch mask */
-       __u32           cookie;         /* cookie to synchronize two events */
-       __u32           len;            /* length (including nulls) of name */
-       char            name[0];        /* stub for possible name */
-};
-
-/* the following are legal, implemented events that user-space can watch for */
-#define IN_ACCESS              0x00000001      /* File was accessed */
-#define IN_MODIFY              0x00000002      /* File was modified */
-#define IN_ATTRIB              0x00000004      /* Metadata changed */
-#define IN_CLOSE_WRITE         0x00000008      /* Writtable file was closed */
-#define IN_CLOSE_NOWRITE       0x00000010      /* Unwrittable file closed */
-#define IN_OPEN                        0x00000020      /* File was opened */
-#define IN_MOVED_FROM          0x00000040      /* File was moved from X */
-#define IN_MOVED_TO            0x00000080      /* File was moved to Y */
-#define IN_CREATE              0x00000100      /* Subfile was created */
-#define IN_DELETE              0x00000200      /* Subfile was deleted */
-#define IN_DELETE_SELF         0x00000400      /* Self was deleted */
-#define IN_MOVE_SELF           0x00000800      /* Self was moved */
-
-/* the following are legal events.  they are sent as needed to any watch */
-#define IN_UNMOUNT             0x00002000      /* Backing fs was unmounted */
-#define IN_Q_OVERFLOW          0x00004000      /* Event queued overflowed */
-#define IN_IGNORED             0x00008000      /* File was ignored */
-
-/* helper events */
-#define IN_CLOSE               (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
-#define IN_MOVE                        (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
-
-/* special flags */
-#define IN_ISDIR               0x40000000      /* event occurred against dir */
-#define IN_ONESHOT             0x80000000      /* only send event once */
-
-/*
- * All of the events - we build the list by hand so that we can add flags in
- * the future and not break backward compatibility.  Apps will get only the
- * events that they originally wanted.  Be sure to add new events here!
- */
-#define IN_ALL_EVENTS  (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
-                        IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
-                        IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
-                        IN_MOVE_SELF)
-
-#ifdef __KERNEL__
-
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/config.h>
-
-#ifdef CONFIG_INOTIFY
-
-extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
-                                     const char *);
-extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
-                                             const char *);
-extern void inotify_unmount_inodes(struct list_head *);
-extern void inotify_inode_is_dead(struct inode *);
-extern u32 inotify_get_cookie(void);
-
-#else
-
-static inline void inotify_inode_queue_event(struct inode *inode,
-                                            __u32 mask, __u32 cookie,
-                                            const char *filename)
-{
-}
-
-static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
-                                                    __u32 mask, __u32 cookie,
-                                                    const char *filename)
-{
-}
-
-static inline void inotify_unmount_inodes(struct list_head *list)
-{
-}
-
-static inline void inotify_inode_is_dead(struct inode *inode)
-{
-}
-
-static inline u32 inotify_get_cookie(void)
-{
-       return 0;
-}
-
-#endif /* CONFIG_INOTIFY */
-
-#endif /* __KERNEL __ */
-
-#endif /* _LINUX_INOTIFY_H */
index 8190f2a..d7c9fba 100644 (file)
@@ -1,18 +1,18 @@
 /*
  *      lxlauncher.c - Open source replace for EeePC Asus Launcher
- *      
+ *
  *      Copyright 2008 PCMan <pcman.tw@gmail.com>
- *      
+ *
  *      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., 51 Franklin Street, Fifth Floor, Boston,
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 
-#include <errno.h>
+#define GMENU_I_KNOW_THIS_IS_UNSTABLE
+#include <gmenu-tree.h>
 
-#include "vfs-app-desktop.h"
+#include <errno.h>
 
-#include "inotify/linux-inotify.h"
-#include "inotify/inotify-syscalls.h"
+#include <cairo.h>
 
 #include "exo-wrap-table.h"
 #include "working-area.h"
@@ -45,6 +45,7 @@
 #define BUTTON_SIZE    120
 #define IMG_SIZE       48
 
+#define DATA_DIR  PACKAGE_DATA_DIR"/lxlauncher"
 #define BACKGROUND_DIR  PACKAGE_DATA_DIR"/lxlauncher/background"
 #define ICON_DIR        PACKAGE_DATA_DIR"/lxlauncher/icons"
 
@@ -56,167 +57,51 @@ static GtkIconSize icon_size;
 
 static Atom atom_NET_WORKAREA = NULL;
 
-static int inotify_fd = -1;
-static GIOChannel* inotify_io_channel = NULL;
-static int* watches = NULL;
-static guint inotify_io_watch = 0;
-static int reload_handler = 0;
+static GMenuTree* menu_tree = NULL;
+static GMenuTreeDirectory* root_dir = NULL;
 
-typedef struct {
-       char* title;
-       char* background;
-       char* icon;
-       char* themed_icon;
-       GtkWidget* page;
-       char** categories;
-}Group;
-
-static char* net_cats[] = { "Network", NULL };
-static char* work_cats[] = { "Office", "Utility", "Graphics", "TextEditor", "TextTools", "Viewer", "Core", "Development", NULL };
-static char* learn_cats[] = { "Education", "Dictionary", NULL };
-static char* play_cats[] = { "AudioVideo", "Game", NULL };
-static char* settings_cats[] = { "Settings", "System", NULL };
-
-static Group groups[]={
-       {
-           N_("Internet"),
-        "accessibility_internet_wallpaper.jpg",
-        "Internet.png", "applications-internet",
-        NULL, net_cats, 0
-    },
-       {
-           N_("Learn"),
-        "accessibility_learn_wallpaper.jpg",
-        "learn_sel.png", "applications-accessories",
-        NULL, learn_cats, 0
-    },
-       {
-           N_("Work"),
-       "accessibility_work_wallpaper.jpg",
-       "work_sel.png", "applications-office",
-       NULL, work_cats, 0
-    },
-       {
-           N_("Play"),
-        "accessibility_play_wallpaper.jpg",
-        "play_sel.png", "applications-multimedia",
-         NULL, play_cats, 0
-    },
-       {
-           N_("Settings"),
-        "accessibility_settings_wallpaper.jpg",
-        "system_sel.png", "gtk-preferences",
-        NULL, settings_cats, 0
-    },
-};
-
-static void finalize_inotify();
+static int reload_handler = 0;
 
-static void load_app_desktops( GHashTable* hash, const char* dir_path, const char* parent )
-{
-       GDir* dir = g_dir_open( dir_path, 0, NULL );
-       if( dir )
-       {
-               char* name;
-               while( name = g_dir_read_name(dir) )
-               {
-                       char* desktop_id = NULL, *file;
-                       if( parent )
-                               desktop_id = g_strconcat( parent, "-", name, NULL );
-                       else
-                               desktop_id = g_strdup( name );
-
-                       file = g_build_filename( dir_path, name, NULL );
-
-                       if( g_file_test( file, G_FILE_TEST_IS_DIR ) ) // sub dir
-                       {
-                               load_app_desktops( hash, file, desktop_id );
-                       }
-                       else // desktop entry file
-                       {
-                               VFSAppDesktop* app_desktop;
-                               if( ! g_str_has_suffix( name, ".desktop" ) )
-                                       continue;
-                               app_desktop = vfs_app_desktop_new( file );
-                               if( ! vfs_app_desktop_is_hidden( app_desktop ) )
-                               {
-                                       g_hash_table_replace( hash, g_strdup( desktop_id ),
-                                                                                                app_desktop );
-                               }
-                               else
-                               {
-                                       g_hash_table_remove( hash, desktop_id );
-                                       vfs_app_desktop_unref( app_desktop );
-                               }
-                       }
-
-                       g_free( desktop_id );
-                               g_free( file );
-                       
-               }
-               g_dir_close( dir );
-       }
-}
+typedef struct _PageData{
+    GMenuTreeDirectory* dir;
+       GtkWidget* page_vbox;
+       GtkBox* go_up_bar;
+       GtkWidget* table;
+       GdkPixbuf* background;
+}PageData;
 
-static void on_btn_clicked( GtkButton* btn, VFSAppDesktop* app )
+static void on_app_btn_clicked( GtkButton* btn, GMenuTreeEntry* app )
 {
-       vfs_app_desktop_open_files( gdk_screen_get_default(),
-                                                                               NULL, app, NULL, NULL );
+       lxlauncher_execute_app( gdk_screen_get_default(),
+                                                                               NULL, gmenu_tree_entry_get_exec(app), 
+                                                                               gmenu_tree_entry_get_name(app), NULL, 
+                                                                               gmenu_tree_entry_get_launch_in_terminal(app),
+                                                                               NULL );
 }
 
-static gboolean is_app_in_group( VFSAppDesktop* app, Group* grp )
-{
-       char **grp_cat, **app_cat;
-       for( grp_cat=grp->categories; *grp_cat; ++grp_cat )
-       {
-               for( app_cat=app->categories; *app_cat; ++app_cat )
-               {
-                       if( 0 == strcmp( *app_cat, *grp_cat ) )
-                               return TRUE;
-               }
-       }
-       return FALSE;
-}
+static void notebook_page_chdir( PageData* data, GMenuTreeDirectory* dir );
 
-static void categorize_app( gpointer key, gpointer val, gpointer data )
+static void on_dir_btn_clicked( GtkButton* btn, PageData* data )
 {
-    GList** app_lists = (GList**)data;
-       int i;
-       VFSAppDesktop* app = val;
-       if( app->categories )
-       {
-               for( i = 0; i < G_N_ELEMENTS(groups); ++i )
-               {
-                       if( is_app_in_group( app, &groups[i] ) )
-                       {
-                           app_lists[i] = g_list_prepend(app_lists[i], app);
-                           // g_debug( "add %s to %s", app->disp_name, groups[i].title );
-                               return;
-                       }
-               }
-       }
+    GMenuTreeDirectory* dir = (GMenuTreeDirectory*)g_object_get_data( btn, "dir" );
+    notebook_page_chdir( data, dir );
 }
 
-static void add_app_btn( Group* group, VFSAppDesktop* app )
+static GtkWidget* add_btn( GtkWidget* table, const char* text, GdkPixbuf* icon, const char* tip )
 {
-    GtkButton *btn, *box, *img, *label;
-    GtkTable* table = (GtkTable*)group->page;
+    GtkWidget *btn, *box, *img, *label;
 
     // add the app to that page
     btn = gtk_button_new();
     GTK_WIDGET_UNSET_FLAGS(btn, GTK_CAN_FOCUS );
     GTK_WIDGET_UNSET_FLAGS(btn, GTK_CAN_DEFAULT );
-//  if( g_path_is_absolute( vfs_app_desktop_get_icon_name(app) ) )
-//  {
-        GdkPixbuf* pix = vfs_app_desktop_get_icon( app, IMG_SIZE, TRUE );
-        img = gtk_image_new_from_pixbuf( pix );
-//  }
-//  else
-//      img = gtk_image_new_from_icon_name( vfs_app_desktop_get_icon_name(app), icon_size );
+
+    img = gtk_image_new_from_pixbuf( icon );
+
     box = gtk_vbox_new( FALSE, 2 );
     gtk_box_pack_start( box, img, FALSE, TRUE, 2 );
 
-    label = gtk_label_new( vfs_app_desktop_get_disp_name(app) );
+    label = gtk_label_new( text );
     gtk_widget_show( label );
     gtk_widget_set_size_request( label, BUTTON_SIZE - 10, -1 );
     gtk_label_set_line_wrap_mode( label, PANGO_WRAP_WORD_CHAR );
@@ -229,90 +114,102 @@ static void add_app_btn( Group* group, VFSAppDesktop* app )
     gtk_widget_set_size_request( btn, BUTTON_SIZE, BUTTON_SIZE );
     gtk_widget_show_all( btn );
 
-    gtk_tooltips_set_tip( tooltips, btn, vfs_app_desktop_get_desc(app), NULL );
-
-    vfs_app_desktop_ref( app );
-    g_signal_connect( btn, "clicked", G_CALLBACK(on_btn_clicked), app );
+    if( tip )
+        gtk_tooltips_set_tip( tooltips, btn, tip, NULL );
 
     gtk_container_add( table, btn );
 
     gtk_widget_realize( btn );
     gtk_widget_set_app_paintable( btn, TRUE );
     gdk_window_set_back_pixmap( ((GtkWidget*)btn)->window, NULL, TRUE );
+    return btn;
 }
 
-// compare func used to sort apps in lists
-static int sort_apps(VFSAppDesktop* app1, VFSAppDesktop* app2, Group* group)
-{
-    return g_utf8_collate( app1->disp_name, app2->disp_name );
-}
-
-static void load_apps()
+#if 0
+GdkPixbuf* load_icon( const char* icon_name, int size, gboolean use_fallback )
 {
-       char** dirs = (char**)g_get_system_data_dirs(), **dir;
-       GHashTable* hash = g_hash_table_new_full( g_str_hash, g_str_equal, g_free,
-                                                                                                                 vfs_app_desktop_unref );
-    gboolean init_watch = FALSE;
-    GList* app_lists[ G_N_ELEMENTS(groups) ] = {0};
-    int i;
-    static int n = 0;
+    GtkIconTheme* theme;
+    char *_icon_name = NULL, *suffix;
+    GdkPixbuf* icon = NULL;
 
-    if( ! watches )
+    if( app->icon_name )
     {
-        n = g_strv_length(dirs) + 1;
-        watches = g_new0( int, n );
-        init_watch = TRUE;
-    }
-
-    // load system-wide apps
-    for( dir = dirs; *dir; ++dir )
-       {
-               char* dir_path = g_build_filename( *dir, "applications",NULL );
-
-        if( init_watch )
+        if( g_path_is_absolute( app->icon_name) )
         {
-            // monitor the dir for changes
-            watches[(dir-dirs)] = inotify_add_watch ( inotify_fd, dir_path,
-                                        IN_MODIFY|IN_CREATE|IN_DELETE );
+            icon = gdk_pixbuf_new_from_file_at_scale( app->icon_name,
+                                                     size, size, TRUE, NULL );
         }
-
-               load_app_desktops( hash, dir_path, NULL );
-               g_free( dir_path );
-       }
-       // load user-specific apps
-       {
-               char* dir_path = g_build_filename( g_get_user_data_dir(), "applications",NULL );
-        if( init_watch )
+        else
         {
-            // monitor the dir for changes
-            watches[n - 2] = inotify_add_watch ( inotify_fd, dir_path,
-                                        IN_MODIFY|IN_CREATE|IN_DELETE );
+            theme = gtk_icon_theme_get_default();
+            suffix = strchr( app->icon_name, '.' );
+            if( suffix ) /* has file extension, it's a basename of icon file */
+            {
+                /* try to find it in pixmaps dirs */
+                icon = load_icon_file( app->icon_name, size );
+                if( G_UNLIKELY( ! icon ) )  /* unfortunately, not found */
+                {
+                    /* Let's remove the suffix, and see if this name can match an icon
+                         in current icon theme */
+                    _icon_name = g_strndup( app->icon_name,
+                                           (suffix - app->icon_name) );
+                    icon = vfs_load_icon( theme, _icon_name, size );
+                    g_free( _icon_name );
+                }
+            }
+            else  /* no file extension, it could be an icon name in the icon theme */
+            {
+                icon = vfs_load_icon( theme, app->icon_name, size );
+            }
         }
-               load_app_desktops( hash, dir_path, NULL );
-               g_free( dir_path );
     }
-       watches[n-1] = -1;
-
-       g_hash_table_foreach( hash, categorize_app, app_lists );
-
-    // add the categorized apps to every pages
-    for( i = 0; i < G_N_ELEMENTS(groups); ++i )
+    if( G_UNLIKELY( ! icon ) && use_fallback )  /* fallback to generic icon */
     {
-        GList* l;
-        // sort the apps
-        app_lists[i] = g_list_sort_with_data( app_lists[i], (GCompareDataFunc)sort_apps, &groups[i] );
-
-        // add the apps to every pages
-        for( l = app_lists[i]; l; l = l->next )
+        theme = gtk_icon_theme_get_default();
+        icon = vfs_load_icon( theme, "application-x-executable", size );
+        if( G_UNLIKELY( ! icon ) )  /* fallback to generic icon */
         {
-            VFSAppDesktop* app = (VFSAppDesktop*)l->data;
-            add_app_btn( &groups[i], app );
+            icon = vfs_load_icon( theme, "gnome-mime-application-x-executable", size );
         }
-        
-        g_list_free( app_lists[i] );
     }
+    return icon;
+}
+#endif
+
+static void add_dir_btn( PageData* data, GMenuTreeDirectory* dir )
+{
+    GdkPixbuf* icon;
+    GtkWidget* btn;
+    const char* icon_name = gmenu_tree_directory_get_icon( dir );
+    if( !icon_name )
+        icon_name = "folder";
+
+    icon = lxlauncher_load_icon( icon_name, IMG_SIZE, TRUE );
+
+    btn = add_btn( data->table, gmenu_tree_directory_get_name(dir), icon, gmenu_tree_directory_get_comment(dir) );
+    if( icon )
+        g_object_unref( icon );
+
+    g_object_set_data( btn, "dir", dir );
+    g_signal_connect( btn, "clicked", G_CALLBACK(on_dir_btn_clicked), data );
+}
+
+static void add_app_btn( GtkWidget* table, GMenuTreeEntry* app )
+{
+    GdkPixbuf* icon;
+    GtkWidget* btn;
+    const char* icon_name = gmenu_tree_entry_get_icon( app );
+
+    if( !icon_name )
+        icon_name = "application-x-executable";
+
+    icon = lxlauncher_load_icon( icon_name, IMG_SIZE, TRUE );
 
-       g_hash_table_destroy( hash );
+    btn = add_btn( table, gmenu_tree_entry_get_name(app), icon, gmenu_tree_entry_get_comment(app) );
+
+    if( icon )
+        g_object_unref( icon );
+    g_signal_connect( btn, "clicked", G_CALLBACK(on_app_btn_clicked), app );
 }
 
 static gboolean on_viewport_expose( GtkWidget* w, GdkEventExpose* evt, gpointer data )
@@ -323,6 +220,25 @@ static gboolean on_viewport_expose( GtkWidget* w, GdkEventExpose* evt, gpointer
 
     if( GTK_WIDGET_DRAWABLE(w) && evt->window == ((GtkViewport*)w)->bin_window )
     {
+        cairo_t *cr;
+        cairo_pattern_t* pat;
+
+        GtkWidget* scroll = gtk_widget_get_parent(w);
+        GtkAdjustment* vadj = gtk_scrolled_window_get_vadjustment(scroll);
+
+        cr = gdk_cairo_create (evt->window);
+        pat = cairo_pattern_create_linear( 0, gtk_adjustment_get_value(vadj), 0, w->allocation.height + gtk_adjustment_get_value(vadj) );
+        cairo_pattern_add_color_stop_rgb( pat, 0, 1, 1, 1);
+        cairo_pattern_add_color_stop_rgb( pat, 1.0, ((gdouble)184/256), ((gdouble)215/256), ((gdouble)235/256));
+//        cairo_rectangle(cr, 0, 0, w->allocation.width, w->allocation.height );
+//        cairo_rectangle(cr, evt->area.x, evt->area.y, evt->area.width, evt->area.height );
+        cairo_rectangle(cr, evt->area.x, evt->area.y, evt->area.width, evt->area.height );
+        cairo_set_source(cr, pat);
+        cairo_fill(cr);
+        cairo_pattern_destroy(pat);
+        cairo_destroy(cr);
+
+/*
         GdkGC* gc = gdk_gc_new(evt->window);
 
         gdk_gc_set_tile( gc, pixmap );
@@ -332,6 +248,7 @@ static gboolean on_viewport_expose( GtkWidget* w, GdkEventExpose* evt, gpointer
         gdk_draw_rectangle( evt->window, gc, TRUE, evt->area.x, evt->area.y, evt->area.width, evt->area.height );
 
         gdk_gc_unref( gc );
+*/
     }
 
     // call handler of tha parent GtkContainer class to propagate the event to children
@@ -339,107 +256,148 @@ static gboolean on_viewport_expose( GtkWidget* w, GdkEventExpose* evt, gpointer
     return TRUE;
 }
 
-static gboolean reload_apps()
+static gboolean on_scroll( GtkAdjustment* adj, PageData* data )
+{
+    // Dirty hacks used to force pseudo-transparent background
+    gtk_widget_queue_draw( data->table );
+}
+
+// Dirty hacks used to reduce unnecessary redrew during scroll
+static gboolean on_scroll_change_val( GtkRange* scroll, GtkScrollType type, gdouble value, PageData* data )
 {
-    int i;;
-    for( i = 0; i < G_N_ELEMENTS(groups); ++i )
+    GtkAdjustment* adj = gtk_range_get_adjustment(scroll);
+
+    if( type == GTK_SCROLL_JUMP )
     {
-        // destroy all existing buttons
-        gtk_container_foreach( groups[i].page, G_CALLBACK(gtk_widget_destroy), NULL );
-        // groups[i].n_btns = 0;
-        // gtk_table_resize( groups[i].page, 1, 1 );
-        // g_debug("remove all children");
+        if( ABS( adj->value - value ) < BUTTON_SIZE / 2 )
+        {
+            if( adj->value > value )    // upward
+            {
+                if( (adj->value - adj->lower) < BUTTON_SIZE / 2 )
+                {
+                    gtk_adjustment_set_value( adj, adj->lower );
+                }
+            }
+            else // downward
+            {
+                if( (adj->upper - adj->value) < BUTTON_SIZE / 2 )
+                {
+                    gtk_adjustment_set_value( adj, adj->lower );
+                }
+            }
+            return TRUE;
+        }
     }
-    // load all apps again
-    load_apps();
-    reload_handler = 0;
     return FALSE;
 }
 
-/* event handler of all inotify events */
-static gboolean on_inotify_event( GIOChannel * channel,
-                                  GIOCondition cond,
-                                  gpointer user_data )
+static char* menu_dir_to_path( GMenuTreeDirectory* dir )
 {
-    #define BUF_LEN (1024 * (sizeof (struct inotify_event) + 16))
-    char buf[ BUF_LEN ];
-    int i, len;
-
-    if ( cond & (G_IO_HUP | G_IO_ERR) )
+    if( gmenu_tree_item_get_parent(dir) == root_dir )
+        return g_strdup( gmenu_tree_directory_get_name(dir) );
+    else
     {
-        finalize_inotify();
-        return TRUE; /* don't need to remove the event source since
-                        it has been removed by finalize_inotify(). */
+        char* parent = menu_dir_to_path( gmenu_tree_item_get_parent(dir) );
+        char* ret;
+        ret = g_strconcat( parent, " > ", gmenu_tree_directory_get_name(dir), NULL );
+        g_free( parent );
+        return ret;
     }
+    return NULL;
+}
 
-    // keep reading if error happens
-    while( ( len = read ( inotify_fd, buf, BUF_LEN ) ) < 0
-            && errno == EINTR );
-
-    if ( len < 0 )
-        return FALSE;   // error
+static void create_notebook_pages();
 
-    if ( len == 0 )
-        return FALSE;   // error
+static PageData* notebook_page_from_dir( GMenuTreeDirectory* dir )
+{
+    int i, n;
+    GtkWidget* page;
+    GMenuTreeDirectory* top = dir;
+    PageData* page_data;
 
-    // some changes happened in applications dirs
-    // reload is needed
+    // get toplevel parent dir
+    while( gmenu_tree_item_get_parent(top) != root_dir )
+        top = gmenu_tree_item_get_parent(top);
 
-    if( reload_handler )
-        g_source_remove( reload_handler );
+    n = gtk_notebook_get_n_pages( notebook );
+    for( i = 0; i < n; ++i )
+    {
 
-    reload_handler = g_timeout_add( 1000,(GSourceFunc)reload_apps, NULL );
+        GMenuTreeDirectory* top2;
+        page = gtk_notebook_get_nth_page( notebook, i );
+        page_data = (PageData*)g_object_get_data(page, "page");
+        top2 = page_data->dir;
+        while( gmenu_tree_item_get_parent(top2) != root_dir )
+            top2 = gmenu_tree_item_get_parent(top2);
 
-#if 0
-    i = 0;
-    while ( i < len )
-    {
-        struct inotify_event * ievent = ( struct inotify_event * ) & buf [ i ];
-        if( ievent->len > 0 )
-        {
-            // g_debug( "file: %s was modified", ievent->name );
-        }
-        i += sizeof ( struct inotify_event ) + ievent->len;
+        if( top == top2 )
+            return page_data;
     }
-#endif
-    return TRUE;
+    return NULL;
 }
 
-static gboolean init_inotify()
+static gboolean reload_apps()
 {
-    inotify_fd = inotify_init();
-    if ( inotify_fd < 0 )
+    int i;
+    PageData* page_data;
+    GtkWidget* page;
+
+    int n = gtk_notebook_get_n_pages( notebook );
+    char** page_paths = g_new0(char*, n + 1);
+    int cur_page = gtk_notebook_get_current_page(notebook);
+
+    for( i = 0; i < n; ++i )
     {
-        g_warning( "failed to initialize inotify." );
-        return FALSE;
+        page = gtk_notebook_get_nth_page( notebook, 0 );
+        page_data = (PageData*)g_object_get_data( page, "page" );
+        page_paths[i] = gmenu_tree_directory_make_path( page_data->dir, NULL);
+        gtk_notebook_remove_page( notebook, 0 );
     }
-    inotify_io_channel = g_io_channel_unix_new( inotify_fd );
-    g_io_channel_set_encoding( inotify_io_channel, NULL, NULL );
-    g_io_channel_set_buffered( inotify_io_channel, FALSE );
-    g_io_channel_set_flags( inotify_io_channel, G_IO_FLAG_NONBLOCK, NULL );
-
-    inotify_io_watch = g_io_add_watch( inotify_io_channel,
-                                   G_IO_IN | G_IO_PRI | G_IO_HUP|G_IO_ERR,
-                                   on_inotify_event,
-                                   NULL );
-    return TRUE;
+
+    // rebuild every pages
+    create_notebook_pages();
+    root_dir = gmenu_tree_get_root_directory( menu_tree );
+
+    for( i = 0; i < n; ++i )
+    {
+        GMenuTreeDirectory* dir = gmenu_tree_get_directory_from_path( menu_tree, page_paths[i] );
+        if( dir )
+        {
+            GMenuTreeDirectory* top = dir;
+            // get toplevel parent dir
+
+            while( gmenu_tree_item_get_parent(top) != root_dir )
+                top = gmenu_tree_item_get_parent(top);
+
+            // find notebook page containing the top dir
+            page_data = notebook_page_from_dir( top );
+
+            if( ! page_data )
+                continue;
+
+            if( page_data->dir != dir )
+                notebook_page_chdir( page_data, dir );
+
+            if( i == cur_page )
+                gtk_notebook_set_current_page( notebook, cur_page );
+        }
+    }
+    g_strfreev( page_paths );
+    return FALSE;
 }
 
-static void finalize_inotify()
+void on_menu_tree_changed( GMenuTree *tree, gpointer  user_data )
 {
-    int *watch;
-
-    for( watch = watches; *watch != -1; ++watch )
-        inotify_rm_watch ( inotify_fd, *watch );
-    g_free( watches );
-    watches = NULL;
+    // some changes happened in applications dirs
+    // reload is needed
+    // g_debug( "file changed" );
 
-    g_io_channel_unref( inotify_io_channel );
-    inotify_io_channel = NULL;
-    g_source_remove( inotify_io_watch );
+    if( reload_handler )
+        g_source_remove( reload_handler );
 
-    close( inotify_fd );
-    inotify_fd = -1;
+    // delay the reload deliberately to prevent frequent massive changes to the menu dirs 
+    // due to system upgrade or something.
+    reload_handler = g_timeout_add( 5000,(GSourceFunc)reload_apps, NULL );
 }
 
 GdkFilterReturn evt_filter(GdkXEvent *xevt, GdkEvent *evt, gpointer data)
@@ -461,123 +419,240 @@ static gboolean window_delete(GtkWidget *window, gpointer data)
     return TRUE;
 }
 
-int main(int argc, char** argv)
+#define skip_spaces( str ) \
+    while( *str == ' ' || *str == '\t' ) ++str;
+
+static char* get_line( char** buf )
 {
-       int i;
-       gboolean use_asus_icons;
-       GdkRectangle working_area;
+    char *ret, *pbuf;
+    ret = pbuf = *buf;
 
-#ifdef ENABLE_NLS
-    bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
-    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-    textdomain (GETTEXT_PACKAGE);
-#endif
+    while( *pbuf && *pbuf != '\n' )
+        ++pbuf;
+    if( G_LIKELY(*pbuf == '\n') )
+    {
+        *pbuf = '\0';
+        *buf = pbuf + 1;
+    }
+    else
+        *buf = NULL;
 
-       gtk_init( &argc, &argv );
+    return ret;
+}
 
-    // init inotify
-    if( !init_inotify() )
-        return 1;
+static void notebook_page_chdir( PageData* data, GMenuTreeDirectory* dir )
+{
+    GSList* l;
+    char* dir_path;
+    GMenuTreeDirectory* parent_dir;
 
-    // set up themes for notebook
-    gtk_rc_parse( PACKAGE_DATA_DIR "/lxlauncher/gtkrc" );
+    data->dir = dir;
 
-       icon_size = gtk_icon_size_register( "ALIcon", IMG_SIZE, IMG_SIZE );
+    // destroy old buttons
+    gtk_container_foreach( data->table, gtk_widget_destroy, NULL );
 
-       main_window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
-       gtk_window_move( main_window, 0, 0 );
-       gtk_window_set_skip_pager_hint( main_window, TRUE );
-       gtk_window_set_skip_taskbar_hint( main_window, TRUE );
+    gtk_container_forall( data->go_up_bar, gtk_widget_destroy, NULL );
 
-    gtk_widget_realize( main_window );
-       gdk_window_set_keep_below( main_window->window, TRUE );
-       //gdk_window_set_decorations( main_window->window );
-       gdk_window_set_type_hint( main_window->window, GDK_WINDOW_TYPE_HINT_DESKTOP );
-       gtk_window_set_position( main_window, GTK_WIN_POS_NONE );
-       //gtk_window_set_gravity(GDK_GRAVITY_STATIC );
-       
-    g_signal_connect(main_window, "delete-event", G_CALLBACK(window_delete), NULL);
+    if( G_UNLIKELY( !dir ) )
+        return;
 
-    atom_NET_WORKAREA = XInternAtom( GDK_DISPLAY(), "_NET_WORKAREA", True);;
-    XSelectInput(GDK_DISPLAY(), GDK_WINDOW_XID(gtk_widget_get_root_window(main_window)), PropertyChangeMask);
-       gdk_window_add_filter( gtk_widget_get_root_window(main_window), evt_filter, NULL );
+    for( l = gmenu_tree_directory_get_contents(dir); l; l = l->next )
+    {
+        GMenuTreeItem* item = (GMenuTreeItem*)l->data;
+        GMenuTreeItemType type = gmenu_tree_item_get_type(item);
+        if( type == GMENU_TREE_ITEM_DIRECTORY )
+            add_dir_btn( data, (GMenuTreeDirectory*)item );
+        else if( type == GMENU_TREE_ITEM_ENTRY )
+        {
+            if( gmenu_tree_entry_get_is_nodisplay(item) || gmenu_tree_entry_get_is_excluded(item) )
+                continue;
+            add_app_btn( data->table, (GMenuTreeEntry*)item );
+        }
+    }
 
-       notebook = gtk_notebook_new();
-       GTK_WIDGET_UNSET_FLAGS(notebook, GTK_CAN_FOCUS );
-       gtk_container_add( (GtkContainer*)main_window, notebook );
+    parent_dir = gmenu_tree_item_get_parent((GMenuTreeItem*)dir);
 
-       tooltips = gtk_tooltips_new();
-       g_object_ref_sink( tooltips );
+    if( parent_dir != root_dir )   // if dir has parent, not top-level group
+    {
+        GtkWidget* label;
+        char* text = g_strdup_printf( _("Go back to \"%s\""), gmenu_tree_directory_get_name(parent_dir) );
+        GtkWidget* btn = gtk_button_new_with_label( text );
+        g_free( text );
 
-    use_asus_icons = g_file_test( ICON_DIR, G_FILE_TEST_IS_DIR );
+        dir_path = menu_dir_to_path( dir );
 
-       for( i = 0; i < G_N_ELEMENTS(groups); ++i )
+        label = gtk_label_new( dir_path );
+        g_free( dir_path );
+
+        gtk_misc_set_alignment( label, 0.0, 0.5 );
+        g_object_set_data( btn, "dir", parent_dir );
+        g_signal_connect( btn, "clicked", on_dir_btn_clicked, data );
+        gtk_button_set_image( btn, gtk_image_new_from_stock( GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON ) );
+
+        gtk_box_pack_start( data->go_up_bar, label, TRUE, TRUE, 4 );
+        gtk_box_pack_start( data->go_up_bar, btn, FALSE, TRUE, 2 );
+        gtk_widget_show_all( data->go_up_bar );
+    }
+    else
+    {
+        gtk_widget_hide( data->go_up_bar );
+    }
+}
+
+static void page_data_free( PageData* data )
+{
+    if( data->background )
+        g_object_unref( data->background );
+    g_free( data );
+}
+
+static void create_notebook_pages()
+{
+    GSList* l;
+
+    root_dir = gmenu_tree_get_root_directory( menu_tree );
+
+    // build pages for toplevel groups
+       for( l = gmenu_tree_directory_get_contents(root_dir); l; l = l->next )
        {
            GtkWidget* *viewport;
+               GtkAdjustment* adj;
                GtkWidget* scroll = gtk_scrolled_window_new(NULL, NULL);
-               GtkWidget* page = exo_wrap_table_new(TRUE);
+               GtkWidget* page_vbox = gtk_vbox_new(FALSE, 0);
+               GtkWidget* table = exo_wrap_table_new(TRUE);
                GtkWidget* label;
                GtkWidget* image;
-               GdkPixbuf* pixbuf;
+               GtkWidget* go_up_bar = gtk_hbox_new( FALSE, 2 );
+               GdkPixbuf* pixbuf=NULL;
                GdkPixmap* pixmap;
+               GdkGC *pixmap_gc=NULL;
                char* file;
+        PageData* page_data;
+               GMenuTreeDirectory* dir = (GMenuTreeDirectory*)l->data;
+
+               if( G_UNLIKELY( gmenu_tree_item_get_type((GMenuTreeItem*)dir) != GMENU_TREE_ITEM_DIRECTORY ) )
+                   continue;
+
+        page_data = g_new0( PageData, 1 );
+        g_object_set_data_full( page_vbox, "page", page_data, page_data_free );
 
                label = gtk_hbox_new( FALSE, 2 );
 
                gtk_scrolled_window_set_policy(scroll, GTK_POLICY_NEVER,GTK_POLICY_AUTOMATIC );
 
+        // Very bad dirty hacks used to force gtk+ to draw transparent background
+               GtkRange* range = gtk_scrolled_window_get_vscrollbar(scroll);
+               //gtk_range_set_update_policy( range, GTK_UPDATE_DELAYED );
+               g_signal_connect( range, "change-value", G_CALLBACK(on_scroll_change_val), page_data );
+               adj = gtk_scrolled_window_get_vadjustment(scroll);
+               adj->step_increment = BUTTON_SIZE / 3;
+               adj->page_increment = BUTTON_SIZE / 2;
+               gtk_adjustment_changed( adj );
+        g_signal_connect( adj, "value-changed", G_CALLBACK(on_scroll), page_data );
+
         // create label
-        if( use_asus_icons ) // use the ugly asus icons
-        {
-            file = g_build_filename( ICON_DIR, groups[i].icon, NULL );
-            image = gtk_image_new_from_file(file);
-            g_free( file );
-        }
-        else // use themed icon provided by icon themes
-            image = gtk_image_new_from_icon_name(groups[i].themed_icon, GTK_ICON_SIZE_MENU);
+        image = gtk_image_new_from_icon_name( gmenu_tree_directory_get_icon(dir), GTK_ICON_SIZE_MENU );
 
                gtk_box_pack_start( label, image, FALSE, TRUE, 2 );
-               gtk_box_pack_start( label, gtk_label_new(_(groups[i].title)), FALSE, TRUE, 2 );
+               gtk_box_pack_start( label, gtk_label_new( gmenu_tree_directory_get_name(dir) ), FALSE, TRUE, 2 );
                gtk_widget_show_all(label);
 
-        // gtk_container_set_border_width( page, 4 );
-        exo_wrap_table_set_col_spacing( page, 8 );
+        // gtk_container_set_border_width( page_vbox, 4 );
+        exo_wrap_table_set_col_spacing( table, 8 );
 
                viewport = gtk_viewport_new( NULL, NULL );
-               gtk_container_add( viewport, page );
+               gtk_container_add( viewport, table );
                gtk_container_add( scroll, viewport );
                gtk_widget_show_all( scroll );
 
-               gtk_notebook_append_page( notebook, scroll, label );
-               groups[i].page = page;
+        gtk_box_pack_start( page_vbox, go_up_bar, FALSE, TRUE, 0 );
+        gtk_box_pack_start( page_vbox, scroll, TRUE, TRUE, 0 );
+               gtk_widget_show_all( page_vbox );
+
+               gtk_notebook_append_page( notebook, page_vbox, label );
 
         // set background
         gtk_widget_set_app_paintable( viewport, TRUE );
-
+/*
         file = g_build_filename( BACKGROUND_DIR, groups[i].background, NULL );
         pixbuf = gdk_pixbuf_new_from_file( file, NULL );
         g_free( file );
-
+*/
         if( pixbuf )
         {
             pixmap = gdk_pixmap_new( gdk_get_default_root_window(), gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), -1 );
-            gdk_pixbuf_render_to_drawable(pixbuf, pixmap, scroll->style->black_gc,
+            pixmap_gc = gdk_gc_new(pixmap);
+            gdk_pixbuf_render_to_drawable(pixbuf, pixmap, pixmap_gc,
                                     0, 0, 0, 0,
                                     gdk_pixbuf_get_width(pixbuf),
                                     gdk_pixbuf_get_height(pixbuf),
                                     GDK_RGB_DITHER_NORMAL, 0, 0 );
             g_object_unref( pixbuf );
 
-            g_signal_connect( viewport, "expose_event", G_CALLBACK(on_viewport_expose), pixmap );
             g_object_weak_ref( viewport, (GWeakNotify)g_object_unref, pixmap );
+            g_object_unref(pixmap_gc);
         }
+        g_signal_connect( viewport, "expose_event", G_CALLBACK(on_viewport_expose), pixmap );
+
+        page_data->page_vbox = page_vbox;
+        page_data->go_up_bar = go_up_bar;
+        page_data->table = table;
+        notebook_page_chdir( page_data, dir );
        }
+}
+
+int main(int argc, char** argv)
+{
+       int i;
+       GdkRectangle working_area;
+    GList* l;
+
+#ifdef ENABLE_NLS
+    bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+    textdomain (GETTEXT_PACKAGE);
+#endif
+
+       gtk_init( &argc, &argv );
+
+    // set up themes for notebook
+    gtk_rc_parse( PACKAGE_DATA_DIR "/lxlauncher/gtkrc" );
+
+       icon_size = gtk_icon_size_register( "ALIcon", IMG_SIZE, IMG_SIZE );
+
+       main_window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+       gtk_window_move( main_window, 0, 0 );
+       gtk_window_set_skip_pager_hint( main_window, TRUE );
+       gtk_window_set_skip_taskbar_hint( main_window, TRUE );
+
+    gtk_widget_realize( main_window );
+       gdk_window_set_keep_below( main_window->window, TRUE );
+       //gdk_window_set_decorations( main_window->window );
+       gdk_window_set_type_hint( main_window->window, GDK_WINDOW_TYPE_HINT_DESKTOP );
+       gtk_window_set_position( main_window, GTK_WIN_POS_NONE );
+       //gtk_window_set_gravity(GDK_GRAVITY_STATIC );
+
+    g_signal_connect(main_window, "delete-event", G_CALLBACK(window_delete), NULL);
+
+    atom_NET_WORKAREA = XInternAtom( GDK_DISPLAY(), "_NET_WORKAREA", True);;
+    XSelectInput(GDK_DISPLAY(), GDK_WINDOW_XID(gtk_widget_get_root_window(main_window)), PropertyChangeMask );
+       gdk_window_add_filter( gtk_widget_get_root_window(main_window), evt_filter, NULL );
+
+       notebook = gtk_notebook_new();
+       GTK_WIDGET_UNSET_FLAGS(notebook, GTK_CAN_FOCUS );
+       gtk_container_add( (GtkContainer*)main_window, notebook );
+
+       tooltips = gtk_tooltips_new();
+       g_object_ref_sink( tooltips );
 
-       gtk_notebook_reorder_child(notebook, gtk_notebook_get_nth_page(notebook, 2), 1 );
+    menu_tree = gmenu_tree_lookup( DATA_DIR"/launcher.menu", GMENU_TREE_FLAGS_NONE );
+    gmenu_tree_add_monitor( menu_tree, on_menu_tree_changed, NULL );
 
-       load_apps();
+    create_notebook_pages();
 
     get_working_area( gtk_widget_get_screen(main_window), &working_area );
+    // working_area.width = 800;
+    // working_area.height = 480;
     gtk_window_move( main_window, working_area.x, working_area.y );
     gtk_window_resize( main_window, working_area.width, working_area.height );
 
@@ -586,7 +661,8 @@ int main(int argc, char** argv)
 
     gdk_window_remove_filter( gtk_widget_get_root_window(main_window), evt_filter, NULL );
 
-    finalize_inotify();
+    gmenu_tree_remove_monitor( menu_tree, on_menu_tree_changed, NULL );
+    gmenu_tree_unref( menu_tree );
 
        return 0;
 }
diff --git a/src/misc.c b/src/misc.c
new file mode 100644 (file)
index 0000000..d6f93f7
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ *      misc.c
+ *      
+ *      Copyright 2008 PCMan <pcman@debian>
+ *      
+ *      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., 51 Franklin Street, Fifth Floor, Boston,
+ *      MA 02110-1301, USA.
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "misc.h"
+#include "vfs-utils.h"
+#include "vfs-execute.h"
+
+static GdkPixbuf* load_icon_file( const char* file_name, int size )
+{
+    GdkPixbuf* icon = NULL;
+    char* file_path;
+    const gchar** dirs = (const gchar**) g_get_system_data_dirs();
+    const gchar** dir;
+    for( dir = dirs; *dir; ++dir )
+    {
+        file_path = g_build_filename( *dir, "pixmaps", file_name, NULL );
+        icon = gdk_pixbuf_new_from_file_at_scale( file_path, size, size, TRUE, NULL );
+        g_free( file_path );
+        if( icon )
+            break;
+    }
+    return icon;
+}
+
+GdkPixbuf* lxlauncher_load_icon( const char* name, int size, gboolean use_fallback )
+{
+    GtkIconTheme* theme;
+    char *icon_name = NULL, *suffix;
+    GdkPixbuf* icon = NULL;
+
+    if( name )
+    {
+        if( g_path_is_absolute( name) )
+        {
+            icon = gdk_pixbuf_new_from_file_at_scale( name,
+                                                     size, size, TRUE, NULL );
+        }
+        else
+        {
+            theme = gtk_icon_theme_get_default();
+            suffix = strchr( name, '.' );
+            if( suffix ) /* has file extension, it's a basename of icon file */
+            {
+                /* try to find it in pixmaps dirs */
+                icon = load_icon_file( name, size );
+                if( G_UNLIKELY( ! icon ) )  /* unfortunately, not found */
+                {
+                    /* Let's remove the suffix, and see if this name can match an icon
+                         in current icon theme */
+                    icon_name = g_strndup( name,
+                                           (suffix - name) );
+                    icon = vfs_load_icon( theme, icon_name, size );
+                    g_free( icon_name );
+                }
+            }
+            else  /* no file extension, it could be an icon name in the icon theme */
+            {
+                icon = vfs_load_icon( theme, name, size );
+            }
+        }
+    }
+    if( G_UNLIKELY( ! icon ) && use_fallback )  /* fallback to generic icon */
+    {
+        theme = gtk_icon_theme_get_default();
+        icon = vfs_load_icon( theme, "application-x-executable", size );
+        if( G_UNLIKELY( ! icon ) )  /* fallback to generic icon */
+        {
+            icon = vfs_load_icon( theme, "gnome-mime-application-x-executable", size );
+        }
+    }
+    return icon;
+}
+
+
+static gboolean can_desktop_entry_open_multiple_files( const char* exec )
+{
+    char* p;
+    if( exec )
+    {
+        for( p = exec; *p; ++p )
+        {
+            if( *p == '%' )
+            {
+                ++p;
+                switch( *p )
+                {
+                case 'U':
+                case 'F':
+                case 'N':
+                case 'D':
+                    return TRUE;
+                case '\0':
+                    return FALSE;
+                }
+            }
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*
+* Parse Exec command line of app desktop file, and translate
+* it into a real command which can be passed to g_spawn_command_line_async().
+* file_list is a null-terminated file list containing full
+* paths of the files passed to app.
+* returned char* should be freed when no longer needed.
+*/
+static char* translate_app_exec_to_command_line( const char* pexec,
+                                                 GList* file_list )
+{
+    char* file;
+    GList* l;
+    gchar *tmp;
+    GString* cmd = g_string_new("");
+    gboolean add_files = FALSE;
+
+    for( ; *pexec; ++pexec )
+    {
+        if( *pexec == '%' )
+        {
+            ++pexec;
+            switch( *pexec )
+            {
+            case 'U':
+                for( l = file_list; l; l = l->next )
+                {
+                    tmp = g_filename_to_uri( (char*)l->data, NULL, NULL );
+                    file = g_shell_quote( tmp );
+                    g_free( tmp );
+                    g_string_append( cmd, file );
+                    g_string_append_c( cmd, ' ' );
+                    g_free( file );
+                }
+                add_files = TRUE;
+                break;
+            case 'u':
+                if( file_list && file_list->data )
+                {
+                    file = (char*)file_list->data;
+                    tmp = g_filename_to_uri( file, NULL, NULL );
+                    file = g_shell_quote( tmp );
+                    g_free( tmp );
+                    g_string_append( cmd, file );
+                    g_free( file );
+                    add_files = TRUE;
+                }
+                break;
+            case 'F':
+            case 'N':
+                for( l = file_list; l; l = l->next )
+                {
+                    file = (char*)l->data;
+                    tmp = g_shell_quote( file );
+                    g_string_append( cmd, tmp );
+                    g_string_append_c( cmd, ' ' );
+                    g_free( tmp );
+                }
+                add_files = TRUE;
+                break;
+            case 'f':
+            case 'n':
+                if( file_list && file_list->data )
+                {
+                    file = (char*)file_list->data;
+                    tmp = g_shell_quote( file );
+                    g_string_append( cmd, tmp );
+                    g_free( tmp );
+                    add_files = TRUE;
+                }
+                break;
+            case 'D':
+                for( l = file_list; l; l = l->next )
+                {
+                    tmp = g_path_get_dirname( (char*)l->data );
+                    file = g_shell_quote( tmp );
+                    g_free( tmp );
+                    g_string_append( cmd, file );
+                    g_string_append_c( cmd, ' ' );
+                    g_free( file );
+                }
+                add_files = TRUE;
+                break;
+            case 'd':
+                if( file_list && file_list->data )
+                {
+                    tmp = g_path_get_dirname( (char*)file_list->data );
+                    file = g_shell_quote( tmp );
+                    g_free( tmp );
+                    g_string_append( cmd, file );
+                    g_free( tmp );
+                    add_files = TRUE;
+                }
+                break;
+            case 'c':
+                #if 0
+                g_string_append( cmd, vfs_app_desktop_get_disp_name( app ) );
+                #endif
+                break;
+            case 'i':
+                /* Add icon name */
+                #if 0
+                if( vfs_app_desktop_get_icon_name( app ) )
+                {
+                    g_string_append( cmd, "--icon " );
+                    g_string_append( cmd, vfs_app_desktop_get_icon_name( app ) );
+                }
+                #endif
+                break;
+            case 'k':
+                /* Location of the desktop file */
+                break;
+            case 'v':
+                /* Device name */
+                break;
+            case '%':
+                g_string_append_c ( cmd, '%' );
+                break;
+            case '\0':
+                goto _finish;
+                break;
+            }
+        }
+        else  /* not % escaped part */
+        {
+            g_string_append_c ( cmd, *pexec );
+        }
+    }
+_finish:
+    if( ! add_files )
+    {
+        g_string_append_c ( cmd, ' ' );
+        for( l = file_list; l; l = l->next )
+        {
+            file = (char*)l->data;
+            tmp = g_shell_quote( file );
+            g_string_append( cmd, tmp );
+            g_string_append_c( cmd, ' ' );
+            g_free( tmp );
+        }
+    }
+
+    return g_string_free( cmd, FALSE );
+}
+
+gboolean lxlauncher_execute_app( GdkScreen* screen,
+                                     const char* working_dir,
+                                     const char* desktop_entry_exec,
+                                     const char* app_disp_name,
+                                     GList* file_paths,
+                                     gboolean in_terminal, /* not supported now */
+                                     GError** err )
+{
+    char* exec = NULL;
+    char* cmd;
+    GList* l;
+    gchar** argv = NULL;
+    gint argc = 0;
+    const char* sn_desc;
+
+    if( desktop_entry_exec )
+    {
+        if ( ! strchr( desktop_entry_exec, '%' ) )
+        { /* No filename parameters */
+            exec = g_strconcat( desktop_entry_exec, " %f", NULL );
+        }
+        else
+        {
+            exec = g_strdup( desktop_entry_exec );
+        }
+    }
+
+    if ( exec )
+    {
+        if( !screen )
+            screen = gdk_screen_get_default();
+
+        sn_desc = app_disp_name;
+        if( !sn_desc )
+            sn_desc = exec;
+        if( can_desktop_entry_open_multiple_files( desktop_entry_exec ) )
+        {
+            cmd = translate_app_exec_to_command_line( desktop_entry_exec, file_paths );
+            if ( cmd )
+            {
+                /* g_debug( "Execute %s\n", cmd ); */
+                if( g_shell_parse_argv( cmd, &argc, &argv, NULL ) )
+                {
+                    vfs_exec_on_screen( screen, NULL, argv, NULL,
+                                        sn_desc, VFS_EXEC_DEFAULT_FLAGS, err );
+                    g_strfreev( argv );
+                }
+                g_free( cmd );
+            }
+            else
+            {
+                for( l = file_paths; l; l = l->next )
+                {
+                    cmd = translate_app_exec_to_command_line( desktop_entry_exec, l );
+                    if ( cmd )
+                    {
+                        /* g_debug( "Execute %s\n", cmd ); */
+                        if( g_shell_parse_argv( cmd, &argc, &argv, NULL ) )
+                        {
+                            vfs_exec_on_screen( screen, NULL,argv, NULL, sn_desc,
+                                                G_SPAWN_SEARCH_PATH|
+                                                G_SPAWN_STDOUT_TO_DEV_NULL|
+                                                G_SPAWN_STDERR_TO_DEV_NULL,
+                                    err );
+                            g_strfreev( argv );
+                        }
+                        g_free( cmd );
+                    }
+                }
+            }
+            g_free( exec );
+        }
+        return TRUE;
+    }
+
+    g_set_error( err, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Command not found") );
+    return FALSE;
+}
diff --git a/src/misc.h b/src/misc.h
new file mode 100644 (file)
index 0000000..645f68b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *      misc.h
+ *
+ *      Copyright 2008 PCMan <pcman.tw@gmail.com>
+ *
+ *      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., 51 Franklin Street, Fifth Floor, Boston,
+ *      MA 02110-1301, USA.
+ */
+
+#ifndef _MISC_H_
+#define _MISC_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+gboolean lxlauncher_execute_app( GdkScreen* screen,
+                                     const char* working_dir,
+                                     const char* desktop_entry_exec,
+                                     const char* app_disp_name,
+                                     GList* file_paths,
+                                     gboolean in_terminal, /* not supported now */
+                                     GError** err );
+
+GdkPixbuf* lxlauncher_load_icon( const char* name, int size, gboolean use_fallback );
+
+G_END_DECLS
+
+#endif
diff --git a/src/vfs-app-desktop.c b/src/vfs-app-desktop.c
deleted file mode 100644 (file)
index 9f49bac..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
-*  C Implementation: vfs-app-desktop
-*
-* Description:
-*
-*
-* Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006
-*
-* Copyright: See COPYING file that comes with this distribution
-*
-*/
-
-#include "vfs-app-desktop.h"
-#include <glib/gi18n.h>
-#include "glib-mem.h"
-
-#include <string.h>
-
-#include "vfs-execute.h"
-
-#include "vfs-utils.h"  /* for vfs_load_icon */
-
-const char desktop_entry_name[] = "Desktop Entry";
-
-/*
-* If file_name is not a full path, this function searches default paths
-* for the desktop file.
-*/
-VFSAppDesktop* vfs_app_desktop_new( const char* file_name )
-{
-    GKeyFile* file;
-    gboolean load;
-    char* relative_path;
-
-    VFSAppDesktop* app = g_slice_new0( VFSAppDesktop );
-    app->n_ref = 1;
-
-    file = g_key_file_new();
-
-    if( !file_name )
-    {
-        g_key_file_free( file );
-        return app;
-    }
-
-    if( g_path_is_absolute( file_name ) )
-    {
-        app->file_name = g_path_get_basename( file_name );
-        load = g_key_file_load_from_file( file, file_name,
-                                          G_KEY_FILE_NONE, NULL );
-    }
-    else
-    {
-        app->file_name = g_strdup( file_name );
-        relative_path = g_build_filename( "applications",
-                                          app->file_name, NULL );
-        load = g_key_file_load_from_data_dirs( file, relative_path, NULL,
-                                               G_KEY_FILE_NONE, NULL );
-        g_free( relative_path );
-    }
-
-    if( load )
-    {
-        app->disp_name = g_key_file_get_locale_string ( file,
-                                                        desktop_entry_name,
-                                                        "Name", NULL, NULL);
-        app->comment = g_key_file_get_locale_string ( file, desktop_entry_name,
-                                                      "Comment", NULL, NULL);
-        app->exec = g_key_file_get_string ( file, desktop_entry_name,
-                                            "Exec", NULL);
-        app->icon_name = g_key_file_get_string ( file, desktop_entry_name,
-                                                 "Icon", NULL);
-        app->terminal = g_key_file_get_boolean( file, desktop_entry_name,
-                                                "Terminal", NULL );
-        app->hidden = g_key_file_get_boolean( file, desktop_entry_name,
-                                                "NoDisplay", NULL );
-                                                
-               app->categories = g_key_file_get_string_list( file, desktop_entry_name,
-                                                                                               "Categories", NULL, NULL );
-    }
-
-    g_key_file_free( file );
-
-    return app;
-}
-
-static void vfs_app_desktop_free( VFSAppDesktop* app )
-{
-    g_free( app->disp_name );
-    g_free( app->comment );
-    g_free( app->exec );
-    g_free( app->icon_name );
-    g_strfreev( app->categories );
-
-    g_slice_free( VFSAppDesktop, app );
-}
-
-void vfs_app_desktop_ref( VFSAppDesktop* app )
-{
-    g_atomic_int_inc( &app->n_ref );
-}
-
-void vfs_app_desktop_unref( gpointer data )
-{
-    VFSAppDesktop* app = (VFSAppDesktop*)data;
-    if( g_atomic_int_dec_and_test(&app->n_ref) )
-        vfs_app_desktop_free( app );
-}
-
-const char* vfs_app_desktop_get_name( VFSAppDesktop* app )
-{
-    return app->file_name;
-}
-
-const char* vfs_app_desktop_get_disp_name( VFSAppDesktop* app )
-{
-    if( G_LIKELY(app->disp_name) )
-        return app->disp_name;
-    return app->file_name;
-}
-
-const char* vfs_app_desktop_get_desc( VFSAppDesktop* app )
-{
-    if( G_LIKELY(app->comment) )
-        return app->comment;
-    return vfs_app_desktop_get_disp_name(app); 
-}
-
-const char* vfs_app_desktop_get_exec( VFSAppDesktop* app )
-{
-    return app->exec;
-}
-
-const char* vfs_app_desktop_get_icon_name( VFSAppDesktop* app )
-{
-    return app->icon_name;
-}
-
-static GdkPixbuf* load_icon_file( const char* file_name, int size )
-{
-    GdkPixbuf* icon = NULL;
-    char* file_path;
-    const gchar** dirs = (const gchar**) g_get_system_data_dirs();
-    const gchar** dir;
-    for( dir = dirs; *dir; ++dir )
-    {
-        file_path = g_build_filename( *dir, "pixmaps", file_name, NULL );
-        icon = gdk_pixbuf_new_from_file_at_scale( file_path, size, size, TRUE, NULL );
-        g_free( file_path );
-        if( icon )
-            break;
-    }
-    return icon;
-}
-
-GdkPixbuf* vfs_app_desktop_get_icon( VFSAppDesktop* app, int size, gboolean use_fallback )
-{
-    GtkIconTheme* theme;
-    char *icon_name = NULL, *suffix;
-    GdkPixbuf* icon = NULL;
-
-    if( app->icon_name )
-    {
-        if( g_path_is_absolute( app->icon_name) )
-        {
-            icon = gdk_pixbuf_new_from_file_at_scale( app->icon_name,
-                                                     size, size, TRUE, NULL );
-        }
-        else
-        {
-            theme = gtk_icon_theme_get_default();
-            suffix = strchr( app->icon_name, '.' );
-            if( suffix ) /* has file extension, it's a basename of icon file */
-            {
-                /* try to find it in pixmaps dirs */
-                icon = load_icon_file( app->icon_name, size );
-                if( G_UNLIKELY( ! icon ) )  /* unfortunately, not found */
-                {
-                    /* Let's remove the suffix, and see if this name can match an icon
-                         in current icon theme */
-                    icon_name = g_strndup( app->icon_name,
-                                           (suffix - app->icon_name) );
-                    icon = vfs_load_icon( theme, icon_name, size );
-                    g_free( icon_name );
-                }
-            }
-            else  /* no file extension, it could be an icon name in the icon theme */
-            {
-                icon = vfs_load_icon( theme, app->icon_name, size );
-            }
-        }
-    }
-    if( G_UNLIKELY( ! icon ) && use_fallback )  /* fallback to generic icon */
-    {
-        theme = gtk_icon_theme_get_default();
-        icon = vfs_load_icon( theme, "application-x-executable", size );
-        if( G_UNLIKELY( ! icon ) )  /* fallback to generic icon */
-        {
-            icon = vfs_load_icon( theme, "gnome-mime-application-x-executable", size );
-        }
-    }
-    return icon;
-}
-
-gboolean vfs_app_desktop_open_multiple_files( VFSAppDesktop* app )
-{
-    char* p;
-    if( app->exec )
-    {
-        for( p = app->exec; *p; ++p )
-        {
-            if( *p == '%' )
-            {
-                ++p;
-                switch( *p )
-                {
-                case 'U':
-                case 'F':
-                case 'N':
-                case 'D':
-                    return TRUE;
-                case '\0':
-                    return FALSE;
-                }
-            }
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-gboolean vfs_app_desktop_open_in_terminal( VFSAppDesktop* app )
-{
-    return app->terminal;
-}
-
-gboolean vfs_app_desktop_is_hidden( VFSAppDesktop* app )
-{
-    return app->hidden;
-}
-
-/*
-* Parse Exec command line of app desktop file, and translate
-* it into a real command which can be passed to g_spawn_command_line_async().
-* file_list is a null-terminated file list containing full
-* paths of the files passed to app.
-* returned char* should be freed when no longer needed.
-*/
-static char* translate_app_exec_to_command_line( VFSAppDesktop* app,
-                                                 GList* file_list )
-{
-    const char* pexec = vfs_app_desktop_get_exec( app );
-    char* file;
-    GList* l;
-    gchar *tmp;
-    GString* cmd = g_string_new("");
-    gboolean add_files = FALSE;
-
-    for( ; *pexec; ++pexec )
-    {
-        if( *pexec == '%' )
-        {
-            ++pexec;
-            switch( *pexec )
-            {
-            case 'U':
-                for( l = file_list; l; l = l->next )
-                {
-                    tmp = g_filename_to_uri( (char*)l->data, NULL, NULL );
-                    file = g_shell_quote( tmp );
-                    g_free( tmp );
-                    g_string_append( cmd, file );
-                    g_string_append_c( cmd, ' ' );
-                    g_free( file );
-                }
-                add_files = TRUE;
-                break;
-            case 'u':
-                if( file_list && file_list->data )
-                {
-                    file = (char*)file_list->data;
-                    tmp = g_filename_to_uri( file, NULL, NULL );
-                    file = g_shell_quote( tmp );
-                    g_free( tmp );
-                    g_string_append( cmd, file );
-                    g_free( file );
-                    add_files = TRUE;
-                }
-                break;
-            case 'F':
-            case 'N':
-                for( l = file_list; l; l = l->next )
-                {
-                    file = (char*)l->data;
-                    tmp = g_shell_quote( file );
-                    g_string_append( cmd, tmp );
-                    g_string_append_c( cmd, ' ' );
-                    g_free( tmp );
-                }
-                add_files = TRUE;
-                break;
-            case 'f':
-            case 'n':
-                if( file_list && file_list->data )
-                {
-                    file = (char*)file_list->data;
-                    tmp = g_shell_quote( file );
-                    g_string_append( cmd, tmp );
-                    g_free( tmp );
-                    add_files = TRUE;
-                }
-                break;
-            case 'D':
-                for( l = file_list; l; l = l->next )
-                {
-                    tmp = g_path_get_dirname( (char*)l->data );
-                    file = g_shell_quote( tmp );
-                    g_free( tmp );
-                    g_string_append( cmd, file );
-                    g_string_append_c( cmd, ' ' );
-                    g_free( file );
-                }
-                add_files = TRUE;
-                break;
-            case 'd':
-                if( file_list && file_list->data )
-                {
-                    tmp = g_path_get_dirname( (char*)file_list->data );
-                    file = g_shell_quote( tmp );
-                    g_free( tmp );
-                    g_string_append( cmd, file );
-                    g_free( tmp );
-                    add_files = TRUE;
-                }
-                break;
-            case 'c':
-                g_string_append( cmd, vfs_app_desktop_get_disp_name( app ) );
-                break;
-            case 'i':
-                /* Add icon name */
-                if( vfs_app_desktop_get_icon_name( app ) )
-                {
-                    g_string_append( cmd, "--icon " );
-                    g_string_append( cmd, vfs_app_desktop_get_icon_name( app ) );
-                }
-                break;
-            case 'k':
-                /* Location of the desktop file */
-                break;
-            case 'v':
-                /* Device name */
-                break;
-            case '%':
-                g_string_append_c ( cmd, '%' );
-                break;
-            case '\0':
-                goto _finish;
-                break;
-            }
-        }
-        else  /* not % escaped part */
-        {
-            g_string_append_c ( cmd, *pexec );
-        }
-    }
-_finish:
-    if( ! add_files )
-    {
-        g_string_append_c ( cmd, ' ' );
-        for( l = file_list; l; l = l->next )
-        {
-            file = (char*)l->data;
-            tmp = g_shell_quote( file );
-            g_string_append( cmd, tmp );
-            g_string_append_c( cmd, ' ' );
-            g_free( tmp );
-        }
-    }
-
-    return g_string_free( cmd, FALSE );
-}
-
-gboolean vfs_app_desktop_open_files( GdkScreen* screen,
-                                     const char* working_dir,
-                                     VFSAppDesktop* app,
-                                     GList* file_paths,
-                                     GError** err )
-{
-    char* exec = NULL;
-    char* cmd;
-    GList* l;
-    gchar** argv = NULL;
-    gint argc = 0;
-    const char* sn_desc;
-
-    if( vfs_app_desktop_get_exec( app ) )
-    {
-        if ( ! strchr( vfs_app_desktop_get_exec( app ), '%' ) )
-        { /* No filename parameters */
-            exec = g_strconcat( vfs_app_desktop_get_exec( app ), " %f", NULL );
-        }
-        else
-        {
-            exec = g_strdup( vfs_app_desktop_get_exec( app ) );
-        }
-    }
-g_debug(vfs_app_desktop_get_exec( app ));
-    if ( exec )
-    {
-        if( !screen )
-            screen = gdk_screen_get_default();
-
-        sn_desc = vfs_app_desktop_get_disp_name( app );
-        if( !sn_desc )
-            sn_desc = exec;
-        if( vfs_app_desktop_open_multiple_files( app ) )
-        {
-            cmd = translate_app_exec_to_command_line( app, file_paths );
-            if ( cmd )
-            {
-                g_debug( "Execute %s\n", cmd );
-                if( g_shell_parse_argv( cmd, &argc, &argv, NULL ) )
-                {
-                    vfs_exec_on_screen( screen, NULL, argv, NULL,
-                                        sn_desc, VFS_EXEC_DEFAULT_FLAGS, err );
-                    g_strfreev( argv );
-                }
-                g_free( cmd );
-            }
-            else
-            {
-                for( l = file_paths; l; l = l->next )
-                {
-                    cmd = translate_app_exec_to_command_line( app, l );
-                    if ( cmd )
-                    {
-                        /* g_debug( "Execute %s\n", cmd ); */
-                        if( g_shell_parse_argv( cmd, &argc, &argv, NULL ) )
-                        {
-                            vfs_exec_on_screen( screen, NULL,argv, NULL, sn_desc,
-                                                G_SPAWN_SEARCH_PATH|
-                                                G_SPAWN_STDOUT_TO_DEV_NULL|
-                                                G_SPAWN_STDERR_TO_DEV_NULL,
-                                    err );
-                            g_strfreev( argv );
-                        }
-                        g_free( cmd );
-                    }
-                }
-            }
-            g_free( exec );
-        }
-        return TRUE;
-    }
-
-    g_set_error( err, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Command not found") );
-    return FALSE;
-}
diff --git a/src/vfs-app-desktop.h b/src/vfs-app-desktop.h
deleted file mode 100644 (file)
index 4ab38a2..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-*  C Interface: vfs-app-desktop
-*
-* Description:
-*
-*
-* Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006
-*
-* Copyright: See COPYING file that comes with this distribution
-*
-*/
-
-#ifndef _VFS_APP_DESKTOP_H_
-#define _VFS_APP_DESKTOP_H_
-
-#include <glib.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-typedef struct _VFSAppDesktop VFSAppDesktop;
-
-struct _VFSAppDesktop
-{
-    char* file_name;
-    char* disp_name;
-    char* comment;
-    char* exec;
-    char* icon_name;
-    char** categories;
-    gboolean terminal : 1;
-    gboolean hidden : 1;
-
-    /* <private> */
-    int n_ref;
-};
-
-/*
-* If file_name is not a full path, this function searches default paths
-* for the desktop file.
-*/
-VFSAppDesktop* vfs_app_desktop_new( const char* file_name );
-
-void vfs_app_desktop_ref( VFSAppDesktop* app );
-
-void vfs_app_desktop_unref( gpointer data );
-
-const char* vfs_app_desktop_get_name( VFSAppDesktop* app );
-
-const char* vfs_app_desktop_get_disp_name( VFSAppDesktop* app );
-
-const char* vfs_app_desktop_get_desc( VFSAppDesktop* app );
-
-const char* vfs_app_desktop_get_exec( VFSAppDesktop* app );
-
-GdkPixbuf* vfs_app_desktop_get_icon( VFSAppDesktop* app, int size, gboolean use_fallback );
-
-const char* vfs_app_desktop_get_icon_name( VFSAppDesktop* app );
-
-gboolean vfs_app_desktop_open_multiple_files( VFSAppDesktop* app );
-
-gboolean vfs_app_desktop_open_in_terminal( VFSAppDesktop* app );
-
-gboolean vfs_app_desktop_is_hidden( VFSAppDesktop* app );
-
-gboolean vfs_app_desktop_open_files( GdkScreen* screen,
-                                     const char* working_dir,
-                                     VFSAppDesktop* app,
-                                     GList* file_paths,
-                                     GError** err );
-
-G_END_DECLS
-
-#endif