support in remember for specifying groups.

Also split atomhandler::setupWindow
This commit is contained in:
rathnor 2003-07-04 01:03:41 +00:00
parent 672ac02352
commit 3144086eef
16 changed files with 239 additions and 68 deletions

3
BUGS
View file

@ -19,6 +19,9 @@ bugs:
large number of [remote] xload windows.
* Can lock up on workspace change - possibly related to above as it
works when there aren't too many xload windows started up yet.
* Remember-patch grouping can change order on each restart. Need to turn
off remember functionality when restarting (only use it for first
instance).
other todo:
FAQ items for:

View file

@ -1,5 +1,19 @@
(Format: Year/Month/Day)
Changes for 0.9.4:
*03/07/04:
* Add support in remember for grouping apps (Simon)
Achieved by using [group], e.g.
[group]
[app] (title=groupme)
[Deco] {NONE}
[end]
will group anything with the title "groupme" and will give that group
no decorations. You can have multiple [app] lines in a [group].
Recall that app lines can also use regular expressions.
- also includes split AtomHandler::setupWindow(fbw) into
setupFrame(fbw) and setupClient(winclient).
Remember.hh/cc Window.cc Screen.cc fluxbox.hh/cc
AtomHandler.hh Gnome.hh/cc Ewmh.hh/cc ToolbarHandler.hh/cc
*03/07/03:
* Added selected dot for style menu so one can see which style is selected (Henrik)
Screen.cc

View file

@ -133,7 +133,7 @@ Key Features:
* Regular expression support in remember
on several attributes (Simon)
* Save grouping so it persists over restart (Simon)
- Autogrouping functionality into remember (Simon)
* Autogrouping functionality into remember (Simon)
(this will thus get regexp matching etc)
+ Shaped menu/slit/toolbar (Henrik)
* Improved screen object placement (Henrik)

View file

@ -19,7 +19,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: AtomHandler.hh,v 1.8 2003/06/18 13:32:19 fluxgen Exp $
// $Id: AtomHandler.hh,v 1.9 2003/07/04 01:03:40 rathnor Exp $
#ifndef ATOMHANDLER_HH
#define ATOMHANDLER_HH
@ -27,6 +27,7 @@
#include <X11/Xlib.h>
class FluxboxWindow;
class WinClient;
class BScreen;
class AtomHandler {
@ -34,7 +35,8 @@ public:
virtual ~AtomHandler() { }
virtual void initForScreen(BScreen &screen) = 0;
virtual void setupWindow(FluxboxWindow &win) = 0;
virtual void setupFrame(FluxboxWindow &win) = 0;
virtual void setupClient(WinClient &winclient) = 0;
virtual void updateClientList(BScreen &screen) = 0;
virtual void updateWorkspaceNames(BScreen &screen) = 0;

View file

@ -19,7 +19,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Ewmh.cc,v 1.28 2003/07/02 14:31:43 fluxgen Exp $
// $Id: Ewmh.cc,v 1.29 2003/07/04 01:03:40 rathnor Exp $
#include "Ewmh.hh"
@ -95,7 +95,7 @@ void Ewmh::initForScreen(BScreen &screen) {
}
void Ewmh::setupWindow(FluxboxWindow &win) {
void Ewmh::setupFrame(FluxboxWindow &win) {
Atom ret_type;
int fmt;

View file

@ -19,7 +19,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Ewmh.hh,v 1.7 2003/06/18 13:33:15 fluxgen Exp $
// $Id: Ewmh.hh,v 1.8 2003/07/04 01:03:40 rathnor Exp $
#include "AtomHandler.hh"
@ -32,8 +32,9 @@ public:
Ewmh();
~Ewmh();
void initForScreen(BScreen &screen);
void setupWindow(FluxboxWindow &win);
void setupFrame(FluxboxWindow &win);
void setupClient(WinClient &winclient) {}
void updateClientList(BScreen &screen);
void updateWorkspaceNames(BScreen &screen);
void updateCurrentWorkspace(BScreen &screen);

View file

@ -19,7 +19,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Gnome.cc,v 1.28 2003/06/26 12:22:42 rathnor Exp $
// $Id: Gnome.cc,v 1.29 2003/07/04 01:03:40 rathnor Exp $
#include "Gnome.hh"
@ -85,8 +85,8 @@ void Gnome::initForScreen(BScreen &screen) {
}
void Gnome::setupWindow(FluxboxWindow &win) {
// load gnome state atom
void Gnome::setupFrame(FluxboxWindow &win) {
// load gnome state (take queues from the main window of the frame)
Display *disp = FbTk::App::instance()->display();
Atom ret_type;
int fmt;

View file

@ -19,7 +19,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Gnome.hh,v 1.7 2003/06/18 13:32:43 fluxgen Exp $
// $Id: Gnome.hh,v 1.8 2003/07/04 01:03:40 rathnor Exp $
#ifndef GNOME_HH
#define GNOME_HH
@ -65,7 +65,8 @@ public:
Gnome();
~Gnome();
void initForScreen(BScreen &screen);
void setupWindow(FluxboxWindow &win);
void setupFrame(FluxboxWindow &win);
void setupClient(WinClient &winclient) {}
void updateClientList(BScreen &screen);
void updateWorkspaceNames(BScreen &screen);

View file

@ -21,7 +21,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Remember.cc,v 1.24 2003/06/12 15:12:19 rathnor Exp $
// $Id: Remember.cc,v 1.25 2003/07/04 01:03:40 rathnor Exp $
#include "Remember.hh"
#include "ClientPattern.hh"
@ -46,6 +46,7 @@
#include <fstream>
#include <string>
#include <memory>
#include <set>
using namespace std;
@ -128,7 +129,10 @@ FbTk::Menu *createRememberMenu(Remember &remember, FluxboxWindow &win) {
}; // end anonymous namespace
Application::Application() {
Application::Application(bool grouped)
: is_grouped(grouped),
group(0)
{
workspace_remember =
dimensions_remember =
position_remember =
@ -146,6 +150,7 @@ Application::Application() {
************/
Remember::Remember() {
enableUpdate();
load();
}
@ -155,12 +160,19 @@ Remember::~Remember() {
// the patterns free the "Application"s
// the client mapping shouldn't need cleaning
Patterns::iterator it;
std::set<Application *> all_apps; // no duplicates
while (!m_pats.empty()) {
it = m_pats.begin();
delete it->first; // ClientPattern
delete it->second; // Application
all_apps.insert(it->second); // Application, not necessarily unique
m_pats.erase(it);
}
std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates
while (ait != all_apps.end()) {
delete (*ait);
++ait;
}
}
Application* Remember::find(WinClient &winclient) {
@ -184,7 +196,7 @@ Application* Remember::find(WinClient &winclient) {
Application * Remember::add(WinClient &winclient) {
ClientPattern *p = new ClientPattern();
Application *app = new Application();
Application *app = new Application(false);
// by default, we match against the WMClass of a window.
p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
m_clients[&winclient] = app;
@ -193,11 +205,16 @@ Application * Remember::add(WinClient &winclient) {
return app;
}
int Remember::parseApp(ifstream &file, Application &app) {
int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
string line;
int row = 0;
while (! file.eof()) {
if (getline(file, line)) {
if (first_line || getline(file, line)) {
if (first_line) {
line = *first_line;
first_line = 0;
}
row++;
if (line[0] != '#') { //the line is commented
int parse_pos = 0, err = 0;
@ -307,6 +324,8 @@ void Remember::load() {
if (!apps_file.eof()) {
string line;
int row = 0;
bool in_group = false;
std::list<ClientPattern *> grouped_pats;
while (getline(apps_file, line) && ! apps_file.eof()) {
row++;
if (line[0] == '#')
@ -319,14 +338,36 @@ void Remember::load() {
if (pos > 0 && key == "app") {
ClientPattern *pat = new ClientPattern(line.c_str() + pos);
if ((err = pat->error()) == 0) {
Application *app = new Application();
m_pats.push_back(make_pair(pat, app));
row += parseApp(apps_file, *app);
if (!in_group) {
if ((err = pat->error()) == 0) {
Application *app = new Application(false);
m_pats.push_back(make_pair(pat, app));
row += parseApp(apps_file, *app);
} else {
cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
delete pat; // since it didn't work
}
} else {
cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
delete pat; // since it didn't work
grouped_pats.push_back(pat);
}
} else if (pos > 0 && key == "group") {
in_group = true;
} else if (in_group) {
// otherwise assume that it is the start of the attributes
Application *app = new Application(true);
while (!grouped_pats.empty()) {
// associate all the patterns with this app
m_pats.push_back(make_pair(grouped_pats.front(), app));
grouped_pats.pop_front();
}
// we hit end... probably don't have attribs for the group
// so finish it off with an empty application
// otherwise parse the app
if (!(pos>0 && key == "end")) {
row += parseApp(apps_file, *app, &line);
}
in_group = false;
} else
cerr<<"Error in apps file on line "<<row<<"."<<endl;
@ -350,9 +391,27 @@ void Remember::save() {
ofstream apps_file(apps_string.c_str());
Patterns::iterator it = m_pats.begin();
Patterns::iterator it_end = m_pats.end();
std::set<Application *> grouped_apps; // no duplicates
for (; it != it_end; ++it) {
apps_file << "[app]"<<it->first->toString()<<endl;
Application &a = *it->second;
if (a.is_grouped) {
// if already processed
if (grouped_apps.find(&a) != grouped_apps.end())
continue;
// otherwise output this whole group
apps_file << "[group]" << endl;
Patterns::iterator git = m_pats.begin();
Patterns::iterator git_end = m_pats.end();
for (; git != git_end; git++) {
if (git->second->group == a.group) {
apps_file << " [app]"<<git->first->toString()<<endl;
}
}
} else {
apps_file << "[app]"<<it->first->toString()<<endl;
}
if (a.workspace_remember) {
apps_file << " [Workspace]\t{" << a.workspace << "}" << endl;
}
@ -541,7 +600,7 @@ void Remember::forgetAttrib(WinClient &winclient, Attribute attrib) {
}
}
void Remember::setupWindow(FluxboxWindow &win) {
void Remember::setupFrame(FluxboxWindow &win) {
WinClient &winclient = win.winClient();
// we don't touch the window if it is a transient
@ -573,7 +632,10 @@ void Remember::setupWindow(FluxboxWindow &win) {
if (app == 0)
return; // nothing to do
BScreen &screen = win.screen();
if (app->is_grouped && app->group == 0)
app->group = &win;
BScreen &screen = winclient.screen();
if (app->workspace_remember) {
// TODO: fix placement to initialise properly
@ -611,10 +673,29 @@ void Remember::setupWindow(FluxboxWindow &win) {
}
void Remember::setupClient(WinClient &winclient) {
Application *app = find(winclient);
if (app == 0)
return; // nothing to do
if (winclient.fbwindow() == 0 && app->is_grouped && app->group) {
app->group->attachClient(winclient);
}
}
void Remember::updateWindowClose(FluxboxWindow &win) {
// This doesn't work at present since fluxbox.cc is missing the windowclose stuff.
// I don't trust it (particularly winClient()) while this is the case
// scan all winclients and remove this fbw
Patterns::iterator it = m_pats.begin();
while (it != m_pats.end()) {
if (&win == it->second->group)
it->second->group = 0;
++it;
}
return;
WinClient &winclient = win.winClient();

View file

@ -21,7 +21,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Remember.hh,v 1.8 2003/06/18 13:34:56 fluxgen Exp $
// $Id: Remember.hh,v 1.9 2003/07/04 01:03:40 rathnor Exp $
/* Based on the original "Remember patch" by Xavier Brouckaert */
@ -43,7 +43,7 @@ class ClientPattern;
class Application {
public:
Application();
Application(bool grouped);
inline void forgetWorkspace() { workspace_remember = false; }
inline void forgetDimensions() { dimensions_remember = false; }
inline void forgetPosition() { position_remember = false; }
@ -107,6 +107,9 @@ public:
bool save_on_close_remember;
bool save_on_close;
bool is_grouped;
FluxboxWindow *group;
};
/**
@ -161,7 +164,8 @@ public:
// Functions relating to AtomHandler
// Functions we actually use
void setupWindow(FluxboxWindow &win);
void setupFrame(FluxboxWindow &win);
void setupClient(WinClient &winclient);
void updateWindowClose(FluxboxWindow &win);
// Functions we ignore (zero from AtomHandler)
@ -186,7 +190,8 @@ public:
private:
// returns number of lines read
int parseApp(std::ifstream &file, Application &app);
// optionally can give a line to read before the first (lookahead line)
int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0);
Patterns m_pats;
Clients m_clients;

View file

@ -22,7 +22,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Screen.cc,v 1.200 2003/07/03 13:57:58 fluxgen Exp $
// $Id: Screen.cc,v 1.201 2003/07/04 01:03:40 rathnor Exp $
#include "Screen.hh"
@ -1035,40 +1035,53 @@ FluxboxWindow *BScreen::createWindow(Window client) {
return 0;
}
bool new_win = false;
// check if it should be grouped with something else
FluxboxWindow *win;
if ((win = findGroupLeft(*winclient)) != 0) {
win->attachClient(*winclient);
Fluxbox::instance()->attachSignals(*winclient);
} else {
win = new FluxboxWindow(*winclient, *this,
winFrameTheme(), *menuTheme(),
*layerManager().getLayer(Fluxbox::instance()->getNormalLayer()));
Fluxbox::instance()->attachSignals(*winclient);
if (winclient->fbwindow()) // may have been set in an atomhandler
win = winclient->fbwindow();
else {
win = new FluxboxWindow(*winclient, *this,
winFrameTheme(), *menuTheme(),
*layerManager().getLayer(Fluxbox::instance()->getNormalLayer()));
new_win = true;
if (!win->isManaged()) {
delete win;
return 0;
}
}
}
if (!win->isManaged()) {
delete win;
return 0;
} else {
// always put on end of focused list, if it gets focused it'll get pushed up
// there is only the one win client at this stage
if (doFocusNew())
focused_list.push_front(&win->winClient());
else
focused_list.push_back(&win->winClient());
//TODO: is next line needed?
Fluxbox::instance()->saveWindowSearch(client, win);
// always put on end of focused list, if it gets focused it'll get pushed up
// there is only the one win client at this stage
if (doFocusNew())
focused_list.push_front(&win->winClient());
else
focused_list.push_back(&win->winClient());
if (new_win) {
setupWindowActions(*win);
Fluxbox::instance()->attachSignals(*win);
}
Fluxbox::instance()->saveWindowSearch(client, win);
// we also need to check if another window expects this window to the left
// and if so, then join it.
FluxboxWindow *otherwin = 0;
// TODO: does this do the right stuff focus-wise?
if ((otherwin = findGroupRight(*winclient)) && otherwin != win)
if ((otherwin = findGroupRight(*winclient)) && otherwin != win) {
win->attachClient(otherwin->winClient());
}
if (!win->isIconic() && (win->workspaceNumber() == currentWorkspaceID() || win->isStuck())) {
win->show();
@ -1096,6 +1109,7 @@ FluxboxWindow *BScreen::createWindow(WinClient &client) {
Fluxbox::instance()->saveWindowSearch(client.window(), win);
setupWindowActions(*win);
Fluxbox::instance()->attachSignals(*win);
// winclient actions should have been setup when the WinClient was created
if (win->workspaceNumber() == currentWorkspaceID() || win->isStuck()) {
win->show();
}

View file

@ -20,7 +20,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: ToolbarHandler.cc,v 1.19 2003/07/01 12:40:56 fluxgen Exp $
// $Id: ToolbarHandler.cc,v 1.20 2003/07/04 01:03:40 rathnor Exp $
/**
* The ToolbarHandler class acts as a rough interface to the toolbar.
@ -267,7 +267,7 @@ void ToolbarHandler::initForScreen(BScreen &screen) {
}
void ToolbarHandler::setupWindow(FluxboxWindow &win) {
void ToolbarHandler::setupFrame(FluxboxWindow &win) {
if (&win.screen() != &m_screen)
return;

View file

@ -20,7 +20,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: ToolbarHandler.hh,v 1.4 2003/06/24 16:27:18 fluxgen Exp $
// $Id: ToolbarHandler.hh,v 1.5 2003/07/04 01:03:40 rathnor Exp $
#ifndef TOOLBARHANDLER_HH
#define TOOLBARHANDLER_HH
@ -56,7 +56,9 @@ public:
void initForScreen(BScreen &screen);
void setupWindow(FluxboxWindow &win);
void setupFrame(FluxboxWindow &win);
// TODO: add setupClient and configure option to show groups or indiv. clients
void setupClient(WinClient &winclient) {}
void updateState(FluxboxWindow &win);
void updateWindowClose(FluxboxWindow &win);

View file

@ -22,7 +22,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: Window.cc,v 1.201 2003/07/02 05:27:40 fluxgen Exp $
// $Id: Window.cc,v 1.202 2003/07/04 01:03:40 rathnor Exp $
#include "Window.hh"
@ -557,11 +557,8 @@ void FluxboxWindow::attachClient(WinClient &client) {
// get the current window on the end of our client list
Window leftwin = None;
ClientList::iterator client_it = clientList().end();
ClientList::iterator client_it_end = clientList().end();
--client_it;
if (client_it != client_it_end)
leftwin = (*client_it)->window();
if (!clientList().empty())
leftwin = clientList().back()->window();
client.setGroupLeftWindow(leftwin);
@ -570,8 +567,8 @@ void FluxboxWindow::attachClient(WinClient &client) {
Fluxbox *fb = Fluxbox::instance();
// make sure we set new window search for each client
client_it = old_win->clientList().begin();
client_it_end = old_win->clientList().end();
ClientList::iterator client_it = old_win->clientList().begin();
ClientList::iterator client_it_end = old_win->clientList().end();
for (; client_it != client_it_end; ++client_it) {
// setup eventhandlers for client
fb->saveWindowSearch((*client_it)->window(), this);
@ -638,6 +635,7 @@ void FluxboxWindow::attachClient(WinClient &client) {
Fluxbox::instance()->saveWindowSearch(client.window(), this);
client.saveBlackboxAttribs(m_blackbox_attrib);
m_clientlist.push_back(&client);
}
// make sure that the state etc etc is updated for the new client
@ -659,6 +657,46 @@ bool FluxboxWindow::detachClient(WinClient &client) {
if (client.m_win != this || numClients() <= 1)
return false;
// I'm not sure how to do this bit better
// we need to find the window we've got, and update the
// window to its right to have a left window set to the
// window which is to the left of the current.
// Think in terms of:
// window1 <- my_window <- window2
// we need to take out my_window, so update window2 leftwin to be window1
Window leftwin = None;
ClientList::iterator client_it_end = clientList().end();
ClientList::iterator client_it = clientList().begin();
ClientList::iterator client_it_before = client_it_end;
ClientList::iterator client_it_after = clientList().begin();
if (!clientList().empty()) {
++client_it_after;
if (clientList().front() == &client) {
leftwin = None;
} else {
++client_it;
client_it_before = clientList().begin();
++client_it_after;
while (client_it != client_it_end) {
if (*client_it == &client) {
break;
}
++client_it_before;
++client_it;
++client_it_after;
}
}
}
// update the leftwin of the window to the right
if (client_it_before != client_it_end)
leftwin = (*client_it_before)->window();
if (client_it_after != client_it_end)
(*client_it_after)->setGroupLeftWindow(leftwin);
removeClient(client);
client.m_win = screen().createWindow(client);
@ -2998,6 +3036,7 @@ void FluxboxWindow::restore(bool remap) {
while (!clientList().empty()) {
restore(clientList().back(), remap);
// deleting winClient removes it from the clientList
}
}

View file

@ -22,7 +22,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: fluxbox.cc,v 1.167 2003/07/01 20:29:44 fluxgen Exp $
// $Id: fluxbox.cc,v 1.168 2003/07/04 01:03:41 rathnor Exp $
#include "fluxbox.hh"
@ -1326,10 +1326,17 @@ void Fluxbox::attachSignals(FluxboxWindow &win) {
win.stateSig().attach(this);
win.workspaceSig().attach(this);
win.layerSig().attach(this);
win.winClient().dieSig().attach(this);
win.dieSig().attach(this);
for (size_t i=0; i<m_atomhandler.size(); ++i) {
m_atomhandler[i]->setupWindow(win);
m_atomhandler[i]->setupFrame(win);
}
}
void Fluxbox::attachSignals(WinClient &winclient) {
winclient.dieSig().attach(this);
for (size_t i=0; i<m_atomhandler.size(); ++i) {
m_atomhandler[i]->setupClient(winclient);
}
}

View file

@ -22,7 +22,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id: fluxbox.hh,v 1.63 2003/06/30 15:04:06 fluxgen Exp $
// $Id: fluxbox.hh,v 1.64 2003/07/04 01:03:41 rathnor Exp $
#ifndef FLUXBOX_HH
#define FLUXBOX_HH
@ -61,6 +61,7 @@
class AtomHandler;
class FluxboxWindow;
class WinClient;
class Keys;
class BScreen;
class FbAtoms;
@ -175,6 +176,7 @@ public:
void update(FbTk::Subject *changed);
void attachSignals(FluxboxWindow &win);
void attachSignals(WinClient &winclient);
virtual void timeout();