diff --git a/doc/asciidoc/fluxbox.txt b/doc/asciidoc/fluxbox.txt
index a324336..22d07ac 100644
--- a/doc/asciidoc/fluxbox.txt
+++ b/doc/asciidoc/fluxbox.txt
@@ -1001,10 +1001,12 @@ This specifies the width of external tabs in pixels.
+
Default: *64*
-*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.
+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*
diff --git a/doc/fluxbox.1.in b/doc/fluxbox.1.in
index 7e36b8c..c65545f 100644
--- a/doc/fluxbox.1.in
+++ b/doc/fluxbox.1.in
@@ -1,13 +1,13 @@
'\" t
.\" Title: fluxbox
.\" Author: [see the "AUTHORS" section]
-.\" Generator: DocBook XSL Stylesheets v1.75.1
-.\" Date: 01/14/2010
+.\" Generator: DocBook XSL Stylesheets v1.75.2
+.\" Date: 05/28/2010
.\" Manual: Fluxbox Manual
.\" Source: fluxbox.txt
.\" Language: English
.\"
-.TH "FLUXBOX" "1" "01/14/2010" "fluxbox\&.txt" "Fluxbox Manual"
+.TH "FLUXBOX" "1" "05/28/2010" "fluxbox\&.txt" "Fluxbox Manual"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
@@ -1693,9 +1693,9 @@ Default:
\fB64\fR
.RE
.PP
-\fBsession\&.screen0\&.focusModel\fR: \fBClickToFocus|MouseFocus\fR
+\fBsession\&.screen0\&.focusModel\fR: \fBClickToFocus|MouseFocus|StrictMouseFocus\fR
.RS 4
-This controls how windows gain focus via the mouse\&. With \(oqClickToFocus\(cq, the user must click on the window\&. With \(oqMouseFocus\(cq, windows gain focus whenever the mouse moves over them\&.
+This controls how windows gain focus via the mouse\&. With \(oqClickToFocus\(cq, the user must click on the window\&. With \(oqMouseFocus\(cq, windows gain focus whenever the mouse moves over them, but only when the mouse is moving\&. With \(oqStrictMouseFocus\(cq, 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\&.
.sp
Default:
\fBClickToFocus\fR
diff --git a/nls/fluxbox-nls.hh b/nls/fluxbox-nls.hh
index 7e461ca..7ddc978 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/ClientMenu.cc b/src/ClientMenu.cc
index 02df7e4..67ec374 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"
@@ -56,8 +57,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 3ba9dc6..63ca773 100644
--- a/src/FocusControl.cc
+++ b/src/FocusControl.cc
@@ -401,21 +401,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)
@@ -489,6 +498,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;
@@ -593,6 +603,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");
}
@@ -605,6 +617,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..c265253 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,14 +91,20 @@ 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; }
/// 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);
diff --git a/src/Screen.cc b/src/Screen.cc
index b712b81..44649c0 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -1555,8 +1555,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());