allow arbitrary window patterns in iconbar
This commit is contained in:
parent
807a1b5575
commit
5d7043320d
28 changed files with 724 additions and 463 deletions
|
@ -1,5 +1,11 @@
|
|||
(Format: Year/Month/Day)
|
||||
Changes for 1.0.1:
|
||||
*07/11/12:
|
||||
* Allow arbitrary window patterns for the iconbar mode (Mark)
|
||||
- Note: for now, if you match against the current head of a window, it will
|
||||
not be updated as expected in the toolbar
|
||||
ClientPattern.cc/hh FocusControl.cc/hh IconbarTool.cc/hh FbTk/Subject.cc
|
||||
fluxbox.cc, added FocusableList.cc/hh
|
||||
*07/11/08:
|
||||
* Fix crash when cycling focus and window closes, bug #1787345 (Mark)
|
||||
FocusControl.cc
|
||||
|
|
|
@ -31,4 +31,4 @@ session.colorsPerChannel: 4
|
|||
session.doubleClickInterval: 250
|
||||
session.cacheMax: 200
|
||||
session.imageDither: True
|
||||
session.configVersion: 4
|
||||
session.configVersion: 5
|
||||
|
|
|
@ -779,15 +779,10 @@ session.screen0.toolbar.onhead: <integer>
|
|||
head where they would like to see the slit and toolbar, starting from 1.
|
||||
Setting this to 0 will ignore xinerama information. Default: 0
|
||||
|
||||
session.screen0.iconbar.mode: <mode>
|
||||
This value is set in the Iconbar Mode menu. The available options are::
|
||||
- All Windows
|
||||
- Icons
|
||||
- NoIcons
|
||||
- None
|
||||
- Workspace
|
||||
- WorkspaceIcons
|
||||
- WorkspaceNoIcons
|
||||
session.screen0.iconbar.mode: <pattern>
|
||||
This determines which windows will be displayed in the iconbar. Any window
|
||||
pattern available to the Next/PrevWindow keybindings is acceptable.
|
||||
Default: {static groups} (workspace)
|
||||
|
||||
session.screen0.iconbar.usePixmap: <boolean>
|
||||
This is also set in the Iconbar Mode menu. When set to True, this will
|
||||
|
|
|
@ -274,9 +274,19 @@ bool ClientPattern::match(const Focusable &win) const {
|
|||
for (; it != it_end; ++it) {
|
||||
if ((*it)->orig == "[current]") {
|
||||
WinClient *focused = FocusControl::focusedWindow();
|
||||
if (!focused || !((*it)->negate ^
|
||||
(getProperty((*it)->prop, win) ==
|
||||
getProperty((*it)->prop, *focused))))
|
||||
if ((*it)->prop == WORKSPACE) {
|
||||
char tmpstr[128];
|
||||
sprintf(tmpstr, "%d", win.screen().currentWorkspaceID());
|
||||
if (!(*it)->negate ^ (getProperty((*it)->prop, win) == tmpstr))
|
||||
return false;
|
||||
} else if ((*it)->prop == WORKSPACENAME) {
|
||||
const Workspace *w = win.screen().currentWorkspace();
|
||||
if (!w || (!(*it)->negate ^
|
||||
(getProperty((*it)->prop, win) == w->name())))
|
||||
return false;
|
||||
} else if (!focused || (!(*it)->negate ^
|
||||
(getProperty((*it)->prop, win) ==
|
||||
getProperty((*it)->prop, *focused))))
|
||||
return false;
|
||||
} else if ((*it)->prop == HEAD &&
|
||||
(*it)->orig == "[mouse]") {
|
||||
|
@ -293,6 +303,26 @@ bool ClientPattern::match(const Focusable &win) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ClientPattern::dependsOnFocusedWindow() const {
|
||||
Terms::const_iterator it = m_terms.begin(), it_end = m_terms.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if ((*it)->prop != WORKSPACE && (*it)->prop != WORKSPACENAME &&
|
||||
(*it)->orig == "[current]")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientPattern::dependsOnCurrentWorkspace() const {
|
||||
Terms::const_iterator it = m_terms.begin(), it_end = m_terms.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (((*it)->prop == WORKSPACE || (*it)->prop == WORKSPACENAME) &&
|
||||
(*it)->orig == "[current]")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// add an expression to match against
|
||||
// The first argument is a regular expression, the second is the member
|
||||
// function that we wish to match against.
|
||||
|
|
|
@ -62,6 +62,12 @@ public:
|
|||
/// Does this client match this pattern?
|
||||
bool match(const Focusable &win) const;
|
||||
|
||||
/// Does this pattern depend on the focused window?
|
||||
bool dependsOnFocusedWindow() const;
|
||||
|
||||
/// Does this pattern depend on the current workspace?
|
||||
bool dependsOnCurrentWorkspace() const;
|
||||
|
||||
/**
|
||||
* Add an expression to match against
|
||||
* @param str is a regular expression
|
||||
|
|
|
@ -33,7 +33,7 @@ bool ColSmartPlacement::placeWindow(const FluxboxWindow &win, int head,
|
|||
|
||||
std::list<FluxboxWindow *> windowlist;
|
||||
const std::list<Focusable *> focusables =
|
||||
win.screen().focusControl().focusedOrderWinList();
|
||||
win.screen().focusControl().focusedOrderWinList().clientList();
|
||||
std::list<Focusable *>::const_iterator foc_it = focusables.begin(),
|
||||
foc_it_end = focusables.end();
|
||||
unsigned int workspace = win.workspaceNumber();
|
||||
|
|
|
@ -345,7 +345,8 @@ void Ewmh::updateClientList(BScreen &screen) {
|
|||
if (screen.isShuttingdown())
|
||||
return;
|
||||
|
||||
list<Focusable *> creation_order_list = screen.focusControl().creationOrderList();
|
||||
list<Focusable *> creation_order_list =
|
||||
screen.focusControl().creationOrderList().clientList();
|
||||
|
||||
size_t num = creation_order_list.size();
|
||||
Window *wl = FB_new_nothrow Window[num];
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "FbCommandFactory.hh"
|
||||
|
||||
#include "FocusableList.hh"
|
||||
#include "CurrentWindowCmd.hh"
|
||||
#include "FbCommands.hh"
|
||||
#include "Window.hh"
|
||||
|
@ -59,26 +60,6 @@ static int getint(const char *str, int defaultvalue) {
|
|||
return defaultvalue;
|
||||
}
|
||||
|
||||
void parseNextWindowArgs(const string &in, int &opts, string &pat) {
|
||||
string options;
|
||||
int err = FbTk::StringUtil::getStringBetween(options, in.c_str(), '{', '}');
|
||||
|
||||
// the rest of the string is a ClientPattern
|
||||
pat = in.c_str() + err;
|
||||
|
||||
// now parse the options
|
||||
vector<string> args;
|
||||
FbTk::StringUtil::stringtok(args, options);
|
||||
vector<string>::iterator it = args.begin(), it_end = args.end();
|
||||
opts = 0;
|
||||
for (; it != it_end; ++it) {
|
||||
if (strcasecmp((*it).c_str(), "static") == 0)
|
||||
opts |= FocusControl::CYCLELINEAR;
|
||||
else if (strcasecmp((*it).c_str(), "groups") == 0)
|
||||
opts |= FocusControl::CYCLEGROUPS;
|
||||
}
|
||||
}
|
||||
|
||||
}; // end anonymous namespace
|
||||
|
||||
FbCommandFactory::FbCommandFactory() {
|
||||
|
@ -522,29 +503,29 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
|
|||
} else if (command == "attach") {
|
||||
int opts; // not used
|
||||
string pat;
|
||||
parseNextWindowArgs(arguments, opts, pat);
|
||||
FocusableList::parseArgs(arguments, opts, pat);
|
||||
return new AttachCmd(pat);
|
||||
} else if (command == "nextwindow") {
|
||||
int opts;
|
||||
string pat;
|
||||
parseNextWindowArgs(arguments, opts, pat);
|
||||
FocusableList::parseArgs(arguments, opts, pat);
|
||||
return new NextWindowCmd(opts, pat);
|
||||
} else if (command == "nextgroup") {
|
||||
int opts;
|
||||
string pat;
|
||||
parseNextWindowArgs(arguments, opts, pat);
|
||||
opts |= FocusControl::CYCLEGROUPS;
|
||||
FocusableList::parseArgs(arguments, opts, pat);
|
||||
opts |= FocusableList::LIST_GROUPS;
|
||||
return new NextWindowCmd(opts, pat);
|
||||
} else if (command == "prevwindow") {
|
||||
int opts;
|
||||
string pat;
|
||||
parseNextWindowArgs(arguments, opts, pat);
|
||||
FocusableList::parseArgs(arguments, opts, pat);
|
||||
return new PrevWindowCmd(opts, pat);
|
||||
} else if (command == "prevgroup") {
|
||||
int opts;
|
||||
string pat;
|
||||
parseNextWindowArgs(arguments, opts, pat);
|
||||
opts |= FocusControl::CYCLEGROUPS;
|
||||
FocusableList::parseArgs(arguments, opts, pat);
|
||||
opts |= FocusableList::LIST_GROUPS;
|
||||
return new PrevWindowCmd(opts, pat);
|
||||
} else if (command == "gotowindow") {
|
||||
int num, opts;
|
||||
|
@ -554,12 +535,12 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
|
|||
string::size_type pos = arguments.find_first_of("({");
|
||||
if (pos != string::npos && pos != arguments.size())
|
||||
args = arguments.c_str() + pos;
|
||||
parseNextWindowArgs(args, opts, pat);
|
||||
FocusableList::parseArgs(args, opts, pat);
|
||||
return new GoToWindowCmd(num, opts, pat);
|
||||
} else if (command == "clientmenu") {
|
||||
int opts;
|
||||
string pat;
|
||||
parseNextWindowArgs(arguments, opts, pat);
|
||||
FocusableList::parseArgs(arguments, opts, pat);
|
||||
return new ShowClientMenuCmd(opts, pat);
|
||||
} else if (command == "focusup")
|
||||
return new DirFocusCmd(FocusControl::FOCUSUP);
|
||||
|
|
|
@ -277,20 +277,12 @@ void ShowClientMenuCmd::execute() {
|
|||
return;
|
||||
|
||||
// TODO: ClientMenu only accepts lists of FluxboxWindows for now
|
||||
const FocusControl::Focusables *win_list = 0;
|
||||
// if (m_option & FocusControl::CYCLEGROUPS) {
|
||||
win_list = (m_option & FocusControl::CYCLELINEAR) ?
|
||||
&screen->focusControl().creationOrderWinList() :
|
||||
&screen->focusControl().focusedOrderWinList();
|
||||
/* } else {
|
||||
win_list = (m_option & FocusControl::CYCLELINEAR) ?
|
||||
&screen->focusControl().creationOrderList() :
|
||||
&screen->focusControl().focusedOrderList();
|
||||
} */
|
||||
|
||||
// when that's fixed, use a FocusableList for m_list
|
||||
const FocusableList *list =
|
||||
FocusableList::getListFromOptions(*screen, m_option);
|
||||
m_list.clear();
|
||||
FocusControl::Focusables::const_iterator it = win_list->begin(),
|
||||
it_end = win_list->end();
|
||||
FocusControl::Focusables::const_iterator it = list->clientList().begin(),
|
||||
it_end = list->clientList().end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (typeid(**it) == typeid(FluxboxWindow) && m_pat.match(**it))
|
||||
m_list.push_back(static_cast<FluxboxWindow *>(*it));
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "FbTk/RefCount.hh"
|
||||
#include "ClientMenu.hh"
|
||||
#include "ClientPattern.hh"
|
||||
#include "FocusableList.hh"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
@ -118,7 +119,7 @@ public:
|
|||
class ShowClientMenuCmd: public FbTk::Command {
|
||||
public:
|
||||
ShowClientMenuCmd(int option, std::string &pat):
|
||||
m_option(option), m_pat(pat.c_str()) { }
|
||||
m_option(option|FocusableList::LIST_GROUPS), m_pat(pat.c_str()) { }
|
||||
void execute();
|
||||
private:
|
||||
const int m_option;
|
||||
|
|
|
@ -58,16 +58,22 @@ void Subject::detach(Observer *obj) {
|
|||
}
|
||||
|
||||
void Subject::notify() {
|
||||
m_notify_mode = true;
|
||||
std::for_each(m_observerlist.begin(), m_observerlist.end(),
|
||||
std::bind2nd(std::mem_fun(&Observer::update), this));
|
||||
m_notify_mode = false;
|
||||
ObserverList::iterator it = m_observerlist.begin(),
|
||||
it_end = m_observerlist.end();
|
||||
for (; it != it_end; ++it) {
|
||||
m_notify_mode = true;
|
||||
(*it)->update(this);
|
||||
ObserverList::iterator d_it = m_dead_observers.begin(),
|
||||
d_it_end = m_dead_observers.end();
|
||||
m_notify_mode = false;
|
||||
|
||||
// remove dead observers
|
||||
if (!m_dead_observers.empty()) {
|
||||
std::for_each(m_dead_observers.begin(),
|
||||
m_dead_observers.end(),
|
||||
std::bind1st(std::mem_fun(&Subject::detach), this));
|
||||
// there might be dead observers later in the list, so we must remove
|
||||
// them now
|
||||
for (; d_it != d_it_end; ++d_it) {
|
||||
if (*d_it == *it)
|
||||
--it; // don't invalidate our iterator
|
||||
detach(*d_it);
|
||||
}
|
||||
m_dead_observers.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,15 +78,17 @@ FocusControl::FocusControl(BScreen &screen):
|
|||
m_focus_new(screen.resourceManager(), true,
|
||||
screen.name()+".focusNewWindows",
|
||||
screen.altName()+".FocusNewWindows"),
|
||||
m_focused_list(screen), m_creation_order_list(screen),
|
||||
m_focused_win_list(screen), m_creation_order_win_list(screen),
|
||||
m_cycling_list(0),
|
||||
m_was_iconic(false),
|
||||
m_cycling_last(0) {
|
||||
|
||||
m_cycling_window = m_focused_win_list.end();
|
||||
m_cycling_window = m_focused_list.clientList().end();
|
||||
|
||||
}
|
||||
|
||||
void FocusControl::cycleFocus(const Focusables &window_list,
|
||||
void FocusControl::cycleFocus(const FocusableList &window_list,
|
||||
const ClientPattern *pat, bool cycle_reverse) {
|
||||
|
||||
if (!m_cycling_list) {
|
||||
|
@ -98,8 +100,8 @@ void FocusControl::cycleFocus(const Focusables &window_list,
|
|||
} else if (m_cycling_list != &window_list)
|
||||
m_cycling_list = &window_list;
|
||||
|
||||
Focusables::const_iterator it_begin = window_list.begin();
|
||||
Focusables::const_iterator it_end = window_list.end();
|
||||
Focusables::const_iterator it_begin = window_list.clientList().begin();
|
||||
Focusables::const_iterator it_end = window_list.clientList().end();
|
||||
|
||||
// too many things can go wrong with remembering this
|
||||
m_cycling_window = find(it_begin, it_end, s_focused_window);
|
||||
|
@ -165,10 +167,10 @@ void FocusControl::cycleFocus(const Focusables &window_list,
|
|||
|
||||
}
|
||||
|
||||
void FocusControl::goToWindowNumber(const Focusables &winlist, int num,
|
||||
void FocusControl::goToWindowNumber(const FocusableList &winlist, int num,
|
||||
const ClientPattern *pat) {
|
||||
Focusables::const_iterator it = winlist.begin();
|
||||
Focusables::const_iterator it_end = winlist.end();
|
||||
Focusables::const_iterator it = winlist.clientList().begin();
|
||||
Focusables::const_iterator it_end = winlist.clientList().end();
|
||||
for (; it != it_end && num; ++it) {
|
||||
if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) {
|
||||
num > 0 ? --num : ++num;
|
||||
|
@ -182,61 +184,43 @@ void FocusControl::goToWindowNumber(const Focusables &winlist, int num,
|
|||
}
|
||||
|
||||
void FocusControl::addFocusBack(WinClient &client) {
|
||||
m_focused_list.push_back(&client);
|
||||
m_creation_order_list.push_back(&client);
|
||||
m_focused_list.pushBack(client);
|
||||
m_creation_order_list.pushBack(client);
|
||||
}
|
||||
|
||||
void FocusControl::addFocusFront(WinClient &client) {
|
||||
m_focused_list.push_front(&client);
|
||||
m_creation_order_list.push_back(&client);
|
||||
m_focused_list.pushFront(client);
|
||||
m_creation_order_list.pushBack(client);
|
||||
}
|
||||
|
||||
void FocusControl::addFocusWinBack(Focusable &win) {
|
||||
m_focused_win_list.push_back(&win);
|
||||
m_creation_order_win_list.push_back(&win);
|
||||
m_focused_win_list.pushBack(win);
|
||||
m_creation_order_win_list.pushBack(win);
|
||||
}
|
||||
|
||||
void FocusControl::addFocusWinFront(Focusable &win) {
|
||||
m_focused_win_list.push_front(&win);
|
||||
m_creation_order_win_list.push_back(&win);
|
||||
m_focused_win_list.pushFront(win);
|
||||
m_creation_order_win_list.pushBack(win);
|
||||
}
|
||||
|
||||
// move all clients in given window to back of focused list
|
||||
void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
|
||||
void FocusControl::setFocusBack(FluxboxWindow &fbwin) {
|
||||
// do nothing if there are no windows open
|
||||
// don't change focus order while cycling
|
||||
if (m_focused_list.empty() || s_reverting)
|
||||
return;
|
||||
|
||||
// if the window isn't already in this list, we could accidentally add it
|
||||
Focusables::iterator win_begin = m_focused_win_list.begin(),
|
||||
win_end = m_focused_win_list.end();
|
||||
Focusables::iterator win_it = find(win_begin, win_end, fbwin);
|
||||
if (win_it == win_end)
|
||||
return;
|
||||
m_focused_win_list.moveToBack(fbwin);
|
||||
|
||||
m_focused_win_list.erase(win_it);
|
||||
m_focused_win_list.push_back(fbwin);
|
||||
|
||||
Focusables::iterator it = m_focused_list.begin();
|
||||
// use back to avoid an infinite loop
|
||||
Focusables::iterator it_back = --m_focused_list.end();
|
||||
|
||||
while (it != it_back) {
|
||||
if ((*it)->fbwindow() == fbwin) {
|
||||
m_focused_list.push_back(*it);
|
||||
it = m_focused_list.erase(it);
|
||||
} else
|
||||
++it;
|
||||
// we need to move its clients to the back while preserving their order
|
||||
Focusables list = m_focused_list.clientList();
|
||||
Focusables::iterator it = list.begin(), it_end = list.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if ((*it)->fbwindow() == &fbwin)
|
||||
m_focused_list.moveToBack(**it);
|
||||
}
|
||||
// move the last one, if necessary, in order to preserve focus order
|
||||
if ((*it)->fbwindow() == fbwin) {
|
||||
m_focused_list.push_back(*it);
|
||||
m_focused_list.erase(it);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FocusControl::stopCyclingFocus() {
|
||||
// nothing to do
|
||||
if (m_cycling_list == 0)
|
||||
|
@ -262,10 +246,10 @@ void FocusControl::stopCyclingFocus() {
|
|||
Focusable *FocusControl::lastFocusedWindow(int workspace) {
|
||||
if (m_focused_list.empty() || m_screen.isShuttingdown()) return 0;
|
||||
if (workspace < 0 || workspace >= (int) m_screen.numberOfWorkspaces())
|
||||
return m_focused_list.front();
|
||||
return m_focused_list.clientList().front();
|
||||
|
||||
Focusables::iterator it = m_focused_list.begin();
|
||||
Focusables::iterator it_end = m_focused_list.end();
|
||||
Focusables::iterator it = m_focused_list.clientList().begin();
|
||||
Focusables::iterator it_end = m_focused_list.clientList().end();
|
||||
for (; it != it_end; ++it) {
|
||||
if ((*it)->fbwindow() &&
|
||||
((((int)(*it)->fbwindow()->workspaceNumber()) == workspace ||
|
||||
|
@ -285,8 +269,8 @@ WinClient *FocusControl::lastFocusedWindow(FluxboxWindow &group, WinClient *igno
|
|||
if (m_focused_list.empty() || m_screen.isShuttingdown())
|
||||
return 0;
|
||||
|
||||
Focusables::iterator it = m_focused_list.begin();
|
||||
Focusables::iterator it_end = m_focused_list.end();
|
||||
Focusables::iterator it = m_focused_list.clientList().begin();
|
||||
Focusables::iterator it_end = m_focused_list.clientList().end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (((*it)->fbwindow() == &group) &&
|
||||
(*it) != ignore_client)
|
||||
|
@ -300,27 +284,9 @@ void FocusControl::setScreenFocusedWindow(WinClient &win_client) {
|
|||
// raise newly focused window to the top of the focused list
|
||||
// don't change the order if we're cycling or shutting down
|
||||
if (!isCycling() && !m_screen.isShuttingdown() && !s_reverting) {
|
||||
|
||||
// make sure client is in our list, or else we could end up adding it
|
||||
Focusables::iterator it_begin = m_focused_list.begin(),
|
||||
it_end = m_focused_list.end();
|
||||
Focusables::iterator it = find(it_begin, it_end, &win_client);
|
||||
if (it == it_end)
|
||||
return;
|
||||
|
||||
m_focused_list.erase(it);
|
||||
m_focused_list.push_front(&win_client);
|
||||
|
||||
// also check the fbwindow
|
||||
it_begin = m_focused_win_list.begin();
|
||||
it_end = m_focused_win_list.end();
|
||||
it = find(it_begin, it_end, win_client.fbwindow());
|
||||
|
||||
if (it != it_end) {
|
||||
m_focused_win_list.erase(it);
|
||||
m_focused_win_list.push_front(win_client.fbwindow());
|
||||
}
|
||||
|
||||
m_focused_list.moveToFront(win_client);
|
||||
if (win_client.fbwindow())
|
||||
m_focused_win_list.moveToFront(*win_client.fbwindow());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,15 +401,15 @@ void FocusControl::removeClient(WinClient &client) {
|
|||
if (client.screen().isShuttingdown())
|
||||
return;
|
||||
|
||||
if (m_cycling_list && m_cycling_window != m_cycling_list->end() &&
|
||||
if (isCycling() && m_cycling_window != m_cycling_list->clientList().end() &&
|
||||
*m_cycling_window == &client) {
|
||||
m_cycling_window = m_cycling_list->end();
|
||||
m_cycling_window = m_cycling_list->clientList().end();
|
||||
stopCyclingFocus();
|
||||
} else if (m_cycling_last == &client)
|
||||
m_cycling_last = 0;
|
||||
|
||||
m_focused_list.remove(&client);
|
||||
m_creation_order_list.remove(&client);
|
||||
m_focused_list.remove(client);
|
||||
m_creation_order_list.remove(client);
|
||||
client.screen().clientListSig().notify();
|
||||
}
|
||||
|
||||
|
@ -451,21 +417,21 @@ void FocusControl::removeWindow(Focusable &win) {
|
|||
if (win.screen().isShuttingdown())
|
||||
return;
|
||||
|
||||
if (m_cycling_list && m_cycling_window != m_cycling_list->end() &&
|
||||
if (isCycling() && m_cycling_window != m_cycling_list->clientList().end() &&
|
||||
*m_cycling_window == &win) {
|
||||
m_cycling_window = m_cycling_list->end();
|
||||
m_cycling_window = m_cycling_list->clientList().end();
|
||||
stopCyclingFocus();
|
||||
}
|
||||
|
||||
m_focused_win_list.remove(&win);
|
||||
m_creation_order_win_list.remove(&win);
|
||||
m_focused_win_list.remove(win);
|
||||
m_creation_order_win_list.remove(win);
|
||||
win.screen().clientListSig().notify();
|
||||
}
|
||||
|
||||
void FocusControl::shutdown() {
|
||||
// restore windows backwards so they get put back correctly on restart
|
||||
Focusables::reverse_iterator it = m_focused_list.rbegin();
|
||||
for (; it != m_focused_list.rend(); ++it) {
|
||||
Focusables::reverse_iterator it = m_focused_list.clientList().rbegin();
|
||||
for (; it != m_focused_list.clientList().rend(); ++it) {
|
||||
WinClient *client = dynamic_cast<WinClient *>(*it);
|
||||
if (client && client->fbwindow())
|
||||
client->fbwindow()->restore(client, true);
|
||||
|
@ -582,7 +548,10 @@ void FocusControl::setFocusedWindow(WinClient *client) {
|
|||
}
|
||||
|
||||
// update AtomHandlers and/or other stuff...
|
||||
Fluxbox::instance()->updateFocusedWindow(screen, old_screen);
|
||||
if (screen)
|
||||
screen->focusedWindowSig().notify();
|
||||
if (old_screen && screen != old_screen)
|
||||
old_screen->focusedWindowSig().notify();
|
||||
}
|
||||
|
||||
////////////////////// FocusControl RESOURCES
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <list>
|
||||
|
||||
#include "FbTk/Resource.hh"
|
||||
#include "FocusableList.hh"
|
||||
|
||||
class ClientPattern;
|
||||
class WinClient;
|
||||
|
@ -60,12 +61,6 @@ public:
|
|||
FOCUSRIGHT ///< window is right
|
||||
};
|
||||
|
||||
/// prevFocus/nextFocus option bits
|
||||
enum {
|
||||
CYCLEGROUPS = 0x01, //< cycle through groups
|
||||
CYCLELINEAR = 0x08, ///< linear cycle
|
||||
};
|
||||
|
||||
explicit FocusControl(BScreen &screen);
|
||||
/// cycle previous focuable
|
||||
void prevFocus() { cycleFocus(m_focused_list, 0, true); }
|
||||
|
@ -77,10 +72,10 @@ public:
|
|||
* @param pat pattern for matching focusables
|
||||
* @param reverse reverse the cycle order
|
||||
*/
|
||||
void cycleFocus(const Focusables &winlist, const ClientPattern *pat = 0,
|
||||
void cycleFocus(const FocusableList &winlist, const ClientPattern *pat = 0,
|
||||
bool reverse = false);
|
||||
|
||||
void goToWindowNumber(const Focusables &winlist, int num,
|
||||
void goToWindowNumber(const FocusableList &winlist, int num,
|
||||
const ClientPattern *pat = 0);
|
||||
/// sets the focused window on a screen
|
||||
void setScreenFocusedWindow(WinClient &win_client);
|
||||
|
@ -108,7 +103,7 @@ public:
|
|||
void addFocusFront(WinClient &client);
|
||||
void addFocusWinBack(Focusable &win);
|
||||
void addFocusWinFront(Focusable &win);
|
||||
void setFocusBack(FluxboxWindow *fbwin);
|
||||
void setFocusBack(FluxboxWindow &fbwin);
|
||||
/// @return main focus model
|
||||
FocusModel focusModel() const { return *m_focus_model; }
|
||||
/// @return tab focus model
|
||||
|
@ -122,11 +117,11 @@ public:
|
|||
WinClient *lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client = 0);
|
||||
|
||||
/// @return focus list in creation order
|
||||
const Focusables &creationOrderList() const { return m_creation_order_list; }
|
||||
const FocusableList &creationOrderList() const { return m_creation_order_list; }
|
||||
/// @return the focus list in focused order
|
||||
const Focusables &focusedOrderList() const { return m_focused_list; }
|
||||
const Focusables &creationOrderWinList() const { return m_creation_order_win_list; }
|
||||
const Focusables &focusedOrderWinList() const { return m_focused_win_list; }
|
||||
const FocusableList &focusedOrderList() const { return m_focused_list; }
|
||||
const FocusableList &creationOrderWinList() const { return m_creation_order_win_list; }
|
||||
const FocusableList &focusedOrderWinList() const { return m_focused_win_list; }
|
||||
|
||||
/// remove client from focus list
|
||||
void removeClient(WinClient &client);
|
||||
|
@ -153,13 +148,13 @@ private:
|
|||
|
||||
// This list keeps the order of window focusing for this screen
|
||||
// Screen global so it works for sticky windows too.
|
||||
Focusables m_focused_list;
|
||||
Focusables m_creation_order_list;
|
||||
Focusables m_focused_win_list;
|
||||
Focusables m_creation_order_win_list;
|
||||
FocusableList m_focused_list;
|
||||
FocusableList m_creation_order_list;
|
||||
FocusableList m_focused_win_list;
|
||||
FocusableList m_creation_order_win_list;
|
||||
|
||||
Focusables::const_iterator m_cycling_window;
|
||||
const Focusables *m_cycling_list;
|
||||
const FocusableList *m_cycling_list;
|
||||
Focusable *m_was_iconic;
|
||||
WinClient *m_cycling_last;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// $Id$
|
||||
// $Id: $
|
||||
|
||||
#ifndef FOCUSABLE_HH
|
||||
#define FOCUSABLE_HH
|
||||
|
|
293
src/FocusableList.cc
Normal file
293
src/FocusableList.cc
Normal file
|
@ -0,0 +1,293 @@
|
|||
// FocusableList.cc
|
||||
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// $Id: $
|
||||
|
||||
#include "FocusableList.hh"
|
||||
|
||||
#include "Focusable.hh"
|
||||
#include "FocusControl.hh"
|
||||
#include "Screen.hh"
|
||||
#include "WinClient.hh"
|
||||
#include "Window.hh"
|
||||
|
||||
#include "FbTk/StringUtil.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
void FocusableList::parseArgs(const string &in, int &opts, string &pat) {
|
||||
string options;
|
||||
int err = FbTk::StringUtil::getStringBetween(options, in.c_str(), '{', '}');
|
||||
|
||||
// the rest of the string is a ClientPattern
|
||||
pat = in.c_str() + err;
|
||||
|
||||
// now parse the options
|
||||
vector<string> args;
|
||||
FbTk::StringUtil::stringtok(args, options);
|
||||
vector<string>::iterator it = args.begin(), it_end = args.end();
|
||||
opts = 0;
|
||||
for (; it != it_end; ++it) {
|
||||
if (strcasecmp((*it).c_str(), "static") == 0)
|
||||
opts |= STATIC_ORDER;
|
||||
else if (strcasecmp((*it).c_str(), "groups") == 0)
|
||||
opts |= LIST_GROUPS;
|
||||
}
|
||||
}
|
||||
|
||||
const FocusableList *FocusableList::getListFromOptions(BScreen &scr, int opts) {
|
||||
if (opts & LIST_GROUPS)
|
||||
return (opts & STATIC_ORDER) ?
|
||||
&scr.focusControl().creationOrderWinList() :
|
||||
&scr.focusControl().focusedOrderWinList();
|
||||
return (opts & STATIC_ORDER) ?
|
||||
&scr.focusControl().creationOrderList() :
|
||||
&scr.focusControl().focusedOrderList();
|
||||
}
|
||||
|
||||
FocusableList::FocusableList(BScreen &scr, const string pat):
|
||||
m_pat(0), m_parent(0), m_screen(scr) {
|
||||
|
||||
int options = 0;
|
||||
string pattern;
|
||||
parseArgs(pat, options, pattern);
|
||||
m_parent = getListFromOptions(scr, options);
|
||||
m_pat.reset(new ClientPattern(pattern.c_str()));
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
FocusableList::FocusableList(BScreen &scr, const FocusableList &parent,
|
||||
const string pat):
|
||||
m_pat(new ClientPattern(pat.c_str())), m_parent(&parent), m_screen(scr) {
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
void FocusableList::init() {
|
||||
addMatching();
|
||||
m_parent->attachChild(*this);
|
||||
|
||||
// TODO: can't handle (head=[mouse]) yet
|
||||
if (m_pat->dependsOnCurrentWorkspace())
|
||||
m_screen.currentWorkspaceSig().attach(this);
|
||||
if (m_pat->dependsOnFocusedWindow())
|
||||
m_screen.focusedWindowSig().attach(this);
|
||||
}
|
||||
|
||||
void FocusableList::update(FbTk::Subject *subj) {
|
||||
if (subj == 0 || m_screen.isShuttingdown())
|
||||
return;
|
||||
|
||||
if (typeid(*subj) == typeid(Focusable::FocusSubject)) {
|
||||
Focusable::FocusSubject *fsubj =
|
||||
static_cast<Focusable::FocusSubject *>(subj);
|
||||
if (fsubj == &fsubj->win().dieSig())
|
||||
remove(fsubj->win());
|
||||
else if (fsubj == &fsubj->win().titleSig())
|
||||
checkUpdate(fsubj->win());
|
||||
}
|
||||
if (typeid(*subj) == typeid(FluxboxWindow::WinSubject)) {
|
||||
FluxboxWindow::WinSubject *fsubj =
|
||||
static_cast<FluxboxWindow::WinSubject *>(subj);
|
||||
// we only bind these for matching patterns, so skip finding out signal
|
||||
FluxboxWindow &fbwin = fsubj->win();
|
||||
if (m_parent->contains(fbwin))
|
||||
checkUpdate(fbwin);
|
||||
std::list<WinClient *> list = fbwin.clientList();
|
||||
std::list<WinClient *>::iterator it = list.begin(), it_end = list.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (m_parent->contains(**it))
|
||||
checkUpdate(**it);
|
||||
}
|
||||
}
|
||||
if (typeid(*subj) == typeid(FocusableListSubject)) {
|
||||
FocusableListSubject *fsubj =
|
||||
static_cast<FocusableListSubject *>(subj);
|
||||
if (subj == &m_parent->addSig()) {
|
||||
if (m_pat->match(*fsubj->win())) {
|
||||
insertFromParent(*fsubj->win());
|
||||
m_addsig.notify(fsubj->win());
|
||||
} else // we still want to watch it, in case it changes to match
|
||||
attachSignals(*fsubj->win());
|
||||
} else if (subj == &m_parent->removeSig())
|
||||
remove(*fsubj->win());
|
||||
else if (subj == &m_parent->resetSig())
|
||||
reset();
|
||||
else if (subj == &m_parent->orderSig()) {
|
||||
Focusable *win = fsubj->win();
|
||||
if (!win || !contains(*win))
|
||||
return;
|
||||
if (insertFromParent(*win))
|
||||
m_ordersig.notify(win);
|
||||
}
|
||||
} else if (subj == &m_screen.currentWorkspaceSig() ||
|
||||
subj == &m_screen.focusedWindowSig())
|
||||
reset();
|
||||
}
|
||||
|
||||
void FocusableList::checkUpdate(Focusable &win) {
|
||||
if (contains(win)) {
|
||||
if (!m_pat->match(win)) {
|
||||
m_list.remove(&win);
|
||||
m_removesig.notify(&win);
|
||||
}
|
||||
} else if (m_pat->match(win)) {
|
||||
insertFromParent(win);
|
||||
m_addsig.notify(&win);
|
||||
}
|
||||
}
|
||||
|
||||
// returns whether or not the window was moved
|
||||
bool FocusableList::insertFromParent(Focusable &win) {
|
||||
const Focusables list = m_parent->clientList();
|
||||
Focusables::const_iterator p_it = list.begin(), p_it_end = list.end();
|
||||
Focusables::iterator our_it = m_list.begin(), our_it_end = m_list.end();
|
||||
// walk through our list looking for corresponding entries in
|
||||
// parent's list, until we find the window that moved
|
||||
for (; our_it != our_it_end && p_it != p_it_end; p_it++) {
|
||||
if (*p_it == &win) {
|
||||
if (*our_it == &win) // win didn't move in our list
|
||||
return false;
|
||||
m_list.remove(&win);
|
||||
m_list.insert(our_it, &win);
|
||||
return true;
|
||||
}
|
||||
if (*p_it == *our_it)
|
||||
++our_it;
|
||||
}
|
||||
m_list.remove(&win);
|
||||
m_list.push_back(&win);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FocusableList::addMatching() {
|
||||
if (!m_parent)
|
||||
return;
|
||||
|
||||
const Focusables list = m_parent->clientList();
|
||||
Focusables::const_iterator it = list.begin(), it_end = list.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (m_pat->match(**it))
|
||||
pushBack(**it);
|
||||
else // we still want to watch it, in case it changes to match
|
||||
attachSignals(**it);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusableList::pushFront(Focusable &win) {
|
||||
m_list.push_front(&win);
|
||||
attachSignals(win);
|
||||
m_addsig.notify(&win);
|
||||
}
|
||||
|
||||
void FocusableList::pushBack(Focusable &win) {
|
||||
m_list.push_back(&win);
|
||||
attachSignals(win);
|
||||
m_addsig.notify(&win);
|
||||
}
|
||||
|
||||
void FocusableList::moveToFront(Focusable &win) {
|
||||
// if the window isn't already in this list, we could accidentally add it
|
||||
if (!contains(win))
|
||||
return;
|
||||
|
||||
m_list.remove(&win);
|
||||
m_list.push_front(&win);
|
||||
m_ordersig.notify(&win);
|
||||
}
|
||||
|
||||
void FocusableList::moveToBack(Focusable &win) {
|
||||
// if the window isn't already in this list, we could accidentally add it
|
||||
if (!contains(win))
|
||||
return;
|
||||
|
||||
m_list.remove(&win);
|
||||
m_list.push_back(&win);
|
||||
m_ordersig.notify(&win);
|
||||
}
|
||||
|
||||
void FocusableList::remove(Focusable &win) {
|
||||
// if the window isn't already in this list, we could send a bad signal
|
||||
bool contained = contains(win);
|
||||
|
||||
detachSignals(win);
|
||||
if (!contained)
|
||||
return;
|
||||
m_list.remove(&win);
|
||||
m_removesig.notify(&win);
|
||||
}
|
||||
|
||||
void FocusableList::attachSignals(Focusable &win) {
|
||||
win.dieSig().attach(this);
|
||||
if (m_parent) {
|
||||
// attach various signals for matching
|
||||
win.titleSig().attach(this);
|
||||
FluxboxWindow *fbwin = win.fbwindow();
|
||||
if (!fbwin)
|
||||
return;
|
||||
fbwin->workspaceSig().attach(this);
|
||||
fbwin->stateSig().attach(this);
|
||||
fbwin->layerSig().attach(this);
|
||||
// TODO: can't watch (head=...) yet
|
||||
}
|
||||
}
|
||||
|
||||
void FocusableList::detachSignals(Focusable &win) {
|
||||
win.dieSig().detach(this);
|
||||
if (m_parent) {
|
||||
// detach various signals for matching
|
||||
win.titleSig().detach(this);
|
||||
FluxboxWindow *fbwin = win.fbwindow();
|
||||
if (!fbwin)
|
||||
return;
|
||||
fbwin->workspaceSig().detach(this);
|
||||
fbwin->stateSig().detach(this);
|
||||
fbwin->layerSig().detach(this);
|
||||
// TODO: can't watch (head=...) yet
|
||||
}
|
||||
}
|
||||
|
||||
void FocusableList::reset() {
|
||||
while (!m_list.empty()) {
|
||||
detachSignals(*m_list.back());
|
||||
m_list.pop_back();
|
||||
}
|
||||
if (m_parent)
|
||||
addMatching();
|
||||
m_resetsig.notify(0);
|
||||
}
|
||||
|
||||
bool FocusableList::contains(const Focusable &win) const {
|
||||
Focusables::const_iterator it = m_list.begin(), it_end = m_list.end();
|
||||
it = find(it, it_end, &win);
|
||||
return (it != it_end);
|
||||
}
|
||||
|
||||
void FocusableList::attachChild(FocusableList &child) const {
|
||||
m_addsig.attach(&child);
|
||||
m_removesig.attach(&child);
|
||||
m_resetsig.attach(&child);
|
||||
m_ordersig.attach(&child);
|
||||
}
|
121
src/FocusableList.hh
Normal file
121
src/FocusableList.hh
Normal file
|
@ -0,0 +1,121 @@
|
|||
// FocusableList.hh
|
||||
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// $Id: $
|
||||
|
||||
#ifndef FOCUSABLELIST_HH
|
||||
#define FOCUSABLELIST_HH
|
||||
|
||||
#include "FbTk/NotCopyable.hh"
|
||||
#include "FbTk/Observer.hh"
|
||||
#include "FbTk/Subject.hh"
|
||||
|
||||
#include "ClientPattern.hh"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
class BScreen;
|
||||
class Focusable;
|
||||
|
||||
class FocusableList: public FbTk::Observer, private FbTk::NotCopyable {
|
||||
public:
|
||||
typedef std::list<Focusable *> Focusables;
|
||||
|
||||
/// list option bits
|
||||
enum {
|
||||
LIST_GROUPS = 0x01, //< list groups instead of clients
|
||||
STATIC_ORDER = 0x02, ///< use creation order instead of focused order
|
||||
};
|
||||
|
||||
FocusableList(BScreen &scr): m_pat(0), m_parent(0), m_screen(scr) { }
|
||||
FocusableList(BScreen &scr, const std::string pat);
|
||||
FocusableList(BScreen &scr, const FocusableList &parent,
|
||||
const std::string pat);
|
||||
|
||||
static void parseArgs(const std::string &in, int &opts, std::string &out);
|
||||
static const FocusableList *getListFromOptions(BScreen &scr, int opts);
|
||||
|
||||
void update(FbTk::Subject *subj);
|
||||
|
||||
/// functions for modifying the list contents
|
||||
void pushFront(Focusable &win);
|
||||
void pushBack(Focusable &win);
|
||||
void moveToFront(Focusable &win);
|
||||
void moveToBack(Focusable &win);
|
||||
void remove(Focusable &win);
|
||||
|
||||
/// accessor for list
|
||||
Focusables &clientList() { return m_list; }
|
||||
const Focusables &clientList() const { return m_list; }
|
||||
|
||||
/// does the list contain any windows?
|
||||
bool empty() const { return m_list.empty(); }
|
||||
/// does the list contain the given window?
|
||||
bool contains(const Focusable &win) const;
|
||||
|
||||
/**
|
||||
@name signals
|
||||
@{
|
||||
*/
|
||||
FbTk::Subject &orderSig() { return m_ordersig; }
|
||||
const FbTk::Subject &orderSig() const { return m_ordersig; }
|
||||
FbTk::Subject &addSig() { return m_addsig; }
|
||||
const FbTk::Subject &addSig() const { return m_addsig; }
|
||||
FbTk::Subject &removeSig() { return m_removesig; }
|
||||
const FbTk::Subject &removeSig() const { return m_removesig; }
|
||||
FbTk::Subject &resetSig() { return m_resetsig; }
|
||||
const FbTk::Subject &resetSig() const { return m_resetsig; }
|
||||
/** @} */ // end group signals
|
||||
|
||||
/**
|
||||
* Signaling object to attatch observers to.
|
||||
*/
|
||||
class FocusableListSubject: public FbTk::Subject {
|
||||
public:
|
||||
explicit FocusableListSubject(): m_win(0) { }
|
||||
void notify(Focusable *win) { m_win = win; FbTk::Subject::notify(); }
|
||||
/// @return context for this signal
|
||||
Focusable *win() { return m_win; }
|
||||
|
||||
private:
|
||||
Focusable *m_win;
|
||||
};
|
||||
|
||||
private:
|
||||
void init();
|
||||
void addMatching();
|
||||
void checkUpdate(Focusable &win);
|
||||
bool insertFromParent(Focusable &win);
|
||||
void attachSignals(Focusable &win);
|
||||
void detachSignals(Focusable &win);
|
||||
void reset();
|
||||
void attachChild(FocusableList &child) const;
|
||||
|
||||
std::auto_ptr<ClientPattern> m_pat;
|
||||
const FocusableList *m_parent;
|
||||
BScreen &m_screen;
|
||||
std::list<Focusable *> m_list;
|
||||
|
||||
mutable FocusableListSubject m_ordersig, m_addsig, m_removesig, m_resetsig;
|
||||
};
|
||||
|
||||
#endif // FOCUSABLELIST_HH
|
|
@ -38,6 +38,7 @@
|
|||
#include "FocusControl.hh"
|
||||
#include "FbCommands.hh"
|
||||
#include "Layer.hh"
|
||||
#include "STLUtil.hh"
|
||||
|
||||
#include "FbTk/I18n.hh"
|
||||
#include "FbTk/Menu.hh"
|
||||
|
@ -67,26 +68,6 @@ using std::endl;
|
|||
|
||||
namespace FbTk {
|
||||
|
||||
template<>
|
||||
void FbTk::Resource<IconbarTool::Mode>::setFromString(const char *strval) {
|
||||
if (strcasecmp(strval, "None") == 0)
|
||||
m_value = IconbarTool::NONE;
|
||||
else if (strcasecmp(strval, "Icons") == 0)
|
||||
m_value = IconbarTool::ICONS;
|
||||
else if (strcasecmp(strval, "NoIcons") == 0)
|
||||
m_value = IconbarTool::NOICONS;
|
||||
else if (strcasecmp(strval, "WorkspaceIcons") == 0)
|
||||
m_value = IconbarTool::WORKSPACEICONS;
|
||||
else if (strcasecmp(strval, "WorkspaceNoIcons") == 0)
|
||||
m_value = IconbarTool::WORKSPACENOICONS;
|
||||
else if (strcasecmp(strval, "Workspace") == 0)
|
||||
m_value = IconbarTool::WORKSPACE;
|
||||
else if (strcasecmp(strval, "AllWindows") == 0)
|
||||
m_value = IconbarTool::ALLWINDOWS;
|
||||
else
|
||||
setDefaultValue();
|
||||
}
|
||||
|
||||
template<>
|
||||
void FbTk::Resource<Container::Alignment>::setDefaultValue() {
|
||||
m_value = Container::RELATIVE;
|
||||
|
@ -117,35 +98,6 @@ void FbTk::Resource<Container::Alignment>::setFromString(const char *str) {
|
|||
setDefaultValue();
|
||||
}
|
||||
|
||||
template<>
|
||||
string FbTk::Resource<IconbarTool::Mode>::getString() const {
|
||||
|
||||
switch (m_value) {
|
||||
case IconbarTool::NONE:
|
||||
return string("None");
|
||||
break;
|
||||
case IconbarTool::ICONS:
|
||||
return string("Icons");
|
||||
break;
|
||||
case IconbarTool::NOICONS:
|
||||
return string("NoIcons");
|
||||
break;
|
||||
case IconbarTool::WORKSPACEICONS:
|
||||
return string("WorkspaceIcons");
|
||||
break;
|
||||
case IconbarTool::WORKSPACENOICONS:
|
||||
return string("WorkspaceNoIcons");
|
||||
break;
|
||||
case IconbarTool::WORKSPACE:
|
||||
return string("Workspace");
|
||||
break;
|
||||
case IconbarTool::ALLWINDOWS:
|
||||
return string("AllWindows");
|
||||
break;
|
||||
}
|
||||
// default string
|
||||
return string("Icons");
|
||||
}
|
||||
} // end namespace FbTk
|
||||
|
||||
namespace {
|
||||
|
@ -153,7 +105,7 @@ namespace {
|
|||
class ToolbarModeMenuItem : public FbTk::MenuItem {
|
||||
public:
|
||||
ToolbarModeMenuItem(const FbTk::FbString &label, IconbarTool &handler,
|
||||
IconbarTool::Mode mode,
|
||||
string mode,
|
||||
FbTk::RefCount<FbTk::Command> &cmd):
|
||||
FbTk::MenuItem(label, cmd), m_handler(handler), m_mode(mode) {
|
||||
}
|
||||
|
@ -165,7 +117,7 @@ public:
|
|||
|
||||
private:
|
||||
IconbarTool &m_handler;
|
||||
IconbarTool::Mode m_mode;
|
||||
string m_mode;
|
||||
};
|
||||
|
||||
class ToolbarAlignMenuItem: public FbTk::MenuItem {
|
||||
|
@ -198,42 +150,42 @@ void setupModeMenu(FbTk::Menu &menu, IconbarTool &handler) {
|
|||
menu.insert(new ToolbarModeMenuItem(_FB_XTEXT(Toolbar, IconbarModeNone,
|
||||
"None", "No icons are shown in the iconbar"),
|
||||
handler,
|
||||
IconbarTool::NONE, saverc_cmd));
|
||||
"none", saverc_cmd));
|
||||
|
||||
menu.insert(new ToolbarModeMenuItem(
|
||||
_FB_XTEXT(Toolbar, IconbarModeIcons,
|
||||
"Icons", "Iconified windows from all workspaces are shown"),
|
||||
handler,
|
||||
IconbarTool::ICONS, saverc_cmd));
|
||||
"{static groups} (minimized=yes)", saverc_cmd));
|
||||
|
||||
menu.insert(new ToolbarModeMenuItem(
|
||||
_FB_XTEXT(Toolbar, IconbarModeNoIcons,
|
||||
"NoIcons", "No iconified windows from all workspaces are shown"),
|
||||
handler,
|
||||
IconbarTool::NOICONS, saverc_cmd));
|
||||
"{static groups} (minimized=no)", saverc_cmd));
|
||||
|
||||
menu.insert(new ToolbarModeMenuItem(
|
||||
_FB_XTEXT(Toolbar, IconbarModeWorkspaceIcons,
|
||||
"WorkspaceIcons", "Iconified windows from this workspace are shown"),
|
||||
handler,
|
||||
IconbarTool::WORKSPACEICONS, saverc_cmd));
|
||||
"{static groups} (minimized=yes) (workspace)", saverc_cmd));
|
||||
|
||||
menu.insert(new ToolbarModeMenuItem(
|
||||
_FB_XTEXT(Toolbar, IconbarModeWorkspaceNoIcons,
|
||||
"WorkspaceNoIcons", "No iconified windows from this workspace are shown"),
|
||||
handler,
|
||||
IconbarTool::WORKSPACENOICONS, saverc_cmd));
|
||||
"{static groups} (minimized=no) (workspace)", saverc_cmd));
|
||||
|
||||
menu.insert(new ToolbarModeMenuItem(
|
||||
_FB_XTEXT(Toolbar, IconbarModeWorkspace,
|
||||
"Workspace", "Normal and iconified windows from this workspace are shown"),
|
||||
handler,
|
||||
IconbarTool::WORKSPACE, saverc_cmd));
|
||||
"{static groups} (workspace)", saverc_cmd));
|
||||
|
||||
menu.insert(new ToolbarModeMenuItem(
|
||||
_FB_XTEXT(Toolbar, IconbarModeAllWindows, "All Windows", "All windows are shown"),
|
||||
handler,
|
||||
IconbarTool::ALLWINDOWS, saverc_cmd));
|
||||
"{static groups}", saverc_cmd));
|
||||
|
||||
menu.insert(new FbTk::MenuSeparator());
|
||||
|
||||
|
@ -257,26 +209,6 @@ void setupModeMenu(FbTk::Menu &menu, IconbarTool &handler) {
|
|||
menu.updateMenu();
|
||||
}
|
||||
|
||||
inline bool checkAddWindow(IconbarTool::Mode mode, const FluxboxWindow &win) {
|
||||
if (win.isIconHidden() || mode == IconbarTool::NONE)
|
||||
return false;
|
||||
|
||||
if ((mode == IconbarTool::ICONS || mode == IconbarTool::WORKSPACEICONS) &&
|
||||
!win.isIconic())
|
||||
return false;
|
||||
|
||||
if ((mode == IconbarTool::NOICONS || mode == IconbarTool::WORKSPACENOICONS)
|
||||
&& win.isIconic())
|
||||
return false;
|
||||
|
||||
if ((mode == IconbarTool::WORKSPACE || mode == IconbarTool::WORKSPACEICONS
|
||||
|| mode == IconbarTool::WORKSPACENOICONS) &&
|
||||
win.workspaceNumber() != win.screen().currentWorkspaceID())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef FbTk::RefCount<FbTk::Command> RefCmd;
|
||||
|
||||
class ShowMenu: public FbTk::Command {
|
||||
|
@ -322,14 +254,16 @@ private:
|
|||
|
||||
}; // end anonymous namespace
|
||||
|
||||
IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScreen &screen,
|
||||
FbTk::Menu &menu):
|
||||
IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme,
|
||||
BScreen &screen, FbTk::Menu &menu):
|
||||
ToolbarItem(ToolbarItem::RELATIVE),
|
||||
m_screen(screen),
|
||||
m_icon_container(parent),
|
||||
m_theme(theme),
|
||||
m_empty_pm( screen.imageControl() ),
|
||||
m_rc_mode(screen.resourceManager(), WORKSPACE,
|
||||
m_winlist(new FocusableList(screen)),
|
||||
m_mode("none"),
|
||||
m_rc_mode(screen.resourceManager(), "{static groups} (workspace)",
|
||||
screen.name() + ".iconbar.mode", screen.altName() + ".Iconbar.Mode"),
|
||||
m_rc_alignment(screen.resourceManager(), Container::LEFT,
|
||||
screen.name() + ".iconbar.alignment", screen.altName() + ".Iconbar.Alignment"),
|
||||
|
@ -365,10 +299,7 @@ IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScr
|
|||
|
||||
// setup signals
|
||||
theme.reconfigSig().attach(this);
|
||||
screen.clientListSig().attach(this);
|
||||
screen.iconListSig().attach(this);
|
||||
screen.currentWorkspaceSig().attach(this);
|
||||
|
||||
setMode(*m_rc_mode);
|
||||
}
|
||||
|
||||
IconbarTool::~IconbarTool() {
|
||||
|
@ -405,20 +336,33 @@ void IconbarTool::setAlignment(Container::Alignment align) {
|
|||
m_menu.reconfigure();
|
||||
}
|
||||
|
||||
void IconbarTool::setMode(Mode mode) {
|
||||
if (mode == *m_rc_mode)
|
||||
void IconbarTool::setMode(string mode) {
|
||||
if (mode == m_mode)
|
||||
return;
|
||||
|
||||
*m_rc_mode = mode;
|
||||
*m_rc_mode = m_mode = mode;
|
||||
|
||||
// lock graphics update
|
||||
m_icon_container.setUpdateLock(true);
|
||||
|
||||
deleteIcons();
|
||||
|
||||
// update mode
|
||||
if (mode != NONE)
|
||||
updateList();
|
||||
if (m_winlist.get()) {
|
||||
m_winlist->addSig().detach(this);
|
||||
m_winlist->removeSig().detach(this);
|
||||
m_winlist->orderSig().detach(this);
|
||||
m_winlist->resetSig().detach(this);
|
||||
}
|
||||
if (mode == "none")
|
||||
m_winlist.reset(new FocusableList(m_screen));
|
||||
else
|
||||
m_winlist.reset(new FocusableList(m_screen,
|
||||
mode + " (iconhidden=no)"));
|
||||
if (m_winlist.get()) {
|
||||
m_winlist->addSig().attach(this);
|
||||
m_winlist->removeSig().attach(this);
|
||||
m_winlist->orderSig().attach(this);
|
||||
m_winlist->resetSig().attach(this);
|
||||
}
|
||||
reset();
|
||||
|
||||
// unlock graphics update
|
||||
m_icon_container.setUpdateLock(false);
|
||||
|
@ -445,10 +389,7 @@ unsigned int IconbarTool::borderWidth() const {
|
|||
void IconbarTool::update(FbTk::Subject *subj) {
|
||||
// ignore updates if we're shutting down
|
||||
if (m_screen.isShuttingdown()) {
|
||||
m_screen.clientListSig().detach(this);
|
||||
m_screen.iconListSig().detach(this);
|
||||
m_screen.currentWorkspaceSig().detach(this);
|
||||
if (!m_icon_list.empty())
|
||||
if (!m_icons.empty())
|
||||
deleteIcons();
|
||||
return;
|
||||
}
|
||||
|
@ -462,68 +403,26 @@ void IconbarTool::update(FbTk::Subject *subj) {
|
|||
|
||||
m_icon_container.setMaxSizePerClient(*m_rc_client_width);
|
||||
|
||||
|
||||
if (mode() == NONE) {
|
||||
if (subj != 0 && typeid(*subj) == typeid(IconbarTheme))
|
||||
renderTheme();
|
||||
if (subj == &m_theme.reconfigSig()) {
|
||||
setMode(*m_rc_mode);
|
||||
return;
|
||||
}
|
||||
|
||||
// handle window signal
|
||||
if (subj != 0 && typeid(*subj) == typeid(FluxboxWindow::WinSubject)) {
|
||||
// we handle everything except die signal here
|
||||
FluxboxWindow::WinSubject *winsubj = static_cast<FluxboxWindow::WinSubject *>(subj);
|
||||
if (subj == &(winsubj->win().workspaceSig())) {
|
||||
// we can ignore this signal if we're in ALLWINDOWS mode
|
||||
if (mode() == ALLWINDOWS || mode() == ICONS || mode() == NOICONS)
|
||||
return;
|
||||
|
||||
// workspace changed for this window, and if it's not on current workspace we remove it
|
||||
if (m_screen.currentWorkspaceID() != winsubj->win().workspaceNumber()) {
|
||||
removeWindow(winsubj->win());
|
||||
renderTheme();
|
||||
}
|
||||
return;
|
||||
} else if (subj == &(winsubj->win().stateSig())) {
|
||||
if (!checkAddWindow(mode(), winsubj->win())) {
|
||||
removeWindow(winsubj->win());
|
||||
renderTheme();
|
||||
}
|
||||
return;
|
||||
|
||||
} else {
|
||||
// signal not handled
|
||||
return;
|
||||
}
|
||||
} else if (subj != 0 && typeid(*subj) == typeid(Focusable::FocusSubject)) {
|
||||
Focusable::FocusSubject *winsubj = static_cast<Focusable::FocusSubject *>(subj);
|
||||
if (subj == &(winsubj->win().dieSig())) { // die sig
|
||||
removeWindow(winsubj->win());
|
||||
renderTheme();
|
||||
return; // we don't need to update the entire list
|
||||
}
|
||||
}
|
||||
|
||||
bool remove_all = false; // if we should readd all windows
|
||||
|
||||
if (subj != 0 && typeid(*subj) == typeid(BScreen::ScreenSubject) &&
|
||||
mode() != ALLWINDOWS && mode() != ICONS && mode() != NOICONS) {
|
||||
BScreen::ScreenSubject *screen_subj = static_cast<BScreen::ScreenSubject *>(subj);
|
||||
// current workspace sig
|
||||
if (&m_screen.currentWorkspaceSig() == screen_subj ) {
|
||||
remove_all = true; // remove and readd all windows
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// lock graphic update
|
||||
m_icon_container.setUpdateLock(true);
|
||||
|
||||
if (remove_all)
|
||||
deleteIcons();
|
||||
|
||||
// ok, we got some signal that we need to update our iconbar container
|
||||
updateList();
|
||||
if (typeid(*subj) == typeid(FocusableList::FocusableListSubject)) {
|
||||
FocusableList::FocusableListSubject *fsubj =
|
||||
static_cast<FocusableList::FocusableListSubject *>(subj);
|
||||
if (subj == &m_winlist->addSig())
|
||||
insertWindow(*fsubj->win());
|
||||
else if (subj == &m_winlist->removeSig())
|
||||
removeWindow(*fsubj->win());
|
||||
else if (subj == &m_winlist->resetSig())
|
||||
reset();
|
||||
else if (subj == &m_winlist->orderSig())
|
||||
insertWindow(*fsubj->win());
|
||||
}
|
||||
|
||||
// unlock container and update graphics
|
||||
m_icon_container.setUpdateLock(false);
|
||||
|
@ -540,25 +439,42 @@ void IconbarTool::update(FbTk::Subject *subj) {
|
|||
renderTheme();
|
||||
}
|
||||
|
||||
IconButton *IconbarTool::findButton(Focusable &win) {
|
||||
void IconbarTool::insertWindow(Focusable &win, int pos) {
|
||||
IconButton *button = 0;
|
||||
|
||||
IconList::iterator icon_it = m_icon_list.begin();
|
||||
IconList::iterator icon_it_end = m_icon_list.end();
|
||||
for (; icon_it != icon_it_end; ++icon_it) {
|
||||
if (&(*icon_it)->win() == &win)
|
||||
return *icon_it;
|
||||
IconMap::iterator icon_it = m_icons.find(&win);
|
||||
if (icon_it != m_icons.end())
|
||||
button = icon_it->second;
|
||||
|
||||
if (button)
|
||||
m_icon_container.removeItem(button);
|
||||
else
|
||||
button = makeButton(win);
|
||||
if (!button) return;
|
||||
|
||||
if (pos == -2) {
|
||||
pos = 0;
|
||||
list<Focusable *>::iterator it = m_winlist->clientList().begin(),
|
||||
it_end = m_winlist->clientList().end();
|
||||
for (; it != it_end && *it != &win; ++it)
|
||||
pos++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
m_icon_container.insertItem(button, pos);
|
||||
}
|
||||
|
||||
void IconbarTool::reset() {
|
||||
deleteIcons();
|
||||
updateList();
|
||||
}
|
||||
|
||||
void IconbarTool::updateSizing() {
|
||||
m_icon_container.setBorderWidth(m_theme.border().width());
|
||||
|
||||
IconList::iterator icon_it = m_icon_list.begin();
|
||||
const IconList::iterator icon_it_end = m_icon_list.end();
|
||||
IconMap::iterator icon_it = m_icons.begin();
|
||||
const IconMap::iterator icon_it_end = m_icons.end();
|
||||
for (; icon_it != icon_it_end; ++icon_it)
|
||||
(*icon_it)->reconfigTheme();
|
||||
icon_it->second->reconfigTheme();
|
||||
|
||||
}
|
||||
|
||||
|
@ -588,10 +504,10 @@ void IconbarTool::renderTheme() {
|
|||
m_icon_container.setAlpha(m_alpha);
|
||||
|
||||
// update buttons
|
||||
IconList::iterator icon_it = m_icon_list.begin();
|
||||
const IconList::iterator icon_it_end = m_icon_list.end();
|
||||
IconMap::iterator icon_it = m_icons.begin();
|
||||
const IconMap::iterator icon_it_end = m_icons.end();
|
||||
for (; icon_it != icon_it_end; ++icon_it)
|
||||
renderButton(*(*icon_it));
|
||||
renderButton(*icon_it->second);
|
||||
|
||||
}
|
||||
|
||||
|
@ -606,49 +522,30 @@ void IconbarTool::renderButton(IconButton &button, bool clear) {
|
|||
|
||||
void IconbarTool::deleteIcons() {
|
||||
m_icon_container.removeAll();
|
||||
while (!m_icon_list.empty()) {
|
||||
delete m_icon_list.back();
|
||||
m_icon_list.pop_back();
|
||||
}
|
||||
STLUtil::destroyAndClearSecond(m_icons);
|
||||
}
|
||||
|
||||
void IconbarTool::removeWindow(Focusable &win) {
|
||||
// got window die signal, lets find and remove the window
|
||||
IconList::iterator it = m_icon_list.begin();
|
||||
IconList::iterator it_end = m_icon_list.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (&(*it)->win() == &win)
|
||||
break;
|
||||
}
|
||||
// did we find it?
|
||||
if (it == m_icon_list.end()) {
|
||||
IconMap::iterator it = m_icons.find(&win);
|
||||
if (it == m_icons.end())
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
cerr<<"IconbarTool::"<<__FUNCTION__<<"( 0x"<<&win<<" title = "<<win.title()<<") found!"<<endl;
|
||||
#endif // DEBUG
|
||||
// detach from all signals
|
||||
win.dieSig().detach(this);
|
||||
if (win.fbwindow()) {
|
||||
win.fbwindow()->workspaceSig().detach(this);
|
||||
win.fbwindow()->stateSig().detach(this);
|
||||
}
|
||||
|
||||
// remove from list and render theme again
|
||||
IconButton *button = *it;
|
||||
|
||||
m_icon_container.removeItem(m_icon_container.find(*it));
|
||||
m_icon_list.erase(it);
|
||||
|
||||
IconButton *button = it->second;
|
||||
m_icons.erase(it);
|
||||
m_icon_container.removeItem(button);
|
||||
delete button;
|
||||
|
||||
}
|
||||
|
||||
void IconbarTool::addWindow(Focusable &win) {
|
||||
IconButton *IconbarTool::makeButton(Focusable &win) {
|
||||
// we just want windows that have clients
|
||||
FluxboxWindow *fbwin = win.fbwindow();
|
||||
if (!fbwin || fbwin->clientList().empty() || fbwin->isIconHidden())
|
||||
return;
|
||||
if (!fbwin || fbwin->clientList().empty())
|
||||
return 0;
|
||||
#ifdef DEBUG
|
||||
cerr<<"IconbarTool::addWindow(0x"<<&win<<" title = "<<win.title()<<")"<<endl;
|
||||
#endif // DEBUG
|
||||
|
@ -660,39 +557,21 @@ void IconbarTool::addWindow(Focusable &win) {
|
|||
button->setOnClick(menu_cmd, 3);
|
||||
|
||||
renderButton(*button, false); // update the attributes, but don't clear it
|
||||
m_icon_container.insertItem(button);
|
||||
m_icon_list.push_back(button);
|
||||
|
||||
// dont forget to detach signal in removeWindow
|
||||
win.dieSig().attach(this);
|
||||
fbwin->workspaceSig().attach(this);
|
||||
fbwin->stateSig().attach(this);
|
||||
m_icons[&win] = button;
|
||||
return button;
|
||||
}
|
||||
|
||||
void IconbarTool::updateList() {
|
||||
list<Focusable *> ordered_list =
|
||||
m_screen.focusControl().creationOrderWinList();
|
||||
list<Focusable *>::iterator it = ordered_list.begin();
|
||||
list<Focusable *>::iterator it_end = ordered_list.end();
|
||||
list<Focusable *>::iterator it = m_winlist->clientList().begin();
|
||||
list<Focusable *>::iterator it_end = m_winlist->clientList().end();
|
||||
for (; it != it_end; ++it) {
|
||||
if ((*it)->fbwindow() && checkAddWindow(mode(), *(*it)->fbwindow()) &&
|
||||
!checkDuplicate(**it))
|
||||
addWindow(**it);
|
||||
if ((*it)->fbwindow())
|
||||
insertWindow(**it, -1);
|
||||
}
|
||||
|
||||
renderTheme();
|
||||
}
|
||||
|
||||
bool IconbarTool::checkDuplicate(Focusable &win) {
|
||||
IconList::iterator it = m_icon_list.begin();
|
||||
IconList::iterator it_end = m_icon_list.end();
|
||||
for (; it != it_end; ++it) {
|
||||
if (&win == &(*it)->win())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IconbarTool::setOrientation(FbTk::Orientation orient) {
|
||||
m_icon_container.setOrientation(orient);
|
||||
ToolbarItem::setOrientation(orient);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "ToolbarItem.hh"
|
||||
#include "Container.hh"
|
||||
#include "FbMenu.hh"
|
||||
#include "FocusableList.hh"
|
||||
|
||||
#include "FbTk/CachedPixmap.hh"
|
||||
#include "FbTk/Observer.hh"
|
||||
|
@ -36,7 +37,7 @@
|
|||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
class IconbarTheme;
|
||||
class BScreen;
|
||||
|
@ -45,17 +46,7 @@ class Focusable;
|
|||
|
||||
class IconbarTool: public ToolbarItem, public FbTk::Observer {
|
||||
public:
|
||||
typedef std::list<IconButton *> IconList;
|
||||
/// iconbar mode
|
||||
enum Mode {
|
||||
NONE, ///< no icons
|
||||
ICONS, ///< all icons from all workspaces
|
||||
NOICONS, ///< all noniconified windows from all workspaces
|
||||
WORKSPACEICONS, ///< icons on current workspace
|
||||
WORKSPACENOICONS, ///< non iconified workspaces on current workspaces
|
||||
WORKSPACE, ///< all windows and all icons on current workspace
|
||||
ALLWINDOWS ///< all windows and all icons from all workspaces
|
||||
};
|
||||
typedef std::map<Focusable *, IconButton *> IconMap;
|
||||
|
||||
IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme,
|
||||
BScreen &screen, FbTk::Menu &menu);
|
||||
|
@ -70,14 +61,14 @@ public:
|
|||
void show();
|
||||
void hide();
|
||||
void setAlignment(Container::Alignment a);
|
||||
void setMode(Mode mode);
|
||||
void setMode(std::string mode);
|
||||
void parentMoved() { m_icon_container.parentMoved(); }
|
||||
|
||||
unsigned int width() const;
|
||||
unsigned int height() const;
|
||||
unsigned int borderWidth() const;
|
||||
|
||||
Mode mode() const { return *m_rc_mode; }
|
||||
std::string mode() const { return *m_rc_mode; }
|
||||
|
||||
void setOrientation(FbTk::Orientation orient);
|
||||
Container::Alignment alignment() const { return m_icon_container.alignment(); }
|
||||
|
@ -85,9 +76,6 @@ public:
|
|||
const BScreen &screen() const { return m_screen; }
|
||||
private:
|
||||
|
||||
/// @return button associated with window
|
||||
IconButton *findButton(Focusable &win);
|
||||
|
||||
void updateSizing();
|
||||
|
||||
/// render single button, and probably apply changes (clear)
|
||||
|
@ -99,14 +87,16 @@ private:
|
|||
void renderTheme(unsigned char alpha);
|
||||
/// destroy all icons
|
||||
void deleteIcons();
|
||||
/// add or move a single window
|
||||
void insertWindow(Focusable &win, int pos = -2);
|
||||
/// remove a single window
|
||||
void removeWindow(Focusable &win);
|
||||
/// add a single window
|
||||
void addWindow(Focusable &win);
|
||||
/// make a button for the window
|
||||
IconButton *makeButton(Focusable &win);
|
||||
/// remove all windows and add again
|
||||
void reset();
|
||||
/// add icons to the list
|
||||
void updateList();
|
||||
/// check if window is already in the list
|
||||
bool checkDuplicate(Focusable &win);
|
||||
|
||||
BScreen &m_screen;
|
||||
Container m_icon_container;
|
||||
|
@ -114,8 +104,10 @@ private:
|
|||
FbTk::CachedPixmap m_empty_pm; ///< pixmap for empty container
|
||||
|
||||
|
||||
IconList m_icon_list;
|
||||
FbTk::Resource<Mode> m_rc_mode;
|
||||
std::auto_ptr<FocusableList> m_winlist;
|
||||
IconMap m_icons;
|
||||
std::string m_mode;
|
||||
FbTk::Resource<std::string> m_rc_mode;
|
||||
FbTk::Resource<Container::Alignment> m_rc_alignment; ///< alignment of buttons
|
||||
FbTk::Resource<int> m_rc_client_width; ///< size of client button in LEFT/RIGHT mode
|
||||
FbTk::Resource<unsigned int> m_rc_client_padding; ///< padding of the text
|
||||
|
|
|
@ -151,7 +151,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
|
|||
IconButton.hh IconButton.cc \
|
||||
IconbarTheme.hh IconbarTheme.cc \
|
||||
STLUtil.hh \
|
||||
Focusable.hh \
|
||||
Focusable.hh FocusableList.hh FocusableList.cc \
|
||||
${newwmspec_SOURCE} ${gnome_SOURCE} \
|
||||
${REMEMBER_SOURCE} ${TOOLBAR_SOURCE}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head,
|
|||
|
||||
std::list<FluxboxWindow *> windowlist;
|
||||
const std::list<Focusable *> focusables =
|
||||
win.screen().focusControl().focusedOrderWinList();
|
||||
win.screen().focusControl().focusedOrderWinList().clientList();
|
||||
std::list<Focusable *>::const_iterator foc_it = focusables.begin(),
|
||||
foc_it_end = focusables.end();
|
||||
unsigned int workspace = win.workspaceNumber();
|
||||
|
|
|
@ -33,7 +33,7 @@ bool RowSmartPlacement::placeWindow(const FluxboxWindow &win, int head,
|
|||
|
||||
std::list<FluxboxWindow *> windowlist;
|
||||
const std::list<Focusable *> focusables =
|
||||
win.screen().focusControl().focusedOrderWinList();
|
||||
win.screen().focusControl().focusedOrderWinList().clientList();
|
||||
std::list<Focusable *>::const_iterator foc_it = focusables.begin(),
|
||||
foc_it_end = focusables.end();
|
||||
unsigned int workspace = win.workspaceNumber();
|
||||
|
|
|
@ -346,6 +346,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
|
|||
m_workspacenames_sig(*this), // workspace names signal
|
||||
m_workspace_area_sig(*this), // workspace area signal
|
||||
m_currentworkspace_sig(*this), // current workspace signal
|
||||
m_focusedwindow_sig(*this), // focused window signal
|
||||
m_reconfigure_sig(*this), // reconfigure signal
|
||||
m_resize_sig(*this),
|
||||
m_bg_change_sig(*this),
|
||||
|
@ -871,19 +872,10 @@ void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) {
|
|||
}
|
||||
|
||||
if (mods == 0) // can't stacked cycle unless there is a mod to grab
|
||||
options |= FocusControl::CYCLELINEAR;
|
||||
|
||||
const FocusControl::Focusables *win_list = 0;
|
||||
if (options & FocusControl::CYCLEGROUPS) {
|
||||
win_list = (options & FocusControl::CYCLELINEAR) ?
|
||||
&focusControl().creationOrderWinList() :
|
||||
&focusControl().focusedOrderWinList();
|
||||
} else {
|
||||
win_list = (options & FocusControl::CYCLELINEAR) ?
|
||||
&focusControl().creationOrderList() :
|
||||
&focusControl().focusedOrderList();
|
||||
}
|
||||
options |= FocusableList::STATIC_ORDER;
|
||||
|
||||
const FocusableList *win_list =
|
||||
FocusableList::getListFromOptions(*this, options);
|
||||
focusControl().cycleFocus(*win_list, pat, reverse);
|
||||
|
||||
}
|
||||
|
|
|
@ -222,6 +222,8 @@ public:
|
|||
FbTk::Subject &workspaceAreaSig() { return m_workspace_area_sig; }
|
||||
/// current workspace signal
|
||||
FbTk::Subject ¤tWorkspaceSig() { return m_currentworkspace_sig; }
|
||||
/// focused window signal
|
||||
FbTk::Subject &focusedWindowSig() { return m_focusedwindow_sig; }
|
||||
/// reconfigure signal
|
||||
FbTk::Subject &reconfigureSig() { return m_reconfigure_sig; }
|
||||
FbTk::Subject &resizeSig() { return m_resize_sig; }
|
||||
|
@ -488,6 +490,7 @@ private:
|
|||
m_workspacenames_sig, ///< workspace names signal
|
||||
m_workspace_area_sig, ///< workspace area changed signal
|
||||
m_currentworkspace_sig, ///< current workspace signal
|
||||
m_focusedwindow_sig, ///< focused window signal
|
||||
m_reconfigure_sig, ///< reconfigure signal
|
||||
m_resize_sig, ///< resize signal
|
||||
m_bg_change_sig; ///< background change signal
|
||||
|
|
|
@ -1405,7 +1405,7 @@ void FluxboxWindow::iconify() {
|
|||
|
||||
hide(true);
|
||||
|
||||
screen().focusControl().setFocusBack(this);
|
||||
screen().focusControl().setFocusBack(*this);
|
||||
|
||||
ClientList::iterator client_it = m_clientlist.begin();
|
||||
const ClientList::iterator client_it_end = m_clientlist.end();
|
||||
|
@ -2038,10 +2038,6 @@ void FluxboxWindow::setState(unsigned long new_state, bool setting_up) {
|
|||
(*it)->show();
|
||||
(*it)->setEventMask(PropertyChangeMask | StructureNotifyMask | FocusChangeMask | KeyPressMask);
|
||||
}
|
||||
|
||||
saveBlackboxAttribs();
|
||||
//notify state changed
|
||||
m_statesig.notify();
|
||||
}
|
||||
|
||||
bool FluxboxWindow::getState() {
|
||||
|
|
|
@ -49,7 +49,7 @@ void WindowListCmd::execute() {
|
|||
|
||||
BScreen *screen = Fluxbox::instance()->keyScreen();
|
||||
if (screen != 0) {
|
||||
FocusControl::Focusables win_list(screen->focusControl().creationOrderWinList());
|
||||
FocusControl::Focusables win_list(screen->focusControl().creationOrderWinList().clientList());
|
||||
|
||||
FocusControl::Focusables::iterator it = win_list.begin(),
|
||||
it_end = win_list.end();
|
||||
|
@ -63,7 +63,7 @@ void WindowListCmd::execute() {
|
|||
void AttachCmd::execute() {
|
||||
BScreen *screen = Fluxbox::instance()->keyScreen();
|
||||
if (screen != 0) {
|
||||
FocusControl::Focusables win_list(screen->focusControl().focusedOrderWinList());
|
||||
FocusControl::Focusables win_list(screen->focusControl().focusedOrderWinList().clientList());
|
||||
|
||||
FocusControl::Focusables::iterator it = win_list.begin(),
|
||||
it_end = win_list.end();
|
||||
|
@ -95,16 +95,8 @@ void PrevWindowCmd::execute() {
|
|||
void GoToWindowCmd::execute() {
|
||||
BScreen *screen = Fluxbox::instance()->keyScreen();
|
||||
if (screen != 0) {
|
||||
const FocusControl::Focusables *win_list = 0;
|
||||
if (m_option & FocusControl::CYCLEGROUPS) {
|
||||
win_list = (m_option & FocusControl::CYCLELINEAR) ?
|
||||
&screen->focusControl().creationOrderWinList() :
|
||||
&screen->focusControl().focusedOrderWinList();
|
||||
} else {
|
||||
win_list = (m_option & FocusControl::CYCLELINEAR) ?
|
||||
&screen->focusControl().creationOrderList() :
|
||||
&screen->focusControl().focusedOrderList();
|
||||
}
|
||||
const FocusableList *win_list =
|
||||
FocusableList::getListFromOptions(*screen, m_option);
|
||||
screen->focusControl().goToWindowNumber(*win_list, m_num, &m_pat);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -514,6 +514,7 @@ void Fluxbox::initScreen(BScreen *screen) {
|
|||
|
||||
// attach screen signals to this
|
||||
screen->currentWorkspaceSig().attach(this);
|
||||
screen->focusedWindowSig().attach(this);
|
||||
screen->workspaceCountSig().attach(this);
|
||||
screen->workspaceNamesSig().attach(this);
|
||||
screen->workspaceAreaSig().attach(this);
|
||||
|
@ -642,7 +643,7 @@ void Fluxbox::setupConfigFiles() {
|
|||
if (create_init)
|
||||
FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str());
|
||||
|
||||
#define CONFIG_VERSION 4
|
||||
#define CONFIG_VERSION 5
|
||||
FbTk::Resource<int> config_version(m_resourcemanager, 0,
|
||||
"session.configVersion", "Session.ConfigVersion");
|
||||
if (*config_version < CONFIG_VERSION) {
|
||||
|
@ -1191,6 +1192,14 @@ void Fluxbox::update(FbTk::Subject *changedsub) {
|
|||
if ((*it).first->update())
|
||||
(*it).first->updateCurrentWorkspace(screen);
|
||||
}
|
||||
} else if ((&(screen.focusedWindowSig())) == changedsub) {
|
||||
for (AtomHandlerContainerIt it= m_atomhandler.begin();
|
||||
it != m_atomhandler.end(); it++) {
|
||||
(*it).first->updateFocusedWindow(screen,
|
||||
(FocusControl::focusedWindow() ?
|
||||
FocusControl::focusedWindow()->window() :
|
||||
0));
|
||||
}
|
||||
} else if ((&(screen.workspaceAreaSig())) == changedsub) {
|
||||
for (AtomHandlerContainerIt it= m_atomhandler.begin();
|
||||
it != m_atomhandler.end(); ++it) {
|
||||
|
@ -1682,23 +1691,6 @@ bool Fluxbox::validateClient(const WinClient *client) const {
|
|||
return it != m_window_search.end();
|
||||
}
|
||||
|
||||
void Fluxbox::updateFocusedWindow(BScreen *screen, BScreen *old_screen) {
|
||||
if (screen != 0) {
|
||||
for (AtomHandlerContainerIt it= m_atomhandler.begin();
|
||||
it != m_atomhandler.end(); it++) {
|
||||
(*it).first->updateFocusedWindow(*screen, (FocusControl::focusedWindow() ?
|
||||
FocusControl::focusedWindow()->window() :
|
||||
0));
|
||||
}
|
||||
}
|
||||
|
||||
if (old_screen && old_screen != screen) {
|
||||
for (AtomHandlerContainerIt it= m_atomhandler.begin();
|
||||
it != m_atomhandler.end(); it++)
|
||||
(*it).first->updateFocusedWindow(*old_screen, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Fluxbox::updateFrameExtents(FluxboxWindow &win) {
|
||||
AtomHandlerContainerIt it = m_atomhandler.begin();
|
||||
AtomHandlerContainerIt it_end = m_atomhandler.end();
|
||||
|
|
|
@ -162,12 +162,6 @@ public:
|
|||
/// handle any system signal sent to the application
|
||||
void handleSignal(int signum);
|
||||
void update(FbTk::Subject *changed);
|
||||
/**
|
||||
* Sends update signal to atomhandlers,
|
||||
* @param screen the new screen
|
||||
* @param old_screen the old screen if any, can be the same as new screen
|
||||
*/
|
||||
void updateFocusedWindow(BScreen *screen, BScreen *old_screen);
|
||||
/// todo, remove this. just temporary
|
||||
void updateFrameExtents(FluxboxWindow &win);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ string read_file(string filename);
|
|||
void write_file(string filename, string &contents);
|
||||
void save_all_files();
|
||||
|
||||
int run_updates(int old_version, FbTk::ResourceManager rm) {
|
||||
int run_updates(int old_version, FbTk::ResourceManager &rm) {
|
||||
int new_version = old_version;
|
||||
|
||||
FbTk::Resource<string> rc_keyfile(rm, "~/.fluxbox/keys",
|
||||
|
@ -214,6 +214,31 @@ int run_updates(int old_version, FbTk::ResourceManager rm) {
|
|||
new_version = 4;
|
||||
}
|
||||
|
||||
if (old_version < 5) { // window patterns for iconbar
|
||||
// this needs to survive after going out of scope
|
||||
// it won't get freed, but that's ok
|
||||
FbTk::Resource<string> *rc_mode =
|
||||
new FbTk::Resource<string>(rm, "Workspace",
|
||||
"session.screen0.iconbar.mode",
|
||||
"Session.Screen0.Iconbar.Mode");
|
||||
if (strcasecmp((**rc_mode).c_str(), "None") == 0)
|
||||
*rc_mode = "none";
|
||||
else if (strcasecmp((**rc_mode).c_str(), "Icons") == 0)
|
||||
*rc_mode = "{static groups} (minimized=yes)";
|
||||
else if (strcasecmp((**rc_mode).c_str(), "NoIcons") == 0)
|
||||
*rc_mode = "{static groups} (minimized=no)";
|
||||
else if (strcasecmp((**rc_mode).c_str(), "WorkspaceIcons") == 0)
|
||||
*rc_mode = "{static groups} (minimized=yes) (workspace)";
|
||||
else if (strcasecmp((**rc_mode).c_str(), "WorkspaceNoIcons") == 0)
|
||||
*rc_mode = "{static groups} (minimized=no) (workspace)";
|
||||
else if (strcasecmp((**rc_mode).c_str(), "AllWindows") == 0)
|
||||
*rc_mode = "{static groups}";
|
||||
else
|
||||
*rc_mode = "{static groups} (workspace)";
|
||||
|
||||
new_version = 5;
|
||||
}
|
||||
|
||||
return new_version;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue