tidy up window cycling Thanks Mark Tiefenbruck, mark at tiefenbruck dot org
simonb simonb
3 files changed,
72 insertions(+),
192 deletions(-)
M
ChangeLog
→
ChangeLog
@@ -1,5 +1,9 @@
(Format: Year/Month/Day) Changes for 0.9.16: +*06/04/23: + * Tidy up window cycling, and make linear mode work in order of + creation (Thanks Mark Tiefenbruck, mark at tiefenbruck dot org) + FocusControl.hh/cc *06/04/22: * Fix workspace menu corruption when window title changes (Simon) sf.net bug #1113668
M
src/FocusControl.cc
→
src/FocusControl.cc
@@ -77,108 +77,84 @@ win->isFocusHidden()
); } -void FocusControl::prevFocus(int opts) { +void FocusControl::cycleFocus(int opts, bool cycle_reverse) { int num_windows = m_screen.currentWorkspace()->numberOfWindows(); if (num_windows < 1) return; - if (!(opts & CYCLELINEAR)) { - if (!m_cycling_focus) { - m_cycling_focus = true; - m_cycling_window = m_focused_list.end(); - m_cycling_last = 0; + FocusedWindows *window_list = (opts & CYCLELINEAR) ? &m_creation_order_list : &m_focused_list; + if (!m_cycling_focus) { + m_cycling_focus = true; + if ((opts & CYCLELINEAR) && m_cycling_window != m_focused_list.end()) { + m_cycling_creation_order = true; + m_cycling_window = find(window_list->begin(),window_list->end(),*m_cycling_window); } else { - // already cycling, so restack to put windows back in their proper order - m_screen.layerManager().restack(); + m_cycling_creation_order = (opts & CYCLELINEAR); + m_cycling_window = window_list->begin(); } - // if it is stacked, we want the highest window in the focused list - // that is on the same workspace - FocusedWindows::iterator it = m_cycling_window; - FocusedWindows::iterator it_end = m_focused_list.end(); + m_cycling_last = 0; + } else { + // already cycling, so restack to put windows back in their proper order + m_screen.layerManager().restack(); + if (m_cycling_creation_order ^ (bool)(opts & CYCLELINEAR)) { + m_cycling_creation_order ^= true; + if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end()) + m_cycling_window = find(window_list->begin(),window_list->end(),*m_cycling_window); + else + m_cycling_window = window_list->begin(); + } + } + // if it is stacked, we want the highest window in the focused list + // that is on the same workspace + FocusedWindows::iterator it = m_cycling_window; + FocusedWindows::iterator it_begin = window_list->begin(); + FocusedWindows::iterator it_end = window_list->end(); - while (true) { - --it; - if (it == it_end) { - it = m_focused_list.end(); - --it; - } - // give up [do nothing] if we reach the current focused again - if ((*it) == (*m_cycling_window)) { - break; - } + while (true) { + if (cycle_reverse && it == it_begin) + it = it_end; + cycle_reverse ? --it : ++it; + if (it == it_end) + it = it_begin; + // give up [do nothing] if we reach the current focused again + if ((*it) == (*m_cycling_window)) + break; - FluxboxWindow *fbwin = (*it)->fbwindow(); - if (fbwin && !fbwin->isIconic() && - (fbwin->isStuck() - || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) { - // either on this workspace, or stuck + FluxboxWindow *fbwin = (*it)->fbwindow(); + if (fbwin && !fbwin->isIconic() && + (fbwin->isStuck() + || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) { + // either on this workspace, or stuck - // keep track of the originally selected window in a set - WinClient &last_client = fbwin->winClient(); - + // keep track of the originally selected window in a set + WinClient &last_client = fbwin->winClient(); - if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) { - // moved onto a new fbwin - if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { - if (m_cycling_last) { - // set back to orig current Client in that fbwin - m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); - } - m_cycling_last = &last_client; + if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) { + // moved onto a new fbwin + if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { + if (m_cycling_last) { + // set back to orig current Client in that fbwin + m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); } - fbwin->tempRaise(); - break; + m_cycling_last = &last_client; } - } - } - m_cycling_window = it; - } else { // not stacked cycling - - Workspace &wksp = *m_screen.currentWorkspace(); - Workspace::Windows &wins = wksp.windowList(); - Workspace::Windows::iterator it = wins.begin(); - - FluxboxWindow *focused_group = 0; - // start from the focused window - bool have_focused = false; - WinClient *focused = focusedWindow(); - if (focused != 0) { - if (focused->screen().screenNumber() == m_screen.screenNumber()) { - have_focused = true; - focused_group = focused->fbwindow(); + fbwin->tempRaise(); + break; } } - - if (!have_focused) { - focused_group = (*it); - } else { - //get focused window iterator - for (; it != wins.end() && (*it) != focused_group; ++it) - continue; - } - - do { - if (it == wins.begin()) - it = wins.end(); - --it; - // see if the window should be skipped - if (! (doSkipWindow((*it)->winClient(), opts) || !(*it)->setInputFocus()) ) - break; - } while ((*it) != focused_group); - - if ((*it) != focused_group && it != wins.end()) - (*it)->raise(); } - + m_cycling_window = it; } void FocusControl::addFocusFront(WinClient &client) { m_focused_list.push_front(&client); + m_creation_order_list.push_back(&client); } void FocusControl::addFocusBack(WinClient &client) { m_focused_list.push_back(&client); + m_creation_order_list.push_back(&client); } void FocusControl::stopCyclingFocus() {@@ -191,7 +167,9 @@ m_cycling_last = 0;
// put currently focused window to top // the iterator may be invalid if the window died // in which case we'll do a proper revert focus - if (m_cycling_window != m_focused_list.end()) { + if (m_cycling_creation_order && m_cycling_window != m_creation_order_list.end()) + m_cycling_window = find(m_focused_list.begin(),m_focused_list.end(),*m_cycling_window); + if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end()) { WinClient *client = *m_cycling_window; m_focused_list.erase(m_cycling_window); m_focused_list.push_front(client);@@ -244,108 +222,6 @@ }
return 0; } -void FocusControl::nextFocus(int opts) { - const int num_windows = m_screen.currentWorkspace()->numberOfWindows(); - - if (num_windows < 1) - return; - - if (!(opts & CYCLELINEAR)) { - if (!m_cycling_focus) { - m_cycling_focus = true; - m_cycling_window = m_focused_list.begin(); - m_cycling_last = 0; - } else { - // already cycling, so restack to put windows back in their proper order - m_screen.layerManager().restack(); - } - // if it is stacked, we want the highest window in the focused list - // that is on the same workspace - FocusedWindows::iterator it = m_cycling_window; - const FocusedWindows::iterator it_end = m_focused_list.end(); - int safety_counter = 0; - while (true) { - ++it; - if (it == it_end) { - it = m_focused_list.begin(); - safety_counter++; - if (safety_counter > 3) - break; - } - // give up [do nothing] if we reach the current focused again - if ((*it) == (*m_cycling_window)) { - break; - } - - FluxboxWindow *fbwin = (*it)->fbwindow(); - if (fbwin && !fbwin->isIconic() && - (fbwin->isStuck() - || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) { - // either on this workspace, or stuck - - // keep track of the originally selected window in a set - WinClient &last_client = fbwin->winClient(); - - if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) { - // moved onto a new fbwin - if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { - if (m_cycling_last) { - // set back to orig current Client in that fbwin - m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); - } - m_cycling_last = &last_client; - } - fbwin->tempRaise(); - break; - } - } - } - m_cycling_window = it; - } else { // not stacked cycling - // I really don't like this, but evidently some people use it(!) - Workspace &wksp = *m_screen.currentWorkspace(); - Workspace::Windows &wins = wksp.windowList(); - Workspace::Windows::iterator it = wins.begin(); - - FluxboxWindow *focused_group = 0; - // start from the focused window - bool have_focused = false; - WinClient *focused = focusedWindow(); - if (focused != 0) { - if (focused->screen().screenNumber() == m_screen.screenNumber()) { - have_focused = true; - focused_group = focused->fbwindow(); - } - } - - if (!have_focused) { - focused_group = (*it); - } else { - // get focused window iterator - for (; it != wins.end() && (*it) != focused_group; ++it) - continue; - } - - int safety_counter = 0; - do { - ++it; - if (it == wins.end()) { - it = wins.begin(); - safety_counter++; - if (safety_counter > 3) - break; - } - // see if the window should be skipped - if (! (doSkipWindow((*it)->winClient(), opts) || !(*it)->setInputFocus()) ) - break; - } while ((*it) != focused_group); - - if ((*it) != focused_group && it != wins.end()) - (*it)->raise(); - } - -} - void FocusControl::raiseFocus() { bool have_focused = false;@@ -483,17 +359,14 @@ }
void FocusControl::removeClient(WinClient &client) { WinClient *cyc = 0; - if (m_cycling_window != m_focused_list.end()) + if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end()) cyc = *m_cycling_window; m_focused_list.remove(&client); + m_creation_order_list.remove(&client); - if (cyc == &client) { - m_cycling_window = m_focused_list.end(); - } - - if (m_cycling_last == &client) - m_cycling_last = 0; + if (cyc == &client) + stopCyclingFocus(); }
M
src/FocusControl.hh
→
src/FocusControl.hh
@@ -67,10 +67,11 @@ };
explicit FocusControl(BScreen &screen); - void prevFocus() { prevFocus(0); } - void nextFocus() { nextFocus(0); } - void prevFocus(int options); - void nextFocus(int options); + void prevFocus() { cycleFocus(0, true); } + void nextFocus() { cycleFocus(0, false); } + void prevFocus(int options) { cycleFocus(options, true); } + void nextFocus(int options) { cycleFocus(options, false); } + void cycleFocus(int options, bool cycle_reverse); void raiseFocus(); void setScreenFocusedWindow(WinClient &win_client);@@ -112,8 +113,10 @@
// This list keeps the order of window focusing for this screen // Screen global so it works for sticky windows too. FocusedWindows m_focused_list; + FocusedWindows m_creation_order_list; FocusedWindows::iterator m_cycling_window; bool m_cycling_focus; + bool m_cycling_creation_order; WinClient *m_cycling_last; static WinClient *s_focused_window;