From a830cf18ce0830451208157ecd0997521e171522 Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Fri, 28 May 2010 13:22:13 -0400 Subject: [PATCH 1/2] Add new focus model: StrictMouseFocus This is not actually implemented yet, but from now on, "MouseFocus" means: Focus follows mouse only when you are moving the mouse, any EnterNotify events caused by non-mouse operations (window closing, keycommands, changing desktops) will *not* shift focus And once fully-implemented, "StrictMouseFocus" will mean: Focus follows mouse on every EnterNotify event (except when the "ClientMenu" closes or during alt+tab window cycling) --- doc/fluxbox.1.in | 7 +++++-- nls/fluxbox-nls.hh | 1 + src/FocusControl.cc | 5 +++++ src/FocusControl.hh | 7 ++++--- src/Screen.cc | 7 ++++++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/doc/fluxbox.1.in b/doc/fluxbox.1.in index 11f70d9..86802b9 100644 --- a/doc/fluxbox.1.in +++ b/doc/fluxbox.1.in @@ -910,10 +910,13 @@ session\.screen0\.followModel: be focused\. `Ignore\' does nothing, and `Follow\' uses the setting in session\.screen0\.userFollowModel\. Default: Ignore -session\.screen0\.focusModel: ClickToFocus|MouseFocus +session\.screen0\.focusModel: ClickToFocus|MouseFocus|StrictMouseFocus This controls how windows gain focus via the mouse\. With `ClickToFocus\', the user must click on the window\. With `MouseFocus\', windows gain focus - whenever the mouse moves over them\. Default: ClickToFocus + whenever the mouse moves over them, but only when the mouse is moving. + With `StrictMouseFocus\', windows gain focus whenever the mouse enters any + exposed area, even if this is due to layer changes, window movement, + changing desktops, closing windows, etc\. Default: ClickToFocus session\.screen0\.autoRaise: When True, this setting automatically raises any window that gains focus\. diff --git a/nls/fluxbox-nls.hh b/nls/fluxbox-nls.hh index a304995..178c2f2 100644 --- a/nls/fluxbox-nls.hh +++ b/nls/fluxbox-nls.hh @@ -84,6 +84,7 @@ enum { ConfigmenuMaxIgnoreInc = 27, ConfigmenuMaxDisableMove = 28, ConfigmenuMaxDisableResize = 29, + ConfigmenuStrictMouseFocus = 30, EwmhSet = 5, EwmhOutOfMemoryClientList = 1, diff --git a/src/FocusControl.cc b/src/FocusControl.cc index e0a3662..66a2ed8 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc @@ -491,6 +491,7 @@ void FocusControl::revertFocus(BScreen &screen) { else { switch (screen.focusControl().focusModel()) { case FocusControl::MOUSEFOCUS: + case FocusControl::STRICTMOUSEFOCUS: XSetInputFocus(screen.rootWindow().display(), PointerRoot, None, CurrentTime); break; @@ -596,6 +597,8 @@ std::string FbTk::Resource::getString() const { switch (m_value) { case FocusControl::MOUSEFOCUS: return string("MouseFocus"); + case FocusControl::STRICTMOUSEFOCUS: + return string("StrictMouseFocus"); case FocusControl::CLICKFOCUS: return string("ClickFocus"); } @@ -608,6 +611,8 @@ void FbTk::Resource:: setFromString(char const *strval) { if (strcasecmp(strval, "MouseFocus") == 0) m_value = FocusControl::MOUSEFOCUS; + else if (strcasecmp(strval, "StrictMouseFocus") == 0) + m_value = FocusControl::STRICTMOUSEFOCUS; else if (strcasecmp(strval, "ClickToFocus") == 0) m_value = FocusControl::CLICKFOCUS; else diff --git a/src/FocusControl.hh b/src/FocusControl.hh index 91681ab..72eec11 100644 --- a/src/FocusControl.hh +++ b/src/FocusControl.hh @@ -42,8 +42,9 @@ public: typedef std::list Focusables; /// main focus model enum FocusModel { - MOUSEFOCUS = 0, ///< focus follows mouse - CLICKFOCUS ///< focus on click + MOUSEFOCUS = 0, ///< focus follows mouse, but only when the mouse is moving + CLICKFOCUS, ///< focus on click + STRICTMOUSEFOCUS ///< focus always follows mouse, even when stationary }; /// focus model for tabs enum TabFocusModel { @@ -90,7 +91,7 @@ public: */ void dirFocus(FluxboxWindow &win, FocusDir dir); /// @return true if focus mode is mouse focus - bool isMouseFocus() const { return focusModel() == MOUSEFOCUS; } + bool isMouseFocus() const { return focusModel() != CLICKFOCUS; } /// @return true if tab focus mode is mouse tab focus bool isMouseTabFocus() const { return tabFocusModel() == MOUSETABFOCUS; } diff --git a/src/Screen.cc b/src/Screen.cc index 649ea2b..0271868 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -1615,8 +1615,13 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) { "Click To Focus", "Click to focus", FocusControl::CLICKFOCUS); _FOCUSITEM(Configmenu, MouseFocus, - "Mouse Focus", "Mouse Focus", + "Mouse Focus (Keyboard Friendly)", + "Mouse Focus (Keyboard Friendly)", FocusControl::MOUSEFOCUS); + _FOCUSITEM(Configmenu, StrictMouseFocus, + "Mouse Focus (Strict)", + "Mouse Focus (Strict)", + FocusControl::STRICTMOUSEFOCUS); #undef _FOCUSITEM focus_menu->insert(new FbTk::MenuSeparator()); -- 1.7.1 From 9db301c26e27e4d139dff424f8eab2f8def30cb5 Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Fri, 28 May 2010 15:50:15 -0400 Subject: [PATCH 2/2] Implement StrictMouseFocus As noted in the previous commit, StrictMouseFocus now works as advertised: Focus follows mouse on every EnterNotify event (except when the "ClientMenu" closes or during alt+tab window cycling) --- src/ClientMenu.cc | 7 ++++++- src/FocusControl.cc | 19 ++++++++++++++----- src/FocusControl.hh | 10 ++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/ClientMenu.cc b/src/ClientMenu.cc index f5af305..46306d9 100644 --- a/src/ClientMenu.cc +++ b/src/ClientMenu.cc @@ -25,6 +25,7 @@ #include "Screen.hh" #include "Window.hh" #include "WindowCmd.hh" +#include "FocusControl.hh" #include #include "FbTk/MenuItem.hh" @@ -52,8 +53,12 @@ public: m_client.focus(); fbwin->raise(); - if ((mods & ControlMask) == 0) + if ((mods & ControlMask) == 0) { + // Ignore any focus changes due to this menu closing + // (even in StrictMouseFocus mode) + m_client.screen().focusControl().ignoreAtPointer(true); parent->hide(); + } } const std::string &label() const { return m_client.title(); } diff --git a/src/FocusControl.cc b/src/FocusControl.cc index 66a2ed8..44cd81b 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc @@ -403,21 +403,30 @@ void FocusControl::dirFocus(FluxboxWindow &win, FocusDir dir) { } -void FocusControl::ignoreAtPointer() +void FocusControl::ignoreAtPointer(bool force) { - int ignore_i; + int ignore_i, ignore_x, ignore_y; unsigned int ignore_ui; Window ignore_w; XQueryPointer(m_screen.rootWindow().display(), m_screen.rootWindow().window(), &ignore_w, &ignore_w, - &m_ignore_mouse_x, &m_ignore_mouse_y, + &ignore_x, &ignore_y, &ignore_i, &ignore_i, &ignore_ui); + + this->ignoreAt(ignore_x, ignore_y, force); +} + +void FocusControl::ignoreAt(int x, int y, bool force) +{ + if (force || this->focusModel() == MOUSEFOCUS) { + m_ignore_mouse_x = x; m_ignore_mouse_y = y; + } } -void FocusControl::ignoreAt(int x, int y) +void FocusControl::ignoreCancel() { - m_ignore_mouse_x = x; m_ignore_mouse_y = y; + m_ignore_mouse_x = m_ignore_mouse_y = -1; } bool FocusControl::isIgnored(int x, int y) diff --git a/src/FocusControl.hh b/src/FocusControl.hh index 72eec11..c265253 100644 --- a/src/FocusControl.hh +++ b/src/FocusControl.hh @@ -96,9 +96,15 @@ public: bool isMouseTabFocus() const { return tabFocusModel() == MOUSETABFOCUS; } /// Set the "ignore" pointer location to the current pointer location - void ignoreAtPointer(); + /// @param force If true, ignore even in StrictMouseFocus mode + void ignoreAtPointer(bool force = false); /// Set the "ignore" pointer location to the given coordinates - void ignoreAt(int x, int y); + /// @param x Current X position of the pointer + /// @param y Current Y position of the pointer + /// @param force If true, ignore even in StrictMouseFocus mode + void ignoreAt(int x, int y, bool force = false); + /// unset the "ignore" pointer location + void ignoreCancel(); /// @return true if events at the given X/Y coordinate should be ignored /// (ie, they were previously cached via one of the ignoreAt calls) bool isIgnored(int x, int y); -- 1.7.1