moved all focus handling to class FocusControl

This commit is contained in:
fluxgen 2006-02-18 11:39:38 +00:00
parent d23eeeaa4e
commit 4d52797b95
6 changed files with 126 additions and 542 deletions

View file

@ -32,6 +32,8 @@
#include "Workspace.hh"
#include "Netizen.hh"
#include "FocusControl.hh"
// themes
#include "FbWinFrameTheme.hh"
#include "MenuTheme.hh"
@ -155,7 +157,6 @@ int anotherWMRunning(Display *display, XErrorEvent *) {
} // end anonymous namespace
BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
const std::string &scrname,
const std::string &altscrname):
@ -167,8 +168,6 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
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 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
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 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
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 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
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 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
screenNumber(), XVisualIDFromVisual(rootWindow().visual()),
rootWindow().depth());
cycling_window = focused_list.end();
rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr));
@ -738,10 +733,10 @@ void BScreen::reconfigure() {
// 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::removeWindow(FluxboxWindow *win) {
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 @@ FluxboxWindow *BScreen::createWindow(Window client) {
// 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 @@ void BScreen::reassociateWindow(FluxboxWindow *w, unsigned int wkspc_id,
}
}
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,23 +1453,30 @@ void BScreen::setupConfigmenu(FbTk::Menu &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);
focus_menu->insert(new TabFocusModelMenuItem("ClickTabFocus", *this, CLICKTABFOCUS, save_and_reconfigure));
focus_menu->insert(new TabFocusModelMenuItem("MouseTabFocus", *this, MOUSETABFOCUS, save_and_reconfigure));
FocusControl::MOUSEFOCUS);
#undef _FOCUSITEM
focus_menu->insert(new TabFocusModelMenuItem("ClickTabFocus", focusControl(),
FocusControl::CLICKTABFOCUS,
save_and_reconfigure));
focus_menu->insert(new TabFocusModelMenuItem("MouseTabFocus", focusControl(),
FocusControl::MOUSETABFOCUS,
save_and_reconfigure));
focus_menu->insert(new BoolMenuItem(_FBTEXT(Configmenu,
AutoRaise,
"Auto Raise",
@ -1821,19 +1505,33 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
"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 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
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 @@ void BScreen::showPosition(int x, int y) {
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 @@ void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
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 @@ void BScreen::leftWorkspace(const 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 @@ void BScreen::renderPosWindow() {
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() {

View file

@ -62,6 +62,7 @@ class Workspace;
class Strut;
class Slit;
class HeadArea;
class FocusControl;
namespace FbTk {
class Menu;
@ -77,25 +78,30 @@ class Subject;
*/
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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,16 +278,8 @@ public:
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();
void shutdown();
@ -382,7 +372,6 @@ public:
private:
void setupConfigmenu(FbTk::Menu &menu);
void initMenu();
bool doSkipWindow(const WinClient &winclient, int options);
void renderGeomWindow();
void renderPosWindow();
@ -400,7 +389,8 @@ private:
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 @@ private:
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 @@ private:
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,14 +454,16 @@ private:
} 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;
int m_xinerama_num_heads;

View file

@ -150,53 +150,6 @@ setFromString(char const *strval) {
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) {

View file

@ -40,6 +40,7 @@
#include "Remember.hh"
#include "MenuCreator.hh"
#include "StringUtil.hh"
#include "FocusControl.hh"
#include "FbTk/TextButton.hh"
#include "FbTk/Compose.hh"
@ -775,7 +776,7 @@ bool FluxboxWindow::removeClient(WinClient &client) {
// 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 @@ void FluxboxWindow::deiconify(bool reassoc, bool do_raise) {
show();
if (was_iconic && screen().doFocusNew())
if (was_iconic && screen().focusControl().focusNew())
setInputFocus();
@ -2032,7 +2033,7 @@ void FluxboxWindow::setFocusFlag(bool focus) {
// 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 @@ void FluxboxWindow::setFocusFlag(bool focus) {
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 @@ void FluxboxWindow::mapNotifyEvent(XMapEvent &ne) {
setState(NormalState, false);
if (client->isTransient() || screen().doFocusNew())
if (client->isTransient() || screen().focusControl().focusNew())
setCurrentClient(*client, true);
else
setFocusFlag(false);
@ -2644,7 +2645,7 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
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 @@ void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) {
}
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 @@ void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) {
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 @@ void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) {
}
}
if (screen().isMouseTabFocus() && client && client != m_client) {
if (screen().focusControl().isMouseTabFocus() && client && client != m_client) {
setCurrentClient(*client, isFocused());
}

View file

@ -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 @@ private:
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 {

View file

@ -34,6 +34,8 @@
#include "WinClient.hh"
#include "Keys.hh"
#include "FbAtoms.hh"
#include "FocusControl.hh"
#include "defaults.hh"
#include "FbTk/I18n.hh"
@ -1050,9 +1052,9 @@ void Fluxbox::handleClientMessage(XClientMessageEvent &ce) {
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 @@ void Fluxbox::unfocusWindow(WinClient &client, bool full_revert, bool unfocus_fr
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;