From 3144086eef171f6c402182f23bfc80a101e71fa2 Mon Sep 17 00:00:00 2001
From: rathnor <rathnor>
Date: Fri, 4 Jul 2003 01:03:41 +0000
Subject: support in remember for specifying groups. Also split
 atomhandler::setupWindow

---
 BUGS                  |   3 ++
 ChangeLog             |  14 +++++++
 RoadMap               |   2 +-
 src/AtomHandler.hh    |   6 ++-
 src/Ewmh.cc           |   4 +-
 src/Ewmh.hh           |   7 ++--
 src/Gnome.cc          |   6 +--
 src/Gnome.hh          |   5 ++-
 src/Remember.cc       | 111 +++++++++++++++++++++++++++++++++++++++++++-------
 src/Remember.hh       |  13 ++++--
 src/Screen.cc         |  52 ++++++++++++++---------
 src/ToolbarHandler.cc |   4 +-
 src/ToolbarHandler.hh |   6 ++-
 src/Window.cc         |  55 +++++++++++++++++++++----
 src/fluxbox.cc        |  13 ++++--
 src/fluxbox.hh        |   4 +-
 16 files changed, 238 insertions(+), 67 deletions(-)

diff --git a/BUGS b/BUGS
index 941572a..6307966 100644
--- a/BUGS
+++ b/BUGS
@@ -19,6 +19,9 @@ bugs:
   large number of [remote] xload windows.
 * Can lock up on workspace change - possibly related to above as it 
   works when there aren't too many xload windows started up yet.
+* Remember-patch grouping can change order on each restart. Need to turn 
+  off remember functionality when restarting (only use it for first 
+  instance).
 
 other todo:
 FAQ items for:
diff --git a/ChangeLog b/ChangeLog
index fbc7de2..2779cc5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 (Format: Year/Month/Day)
 Changes for 0.9.4:
+*03/07/04:
+   * Add support in remember for grouping apps (Simon)
+     Achieved by using [group], e.g.
+     [group]
+       [app] (title=groupme)
+       [Deco] {NONE}
+     [end]
+     will group anything with the title "groupme" and will give that group
+     no decorations. You can have multiple [app] lines in a [group].
+     Recall that app lines can also use regular expressions.
+     - also includes split AtomHandler::setupWindow(fbw) into 
+       setupFrame(fbw) and setupClient(winclient).
+     Remember.hh/cc Window.cc Screen.cc fluxbox.hh/cc 
+     AtomHandler.hh Gnome.hh/cc Ewmh.hh/cc ToolbarHandler.hh/cc
 *03/07/03:
    * Added selected dot for style menu so one can see which style is selected (Henrik)
      Screen.cc
diff --git a/RoadMap b/RoadMap
index 35bca21..d817512 100644
--- a/RoadMap
+++ b/RoadMap
@@ -133,7 +133,7 @@ Key Features:
  * Regular expression support in remember 
    on several attributes                      (Simon)
  * Save grouping so it persists over restart  (Simon)
- - Autogrouping functionality into remember   (Simon)
+ * Autogrouping functionality into remember   (Simon)
    (this will thus get regexp matching etc)
  + Shaped menu/slit/toolbar                   (Henrik)
  * Improved screen object placement           (Henrik)
diff --git a/src/AtomHandler.hh b/src/AtomHandler.hh
index 13183c9..4b47e15 100644
--- a/src/AtomHandler.hh
+++ b/src/AtomHandler.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: AtomHandler.hh,v 1.8 2003/06/18 13:32:19 fluxgen Exp $
+// $Id: AtomHandler.hh,v 1.9 2003/07/04 01:03:40 rathnor Exp $
 
 #ifndef ATOMHANDLER_HH
 #define ATOMHANDLER_HH
@@ -27,6 +27,7 @@
 #include <X11/Xlib.h>
 
 class FluxboxWindow;
+class WinClient;
 class BScreen;
 
 class AtomHandler {
@@ -34,7 +35,8 @@ public:
     virtual ~AtomHandler() { }
 
     virtual void initForScreen(BScreen &screen) = 0;
-    virtual void setupWindow(FluxboxWindow &win) = 0;
+    virtual void setupFrame(FluxboxWindow &win) = 0;
+    virtual void setupClient(WinClient &winclient) = 0;
 
     virtual void updateClientList(BScreen &screen) = 0;
     virtual void updateWorkspaceNames(BScreen &screen) = 0;
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
index 6b59a0c..10fa722 100644
--- a/src/Ewmh.cc
+++ b/src/Ewmh.cc
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Ewmh.cc,v 1.28 2003/07/02 14:31:43 fluxgen Exp $
+// $Id: Ewmh.cc,v 1.29 2003/07/04 01:03:40 rathnor Exp $
 
 #include "Ewmh.hh" 
 
@@ -95,7 +95,7 @@ void Ewmh::initForScreen(BScreen &screen) {
 	
 }
 
-void Ewmh::setupWindow(FluxboxWindow &win) {
+void Ewmh::setupFrame(FluxboxWindow &win) {
 
     Atom ret_type;
     int fmt;
diff --git a/src/Ewmh.hh b/src/Ewmh.hh
index cf81209..ff508e5 100644
--- a/src/Ewmh.hh
+++ b/src/Ewmh.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Ewmh.hh,v 1.7 2003/06/18 13:33:15 fluxgen Exp $
+// $Id: Ewmh.hh,v 1.8 2003/07/04 01:03:40 rathnor Exp $
 
 #include "AtomHandler.hh"
 
@@ -32,8 +32,9 @@ public:
     Ewmh();
     ~Ewmh();
     void initForScreen(BScreen &screen);
-    void setupWindow(FluxboxWindow &win);
-	
+    void setupFrame(FluxboxWindow &win);
+    void setupClient(WinClient &winclient) {}
+
     void updateClientList(BScreen &screen);
     void updateWorkspaceNames(BScreen &screen);
     void updateCurrentWorkspace(BScreen &screen);
diff --git a/src/Gnome.cc b/src/Gnome.cc
index 240c691..10d1775 100644
--- a/src/Gnome.cc
+++ b/src/Gnome.cc
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Gnome.cc,v 1.28 2003/06/26 12:22:42 rathnor Exp $
+// $Id: Gnome.cc,v 1.29 2003/07/04 01:03:40 rathnor Exp $
 
 #include "Gnome.hh"
 
@@ -85,8 +85,8 @@ void Gnome::initForScreen(BScreen &screen) {
 	
 }
 
-void Gnome::setupWindow(FluxboxWindow &win) {
-    // load gnome state atom
+void Gnome::setupFrame(FluxboxWindow &win) {
+    // load gnome state (take queues from the main window of the frame)
     Display *disp = FbTk::App::instance()->display();
     Atom ret_type;
     int fmt;
diff --git a/src/Gnome.hh b/src/Gnome.hh
index 6c78444..35e25c8 100644
--- a/src/Gnome.hh
+++ b/src/Gnome.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Gnome.hh,v 1.7 2003/06/18 13:32:43 fluxgen Exp $
+// $Id: Gnome.hh,v 1.8 2003/07/04 01:03:40 rathnor Exp $
 
 #ifndef GNOME_HH
 #define GNOME_HH
@@ -65,7 +65,8 @@ public:
     Gnome();
     ~Gnome();
     void initForScreen(BScreen &screen);
-    void setupWindow(FluxboxWindow &win);
+    void setupFrame(FluxboxWindow &win);
+    void setupClient(WinClient &winclient) {}
 
     void updateClientList(BScreen &screen);
     void updateWorkspaceNames(BScreen &screen);
diff --git a/src/Remember.cc b/src/Remember.cc
index a31843b..97d1e35 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -21,7 +21,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Remember.cc,v 1.24 2003/06/12 15:12:19 rathnor Exp $
+// $Id: Remember.cc,v 1.25 2003/07/04 01:03:40 rathnor Exp $
 
 #include "Remember.hh"
 #include "ClientPattern.hh"
@@ -46,6 +46,7 @@
 #include <fstream>
 #include <string>
 #include <memory>
+#include <set>
 
 using namespace std;
 
@@ -128,7 +129,10 @@ FbTk::Menu *createRememberMenu(Remember &remember, FluxboxWindow &win) {
 
 }; // end anonymous namespace
 
-Application::Application() {
+Application::Application(bool grouped)
+    : is_grouped(grouped),
+      group(0)
+{
     workspace_remember =
 	dimensions_remember =
 	position_remember =
@@ -146,6 +150,7 @@ Application::Application() {
  ************/
 
 Remember::Remember() {
+    enableUpdate();
     load();
 }
 
@@ -155,12 +160,19 @@ Remember::~Remember() {
     // the patterns free the "Application"s
     // the client mapping shouldn't need cleaning
     Patterns::iterator it;
+    std::set<Application *> all_apps; // no duplicates
     while (!m_pats.empty()) {
         it = m_pats.begin();
         delete it->first; // ClientPattern
-        delete it->second; // Application
+        all_apps.insert(it->second); // Application, not necessarily unique
         m_pats.erase(it);
     }
+
+    std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates
+    while (ait != all_apps.end()) {
+        delete (*ait);
+        ++ait;
+    }
 }
 
 Application* Remember::find(WinClient &winclient) {
@@ -184,7 +196,7 @@ Application* Remember::find(WinClient &winclient) {
 
 Application * Remember::add(WinClient &winclient) {
     ClientPattern *p = new ClientPattern();
-    Application *app = new Application();
+    Application *app = new Application(false);
     // by default, we match against the WMClass of a window.
     p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
     m_clients[&winclient] = app;
@@ -193,11 +205,16 @@ Application * Remember::add(WinClient &winclient) {
     return app;
 }
 
-int Remember::parseApp(ifstream &file, Application &app) {
+int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
     string line;
     int row = 0;
     while (! file.eof()) {
-        if (getline(file, line)) {
+        if (first_line || getline(file, line)) {
+            if (first_line) {
+                line = *first_line;
+                first_line = 0;
+            }
+
             row++;
             if (line[0] != '#') { //the line is commented
                 int parse_pos = 0, err = 0;
@@ -307,6 +324,8 @@ void Remember::load() {
         if (!apps_file.eof()) {
             string line;
             int row = 0;
+            bool in_group = false;
+            std::list<ClientPattern *> grouped_pats;
             while (getline(apps_file, line) && ! apps_file.eof()) {
                 row++;
                 if (line[0] == '#')
@@ -319,14 +338,36 @@ void Remember::load() {
 
                 if (pos > 0 && key == "app") {
                     ClientPattern *pat = new ClientPattern(line.c_str() + pos);
-                    if ((err = pat->error()) == 0) {
-                        Application *app = new Application();
-                        m_pats.push_back(make_pair(pat, app));
-                        row += parseApp(apps_file, *app);
+                    if (!in_group) {
+                        if ((err = pat->error()) == 0) {
+                            Application *app = new Application(false);
+                            m_pats.push_back(make_pair(pat, app));
+                            row += parseApp(apps_file, *app);
+                        } else {
+                            cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
+                            delete pat; // since it didn't work
+                        }
                     } else {
-                        cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
-                        delete pat; // since it didn't work
+                        grouped_pats.push_back(pat);
+                    }
+                } else if (pos > 0 && key == "group") {
+                    in_group = true;
+                } else if (in_group) {
+                    // otherwise assume that it is the start of the attributes
+                    Application *app = new Application(true);
+                    while (!grouped_pats.empty()) {
+                        // associate all the patterns with this app
+                        m_pats.push_back(make_pair(grouped_pats.front(), app));
+                        grouped_pats.pop_front();
+                    }
+                    
+                    // we hit end... probably don't have attribs for the group
+                    // so finish it off with an empty application
+                    // otherwise parse the app
+                    if (!(pos>0 && key == "end")) {
+                        row += parseApp(apps_file, *app, &line);
                     }
+                    in_group = false;
                 } else
                     cerr<<"Error in apps file on line "<<row<<"."<<endl;
                 
@@ -350,9 +391,27 @@ void Remember::save() {
     ofstream apps_file(apps_string.c_str());
     Patterns::iterator it = m_pats.begin();
     Patterns::iterator it_end = m_pats.end();
+
+    std::set<Application *> grouped_apps; // no duplicates
+
     for (; it != it_end; ++it) {
-        apps_file << "[app]"<<it->first->toString()<<endl;
         Application &a = *it->second;
+        if (a.is_grouped) {
+            // if already processed
+            if (grouped_apps.find(&a) != grouped_apps.end())
+                continue;
+            // otherwise output this whole group
+            apps_file << "[group]" << endl;
+            Patterns::iterator git = m_pats.begin();
+            Patterns::iterator git_end = m_pats.end();
+            for (; git != git_end; git++) {
+                if (git->second->group == a.group) {
+                    apps_file << " [app]"<<git->first->toString()<<endl;
+                }
+            }
+        } else {
+            apps_file << "[app]"<<it->first->toString()<<endl;
+        }
         if (a.workspace_remember) {
             apps_file << "  [Workspace]\t{" << a.workspace << "}" << endl;
         }
@@ -541,7 +600,7 @@ void Remember::forgetAttrib(WinClient &winclient, Attribute attrib) {
     }
 }
 
-void Remember::setupWindow(FluxboxWindow &win) {
+void Remember::setupFrame(FluxboxWindow &win) {
     WinClient &winclient = win.winClient();
 
     // we don't touch the window if it is a transient
@@ -573,7 +632,10 @@ void Remember::setupWindow(FluxboxWindow &win) {
     if (app == 0) 
         return; // nothing to do
 
-    BScreen &screen = win.screen();
+    if (app->is_grouped && app->group == 0)
+        app->group = &win;
+
+    BScreen &screen = winclient.screen();
 
     if (app->workspace_remember) {
         // TODO: fix placement to initialise properly
@@ -611,10 +673,29 @@ void Remember::setupWindow(FluxboxWindow &win) {
 
 }
 
+void Remember::setupClient(WinClient &winclient) {
+
+    Application *app = find(winclient);
+    if (app == 0) 
+        return; // nothing to do
+
+    if (winclient.fbwindow() == 0 && app->is_grouped && app->group) {
+        app->group->attachClient(winclient);
+    }
+}
+
 void Remember::updateWindowClose(FluxboxWindow &win) {
     // This doesn't work at present since fluxbox.cc is missing the windowclose stuff.
     // I don't trust it (particularly winClient()) while this is the case
 
+    // scan all winclients and remove this fbw
+    Patterns::iterator it = m_pats.begin();
+    while (it != m_pats.end()) {
+        if (&win == it->second->group)
+            it->second->group = 0;
+        ++it;
+    }
+
     return;
 
     WinClient &winclient = win.winClient();
diff --git a/src/Remember.hh b/src/Remember.hh
index 0e8ffe7..756bc7f 100644
--- a/src/Remember.hh
+++ b/src/Remember.hh
@@ -21,7 +21,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Remember.hh,v 1.8 2003/06/18 13:34:56 fluxgen Exp $
+// $Id: Remember.hh,v 1.9 2003/07/04 01:03:40 rathnor Exp $
 
 /* Based on the original "Remember patch" by Xavier Brouckaert */
 
@@ -43,7 +43,7 @@ class ClientPattern;
 
 class Application {
 public:
-    Application();
+    Application(bool grouped);
     inline void forgetWorkspace() { workspace_remember = false; }
     inline void forgetDimensions() { dimensions_remember = false; }
     inline void forgetPosition() { position_remember = false; }
@@ -107,6 +107,9 @@ public:
     bool save_on_close_remember;
     bool save_on_close;
 
+    bool is_grouped;
+    FluxboxWindow *group;
+
 };
 
 /**
@@ -161,7 +164,8 @@ public:
     // Functions relating to AtomHandler
     
     // Functions we actually use
-    void setupWindow(FluxboxWindow &win);
+    void setupFrame(FluxboxWindow &win);
+    void setupClient(WinClient &winclient);
     void updateWindowClose(FluxboxWindow &win);
 
     // Functions we ignore (zero from AtomHandler)
@@ -186,7 +190,8 @@ public:
 private:
 
     // returns number of lines read
-    int parseApp(std::ifstream &file, Application &app);
+    // optionally can give a line to read before the first (lookahead line)
+    int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0);
     Patterns m_pats;
     Clients m_clients;
 
diff --git a/src/Screen.cc b/src/Screen.cc
index 54432b3..c33a5bb 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.200 2003/07/03 13:57:58 fluxgen Exp $
+// $Id: Screen.cc,v 1.201 2003/07/04 01:03:40 rathnor Exp $
 
 
 #include "Screen.hh"
@@ -1035,40 +1035,53 @@ FluxboxWindow *BScreen::createWindow(Window client) {
         return 0;
     }
 
+    bool new_win = false;
+
     // check if it should be grouped with something else
     FluxboxWindow *win;
     if ((win = findGroupLeft(*winclient)) != 0) {
         win->attachClient(*winclient);
-    } else {
-        win = new FluxboxWindow(*winclient, *this, 
-                                winFrameTheme(), *menuTheme(),
-                                *layerManager().getLayer(Fluxbox::instance()->getNormalLayer()));
-    }
-
-    if (!win->isManaged()) {
-        delete win;
-        return 0;
+        Fluxbox::instance()->attachSignals(*winclient);
     } else {
 
-        // always put on end of focused list, if it gets focused it'll get pushed up
-        // there is only the one win client at this stage
-        if (doFocusNew())
-            focused_list.push_front(&win->winClient());
-        else
-            focused_list.push_back(&win->winClient());
+        Fluxbox::instance()->attachSignals(*winclient);
+        if (winclient->fbwindow()) // may have been set in an atomhandler
+            win = winclient->fbwindow();
+        else {
+            win = new FluxboxWindow(*winclient, *this, 
+                                    winFrameTheme(), *menuTheme(),
+                                    *layerManager().getLayer(Fluxbox::instance()->getNormalLayer()));
+            
+            new_win = true;
 
-        //TODO: is next line needed?
-        Fluxbox::instance()->saveWindowSearch(client, win);
+            if (!win->isManaged()) {
+                delete win;
+                return 0;
+            } 
+        }
+    }
+                
+    // always put on end of focused list, if it gets focused it'll get pushed up
+    // there is only the one win client at this stage
+    if (doFocusNew())
+        focused_list.push_front(&win->winClient());
+    else
+        focused_list.push_back(&win->winClient());
+    
+    if (new_win) {
         setupWindowActions(*win);
         Fluxbox::instance()->attachSignals(*win);
     }
 
+    Fluxbox::instance()->saveWindowSearch(client, win);
+
     // we also need to check if another window expects this window to the left
     // and if so, then join it.
     FluxboxWindow *otherwin = 0;
     // TODO: does this do the right stuff focus-wise?
-    if ((otherwin = findGroupRight(*winclient)) && otherwin != win)
+    if ((otherwin = findGroupRight(*winclient)) && otherwin != win) {
         win->attachClient(otherwin->winClient());
+    }
 
     if (!win->isIconic() && (win->workspaceNumber() == currentWorkspaceID() || win->isStuck())) {
         win->show();
@@ -1096,6 +1109,7 @@ FluxboxWindow *BScreen::createWindow(WinClient &client) {
     Fluxbox::instance()->saveWindowSearch(client.window(), win);
     setupWindowActions(*win);
     Fluxbox::instance()->attachSignals(*win);
+    // winclient actions should have been setup when the WinClient was created
     if (win->workspaceNumber() == currentWorkspaceID() || win->isStuck()) {
         win->show();      
     }
diff --git a/src/ToolbarHandler.cc b/src/ToolbarHandler.cc
index 81b8520..61949ce 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.19 2003/07/01 12:40:56 fluxgen Exp $
+// $Id: ToolbarHandler.cc,v 1.20 2003/07/04 01:03:40 rathnor Exp $
 
 /**
  * The ToolbarHandler class acts as a rough interface to the toolbar.
@@ -267,7 +267,7 @@ void ToolbarHandler::initForScreen(BScreen &screen) {
 
 }
 
-void ToolbarHandler::setupWindow(FluxboxWindow &win) {
+void ToolbarHandler::setupFrame(FluxboxWindow &win) {
     if (&win.screen() != &m_screen)
         return;
 
diff --git a/src/ToolbarHandler.hh b/src/ToolbarHandler.hh
index 3986cc0..f0c470d 100644
--- a/src/ToolbarHandler.hh
+++ b/src/ToolbarHandler.hh
@@ -20,7 +20,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: ToolbarHandler.hh,v 1.4 2003/06/24 16:27:18 fluxgen Exp $
+// $Id: ToolbarHandler.hh,v 1.5 2003/07/04 01:03:40 rathnor Exp $
 
 #ifndef TOOLBARHANDLER_HH
 #define TOOLBARHANDLER_HH
@@ -56,7 +56,9 @@ public:
   
 
     void initForScreen(BScreen &screen);
-    void setupWindow(FluxboxWindow &win);
+    void setupFrame(FluxboxWindow &win);
+    // TODO: add setupClient and configure option to show groups or indiv. clients
+    void setupClient(WinClient &winclient) {}
     
     void updateState(FluxboxWindow &win);
     void updateWindowClose(FluxboxWindow &win);
diff --git a/src/Window.cc b/src/Window.cc
index 7b14cb5..f5c4fb9 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Window.cc,v 1.201 2003/07/02 05:27:40 fluxgen Exp $
+// $Id: Window.cc,v 1.202 2003/07/04 01:03:40 rathnor Exp $
 
 #include "Window.hh"
 
@@ -557,11 +557,8 @@ void FluxboxWindow::attachClient(WinClient &client) {
 
     // get the current window on the end of our client list
     Window leftwin = None;
-    ClientList::iterator client_it = clientList().end();
-    ClientList::iterator client_it_end = clientList().end();
-    --client_it;
-    if (client_it != client_it_end)
-        leftwin = (*client_it)->window();
+    if (!clientList().empty())
+        leftwin = clientList().back()->window();
 
     client.setGroupLeftWindow(leftwin);
 
@@ -570,8 +567,8 @@ void FluxboxWindow::attachClient(WinClient &client) {
 
         Fluxbox *fb = Fluxbox::instance();
         // make sure we set new window search for each client
-        client_it = old_win->clientList().begin();
-        client_it_end = old_win->clientList().end();
+        ClientList::iterator client_it = old_win->clientList().begin();
+        ClientList::iterator client_it_end = old_win->clientList().end();
         for (; client_it != client_it_end; ++client_it) {
             // setup eventhandlers for client
             fb->saveWindowSearch((*client_it)->window(), this);
@@ -638,6 +635,7 @@ void FluxboxWindow::attachClient(WinClient &client) {
 
         Fluxbox::instance()->saveWindowSearch(client.window(), this);
         client.saveBlackboxAttribs(m_blackbox_attrib);
+        m_clientlist.push_back(&client);
     }
 
     // make sure that the state etc etc is updated for the new client
@@ -659,6 +657,46 @@ bool FluxboxWindow::detachClient(WinClient &client) {
     if (client.m_win != this || numClients() <= 1)
         return false;
     
+    // I'm not sure how to do this bit better
+    // we need to find the window we've got, and update the
+    // window to its right to have a left window set to the
+    // window which is to the left of the current.
+    // Think in terms of:
+    // window1 <- my_window <- window2
+    // we need to take out my_window, so update window2 leftwin to be window1
+
+    Window leftwin = None;
+    ClientList::iterator client_it_end = clientList().end();
+    ClientList::iterator client_it = clientList().begin();
+    ClientList::iterator client_it_before = client_it_end;
+    ClientList::iterator client_it_after = clientList().begin();
+    if (!clientList().empty()) {
+        ++client_it_after;
+        if (clientList().front() == &client) {
+            leftwin = None;
+        } else {
+            ++client_it;
+            client_it_before = clientList().begin();
+            ++client_it_after;
+
+            while (client_it != client_it_end) {
+                if (*client_it == &client) {
+                    break;
+                }
+                ++client_it_before;
+                ++client_it;
+                ++client_it_after;
+            }
+        }
+    }
+
+    // update the leftwin of the window to the right
+    if (client_it_before != client_it_end) 
+        leftwin = (*client_it_before)->window();
+
+    if (client_it_after != client_it_end)
+        (*client_it_after)->setGroupLeftWindow(leftwin);
+
     removeClient(client);
 
     client.m_win = screen().createWindow(client);
@@ -2998,6 +3036,7 @@ void FluxboxWindow::restore(bool remap) {
 
     while (!clientList().empty()) {
         restore(clientList().back(), remap);
+        // deleting winClient removes it from the clientList
     }
 }
 
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 7f76e46..cb5cb68 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.167 2003/07/01 20:29:44 fluxgen Exp $
+// $Id: fluxbox.cc,v 1.168 2003/07/04 01:03:41 rathnor Exp $
 
 #include "fluxbox.hh"
 
@@ -1326,10 +1326,17 @@ void Fluxbox::attachSignals(FluxboxWindow &win) {
     win.stateSig().attach(this);
     win.workspaceSig().attach(this);
     win.layerSig().attach(this);
-    win.winClient().dieSig().attach(this);
     win.dieSig().attach(this);
     for (size_t i=0; i<m_atomhandler.size(); ++i) {
-        m_atomhandler[i]->setupWindow(win);
+        m_atomhandler[i]->setupFrame(win);
+    }
+}
+
+void Fluxbox::attachSignals(WinClient &winclient) {
+    winclient.dieSig().attach(this);
+
+    for (size_t i=0; i<m_atomhandler.size(); ++i) {
+        m_atomhandler[i]->setupClient(winclient);
     }
 }
 
diff --git a/src/fluxbox.hh b/src/fluxbox.hh
index cf1e9a8..b819636 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.63 2003/06/30 15:04:06 fluxgen Exp $
+// $Id: fluxbox.hh,v 1.64 2003/07/04 01:03:41 rathnor Exp $
 
 #ifndef	 FLUXBOX_HH
 #define	 FLUXBOX_HH
@@ -61,6 +61,7 @@
 
 class AtomHandler;
 class FluxboxWindow;
+class WinClient;
 class Keys;
 class BScreen;
 class FbAtoms;
@@ -175,6 +176,7 @@ public:
     void update(FbTk::Subject *changed);
 
     void attachSignals(FluxboxWindow &win);
+    void attachSignals(WinClient &winclient);
 	
     virtual void timeout();
 
-- 
cgit v0.11.2