some fixes for grouping with the apps file
This commit is contained in:
parent
cf6e471fbf
commit
e4488da120
4 changed files with 73 additions and 37 deletions
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue