From 518af23488b63ef8b3b57c2fabc195e38d685283 Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Sat, 10 May 2008 15:42:35 -0700
Subject: remove some unnecessary code

---
 src/Screen.cc | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/src/Screen.cc b/src/Screen.cc
index 1ae5fbc..c94891b 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -956,18 +956,7 @@ void BScreen::reconfigure() {
         }
     }
 
-    // if timestamp hasn't changed, then just a reconfigure is fine
-    // and that seems to happen somewhere else, anyway
-    if (fluxbox->menuTimestampsChanged()) {
-        // all bets are off, so just hide the menu and reset the filenames
-        fluxbox->clearMenuFilenames();
-        m_rootmenu->hide();
-        rereadMenu();
-    }
-
     //reconfigure menus
-    m_workspacemenu->reconfigure();
-    m_configmenu->reconfigure();
     // recreate window menu
     m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber()));
     m_windowmenu->setInternalMenu();
-- 
cgit v0.11.2


From a9fd0f5b26860c2227ac6169039332a00e65cc01 Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Sun, 11 May 2008 08:54:18 -0700
Subject: remove some more useless code

---
 src/FbCommands.cc |  2 +-
 src/fluxbox.cc    | 26 +++++---------------------
 src/fluxbox.hh    |  6 ++----
 3 files changed, 8 insertions(+), 26 deletions(-)

diff --git a/src/FbCommands.cc b/src/FbCommands.cc
index cb55469..91490d3 100644
--- a/src/FbCommands.cc
+++ b/src/FbCommands.cc
@@ -80,7 +80,7 @@ void showMenu(const BScreen &screen, FbTk::Menu &menu) {
             // we dont show the menu here because fluxbox
             // will bring up the rootmenu after the timed
             // reread of the menu
-            fb->rereadMenu(true);
+            fb->rereadMenu();
             return;
         }
     }
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 300d683..d765d3c 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -399,7 +399,7 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
     //XSynchronize(disp, False);
     sync(false);
 
-    m_reconfigure_wait = m_reread_menu_wait = false;
+    m_reconfigure_wait = false;
 
     m_resourcemanager.unlock();
     ungrab();
@@ -1484,28 +1484,15 @@ bool Fluxbox::menuTimestampsChanged() const {
     return false;
 }
 
-void Fluxbox::rereadMenu(bool show_after_reread) {
-    m_reread_menu_wait = true;
-    m_show_menu_after_reread = show_after_reread;
-    m_reconfig_timer.start();
-}
-
-
-void Fluxbox::real_rereadMenu() {
-
+void Fluxbox::rereadMenu() {
     clearMenuFilenames();
 
     for_each(m_screen_list.begin(),
              m_screen_list.end(),
              mem_fun(&BScreen::rereadMenu));
 
-    if(m_show_menu_after_reread) {
-
-        FbCommands::ShowRootMenuCmd showcmd;
-        showcmd.execute();
-
-        m_show_menu_after_reread = false;
-    }
+    FbCommands::ShowRootMenuCmd showcmd;
+    showcmd.execute();
 }
 
 void Fluxbox::saveMenuFilename(const char *filename) {
@@ -1546,10 +1533,7 @@ void Fluxbox::timed_reconfigure() {
     if (m_reconfigure_wait)
         real_reconfigure();
 
-    if (m_reread_menu_wait)
-        real_rereadMenu();
-
-    m_reconfigure_wait = m_reread_menu_wait = false;
+    m_reconfigure_wait = false;
 }
 
 void Fluxbox::revertFocus() {
diff --git a/src/fluxbox.hh b/src/fluxbox.hh
index d930ad1..e7c7556 100644
--- a/src/fluxbox.hh
+++ b/src/fluxbox.hh
@@ -149,7 +149,7 @@ public:
     void removeGroupSearch(Window win);
     void restart(const char *command = 0);
     void reconfigure();
-    void rereadMenu(bool show_after_reread = false);
+    void rereadMenu();
     /// reloads the menus if the timestamps changed
 
     /// handle any system signal sent to the application
@@ -201,7 +201,6 @@ private:
     std::string getRcFilename();
     void load_rc();
 
-    void real_rereadMenu();
     void real_reconfigure();
 
     void handleEvent(XEvent *xe);
@@ -251,7 +250,7 @@ private:
 
     Atom m_fluxbox_pid;
 
-    bool m_reconfigure_wait, m_reread_menu_wait;
+    bool m_reconfigure_wait;
     Time m_last_time;
     Window m_masked;
     std::string m_rc_file; ///< resource filename
@@ -279,7 +278,6 @@ private:
     bool m_starting;
     bool m_restarting;
     bool m_shutdown;
-    bool m_show_menu_after_reread;
     int m_server_grabs;
     int m_randr_event_type; ///< the type number of randr event
     int m_shape_eventbase; ///< event base for shape events
-- 
cgit v0.11.2


From 85d8ac754974aae0a513b585e4f1810007cb157c Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Sun, 11 May 2008 09:08:14 -0700
Subject: more useless code

---
 src/MenuCreator.cc | 4 ----
 src/Screen.cc      | 4 ----
 src/Screen.hh      | 4 ----
 3 files changed, 12 deletions(-)

diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc
index b420d3f..3f184f7 100644
--- a/src/MenuCreator.cc
+++ b/src/MenuCreator.cc
@@ -281,10 +281,6 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
         parseMenu(parse, *submenu, labelconvertor);
         submenu->updateMenu();
         menu.insert(str_label, submenu);
-        // save to screen list so we can delete it later
-        BScreen *screen = Fluxbox::instance()->findScreen(screen_number);
-        if (screen != 0)
-            screen->saveMenu(*submenu);
 
     } // end of submenu
     else if (str_key == "stylesdir" || str_key == "stylesmenu") {
diff --git a/src/Screen.cc b/src/Screen.cc
index c94891b..1708a69 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -1498,12 +1498,8 @@ void BScreen::initMenus() {
 void BScreen::initMenu() {
 
     if (m_rootmenu.get()) {
-        // since all menus in root is submenus in m_rootmenu
-        // just remove every item in m_rootmenu and then clear m_rootmenu_list
         while (m_rootmenu->numberOfItems())
             m_rootmenu->remove(0);
-        m_rootmenu_list.clear();
-
     } else
         m_rootmenu.reset(createMenu(""));
 
diff --git a/src/Screen.hh b/src/Screen.hh
index 02fcc0d..7758c90 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -276,8 +276,6 @@ public:
 
     void saveWorkspaces(int w) { *resource.workspaces = w;  }
 
-    void saveMenu(FbTk::Menu &menu) { m_rootmenu_list.push_back(&menu); }
-
     FbTk::ThemeProxy<FbWinFrameTheme> &focusedWinFrameTheme() { return *m_focused_windowtheme.get(); }
     const FbTk::ThemeProxy<FbWinFrameTheme> &focusedWinFrameTheme() const { return *m_focused_windowtheme.get(); }
     FbTk::ThemeProxy<FbWinFrameTheme> &unfocusedWinFrameTheme() { return *m_unfocused_windowtheme.get(); }
@@ -521,11 +519,9 @@ private:
 
     ExtraMenus m_extramenus;
 
-    typedef std::list<FbTk::Menu *> Rootmenus;
     typedef std::list<std::pair<FbTk::FbString, FbTk::Menu *> > Configmenus;
 
 
-    Rootmenus m_rootmenu_list;
     Configmenus m_configmenu_list;
     Icons m_icon_list;
 
-- 
cgit v0.11.2


From 72a45fae3c39323206e7d19913bb3ab17a691691 Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Sun, 11 May 2008 10:17:21 -0700
Subject: reuse some menu pointers instead of using delete/new

---
 src/FbCommands.cc  | 25 ++++++++++++-------------
 src/FbCommands.hh  |  7 ++++---
 src/MenuCreator.cc | 41 ++++++++++++-----------------------------
 src/MenuCreator.hh |  4 ++--
 src/Screen.cc      | 15 ++++++---------
 src/fluxbox.cc     |  3 ---
 6 files changed, 36 insertions(+), 59 deletions(-)

diff --git a/src/FbCommands.cc b/src/FbCommands.cc
index 91490d3..4eabae2 100644
--- a/src/FbCommands.cc
+++ b/src/FbCommands.cc
@@ -76,13 +76,8 @@ void showMenu(const BScreen &screen, FbTk::Menu &menu) {
     // special case for root menu
     if (&menu == &screen.rootMenu()) {
         Fluxbox* fb = Fluxbox::instance();
-        if(fb->menuTimestampsChanged()) {
-            // we dont show the menu here because fluxbox
-            // will bring up the rootmenu after the timed
-            // reread of the menu
+        if(fb->menuTimestampsChanged())
             fb->rereadMenu();
-            return;
-        }
     }
 
     Window root_ret; // not used
@@ -335,8 +330,8 @@ void ShowClientMenuCmd::execute() {
             m_list.push_back(static_cast<FluxboxWindow *>(*it));
     }
 
-    m_menu = new ClientMenu(*screen, m_list, 0);
-    ::showMenu(*screen, **m_menu);
+    m_menu.reset(new ClientMenu(*screen, m_list, 0));
+    ::showMenu(*screen, *m_menu.get());
 }
 
 REGISTER_COMMAND_WITH_ARGS(custommenu, FbCommands::ShowCustomMenuCmd, void);
@@ -347,11 +342,15 @@ void ShowCustomMenuCmd::execute() {
     BScreen *screen = Fluxbox::instance()->mouseScreen();
     if (screen == 0)
         return;
-    m_menu = MenuCreator::createFromFile(custom_menu_file,
-                                         screen->screenNumber());
-    if (!m_menu.get())
-        return;
-    ::showMenu(*screen, **m_menu);
+
+    if (m_menu.get()) {
+        m_menu->removeAll();
+        m_menu->setLabel("");
+    } else
+        m_menu.reset(screen->createMenu(""));
+
+    MenuCreator::createFromFile(custom_menu_file, *m_menu.get());
+    ::showMenu(*screen, *m_menu.get());
 }
 
 REGISTER_COMMAND(rootmenu, FbCommands::ShowRootMenuCmd, void);
diff --git a/src/FbCommands.hh b/src/FbCommands.hh
index f9c33af..3ad45c4 100644
--- a/src/FbCommands.hh
+++ b/src/FbCommands.hh
@@ -25,7 +25,8 @@
 #define FBCOMMANDS_HH
 
 #include "FbTk/Command.hh"
-#include "FbTk/RefCount.hh"
+
+#include <memory>
 
 #include "ClientMenu.hh"
 #include "ClientPattern.hh"
@@ -124,7 +125,7 @@ private:
     const int m_option;
     const ClientPattern m_pat;
     std::list<FluxboxWindow *> m_list;
-    FbTk::RefCount<ClientMenu> m_menu;
+    std::auto_ptr<ClientMenu> m_menu;
 };
 
 class ShowCustomMenuCmd: public FbTk::Command<void> {
@@ -133,7 +134,7 @@ public:
     void execute();
 private:
    std::string custom_menu_file;
-   FbTk::RefCount<FbTk::Menu> m_menu;    
+   std::auto_ptr<FbTk::Menu> m_menu;    
 };
 
 class ShowRootMenuCmd: public FbTk::Command<void> {
diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc
index 3f184f7..25f99ca 100644
--- a/src/MenuCreator.cc
+++ b/src/MenuCreator.cc
@@ -255,13 +255,13 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
                 if (FbTk::FileUtil::isRegularFile(thisfile.c_str()) &&
                         (filelist[file_index][0] != '.') &&
                         (thisfile[thisfile.length() - 1] != '~')) {
-                    MenuCreator::createFromFile(thisfile, menu);
+                    MenuCreator::createFromFile(thisfile, menu, false);
                 }
             }
 
         } else {
             // inject this file into the current menu
-            MenuCreator::createFromFile(newfile, menu);
+            MenuCreator::createFromFile(newfile, menu, false);
         }
 
         safe_counter--;
@@ -390,33 +390,8 @@ FbTk::Menu *MenuCreator::createMenu(const string &label, int screen_number) {
     return menu;
 }
 
-FbTk::Menu *MenuCreator::createFromFile(const string &filename, int screen_number) {
-    string real_filename = FbTk::StringUtil::expandFilename(filename);
-    Fluxbox::instance()->saveMenuFilename(real_filename.c_str());
-
-    FbMenuParser parser(real_filename);
-    if (!parser.isLoaded())
-        return 0;
-
-    startFile();
-    string label;
-    if (!getStart(parser, label, m_stringconvertor)) {
-        endFile();
-        return 0;
-    }
-
-    FbTk::Menu *menu = createMenu(label, screen_number);
-    if (menu != 0)
-        parseMenu(parser, *menu, m_stringconvertor);
-
-    endFile();
-
-    return menu;
-}
-
-
 bool MenuCreator::createFromFile(const string &filename,
-                                 FbTk::Menu &inject_into) {
+                                 FbTk::Menu &inject_into, bool begin) {
     string real_filename = FbTk::StringUtil::expandFilename(filename);
 
     FbMenuParser parser(real_filename);
@@ -424,6 +399,14 @@ bool MenuCreator::createFromFile(const string &filename,
         return false;
 
     startFile();
+    if (begin) {
+        string label;
+        if (!getStart(parser, label, m_stringconvertor)) {
+            endFile();
+            return false;
+        }
+        inject_into.setLabel(label);
+    }
 
     // save menu filename, so we can check if it changes
     Fluxbox::instance()->saveMenuFilename(real_filename.c_str());
@@ -467,7 +450,7 @@ FbTk::Menu *MenuCreator::createMenuType(const string &type, int screen_num) {
     } else if (type == "workspacemenu") {
         return new WorkspaceMenu(*screen);
     } else if (type == "windowmenu") {
-        FbTk::Menu *menu = screen->createMenu("");
+        FbTk::Menu *menu = createMenu("", screen_num);
 
         menu->disableTitle(); // not titlebar
         if (screen->windowMenuFilename().empty() ||
diff --git a/src/MenuCreator.hh b/src/MenuCreator.hh
index 4494dc7..660d097 100644
--- a/src/MenuCreator.hh
+++ b/src/MenuCreator.hh
@@ -36,9 +36,9 @@ class FluxboxWindow;
 class MenuCreator {
 public:
     static FbTk::Menu *createMenu(const std::string &label, int screen_num);
-    static FbTk::Menu *createFromFile(const std::string &filename, int screen_num);
     static FbTk::Menu *createMenuType(const std::string &label, int screen_num);
-    static bool createFromFile(const std::string &filename, FbTk::Menu &inject_into);
+    static bool createFromFile(const std::string &filename,
+                               FbTk::Menu &inject_into, bool begin = true);
     static bool createWindowMenuFromFile(const std::string &filename, FbTk::Menu &inject_into);
     static bool createWindowMenuItem(const std::string &type, const std::string &label, 
                                      FbTk::Menu &inject_into);
diff --git a/src/Screen.cc b/src/Screen.cc
index 1708a69..8b00186 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -1498,21 +1498,18 @@ void BScreen::initMenus() {
 void BScreen::initMenu() {
 
     if (m_rootmenu.get()) {
-        while (m_rootmenu->numberOfItems())
-            m_rootmenu->remove(0);
+        m_rootmenu->removeAll();
+        m_rootmenu->setLabel("");
     } else
         m_rootmenu.reset(createMenu(""));
 
     Fluxbox * const fb = Fluxbox::instance();
-    if (!fb->getMenuFilename().empty()) {
-        m_rootmenu.reset(MenuCreator::createFromFile(fb->getMenuFilename(),
-                                                     screenNumber()));
-
-    }
+    if (!fb->getMenuFilename().empty())
+        MenuCreator::createFromFile(fb->getMenuFilename(), *m_rootmenu);
 
-    if (m_rootmenu.get() == 0 || m_rootmenu->numberOfItems() == 0) {
+    if (m_rootmenu->numberOfItems() == 0) {
         _FB_USES_NLS;
-        m_rootmenu.reset(createMenu(_FB_XTEXT(Menu, DefaultRootMenu, "Fluxbox default menu", "Title of fallback root menu")));
+        m_rootmenu->setLabel(_FB_XTEXT(Menu, DefaultRootMenu, "Fluxbox default menu", "Title of fallback root menu"));
         FbTk::RefCount<FbTk::Command<void> > restart_fb(FbTk::CommandParser<void>::instance().parse("restart"));
         FbTk::RefCount<FbTk::Command<void> > exit_fb(FbTk::CommandParser<void>::instance().parse("exit"));
         FbTk::RefCount<FbTk::Command<void> > execute_xterm(FbTk::CommandParser<void>::instance().parse("exec xterm"));
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index d765d3c..7d774cc 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -1490,9 +1490,6 @@ void Fluxbox::rereadMenu() {
     for_each(m_screen_list.begin(),
              m_screen_list.end(),
              mem_fun(&BScreen::rereadMenu));
-
-    FbCommands::ShowRootMenuCmd showcmd;
-    showcmd.execute();
 }
 
 void Fluxbox::saveMenuFilename(const char *filename) {
-- 
cgit v0.11.2


From 93b0c5322a7482d83e38657b36e9814f8415e47b Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Sun, 11 May 2008 17:22:40 -0700
Subject: refactor menu reloading, added FbTk::AutoReloadHelper

---
 src/FbCommands.cc            |  10 ++--
 src/FbMenu.hh                |   7 +++
 src/FbTk/AutoReloadHelper.cc |  66 +++++++++++++++++++++++++
 src/FbTk/AutoReloadHelper.hh |  54 +++++++++++++++++++++
 src/FbTk/Makefile.am         |   1 +
 src/MenuCreator.cc           | 113 ++++++++++++++++++++-----------------------
 src/MenuCreator.hh           |  14 ++++--
 src/Screen.cc                |  85 ++++++++++++++++++++------------
 src/Screen.hh                |  27 ++++++-----
 src/fluxbox.cc               |  59 ----------------------
 src/fluxbox.hh               |  15 ------
 11 files changed, 263 insertions(+), 188 deletions(-)
 create mode 100644 src/FbTk/AutoReloadHelper.cc
 create mode 100644 src/FbTk/AutoReloadHelper.hh

diff --git a/src/FbCommands.cc b/src/FbCommands.cc
index 4eabae2..3a09b69 100644
--- a/src/FbCommands.cc
+++ b/src/FbCommands.cc
@@ -73,11 +73,11 @@ namespace {
 
 void showMenu(const BScreen &screen, FbTk::Menu &menu) {
 
-    // special case for root menu
-    if (&menu == &screen.rootMenu()) {
-        Fluxbox* fb = Fluxbox::instance();
-        if(fb->menuTimestampsChanged())
-            fb->rereadMenu();
+    // check if menu has changed
+    if (typeid(menu) == typeid(FbMenu)) {
+        FbMenu *fbmenu = static_cast<FbMenu *>(&menu);
+        if (fbmenu->reloadHelper())
+            fbmenu->reloadHelper()->checkReload();
     }
 
     Window root_ret; // not used
diff --git a/src/FbMenu.hh b/src/FbMenu.hh
index b9c4654..11ed3c3 100644
--- a/src/FbMenu.hh
+++ b/src/FbMenu.hh
@@ -22,8 +22,11 @@
 #ifndef FBMENU_HH
 #define FBMENU_HH
 
+#include <memory>
+
 #include "FbTk/Menu.hh"
 #include "FbTk/XLayerItem.hh"
+#include "FbTk/AutoReloadHelper.hh"
 
 class FluxboxWindow;
 
@@ -44,11 +47,15 @@ public:
     void buttonReleaseEvent(XButtonEvent &be);
     void keyPressEvent(XKeyEvent &ke);
 
+    void setReloadHelper(FbTk::AutoReloadHelper *helper) { m_reloader.reset(helper); }
+    FbTk::AutoReloadHelper *reloadHelper() { return m_reloader.get(); }
+
     static void setWindow(FluxboxWindow *win) { s_window = win; }
     static FluxboxWindow *window() { return s_window; }
 
 private:
     FbTk::XLayerItem m_layeritem;
+    std::auto_ptr<FbTk::AutoReloadHelper> m_reloader;
     static FluxboxWindow *s_window;
 };
 
diff --git a/src/FbTk/AutoReloadHelper.cc b/src/FbTk/AutoReloadHelper.cc
new file mode 100644
index 0000000..e3c1d59
--- /dev/null
+++ b/src/FbTk/AutoReloadHelper.cc
@@ -0,0 +1,66 @@
+// AutoReloadHelper.cc
+// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#include "AutoReloadHelper.hh"
+
+#include "FileUtil.hh"
+#include "StringUtil.hh"
+
+namespace FbTk {
+
+void AutoReloadHelper::checkReload() {
+    if (!m_reload_cmd.get())
+        return;
+    TimestampMap::const_iterator it = m_timestamps.begin();
+    TimestampMap::const_iterator it_end = m_timestamps.end();
+    for (; it != it_end; ++it) {
+        if (FileUtil::getLastStatusChangeTimestamp(it->first.c_str()) !=
+            it->second) {
+            reload();
+            return;
+        }
+    }
+}
+
+void AutoReloadHelper::setMainFile(std::string file) {
+    file = StringUtil::expandFilename(file);
+    if (file == m_main_file)
+        return;
+    m_main_file = file;
+    reload();
+}
+
+void AutoReloadHelper::addFile(std::string file) {
+    if (file.empty())
+        return;
+    file = StringUtil::expandFilename(file);
+    m_timestamps[file] = FileUtil::getLastStatusChangeTimestamp(file.c_str());
+}
+
+void AutoReloadHelper::reload() {
+    if (!m_reload_cmd.get())
+        return;
+    m_timestamps.clear();
+    addFile(m_main_file);
+    m_reload_cmd->execute();
+}
+
+} // end namespace FbTk
diff --git a/src/FbTk/AutoReloadHelper.hh b/src/FbTk/AutoReloadHelper.hh
new file mode 100644
index 0000000..36be8f1
--- /dev/null
+++ b/src/FbTk/AutoReloadHelper.hh
@@ -0,0 +1,54 @@
+// AutoReloadHelper.hh
+// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef AUTORELOADHELPER_HH
+#define AUTORELOADHELPER_HH
+
+#include <map>
+#include <string>
+#include <sys/types.h>
+
+#include "Command.hh"
+#include "RefCount.hh"
+
+namespace FbTk {
+
+class AutoReloadHelper {
+public:
+
+    void setMainFile(std::string filename);
+    void addFile(std::string filename);
+    void setReloadCmd(RefCount<Command<void> > cmd) { m_reload_cmd = cmd; }
+
+    void checkReload();
+    void reload();
+
+private:
+    RefCount<Command<void> > m_reload_cmd;
+    std::string m_main_file;
+
+    typedef std::map<std::string, time_t> TimestampMap;
+    TimestampMap m_timestamps;
+};
+
+} // end namespace FbTk
+
+#endif // AUTORELOADHELPER_HH
diff --git a/src/FbTk/Makefile.am b/src/FbTk/Makefile.am
index fcf0304..f830e4a 100644
--- a/src/FbTk/Makefile.am
+++ b/src/FbTk/Makefile.am
@@ -45,6 +45,7 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \
 	RegExp.hh RegExp.cc \
 	FbString.hh FbString.cc \
 	Subject.hh Subject.cc Observer.hh Observer.cc SimpleObserver.hh \
+	AutoReloadHelper.hh AutoReloadHelper.cc \
 	Transparent.hh Transparent.cc \
 	FbPixmap.hh FbPixmap.cc \
 	FbDrawable.hh FbDrawable.cc \
diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc
index 25f99ca..1af5482 100644
--- a/src/MenuCreator.cc
+++ b/src/MenuCreator.cc
@@ -59,6 +59,7 @@ using std::string;
 using std::vector;
 using std::list;
 using std::less;
+using FbTk::AutoReloadHelper;
 
 list<string> MenuCreator::encoding_stack;
 list<size_t> MenuCreator::stacksize_stack;
@@ -68,13 +69,16 @@ FbTk::StringConvertor MenuCreator::m_stringconvertor(FbTk::StringConvertor::ToFb
 namespace {
 
 void createStyleMenu(FbTk::Menu &parent, const string &label,
-                            const string &directory) {
+                     AutoReloadHelper *reloader, const string &directory) {
     // perform shell style ~ home directory expansion
     string stylesdir(FbTk::StringUtil::expandFilename(directory));
 
     if (!FbTk::FileUtil::isDirectory(stylesdir.c_str()))
         return;
 
+    if (reloader)
+        reloader->addFile(stylesdir);
+
     FbTk::Directory dir(stylesdir.c_str());
 
     // create a vector of all the filenames in the directory
@@ -99,18 +103,21 @@ void createStyleMenu(FbTk::Menu &parent, const string &label,
     }
     // update menu graphics
     parent.updateMenu();
-    Fluxbox::instance()->saveMenuFilename(stylesdir.c_str());
 
 }
 
 void createRootCmdMenu(FbTk::Menu &parent, const string &label,
-                                const string &directory, const string &cmd) {
+                       const string &directory, AutoReloadHelper *reloader,
+                       const string &cmd) {
     // perform shell style ~ home directory expansion
     string rootcmddir(FbTk::StringUtil::expandFilename(directory));
 
     if (!FbTk::FileUtil::isDirectory(rootcmddir.c_str()))
         return;
 
+    if (reloader)
+        reloader->addFile(rootcmddir);
+
     FbTk::Directory dir(rootcmddir.c_str());
 
     // create a vector of all the filenames in the directory
@@ -134,7 +141,6 @@ void createRootCmdMenu(FbTk::Menu &parent, const string &label,
     }
     // update menu graphics
     parent.updateMenu();
-    Fluxbox::instance()->saveMenuFilename(rootcmddir.c_str());
 
 }
 
@@ -172,20 +178,26 @@ public:
 
 };
 
-void translateMenuItem(FbTk::Parser &parse, ParseItem &item, FbTk::StringConvertor &labelconvertor);
+void translateMenuItem(FbTk::Parser &parse, ParseItem &item,
+                       FbTk::StringConvertor &labelconvertor,
+                       AutoReloadHelper *reloader);
 
 
-void parseMenu(FbTk::Parser &pars, FbTk::Menu &menu, FbTk::StringConvertor &label_convertor) {
+void parseMenu(FbTk::Parser &pars, FbTk::Menu &menu,
+               FbTk::StringConvertor &label_convertor,
+               AutoReloadHelper *reloader) {
     ParseItem pitem(&menu);
     while (!pars.eof()) {
         pitem.load(pars, label_convertor);
         if (pitem.key() == "end")
             return;
-        translateMenuItem(pars, pitem, label_convertor);
+        translateMenuItem(pars, pitem, label_convertor, reloader);
     }
 }
 
-void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConvertor &labelconvertor) {
+void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem,
+                       FbTk::StringConvertor &labelconvertor,
+                       AutoReloadHelper *reloader) {
     if (pitem.menu() == 0)
         throw string("translateMenuItem: We must have a menu in ParseItem!");
 
@@ -255,13 +267,13 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
                 if (FbTk::FileUtil::isRegularFile(thisfile.c_str()) &&
                         (filelist[file_index][0] != '.') &&
                         (thisfile[thisfile.length() - 1] != '~')) {
-                    MenuCreator::createFromFile(thisfile, menu, false);
+                    MenuCreator::createFromFile(thisfile, menu, reloader, false);
                 }
             }
 
         } else {
             // inject this file into the current menu
-            MenuCreator::createFromFile(newfile, menu, false);
+            MenuCreator::createFromFile(newfile, menu, reloader, false);
         }
 
         safe_counter--;
@@ -278,22 +290,22 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
         else
             submenu->setLabel(str_label);
 
-        parseMenu(parse, *submenu, labelconvertor);
+        parseMenu(parse, *submenu, labelconvertor, reloader);
         submenu->updateMenu();
         menu.insert(str_label, submenu);
 
     } // end of submenu
     else if (str_key == "stylesdir" || str_key == "stylesmenu") {
-        createStyleMenu(menu, str_label,
+        createStyleMenu(menu, str_label, reloader,
                         str_key == "stylesmenu" ? str_cmd : str_label);
     } // end of stylesdir
     else if (str_key == "themesdir" || str_key == "themesmenu") {
-        createStyleMenu(menu, str_label,
+        createStyleMenu(menu, str_label, reloader,
                         str_key == "themesmenu" ? str_cmd : str_label);
     } // end of themesdir
     else if (str_key == "wallpapers" || str_key == "wallpapermenu" ||
              str_key == "rootcommands") {
-         createRootCmdMenu(menu, str_label, str_label,
+         createRootCmdMenu(menu, str_label, str_label, reloader,
                           str_cmd == "" ? realProgramName("fbsetbg") : str_cmd);
     } // end of wallpapers
     else if (str_key == "workspaces") {
@@ -335,7 +347,9 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
 }
 
 
-void parseWindowMenu(FbTk::Parser &parse, FbTk::Menu &menu, FbTk::StringConvertor &labelconvertor) {
+void parseWindowMenu(FbTk::Parser &parse, FbTk::Menu &menu,
+                     FbTk::StringConvertor &labelconvertor,
+                     AutoReloadHelper *reloader) {
 
     ParseItem pitem(&menu);
     while (!parse.eof()) {
@@ -343,16 +357,16 @@ void parseWindowMenu(FbTk::Parser &parse, FbTk::Menu &menu, FbTk::StringConverto
         if (MenuCreator::createWindowMenuItem(pitem.key(), pitem.label(), menu))
             continue;
 
-        if (pitem.key() == "end") {
+        if (pitem.key() == "end")
             return;
-        } else if (pitem.key() == "submenu") {
+        if (pitem.key() == "submenu") {
             FbTk::Menu *submenu = MenuCreator::createMenu(pitem.label(), menu.screenNumber());
-            parseWindowMenu(parse, *submenu, labelconvertor);
+            parseWindowMenu(parse, *submenu, labelconvertor, reloader);
             submenu->updateMenu();
             menu.insert(pitem.label(), submenu);
 
         } else { // try non window menu specific stuff
-            translateMenuItem(parse, pitem, labelconvertor);
+            translateMenuItem(parse, pitem, labelconvertor, reloader);
         }
     }
 }
@@ -376,12 +390,12 @@ bool getStart(FbMenuParser &parser, string &label, FbTk::StringConvertor &labelc
 
 }; // end of anonymous namespace
 
-FbTk::Menu *MenuCreator::createMenu(const string &label, int screen_number) {
+FbMenu *MenuCreator::createMenu(const string &label, int screen_number) {
     BScreen *screen = Fluxbox::instance()->findScreen(screen_number);
     if (screen == 0)
         return 0;
 
-    FbTk::Menu *menu = new FbMenu(screen->menuTheme(),
+    FbMenu *menu = new FbMenu(screen->menuTheme(),
                                   screen->imageControl(),
                                   *screen->layerManager().getLayer(Layer::MENU));
     if (!label.empty())
@@ -391,7 +405,8 @@ FbTk::Menu *MenuCreator::createMenu(const string &label, int screen_number) {
 }
 
 bool MenuCreator::createFromFile(const string &filename,
-                                 FbTk::Menu &inject_into, bool begin) {
+                                 FbTk::Menu &inject_into,
+                                 AutoReloadHelper *reloader, bool begin) {
     string real_filename = FbTk::StringUtil::expandFilename(filename);
 
     FbMenuParser parser(real_filename);
@@ -409,73 +424,49 @@ bool MenuCreator::createFromFile(const string &filename,
     }
 
     // save menu filename, so we can check if it changes
-    Fluxbox::instance()->saveMenuFilename(real_filename.c_str());
+    if (reloader)
+        reloader->addFile(real_filename);
 
-    parseMenu(parser, inject_into, m_stringconvertor);
+    parseMenu(parser, inject_into, m_stringconvertor, reloader);
     endFile();
 
     return true;
 }
 
 
-bool MenuCreator::createWindowMenuFromFile(const string &filename,
-                                           FbTk::Menu &inject_into) {
+void MenuCreator::createWindowMenuFromFile(const string &filename,
+                                           FbTk::Menu &inject_into,
+                                           AutoReloadHelper *reloader) {
     string real_filename = FbTk::StringUtil::expandFilename(filename);
     FbMenuParser parser(real_filename);
     if (!parser.isLoaded())
-        return false;
+        return;
 
     string label;
 
     startFile();
     if (!getStart(parser, label, m_stringconvertor)) {
         endFile();
-        return false;
+        return;
     }
 
-    parseWindowMenu(parser, inject_into, m_stringconvertor);
-    endFile();
+    if (reloader)
+        reloader->addFile(real_filename);
 
-    return true;
+    parseWindowMenu(parser, inject_into, m_stringconvertor, reloader);
+    endFile();
 }
 
 
-FbTk::Menu *MenuCreator::createMenuType(const string &type, int screen_num) {
+FbMenu *MenuCreator::createMenuType(const string &type, int screen_num) {
     BScreen *screen = Fluxbox::instance()->findScreen(screen_num);
     if (screen == 0)
         return 0;
-    if (type == "iconmenu") {
+    if (type == "iconmenu")
         return new ClientMenu(*screen, screen->iconList(),
                               &screen->iconListSig());
-    } else if (type == "workspacemenu") {
+    else if (type == "workspacemenu")
         return new WorkspaceMenu(*screen);
-    } else if (type == "windowmenu") {
-        FbTk::Menu *menu = createMenu("", screen_num);
-
-        menu->disableTitle(); // not titlebar
-        if (screen->windowMenuFilename().empty() ||
-            ! createWindowMenuFromFile(screen->windowMenuFilename(), *menu)) {
-            const char *default_menu[] = {
-                "shade",
-                "stick",
-                "maximize",
-                "iconify",
-                "raise",
-                "lower",
-                "sendto",
-                "layer",
-                "alpha",
-                "extramenus",
-                "separator",
-                "close",
-                0
-            };
-            for (unsigned int i=0; default_menu[i]; ++i)
-                createWindowMenuItem(default_menu[i], "", *menu);
-        }
-        menu->reconfigure(); // update graphics
-        return menu;
-    }
 
     return 0;
 }
diff --git a/src/MenuCreator.hh b/src/MenuCreator.hh
index 660d097..8fb0242 100644
--- a/src/MenuCreator.hh
+++ b/src/MenuCreator.hh
@@ -28,18 +28,24 @@
 #include <list>
 
 namespace FbTk {
+class AutoReloadHelper;
 class Menu;
 }
 
+class FbMenu;
 class FluxboxWindow;
 
 class MenuCreator {
 public:
-    static FbTk::Menu *createMenu(const std::string &label, int screen_num);
-    static FbTk::Menu *createMenuType(const std::string &label, int screen_num);
+    static FbMenu *createMenu(const std::string &label, int screen_num);
+    static FbMenu *createMenuType(const std::string &label, int screen_num);
     static bool createFromFile(const std::string &filename,
-                               FbTk::Menu &inject_into, bool begin = true);
-    static bool createWindowMenuFromFile(const std::string &filename, FbTk::Menu &inject_into);
+                               FbTk::Menu &inject_into,
+                               FbTk::AutoReloadHelper *reloader = NULL,
+                               bool begin = true);
+    static void createWindowMenuFromFile(const std::string &filename,
+                                         FbTk::Menu &inject_into,
+                                         FbTk::AutoReloadHelper *reloader);
     static bool createWindowMenuItem(const std::string &type, const std::string &label, 
                                      FbTk::Menu &inject_into);
 
diff --git a/src/Screen.cc b/src/Screen.cc
index 8b00186..609da60 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -502,6 +502,15 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
     // own resources we must do this.
     fluxbox->load_rc(*this);
 
+    m_windowmenu.reset(createMenu(""));
+    m_windowmenu->setInternalMenu();
+    m_windowmenu->setReloadHelper(new FbTk::AutoReloadHelper());
+    m_windowmenu->reloadHelper()->setReloadCmd(FbTk::RefCount<FbTk::Command<void> >(new FbTk::SimpleCommand<BScreen>(*this, &BScreen::rereadWindowMenu)));
+
+    m_rootmenu.reset(createMenu(""));
+    m_rootmenu->setReloadHelper(new FbTk::AutoReloadHelper());
+    m_rootmenu->reloadHelper()->setReloadCmd(FbTk::RefCount<FbTk::Command<void> >(new FbTk::SimpleCommand<BScreen>(*this, &BScreen::rereadMenu)));
+
     m_configmenu.reset(createMenu(_FB_XTEXT(Menu, Configuration,
                                   "Configuration", "Title of configuration menu")));
     setupConfigmenu(*m_configmenu.get());
@@ -889,8 +898,8 @@ void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) {
 
 }
 
-FbTk::Menu *BScreen::createMenu(const string &label) {
-    FbTk::Menu *menu = new FbMenu(menuTheme(),
+FbMenu *BScreen::createMenu(const string &label) {
+    FbMenu *menu = new FbMenu(menuTheme(),
                                   imageControl(),
                                   *layerManager().getLayer(Layer::MENU));
     if (!label.empty())
@@ -898,8 +907,9 @@ FbTk::Menu *BScreen::createMenu(const string &label) {
 
     return menu;
 }
-FbTk::Menu *BScreen::createToggleMenu(const string &label) {
-    FbTk::Menu *menu = new ToggleMenu(menuTheme(),
+
+FbMenu *BScreen::createToggleMenu(const string &label) {
+    FbMenu *menu = new ToggleMenu(menuTheme(),
                                       imageControl(),
                                       *layerManager().getLayer(Layer::MENU));
     if (!label.empty())
@@ -912,9 +922,7 @@ void BScreen::addExtraWindowMenu(const FbTk::FbString &label, FbTk::Menu *menu)
     menu->setInternalMenu();
     menu->disableTitle();
     m_extramenus.push_back(make_pair(label, menu));
-    // recreate window menu
-    m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber()));
-    m_windowmenu->setInternalMenu();
+    rereadWindowMenu();
 }
 
 void BScreen::reconfigure() {
@@ -956,10 +964,9 @@ void BScreen::reconfigure() {
         }
     }
 
-    //reconfigure menus
-    // recreate window menu
-    m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber()));
-    m_windowmenu->setInternalMenu();
+    // update menu filenames
+    m_rootmenu->reloadHelper()->setMainFile(fluxbox->getMenuFilename());
+    m_windowmenu->reloadHelper()->setMainFile(windowMenuFilename());
 
     // reconfigure workspaces
     for_each(m_workspaces_list.begin(),
@@ -992,12 +999,6 @@ void BScreen::reconfigureTabs() {
         (*it)->fbwindow()->applyDecorations();
 }
 
-
-void BScreen::rereadMenu() {
-    initMenu();
-    m_rootmenu->reconfigure();
-}
-
 void BScreen::updateWorkspaceName(unsigned int w) {
     Workspace *space = getWorkspace(w);
     if (space) {
@@ -1489,23 +1490,20 @@ void BScreen::reassociateWindow(FluxboxWindow *w, unsigned int wkspc_id,
 
 void BScreen::initMenus() {
     m_workspacemenu.reset(MenuCreator::createMenuType("workspacemenu", screenNumber()));
-    m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber()));
-    m_windowmenu->setInternalMenu();
-    initMenu();
+    m_rootmenu->reloadHelper()->setMainFile(Fluxbox::instance()->getMenuFilename());
+    m_windowmenu->reloadHelper()->setMainFile(windowMenuFilename());
 }
 
 
-void BScreen::initMenu() {
+void BScreen::rereadMenu() {
 
-    if (m_rootmenu.get()) {
-        m_rootmenu->removeAll();
-        m_rootmenu->setLabel("");
-    } else
-        m_rootmenu.reset(createMenu(""));
+    m_rootmenu->removeAll();
+    m_rootmenu->setLabel("");
 
     Fluxbox * const fb = Fluxbox::instance();
     if (!fb->getMenuFilename().empty())
-        MenuCreator::createFromFile(fb->getMenuFilename(), *m_rootmenu);
+        MenuCreator::createFromFile(fb->getMenuFilename(), *m_rootmenu,
+                                    m_rootmenu->reloadHelper());
 
     if (m_rootmenu->numberOfItems() == 0) {
         _FB_USES_NLS;
@@ -1521,14 +1519,39 @@ void BScreen::initMenu() {
                            restart_fb);
         m_rootmenu->insert(_FB_XTEXT(Menu, Exit, "Exit", "Exit command"),
                            exit_fb);
-        // still save the menu filename, in case it becomes valid later
-        if (!fb->getMenuFilename().empty())
-            fb->saveMenuFilename(fb->getMenuFilename().c_str());
     }
 
-    m_rootmenu->updateMenu();
 }
 
+void BScreen::rereadWindowMenu() {
+
+    m_windowmenu->removeAll();
+    if (!windowMenuFilename().empty())
+        MenuCreator::createWindowMenuFromFile(windowMenuFilename(),
+                                              *m_windowmenu,
+                                              m_windowmenu->reloadHelper());
+
+    if (m_windowmenu->numberOfItems() == 0) {
+        const char *defaults[] = {
+            "shade",
+            "stick",
+            "maximize",
+            "iconify",
+            "raise",
+            "lower",
+            "sendto",
+            "layer",
+            "alpha",
+            "extramenus",
+            "separator",
+            "close",
+            0
+        };
+        for (unsigned int i=0; defaults[i]; ++i)
+            MenuCreator::createWindowMenuItem(defaults[i], "", *m_windowmenu);
+    }
+
+}
 
 void BScreen::addConfigMenu(const FbTk::FbString &label, FbTk::Menu &menu) {
     m_configmenu_list.push_back(make_pair(label, &menu));
diff --git a/src/Screen.hh b/src/Screen.hh
index 7758c90..57c41b6 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -54,6 +54,7 @@
 #include <map>
 
 class ClientPattern;
+class FbMenu;
 class Focusable;
 class FluxboxWindow;
 class WinClient;
@@ -122,12 +123,12 @@ public:
     const std::string &windowMenuFilename() const { return *resource.windowmenufile; }
     FbTk::ImageControl &imageControl() { return *m_image_control.get(); }
     // menus
-    const FbTk::Menu &rootMenu() const { return *m_rootmenu.get(); }
-    FbTk::Menu &rootMenu() { return *m_rootmenu.get(); }
-    const FbTk::Menu &configMenu() const { return *m_configmenu.get(); }
-    FbTk::Menu &configMenu() { return *m_configmenu.get(); }
-    const FbTk::Menu &windowMenu() const { return *m_windowmenu.get(); }
-    FbTk::Menu &windowMenu() { return *m_windowmenu.get(); }
+    const FbMenu &rootMenu() const { return *m_rootmenu.get(); }
+    FbMenu &rootMenu() { return *m_rootmenu.get(); }
+    const FbMenu &configMenu() const { return *m_configmenu.get(); }
+    FbMenu &configMenu() { return *m_configmenu.get(); }
+    const FbMenu &windowMenu() const { return *m_windowmenu.get(); }
+    FbMenu &windowMenu() { return *m_windowmenu.get(); }
     ExtraMenus &extraWindowMenus() { return m_extramenus; }
     const ExtraMenus &extraWindowMenus() const { return m_extramenus; }
 
@@ -166,9 +167,9 @@ public:
     Workspace *currentWorkspace() { return m_current_workspace; }
     const Workspace *currentWorkspace() const { return m_current_workspace; }
     /// @return the workspace menu
-    const FbTk::Menu &workspaceMenu() const { return *m_workspacemenu.get(); }
+    const FbMenu &workspaceMenu() const { return *m_workspacemenu.get(); }
     /// @return the workspace menu
-    FbTk::Menu &workspaceMenu() { return *m_workspacemenu.get(); }
+    FbMenu &workspaceMenu() { return *m_workspacemenu.get(); }
     /// @return focus control handler
     const FocusControl &focusControl() const { return *m_focus_control; }
     /// @return focus control handler
@@ -251,15 +252,15 @@ public:
     /**
      * Creates an empty menu with specified label
      * @param label for the menu
-     * @return create menu
+     * @return created menu
      */
-    FbTk::Menu *createMenu(const std::string &label);
+    FbMenu *createMenu(const std::string &label);
     /**
      * Creates an empty toggle menu with a specific label
      * @param label
      * @return created menu
      */
-    FbTk::Menu *createToggleMenu(const std::string &label);
+    FbMenu *createToggleMenu(const std::string &label);
 
     /**
      * For extras to add menus.
@@ -383,6 +384,7 @@ public:
     void reconfigure();
     void reconfigureTabs();
     void rereadMenu();
+    void rereadWindowMenu();
     void shutdown();
     /// show position window centered on the screen with "X x Y" text
     void showPosition(int x, int y);
@@ -489,7 +491,6 @@ public:
 
 private:
     void setupConfigmenu(FbTk::Menu &menu);
-    void initMenu();
     void renderGeomWindow();
     void renderPosWindow();
 
@@ -515,7 +516,7 @@ private:
 
 
     std::auto_ptr<FbTk::ImageControl> m_image_control;
-    std::auto_ptr<FbTk::Menu> m_configmenu, m_rootmenu, m_workspacemenu, m_windowmenu;
+    std::auto_ptr<FbMenu> m_configmenu, m_rootmenu, m_workspacemenu, m_windowmenu;
 
     ExtraMenus m_extramenus;
 
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 7d774cc..70503a5 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -437,8 +437,6 @@ Fluxbox::~Fluxbox() {
         delete (*it).first;
     }
     m_atomhandler.clear();
-
-    clearMenuFilenames();
 }
 
 
@@ -1469,63 +1467,6 @@ BScreen *Fluxbox::findScreen(int id) {
     return *it;
 }
 
-bool Fluxbox::menuTimestampsChanged() const {
-    list<MenuTimestamp *>::const_iterator it = m_menu_timestamps.begin();
-    list<MenuTimestamp *>::const_iterator it_end = m_menu_timestamps.end();
-    for (; it != it_end; ++it) {
-
-        time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp((*it)->filename.c_str());
-
-        if (timestamp != (*it)->timestamp)
-            return true;
-    }
-
-    // no timestamp changed
-    return false;
-}
-
-void Fluxbox::rereadMenu() {
-    clearMenuFilenames();
-
-    for_each(m_screen_list.begin(),
-             m_screen_list.end(),
-             mem_fun(&BScreen::rereadMenu));
-}
-
-void Fluxbox::saveMenuFilename(const char *filename) {
-    if (filename == 0)
-        return;
-
-    bool found = false;
-
-    list<MenuTimestamp *>::iterator it = m_menu_timestamps.begin();
-    list<MenuTimestamp *>::iterator it_end = m_menu_timestamps.end();
-    for (; it != it_end; ++it) {
-        if ((*it)->filename == filename) {
-            found = true;
-            break;
-        }
-    }
-
-    if (! found) {
-        time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(filename);
-
-        MenuTimestamp *ts = new MenuTimestamp;
-
-        ts->filename = filename;
-        ts->timestamp = timestamp;
-
-        m_menu_timestamps.push_back(ts);
-    }
-}
-
-void Fluxbox::clearMenuFilenames() {
-    while(!m_menu_timestamps.empty()) {
-        delete m_menu_timestamps.back();
-        m_menu_timestamps.pop_back();
-    }
-}
-
 void Fluxbox::timed_reconfigure() {
     if (m_reconfigure_wait)
         real_reconfigure();
diff --git a/src/fluxbox.hh b/src/fluxbox.hh
index e7c7556..8b22a04 100644
--- a/src/fluxbox.hh
+++ b/src/fluxbox.hh
@@ -136,8 +136,6 @@ public:
     void shutdown();
     void load_rc(BScreen &scr);
     void saveStyleFilename(const char *val) { m_rc_stylefile = (val == 0 ? "" : val); }
-    void saveMenuFilename(const char *);
-    void clearMenuFilenames();
     void saveWindowSearch(Window win, WinClient *winclient);
     // some windows relate to the group, not the client, so we record separately
     // searchWindow on these windows will give the active client in the group
@@ -149,8 +147,6 @@ public:
     void removeGroupSearch(Window win);
     void restart(const char *command = 0);
     void reconfigure();
-    void rereadMenu();
-    /// reloads the menus if the timestamps changed
 
     /// handle any system signal sent to the application
     void handleSignal(int signum);
@@ -176,8 +172,6 @@ public:
     typedef std::list<BScreen *> ScreenList;
     const ScreenList screenList() const { return m_screen_list; }
 
-    /// @return whether the timestamps on the menu changed
-    bool menuTimestampsChanged() const;
     bool haveShape() const { return m_have_shape; }
     int shapeEventbase() const { return m_shape_eventbase; }
     void getDefaultDataFilename(const char *name, std::string &) const;
@@ -190,14 +184,6 @@ public:
     AttentionNoticeHandler &attentionHandler() { return m_attention_handler; }
 
 private:
-
-    typedef struct MenuTimestamp {
-        std::string filename;
-        time_t timestamp;
-    } MenuTimestamp;
-
-
-
     std::string getRcFilename();
     void load_rc();
 
@@ -241,7 +227,6 @@ private:
     // will have it's window being the group index
     std::multimap<Window, WinClient *> m_group_search;
 
-    std::list<MenuTimestamp *> m_menu_timestamps;
     ScreenList m_screen_list;
 
     FluxboxWindow *m_masked_window;
-- 
cgit v0.11.2


From 0b2e002d4f281edfef0e6c036cf58d9fdb7ae978 Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Mon, 12 May 2008 09:00:02 -0700
Subject: use AutoReloadHelper in apps file, check for changes automatically

---
 ChangeLog       |  3 +++
 src/Remember.cc | 28 ++++++++++++++--------------
 src/Remember.hh |  6 ++++--
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 690212b..e441093 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
  (Format: Year/Month/Day)
 Changes for 1.1
+*08/05/12:
+   * Modifying the apps file no longer requires a reconfigure (Mark)
+     Remember.cc/hh
 *08/05/09:
    * Made tooltip in toolbar update when the title changes (Henrik)
      Tooltip.cc/hh, Screen.cc/cc, OSDWindow.hh
diff --git a/src/Remember.cc b/src/Remember.cc
index 8e133b8..825a070 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -281,14 +281,14 @@ void Application::reset() {
 Remember *Remember::s_instance = 0;
 
 Remember::Remember():
-    m_pats(new Patterns()),
-    m_last_timestamp(0)
-{
+    m_pats(new Patterns()) {
     if (s_instance != 0)
         throw string("Can not create more than one instance of Remember");
 
     s_instance = this;
     enableUpdate();
+
+    m_reloader.setReloadCmd(FbTk::RefCount<FbTk::Command<void> >(new FbTk::SimpleCommand<Remember>(*this, &Remember::reload)));
     reconfigure();
 }
 
@@ -579,11 +579,12 @@ Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlis
 
 
 void Remember::reconfigure() {
-    string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename());
+    m_reloader.setMainFile(Fluxbox::instance()->getAppsFilename());
+    m_reloader.checkReload();
+}
 
-    time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(apps_string.c_str());
-    if (m_last_timestamp > 0 && m_last_timestamp == timestamp)
-        return;
+void Remember::reload() {
+    string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename());
 
 #ifdef DEBUG
     cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl;
@@ -598,7 +599,6 @@ void Remember::reconfigure() {
     m_startups.clear();
 
     if (!apps_file.fail()) {
-        m_last_timestamp = timestamp;
         if (!apps_file.eof()) {
             string line;
             int row = 0;
@@ -687,7 +687,7 @@ void Remember::reconfigure() {
 #endif
         }
     } else {
-        cerr << "apps file failure" << endl;
+        cerr << "failed to open apps file" << endl;
     }
 
     // Clean up old state
@@ -895,11 +895,8 @@ void Remember::save() {
         apps_file << "[end]" << endl;
     }
     apps_file.close();
-
-    time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(apps_string.c_str());
-    if (timestamp > 0)
-        m_last_timestamp = timestamp;
-
+    // update timestamp to avoid unnecessary reload
+    m_reloader.addFile(Fluxbox::instance()->getAppsFilename());
 }
 
 bool Remember::isRemembered(WinClient &winclient, Attribute attrib) {
@@ -1216,6 +1213,9 @@ void Remember::setupClient(WinClient &winclient) {
     if (winclient.screen().isRestart())
         return;
 
+    // check if apps file has changed
+    reconfigure();
+
     Application *app = find(winclient);
     if (app == 0)
         return; // nothing to do
diff --git a/src/Remember.hh b/src/Remember.hh
index 4ab8f2a..107f1d2 100644
--- a/src/Remember.hh
+++ b/src/Remember.hh
@@ -29,6 +29,7 @@
 #include "AtomHandler.hh"
 #include "ClientPattern.hh"
 
+#include "FbTk/AutoReloadHelper.hh"
 #include "FbTk/RefCount.hh"
 
 #include <fstream>
@@ -223,7 +224,8 @@ public:
     Application* add(WinClient &winclient);
     FluxboxWindow* findGroup(Application *, BScreen &screen);
 
-    void reconfigure(); // was load
+    void reconfigure();
+    void reload();
     void save();
 
     bool isRemembered(WinClient &win, Attribute attrib);
@@ -277,7 +279,7 @@ private:
     Startups m_startups;
     static Remember *s_instance;
 
-    time_t m_last_timestamp;
+    FbTk::AutoReloadHelper m_reloader;
 };
 
 #endif // REMEMBER_HH
-- 
cgit v0.11.2


From a56492c0d538c9c3a019812558938df0b6afedeb Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Mon, 12 May 2008 09:30:13 -0700
Subject: some minor changes

---
 src/Remember.cc | 9 ++++++---
 src/Remember.hh | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/Remember.cc b/src/Remember.cc
index 825a070..2bd691f 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -120,7 +120,7 @@ public:
 
     void click(int button, int time, unsigned int mods) {
         // reconfigure only does stuff if the apps file has changed
-        Remember::instance().reconfigure();
+        Remember::instance().checkReload();
         if (WindowCmd<void>::window() != 0) {
             if (isSelected()) {
                 Remember::instance().forgetAttrib(WindowCmd<void>::window()->winClient(), m_attrib);
@@ -580,6 +580,9 @@ Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlis
 
 void Remember::reconfigure() {
     m_reloader.setMainFile(Fluxbox::instance()->getAppsFilename());
+}
+
+void Remember::checkReload() {
     m_reloader.checkReload();
 }
 
@@ -1214,7 +1217,7 @@ void Remember::setupClient(WinClient &winclient) {
         return;
 
     // check if apps file has changed
-    reconfigure();
+    checkReload();
 
     Application *app = find(winclient);
     if (app == 0)
@@ -1249,7 +1252,7 @@ FluxboxWindow *Remember::findGroup(Application *app, BScreen &screen) {
 }
 
 void Remember::updateClientClose(WinClient &winclient) {
-    reconfigure(); // reload if it's changed
+    checkReload(); // reload if it's changed
     Application *app = find(winclient);
 
     if (app && (app->save_on_close_remember && app->save_on_close)) {
diff --git a/src/Remember.hh b/src/Remember.hh
index 107f1d2..1f3ed7f 100644
--- a/src/Remember.hh
+++ b/src/Remember.hh
@@ -225,6 +225,7 @@ public:
     FluxboxWindow* findGroup(Application *, BScreen &screen);
 
     void reconfigure();
+    void checkReload();
     void reload();
     void save();
 
-- 
cgit v0.11.2


From dcdc78332431ff2b258c54a99d6fac382c6a0595 Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Mon, 12 May 2008 12:16:37 -0700
Subject: only reload the keys file if the contents have changed

---
 ChangeLog      |  2 ++
 src/Keys.cc    | 37 ++++++++++++-------------------------
 src/Keys.hh    | 23 +++++++++--------------
 src/fluxbox.cc |  6 +++---
 src/fluxbox.hh |  1 +
 5 files changed, 27 insertions(+), 42 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index e441093..89a93d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
  (Format: Year/Month/Day)
 Changes for 1.1
 *08/05/12:
+   * Only reload the keys file if the contents have changed (Mark)
+     Keys.cc/hh fluxbox.cc/hh
    * Modifying the apps file no longer requires a reconfigure (Mark)
      Remember.cc/hh
 *08/05/09:
diff --git a/src/Keys.cc b/src/Keys.cc
index eb3d9d5..ec1fde0 100644
--- a/src/Keys.cc
+++ b/src/Keys.cc
@@ -170,7 +170,9 @@ Keys::t_key::~t_key() {
 
 
 
-Keys::Keys() : next_key(0) { }
+Keys::Keys(): next_key(0) {
+    m_reloader.setReloadCmd(FbTk::RefCount<FbTk::Command<void> >(new FbTk::SimpleCommand<Keys>(*this, &Keys::reload)));
+}
 
 Keys::~Keys() {
     ungrabKeys();
@@ -255,27 +257,25 @@ void Keys::grabWindow(Window win) {
 /**
     Load and grab keys
     TODO: error checking
-    @return true on success else false
 */
-bool Keys::load(const char *filename) {
+void Keys::reload() {
     // an intentionally empty file will still have one root mapping
     bool firstload = m_map.empty();
 
-    if (!filename) {
+    if (m_filename.empty()) {
         if (firstload)
             loadDefaults();
-        return false;
+        return;
     }
 
     FbTk::App::instance()->sync(false);
 
     // open the file
-    ifstream infile(filename);
+    ifstream infile(m_filename.c_str());
     if (!infile) {
         if (firstload)
             loadDefaults();
-
-        return false; // failed to open file
+        return; // failed to open file
     }
 
     // free memory of previous grabs
@@ -301,9 +301,7 @@ bool Keys::load(const char *filename) {
         }
     } // end while eof
 
-    m_filename = filename;
     keyMode("default");
-    return true;
 }
 
 /**
@@ -321,19 +319,6 @@ void Keys::loadDefaults() {
     keyMode("default");
 }
 
-bool Keys::save(const char *filename) const {
-    //!!
-    //!! TODO: fix keybinding saving
-    //!! (we probably need to save key actions
-    //!! as strings instead of creating new Commands)
-
-    // open file for writing
-    //    ofstream outfile(filename);
-    //    if (!outfile)
-    return false;
-    //    return true;
-}
-
 bool Keys::addBinding(const string &linebuffer) {
 
     vector<string> val;
@@ -583,8 +568,10 @@ void Keys::unregisterWindow(Window win) {
  deletes the tree and load configuration
  returns true on success else false
 */
-bool Keys::reconfigure(const char *filename) {
-    return load(filename);
+void Keys::reconfigure() {
+    m_filename = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getKeysFilename());
+    m_reloader.setMainFile(m_filename);
+    m_reloader.checkReload();
 }
 
 void Keys::keyMode(const string& keyMode) {
diff --git a/src/Keys.hh b/src/Keys.hh
index 7ebb0a7..68ff4ec 100644
--- a/src/Keys.hh
+++ b/src/Keys.hh
@@ -23,6 +23,7 @@
 #define KEYS_HH
 
 #include "FbTk/NotCopyable.hh"
+#include "FbTk/AutoReloadHelper.hh"
 
 #include <X11/Xlib.h>
 #include <string>
@@ -57,17 +58,6 @@ public:
     /// destructor
     ~Keys();
 
-    /**
-       Load configuration from file
-       @return true on success, else false
-    */
-    bool load(const char *filename = 0);
-    /**
-       Save keybindings to a file
-       Note: the file will be overwritten
-       @return true on success, else false
-     */
-    bool save(const char *filename = 0) const;
     /// bind a key action from a string
     /// @return false on failure
     bool addBinding(const std::string &binding);
@@ -83,12 +73,12 @@ public:
     /// unregister window
     void unregisterWindow(Window win);
 
+    const std::string& filename() const { return m_filename; }
     /**
        Reload configuration from filename
        @return true on success, else false
     */
-    bool reconfigure(const char *filename);
-    const std::string& filename() const { return m_filename; }
+    void reconfigure();
     void keyMode(const std::string& keyMode);
 private:
     class t_key; // helper class to build a 'keytree'
@@ -104,13 +94,18 @@ private:
     void ungrabButtons();
     void grabWindow(Window win);
 
-    // Load default keybindings for when there are errors loading the initial one
+    /**
+       Load configuration from file
+    */
+    void reload();
+    // Load default keybindings for when there are errors loading the keys file
     void loadDefaults();
     void setKeyMode(t_key *keyMode);
 
 
     // member variables
     std::string m_filename;
+    FbTk::AutoReloadHelper m_reloader;
     t_key *m_keylist;
     keyspace_t m_map;
 
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 70503a5..076ae45 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -307,7 +307,7 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
     // Create keybindings handler and load keys file
     // Note: this needs to be done before creating screens
     m_key.reset(new Keys);
-    m_key->load(StringUtil::expandFilename(*m_rc_keyfile).c_str());
+    m_key->reconfigure();
 
     vector<int> screens;
     int i;
@@ -751,7 +751,7 @@ void Fluxbox::handleEvent(XEvent * const e) {
             XRefreshKeyboardMapping(&e->xmapping);
             FbTk::KeyUtil::instance().init(); // reinitialise the key utils
             // reconfigure keys (if the mapping changes, they don't otherwise update
-            m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str());
+            m_key->reconfigure();
         }
         break;
     case CreateNotify:
@@ -1443,7 +1443,7 @@ void Fluxbox::real_reconfigure() {
     for_each(m_screen_list.begin(), m_screen_list.end(), mem_fun(&BScreen::reconfigure));
 
     //reconfigure keys
-    m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str());
+    m_key->reconfigure();
 
     // and atomhandlers
     for (AtomHandlerContainerIt it= m_atomhandler.begin();
diff --git a/src/fluxbox.hh b/src/fluxbox.hh
index 8b22a04..fc86125 100644
--- a/src/fluxbox.hh
+++ b/src/fluxbox.hh
@@ -120,6 +120,7 @@ public:
     const std::string &getMenuFilename() const { return *m_rc_menufile; }
     const std::string &getSlitlistFilename() const { return *m_rc_slitlistfile; }
     const std::string &getAppsFilename() const { return *m_rc_appsfile; }
+    const std::string &getKeysFilename() const { return *m_rc_keyfile; }
     int colorsPerChannel() const { return *m_rc_colors_per_channel; }
     int getTabsPadding() const { return *m_rc_tabs_padding; }
 
-- 
cgit v0.11.2


From 68cf3092208830e075c4fe5eddfdcbef3f11596a Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Mon, 12 May 2008 18:13:56 -0700
Subject: implement smarter reloading for custom menus

---
 ChangeLog         |  3 +++
 src/FbCommands.cc | 17 ++++++++++++-----
 src/FbCommands.hh |  3 ++-
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 89a93d6..80147cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
  (Format: Year/Month/Day)
 Changes for 1.1
+*08/05/13:
+   * Only reload custom menus when necessary (Mark)
+     FbCommands.cc/hh
 *08/05/12:
    * Only reload the keys file if the contents have changed (Mark)
      Keys.cc/hh fluxbox.cc/hh
diff --git a/src/FbCommands.cc b/src/FbCommands.cc
index 3a09b69..e0d0768 100644
--- a/src/FbCommands.cc
+++ b/src/FbCommands.cc
@@ -343,16 +343,23 @@ void ShowCustomMenuCmd::execute() {
     if (screen == 0)
         return;
 
-    if (m_menu.get()) {
-        m_menu->removeAll();
-        m_menu->setLabel("");
-    } else
+    if (!m_menu.get() || screen->screenNumber() != m_menu->screenNumber()) {
         m_menu.reset(screen->createMenu(""));
+        m_menu->setReloadHelper(new FbTk::AutoReloadHelper());
+        m_menu->reloadHelper()->setReloadCmd(FbTk::RefCount<FbTk::Command<void> >(new FbTk::SimpleCommand<ShowCustomMenuCmd>(*this, &ShowCustomMenuCmd::reload)));
+        m_menu->reloadHelper()->setMainFile(custom_menu_file);
+    } else
+        m_menu->reloadHelper()->checkReload();
 
-    MenuCreator::createFromFile(custom_menu_file, *m_menu.get());
     ::showMenu(*screen, *m_menu.get());
 }
 
+void ShowCustomMenuCmd::reload() {
+    m_menu->removeAll();
+    m_menu->setLabel("");
+    MenuCreator::createFromFile(custom_menu_file, *m_menu.get(), m_menu->reloadHelper());
+}
+
 REGISTER_COMMAND(rootmenu, FbCommands::ShowRootMenuCmd, void);
 
 void ShowRootMenuCmd::execute() {
diff --git a/src/FbCommands.hh b/src/FbCommands.hh
index 3ad45c4..811fb78 100644
--- a/src/FbCommands.hh
+++ b/src/FbCommands.hh
@@ -132,9 +132,10 @@ class ShowCustomMenuCmd: public FbTk::Command<void> {
 public:
     explicit ShowCustomMenuCmd(const std::string &arguments);
     void execute();
+    void reload();
 private:
    std::string custom_menu_file;
-   std::auto_ptr<FbTk::Menu> m_menu;    
+   std::auto_ptr<FbMenu> m_menu;    
 };
 
 class ShowRootMenuCmd: public FbTk::Command<void> {
-- 
cgit v0.11.2


From d7aa526d9275f7c94f0b1ce27464eaf3dae0d78d Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Tue, 13 May 2008 01:43:51 -0700
Subject: change default edge snap threshold to 10 pixels

---
 src/Screen.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Screen.cc b/src/Screen.cc
index 609da60..73b826b 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -283,7 +283,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
     follow_model(rm, IGNORE_OTHER_WORKSPACES, scrname+".followModel", altscrname+".followModel"),
     user_follow_model(rm, FOLLOW_ACTIVE_WINDOW, scrname+".userFollowModel", altscrname+".UserFollowModel"),
     workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"),
-    edge_snap_threshold(rm, 0, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"),
+    edge_snap_threshold(rm, 10, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"),
     focused_alpha(rm, 255, scrname+".window.focus.alpha", altscrname+".Window.Focus.Alpha"),
     unfocused_alpha(rm, 255, scrname+".window.unfocus.alpha", altscrname+".Window.Unfocus.Alpha"),
     menu_alpha(rm, 255, scrname+".menu.alpha", altscrname+".Menu.Alpha"),
-- 
cgit v0.11.2