aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lübking <thomas.luebking@gmail.com>2016-05-23 13:00:19 (GMT)
committerMathias Gumz <akira@fluxbox.org>2016-05-28 09:05:45 (GMT)
commit98313bfb91e45a3f95a74e84ea4cbc7ec7f8a66f (patch)
treed7a39e314fa0423debac796233a1f1e0d25d4909
parentcb1a82ba9fa78dfc98d59cd875e19f40d6e9cf7a (diff)
downloadfluxbox-98313bfb91e45a3f95a74e84ea4cbc7ec7f8a66f.zip
fluxbox-98313bfb91e45a3f95a74e84ea4cbc7ec7f8a66f.tar.bz2
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.
-rw-r--r--src/FocusControl.cc16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/FocusControl.cc b/src/FocusControl.cc
index f0d88b9..3be7937 100644
--- a/src/FocusControl.cc
+++ b/src/FocusControl.cc
@@ -239,7 +239,11 @@ void FocusControl::stopCyclingFocus() {
239 239
240 // put currently focused window to top 240 // put currently focused window to top
241 if (s_focused_window) { 241 if (s_focused_window) {
242 setScreenFocusedWindow(*s_focused_window); 242 // re-focus last window to give the client a chance to redistribute the
243 // focus internally (client-side only modality)
244 s_focused_window->focus();
245 if (s_focused_window)
246 setScreenFocusedWindow(*s_focused_window);
243 if (s_focused_fbwindow) 247 if (s_focused_fbwindow)
244 s_focused_fbwindow->raise(); 248 s_focused_fbwindow->raise();
245 } else 249 } else
@@ -574,6 +578,16 @@ void FocusControl::setFocusedWindow(WinClient *client) {
574 return; 578 return;
575 579
576 BScreen *screen = client ? &client->screen() : 0; 580 BScreen *screen = client ? &client->screen() : 0;
581 if (screen && screen->focusControl().isCycling()) {
582 WinClient *last = screen->focusControl().m_cycling_last;
583 if (last && last != client && screen->focusControl().m_cycling_list->contains(*last)) {
584 // if we're currently cycling and the client tries to juggle around focus
585 // on FocusIn events to provide client-side modality - don't let him
586 last->focus();
587 return;
588 }
589 }
590
577 BScreen *old_screen = 591 BScreen *old_screen =
578 FocusControl::focusedWindow() ? 592 FocusControl::focusedWindow() ?
579 &FocusControl::focusedWindow()->screen() : 0; 593 &FocusControl::focusedWindow()->screen() : 0;