harden focus cycling against client focussing Clients which implement a client-side modality might cause livelocks by reverting the focus to the transient (after the WM tried to put it on the leader as the transient's modality is unknown) So while cycling we revert the focus whenever it moves somewhere where we don't expect it. When done, we also focus the window that should have the focus anyway to allow the client to redistribute the focus (as we prevented it during cycling) Hall of Shame: Softmaker Freeoffice uses (only) client side modality.
Thomas Lübking thomas.luebking@gmail.com
1 files changed,
15 insertions(+),
1 deletions(-)
jump to
M
src/FocusControl.cc
→
src/FocusControl.cc
@@ -239,7 +239,11 @@ m_cycling_list = 0;
// put currently focused window to top if (s_focused_window) { - setScreenFocusedWindow(*s_focused_window); + // re-focus last window to give the client a chance to redistribute the + // focus internally (client-side only modality) + s_focused_window->focus(); + if (s_focused_window) + setScreenFocusedWindow(*s_focused_window); if (s_focused_fbwindow) s_focused_fbwindow->raise(); } else@@ -574,6 +578,16 @@ (!client || client->fbwindow() == s_focused_fbwindow))
return; BScreen *screen = client ? &client->screen() : 0; + if (screen && screen->focusControl().isCycling()) { + WinClient *last = screen->focusControl().m_cycling_last; + if (last && last != client && screen->focusControl().m_cycling_list->contains(*last)) { + // if we're currently cycling and the client tries to juggle around focus + // on FocusIn events to provide client-side modality - don't let him + last->focus(); + return; + } + } + BScreen *old_screen = FocusControl::focusedWindow() ? &FocusControl::focusedWindow()->screen() : 0;