some fixes for grouping with the apps file

This commit is contained in:
markt 2007-02-05 17:20:01 +00:00
parent cf6e471fbf
commit e4488da120
4 changed files with 73 additions and 37 deletions

View file

@ -1,5 +1,14 @@
(Format: Year/Month/Day) (Format: Year/Month/Day)
Changes for 1.0rc3: Changes for 1.0rc3:
*07/02/05:
* Made some changes to the way autogrouping in the apps file works (Mark)
- Introduced new syntax [group] (workspace) to group new windows only with
windows on the current workspace
- Fixed an unreported bug with grouping windows on multiple screens
- Groups are now associated with clients rather than windows, so they
will be more robust when attaching or detaching tabs and when restarting
fluxbox
Remember.cc/hh
*07/02/04: *07/02/04:
* Layer wasn't set properly on remembered windows, and the layer menu * Layer wasn't set properly on remembered windows, and the layer menu
wasn't getting updated properly, bugs #1535304, #1572683, #1646740 wasn't getting updated properly, bugs #1535304, #1572683, #1646740

View file

@ -1510,9 +1510,10 @@ If no `property' is specified, the name property is assumed. You can find out
the value for these fields for a particular window by running xprop(1). the value for these fields for a particular window by running xprop(1).
You can also place [group] tag around several [app] tags, with an [end] tag to You can also place [group] tag around several [app] tags, with an [end] tag to
indicate the end of the group. You can also specify dimensions, positions, indicate the end of the group. If you place (workspace) after the [group] tag, a
etc. for the group as for normal app entries. Here is a short example new window will only get grouped with other windows on the current workspace.
of an `apps' file: You can also specify dimensions, positions, etc. for the group as for normal app
entries. Here is a short example of an `apps' file:
......................................................... .........................................................
[startup] {xterm} [startup] {xterm}

View file

@ -230,9 +230,8 @@ bool handleStartupItem(const string &line, int offset) {
}; // end anonymous namespace }; // end anonymous namespace
Application::Application(bool grouped) Application::Application(int grouped)
: is_grouped(grouped), : is_grouped(grouped)
group(0)
{ {
decostate_remember = decostate_remember =
dimensions_remember = dimensions_remember =
@ -312,7 +311,7 @@ Application* Remember::find(WinClient &winclient) {
Application * Remember::add(WinClient &winclient) { Application * Remember::add(WinClient &winclient) {
ClientPattern *p = new ClientPattern(); ClientPattern *p = new ClientPattern();
Application *app = new Application(false); Application *app = new Application(0);
// by default, we match against the WMClass of a window. // by default, we match against the WMClass of a window.
string win_name = p->getProperty(ClientPattern::NAME, winclient); string win_name = p->getProperty(ClientPattern::NAME, winclient);
@ -534,7 +533,7 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
effectively moved into the new effectively moved into the new
*/ */
Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group) { Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, int is_group) {
Patterns::iterator it = patlist->begin(); Patterns::iterator it = patlist->begin();
Patterns::iterator it_end = patlist->end(); Patterns::iterator it_end = patlist->end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
@ -590,7 +589,7 @@ void Remember::reconfigure() {
if (!apps_file.eof()) { if (!apps_file.eof()) {
string line; string line;
int row = 0; int row = 0;
bool in_group = false; int in_group = 0;
list<ClientPattern *> grouped_pats; list<ClientPattern *> grouped_pats;
while (getline(apps_file, line) && ! apps_file.eof()) { while (getline(apps_file, line) && ! apps_file.eof()) {
row++; row++;
@ -606,11 +605,11 @@ void Remember::reconfigure() {
if (pos > 0 && strcasecmp(key.c_str(), "app") == 0) { if (pos > 0 && strcasecmp(key.c_str(), "app") == 0) {
ClientPattern *pat = new ClientPattern(line.c_str() + pos); ClientPattern *pat = new ClientPattern(line.c_str() + pos);
if (!in_group) { if (in_group == 0) {
if ((err = pat->error()) == 0) { if ((err = pat->error()) == 0) {
Application *app = findMatchingPatterns(pat, old_pats, false); Application *app = findMatchingPatterns(pat, old_pats, 0);
if (!app) if (!app)
app = new Application(false); app = new Application(0);
m_pats->push_back(make_pair(pat, app)); m_pats->push_back(make_pair(pat, app));
row += parseApp(apps_file, *app); row += parseApp(apps_file, *app);
@ -629,7 +628,12 @@ void Remember::reconfigure() {
// save the item even if it was bad (aren't we nice) // save the item even if it was bad (aren't we nice)
m_startups.push_back(line.substr(pos)); m_startups.push_back(line.substr(pos));
} else if (pos > 0 && strcasecmp(key.c_str(), "group") == 0) { } else if (pos > 0 && strcasecmp(key.c_str(), "group") == 0) {
in_group = true; in_group = Application::IS_GROUPED;
pos = FbTk::StringUtil::getStringBetween(key,
line.c_str() + pos,
'(', ')');
if (pos > 0 && strcasecmp(key.c_str(), "workspace") == 0)
in_group |= Application::MATCH_WORKSPACE;
} else if (in_group) { } else if (in_group) {
// otherwise assume that it is the start of the attributes // otherwise assume that it is the start of the attributes
Application *app = 0; Application *app = 0;
@ -637,12 +641,12 @@ void Remember::reconfigure() {
list<ClientPattern *>::iterator it = grouped_pats.begin(); list<ClientPattern *>::iterator it = grouped_pats.begin();
list<ClientPattern *>::iterator it_end = grouped_pats.end(); list<ClientPattern *>::iterator it_end = grouped_pats.end();
while (!app && it != it_end) { while (!app && it != it_end) {
app = findMatchingPatterns(*it, old_pats, true); app = findMatchingPatterns(*it, old_pats, in_group);
++it; ++it;
} }
if (!app) if (!app)
app = new Application(true); app = new Application(in_group);
while (!grouped_pats.empty()) { while (!grouped_pats.empty()) {
// associate all the patterns with this app // associate all the patterns with this app
@ -656,7 +660,7 @@ void Remember::reconfigure() {
if (!(pos>0 && strcasecmp(key.c_str(), "end") == 0)) { if (!(pos>0 && strcasecmp(key.c_str(), "end") == 0)) {
row += parseApp(apps_file, *app, &line); row += parseApp(apps_file, *app, &line);
} }
in_group = false; in_group = 0;
} else } else
cerr<<"Error in apps file on line "<<row<<"."<<endl; cerr<<"Error in apps file on line "<<row<<"."<<endl;
@ -733,7 +737,11 @@ void Remember::save() {
continue; continue;
grouped_apps.insert(&a); grouped_apps.insert(&a);
// otherwise output this whole group // otherwise output this whole group
apps_file << "[group]" << endl; apps_file << "[group]";
if (a.is_grouped & Application::MATCH_WORKSPACE)
apps_file << " (workspace)";
apps_file << endl;
Patterns::iterator git = m_pats->begin(); Patterns::iterator git = m_pats->begin();
Patterns::iterator git_end = m_pats->end(); Patterns::iterator git_end = m_pats->end();
for (; git != git_end; git++) { for (; git != git_end; git++) {
@ -1035,9 +1043,6 @@ void Remember::setupFrame(FluxboxWindow &win) {
// first, set the options that aren't preserved as window properties on // first, set the options that aren't preserved as window properties on
// restart, then return if fluxbox is restarting -- we want restart to // restart, then return if fluxbox is restarting -- we want restart to
// disturb the current window state as little as possible // disturb the current window state as little as possible
Window leftwin = winclient.getGroupLeftWindow();
if (app->is_grouped && app->group == 0 && leftwin == None)
app->group = &win;
if (app->focushiddenstate_remember) if (app->focushiddenstate_remember)
win.setFocusHidden(app->focushiddenstate); win.setFocusHidden(app->focushiddenstate);
@ -1133,14 +1138,37 @@ void Remember::setupClient(WinClient &winclient) {
if (app == 0) if (app == 0)
return; // nothing to do return; // nothing to do
if (winclient.fbwindow() == 0 && app->is_grouped && app->group) { FluxboxWindow *group;
app->group->attachClient(winclient); if (winclient.fbwindow() == 0 && app->is_grouped &&
(group = findGroup(app, winclient.screen()))) {
group->attachClient(winclient);
if (app->jumpworkspace_remember && app->jumpworkspace) if (app->jumpworkspace_remember && app->jumpworkspace)
// jump to window, not saved workspace // jump to window, not saved workspace
winclient.screen().changeWorkspaceID(app->group->workspaceNumber()); winclient.screen().changeWorkspaceID(group->workspaceNumber());
} }
} }
FluxboxWindow *Remember::findGroup(Application *app, BScreen &screen) {
if (!app || !app->is_grouped)
return 0;
// find the first client associated with the app and return its fbwindow
Clients::iterator it = m_clients.begin();
Clients::iterator it_end = m_clients.end();
for (; it != it_end; ++it) {
if (it->second == app && it->first->fbwindow() &&
&screen == &it->first->screen() &&
(!(app->is_grouped & Application::MATCH_WORKSPACE) ||
it->first->fbwindow()->workspaceNumber() ==
screen.currentWorkspaceID()))
return it->first->fbwindow();
}
// there weren't any open, but that's ok
return 0;
}
void Remember::updateClientClose(WinClient &winclient) { void Remember::updateClientClose(WinClient &winclient) {
reconfigure(); // reload if it's changed reconfigure(); // reload if it's changed
Application *app = find(winclient); Application *app = find(winclient);
@ -1172,12 +1200,3 @@ void Remember::initForScreen(BScreen &screen) {
createRememberMenu(screen)); createRememberMenu(screen));
} }
void Remember::updateFrameClose(FluxboxWindow &win) {
// scan all applications and remove this fbw if it is a recorded group
Patterns::iterator it = m_pats->begin();
for (; it != m_pats->end(); ++it) {
if (&win == it->second->group)
it->second->group = 0;
}
}

View file

@ -44,7 +44,7 @@ class ClientPattern;
class Application { class Application {
public: public:
Application(bool grouped); Application(int grouped);
inline void forgetWorkspace() { workspace_remember = false; } inline void forgetWorkspace() { workspace_remember = false; }
inline void forgetHead() { head_remember = false; } inline void forgetHead() { head_remember = false; }
inline void forgetDimensions() { dimensions_remember = false; } inline void forgetDimensions() { dimensions_remember = false; }
@ -137,8 +137,14 @@ public:
bool save_on_close_remember; bool save_on_close_remember;
bool save_on_close; bool save_on_close;
bool is_grouped; enum {
FluxboxWindow *group; IS_GROUPED = 0x01,
MATCH_WORKSPACE = 0x02
// MATCH_HEAD, STUCK, ICONIFIED, etc.?
// this will probably evolve into a ClientPattern as soon as they
// match things like currentworkspace
};
int is_grouped;
}; };
@ -201,6 +207,7 @@ public:
Application* find(WinClient &winclient); Application* find(WinClient &winclient);
Application* add(WinClient &winclient); Application* add(WinClient &winclient);
FluxboxWindow* findGroup(Application *, BScreen &screen);
void reconfigure(); // was load void reconfigure(); // was load
void save(); void save();
@ -214,7 +221,6 @@ public:
// Functions we actually use // Functions we actually use
void setupFrame(FluxboxWindow &win); void setupFrame(FluxboxWindow &win);
void setupClient(WinClient &winclient); void setupClient(WinClient &winclient);
void updateFrameClose(FluxboxWindow &win);
void updateClientClose(WinClient &winclient); void updateClientClose(WinClient &winclient);
void initForScreen(BScreen &screen); void initForScreen(BScreen &screen);
@ -233,6 +239,7 @@ public:
void updateState(FluxboxWindow &win) {} void updateState(FluxboxWindow &win) {}
void updateHints(FluxboxWindow &win) {} void updateHints(FluxboxWindow &win) {}
void updateLayer(FluxboxWindow &win) {} void updateLayer(FluxboxWindow &win) {}
void updateFrameClose(FluxboxWindow &win) {}
bool checkClientMessage(const XClientMessageEvent &ce, bool checkClientMessage(const XClientMessageEvent &ce,
BScreen * screen, WinClient * const winclient) { return false; } BScreen * screen, WinClient * const winclient) { return false; }
@ -247,7 +254,7 @@ private:
// optionally can give a line to read before the first (lookahead line) // optionally can give a line to read before the first (lookahead line)
int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0); int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0);
Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group); Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, int is_group);
std::auto_ptr<Patterns> m_pats; std::auto_ptr<Patterns> m_pats;
Clients m_clients; Clients m_clients;