[Xfce4-commits] <xfce4-panel:devel> Add new application menu plugin.

Nick Schermer noreply at xfce.org
Thu Feb 18 20:36:01 CET 2010


Updating branch refs/heads/devel
         to ec2c43950b79b54c71d7958d673fb2a45c449c64 (commit)
       from ec821734e753a0d8fba9d898cae560fe91804f39 (commit)

commit ec2c43950b79b54c71d7958d673fb2a45c449c64
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Feb 18 12:18:18 2010 +0100

    Add new application menu plugin.
    
    Garcon based menu plugin. Basically works the same as
    the plugin in xfdesktop, with an  additional option
    to show the generic names in the menu.
    
    Also extend the migration program to migrate from the
    xfdesktop menu to the panel menu.

 configure.ac.in                                    |    1 +
 docs/README.gtkrc-2.0                              |    8 +
 icons/16x16/Makefile.am                            |    3 +-
 icons/16x16/xfce4-panel-menu.png                   |  Bin 0 -> 1024 bytes
 icons/22x22/Makefile.am                            |    3 +-
 icons/22x22/xfce4-panel-menu.png                   |  Bin 0 -> 1623 bytes
 icons/24x24/Makefile.am                            |    3 +-
 icons/24x24/xfce4-panel-menu.png                   |  Bin 0 -> 1400 bytes
 icons/32x32/Makefile.am                            |    3 +-
 icons/32x32/xfce4-panel-menu.png                   |  Bin 0 -> 2154 bytes
 icons/48x48/Makefile.am                            |    3 +-
 icons/48x48/xfce4-panel-menu.png                   |  Bin 0 -> 3106 bytes
 migrate/migrate-46.c                               |   23 +
 plugins/Makefile.am                                |    1 +
 .../{windowmenu => applicationsmenu}/Makefile.am   |   47 +-
 .../applicationsmenu-dialog.glade}                 |  239 +++----
 plugins/applicationsmenu/applicationsmenu.c        |  832 ++++++++++++++++++++
 .../applicationsmenu/applicationsmenu.desktop.in   |    8 +
 plugins/applicationsmenu/applicationsmenu.h        |   42 +
 .../xfce4-popup-applicationsmenu.in}               |    2 +-
 plugins/launcher/launcher.c                        |    2 +-
 po/POTFILES.in                                     |    4 +
 22 files changed, 1051 insertions(+), 173 deletions(-)

diff --git a/configure.ac.in b/configure.ac.in
index da979ab..498355b 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -212,6 +212,7 @@ panel/Makefile
 wrapper/Makefile
 plugins/Makefile
 plugins/actions/Makefile
+plugins/applicationsmenu/Makefile
 plugins/clock/Makefile
 plugins/directorymenu/Makefile
 plugins/launcher/Makefile
diff --git a/docs/README.gtkrc-2.0 b/docs/README.gtkrc-2.0
index 98f0821..a843088 100644
--- a/docs/README.gtkrc-2.0
+++ b/docs/README.gtkrc-2.0
@@ -117,3 +117,11 @@ XfceDirectoryMenuPlugin
 You can set a custom icon size in gtk-icon-sizes with the name
 panel-directory-menu. The default icon size is 16px.
 Special widget name in this plugin is directorymenu-button.
+
+
+
+XfceApplicationsMenuPlugin
+-----------------------
+You can set a custom icon size in gtk-icon-sizes with the name
+panel-application-menu. The default icon size is 16px.
+Special widget name in this plugin is applicationmenu-button.
diff --git a/icons/16x16/Makefile.am b/icons/16x16/Makefile.am
index ccfbb80..10b1626 100644
--- a/icons/16x16/Makefile.am
+++ b/icons/16x16/Makefile.am
@@ -1,7 +1,8 @@
 
 iconsdir = $(datadir)/icons/hicolor/16x16/apps
 icons_DATA = \
-	xfce4-panel.png
+	xfce4-panel.png \
+	xfce4-panel-menu.png
 
 EXTRA_DIST = \
 	$(icons_DATA)
diff --git a/icons/16x16/xfce4-panel-menu.png b/icons/16x16/xfce4-panel-menu.png
new file mode 100644
index 0000000..d714d2e
Binary files /dev/null and b/icons/16x16/xfce4-panel-menu.png differ
diff --git a/icons/22x22/Makefile.am b/icons/22x22/Makefile.am
index 536ac33..eca3a3f 100644
--- a/icons/22x22/Makefile.am
+++ b/icons/22x22/Makefile.am
@@ -1,7 +1,8 @@
 
 iconsdir = $(datadir)/icons/hicolor/22x22/apps
 icons_DATA = \
-	xfce4-panel.png
+	xfce4-panel.png \
+	xfce4-panel-menu.png
 
 EXTRA_DIST = \
 	$(icons_DATA)
diff --git a/icons/22x22/xfce4-panel-menu.png b/icons/22x22/xfce4-panel-menu.png
new file mode 100644
index 0000000..e00f2da
Binary files /dev/null and b/icons/22x22/xfce4-panel-menu.png differ
diff --git a/icons/24x24/Makefile.am b/icons/24x24/Makefile.am
index 64daf3b..e32f44d 100644
--- a/icons/24x24/Makefile.am
+++ b/icons/24x24/Makefile.am
@@ -1,7 +1,8 @@
 
 iconsdir = $(datadir)/icons/hicolor/24x24/apps
 icons_DATA = \
-	xfce4-panel.png
+	xfce4-panel.png \
+	xfce4-panel-menu.png
 
 EXTRA_DIST = \
 	$(icons_DATA)
diff --git a/icons/24x24/xfce4-panel-menu.png b/icons/24x24/xfce4-panel-menu.png
new file mode 100644
index 0000000..278b98a
Binary files /dev/null and b/icons/24x24/xfce4-panel-menu.png differ
diff --git a/icons/32x32/Makefile.am b/icons/32x32/Makefile.am
index f4d5f31..8ef52e8 100644
--- a/icons/32x32/Makefile.am
+++ b/icons/32x32/Makefile.am
@@ -1,7 +1,8 @@
 
 iconsdir = $(datadir)/icons/hicolor/32x32/apps
 icons_DATA = \
-	xfce4-panel.png
+	xfce4-panel.png \
+	xfce4-panel-menu.png
 
 EXTRA_DIST = \
 	$(icons_DATA)
diff --git a/icons/32x32/xfce4-panel-menu.png b/icons/32x32/xfce4-panel-menu.png
new file mode 100644
index 0000000..1d0253e
Binary files /dev/null and b/icons/32x32/xfce4-panel-menu.png differ
diff --git a/icons/48x48/Makefile.am b/icons/48x48/Makefile.am
index 290170e..43353d3 100644
--- a/icons/48x48/Makefile.am
+++ b/icons/48x48/Makefile.am
@@ -1,7 +1,8 @@
 
 iconsdir = $(datadir)/icons/hicolor/48x48/apps
 icons_DATA = \
-	xfce4-panel.png
+	xfce4-panel.png \
+	xfce4-panel-menu.png
 
 EXTRA_DIST = \
 	$(icons_DATA)
diff --git a/icons/48x48/xfce4-panel-menu.png b/icons/48x48/xfce4-panel-menu.png
new file mode 100644
index 0000000..dd662fc
Binary files /dev/null and b/icons/48x48/xfce4-panel-menu.png differ
diff --git a/migrate/migrate-46.c b/migrate/migrate-46.c
index 8050861..c9ba686 100644
--- a/migrate/migrate-46.c
+++ b/migrate/migrate-46.c
@@ -553,6 +553,23 @@ migrate_46_plugin_windowlist (XfconfChannel *channel,
 
 
 static void
+migrate_46_plugin_xfce4_menu (XfconfChannel *channel,
+                              XfceRc        *rc)
+{
+  migrate_46_plugin_bool ("show_menu_icons", "show-menu-icons", TRUE);
+  migrate_46_plugin_bool ("show_button_title", "show-button-title", TRUE);
+  migrate_46_plugin_string ("menu_file", "custom-menu-file", "");
+  migrate_46_plugin_string ("icon_file", "button-icon", "xfce4-panel-menu");
+  migrate_46_plugin_string ("button_title", "button-title", "");
+
+  if (xfce_rc_has_entry (rc, "use_default_menu"))
+    xfconf_channel_set_bool (channel, "/custom-menu",
+       !xfce_rc_read_bool_entry (rc, "use_default_menu", TRUE));
+}
+
+
+
+static void
 migrate_46_panel_add_plugin (ConfigParser  *parser,
                              const gchar   *name,
                              const gchar   *id,
@@ -626,6 +643,12 @@ migrate_46_panel_add_plugin (ConfigParser  *parser,
       if (G_LIKELY (rc != NULL))
         migrate_46_plugin_windowlist (channel, rc);
     }
+  else if (strcmp (name, "xfce4-menu") == 0)
+    {
+      plugin_name = "applicationsmenu";
+      if (G_LIKELY (rc != NULL))
+        migrate_46_plugin_xfce4_menu (channel, rc);
+    }
   else
     {
       /* handle other "external" plugins */
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 70540b2..6a38442 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,6 +1,7 @@
 
 SUBDIRS = \
 	actions \
+	applicationsmenu \
 	clock \
 	directorymenu \
 	launcher \
diff --git a/plugins/windowmenu/Makefile.am b/plugins/applicationsmenu/Makefile.am
similarity index 59%
copy from plugins/windowmenu/Makefile.am
copy to plugins/applicationsmenu/Makefile.am
index 78711a2..e97f518 100644
--- a/plugins/windowmenu/Makefile.am
+++ b/plugins/applicationsmenu/Makefile.am
@@ -1,72 +1,71 @@
 
 INCLUDES = \
 	-I$(top_srcdir) \
-	-DG_LOG_DOMAIN=\"libwindowmenu\" \
-	-DWNCK_I_KNOW_THIS_IS_UNSTABLE \
+	-DG_LOG_DOMAIN=\"libapplicationsmenu\" \
 	$(PLATFORM_CPPFLAGS)
 
 plugindir = $(libdir)/xfce4/panel-plugins
 
 plugin_LTLIBRARIES = \
-	libwindowmenu.la
+	libapplicationsmenu.la
 
-libwindowmenu_built_sources = \
-	windowmenu-dialog_ui.h
+libapplicationsmenu_built_sources = \
+	applicationsmenu-dialog_ui.h
 
-libwindowmenu_la_SOURCES = \
-	$(libwindowmenu_built_sources) \
-	windowmenu.c \
-	windowmenu.h
+libapplicationsmenu_la_SOURCES = \
+	$(libapplicationsmenu_built_sources) \
+	applicationsmenu.c \
+	applicationsmenu.h
 
-libwindowmenu_la_CFLAGS = \
+libapplicationsmenu_la_CFLAGS = \
 	$(GTK_CFLAGS) \
 	$(EXO_CFLAGS) \
 	$(XFCONF_CFLAGS) \
 	$(LIBXFCE4UTIL_CFLAGS) \
 	$(LIBXFCE4UI_CFLAGS) \
-	$(LIBWNCK_CFLAGS) \
+	$(GARCON_CFLAGS) \
 	$(PLATFORM_CFLAGS)
 
-libwindowmenu_la_LDFLAGS = \
+libapplicationsmenu_la_LDFLAGS = \
 	-avoid-version \
 	-module \
 	-no-undefined \
 	-export-symbols-regex '^xfce_panel_module_(preinit|init|construct)' \
 	$(PLATFORM_LDFLAGS)
 
-libwindowmenu_la_LIBADD = \
+libapplicationsmenu_la_LIBADD = \
 	$(top_builddir)/libxfce4panel/libxfce4panel-$(LIBXFCE4PANEL_VERSION_API).la \
 	$(top_builddir)/common/libpanel-common.la \
 	$(EXO_LIBS) \
 	$(GTK_LIBS) \
 	$(LIBXFCE4UTIL_LIBS) \
 	$(LIBXFCE4UI_LIBS) \
-	$(LIBWNCK_LIBS) \
+	$(GARCON_LIBS) \
 	$(XFCONF_LIBS)
 
-libwindowmenu_la_DEPENDENCIES = \
+libapplicationsmenu_la_DEPENDENCIES = \
 	$(top_builddir)/libxfce4panel/libxfce4panel-$(LIBXFCE4PANEL_VERSION_API).la \
 	$(top_builddir)/common/libpanel-common.la
 
 #
-# xfce4-popup-windowmenu script
+# xfce4-popup-applicationsmenu script
 #
 bin_SCRIPTS = \
-	xfce4-popup-windowmenu
+	xfce4-popup-applicationsmenu
 
-xfce4-popup-windowmenu: xfce4-popup-windowmenu.in Makefile
+xfce4-popup-applicationsmenu: xfce4-popup-applicationsmenu.in Makefile
 	$(AM_V_GEN) sed -e "s,\@bindir\@,$(bindir),g" $< >$@
 
 #
 # .desktop file
 #
 desktopdir = $(datadir)/xfce4/panel-plugins
-desktop_in_files = windowmenu.desktop.in
+desktop_in_files = applicationsmenu.desktop.in
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 @INTLTOOL_DESKTOP_RULE@
 
 EXTRA_DIST = \
-	windowmenu-dialog.glade \
+	applicationsmenu-dialog.glade \
 	$(desktop_in_files)
 
 DISTCLEANFILES = \
@@ -74,13 +73,13 @@ DISTCLEANFILES = \
 
 if MAINTAINER_MODE
 BUILT_SOURCES = \
-	$(libwindowmenu_built_sources)
+	$(libapplicationsmenu_built_sources)
 
 DISTCLEANFILES += \
-	$(libwindowmenu_built_sources)
+	$(libapplicationsmenu_built_sources)
 
-windowmenu-dialog_ui.h: windowmenu-dialog.glade
-	$(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=windowmenu_dialog_ui $< >$@
+applicationsmenu-dialog_ui.h: applicationsmenu-dialog.glade
+	$(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=applicationsmenu_dialog_ui $< >$@
 endif
 
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/plugins/tasklist/tasklist-dialog.glade b/plugins/applicationsmenu/applicationsmenu-dialog.glade
similarity index 67%
copy from plugins/tasklist/tasklist-dialog.glade
copy to plugins/applicationsmenu/applicationsmenu-dialog.glade
index 7947788..24983e7 100644
--- a/plugins/tasklist/tasklist-dialog.glade
+++ b/plugins/applicationsmenu/applicationsmenu-dialog.glade
@@ -4,7 +4,7 @@
   <!-- interface-requires libxfce4ui 0.0 -->
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="XfceTitledDialog" id="dialog">
-    <property name="title" translatable="yes">Window Buttons</property>
+    <property name="title" translatable="yes">Applications Menu</property>
     <property name="icon_name">gtk-properties</property>
     <property name="type_hint">normal</property>
     <property name="has_separator">False</property>
@@ -27,6 +27,7 @@
                 <child>
                   <object class="GtkAlignment" id="alignment3">
                     <property name="visible">True</property>
+                    <property name="bottom_padding">6</property>
                     <property name="left_padding">12</property>
                     <child>
                       <object class="GtkVBox" id="vbox3">
@@ -35,11 +36,12 @@
                         <property name="orientation">vertical</property>
                         <property name="spacing">6</property>
                         <child>
-                          <object class="GtkCheckButton" id="show-labels">
-                            <property name="label" translatable="yes">Show button _labels</property>
+                          <object class="GtkCheckButton" id="show-generic-names">
+                            <property name="label" translatable="yes">Show generic application n_ames</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
+                            <property name="tooltip_text" translatable="yes">Select this option to show the generic application name in the menu, for example "File Manager" instead of "Thunar"</property>
                             <property name="use_underline">True</property>
                             <property name="draw_indicator">True</property>
                           </object>
@@ -48,8 +50,8 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkCheckButton" id="flat-buttons">
-                            <property name="label" translatable="yes">Show _flat buttons</property>
+                          <object class="GtkCheckButton" id="show-menu-icons">
+                            <property name="label" translatable="yes">Show ic_ons in menu</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
@@ -61,8 +63,8 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkCheckButton" id="show-handle">
-                            <property name="label" translatable="yes">Show _handle</property>
+                          <object class="GtkCheckButton" id="show-button-title">
+                            <property name="label" translatable="yes">_Show button title</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
@@ -74,15 +76,22 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkHBox" id="hbox2">
+                          <object class="GtkHBox" id="title-box">
                             <property name="visible">True</property>
                             <property name="spacing">12</property>
                             <child>
-                              <object class="GtkLabel" id="label5">
+                              <object class="GtkAlignment" id="alignment4">
                                 <property name="visible">True</property>
-                                <property name="label" translatable="yes">Sorting _order:</property>
-                                <property name="use_underline">True</property>
-                                <property name="mnemonic_widget">sort-order</property>
+                                <property name="left_padding">22</property>
+                                <child>
+                                  <object class="GtkLabel" id="label2">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">Button _title:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">button-title</property>
+                                  </object>
+                                </child>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -90,18 +99,12 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkComboBox" id="sort-order">
+                              <object class="GtkEntry" id="button-title">
                                 <property name="visible">True</property>
-                                <property name="model">sort-order-model</property>
-                                <child>
-                                  <object class="GtkCellRendererText" id="cellrenderertext1"/>
-                                  <attributes>
-                                    <attribute name="text">0</attribute>
-                                  </attributes>
-                                </child>
+                                <property name="can_focus">True</property>
+                                <property name="invisible_char">&#x2022;</property>
                               </object>
                               <packing>
-                                <property name="expand">False</property>
                                 <property name="position">1</property>
                               </packing>
                             </child>
@@ -110,51 +113,17 @@
                             <property name="position">3</property>
                           </packing>
                         </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Appearance</property>
-                    <attributes>
-                      <attribute name="weight" value="bold"/>
-                    </attributes>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="left_padding">12</property>
-                    <child>
-                      <object class="GtkVBox" id="vbox2">
-                        <property name="visible">True</property>
-                        <property name="border_width">6</property>
-                        <property name="orientation">vertical</property>
-                        <property name="spacing">6</property>
                         <child>
-                          <object class="GtkHBox" id="hbox1">
+                          <object class="GtkHBox" id="hbox3">
                             <property name="visible">True</property>
                             <property name="spacing">12</property>
                             <child>
                               <object class="GtkLabel" id="label4">
                                 <property name="visible">True</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Window _grouping:</property>
+                                <property name="label" translatable="yes">_Icon:</property>
                                 <property name="use_underline">True</property>
-                                <property name="mnemonic_widget">grouping</property>
+                                <property name="mnemonic_widget">icon-button</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -162,50 +131,29 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkComboBox" id="grouping">
+                              <object class="GtkAlignment" id="alignment2">
                                 <property name="visible">True</property>
-                                <property name="model">grouping-model</property>
+                                <property name="xalign">0</property>
+                                <property name="xscale">0</property>
+                                <property name="yscale">0</property>
                                 <child>
-                                  <object class="GtkCellRendererText" id="cellrenderertext2"/>
-                                  <attributes>
-                                    <attribute name="text">0</attribute>
-                                  </attributes>
+                                  <object class="GtkButton" id="icon-button">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                  </object>
                                 </child>
                               </object>
                               <packing>
-                                <property name="expand">False</property>
                                 <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="switch-workspace-on-unminimize">
-                            <property name="label" translatable="yes">Restore minimized windows to current _workspace</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="show-wireframes">
-                            <property name="label" translatable="yes">D_raw window frame when hovering a button</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
+                            <property name="position">4</property>
                           </packing>
                         </child>
                       </object>
@@ -213,9 +161,9 @@
                   </object>
                 </child>
                 <child type="label">
-                  <object class="GtkLabel" id="label3">
+                  <object class="GtkLabel" id="label1">
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">Behaviour</property>
+                    <property name="label" translatable="yes">Appearance</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
@@ -224,31 +172,32 @@
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="position">1</property>
+                <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkFrame" id="frame2">
+              <object class="GtkFrame" id="frame1">
                 <property name="visible">True</property>
                 <property name="label_xalign">0</property>
                 <property name="shadow_type">none</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment2">
+                  <object class="GtkAlignment" id="alignment1">
                     <property name="visible">True</property>
                     <property name="left_padding">12</property>
                     <child>
-                      <object class="GtkVBox" id="vbox4">
+                      <object class="GtkVBox" id="vbox2">
                         <property name="visible">True</property>
                         <property name="border_width">6</property>
                         <property name="orientation">vertical</property>
                         <property name="spacing">6</property>
                         <child>
-                          <object class="GtkCheckButton" id="include-all-workspaces">
-                            <property name="label" translatable="yes">Show windows from _all workspaces</property>
+                          <object class="GtkRadioButton" id="use-default-file">
+                            <property name="label" translatable="yes">Use _default menu file</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
                             <property name="use_underline">True</property>
+                            <property name="active">True</property>
                             <property name="draw_indicator">True</property>
                           </object>
                           <packing>
@@ -256,26 +205,63 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkCheckButton" id="show-only-minimized">
-                            <property name="label" translatable="yes">Show only _minimized windows</property>
+                          <object class="GtkRadioButton" id="use-custom-file">
+                            <property name="label" translatable="yes">Use c_ustom menu file</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
                             <property name="use_underline">True</property>
+                            <property name="active">True</property>
                             <property name="draw_indicator">True</property>
+                            <property name="group">use-default-file</property>
                           </object>
                           <packing>
                             <property name="position">1</property>
                           </packing>
                         </child>
+                        <child>
+                          <object class="GtkAlignment" id="alignment5">
+                            <property name="visible">True</property>
+                            <property name="left_padding">22</property>
+                            <child>
+                              <object class="GtkHBox" id="custom-box">
+                                <property name="visible">True</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <object class="GtkLabel" id="label5">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">Menu _file:</property>
+                                    <property name="use_underline">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkFileChooserButton" id="custom-file">
+                                    <property name="visible">True</property>
+                                    <property name="title" translatable="yes">Select A Menu File</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
                       </object>
                     </child>
                   </object>
                 </child>
                 <child type="label">
-                  <object class="GtkLabel" id="label2">
+                  <object class="GtkLabel" id="label3">
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">Filtering</property>
+                    <property name="label" translatable="yes">Menu File</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
@@ -283,12 +269,12 @@
                 </child>
               </object>
               <packing>
-                <property name="position">2</property>
+                <property name="expand">False</property>
+                <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
             <property name="position">1</property>
           </packing>
         </child>
@@ -323,41 +309,10 @@
       <action-widget response="0">close-button</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkListStore" id="grouping-model">
-    <columns>
-      <!-- column-name title -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Never</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">When space is limited</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Always</col>
-      </row>
-    </data>
-  </object>
-  <object class="GtkListStore" id="sort-order-model">
-    <columns>
-      <!-- column-name title -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Timestamp</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Group title and timestamp</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Window title</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Group title and window title</col>
-      </row>
-    </data>
+  <object class="GtkSizeGroup" id="sizegroup1">
+    <widgets>
+      <widget name="label4"/>
+      <widget name="alignment4"/>
+    </widgets>
   </object>
 </interface>
diff --git a/plugins/applicationsmenu/applicationsmenu.c b/plugins/applicationsmenu/applicationsmenu.c
new file mode 100644
index 0000000..7f7dac7
--- /dev/null
+++ b/plugins/applicationsmenu/applicationsmenu.c
@@ -0,0 +1,832 @@
+/*
+ * Copyright (C) 2010 Nick Schermer <nick at xfce.org>
+ *
+ * This library 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 library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <exo/exo.h>
+#include <garcon/garcon.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include <common/panel-xfconf.h>
+#include <common/panel-builder.h>
+#include <common/panel-private.h>
+
+#include "applicationsmenu.h"
+#include "applicationsmenu-dialog_ui.h"
+
+
+
+#define DEFAULT_ICON_NAME "xfce4-panel-menu"
+#define DEFAULT_TITLE     _("Xfce Menu")
+#define DEFAULT_ICON_SIZE (16)
+
+
+
+struct _ApplicationsMenuPluginClass
+{
+  XfcePanelPluginClass __parent__;
+};
+
+struct _ApplicationsMenuPlugin
+{
+  XfcePanelPlugin __parent__;
+
+  GtkWidget       *button;
+  GtkWidget       *box;
+  GtkWidget       *icon;
+  GtkWidget       *label;
+
+  guint            show_generic_names : 1;
+  guint            show_menu_icons : 1;
+  guint            show_button_title : 1;
+  gchar           *button_title;
+  gchar           *button_icon;
+  guint            custom_menu : 1;
+  gchar           *custom_menu_file;
+
+  /* temp item we store here when the
+   * properties dialog is opened */
+  GtkWidget       *dialog_icon;
+};
+
+enum
+{
+  PROP_0,
+  PROP_SHOW_GENERIC_NAMES,
+  PROP_SHOW_MENU_ICONS,
+  PROP_SHOW_BUTTON_TITLE,
+  PROP_BUTTON_TITLE,
+  PROP_BUTTON_ICON,
+  PROP_CUSTOM_MENU,
+  PROP_CUSTOM_MENU_FILE
+};
+
+
+
+static void      applications_menu_plugin_get_property         (GObject                *object,
+                                                                guint                   prop_id,
+                                                                GValue                 *value,
+                                                                GParamSpec             *pspec);
+static void      applications_menu_plugin_set_property         (GObject                *object,
+                                                                guint                   prop_id,
+                                                                const GValue           *value,
+                                                                GParamSpec             *pspec);
+static void      applications_menu_plugin_construct            (XfcePanelPlugin        *panel_plugin);
+static void      applications_menu_plugin_free_data            (XfcePanelPlugin        *panel_plugin);
+static gboolean  applications_menu_plugin_size_changed         (XfcePanelPlugin        *panel_plugin,
+                                                                gint                    size);
+static void      applications_menu_plugin_orientation_changed  (XfcePanelPlugin        *panel_plugin,
+                                                                GtkOrientation          orientation);
+static void      applications_menu_plugin_configure_plugin     (XfcePanelPlugin        *panel_plugin);
+static gboolean  applications_menu_plugin_remote_event         (XfcePanelPlugin        *panel_plugin,
+                                                                const gchar            *name,
+                                                                const GValue           *value);
+static void      applications_menu_plugin_menu                 (GtkWidget              *button,
+                                                                ApplicationsMenuPlugin *plugin);
+
+
+
+/* define the plugin */
+XFCE_PANEL_DEFINE_PLUGIN (ApplicationsMenuPlugin, applications_menu_plugin)
+
+
+
+static GtkIconSize menu_icon_size = GTK_ICON_SIZE_INVALID;
+
+
+
+static void
+applications_menu_plugin_class_init (ApplicationsMenuPluginClass *klass)
+{
+  XfcePanelPluginClass *plugin_class;
+  GObjectClass         *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->get_property = applications_menu_plugin_get_property;
+  gobject_class->set_property = applications_menu_plugin_set_property;
+
+  plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
+  plugin_class->construct = applications_menu_plugin_construct;
+  plugin_class->free_data = applications_menu_plugin_free_data;
+  plugin_class->size_changed = applications_menu_plugin_size_changed;
+  plugin_class->orientation_changed = applications_menu_plugin_orientation_changed;
+  plugin_class->configure_plugin = applications_menu_plugin_configure_plugin;
+  plugin_class->remote_event = applications_menu_plugin_remote_event;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_SHOW_GENERIC_NAMES,
+                                   g_param_spec_boolean ("show-generic-names",
+                                                         NULL, NULL,
+                                                         TRUE,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_SHOW_MENU_ICONS,
+                                   g_param_spec_boolean ("show-menu-icons",
+                                                         NULL, NULL,
+                                                         TRUE,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_SHOW_BUTTON_TITLE,
+                                   g_param_spec_boolean ("show-button-title",
+                                                         NULL, NULL,
+                                                         TRUE,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_BUTTON_TITLE,
+                                   g_param_spec_string ("button-title",
+                                                        NULL, NULL,
+                                                        DEFAULT_TITLE,
+                                                        EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_BUTTON_ICON,
+                                   g_param_spec_string ("button-icon",
+                                                        NULL, NULL,
+                                                        DEFAULT_ICON_NAME,
+                                                        EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_CUSTOM_MENU,
+                                   g_param_spec_boolean ("custom-menu",
+                                                         NULL, NULL,
+                                                         FALSE,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_CUSTOM_MENU_FILE,
+                                   g_param_spec_string ("custom-menu-file",
+                                                        NULL, NULL,
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  menu_icon_size = gtk_icon_size_from_name ("panel-application-menu");
+  if (menu_icon_size == GTK_ICON_SIZE_INVALID)
+    menu_icon_size = gtk_icon_size_register ("panel-application-menu",
+                                             DEFAULT_ICON_SIZE,
+                                             DEFAULT_ICON_SIZE);
+}
+
+
+
+static void
+applications_menu_plugin_init (ApplicationsMenuPlugin *plugin)
+{
+  plugin->show_menu_icons = TRUE;
+  plugin->show_button_title = TRUE;
+
+  garcon_set_environment ("XFCE");
+
+  plugin->button = xfce_panel_create_toggle_button ();
+  xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button);
+  gtk_container_add (GTK_CONTAINER (plugin), plugin->button);
+  gtk_widget_set_name (plugin->button, "applicationmenu-button");
+  gtk_button_set_relief (GTK_BUTTON (plugin->button), GTK_RELIEF_NONE);
+  g_signal_connect (G_OBJECT (plugin->button), "toggled",
+      G_CALLBACK (applications_menu_plugin_menu), plugin);
+
+  plugin->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 1);
+  gtk_container_add (GTK_CONTAINER (plugin->button), plugin->box);
+  gtk_widget_show (plugin->box);
+
+  plugin->icon = xfce_panel_image_new_from_source (DEFAULT_ICON_NAME);
+  gtk_box_pack_start (GTK_BOX (plugin->box), plugin->icon, FALSE, FALSE, 0);
+  gtk_widget_show (plugin->icon);
+
+  plugin->label = gtk_label_new (DEFAULT_TITLE);
+  gtk_box_pack_start (GTK_BOX (plugin->box), plugin->label, FALSE, FALSE, 0);
+  gtk_widget_show (plugin->label);
+}
+
+
+
+static void
+applications_menu_plugin_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_SHOW_GENERIC_NAMES:
+      g_value_set_boolean (value, plugin->show_generic_names);
+      break;
+
+    case PROP_SHOW_MENU_ICONS:
+      g_value_set_boolean (value, plugin->show_menu_icons);
+      break;
+
+    case PROP_SHOW_BUTTON_TITLE:
+      g_value_set_boolean (value, plugin->show_button_title);
+      break;
+
+    case PROP_BUTTON_TITLE:
+      g_value_set_string (value, exo_str_is_empty (plugin->button_title) ?
+          DEFAULT_TITLE : plugin->button_title);
+      break;
+
+    case PROP_BUTTON_ICON:
+      g_value_set_string (value, exo_str_is_empty (plugin->button_icon) ?
+          DEFAULT_ICON_NAME : plugin->button_icon);
+      break;
+
+    case PROP_CUSTOM_MENU:
+      g_value_set_boolean (value, plugin->custom_menu);
+      break;
+
+    case PROP_CUSTOM_MENU_FILE:
+      g_value_set_string (value, plugin->custom_menu_file);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+applications_menu_plugin_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_SHOW_GENERIC_NAMES:
+      plugin->show_generic_names = g_value_get_boolean (value);
+      break;
+
+    case PROP_SHOW_MENU_ICONS:
+      plugin->show_menu_icons = g_value_get_boolean (value);
+      break;
+
+    case PROP_SHOW_BUTTON_TITLE:
+      plugin->show_button_title = g_value_get_boolean (value);
+      if (plugin->show_button_title)
+        gtk_widget_show (plugin->label);
+      else
+        gtk_widget_hide (plugin->label);
+      applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
+          xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
+      break;
+
+    case PROP_BUTTON_TITLE:
+      g_free (plugin->button_title);
+      plugin->button_title = g_value_dup_string (value);
+      gtk_label_set_text (GTK_LABEL (plugin->label),
+          plugin->button_title != NULL ? plugin->button_title : "");
+      break;
+
+    case PROP_BUTTON_ICON:
+      g_free (plugin->button_icon);
+      plugin->button_icon = g_value_dup_string (value);
+      xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (plugin->icon),
+          exo_str_is_empty (plugin->button_icon) ? DEFAULT_ICON_NAME : plugin->button_icon);
+      break;
+
+    case PROP_CUSTOM_MENU:
+      plugin->custom_menu = g_value_get_boolean (value);
+      break;
+
+    case PROP_CUSTOM_MENU_FILE:
+      g_free (plugin->custom_menu_file);
+      plugin->custom_menu_file = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+applications_menu_plugin_construct (XfcePanelPlugin *panel_plugin)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
+  const PanelProperty  properties[] =
+  {
+    { "show-generic-names", G_TYPE_BOOLEAN },
+    { "show-menu-icons", G_TYPE_BOOLEAN },
+    { "show-button-title", G_TYPE_BOOLEAN },
+    { "button-title", G_TYPE_STRING },
+    { "button-icon", G_TYPE_STRING },
+    { "custom-menu", G_TYPE_BOOLEAN },
+    { "custom-menu-file", G_TYPE_STRING },
+    { NULL }
+  };
+
+  xfce_panel_plugin_menu_show_configure (XFCE_PANEL_PLUGIN (plugin));
+
+  /* bind all properties */
+  panel_properties_bind (NULL, G_OBJECT (plugin),
+                         xfce_panel_plugin_get_property_base (panel_plugin),
+                         properties, FALSE);
+
+  gtk_widget_show (plugin->button);
+}
+
+
+
+static void
+applications_menu_plugin_free_data (XfcePanelPlugin *panel_plugin)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
+
+  g_free (plugin->button_title);
+  g_free (plugin->button_icon);
+  g_free (plugin->custom_menu_file);
+}
+
+
+
+static gboolean
+applications_menu_plugin_size_changed (XfcePanelPlugin *panel_plugin,
+                                       gint             size)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
+  gint                    icon_size;
+  GtkStyle               *style;
+
+  gtk_box_set_child_packing (GTK_BOX (plugin->box), plugin->icon,
+                             !plugin->show_button_title, !plugin->show_button_title,
+                             0, GTK_PACK_START);
+
+  if (!plugin->show_button_title)
+    {
+      xfce_panel_image_set_size (XFCE_PANEL_IMAGE (plugin->icon), -1);
+      gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), size, size);
+    }
+  else
+    {
+      style = gtk_widget_get_style (plugin->button);
+      icon_size = size - 2 * MAX (style->xthickness, style->ythickness);
+      xfce_panel_image_set_size (XFCE_PANEL_IMAGE (plugin->icon), icon_size);
+      gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), -1, -1);
+    }
+
+  return TRUE;
+}
+
+
+
+static void
+applications_menu_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
+                                              GtkOrientation   orientation)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
+
+  xfce_hvbox_set_orientation (XFCE_HVBOX (plugin->box), orientation);
+  gtk_label_set_angle (GTK_LABEL (plugin->label), orientation == GTK_ORIENTATION_HORIZONTAL ? 0 : 270);
+}
+
+
+
+static void
+applications_menu_plugin_configure_plugin_file_set (GtkFileChooserButton   *button,
+                                                    ApplicationsMenuPlugin *plugin)
+{
+  gchar *filename;
+
+  panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
+  panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
+
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button));
+  g_object_set (G_OBJECT (plugin), "custom-menu-file", filename, NULL);
+  g_free (filename);
+}
+
+
+
+static void
+applications_menu_plugin_configure_plugin_icon_chooser (GtkWidget           *button,
+                                                        ApplicationsMenuPlugin *plugin)
+{
+  GtkWidget *chooser;
+  gchar     *icon;
+
+  panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
+  panel_return_if_fail (XFCE_IS_PANEL_IMAGE (plugin->dialog_icon));
+
+  chooser = exo_icon_chooser_dialog_new (_("Select An Icon"),
+                                         GTK_WINDOW (gtk_widget_get_toplevel (button)),
+                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                         GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                         NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (chooser),
+                                           GTK_RESPONSE_ACCEPT,
+                                           GTK_RESPONSE_CANCEL, -1);
+
+  if (!exo_str_is_empty (plugin->button_icon))
+    exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), plugin->button_icon);
+
+  if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
+    {
+      icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser));
+      g_object_set (G_OBJECT (plugin), "button-icon", icon, NULL);
+      xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (plugin->dialog_icon), icon);
+      g_free (icon);
+    }
+
+  gtk_widget_destroy (chooser);
+}
+
+
+
+static void
+applications_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
+  GtkBuilder             *builder;
+  GObject                *dialog, *object, *object2;
+  const gchar            *button_icon = plugin->button_icon;
+
+  if (exo_str_is_empty (button_icon))
+    button_icon = DEFAULT_ICON_NAME;
+
+  /* setup the dialog */
+  PANEL_BUILDER_LINK_4UI
+  builder = panel_builder_new (panel_plugin, applicationsmenu_dialog_ui,
+                               applicationsmenu_dialog_ui_length, &dialog);
+  if (G_UNLIKELY (builder == NULL))
+    return;
+
+  object = gtk_builder_get_object (builder, "show-generic-names");
+  panel_return_if_fail (GTK_IS_CHECK_BUTTON (object));
+  exo_mutual_binding_new (G_OBJECT (plugin), "show-generic-names",
+                          G_OBJECT (object), "active");
+
+  object = gtk_builder_get_object (builder, "show-menu-icons");
+  panel_return_if_fail (GTK_IS_CHECK_BUTTON (object));
+  exo_mutual_binding_new (G_OBJECT (plugin), "show-menu-icons",
+                          G_OBJECT (object), "active");
+
+  object = gtk_builder_get_object (builder, "show-button-title");
+  panel_return_if_fail (GTK_IS_CHECK_BUTTON (object));
+  exo_mutual_binding_new (G_OBJECT (plugin), "show-button-title",
+                          G_OBJECT (object), "active");
+
+  object2 = gtk_builder_get_object (builder, "title-box");
+  panel_return_if_fail (GTK_IS_WIDGET (object2));
+  exo_binding_new (G_OBJECT (object), "active", G_OBJECT (object2), "sensitive");
+
+  object = gtk_builder_get_object (builder, "button-title");
+  panel_return_if_fail (GTK_IS_ENTRY (object));
+  exo_mutual_binding_new (G_OBJECT (plugin), "button-title",
+                          G_OBJECT (object), "text");
+
+  object = gtk_builder_get_object (builder, "icon-button");
+  panel_return_if_fail (GTK_IS_BUTTON (object));
+  g_signal_connect (G_OBJECT (object), "clicked",
+     G_CALLBACK (applications_menu_plugin_configure_plugin_icon_chooser), plugin);
+
+  plugin->dialog_icon = xfce_panel_image_new_from_source (button_icon);
+  xfce_panel_image_set_size (XFCE_PANEL_IMAGE (plugin->dialog_icon), 48);
+  gtk_container_add (GTK_CONTAINER (object), plugin->dialog_icon);
+  g_object_add_weak_pointer (G_OBJECT (plugin->dialog_icon), (gpointer) &plugin->dialog_icon);
+  gtk_widget_show (plugin->dialog_icon);
+
+  object = gtk_builder_get_object (builder, "use-custom-file");
+  panel_return_if_fail (GTK_IS_RADIO_BUTTON (object));
+  exo_mutual_binding_new (G_OBJECT (plugin), "custom-menu",
+                          G_OBJECT (object), "active");
+  object2 = gtk_builder_get_object (builder, "custom-box");
+  panel_return_if_fail (GTK_IS_WIDGET (object2));
+  exo_binding_new (G_OBJECT (object), "active", G_OBJECT (object2), "sensitive");
+
+  object = gtk_builder_get_object (builder, "custom-file");
+  panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (object));
+  if (!exo_str_is_empty (plugin->custom_menu_file))
+    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (object), plugin->custom_menu_file);
+  g_signal_connect (G_OBJECT (object), "file-set",
+     G_CALLBACK (applications_menu_plugin_configure_plugin_file_set), plugin);
+
+  gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+
+
+static gboolean
+applications_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin,
+                                    const gchar     *name,
+                                    const GValue    *value)
+{
+  ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
+
+  panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
+
+  if (strcmp (name, "popup") == 0
+      && GTK_WIDGET_VISIBLE (panel_plugin)
+      && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (plugin->button)))
+    {
+      /* show the menu */
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), TRUE);
+
+      /* don't popup another menu */
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
+static void
+applications_menu_plugin_menu_deactivate (GtkWidget *menu,
+                                          GtkWidget *button)
+{
+  panel_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+  panel_return_if_fail (GTK_IS_MENU (menu));
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+
+  /* delay destruction so we can handle the activate event first */
+  exo_gtk_object_destroy_later (GTK_OBJECT (menu));
+}
+
+
+static void
+applications_menu_plugin_append_quoted (GString     *string,
+                                        const gchar *unquoted)
+{
+  gchar *quoted;
+
+  quoted = g_shell_quote (unquoted);
+  g_string_append (string, quoted);
+  g_free (quoted);
+}
+
+
+
+static void
+applications_menu_plugin_menu_item_activate (GtkWidget      *mi,
+                                             GarconMenuItem *item)
+{
+  GString      *string;
+  const gchar  *command;
+  const gchar  *p;
+  const gchar  *tmp;
+  gchar       **argv;
+  gboolean      result = FALSE;
+  gchar        *uri;
+  GError       *error = NULL;
+
+  panel_return_if_fail (GTK_IS_WIDGET (mi));
+  panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
+
+  command = garcon_menu_item_get_command (item);
+  if (exo_str_is_empty (command))
+    return;
+
+  string = g_string_sized_new (100);
+
+  if (garcon_menu_item_requires_terminal (item))
+    g_string_append (string, "exo-open --launch TerminalEmulator ");
+
+  /* expand the field codes */
+  for (p = command; *p != '\0'; ++p)
+    {
+      if (G_UNLIKELY (p[0] == '%' && p[1] != '\0'))
+        {
+          switch (*++p)
+            {
+            case 'f': case 'F':
+            case 'u': case 'U':
+              /* TODO for dnd, not a regression, xfdesktop never had this */
+              break;
+
+            case 'i':
+              tmp = garcon_menu_item_get_icon_name (item);
+              if (!exo_str_is_empty (tmp))
+                {
+                  g_string_append (string, "--icon ");
+                  applications_menu_plugin_append_quoted (string, tmp);
+                }
+              break;
+
+            case 'c':
+              tmp = garcon_menu_item_get_name (item);
+              if (!exo_str_is_empty (tmp))
+                applications_menu_plugin_append_quoted (string, tmp);
+              break;
+
+            case 'k':
+              uri = garcon_menu_item_get_uri (item);
+              if (!exo_str_is_empty (uri))
+                applications_menu_plugin_append_quoted (string, uri);
+              g_free (uri);
+              break;
+
+            case '%':
+              g_string_append_c (string, '%');
+              break;
+            }
+        }
+      else
+        {
+          g_string_append_c (string, *p);
+        }
+    }
+
+  /* parse and spawn command */
+  if (g_shell_parse_argv (string->str, NULL, &argv, &error))
+    {
+      result = xfce_spawn_on_screen (gtk_widget_get_screen (mi),
+                                     garcon_menu_item_get_path (item),
+                                     argv, NULL, G_SPAWN_SEARCH_PATH,
+                                     garcon_menu_item_supports_startup_notification (item),
+                                     gtk_get_current_event_time (),
+                                     garcon_menu_item_get_icon_name (item),
+                                     &error);
+
+      g_strfreev (argv);
+    }
+
+  if (G_UNLIKELY (!result))
+    {
+      xfce_dialog_show_error (NULL, error, _("Failed to execute command \"%s\"."), command);
+      g_error_free (error);
+    }
+
+  g_string_free (string, TRUE);
+}
+
+
+
+static gboolean
+applications_menu_plugin_menu_add (GtkWidget              *gtk_menu,
+                                   GarconMenu             *menu,
+                                   ApplicationsMenuPlugin *plugin)
+{
+  GList       *elements, *li;
+  GtkWidget   *mi, *image;
+  const gchar *name, *icon_name;
+  GtkWidget   *submenu;
+  gboolean     has_children = FALSE;
+  gint         size = DEFAULT_ICON_SIZE, w, h;
+  const gchar *command;
+
+  panel_return_val_if_fail (GTK_IS_MENU (gtk_menu), FALSE);
+  panel_return_val_if_fail (GARCON_IS_MENU (menu), FALSE);
+  panel_return_val_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin), FALSE);
+
+  if (gtk_icon_size_lookup (menu_icon_size, &w, &h))
+    size = MIN (w, h);
+
+  elements = garcon_menu_get_elements (menu);
+  for (li = elements; li != NULL; li = li->next)
+    {
+      if (GARCON_IS_MENU_ITEM (li->data))
+        {
+          name = NULL;
+          if (plugin->show_generic_names)
+            name = garcon_menu_item_get_generic_name (li->data);
+          if (G_UNLIKELY (name == NULL))
+            name = garcon_menu_item_get_name (li->data);
+          if (G_UNLIKELY (name == NULL))
+            continue;
+
+          mi = gtk_image_menu_item_new_with_label (name);
+          gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi);
+
+          g_signal_connect_data (G_OBJECT (mi), "activate",
+              G_CALLBACK (applications_menu_plugin_menu_item_activate),
+              g_object_ref (li->data), (GClosureNotify) g_object_unref, 0);
+          gtk_widget_show (mi);
+
+          command = garcon_menu_item_get_command (li->data);
+          gtk_widget_set_sensitive (mi, !exo_str_is_empty (command));
+
+          if (plugin->show_menu_icons)
+            {
+              icon_name = garcon_menu_item_get_icon_name (li->data);
+              if (exo_str_is_empty (icon_name))
+                icon_name = "applications-other";
+
+              image = xfce_panel_image_new_from_source (icon_name);
+              xfce_panel_image_set_size (XFCE_PANEL_IMAGE (image), size);
+              gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+              gtk_widget_show (image);
+            }
+
+          has_children = TRUE;
+        }
+      else if (GARCON_IS_MENU_SEPARATOR (li->data))
+        {
+          mi = gtk_separator_menu_item_new ();
+          gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi);
+          gtk_widget_show (mi);
+        }
+      else if (GARCON_IS_MENU (li->data))
+        {
+          submenu = gtk_menu_new ();
+          if (applications_menu_plugin_menu_add (submenu, li->data, plugin))
+            {
+              name = garcon_menu_element_get_name (li->data);
+              mi = gtk_image_menu_item_new_with_label (name);
+              gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi);
+              gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), submenu);
+              gtk_widget_show (mi);
+
+              if (plugin->show_menu_icons)
+                {
+                  icon_name = garcon_menu_element_get_icon_name (li->data);
+                  if (exo_str_is_empty (icon_name))
+                    icon_name = "applications-other";
+
+                  image = xfce_panel_image_new_from_source (icon_name);
+                  xfce_panel_image_set_size (XFCE_PANEL_IMAGE (image), size);
+                  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+                  gtk_widget_show (image);
+                }
+
+              has_children = TRUE;
+            }
+          else
+            {
+              gtk_widget_destroy (submenu);
+            }
+        }
+    }
+
+  g_list_free (elements);
+
+  return has_children;
+}
+
+
+
+static void
+applications_menu_plugin_menu (GtkWidget              *button,
+                               ApplicationsMenuPlugin *plugin)
+{
+  GtkWidget  *gtk_menu, *mi;
+  GarconMenu *menu;
+  GError     *error = NULL;
+
+  panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
+  panel_return_if_fail (plugin->button == button);
+
+  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+    return;
+
+  if (G_UNLIKELY (plugin->custom_menu
+      && plugin->custom_menu_file != NULL))
+    menu = garcon_menu_new_for_path (plugin->custom_menu_file);
+  else
+    menu = garcon_menu_new_applications ();
+
+  if (garcon_menu_load (menu, NULL, &error))
+    {
+      gtk_menu = gtk_menu_new ();
+      g_signal_connect (G_OBJECT (gtk_menu), "deactivate",
+           G_CALLBACK (applications_menu_plugin_menu_deactivate), button);
+
+      if (!applications_menu_plugin_menu_add (gtk_menu, menu, plugin))
+        {
+          mi = gtk_menu_item_new_with_label (_("No applications found"));
+          gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi);
+          gtk_widget_set_sensitive (mi, FALSE);
+          gtk_widget_show (mi);
+        }
+
+      gtk_menu_popup (GTK_MENU (gtk_menu), NULL, NULL,
+                      xfce_panel_plugin_position_menu, plugin,
+                      1, gtk_get_current_event_time ());
+    }
+  else
+    {
+      xfce_dialog_show_error (NULL, error, _("Failed to load the applications menu"));
+      g_error_free (error);
+    }
+
+  g_object_unref (G_OBJECT (menu));
+}
diff --git a/plugins/applicationsmenu/applicationsmenu.desktop.in b/plugins/applicationsmenu/applicationsmenu.desktop.in
new file mode 100644
index 0000000..3be8ce7
--- /dev/null
+++ b/plugins/applicationsmenu/applicationsmenu.desktop.in
@@ -0,0 +1,8 @@
+[Xfce Panel]
+Type=X-XFCE-PanelPlugin
+Encoding=UTF-8
+_Name=Applications Menu
+_Comment=Show a menu containing categories of installed applications
+Icon=xfce4-panel-menu
+X-XFCE-Module=applicationsmenu
+X-XFCE-Internal=TRUE
diff --git a/plugins/applicationsmenu/applicationsmenu.h b/plugins/applicationsmenu/applicationsmenu.h
new file mode 100644
index 0000000..c6de2c1
--- /dev/null
+++ b/plugins/applicationsmenu/applicationsmenu.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __XFCE_APPLICATIONS_MENU_PLUGIN_H__
+#define __XFCE_APPLICATIONS_MENU_PLUGIN_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ApplicationsMenuPluginClass ApplicationsMenuPluginClass;
+typedef struct _ApplicationsMenuPlugin      ApplicationsMenuPlugin;
+
+#define XFCE_TYPE_APPLICATIONS_MENU_PLUGIN            (applications_menu_plugin_get_type ())
+#define XFCE_APPLICATIONS_MENU_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_APPLICATIONS_MENU_PLUGIN, ApplicationsMenuPlugin))
+#define XFCE_APPLICATIONS_MENU_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_APPLICATIONS_MENU_PLUGIN, ApplicationsMenuPluginClass))
+#define XFCE_IS_APPLICATIONS_MENU_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_APPLICATIONS_MENU_PLUGIN))
+#define XFCE_IS_APPLICATIONS_MENU_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_APPLICATIONS_MENU_PLUGIN))
+#define XFCE_APPLICATIONS_MENU_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_APPLICATIONS_MENU_PLUGIN, ApplicationsMenuPluginClass))
+
+GType applications_menu_plugin_get_type      (void) G_GNUC_CONST;
+
+void  applications_menu_plugin_register_type (XfcePanelTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* !__XFCE_APPLICATIONS_MENU_PLUGIN_H__ */
diff --git a/plugins/directorymenu/xfce4-popup-directorymenu.in b/plugins/applicationsmenu/xfce4-popup-applicationsmenu.in
similarity index 92%
copy from plugins/directorymenu/xfce4-popup-directorymenu.in
copy to plugins/applicationsmenu/xfce4-popup-applicationsmenu.in
index e1ab43c..be1c610 100644
--- a/plugins/directorymenu/xfce4-popup-directorymenu.in
+++ b/plugins/applicationsmenu/xfce4-popup-applicationsmenu.in
@@ -17,6 +17,6 @@
 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 #
 
-exec @bindir@/xfce4-panel --plugin-event=directorymenu:popup
+exec @bindir@/xfce4-panel --plugin-event=applicationsmenu:popup
 
 # vim:set ts=2 sw=2 et ai:
diff --git a/plugins/launcher/launcher.c b/plugins/launcher/launcher.c
index 20fc747..c1c507e 100644
--- a/plugins/launcher/launcher.c
+++ b/plugins/launcher/launcher.c
@@ -2235,7 +2235,7 @@ launcher_plugin_exec_parse (GarconMenuItem   *item,
 
   for (p = command; *p != '\0'; ++p)
     {
-      if (p[0] == '%' && p[1] != '\0')
+      if (G_UNLIKELY (p[0] == '%' && p[1] != '\0'))
         {
           switch (*++p)
             {
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9d44238..e1a2ce3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -57,6 +57,10 @@ plugins/actions/actions.c
 plugins/actions/actions.desktop.in
 plugins/actions/actions.h
 
+plugins/actions/applicationsmenu-dialog.glade
+plugins/actions/applicationsmenu.c
+plugins/actions/applicationsmenu.desktop.in
+
 plugins/clock/clock-analog.c
 plugins/clock/clock-analog.h
 plugins/clock/clock-binary.c



More information about the Xfce4-commits mailing list