From 2f63ba231cfd6bd8e3191ac0cc516c2235ef0ed2 Mon Sep 17 00:00:00 2001
From: markt <markt>
Date: Thu, 1 Mar 2007 21:19:04 +0000
Subject: changed FocusControl::cycleFocus() to take a list of windows as an
 argument also fixed some latent bugs and compiler warnings

---
 src/FocusControl.cc | 69 ++++++++++++++++++++++++++---------------------------
 src/FocusControl.hh | 16 ++++++-------
 src/Window.cc       | 30 +++--------------------
 src/WorkspaceCmd.cc | 34 ++++++++++++++++----------
 src/fluxbox.cc      | 35 ++++++---------------------
 5 files changed, 73 insertions(+), 111 deletions(-)

diff --git a/src/FocusControl.cc b/src/FocusControl.cc
index 5cbf645..f4c8cdf 100644
--- a/src/FocusControl.cc
+++ b/src/FocusControl.cc
@@ -54,7 +54,7 @@ FocusControl::FocusControl(BScreen &screen):
     m_focus_new(screen.resourceManager(), true, 
                 screen.name()+".focusNewWindows", 
                 screen.altName()+".FocusNewWindows"),
-    m_cycling_focus(false),
+    m_cycling_list(0),
     m_was_iconic(false),
     m_cycling_last(0) {
 
@@ -79,26 +79,25 @@ bool doSkipWindow(const WinClient &winclient, int opts) {
     ); 
 }
 
-void FocusControl::cycleFocus(int opts, bool cycle_reverse) {
+void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) {
 
-    FocusedWindows *window_list = (opts & CYCLELINEAR) ? &m_creation_order_list : &m_focused_list;
-    if (!m_cycling_focus) {
+    if (!m_cycling_list) {
         if (&m_screen == Fluxbox::instance()->watchingScreen())
-            m_cycling_focus = true;
-        m_cycling_window = find(window_list->begin(),window_list->end(),s_focused_window);
-        m_cycling_creation_order = (opts & CYCLELINEAR);
-        m_was_iconic = false;
+            // only set this when we're waiting for modifiers
+            m_cycling_list = window_list;
+        m_was_iconic = 0;
         m_cycling_last = 0;
-    } else if (m_cycling_creation_order ^ (bool)(opts & CYCLELINEAR)) {
-        m_cycling_creation_order ^= true;
-        m_cycling_window = find(window_list->begin(),window_list->end(),*m_cycling_window);
-    }
-    // if it is stacked, we want the highest window in the focused list
-    // that is on the same workspace
+    } else if (m_cycling_list != window_list)
+        m_cycling_list = window_list;
+
+    // too many things can go wrong with remembering this
+    m_cycling_window = find(window_list->begin(),window_list->end(),s_focused_window);
+
     FocusedWindows::iterator it = m_cycling_window;
     FocusedWindows::iterator it_begin = window_list->begin();
     FocusedWindows::iterator it_end = window_list->end();
 
+    // find the next window in the list that works
     while (true) {
         if (cycle_reverse && it == it_begin)
             it = it_end;
@@ -130,12 +129,18 @@ void FocusControl::cycleFocus(int opts, bool cycle_reverse) {
 
                         // set back to orig current Client in that fbwin
                         m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false);
+                        if (m_was_iconic == m_cycling_last) {
+                            s_reverting = true; // little hack
+                            m_cycling_last->fbwindow()->iconify();
+                            s_reverting = false;
+                        }
                     }
                     m_cycling_last = &last_client;
-                    if (m_was_iconic)
-                        (*m_cycling_window)->fbwindow()->iconify();
-                    m_was_iconic = fbwin->isIconic();
-                    fbwin->tempRaise();
+                    if (fbwin->isIconic())
+                        m_was_iconic = m_cycling_last;
+                    if (m_cycling_list)
+                        // else window will raise itself (if desired) on FocusIn
+                        fbwin->tempRaise();
                 }
                 break;
             }
@@ -158,7 +163,7 @@ void FocusControl::addFocusFront(WinClient &client) {
 void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
     // do nothing if there are no windows open
     // don't change focus order while cycling
-    if (m_focused_list.empty() || isCycling())
+    if (m_focused_list.empty() || s_reverting)
         return;
 
     FocusedWindows::iterator it = m_focused_list.begin();
@@ -181,28 +186,24 @@ void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
     
 void FocusControl::stopCyclingFocus() {
     // nothing to do
-    if (!m_cycling_focus)
+    if (m_cycling_list == 0)
         return;
 
-    m_cycling_focus = false;
+    FocusedWindows::iterator it_end = m_cycling_list->end();
     m_cycling_last = 0;
+    m_cycling_list = 0;
+
     // put currently focused window to top
     // the iterator may be invalid if the window died
     // in which case we'll do a proper revert focus
-    if (m_cycling_creation_order && m_cycling_window != m_creation_order_list.end())
-        m_cycling_window = find(m_focused_list.begin(),m_focused_list.end(),*m_cycling_window);
-    if (m_cycling_window != m_focused_list.end() &&
-        m_cycling_window != m_creation_order_list.end() &&
-        (*m_cycling_window)->fbwindow() &&
+    if (m_cycling_window != it_end && (*m_cycling_window)->fbwindow() &&
         (*m_cycling_window)->fbwindow()->isVisible()) {
         WinClient *client = *m_cycling_window;
-        m_focused_list.erase(m_cycling_window);
+        m_focused_list.remove(client);
         m_focused_list.push_front(client);
         client->fbwindow()->raise();
-    } else {
+    } else
         revertFocus(m_screen);
-    }
-
 }
 
 /**
@@ -254,7 +255,6 @@ void FocusControl::setScreenFocusedWindow(WinClient &win_client) {
             !Fluxbox::instance()->isStartup()) {
         m_focused_list.remove(&win_client);
         m_focused_list.push_front(&win_client);
-        m_cycling_window = m_focused_list.begin();
     }
 }
 
@@ -370,14 +370,14 @@ void FocusControl::removeClient(WinClient &client) {
         return;
 
     WinClient *cyc = 0;
-    if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end())
+    if (m_cycling_list && m_cycling_window != m_cycling_list->end())
         cyc = *m_cycling_window;
 
     m_focused_list.remove(&client);
     m_creation_order_list.remove(&client);
 
     if (cyc == &client) {
-        m_cycling_window = m_creation_order_list.end();
+        m_cycling_window = m_cycling_list->end();
         stopCyclingFocus();
     }
 }
@@ -402,8 +402,7 @@ void FocusControl::shutdown() {
  * it gets a focusIn
  */
 void FocusControl::revertFocus(BScreen &screen) {
-
-    if (screen.focusControl().isCycling())
+    if (s_reverting)
         return;
 
     FocusControl::s_reverting = true;
diff --git a/src/FocusControl.hh b/src/FocusControl.hh
index ee5fe95..ee66b9e 100644
--- a/src/FocusControl.hh
+++ b/src/FocusControl.hh
@@ -68,11 +68,9 @@ public:
 
     explicit FocusControl(BScreen &screen);
 
-    void prevFocus() { cycleFocus(0, true); }
-    void nextFocus() { cycleFocus(0, false); }
-    void prevFocus(int options) { cycleFocus(options, true); }
-    void nextFocus(int options) { cycleFocus(options, false); }
-    void cycleFocus(int options, bool cycle_reverse);
+    void prevFocus() { cycleFocus(&m_focused_list, 0, true); }
+    void nextFocus() { cycleFocus(&m_focused_list, 0, false); }
+    void cycleFocus(FocusedWindows *winlist, int options, bool reverse = false);
 
     void setScreenFocusedWindow(WinClient &win_client);
     void setFocusModel(FocusModel model);
@@ -83,7 +81,7 @@ public:
     void dirFocus(FluxboxWindow &win, FocusDir dir);
     bool isMouseFocus() const { return focusModel() == MOUSEFOCUS; }
     bool isMouseTabFocus() const { return tabFocusModel() == MOUSETABFOCUS; }
-    bool isCycling() const { return m_cycling_focus; }
+    bool isCycling() const { return m_cycling_list != 0; }
     void addFocusBack(WinClient &client);
     void addFocusFront(WinClient &client);
     void setFocusBack(FluxboxWindow *fbwin);
@@ -120,10 +118,10 @@ private:
     // Screen global so it works for sticky windows too.
     FocusedWindows m_focused_list;
     FocusedWindows m_creation_order_list;
+
     FocusedWindows::iterator m_cycling_window;
-    bool m_cycling_focus;
-    bool m_cycling_creation_order;
-    bool m_was_iconic;
+    FocusedWindows *m_cycling_list;
+    WinClient *m_was_iconic;
     WinClient *m_cycling_last;
 
     static WinClient *s_focused_window;
diff --git a/src/Window.cc b/src/Window.cc
index 27992f0..4e02bfe 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -777,36 +777,14 @@ void FluxboxWindow::nextClient() {
     if (numClients() <= 1)
         return;
 
-    ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), m_client);
-    WinClient *client = 0;
-    if (it == m_clientlist.end()) {
-        client = m_clientlist.front();
-    } else {
-        it++;
-        if (it == m_clientlist.end())
-            client = m_clientlist.front();
-        else
-            client = *it;
-    }
-    setCurrentClient(*client, true);
+    screen().focusControl().cycleFocus(&m_clientlist, 0);
 }
 
 void FluxboxWindow::prevClient() {
     if (numClients() <= 1)
         return;
 
-    ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), m_client);
-    WinClient *client = 0;
-    if (it == m_clientlist.end()) {
-        client = m_clientlist.front();
-    } else {
-        if (it == m_clientlist.begin())
-            client = m_clientlist.back();
-        else
-            client = *(--it);
-    }
-
-    setCurrentClient(*client, true);
+    screen().focusControl().cycleFocus(&m_clientlist, 0, true);
 }
 
 
@@ -3909,8 +3887,6 @@ void FluxboxWindow::setupWindow() {
     // sets up our window
     // we allow both to be done at once to share the commands
 
-    WinButtonTheme &winbutton_theme = screen().winButtonTheme();
-
     using namespace FbTk;
     typedef RefCount<Command> CommandRef;
     typedef SimpleCommand<FluxboxWindow> WindowCmd;
@@ -4024,7 +4000,7 @@ void FluxboxWindow::updateButtons() {
         if (new_size != m_titlebar_buttons[i].size() || need_update)
             need_update = true;
         else {
-            for (int j=0; j < new_size && !need_update; j++) {
+            for (size_t j=0; j < new_size && !need_update; j++) {
                 if ((*(*titlebar_side[i]))[j] != m_titlebar_buttons[i][j])
                     need_update = true;
             }
diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc
index 414f942..7d384aa 100644
--- a/src/WorkspaceCmd.cc
+++ b/src/WorkspaceCmd.cc
@@ -53,14 +53,19 @@ void NextWindowCmd::execute() {
         } else if (ev.type == ButtonPress) {
             mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
         }
+        int options = m_option;
         if (mods == 0) // can't stacked cycle unless there is a mod to grab
-            screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR);
-        else {
-            // if stacked cycling, then set a watch for
-            // the release of exactly these modifiers
+            options |= FocusControl::CYCLELINEAR;
+        else
+            // set a watch for the release of exactly these modifiers
             fb->watchKeyRelease(*screen, mods);
-            screen->focusControl().nextFocus(m_option);
-        }
+
+        FocusControl::FocusedWindows *win_list =
+            (options & FocusControl::CYCLELINEAR) ?
+                &screen->focusControl().creationOrderList() :
+                &screen->focusControl().focusedOrderList();
+        
+        screen->focusControl().cycleFocus(win_list, m_option);
     }
 }
 
@@ -76,14 +81,19 @@ void PrevWindowCmd::execute() {
         } else if (ev.type == ButtonPress) {
             mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
         }
+        int options = m_option;
         if (mods == 0) // can't stacked cycle unless there is a mod to grab
-            screen->focusControl().prevFocus(m_option | FocusControl::CYCLELINEAR);
-        else {
-            // if stacked cycling, then set a watch for
-            // the release of exactly these modifiers
+            options |= FocusControl::CYCLELINEAR;
+        else
+            // set a watch for the release of exactly these modifiers
             fb->watchKeyRelease(*screen, mods);
-            screen->focusControl().prevFocus(m_option);
-        }
+
+        FocusControl::FocusedWindows *win_list =
+            (options & FocusControl::CYCLELINEAR) ?
+                &screen->focusControl().creationOrderList() :
+                &screen->focusControl().focusedOrderList();
+        
+        screen->focusControl().cycleFocus(win_list, m_option, true);
     }
 }
 
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 468e723..89bd0d5 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -970,19 +970,7 @@ void Fluxbox::handleButtonEvent(XButtonEvent &be) {
     if (be.button == 1 && !screen->isRootColormapInstalled())
         screen->imageControl().installRootColormap();
 
-    // see if we need to keep watching for key releases
-    BScreen *old_watching_screen = m_watching_screen;
-    m_watching_screen = 0;
-    if (!m_key->doAction(be.type, be.state, be.button))
-        // no command run, so could still be cycling
-        m_watching_screen = old_watching_screen;
-    else if (old_watching_screen &&
-             m_watching_screen != old_watching_screen) {
-        // no longer need to watch old screen, so stop cycling
-        old_watching_screen->notifyReleasedKeys();
-        if (!m_watching_screen)
-            XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
-    }
+    m_key->doAction(be.type, be.state, be.button);
 }
 
 void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) {
@@ -1113,21 +1101,9 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
     if (keyScreen() == 0 || mouseScreen() == 0)
         return;
 
-    BScreen *old_watching_screen = m_watching_screen;
-
     switch (ke.type) {
     case KeyPress:
-        // see if we need to keep watching for key releases
-        m_watching_screen = 0;
-        if (!m_key->doAction(ke.type, ke.state, ke.keycode))
-            // no command run, so could still be cycling
-            m_watching_screen = old_watching_screen;
-        else if (old_watching_screen &&
-                 m_watching_screen != old_watching_screen) {
-            old_watching_screen->notifyReleasedKeys();
-            if (!m_watching_screen)
-                XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
-        }
+        m_key->doAction(ke.type, ke.state, ke.keycode);
         break;
     case KeyRelease: {
         // we ignore most key releases unless we need to use
@@ -1841,12 +1817,15 @@ void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) {
         cerr<<"WARNING: attempt to grab without modifiers!"<<endl;
         return;
     }
+    // just make sure we are saving the mods with any other flags (xkb)
+    m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods);
+
+    if (m_watching_screen == &screen)
+        return;
     if (m_watching_screen)
         m_watching_screen->focusControl().stopCyclingFocus();
     m_watching_screen = &screen;
 
-    // just make sure we are saving the mods with any other flags (xkb)
-    m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods);
     // TODO: it's possible (and happens to me sometimes) for the mods to be
     // released before we grab the keyboard -- not sure of a good way to fix it
     XGrabKeyboard(FbTk::App::instance()->display(),
-- 
cgit v0.11.2