From 7e1733c4352befe577150bad63d362dd7c1a94b9 Mon Sep 17 00:00:00 2001
From: rathnor <rathnor>
Date: Fri, 18 Jul 2003 15:40:55 +0000
Subject: reorganise operation of ResourceManager plus fix initialisation of
 layer for slit and toolbar

---
 BUGS                          |  10 ++--
 ChangeLog                     |   6 +++
 src/FbTk/Resource.cc          | 105 +++++++++++++++++++++++++++++++++---------
 src/FbTk/Resource.hh          |  65 +++++++++++++++++++++++---
 src/FbTk/XrmDatabaseHelper.hh |   5 +-
 src/Screen.cc                 |   5 +-
 src/Slit.cc                   |   8 ++--
 src/Toolbar.cc                |   9 +++-
 src/ToolbarHandler.cc         |   3 +-
 src/fluxbox.cc                |  17 +++++--
 src/fluxbox.hh                |   4 +-
 11 files changed, 188 insertions(+), 49 deletions(-)

diff --git a/BUGS b/BUGS
index ba45b5a..ae9fbc3 100644
--- a/BUGS
+++ b/BUGS
@@ -2,9 +2,6 @@ Known bugs and missing features that will be fixed in future version:
 
 BUGS:
 
-  * Slit (check toolbar too) layernum isn't initialised to resource 
-    value on init. Also check why Fluxbox::Layer is used rather than int.
-
   * Remember menu sometimes isn't present in window menu. Probably need
     to add a signal for menu reconfigures (Screen::setupWindowActions)
 
@@ -18,9 +15,11 @@ BUGS:
   * Some menus don't close when you click on items.
 
   * Transparancy for the slit does not always work right.
+    => is this fixed now?? (as of ResourceManager changes)
 
   * After startup the font of the toolbar is to big; reload config works
     around this.
+    => is this fixed now?? (as of ResourceManager changes)
 
   * Saving of number of workspaces on restart
 
@@ -70,3 +69,8 @@ Fixed bugs (or not-our-fault bugs):
   * Transient windows seem to not have a X border - is this right?
     => no, they ought to have a border
 
+  * Slit (check toolbar too) layernum isn't initialised to resource 
+    value on init. Also check why Fluxbox::Layer is used rather than int.
+    => Fixed by reorganising the way ResourceManager works.
+       Fluxbox::Layer is used so that we can give some layers names
+
diff --git a/ChangeLog b/ChangeLog
index 84a7834..1b72753 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 (Format: Year/Month/Day)
 Changes for 0.9.5:
+*03/07/19:
+   * Redo ResourceManager so that it loads resources on registration, and
+     only opens the database in blocks of requests    (Simon)
+     - fixes initial loading of init resources (e.g. toolbar.layer)
+     Resource.hh/cc XrmDatabaseHelper.hh Screen.cc fluxbox.hh/cc Slit.cc
+     Toolbar.cc ToolbarHandler.cc
 *03/07/18:
    * Fix java bug. Wasn't sending ConfigureNotify's to client (Simon)
      - also fix missing border on transient windows
diff --git a/src/FbTk/Resource.cc b/src/FbTk/Resource.cc
index a222984..c21e55d 100644
--- a/src/FbTk/Resource.cc
+++ b/src/FbTk/Resource.cc
@@ -19,10 +19,10 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Resource.cc,v 1.1 2003/05/18 22:06:59 fluxgen Exp $
+// $Id: Resource.cc,v 1.2 2003/07/18 15:40:55 rathnor Exp $
 
-#include "Resource.hh"
 #include "XrmDatabaseHelper.hh"
+#include "Resource.hh"
 
 #include <iostream>
 #include <cassert>
@@ -31,22 +31,43 @@ using namespace std;
 
 namespace FbTk {
 
+ResourceManager::ResourceManager(const char *filename, bool lock_db) :
+ m_db_lock(0),
+ m_database(0),
+ m_filename(filename)
+{
+    ensureXrmIsInitialize();
+
+    if (lock_db)
+        lock();
+}
+
+ResourceManager::~ResourceManager() {
+    if (m_database)
+        delete m_database;
+}
+
 bool ResourceManager::m_init = false;
 
 /**
-  loads a resourcefile 
+  reloads all resources from resourcefile 
   @return true on success else false
 */
 bool ResourceManager::load(const char *filename) {
-    assert(filename);
+    m_filename = filename;
 
-    ensureXrmIsInitialize();
-	
-    XrmDatabaseHelper database;
-    database = XrmGetFileDatabase(filename);
-    if (database==0)
+    // force reload (lock will ensure it exists)
+    if (m_database) {
+        delete m_database;
+        m_database = 0;
+    }
+
+    lock();
+    if (!m_database) {
+        unlock();
         return false;
-	
+    }
+        
     XrmValue value;
     char *value_type;
 	
@@ -56,7 +77,7 @@ bool ResourceManager::load(const char *filename) {
     for (; i != i_end; ++i) {
 	
         Resource_base *resource = *i;
-        if (XrmGetResource(*database, resource->name().c_str(),
+        if (XrmGetResource(**m_database, resource->name().c_str(),
                            resource->altName().c_str(), &value_type, &value))			
             resource->setFromString(value.addr);
         else {
@@ -66,6 +87,8 @@ bool ResourceManager::load(const char *filename) {
         }
     }
 
+    unlock();
+
     return true;
 }
 
@@ -75,9 +98,8 @@ bool ResourceManager::load(const char *filename) {
 */
 bool ResourceManager::save(const char *filename, const char *mergefilename) {
     assert(filename);
-	
-    ensureXrmIsInitialize();
-
+    
+    // empty database
     XrmDatabaseHelper database;
 
     string rc_string;	
@@ -92,20 +114,32 @@ bool ResourceManager::save(const char *filename, const char *mergefilename) {
 
     if (database==0)
         return false;
-	
+
     //check if we want to merge a database
     if (mergefilename) {
-        XrmDatabaseHelper olddatabase(mergefilename);
-        if (olddatabase == 0) // did we load the file?
+        // force reload of file
+        m_filename = mergefilename;
+        if (m_database) 
+            delete m_database;
+        m_database = 0;
+
+        lock();
+
+        if (!m_database) {
+            unlock();
             return false;
-		
-        XrmMergeDatabases(*database, &*olddatabase); // merge databases
-        XrmPutFileDatabase(*olddatabase, filename); // save database to file
-		
-        *database = 0; // don't try to destroy the database
+        }
+
+        XrmMergeDatabases(*database, &**m_database); // merge databases
+        XrmPutFileDatabase(**m_database, filename); // save database to file
+
+        // don't try to destroy the database (XrmMergeDatabases destroys it)
+        *database = 0;
+        unlock();
     } else // save database to file
         XrmPutFileDatabase(*database, filename);
 
+    m_filename = filename;
     return true;
 }
 
@@ -115,5 +149,30 @@ void ResourceManager::ensureXrmIsInitialize() {
         m_init = true;
     }
 }
-	
+
+ResourceManager &ResourceManager::lock() {
+    ++m_db_lock;
+    // if the lock was zero, then load the database
+    if ((m_db_lock == 1 || !m_database) &&
+        m_filename != "") {
+        m_database = new XrmDatabaseHelper(m_filename.c_str());
+
+        // check that the database loaded ok
+        if (m_database && *m_database == 0) {
+            // didn't work
+            delete m_database;
+            m_database = 0;
+        }
+    }
+
+    return *this;
+}
+
+void ResourceManager::unlock() {
+    if (--m_db_lock == 0 && m_database) {
+        delete m_database;
+        m_database = 0;
+    }
+}
+
 }; // end namespace FbTk
diff --git a/src/FbTk/Resource.hh b/src/FbTk/Resource.hh
index 4471225..25152bc 100644
--- a/src/FbTk/Resource.hh
+++ b/src/FbTk/Resource.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Resource.hh,v 1.1 2003/05/18 22:06:59 fluxgen Exp $
+// $Id: Resource.hh,v 1.2 2003/07/18 15:40:55 rathnor Exp $
 
 #ifndef FBTK_RESOURCE_HH
 #define FBTK_RESOURCE_HH
@@ -28,9 +28,12 @@
 
 #include <string>
 #include <list>
+#include <X11/Xresource.h>
 
 namespace FbTk {
 
+class XrmDatabaseHelper;
+
 /// Base class for resources, this is only used in ResourceManager
 class Resource_base:private FbTk::NotCopyable
 {
@@ -66,8 +69,10 @@ class ResourceManager
 public:
     typedef std::list<Resource_base *> ResourceList;
 
-    ResourceManager() { }
-    virtual ~ResourceManager() {}
+    // lock specifies if the database should be opened with one level locked
+    // (useful for constructing inside initial set of constructors)
+    ResourceManager(const char *filename, bool lock_db);
+    virtual ~ResourceManager();
 
     /// Load all resources registered to this class
     /// @return true on success
@@ -77,12 +82,11 @@ public:
     /// @return true on success
     virtual bool save(const char *filename, const char *mergefilename=0);
 
+    
+
     /// Add resource to list, only used in Resource<T>
     template <class T>
-    void addResource(Resource<T> &r) {
-        m_resourcelist.push_back(&r);
-        m_resourcelist.unique();
-    }
+    void addResource(Resource<T> &r);
 
     /// Remove a specific resource, only used in Resource<T>
     template <class T>
@@ -90,12 +94,27 @@ public:
         m_resourcelist.remove(&r);
     }
 
+    // this marks the database as "in use" and will avoid reloading 
+    // resources unless it is zero.
+    // It returns this resource manager. Useful for passing to 
+    // constructors like Object(m_rm.lock())
+    ResourceManager &lock();
+    void unlock();
+    // for debugging
+    inline int lockDepth() const { return m_db_lock; }
+
 protected:
     static void ensureXrmIsInitialize();
 
+    int m_db_lock;
+
 private:
     static bool m_init;
     ResourceList m_resourcelist;
+
+    XrmDatabaseHelper *m_database;
+
+    std::string m_filename;
 };
 
 
@@ -142,6 +161,38 @@ private:
     ResourceManager &m_rm;
 };
 
+
+// add the resource and load its value
+template <class T>
+void ResourceManager::addResource(Resource<T> &r) {
+    m_resourcelist.push_back(&r);
+    m_resourcelist.unique();
+
+    // lock ensures that the database is loaded.
+    lock();
+
+    if (m_database == 0) {
+        unlock();
+        return;
+    }
+
+    XrmValue value;
+    char *value_type;
+
+    // now, load the value for this resource
+    if (XrmGetResource(**m_database, r.name().c_str(),
+                       r.altName().c_str(), &value_type, &value)) {
+        r.setFromString(value.addr);
+    } else {
+        cerr<<"Failed to read: "<<r.name()<<endl;
+        cerr<<"Setting default value"<<endl;
+            r.setDefaultValue();
+    }
+
+    unlock();
+}
+	
+
 }; // end namespace FbTk
 
 #endif // FBTK_RESOURCE_HH
diff --git a/src/FbTk/XrmDatabaseHelper.hh b/src/FbTk/XrmDatabaseHelper.hh
index 1b2618d..3388c7b 100644
--- a/src/FbTk/XrmDatabaseHelper.hh
+++ b/src/FbTk/XrmDatabaseHelper.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: XrmDatabaseHelper.hh,v 1.1 2003/05/18 22:06:59 fluxgen Exp $
+// $Id: XrmDatabaseHelper.hh,v 1.2 2003/07/18 15:40:55 rathnor Exp $
 
 // This is a helper for XrmDatabase
 // when database goes out of scope
@@ -34,6 +34,8 @@
 /**
 	Helper class for XrmDatabase.
 */
+namespace FbTk {
+
 class XrmDatabaseHelper
 {
 public:
@@ -75,4 +77,5 @@ private:
     XrmDatabase m_database;	
 };
 
+}; // namespace FbTk
 #endif //_XRMDATABASEHELPER_HH_
diff --git a/src/Screen.cc b/src/Screen.cc
index 21f8481..64ce672 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Screen.cc,v 1.202 2003/07/10 11:29:45 fluxgen Exp $
+// $Id: Screen.cc,v 1.203 2003/07/18 15:40:55 rathnor Exp $
 
 
 #include "Screen.hh"
@@ -481,8 +481,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
         }
     }
 
-
-    // set the toolbarhandler after the windows are setup, so it catches their state properly
+    rm.unlock();
 
     XFree(children);
     XFlush(disp);
diff --git a/src/Slit.cc b/src/Slit.cc
index faa8b3f..69d4824 100644
--- a/src/Slit.cc
+++ b/src/Slit.cc
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Slit.cc,v 1.71 2003/07/06 07:09:53 rathnor Exp $
+// $Id: Slit.cc,v 1.72 2003/07/18 15:40:55 rathnor Exp $
 
 #include "Slit.hh"
 
@@ -264,8 +264,8 @@ Slit::Slit(BScreen &scr, FbTk::XLayer &layer, const char *filename)
       m_strut(0),
 
       // resources
-
-      m_rc_auto_hide(scr.resourceManager(), false, 
+      // lock in first resource
+      m_rc_auto_hide(scr.resourceManager().lock(), false, 
                      scr.name() + ".slit.autoHide", scr.altName() + ".Slit.AutoHide"),
       // TODO: this resource name must change
       m_rc_maximize_over(scr.resourceManager(), false,
@@ -313,12 +313,14 @@ Slit::Slit(BScreen &scr, FbTk::XLayer &layer, const char *filename)
                                          screen().screenNumber()));
 
     m_layeritem.reset(new FbTk::XLayerItem(frame.window, layer));
+    moveToLayer((*m_rc_layernum).getNum());
 
     // Get client list for sorting purposes
     loadClientList(filename);
 
     setupMenu();
 
+    scr.resourceManager().unlock();
 }
 
 
diff --git a/src/Toolbar.cc b/src/Toolbar.cc
index fca4666..e0f4424 100644
--- a/src/Toolbar.cc
+++ b/src/Toolbar.cc
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Toolbar.cc,v 1.100 2003/07/10 15:52:58 fluxgen Exp $
+// $Id: Toolbar.cc,v 1.101 2003/07/18 15:40:55 rathnor Exp $
 
 #include "Toolbar.hh"
 
@@ -262,7 +262,8 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, FbTk::Menu &menu, size_t wi
     m_themelistener(*this),
     m_layeritem(frame.window, layer),
     m_strut(0),
-    m_rc_auto_hide(scrn.resourceManager(), false, 
+    // lock rcmanager here
+    m_rc_auto_hide(scrn.resourceManager().lock(), false, 
                    scrn.name() + ".toolbar.autoHide", scrn.altName() + ".Toolbar.AutoHide"),
     m_rc_maximize_over(scrn.resourceManager(), false,
                        scrn.name() + ".toolbar.maxOver", scrn.altName() + ".Toolbar.MaxOver"),
@@ -281,6 +282,8 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, FbTk::Menu &menu, size_t wi
     // listen to screen reconfigure
     screen().reconfigureSig().attach(&m_themelistener);
 
+    moveToLayer((*m_rc_layernum).getNum());
+
     m_layermenu.setInternalMenu();
     m_placementmenu.setInternalMenu();
     setupMenus();
@@ -330,6 +333,8 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, FbTk::Menu &menu, size_t wi
     reconfigure(); // get everything together
     frame.window.showSubwindows();
     frame.window.show();
+
+    scrn.resourceManager().unlock();
 }
 
 
diff --git a/src/ToolbarHandler.cc b/src/ToolbarHandler.cc
index b9cf8d2..f5e9255 100644
--- a/src/ToolbarHandler.cc
+++ b/src/ToolbarHandler.cc
@@ -20,7 +20,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: ToolbarHandler.cc,v 1.22 2003/07/10 11:53:44 fluxgen Exp $
+// $Id: ToolbarHandler.cc,v 1.23 2003/07/18 15:40:55 rathnor Exp $
 
 /**
  * The ToolbarHandler class acts as a rough interface to the toolbar.
@@ -142,6 +142,7 @@ void setupModeMenu(FbTk::Menu &menu, ToolbarHandler &handler) {
 
 ToolbarHandler::ToolbarHandler(BScreen &screen) 
     : m_screen(screen), 
+      // no need to lock since only one resource
       m_rc_mode(screen.resourceManager(), ToolbarHandler::ICONS,
                 screen.name() + ".toolbar.mode", screen.altName() + ".Toolbar.Mode"), 
       m_toolbar(0),
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index eaa62f9..027da76 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: fluxbox.cc,v 1.170 2003/07/10 12:00:49 fluxgen Exp $
+// $Id: fluxbox.cc,v 1.171 2003/07/18 15:40:55 rathnor Exp $
 
 #include "fluxbox.hh"
 
@@ -388,7 +388,9 @@ Fluxbox::Titlebar Fluxbox::s_titlebar_right[] = {MINIMIZE, MAXIMIZE, CLOSE};
 Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfilename)
     : FbTk::App(dpy_name),
       m_fbatoms(new FbAtoms()),
-      m_resourcemanager(), m_screen_rm(),
+      m_resourcemanager(rcfilename, true), 
+      // TODO: shouldn't need a separate one for screen
+      m_screen_rm(m_resourcemanager),
       m_rc_tabs(m_resourcemanager, true, "session.tabs", "Session.Tabs"),
       m_rc_ignoreborder(m_resourcemanager, false, "session.ignoreBorder", "Session.IgnoreBorder"),
       m_rc_colors_per_channel(m_resourcemanager, 4, 
@@ -463,6 +465,8 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
     XRRQueryExtension(disp, &m_randr_event_type, &error_base);
 #endif // HAVE_RANDR
 
+    load_rc();
+
     // setup atom handlers before we create any windows
 #ifdef USE_GNOME
     addAtomHandler(new Gnome()); // for gnome 1 atom support
@@ -493,13 +497,12 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
     m_fluxbox_pid = XInternAtom(disp, "_BLACKBOX_PID", False);
 #endif // HAVE_GETPID
 
-    load_rc();
     // Allocate screens
     for (int i = 0; i < ScreenCount(display()); i++) {
         char scrname[128], altscrname[128];
         sprintf(scrname, "session.screen%d", i);
         sprintf(altscrname, "session.Screen%d", i);
-        BScreen *screen = new BScreen(m_screen_rm, 
+        BScreen *screen = new BScreen(m_screen_rm.lock(), 
                                       scrname, altscrname,
                                       i, getNumberOfLayers());
         if (! screen->isScreenManaged()) {
@@ -563,7 +566,13 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
     // Create keybindings handler and load keys file	
     m_key.reset(new Keys(StringUtil::expandFilename(*m_rc_keyfile).c_str()));
 
+    m_resourcemanager.unlock();
     ungrab();
+
+#ifdef DEBUG
+    if (m_resourcemanager.lockDepth() != 0) 
+        cerr<<"--- resource manager lockdepth = "<<m_resourcemanager.lockDepth()<<endl;
+#endif //DEBUG
     m_starting = false;
 }
 
diff --git a/src/fluxbox.hh b/src/fluxbox.hh
index b819636..5ce37ab 100644
--- a/src/fluxbox.hh
+++ b/src/fluxbox.hh
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: fluxbox.hh,v 1.64 2003/07/04 01:03:41 rathnor Exp $
+// $Id: fluxbox.hh,v 1.65 2003/07/18 15:40:55 rathnor Exp $
 
 #ifndef	 FLUXBOX_HH
 #define	 FLUXBOX_HH
@@ -224,7 +224,7 @@ private:
     
     std::auto_ptr<FbAtoms> m_fbatoms;
 
-    FbTk::ResourceManager m_resourcemanager, m_screen_rm;
+    FbTk::ResourceManager m_resourcemanager, &m_screen_rm;
 	
     //--- Resources
     FbTk::Resource<bool> m_rc_tabs, m_rc_ignoreborder;
-- 
cgit v0.11.2