From cc2f023a22db212b4097d7756379bb6b9e866b11 Mon Sep 17 00:00:00 2001
From: rathnor <rathnor>
Date: Sat, 22 Feb 2003 15:10:43 +0000
Subject: fix focus models for new event handler and Resource setup

---
 ChangeLog      |   3 ++
 src/Screen.cc  |  46 ++++++++++++----------
 src/Screen.hh  |  18 +++++----
 src/Window.cc  |  66 ++++++++++++++++++++++++++++---
 src/Window.hh  |   4 +-
 src/fluxbox.cc | 120 +++++++++++++++++++++------------------------------------
 src/fluxbox.hh |   6 ++-
 7 files changed, 149 insertions(+), 114 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 10df0e8..2619fa2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 (Format: Year/Month/Day)
 Changes for 0.1.15:
+*03/02/22:
+   * Fixed sloppy focus to use new event handler model (Simon)
+     Screen.hh/cc Window.hh/cc fluxbox.hh/cc   
 *03/02/20:
    * Fixed a size bug without titlebar (Henrik)
      Window.cc, FbWinFrame.cc
diff --git a/src/Screen.cc b/src/Screen.cc
index ee32f56..9ca7859 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.112 2003/02/20 23:31:13 fluxgen Exp $
+// $Id: Screen.cc,v 1.113 2003/02/22 15:10:43 rathnor Exp $
 
 
 #include "Screen.hh"
@@ -139,22 +139,21 @@ FbTk::Menu *createMenuFromScreen(BScreen &screen) {
     return menu;
 }
 
-/*
-class WindowLayerMenuItem : public FbTk::MenuItem {
+class FocusModelMenuItem : public FbTk::MenuItem {
 public:
-    WindowLayerMenuItem(const char *label, FluxboxWindow &win, int layernum):
-        FbTk::MenuItem(label), m_window(win), m_layernum(layernum) {
+    FocusModelMenuItem(const char *label, BScreen &screen, Fluxbox::FocusModel model, FbTk::RefCount<FbTk::Command> &cmd):
+        FbTk::MenuItem(label, cmd), m_screen(screen), m_focusmodel(model) {
     }
-    bool isEnabled() const { return m_window.getLayerNum() != m_layernum; }
+    bool isEnabled() const { return m_screen.getFocusModel() != m_focusmodel; }
     void click(int button, int time) {
-        m_window.moveToLayer(m_layernum);
+        m_screen.saveFocusModel(m_focusmodel);
+        FbTk::MenuItem::click(button, time);
     }
 
 private:
-    FluxboxWindow &m_window;
-    int m_layernum;
+    BScreen &m_screen;
+    Fluxbox::FocusModel m_focusmodel;
 };
-*/
 
 
 }; // End anonymous namespace
@@ -363,6 +362,7 @@ BScreen::ScreenResource::ScreenResource(ResourceManager &rm,
     focus_new(rm, true, scrname+".focusNewWindows", altscrname+".FocusNewWindows"),
     antialias(rm, false, scrname+".antialias", altscrname+".Antialias"),
     rootcommand(rm, "", scrname+".rootCommand", altscrname+".RootCommand"),
+    focus_model(rm, Fluxbox::CLICKTOFOCUS, scrname+".focusModel", altscrname+".FocusModel"),
     workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"),
     toolbar_width_percent(rm, 65, scrname+".toolbar.widthPercent", altscrname+".Toolbar.WidthPercent"),
     edge_snap_threshold(rm, 0, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"),
@@ -616,7 +616,7 @@ BScreen::BScreen(ResourceManager &rm,
         }
     }
 
-    if (! resource.sloppy_focus) {
+    if (! isSloppyFocus()) {
         XSetInputFocus(disp, m_toolbar->getWindowID(),
                        RevertToParent, CurrentTime);
     }
@@ -1733,21 +1733,27 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
     // create focus menu
     FbTk::Menu *focus_menu = createMenuFromScreen(*this);
 
-    /*    focus_menu->insert(new BoolMenuItem(i18n->getMessage(
-          ConfigmenuSet, ConfigmenuClickToFocus,
-          "Click To Focus"),*/
-    focus_menu->insert(new BoolMenuItem(i18n->getMessage(
+    focus_menu->insert(new FocusModelMenuItem(i18n->getMessage(
                                                          ConfigmenuSet, 
+                                                         ConfigmenuClickToFocus,
+                                                         "Click To Focus"), 
+                                              *this,
+                                              Fluxbox::CLICKTOFOCUS,
+                                              save_and_reconfigure));
+    focus_menu->insert(new FocusModelMenuItem(i18n->getMessage(
+        ConfigmenuSet, 
                                                          ConfigmenuSloppyFocus,
                                                          "Sloppy Focus"), 
-                                        resource.sloppy_focus, 
-                                        save_and_reconfigure));
-    focus_menu->insert(new BoolMenuItem(i18n->getMessage(
+                                              *this,
+                                              Fluxbox::SLOPPYFOCUS,
+                                              save_and_reconfigure));
+    focus_menu->insert(new FocusModelMenuItem(i18n->getMessage(
                                                          ConfigmenuSet, 
                                                          ConfigmenuSemiSloppyFocus,
                                                          "Semi Sloppy Focus"),
-                                        resource.semi_sloppy_focus,
-                                        save_and_reconfigure));
+                                              *this,
+                                              Fluxbox::SEMISLOPPYFOCUS,
+                                              save_and_reconfigure));
     focus_menu->insert(new BoolMenuItem(i18n->getMessage(
                                                          ConfigmenuSet, 
                                                          ConfigmenuAutoRaise,
diff --git a/src/Screen.hh b/src/Screen.hh
index 1b833d4..a30ca40 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Screen.hh,v 1.69 2003/02/20 23:33:08 fluxgen Exp $
+// $Id: Screen.hh,v 1.70 2003/02/22 15:10:43 rathnor Exp $
 
 #ifndef	 SCREEN_HH
 #define	 SCREEN_HH
@@ -79,8 +79,8 @@ public:
     ~BScreen();
 
     inline bool doToolbarAutoHide() const { return *resource.toolbar_auto_hide; }
-    inline bool isSloppyFocus() const { return resource.sloppy_focus; }
-    inline bool isSemiSloppyFocus() const { return resource.semi_sloppy_focus; }
+    inline bool isSloppyFocus() const { return (*resource.focus_model == Fluxbox::SLOPPYFOCUS); }
+    inline bool isSemiSloppyFocus() const { return (*resource.focus_model == Fluxbox::SEMISLOPPYFOCUS); }
     inline bool isRootColormapInstalled() const { return root_colormap_installed; }
     inline bool isScreenManaged() const { return managed; }
     inline bool isTabRotateVertical() const { return *resource.tab_rotate_vertical; }
@@ -104,6 +104,7 @@ public:
     FbTk::Menu * const getRootmenu() { return m_rootmenu.get(); }
 	
     inline const std::string &getRootCommand() const { return *resource.rootcommand; }
+    inline Fluxbox::FocusModel getFocusModel() const { return *resource.focus_model; }
 
     inline bool doSlitAutoHide() const { return resource.slit_auto_hide; }
 #ifdef SLIT
@@ -188,9 +189,10 @@ public:
 
     inline void setRootColormapInstalled(Bool r) { root_colormap_installed = r;  }
     inline void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd;  }
-    inline void saveSloppyFocus(bool s) { resource.sloppy_focus = s;  }
-    inline void saveSemiSloppyFocus(bool s) { resource.semi_sloppy_focus = s;  }
-    inline void saveAutoRaise(bool a) { resource.auto_raise = a;  }
+    inline void saveFocusModel(Fluxbox::FocusModel model) { resource.focus_model = model; }
+    //DEL inline void saveSloppyFocus(bool s) { resource.sloppy_focus = s;  }
+    //DEL inline void saveSemiSloppyFocus(bool s) { resource.semi_sloppy_focus = s;  }
+    //DEL inline void saveAutoRaise(bool a) { resource.auto_raise = a;  }
     inline void saveWorkspaces(int w) { *resource.workspaces = w;  }
     inline void saveToolbarAutoHide(bool r) { *resource.toolbar_auto_hide = r;  }
     inline void saveToolbarWidthPercent(int w) { *resource.toolbar_width_percent = w;  }
@@ -382,8 +384,8 @@ private:
             focus_last, focus_new,
             antialias;
         Resource<std::string> rootcommand;		
-        bool auto_raise, sloppy_focus, semi_sloppy_focus,
-            ordered_dither;
+        Resource<Fluxbox::FocusModel> focus_model;
+        bool auto_raise, ordered_dither;
         Resource<int> workspaces, toolbar_width_percent, edge_snap_threshold,
             tab_width, tab_height;
         Resource<Fluxbox::Layer> slit_layernum, toolbar_layernum;
diff --git a/src/Window.cc b/src/Window.cc
index 73afefc..ec0d7f3 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.122 2003/02/20 23:17:36 fluxgen Exp $
+// $Id: Window.cc,v 1.123 2003/02/22 15:10:43 rathnor Exp $
 
 #include "Window.hh"
 
@@ -93,6 +93,26 @@ void grabButton(Display *display, unsigned int button,
 	
 }
 
+// X event scanner for enter/leave notifies - adapted from twm
+typedef struct scanargs {
+    Window w;
+    Bool leave, inferior, enter;
+} scanargs;
+
+// look for valid enter or leave events (that may invalidate the earlier one we are interested in)
+static Bool queueScanner(Display *, XEvent *e, char *args) {
+    if ((e->type == LeaveNotify) &&
+        (e->xcrossing.window == ((scanargs *) args)->w) &&
+        (e->xcrossing.mode == NotifyNormal)) {
+        ((scanargs *) args)->leave = True;
+        ((scanargs *) args)->inferior = (e->xcrossing.detail == NotifyInferior);
+    } else if ((e->type == EnterNotify) &&
+               (e->xcrossing.mode == NotifyUngrab))
+        ((scanargs *) args)->enter = True;
+
+    return False;
+}
+
 /// raise window and do the same for each transient it holds
 void raiseFluxboxWindow(FluxboxWindow &win) {
 
@@ -2066,12 +2086,12 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
                     m_frame.x() < int(me.x_root - button_grab_x - screen->getBorderWidth())) {
                     //warp right
                     new_id = (cur_id + 1) % screen->getCount();
-                    dx = - me.x_root;
+                    dx = - me.x_root; // move mouse back to x=0
                 } else if (me.x_root <= warpPad &&
                            m_frame.x() > int(me.x_root - button_grab_x - screen->getBorderWidth())) {
                     //warp left
                     new_id = (cur_id - 1 + screen->getCount()) % screen->getCount();
-                    dx = screen->getWidth() - me.x_root-1;
+                    dx = screen->getWidth() - me.x_root-1; // move mouse to screen width - 1
                 }
 
                 if (new_id != cur_id) {
@@ -2081,8 +2101,8 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
 
                     last_resize_x = me.x_root + dx;
                     
-                    dx += m_frame.x(); // for window in correct position
-                
+                    // change dx to be relative to window rather than motion event
+                    dx += m_frame.x();
                 }
             }
 
@@ -2098,7 +2118,6 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
                 last_move_x = dx;
                 last_move_y = dy;
             } else {
-            
                 moveResize(dx, dy, m_frame.width(), m_frame.height());
             }
 
@@ -2154,6 +2173,41 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
 
 }
 
+void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) { 
+
+    // ignore grab activates, or if we're not visible
+    if (ev.mode == NotifyGrab ||
+        !isVisible()) {
+        return;
+    }
+
+    if (ev.window == getFrameWindow() ||
+        (!getFrameWindow() && ev.window == client.window)) {
+        if ((screen->isSloppyFocus() || screen->isSemiSloppyFocus()) 
+            && !isFocused()) {
+            Fluxbox::instance()->grab();
+            
+            // check that there aren't any subsequent leave notify events in the 
+            // X event queue
+            XEvent dummy;
+            scanargs sa;
+            sa.w = ev.window;
+            sa.enter = sa.leave = False;
+            XCheckIfEvent(display, &dummy, queueScanner, (char *) &sa);   
+    
+            if ((!sa.leave || sa.inferior) && setInputFocus())
+                installColormap(True);
+            
+            Fluxbox::instance()->ungrab();
+        }        
+    }
+}
+
+void FluxboxWindow::leaveNotifyEvent(XCrossingEvent &ev) { 
+    if (ev.window == getFrameWindow())
+        installColormap(False);
+}
+
 // TODO: functions should not be affected by decoration
 void FluxboxWindow::setDecoration(Decoration decoration) {
     switch (decoration) {
diff --git a/src/Window.hh b/src/Window.hh
index f55b307..5535c6e 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Window.hh,v 1.50 2003/02/18 15:11:11 rathnor Exp $
+// $Id: Window.hh,v 1.51 2003/02/22 15:10:43 rathnor Exp $
 
 #ifndef	 WINDOW_HH
 #define	 WINDOW_HH
@@ -173,6 +173,8 @@ public:
     void exposeEvent(XExposeEvent &ee);
     void configureRequestEvent(XConfigureRequestEvent &ce);
     void propertyNotifyEvent(Atom a);
+    void enterNotifyEvent(XCrossingEvent &ev);
+    void leaveNotifyEvent(XCrossingEvent &ev);
     //@}
 
     void setDecoration(Decoration decoration);
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index be41df1..1cb66a9 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.97 2003/02/18 15:11:12 rathnor Exp $
+// $Id: fluxbox.cc,v 1.98 2003/02/22 15:10:43 rathnor Exp $
 
 
 #include "fluxbox.hh"
@@ -143,25 +143,6 @@ char *basename (char *s) {
 #define RC_PATH "fluxbox"
 #define RC_INIT_FILE "init"
 
-
-// X event scanner for enter/leave notifies - adapted from twm
-typedef struct scanargs {
-    Window w;
-    Bool leave, inferior, enter;
-} scanargs;
-
-static Bool queueScanner(Display *, XEvent *e, char *args) {
-    if ((e->type == LeaveNotify) &&
-        (e->xcrossing.window == ((scanargs *) args)->w) &&
-        (e->xcrossing.mode == NotifyNormal)) {
-        ((scanargs *) args)->leave = True;
-        ((scanargs *) args)->inferior = (e->xcrossing.detail == NotifyInferior);
-    } else if ((e->type == EnterNotify) &&
-               (e->xcrossing.mode == NotifyUngrab))
-        ((scanargs *) args)->enter = True;
-
-    return False;
-}
 //-----------------------------------------------------------------
 //---- accessors for int, bool, and some enums with Resource ------
 //-----------------------------------------------------------------
@@ -189,6 +170,19 @@ setFromString(char const *strval) {
 }
 
 template<>
+void Resource<Fluxbox::FocusModel>::
+setFromString(char const *strval) {
+    if (strcasecmp(strval, "SloppyFocus") == 0) 
+        m_value = Fluxbox::SLOPPYFOCUS;
+    else if (strcasecmp(strval, "SemiSloppyFocus") == 0) 
+        m_value = Fluxbox::SEMISLOPPYFOCUS;
+    else if (strcasecmp(strval, "ClickToFocus") == 0) 
+        m_value = Fluxbox::CLICKTOFOCUS;
+    else
+        setDefaultValue();
+}
+
+template<>
 void Resource<Fluxbox::TitlebarList>::
 setFromString(char const *strval) {
     vector<std::string> val;
@@ -242,6 +236,21 @@ std::string Resource<std::string>::
 getString() { return **this; }
 
 template<>
+std::string Resource<Fluxbox::FocusModel>::
+getString() {
+    switch (m_value) {
+    case Fluxbox::SLOPPYFOCUS:
+        return string("SloppyFocus");
+    case Fluxbox::SEMISLOPPYFOCUS:
+        return string("SemiSloppyFocus");
+    case Fluxbox::CLICKTOFOCUS:
+        return string("ClickToFocus");
+    }
+    // default string
+    return string("ClickToFocus");
+}
+
+template<>
 std::string Resource<Fluxbox::TitlebarList>::
 getString() {
     string retval;
@@ -691,18 +700,7 @@ void Fluxbox::handleEvent(XEvent * const e) {
 
     }
         break;
-    case MotionNotify: {
-        last_time = e->xmotion.time;
-
-        FluxboxWindow *win = 0;
-        Tab *tab = 0;
-			
-        if ((win = searchWindow(e->xmotion.window)) !=0)
-            win->motionNotifyEvent(e->xmotion);
-        else if ((tab = searchTab(e->xmotion.window)) !=0)
-            tab->motionNotifyEvent(&e->xmotion);
-
-    }
+    case MotionNotify: 
         break;
     case PropertyNotify: {
 			
@@ -719,63 +717,26 @@ void Fluxbox::handleEvent(XEvent * const e) {
         break;
     case EnterNotify: {
         last_time = e->xcrossing.time;
-
         BScreen *screen = 0;
-        FluxboxWindow *win = 0;
-        Tab *tab = 0;
 
         if (e->xcrossing.mode == NotifyGrab)
             break;
 
-        XEvent dummy;
-        scanargs sa;
-        sa.w = e->xcrossing.window;
-        sa.enter = sa.leave = False;
-        XCheckIfEvent(getXDisplay(), &dummy, queueScanner, (char *) &sa);
-
         if ((e->xcrossing.window == e->xcrossing.root) &&
             (screen = searchScreen(e->xcrossing.window))) {
             screen->getImageControl()->installRootColormap();
-        } else if ((win = searchWindow(e->xcrossing.window))) {
-            if ((win->getScreen()->isSloppyFocus() ||
-                 win->getScreen()->isSemiSloppyFocus()) &&
-                (! win->isFocused()) && (! no_focus)) {
-
-                grab();
-
-                if (((! sa.leave) || sa.inferior) && win->isVisible() &&
-                    win->setInputFocus())
-                    win->installColormap(True);
 
-                ungrab();
-            }
-        } else if ((tab = searchTab(e->xcrossing.window))) {
-            win = tab->getWindow();
-            if (win->getScreen()->isSloppyFocus() && (! win->isFocused()) &&
-                (! no_focus)) {
-                win->raise();
-					
-                grab();
-
-                if (((! sa.leave) || sa.inferior) && win->isVisible() &&
-                    win->setInputFocus())
-                    win->installColormap(True);
-
-                ungrab();
-            }
-        } 		
+            // if sloppy focus, then remove focus from windows
+            if (screen->isSloppyFocus() ||
+                screen->isSemiSloppyFocus())
+                setFocusedWindow(0);
+        }
 			
     }
         break;
     case LeaveNotify:
         {
             last_time = e->xcrossing.time;
-
-            FluxboxWindow *win = (FluxboxWindow *) 0;
-			
-            if ((win = searchWindow(e->xcrossing.window)))
-                win->installColormap(false);
-			
         }
         break;
     case Expose:
@@ -841,6 +802,7 @@ void Fluxbox::handleButtonEvent(XButtonEvent &be) {
         FluxboxWindow *win = 0;
         Tab *tab = 0; 
 
+        /*
         if ((win = searchWindow(be.window))) {
 
             win->buttonPressEvent(be);
@@ -848,7 +810,7 @@ void Fluxbox::handleButtonEvent(XButtonEvent &be) {
             if (be.button == 1)
                 win->installColormap(True);
         }
-        else if ((tab = searchTab(be.window))) {
+        else*/ if ((tab = searchTab(be.window))) {
             tab->buttonPressEvent(&be);
         } else {
             ScreenList::iterator it = screenList.begin();
@@ -1782,6 +1744,8 @@ void Fluxbox::save_rc() {
                 placement.c_str());
         XrmPutLineResource(&new_blackboxrc, rc_string);
 
+        //TODO 
+/*
         std::string focus_mode;
         if (screen->isSloppyFocus() && screen->doAutoRaise())
             focus_mode = "AutoRaiseSloppyFocus";
@@ -1797,7 +1761,7 @@ void Fluxbox::save_rc() {
         sprintf(rc_string, "session.screen%d.focusModel: %s", screen_number,
                 focus_mode.c_str());
         XrmPutLineResource(&new_blackboxrc, rc_string);
-
+*/
         //		load_rc(screen);
         // these are static, but may not be saved in the users resource file,
         // writing these resources will allow the user to edit them at a later
@@ -2024,6 +1988,8 @@ void Fluxbox::load_rc(BScreen *screen) {
         delete [] search;
     }
 
+//TODO (use Fluxbox::FocusModel enum)
+    /*
     sprintf(name_lookup, "session.screen%d.focusModel", screen_number);
     sprintf(class_lookup, "Session.Screen%d.FocusModel", screen_number);
     if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
@@ -2058,7 +2024,7 @@ void Fluxbox::load_rc(BScreen *screen) {
         screen->saveSloppyFocus(true); 
         screen->saveAutoRaise(false);
     }
-
+    */
     sprintf(name_lookup, "session.screen%d.windowPlacement", screen_number);
     sprintf(class_lookup, "Session.Screen%d.WindowPlacement", screen_number);
     if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
diff --git a/src/fluxbox.hh b/src/fluxbox.hh
index 84aac80..cce734f 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.43 2003/02/18 15:11:12 rathnor Exp $
+// $Id: fluxbox.hh,v 1.44 2003/02/22 15:10:43 rathnor Exp $
 
 #ifndef	 FLUXBOX_HH
 #define	 FLUXBOX_HH
@@ -103,7 +103,9 @@ public:
 	
     /// obsolete
     enum Titlebar{SHADE=0, MINIMIZE, MAXIMIZE, CLOSE, STICK, MENU, EMPTY};		
-    
+
+    enum FocusModel { SLOPPYFOCUS=0, SEMISLOPPYFOCUS, CLICKTOFOCUS };
+
     inline const std::vector<Fluxbox::Titlebar>& getTitlebarRight() { return *m_rc_titlebar_right; }
     inline const std::vector<Fluxbox::Titlebar>& getTitlebarLeft() { return *m_rc_titlebar_left; }
     inline const std::string &getStyleFilename() const { return *m_rc_stylefile; }
-- 
cgit v0.11.2