all repos — fluxbox @ 4d52797b955b8e38b9e49802981e69fb34a734bc

custom fork of the fluxbox windowmanager

moved all focus handling to class FocusControl
fluxgen fluxgen
commit

4d52797b955b8e38b9e49802981e69fb34a734bc

parent

d23eeeaa4e1ed5adb76d97eb47dd0b88b6dfed3f

6 files changed, 125 insertions(+), 541 deletions(-)

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

@@ -32,6 +32,8 @@ #include "Window.hh"

#include "Workspace.hh" #include "Netizen.hh" +#include "FocusControl.hh" + // themes #include "FbWinFrameTheme.hh" #include "MenuTheme.hh"

@@ -155,7 +157,6 @@

} // end anonymous namespace - BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm, const std::string &scrname, const std::string &altscrname):

@@ -167,8 +168,6 @@ scrname+".sloppywindowgrouping", altscrname+".SloppyWindowGrouping"),

workspace_warping(rm, true, scrname+".workspacewarping", altscrname+".WorkspaceWarping"), desktop_wheeling(rm, true, scrname+".desktopwheeling", altscrname+".DesktopWheeling"), show_window_pos(rm, true, scrname+".showwindowposition", altscrname+".ShowWindowPosition"), - focus_last(rm, true, scrname+".focusLastWindow", altscrname+".FocusLastWindow"), - focus_new(rm, true, scrname+".focusNewWindows", altscrname+".FocusNewWindows"), antialias(rm, false, scrname+".antialias", altscrname+".Antialias"), auto_raise(rm, false, scrname+".autoRaise", altscrname+".AutoRaise"), click_raises(rm, true, scrname+".clickRaises", altscrname+".ClickRaises"),

@@ -176,8 +175,6 @@ decorate_transient(rm, false, scrname+".decorateTransient", altscrname+".DecorateTransient"),

rootcommand(rm, "", scrname+".rootCommand", altscrname+".RootCommand"), resize_model(rm, BOTTOMRESIZE, scrname+".resizeMode", altscrname+".ResizeMode"), windowmenufile(rm, "", scrname+".windowMenu", altscrname+".WindowMenu"), - focus_model(rm, CLICKFOCUS, scrname+".focusModel", altscrname+".FocusModel"), - tabfocus_model(rm, CLICKTABFOCUS, scrname+".tabFocusModel", altscrname+".TabFocusModel"), follow_model(rm, IGNORE_OTHER_WORKSPACES, scrname+".followModel", altscrname+".followModel"), workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"), edge_snap_threshold(rm, 0, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"),

@@ -221,8 +218,6 @@ m_currentworkspace_sig(*this), // current workspace signal

m_reconfigure_sig(*this), // reconfigure signal m_resize_sig(*this), m_layermanager(num_layers), - cycling_focus(false), - cycling_last(0), m_windowtheme(new FbWinFrameTheme(scrn)), // the order of windowtheme and winbutton theme is important // because winbutton need to rescale the pixmaps in winbutton theme

@@ -239,9 +234,10 @@ 0, 0, 10, 10,

false, // override redirect true), // save under resource(rm, screenname, altscreenname), + m_resource_manager(rm), m_name(screenname), m_altname(altscreenname), - m_resource_manager(rm), + m_focus_control(new FocusControl(*this)), m_xinerama_headinfo(0), m_shutdown(false) {

@@ -277,7 +273,6 @@ "informational message saying screen number (%d), visual (%lx), and colour depth (%d)"),

screenNumber(), XVisualIDFromVisual(rootWindow().visual()), rootWindow().depth()); - cycling_window = focused_list.end(); rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr));

@@ -738,10 +733,10 @@ // any submenu is in the same place as before if the

// menu changed. // if timestamp changed then no restoring - bool restore_menus = ! Fluxbox::instance()->menuTimestampsChanged(); + bool restore_menus = ! fluxbox->menuTimestampsChanged(); // destroy old timestamps - Fluxbox::instance()->clearMenuFilenames(); + fluxbox->clearMenuFilenames(); // save submenu index so we can restore them afterwards vector<int> remember_sub;

@@ -855,17 +850,7 @@

void BScreen::removeClient(WinClient &client) { - WinClient *cyc = 0; - if (cycling_window != focused_list.end()) - cyc = *cycling_window; - - focused_list.remove(&client); - if (cyc == &client) { - cycling_window = focused_list.end(); - } - - if (cycling_last == &client) - cycling_last = 0; + focusControl().removeClient(client); for_each(getWorkspacesList().begin(), getWorkspacesList().end(), mem_fun(&Workspace::updateClientmenu));

@@ -1257,10 +1242,10 @@ }

// always put on end of focused list, if it gets focused it'll get pushed up // there is only the one win client at this stage - if (doFocusNew()) - focused_list.push_front(&win->winClient()); - else - focused_list.push_back(&win->winClient()); + if (focusControl().focusNew()) + focusControl().addFocusFront(win->winClient()); + else + focusControl().addFocusBack(win->winClient()); // we also need to check if another window expects this window to the left // and if so, then join it.

@@ -1391,314 +1376,6 @@ m_clientlist_sig.notify();

} } - -void BScreen::nextFocus(int opts) { - const int num_windows = currentWorkspace()->numberOfWindows(); - - if (num_windows < 1) - return; - - if (!(opts & CYCLELINEAR)) { - if (!cycling_focus) { - cycling_focus = True; - cycling_window = focused_list.begin(); - cycling_last = 0; - } else { - // already cycling, so restack to put windows back in their proper order - m_layermanager.restack(); - } - // if it is stacked, we want the highest window in the focused list - // that is on the same workspace - FocusedWindows::iterator it = cycling_window; - const FocusedWindows::iterator it_end = focused_list.end(); - - while (true) { - ++it; - if (it == it_end) { - it = focused_list.begin(); - } - // give up [do nothing] if we reach the current focused again - if ((*it) == (*cycling_window)) { - break; - } - - FluxboxWindow *fbwin = (*it)->fbwindow(); - if (fbwin && !fbwin->isIconic() && - (fbwin->isStuck() - || fbwin->workspaceNumber() == 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 (!cycling_last || cycling_last->fbwindow() != fbwin) { - if (cycling_last) - // set back to orig current Client in that fbwin - cycling_last->fbwindow()->setCurrentClient(*cycling_last, false); - cycling_last = &last_client; - } - fbwin->tempRaise(); - break; - } - } - } - cycling_window = it; - } else { // not stacked cycling - // I really don't like this, but evidently some people use it(!) - Workspace *wksp = 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 = Fluxbox::instance()->getFocusedWindow(); - if (focused != 0) { - if (focused->screen().screenNumber() == 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; - } - - do { - ++it; - if (it == wins.end()) - it = wins.begin(); - // 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 BScreen::prevFocus(int opts) { - int num_windows = currentWorkspace()->numberOfWindows(); - - if (num_windows < 1) - return; - - if (!(opts & CYCLELINEAR)) { - if (!cycling_focus) { - cycling_focus = true; - cycling_window = focused_list.end(); - cycling_last = 0; - } else { - // already cycling, so restack to put windows back in their proper order - m_layermanager.restack(); - } - // if it is stacked, we want the highest window in the focused list - // that is on the same workspace - FocusedWindows::iterator it = cycling_window; - FocusedWindows::iterator it_end = focused_list.end(); - - while (true) { - --it; - if (it == it_end) { - it = focused_list.end(); - --it; - } - // give up [do nothing] if we reach the current focused again - if ((*it) == (*cycling_window)) { - break; - } - - FluxboxWindow *fbwin = (*it)->fbwindow(); - if (fbwin && !fbwin->isIconic() && - (fbwin->isStuck() - || fbwin->workspaceNumber() == 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 (!cycling_last || cycling_last->fbwindow() != fbwin) { - if (cycling_last) - // set back to orig current Client in that fbwin - cycling_last->fbwindow()->setCurrentClient(*cycling_last, false); - cycling_last = &last_client; - } - fbwin->tempRaise(); - break; - } - } - } - cycling_window = it; - } else { // not stacked cycling - - Workspace *wksp = 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 = Fluxbox::instance()->getFocusedWindow(); - if (focused != 0) { - if (focused->screen().screenNumber() == 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; - } - - 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(); - } -} - - -void BScreen::raiseFocus() { - bool have_focused = false; - Fluxbox &fb = *Fluxbox::instance(); - // set have_focused if the currently focused window - // is on this screen - if (fb.getFocusedWindow()) { - if (fb.getFocusedWindow()->screen().screenNumber() == screenNumber()) { - have_focused = true; - } - } - - // if we have a focused window on this screen and - // number of windows is greater than one raise the focused window - if (currentWorkspace()->numberOfWindows() > 1 && have_focused) - fb.getFocusedWindow()->raise(); -} - -void BScreen::setFocusedWindow(WinClient &winclient) { - // raise newly focused window to the top of the focused list - if (!cycling_focus) { // don't change the order if we're cycling - focused_list.remove(&winclient); - focused_list.push_front(&winclient); - cycling_window = focused_list.begin(); - } -} - -void BScreen::dirFocus(FluxboxWindow &win, const FocusDir dir) { - // change focus to the window in direction dir from the given window - - // we scan through the list looking for the window that is "closest" - // in the given direction - - FluxboxWindow *foundwin = 0; - int weight = 999999, exposure = 0; // extreme values - int borderW = winFrameTheme().border().width(), - top = win.y(), - bottom = win.y() + win.height() + 2*borderW, - left = win.x(), - right = win.x() + win.width() + 2*borderW; - - Workspace::Windows &wins = currentWorkspace()->windowList(); - Workspace::Windows::iterator it = wins.begin(); - for (; it != wins.end(); ++it) { - if ((*it) == &win - || (*it)->isIconic() - || (*it)->isFocusHidden() - || !(*it)->winClient().acceptsFocus()) - continue; // skip self - - // we check things against an edge, and within the bounds (draw a picture) - int edge=0, upper=0, lower=0, oedge=0, oupper=0, olower=0; - - int otop = (*it)->y(), - obottom = (*it)->y() + (*it)->height() + 2*borderW, - oleft = (*it)->x(), - oright = (*it)->x() + (*it)->width() + 2*borderW; - // check if they intersect - switch (dir) { - case FOCUSUP: - edge = obottom; - oedge = bottom; - upper = left; - oupper = oleft; - lower = right; - olower = oright; - break; - case FOCUSDOWN: - edge = top; - oedge = otop; - upper = left; - oupper = oleft; - lower = right; - olower = oright; - break; - case FOCUSLEFT: - edge = oright; - oedge = right; - upper = top; - oupper = otop; - lower = bottom; - olower = obottom; - break; - case FOCUSRIGHT: - edge = left; - oedge = oleft; - upper = top; - oupper = otop; - lower = bottom; - olower = obottom; - break; - } - - if (oedge < edge) continue; // not in the right direction - if (olower <= upper || oupper >= lower) { - // outside our horz bounds, get a heavy weight penalty - int myweight = 100000 + oedge - edge + abs(upper-oupper)+abs(lower-olower); - if (myweight < weight) { - foundwin = *it; - exposure = 0; - weight = myweight; - } - } else if ((oedge - edge) < weight) { - foundwin = *it; - weight = oedge - edge; - exposure = ((lower < olower)?lower:olower) - ((upper > oupper)?upper:oupper); - } else if (foundwin && oedge - edge == weight) { - int myexp = ((lower < olower)?lower:olower) - ((upper > oupper)?upper:oupper); - if (myexp > exposure) { - foundwin = *it; - // weight is same - exposure = myexp; - } - } // else not improvement - } - - if (foundwin) - foundwin->setInputFocus(); -} void BScreen::initMenus() { m_workspacemenu.reset(MenuCreator::createMenuType("workspacemenu", screenNumber())); m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber()));

@@ -1776,22 +1453,29 @@ // create focus menu

// we don't set this to internal menu so will // be deleted toghether with the parent const char *focusmenu_label = _FBTEXT(Configmenu, FocusModel, - "Focus Model", "Method used to give focus to windows"); + "Focus Model", + "Method used to give focus to windows"); FbTk::Menu *focus_menu = createMenu(focusmenu_label ? focusmenu_label : ""); -#define _FOCUSITEM(a, b, c, d, e) focus_menu->insert(new FocusModelMenuItem(_FBTEXT(a, b, c, d), *this, e, save_and_reconfigure)) +#define _FOCUSITEM(a, b, c, d, e) \ + focus_menu->insert(new FocusModelMenuItem(_FBTEXT(a, b, c, d), focusControl(), \ + e, save_and_reconfigure)) _FOCUSITEM(Configmenu, ClickFocus, "Click To Focus", "Click to focus", - CLICKFOCUS); + FocusControl::CLICKFOCUS); _FOCUSITEM(Configmenu, MouseFocus, "Mouse Focus", "Mouse Focus", - MOUSEFOCUS); + FocusControl::MOUSEFOCUS); +#undef _FOCUSITEM - focus_menu->insert(new TabFocusModelMenuItem("ClickTabFocus", *this, CLICKTABFOCUS, save_and_reconfigure)); - focus_menu->insert(new TabFocusModelMenuItem("MouseTabFocus", *this, MOUSETABFOCUS, save_and_reconfigure)); + focus_menu->insert(new TabFocusModelMenuItem("ClickTabFocus", focusControl(), + FocusControl::CLICKTABFOCUS, + save_and_reconfigure)); + focus_menu->insert(new TabFocusModelMenuItem("MouseTabFocus", focusControl(), + FocusControl::MOUSETABFOCUS, + save_and_reconfigure)); -#undef _FOCUSITEM focus_menu->insert(new BoolMenuItem(_FBTEXT(Configmenu, AutoRaise,

@@ -1821,19 +1505,33 @@ _BOOLITEM(Configmenu, ImageDithering,

"Image Dithering", "Image Dithering", *resource.image_dither, save_and_reconfigure); _BOOLITEM(Configmenu, OpaqueMove, - "Opaque Window Moving", "Window Moving with whole window visible (as opposed to outline moving)", + "Opaque Window Moving", + "Window Moving with whole window visible (as opposed to outline moving)", *resource.opaque_move, saverc_cmd); _BOOLITEM(Configmenu, FullMax, "Full Maximization", "Maximise over slit, toolbar, etc", *resource.full_max, saverc_cmd); - _BOOLITEM(Configmenu, FocusNew, - "Focus New Windows", "Focus newly created windows", - *resource.focus_new, saverc_cmd); - _BOOLITEM(Configmenu, FocusLast, - "Focus Last Window on Workspace", "Focus Last Window on Workspace", - *resource.focus_last, saverc_cmd); + try { + _BOOLITEM(Configmenu, FocusNew, + "Focus New Windows", "Focus newly created windows", + *m_resource_manager.getResource<bool>(name() + ".focusNewWindows"), + saverc_cmd); + } catch (FbTk::ResourceException e) { + cerr<<e.what()<<endl; + } + + try { + _BOOLITEM(Configmenu, FocusLast, + "Focus Last Window on Workspace", "Focus Last Window on Workspace", + *resourceManager().getResource<bool>(name() + ".focusLastWindow"), + saverc_cmd); + } catch (FbTk::ResourceException e) { + cerr<<e.what()<<endl; + } + _BOOLITEM(Configmenu, WorkspaceWarping, - "Workspace Warping", "Workspace Warping - dragging windows to the edge and onto the next workspace", + "Workspace Warping", + "Workspace Warping - dragging windows to the edge and onto the next workspace", *resource.workspace_warping, saverc_cmd); _BOOLITEM(Configmenu, DesktopWheeling, "Desktop MouseWheel Switching", "Workspace switching using mouse wheel",

@@ -1850,26 +1548,38 @@ if (FbTk::Transparent::haveRender() ||

FbTk::Transparent::haveComposite()) { const char *alphamenu_label = _FBTEXT(Configmenu, Transparency, - "Transparency", "Menu containing various transparency options"); + "Transparency", + "Menu containing various transparency options"); FbTk::Menu *alpha_menu = createMenu(alphamenu_label ? alphamenu_label : ""); if (FbTk::Transparent::haveComposite(true)) { alpha_menu->insert(new BoolMenuItem(_FBTEXT(Configmenu, ForcePseudoTrans, - "Force Pseudo-Transparency", "When composite is available, still use old pseudo-transparency"), + "Force Pseudo-Transparency", + "When composite is available, still use old pseudo-transparency"), Fluxbox::instance()->getPseudoTrans(), save_and_reconfigure)); } - FbTk::MenuItem *focused_alpha_item = new IntResMenuItem(_FBTEXT(Configmenu, FocusedAlpha, "Focused Window Alpha", "Transparency level of the focused window"), + FbTk::MenuItem *focused_alpha_item = + new IntResMenuItem(_FBTEXT(Configmenu, FocusedAlpha, + "Focused Window Alpha", + "Transparency level of the focused window"), resource.focused_alpha, 0, 255, *alpha_menu); focused_alpha_item->setCommand(saverc_cmd); alpha_menu->insert(focused_alpha_item); - FbTk::MenuItem *unfocused_alpha_item = new IntResMenuItem(_FBTEXT(Configmenu, UnfocusedAlpha, "Unfocused Window Alpha", "Transparency level of unfocused windows"), + FbTk::MenuItem *unfocused_alpha_item = + new IntResMenuItem(_FBTEXT(Configmenu, + UnfocusedAlpha, + "Unfocused Window Alpha", + "Transparency level of unfocused windows"), + resource.unfocused_alpha, 0, 255, *alpha_menu); unfocused_alpha_item->setCommand(saverc_cmd); alpha_menu->insert(unfocused_alpha_item); - FbTk::MenuItem *menu_alpha_item = new IntResMenuItem(_FBTEXT(Configmenu, MenuAlpha, "Menu Alpha", "Transparency level of menu"), + FbTk::MenuItem *menu_alpha_item = + new IntResMenuItem(_FBTEXT(Configmenu, MenuAlpha, + "Menu Alpha", "Transparency level of menu"), resource.menu_alpha, 0, 255, *alpha_menu); menu_alpha_item->setCommand(saverc_cmd); alpha_menu->insert(menu_alpha_item);

@@ -1907,7 +1617,8 @@ m_pos_window.move(getHeadX(head) + (getHeadWidth(head) - m_pos_window.width()) / 2,

getHeadY(head) + (getHeadHeight(head) - m_pos_window.height()) / 2); } else { - m_pos_window.move((width() - m_pos_window.width()) / 2, (height() - m_pos_window.height()) / 2); + m_pos_window.move((width() - m_pos_window.width()) / 2, + (height() - m_pos_window.height()) / 2); } m_pos_window.show();

@@ -1954,9 +1665,10 @@ if (hasXinerama()) {

unsigned int head = getCurrHead(); m_geom_window.move(getHeadX(head) + (getHeadWidth(head) - m_geom_window.width()) / 2, - getHeadY(head) + (getHeadHeight(head) - m_geom_window.height()) / 2); + getHeadY(head) + (getHeadHeight(head) - m_geom_window.height()) / 2); } else { - m_geom_window.move((width() - m_geom_window.width()) / 2, (height() - m_geom_window.height()) / 2); + m_geom_window.move((width() - m_geom_window.width()) / 2, + (height() - m_geom_window.height()) / 2); } m_geom_window.show();

@@ -2029,19 +1741,6 @@ if (currentWorkspaceID() >= static_cast<unsigned int>(delta))

changeWorkspaceID(currentWorkspaceID()-delta); } -/** - @return true if the windows should be skiped else false -*/ -bool BScreen::doSkipWindow(const WinClient &winclient, int opts) { - const FluxboxWindow *win = winclient.fbwindow(); - return (!win || - (opts & CYCLESKIPSTUCK) != 0 && win->isStuck() || // skip if stuck - // skip if not active client (i.e. only visit each fbwin once) - (opts & CYCLEGROUPS) != 0 && win->winClient().window() != winclient.window() || - (opts & CYCLESKIPSHADED) != 0 && win->isShaded() || // skip if shaded - win->isFocusHidden() - ); -} void BScreen::renderGeomWindow() { _FB_USES_NLS;

@@ -2139,63 +1838,7 @@ /**

Called when a set of watched modifiers has been released */ void BScreen::notifyReleasedKeys(XKeyEvent &ke) { - if (cycling_focus) { - cycling_focus = false; - 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 (cycling_window != focused_list.end()) { - WinClient *client = *cycling_window; - focused_list.erase(cycling_window); - focused_list.push_front(client); - client->fbwindow()->raise(); - } else { - Fluxbox::instance()->revertFocus(*this); - } - } -} - -/** - * Used to find out which window was last focused on the given workspace - * If workspace is outside the ID range, then the absolute last focused window - * is given. - */ -WinClient *BScreen::getLastFocusedWindow(int workspace) { - if (focused_list.empty()) return 0; - if (workspace < 0 || workspace >= (int) numberOfWorkspaces()) - return focused_list.front(); - - FocusedWindows::iterator it = focused_list.begin(); - FocusedWindows::iterator it_end = focused_list.end(); - for (; it != it_end; ++it) { - if ((*it)->fbwindow() && - (((int)(*it)->fbwindow()->workspaceNumber()) == workspace - && !(*it)->fbwindow()->isIconic() - && (!(*it)->fbwindow()->isStuck() || (*it)->fbwindow()->isFocused()))) - // only give focus to a stuck window if it is currently focused - // otherwise they tend to override normal workspace focus - return *it; - } - return 0; -} - -/** - * Used to find out which window was last active in the given group - * If ignore_client is given, it excludes that client. - * Stuck, iconic etc don't matter within a group - */ -WinClient *BScreen::getLastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client) { - if (focused_list.empty()) return 0; - - FocusedWindows::iterator it = focused_list.begin(); - FocusedWindows::iterator it_end = focused_list.end(); - for (; it != it_end; ++it) { - if (((*it)->fbwindow() == &group) && - (*it) != ignore_client) - return *it; - } - return 0; + focusControl().stopCyclingFocus(); } void BScreen::updateSize() {
M src/Screen.hhsrc/Screen.hh

@@ -62,6 +62,7 @@ class Workspace;

class Strut; class Slit; class HeadArea; +class FocusControl; namespace FbTk { class Menu;

@@ -77,25 +78,30 @@ Create workspaces, handles switching between workspaces and windows

*/ class BScreen : public FbTk::Observer, private FbTk::NotCopyable { public: - enum ResizeModel { BOTTOMRESIZE = 0, QUADRANTRESIZE, DEFAULTRESIZE = BOTTOMRESIZE }; - enum FocusModel { MOUSEFOCUS = 0, CLICKFOCUS }; - enum TabFocusModel { MOUSETABFOCUS = 0, CLICKTABFOCUS }; - enum FollowModel { ///< a window becomes active / focussed on a different workspace + /// a window becomes active / focussed on a different workspace + enum FollowModel { IGNORE_OTHER_WORKSPACES = 0, ///< who cares? FOLLOW_ACTIVE_WINDOW, ///< go to that workspace FETCH_ACTIVE_WINDOW ///< put that window to the current workspace }; - enum FocusDir { FOCUSUP, FOCUSDOWN, FOCUSLEFT, FOCUSRIGHT }; - enum PlacementPolicy { ROWSMARTPLACEMENT, COLSMARTPLACEMENT, - CASCADEPLACEMENT, UNDERMOUSEPLACEMENT}; + + enum ResizeModel { + BOTTOMRESIZE = 0, + QUADRANTRESIZE, + DEFAULTRESIZE = BOTTOMRESIZE }; + + enum PlacementPolicy { + ROWSMARTPLACEMENT, + COLSMARTPLACEMENT, + CASCADEPLACEMENT, + UNDERMOUSEPLACEMENT + }; + enum RowDirection { LEFTRIGHT, RIGHTLEFT}; enum ColumnDirection { TOPBOTTOM, BOTTOMTOP}; - // prevFocus/nextFocus option bits - enum { CYCLEGROUPS = 0x01, CYCLESKIPSTUCK = 0x02, CYCLESKIPSHADED = 0x04, - CYCLELINEAR = 0x08, CYCLEDEFAULT = 0x00 }; typedef std::vector<FluxboxWindow *> Icons; - typedef std::list<WinClient *> FocusedWindows; + typedef std::vector<Workspace *> Workspaces; typedef std::vector<std::string> WorkspaceNames; typedef std::list<std::pair<const char *, FbTk::Menu *> > ExtraMenus;

@@ -107,8 +113,7 @@ ~BScreen();

void initWindows(); void initMenus(); - bool isMouseFocus() const { return (*resource.focus_model == MOUSEFOCUS); } - bool isMouseTabFocus() const { return (*resource.tabfocus_model == MOUSETABFOCUS); } + bool isRootColormapInstalled() const { return root_colormap_installed; } bool isScreenManaged() const { return managed; } bool isSloppyWindowGrouping() const { return *resource.sloppy_window_grouping; }

@@ -118,8 +123,6 @@ bool doAutoRaise() const { return *resource.auto_raise; }

bool clickRaises() const { return *resource.click_raises; } bool doOpaqueMove() const { return *resource.opaque_move; } bool doFullMax() const { return *resource.full_max; } - bool doFocusNew() const { return *resource.focus_new; } - bool doFocusLast() const { return *resource.focus_last; } bool doShowWindowPos() const { return *resource.show_window_pos; } bool antialias() const { return *resource.antialias; } bool decorateTransient() const { return *resource.decorate_transient; }

@@ -134,11 +137,9 @@ const FbTk::Menu &windowMenu() const { return *m_windowmenu.get(); }

FbTk::Menu &windowMenu() { return *m_windowmenu.get(); } ExtraMenus &extraWindowMenus() { return m_extramenus; } const ExtraMenus &extraWindowMenus() const { return m_extramenus; } - - ResizeModel getResizeModel() const { return *resource.resize_model; } - FocusModel getFocusModel() const { return *resource.focus_model; } - TabFocusModel getTabFocusModel() const { return *resource.tabfocus_model; } + ResizeModel getResizeModel() const { return *resource.resize_model; } + inline FollowModel getFollowModel() const { return *resource.follow_model; } inline const std::string &getScrollAction() const { return *resource.scroll_action; }

@@ -154,6 +155,8 @@

const FbTk::Menu &workspaceMenu() const { return *m_workspacemenu.get(); } FbTk::Menu &workspaceMenu() { return *m_workspacemenu.get(); } + const FocusControl &focusControl() const { return *m_focus_control; } + FocusControl &focusControl() { return *m_focus_control; } unsigned int currentWorkspaceID() const; /*

@@ -177,10 +180,7 @@ unsigned int numberOfWorkspaces() const { return m_workspaces_list.size(); }

inline const Icons &iconList() const { return m_icon_list; } inline Icons &iconList() { return m_icon_list; } - inline const FocusedWindows &getFocusedList() const { return focused_list; } - inline FocusedWindows &getFocusedList() { return focused_list; } - WinClient *getLastFocusedWindow(int workspace = -1); - WinClient *getLastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client = 0); + const Workspaces &getWorkspacesList() const { return m_workspaces_list; } Workspaces &getWorkspacesList() { return m_workspaces_list; } const WorkspaceNames &getWorkspaceNames() const { return m_workspace_names; }

@@ -225,8 +225,6 @@ inline ColumnDirection getColPlacementDirection() const { return *resource.col_direction; }

void setRootColormapInstalled(bool r) { root_colormap_installed = r; } void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd; } - void saveFocusModel(FocusModel model) { resource.focus_model = model; } - void saveTabFocusModel(TabFocusModel model) { resource.tabfocus_model = model; } void saveWorkspaces(int w) { *resource.workspaces = w; }

@@ -280,15 +278,7 @@ void sendToWorkspace(unsigned int workspace, FluxboxWindow *win=0,

bool changeworkspace=true); void reassociateWindow(FluxboxWindow *window, unsigned int workspace_id, bool ignore_sticky); - void prevFocus() { prevFocus(0); } - void nextFocus() { nextFocus(0); } - void prevFocus(int options); - void nextFocus(int options); - void raiseFocus(); - void setFocusedWindow(WinClient &winclient); - - void dirFocus(FluxboxWindow &win, const FocusDir dir); void reconfigure(); void rereadMenu();

@@ -382,7 +372,6 @@

private: void setupConfigmenu(FbTk::Menu &menu); void initMenu(); - bool doSkipWindow(const WinClient &winclient, int options); void renderGeomWindow(); void renderPosWindow();

@@ -400,7 +389,8 @@ m_resize_sig; ///< resize signal

FbTk::MultLayers m_layermanager; - bool root_colormap_installed, managed, geom_visible, pos_visible, cycling_focus; + bool root_colormap_installed, managed, geom_visible, pos_visible; + GC opGC; Pixmap geom_pixmap, pos_pixmap;

@@ -421,12 +411,6 @@ Netizens m_netizen_list;

Configmenus m_configmenu_list; Icons m_icon_list; - // This list keeps the order of window focusing for this screen - // Screen global so it works for sticky windows too. - FocusedWindows focused_list; - FocusedWindows::iterator cycling_window; - WinClient *cycling_last; - std::auto_ptr<Slit> m_slit; Workspace *m_current_workspace;

@@ -448,14 +432,11 @@ const std::string &altscrname);

FbTk::Resource<bool> image_dither, opaque_move, full_max, sloppy_window_grouping, workspace_warping, - desktop_wheeling, show_window_pos, - focus_last, focus_new, + desktop_wheeling, show_window_pos, antialias, auto_raise, click_raises, decorate_transient; FbTk::Resource<std::string> rootcommand; FbTk::Resource<ResizeModel> resize_model; FbTk::Resource<std::string> windowmenufile; - FbTk::Resource<FocusModel> focus_model; - FbTk::Resource<TabFocusModel> tabfocus_model; FbTk::Resource<FollowModel> follow_model; bool ordered_dither; FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha,

@@ -473,13 +454,15 @@ FbTk::Resource<bool> scroll_reverse;

} resource; + FbTk::ResourceManager &m_resource_manager; + const std::string m_name, m_altname; + + FocusControl *m_focus_control; + // This is a map of windows to clients for clients that had a left // window set, but that window wasn't present at the time typedef std::map<Window, WinClient *> Groupables; Groupables m_expecting_groups; - - const std::string m_name, m_altname; - FbTk::ResourceManager &m_resource_manager; // Xinerama related private data bool m_xinerama_avail;
M src/ScreenResources.ccsrc/ScreenResources.cc

@@ -151,53 +151,6 @@ m_value = BScreen::DEFAULTRESIZE;

} template<> -std::string FbTk::Resource<BScreen::FocusModel>::getString() const { - switch (m_value) { - case BScreen::MOUSEFOCUS: - return string("MouseFocus"); - case BScreen::CLICKFOCUS: - return string("ClickFocus"); - } - // default string - return string("ClickFocus"); -} - -template<> -void FbTk::Resource<BScreen::FocusModel>:: -setFromString(char const *strval) { - if (strcasecmp(strval, "MouseFocus") == 0) - m_value = BScreen::MOUSEFOCUS; - else if (strcasecmp(strval, "ClickToFocus") == 0) - m_value = BScreen::CLICKFOCUS; - else - setDefaultValue(); -} - -template<> - -std::string FbTk::Resource<BScreen::TabFocusModel>::getString() const { - switch (m_value) { - case BScreen::MOUSETABFOCUS: - return string("SloppyTabFocus"); - case BScreen::CLICKTABFOCUS: - return string("ClickToTabFocus"); - } - // default string - return string("ClickToTabFocus"); -} - -template<> -void FbTk::Resource<BScreen::TabFocusModel>:: -setFromString(char const *strval) { - if (strcasecmp(strval, "SloppyTabFocus") == 0 ) - m_value = BScreen::MOUSETABFOCUS; - else if (strcasecmp(strval, "ClickToTabFocus") == 0) - m_value = BScreen::CLICKTABFOCUS; - else - setDefaultValue(); -} - -template<> std::string FbTk::Resource<BScreen::FollowModel>::getString() const { switch (m_value) { case BScreen::FOLLOW_ACTIVE_WINDOW:
M src/Window.ccsrc/Window.cc

@@ -40,6 +40,7 @@ #include "WindowCmd.hh"

#include "Remember.hh" #include "MenuCreator.hh" #include "StringUtil.hh" +#include "FocusControl.hh" #include "FbTk/TextButton.hh" #include "FbTk/Compose.hh"

@@ -775,7 +776,7 @@ #endif // DEBUG

// if it is our active client, deal with it... if (m_client == &client) { - WinClient *next_client = screen().getLastFocusedWindow(*this, m_client); + WinClient *next_client = screen().focusControl().lastFocusedWindow(*this, m_client); if (next_client != 0) setCurrentClient(*next_client, false); }

@@ -1540,7 +1541,7 @@ }

show(); - if (was_iconic && screen().doFocusNew()) + if (was_iconic && screen().focusControl().focusNew()) setInputFocus();

@@ -2032,7 +2033,7 @@ #endif // DEBUG

// Record focus timestamp for window cycling enhancements if (focused) { gettimeofday(&m_last_focus_time, 0); - screen().setFocusedWindow(*m_client); + screen().focusControl().setScreenFocusedWindow(*m_client); } installColormap(focus);

@@ -2040,7 +2041,7 @@

if (focus != frame().focused()) frame().setFocus(focus); - if ((screen().isMouseFocus()) + if ((screen().focusControl().isMouseFocus()) && screen().doAutoRaise()) { if (focused) m_timer.start();

@@ -2407,7 +2408,7 @@ return;

setState(NormalState, false); - if (client->isTransient() || screen().doFocusNew()) + if (client->isTransient() || screen().focusControl().focusNew()) setCurrentClient(*client, true); else setFocusFlag(false);

@@ -2644,7 +2645,7 @@ // check frame events first

frame().buttonPressEvent(be); if (be.button == 1 || (be.button == 3 && be.state == Mod1Mask)) { - if ((! focused) && (! screen().isMouseFocus())) { //check focus + if ((! focused) && (! screen().focusControl().isMouseFocus())) { //check focus setInputFocus(); }

@@ -2939,7 +2940,7 @@ return;

} WinClient *client = 0; - if (screen().isMouseTabFocus()) { + if (screen().focusControl().isMouseTabFocus()) { // determine if we're in a label button (tab) Client2ButtonMap::iterator it = find_if(m_labelbuttons.begin(),

@@ -2956,7 +2957,7 @@ if (ev.window == frame().window() ||

ev.window == m_client->window() || client) { - if (screen().isMouseFocus() && !isFocused()) { + if (screen().focusControl().isMouseFocus() && !isFocused()) { // check that there aren't any subsequent leave notify events in the // X event queue

@@ -2972,7 +2973,7 @@ }

} } - if (screen().isMouseTabFocus() && client && client != m_client) { + if (screen().focusControl().isMouseTabFocus() && client && client != m_client) { setCurrentClient(*client, isFocused()); }
M src/WorkspaceCmd.hhsrc/WorkspaceCmd.hh

@@ -25,7 +25,9 @@

#ifndef WORKSPACECMD_HH #define WORKSPACECMD_HH #include "Command.hh" -#include "Screen.hh" + +#include "FocusControl.hh" + class NextWindowCmd: public FbTk::Command { public:

@@ -45,10 +47,10 @@ };

class DirFocusCmd: public FbTk::Command { public: - explicit DirFocusCmd(const BScreen::FocusDir dir): m_dir(dir) { } + explicit DirFocusCmd(const FocusControl::FocusDir dir): m_dir(dir) { } void execute(); private: - const BScreen::FocusDir m_dir; + const FocusControl::FocusDir m_dir; }; class NextWorkspaceCmd: public FbTk::Command {
M src/fluxbox.ccsrc/fluxbox.cc

@@ -34,6 +34,8 @@ #include "FbCommands.hh"

#include "WinClient.hh" #include "Keys.hh" #include "FbAtoms.hh" +#include "FocusControl.hh" + #include "defaults.hh" #include "FbTk/I18n.hh"

@@ -1050,9 +1052,9 @@ BScreen *screen = searchScreen(ce.window);

if (screen) { if (! ce.data.l[0]) - screen->prevFocus(); + screen->focusControl().prevFocus(); else - screen->nextFocus(); + screen->focusControl().nextFocus(); } } else if (ce.message_type == m_fbatoms->getFluxboxChangeAttributesAtom()) { WinClient *winclient = searchWindow(ce.window);

@@ -1887,18 +1889,18 @@ void Fluxbox::revertFocus(BScreen &screen) {

// Relevant resources: // resource.focus_last = whether we focus last focused when changing workspace // BScreen::FocusModel = sloppy, click, whatever - WinClient *next_focus = screen.getLastFocusedWindow(screen.currentWorkspaceID()); + WinClient *next_focus = screen.focusControl().lastFocusedWindow(screen.currentWorkspaceID()); // if setting focus fails, or isn't possible, fallback correctly if (!(next_focus && next_focus->fbwindow() && next_focus->fbwindow()->setCurrentClient(*next_focus, true))) { setFocusedWindow(0); // so we don't get dangling m_focused_window pointer - switch (screen.getFocusModel()) { - case BScreen::MOUSEFOCUS: + switch (screen.focusControl().focusModel()) { + case FocusControl::MOUSEFOCUS: XSetInputFocus(FbTk::App::instance()->display(), PointerRoot, None, CurrentTime); break; - case BScreen::CLICKFOCUS: + case FocusControl::CLICKFOCUS: screen.rootWindow().setInputFocus(RevertToPointerRoot, CurrentTime); break; }

@@ -1942,7 +1944,7 @@

BScreen &screen = fbwin->screen(); if (!unfocus_frame) { - WinClient *last_focus = screen.getLastFocusedWindow(*fbwin, &client); + WinClient *last_focus = screen.focusControl().lastFocusedWindow(*fbwin, &client); if (last_focus != 0 && fbwin->setCurrentClient(*last_focus, m_focused_window == &client)) { return;