all repos — fluxbox @ 5c7784affe78467d7ef4e52e22da83c341622d53

custom fork of the fluxbox windowmanager

Added facility to selectively ignore EnterNotify events

This will be used to avoid some situations where an EnterNotify event should not
focus the window beneath the mouse cursor.  For example, when a menu (or any
window for that matter) is unmapped, focus should not pass to whatever window is
beneath the current location of the mouse cursor, but to the previous window in
the focus list.

This was first noticed when using the ClientMenu feature with
focus-follows-mouse on -> The focus would always end up on the window beneath
the mouse pointer, not the window selected in the menu.
Jim Ramsay i.am@jimramsay.com
commit

5c7784affe78467d7ef4e52e22da83c341622d53

parent

e7700166604d737ff23427877100c8888c761494

3 files changed, 40 insertions(+), 3 deletions(-)

jump to
M src/FocusControl.ccsrc/FocusControl.cc

@@ -81,7 +81,8 @@ m_focused_list(screen), m_creation_order_list(screen),

m_focused_win_list(screen), m_creation_order_win_list(screen), m_cycling_list(0), m_was_iconic(false), - m_cycling_last(0) { + m_cycling_last(0), + m_ignore_mouse_x(-1), m_ignore_mouse_y(-1) { m_cycling_window = m_focused_list.clientList().end();

@@ -398,6 +399,28 @@

if (foundwin) foundwin->focus(); +} + +void FocusControl::ignoreAtPointer() +{ + int ignore_i; + 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_i, &ignore_i, &ignore_ui); +} + +void FocusControl::ignoreAt(int x, int y) +{ + m_ignore_mouse_x = x; m_ignore_mouse_y = y; +} + +bool FocusControl::isIgnored(int x, int y) +{ + return x == m_ignore_mouse_x && y == m_ignore_mouse_y; } void FocusControl::removeClient(WinClient &client) {
M src/FocusControl.hhsrc/FocusControl.hh

@@ -93,6 +93,15 @@ /// @return true if focus mode is mouse focus

bool isMouseFocus() const { return focusModel() == MOUSEFOCUS; } /// @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(); + /// Set the "ignore" pointer location to the given coordinates + void ignoreAt(int x, int y); + /// @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); + /// @return true if cycling is in progress bool isCycling() const { return m_cycling_list != 0; } /// Appends a client to the front of the focus list

@@ -157,6 +166,7 @@ Focusables::const_iterator m_cycling_window;

const FocusableList *m_cycling_list; Focusable *m_was_iconic; WinClient *m_cycling_last; + int m_ignore_mouse_x, m_ignore_mouse_y; static WinClient *s_focused_window; static FluxboxWindow *s_focused_fbwindow;
M src/Window.ccsrc/Window.cc

@@ -2680,13 +2680,17 @@ sa.w = ev.window;

sa.enter = sa.leave = False; XCheckIfEvent(display, &dummy, queueScanner, (char *) &sa); - if ((!sa.leave || sa.inferior) && !screen().focusControl().isCycling() ) { + if ((!sa.leave || sa.inferior) && + !screen().focusControl().isCycling() && + !screen().focusControl().isIgnored(ev.x_root, ev.y_root) ) { focus(); } } } - if (screen().focusControl().isMouseTabFocus() && client && client != m_client) { + if (screen().focusControl().isMouseTabFocus() && + client && client != m_client && + !screen().focusControl().isIgnored(ev.x_root, ev.y_root) ) { setCurrentClient(*client, isFocused()); }