From 675bc5d66aa08311e99cb00cf836d16a910a73df Mon Sep 17 00:00:00 2001 From: markt Date: Thu, 22 Nov 2007 04:07:57 +0000 Subject: added conditional statements to keys file --- ChangeLog | 18 +++++ src/CurrentWindowCmd.cc | 23 ++++-- src/CurrentWindowCmd.hh | 26 ++++++- src/FbCommandFactory.cc | 192 +++++++++++++++++++++++++++++++++++++++------- src/FbTk/Command.hh | 8 ++ src/FbTk/LogicCommands.cc | 75 ++++++++++++++++++ src/FbTk/LogicCommands.hh | 97 +++++++++++++++++++++++ src/FbTk/Makefile.am | 1 + src/FbTk/SimpleCommand.hh | 12 +++ src/WorkspaceCmd.cc | 49 +++++++++++- src/WorkspaceCmd.hh | 28 ++++++- 11 files changed, 486 insertions(+), 43 deletions(-) create mode 100644 src/FbTk/LogicCommands.cc create mode 100644 src/FbTk/LogicCommands.hh diff --git a/ChangeLog b/ChangeLog index 95cce9a..18c51ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ (Format: Year/Month/Day) Changes for 1.0.1: +*07/11/22: + * Added conditional statements to key commands (Mark) + - for example, this will search for an open xterm window, cycle through + them if there are any, or else open one: + Mod4 t :If {Some Matches (xterm)} {NextWindow (xterm)} {Exec xterm} + - the syntax is :If {} {} {} + - `Matches ' is currently the only test you can make; when used + alone, it tests the focused window or the clicked window for OnWindow + mouse events + - there are many ways to combine tests: + - `Some ' returns true if any open client matches + - `Every ' returns true if every open client matches + - `Not ' negates the value of + - `Or {} {} ...' returns true if any of the tests is true + - `And {} {} ...' returns true if all of the tests are true + - `Xor {} {} ...' returns the boolean xor of the truth values + FbCommandFactory.cc CurrentWindowCmd.cc/hh WorkspaceCmd.cc/hh + FbTk/Command.hh FbTk/SimpleCommand.hh, added files FbTk/LogicCommands.cc/hh *07/11/16: * Added new key command :Focus [] that focuses a window (e.g., using OnWindow or specified using a window pattern) (Mark, thanks Tomas Janousek) diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index 929be5d..a5265f9 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -33,20 +33,25 @@ #include "FocusControl.hh" void WindowHelperCmd::execute() { - m_win = 0; if (WindowCmd::window() || FocusControl::focusedFbWindow()) real_execute(); } -void WindowHelperCmd::execute(FluxboxWindow &win) { - m_win = &win; - real_execute(); +FluxboxWindow &WindowHelperCmd::fbwindow() { + // will exist from execute above + FluxboxWindow *tmp = WindowCmd::window(); + if (tmp) return *tmp; + return *FocusControl::focusedFbWindow(); } -FluxboxWindow &WindowHelperCmd::fbwindow() { +bool WindowHelperBoolCmd::bool_execute() { + if (WindowCmd::window() || FocusControl::focusedFbWindow()) + return real_execute(); + return false; +} + +FluxboxWindow &WindowHelperBoolCmd::fbwindow() { // will exist from execute above - if (m_win) - return *m_win; FluxboxWindow *tmp = WindowCmd::window(); if (tmp) return *tmp; return *FocusControl::focusedFbWindow(); @@ -227,3 +232,7 @@ void SetAlphaCmd::real_execute() { } else fbwindow().setUnfocusedAlpha(m_unfocus); } + +bool MatchCmd::real_execute() { + return m_pat.match(fbwindow()); +} diff --git a/src/CurrentWindowCmd.hh b/src/CurrentWindowCmd.hh index 53dc7b8..e7370de 100644 --- a/src/CurrentWindowCmd.hh +++ b/src/CurrentWindowCmd.hh @@ -27,22 +27,30 @@ #include "Command.hh" #include "Window.hh" +#include "ClientPattern.hh" /// helper class for window commands /// calls real_execute if there's a focused window or a window in button press/release window class WindowHelperCmd: public FbTk::Command { public: - explicit WindowHelperCmd(FluxboxWindow *win = 0): m_win(win) { } + explicit WindowHelperCmd() { } void execute(); - void execute(FluxboxWindow &fbwin); protected: FluxboxWindow &fbwindow(); virtual void real_execute() = 0; +}; -private: - FluxboxWindow *m_win; +class WindowHelperBoolCmd: public FbTk::BoolCommand { +public: + explicit WindowHelperBoolCmd() { } + + bool bool_execute(); + +protected: + FluxboxWindow &fbwindow(); + virtual bool real_execute() = 0; }; /// command that calls FluxboxWindow:: on execute() @@ -221,4 +229,14 @@ private: int m_focus, m_unfocus; int m_relative, m_un_relative; }; + +class MatchCmd: public WindowHelperBoolCmd { +public: + MatchCmd(const std::string &pat): m_pat(pat.c_str()) { }; +protected: + bool real_execute(); +private: + ClientPattern m_pat; +}; + #endif // CURRENTWINDOWCMD_HH diff --git a/src/FbCommandFactory.cc b/src/FbCommandFactory.cc index ce024eb..92099f2 100644 --- a/src/FbCommandFactory.cc +++ b/src/FbCommandFactory.cc @@ -34,6 +34,7 @@ #include "Screen.hh" #include "FbTk/StringUtil.hh" +#include "FbTk/LogicCommands.hh" #include "FbTk/MacroCommand.hh" #include "FbTk/stringstream.hh" @@ -50,6 +51,10 @@ using std::vector; using std::cerr; using std::endl; +using namespace FbTk; +using FbTk::StringUtil::removeFirstWhitespace; +using FbTk::StringUtil::toLower; + // autoregister this module to command parser FbCommandFactory FbCommandFactory::s_autoreg; @@ -60,6 +65,109 @@ static int getint(const char *str, int defaultvalue) { return defaultvalue; } +BoolCommand *parseBoolCommand(string &line, bool trusted) { + // parse arguments and command + string command = line; + string arguments; + string::size_type first_pos = removeFirstWhitespace(command); + FbTk::StringUtil::removeTrailingWhitespace(command); + string::size_type second_pos = command.find_first_of(" \t", first_pos); + if (second_pos != string::npos) { + // ok we have arguments, parsing them here + arguments = command.substr(second_pos); + removeFirstWhitespace(arguments); + command.erase(second_pos); // remove argument from command + } + + // now we have parsed command and arguments + command = toLower(command); + + if (command == "matches") { + return new MatchCmd(arguments); + } else if (command == "some") { + BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); + if (!boolcmd) + return 0; + return new SomeCmd(RefCount(boolcmd)); + } else if (command == "every") { + BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); + if (!boolcmd) + return 0; + return new EveryCmd(RefCount(boolcmd)); + } else if (command == "not") { + BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); + if (!boolcmd) + return 0; + RefCount ref(boolcmd); + return new NotCommand(ref); + } else if (command == "and") { + int pos = 0, err = 0; + AndCommand *andcmd = new AndCommand(); + string cmd; + + while (true) { + RefCount tmp(0); + err = StringUtil::getStringBetween(cmd, arguments.c_str() + pos, + '{', '}', " \t\n", true); + pos += err; + if (err == 0) + break; + + tmp = parseBoolCommand(cmd, trusted); + if (*tmp) + andcmd->add(tmp); + } + + if (andcmd->size() > 0) + return andcmd; + delete andcmd; + } else if (command == "or") { + int pos = 0, err = 0; + OrCommand *orcmd = new OrCommand(); + string cmd; + + while (true) { + RefCount tmp(0); + err = StringUtil::getStringBetween(cmd, arguments.c_str() + pos, + '{', '}', " \t\n", true); + pos += err; + if (err == 0) + break; + + tmp = parseBoolCommand(cmd, trusted); + if (*tmp) + orcmd->add(tmp); + } + + if (orcmd->size() > 0) + return orcmd; + delete orcmd; + } else if (command == "xor") { + int pos = 0, err = 0; + XorCommand *xorcmd = new XorCommand(); + string cmd; + + while (true) { + RefCount tmp(0); + err = StringUtil::getStringBetween(cmd, arguments.c_str() + pos, + '{', '}', " \t\n", true); + pos += err; + if (err == 0) + break; + + tmp = parseBoolCommand(cmd, trusted); + if (*tmp) + xorcmd->add(tmp); + } + + if (xorcmd->size() > 0) + return xorcmd; + delete xorcmd; + } + + return 0; +} + }; // end anonymous namespace FbCommandFactory::FbCommandFactory() { @@ -74,6 +182,7 @@ FbCommandFactory::FbCommandFactory() { "close", "closeallwindows", "commanddialog", + "cond", "custommenu", "deiconify", "detachclient", @@ -91,6 +200,7 @@ FbCommandFactory::FbCommandFactory() { "gotowindow", "hidemenus", "iconify", + "if", "keymode", "kill", "killwindow", @@ -246,15 +356,15 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, // Current focused window commands // else if (command == "fullscreen") - return new WindowListCmd(FbTk::RefCount(new FullscreenCmd()), arguments); + return new WindowListCmd(FbTk::RefCount(new FullscreenCmd()), arguments); else if (command == "minimizewindow" || command == "minimize" || command == "iconify") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::iconify)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::iconify)), arguments); else if (command == "maximizewindow" || command == "maximize") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeFull)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeFull)), arguments); else if (command == "maximizevertical") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeVertical)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeVertical)), arguments); else if (command == "maximizehorizontal") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal)), arguments); else if (command == "setalpha") { typedef vector StringTokens; StringTokens tokens; @@ -281,7 +391,7 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, if (pos != string::npos && pos != arguments.size()) pat = arguments.c_str() + pos; - return new WindowListCmd(FbTk::RefCount(new SetAlphaCmd(focused, relative, unfocused, un_rel)), pat); + return new WindowListCmd(FbTk::RefCount(new SetAlphaCmd(focused, relative, unfocused, un_rel)), pat); } else if (command == "startmoving") return new StartMovingCmd(); else if (command == "startresizing") { @@ -331,7 +441,7 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, if (pos != string::npos && pos != arguments.size()) pat = arguments.c_str() + pos; - FbTk::RefCount cmd; + FbTk::RefCount cmd; if (command == "resizeto") cmd = new ResizeToCmd(dx, dy); else @@ -386,7 +496,7 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, if (pos != string::npos && pos != arguments.size()) pat = arguments.c_str() + pos; - return new WindowListCmd(FbTk::RefCount(new MoveToCmd(dx, dy, refc)), pat); + return new WindowListCmd(FbTk::RefCount(new MoveToCmd(dx, dy, refc)), pat); } else if (command == "move" || command == "moveright" || command == "moveleft" || command == "moveup" || command == "movedown") { @@ -412,29 +522,29 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, if (pos != string::npos && pos != arguments.size()) pat = arguments.c_str() + pos; - return new WindowListCmd(FbTk::RefCount(new MoveCmd(dx, dy)), pat); + return new WindowListCmd(FbTk::RefCount(new MoveCmd(dx, dy)), pat); } else if (command == "raise") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::raise)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::raise)), arguments); else if (command == "raiselayer") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::raiseLayer)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::raiseLayer)), arguments); else if (command == "lower") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::lower)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::lower)), arguments); else if (command == "lowerlayer") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::lowerLayer)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::lowerLayer)), arguments); else if (command == "activate" || command == "focus") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd((void (FluxboxWindow::*)())&FluxboxWindow::focus)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd((void (FluxboxWindow::*)())&FluxboxWindow::focus)), arguments); else if (command == "close") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::close)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::close)), arguments); else if (command == "closeallwindows") return new CloseAllWindowsCmd(); else if (command == "killwindow" || command == "kill") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::kill)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::kill)), arguments); else if (command == "shade" || command == "shadewindow") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::shade)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::shade)), arguments); else if (command == "stick" || command == "stickwindow") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::stick)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::stick)), arguments); else if (command == "toggledecor") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::toggleDecoration)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::toggleDecoration)), arguments); else if (command == "sethead") { int num = 0; string pat; @@ -443,7 +553,7 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, string::size_type pos = arguments.find('('); if (pos != string::npos && pos != arguments.size()) pat = arguments.c_str() + pos; - return new WindowListCmd(FbTk::RefCount(new SetHeadCmd(num)), pat); + return new WindowListCmd(FbTk::RefCount(new SetHeadCmd(num)), pat); } else if (command == "tab" || command == "sendtonextworkspace" || command == "sendtoprevworkspace" || command == "taketonextworkspace" || @@ -457,7 +567,7 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, string::size_type pos = arguments.find('('); if (pos != string::npos && pos != arguments.size()) pat = arguments.c_str() + pos; - FbTk::RefCount cmd; + FbTk::RefCount cmd; if (command == "tab") cmd = new GoToTabCmd(num); @@ -475,15 +585,15 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, cmd = new TakeToWorkspaceCmd(num-1); return new WindowListCmd(cmd, pat); } else if (command == "nexttab") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::nextClient)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::nextClient)), arguments); else if (command == "prevtab") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::prevClient)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::prevClient)), arguments); else if (command == "movetableft") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::moveClientLeft)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::moveClientLeft)), arguments); else if (command == "movetabright") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::moveClientRight)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::moveClientRight)), arguments); else if (command == "detachclient") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::detachCurrentClient)), arguments); + return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::detachCurrentClient)), arguments); else if (command == "windowmenu") return new CurrentWindowCmd(&FluxboxWindow::popupMenu); // @@ -683,6 +793,36 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, return macro; delete macro; + } else if (command == "if" || command == "cond") { + string cmd; + int err = 0, pos = 0; + RefCount cond(0); + RefCount t(0), f(0); + + err = FbTk::StringUtil::getStringBetween(cmd, arguments.c_str(), + '{', '}', " \t\n", true); + if (err > 0) + cond = parseBoolCommand(cmd, trusted); + if (err == 0 || *cond == 0) + return 0; + + pos = err; + err = FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() + pos, + '{', '}', " \t\n", true); + if (err > 0) + t = CommandParser::instance().parseLine(cmd, trusted); + if (err == 0 || *t == 0) + return 0; + + pos += err; + err = FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() + pos, + '{', '}', " \t\n", true); + if (err > 0) + f = CommandParser::instance().parseLine(cmd, trusted); + if (err == 0 || *f == 0) + return 0; + + return new FbTk::IfCommand(cond, t, f); } return 0; } diff --git a/src/FbTk/Command.hh b/src/FbTk/Command.hh index 391aa78..5d38cb8 100644 --- a/src/FbTk/Command.hh +++ b/src/FbTk/Command.hh @@ -31,6 +31,14 @@ public: virtual void execute() = 0; }; +/// Interface class for boolean commands +class BoolCommand: public Command { +public: + virtual ~BoolCommand() { } + virtual void execute() { bool_execute(); } + virtual bool bool_execute() = 0; +}; + } // end namespace FbTk #endif // FBTK_COMMAND_HH diff --git a/src/FbTk/LogicCommands.cc b/src/FbTk/LogicCommands.cc new file mode 100644 index 0000000..99b5b53 --- /dev/null +++ b/src/FbTk/LogicCommands.cc @@ -0,0 +1,75 @@ +// LogicCommands.cc for FbTk +// 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 "LogicCommands.hh" + +namespace FbTk { + +void OrCommand::add(RefCount &com) { + m_commandlist.push_back(com); +} + +size_t OrCommand::size() const { + return m_commandlist.size(); +} + +bool OrCommand::bool_execute() { + for (size_t i=0; i < m_commandlist.size(); ++i) { + if (m_commandlist[i]->bool_execute()) + return true; + } + return false; +} + +void AndCommand::add(RefCount &com) { + m_commandlist.push_back(com); +} + +size_t AndCommand::size() const { + return m_commandlist.size(); +} + +bool AndCommand::bool_execute() { + for (size_t i=0; i < m_commandlist.size(); ++i) { + if (!m_commandlist[i]->bool_execute()) + return false; + } + return true; +} + +void XorCommand::add(RefCount &com) { + m_commandlist.push_back(com); +} + +size_t XorCommand::size() const { + return m_commandlist.size(); +} + +bool XorCommand::bool_execute() { + bool ret = false; + for (size_t i=0; i < m_commandlist.size(); ++i) + ret ^= m_commandlist[i]->bool_execute(); + return ret; +} + +}; // end namespace FbTk diff --git a/src/FbTk/LogicCommands.hh b/src/FbTk/LogicCommands.hh new file mode 100644 index 0000000..a94dad8 --- /dev/null +++ b/src/FbTk/LogicCommands.hh @@ -0,0 +1,97 @@ +// LogicCommands.hh for FbTk +// 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 FBTK_LOGICCOMMANDS_HH +#define FBTK_LOGICCOMMANDS_HH + +#include "Command.hh" +#include "RefCount.hh" + +#include + +namespace FbTk { + +/// executes a boolcommand and uses the result to decide what to do +class IfCommand: public Command { +public: + IfCommand(RefCount &cond, + RefCount &t, RefCount &f): + m_cond(cond), m_t(t), m_f(f) { } + void execute() { + if (m_cond->bool_execute()) + m_t->execute(); + else + m_f->execute(); + } + +private: + RefCount m_cond; + RefCount m_t, m_f; +}; + +/// executes a list of boolcommands until one is true +class OrCommand: public BoolCommand { +public: + void add(RefCount &com); + size_t size() const; + bool bool_execute(); + +private: + std::vector > m_commandlist; +}; + +/// executes a list of boolcommands until one is false +class AndCommand: public BoolCommand { +public: + void add(RefCount &com); + size_t size() const; + bool bool_execute(); + +private: + std::vector > m_commandlist; +}; + +/// executes a list of boolcommands, returning the parity +class XorCommand: public BoolCommand { +public: + void add(RefCount &com); + size_t size() const; + bool bool_execute(); + +private: + std::vector > m_commandlist; +}; + +/// executes a boolcommand and returns the negation +class NotCommand: public BoolCommand { +public: + NotCommand(RefCount &com): m_command(com) { } + bool bool_execute() { return !m_command->bool_execute(); } + +private: + RefCount m_command; +}; + +} // end namespace FbTk + +#endif // FBTK_LOGICCOMMANDS_HH diff --git a/src/FbTk/Makefile.am b/src/FbTk/Makefile.am index d98c8f6..2bf9da7 100644 --- a/src/FbTk/Makefile.am +++ b/src/FbTk/Makefile.am @@ -21,6 +21,7 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \ FbWindow.hh FbWindow.cc Font.cc Font.hh FontImp.hh \ I18n.cc I18n.hh \ ImageControl.hh ImageControl.cc \ + LogicCommands.hh LogicCommands.cc \ MacroCommand.hh MacroCommand.cc \ Menu.hh Menu.cc MenuItem.hh MenuItem.cc \ MultiButtonMenuItem.hh MultiButtonMenuItem.cc \ diff --git a/src/FbTk/SimpleCommand.hh b/src/FbTk/SimpleCommand.hh index 8cc7283..7ae91a5 100644 --- a/src/FbTk/SimpleCommand.hh +++ b/src/FbTk/SimpleCommand.hh @@ -39,6 +39,18 @@ private: Action m_action; }; +template +class SimpleBoolCommand: public BoolCommand { +public: + typedef ReturnType (Receiver::* Action)(); + SimpleBoolCommand(Receiver &r, Action a): + m_receiver(r), m_action(a) { } + bool bool_execute() { return (bool)(m_receiver.*m_action)(); } +private: + Receiver &m_receiver; + Action m_action; +}; + } // end namespace FbTk #endif // FBTK_SIMPLECOMMAND_HH diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 79ceb40..26f113d 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc @@ -30,6 +30,7 @@ #include "fluxbox.hh" #include "WinClient.hh" #include "FocusControl.hh" +#include "WindowCmd.hh" #include "FbTk/KeyUtil.hh" @@ -54,10 +55,54 @@ void WindowListCmd::execute() { FocusControl::Focusables::iterator it = win_list.begin(), it_end = win_list.end(); for (; it != it_end; ++it) { - if (m_pat.match(**it) && (*it)->fbwindow()) - m_cmd->execute(*(*it)->fbwindow()); + if (m_pat.match(**it) && (*it)->fbwindow()) { + WindowCmd::setWindow((*it)->fbwindow()); + m_cmd->execute(); + } + } + } +} + +bool SomeCmd::bool_execute() { + if (m_pat.error()) + return m_cmd->bool_execute(); + + BScreen *screen = Fluxbox::instance()->keyScreen(); + if (screen != 0) { + FocusControl::Focusables win_list(screen->focusControl().creationOrderList().clientList()); + + FocusControl::Focusables::iterator it = win_list.begin(), + it_end = win_list.end(); + for (; it != it_end; ++it) { + WinClient *client = dynamic_cast(*it); + if (!client) continue; + WindowCmd::setClient(client); + if (m_cmd->bool_execute()) + return true; + } + } + return false; +} + +bool EveryCmd::bool_execute() { + if (m_pat.error()) + return m_cmd->bool_execute(); + + BScreen *screen = Fluxbox::instance()->keyScreen(); + if (screen != 0) { + FocusControl::Focusables win_list(screen->focusControl().creationOrderList().clientList()); + + FocusControl::Focusables::iterator it = win_list.begin(), + it_end = win_list.end(); + for (; it != it_end; ++it) { + WinClient *client = dynamic_cast(*it); + if (!client) continue; + WindowCmd::setClient(client); + if (!m_cmd->bool_execute()) + return false; } } + return true; } void AttachCmd::execute() { diff --git a/src/WorkspaceCmd.hh b/src/WorkspaceCmd.hh index a530ae8..4f4545d 100644 --- a/src/WorkspaceCmd.hh +++ b/src/WorkspaceCmd.hh @@ -32,17 +32,37 @@ #include "FbTk/RefCount.hh" -class WindowHelperCmd; - class WindowListCmd: public FbTk::Command { public: - WindowListCmd(FbTk::RefCount cmd, const std::string &pat): + WindowListCmd(FbTk::RefCount cmd, const std::string &pat): m_cmd(cmd), m_pat(pat.c_str()) { } void execute(); private: - FbTk::RefCount m_cmd; + FbTk::RefCount m_cmd; + ClientPattern m_pat; +}; + +class SomeCmd: public FbTk::BoolCommand { +public: + SomeCmd(FbTk::RefCount cmd): m_cmd(cmd) { } + + bool bool_execute(); + +private: + FbTk::RefCount m_cmd; + ClientPattern m_pat; +}; + +class EveryCmd: public FbTk::BoolCommand { +public: + EveryCmd(FbTk::RefCount cmd): m_cmd(cmd) { } + + bool bool_execute(); + +private: + FbTk::RefCount m_cmd; ClientPattern m_pat; }; -- cgit v0.11.2