fluxbox/src/Remember.cc

941 lines
33 KiB
C++
Raw Normal View History

2003-04-26 07:57:00 +00:00
// Remember.cc for Fluxbox Window Manager
2005-01-24 18:34:57 +00:00
// Copyright (c) 2003 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
2005-01-24 17:14:24 +00:00
// and Simon Bowden (rathnor at users.sourceforge.net)
2005-01-24 18:34:57 +00:00
// Copyright (c) 2002 Xavier Brouckaert
//
2003-04-26 07:57:00 +00:00
// 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.
2004-11-19 11:37:27 +00:00
// $Id$
2003-04-26 07:57:00 +00:00
#include "Remember.hh"
#include "ClientPattern.hh"
2003-04-26 12:46:18 +00:00
#include "Screen.hh"
#include "Window.hh"
2003-04-26 07:57:00 +00:00
#include "WinClient.hh"
#include "FbMenu.hh"
2003-07-10 13:23:09 +00:00
#include "FbCommands.hh"
2003-12-19 00:48:41 +00:00
#include "fluxbox.hh"
2004-06-07 11:46:05 +00:00
#include "FbTk/I18n.hh"
2003-12-19 00:48:41 +00:00
#include "FbTk/StringUtil.hh"
#include "FbTk/MenuItem.hh"
#include "FbTk/App.hh"
2003-04-26 07:57:00 +00:00
2003-04-26 12:46:18 +00:00
#include <X11/Xlib.h>
2003-04-26 07:57:00 +00:00
//use GNU extensions
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
2003-04-26 12:46:18 +00:00
2003-04-26 07:57:00 +00:00
#include <iostream>
#include <fstream>
2003-04-26 11:24:55 +00:00
#include <string>
#include <memory>
#include <set>
2003-04-26 07:57:00 +00:00
2003-11-17 00:20:54 +00:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
#ifdef HAVE_SSTREAM
#include <sstream>
#define FB_istringstream istringstream
#elif HAVE_STRSTREAM
2003-11-17 00:20:54 +00:00
#include <strstream>
#define FB_istringstream istrstream
#else
#error "You dont have sstream or strstream headers!"
#endif // HAVE_STRSTREAM
2003-04-26 12:46:18 +00:00
using namespace std;
2003-04-26 07:57:00 +00:00
namespace {
class RememberMenuItem : public FbTk::MenuItem {
public:
RememberMenuItem(const char *label, Remember &remember,
FluxboxWindow &fbwin,
Remember::Attribute attrib) :
FbTk::MenuItem(label), m_remember(remember),
m_win(fbwin), m_attrib(attrib) {
setToggleItem(true);
}
2003-04-26 07:57:00 +00:00
bool isSelected() const {
if (m_win.numClients()) // ensure it HAS clients
return m_remember.isRemembered(m_win.winClient(), m_attrib);
else
return false;
2003-04-26 07:57:00 +00:00
}
bool isEnabled() const {
if (m_attrib != Remember::REM_JUMPWORKSPACE)
2003-04-26 07:57:00 +00:00
return true;
else if (m_win.numClients())
2003-04-26 07:57:00 +00:00
return (m_remember.isRemembered(m_win.winClient(), Remember::REM_WORKSPACE));
else
return false;
2003-04-26 07:57:00 +00:00
}
void click(int button, int time) {
if (isSelected()) {
m_remember.forgetAttrib(m_win.winClient(), m_attrib);
} else {
m_remember.rememberAttrib(m_win.winClient(), m_attrib);
}
m_remember.save();
FbTk::MenuItem::click(button, time);
}
private:
// my remember manager
Remember &m_remember;
FluxboxWindow &m_win;
Remember::Attribute m_attrib;
};
FbTk::Menu *createRememberMenu(Remember &remember, FluxboxWindow &win, bool enabled) {
2003-04-26 07:57:00 +00:00
// each fluxboxwindow has its own windowmenu
// so we also create a remember menu just for it...
2003-12-10 23:08:06 +00:00
FbTk::Menu *menu = win.screen().createMenu("");
// if enabled, then we want this to be a unavailable menu
if (!enabled) {
FbTk::MenuItem *item = new FbTk::MenuItem("unavailable");
item->setEnabled(false);
menu->insert(item);
menu->updateMenu();
return menu;
}
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Workspace, "Workspace", "Remember Workspace"),
2004-06-07 11:46:05 +00:00
remember, win, Remember::REM_WORKSPACE));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, JumpToWorkspace, "Jump to workspace", "Change active workspace to remembered one on open"),
remember, win, Remember::REM_JUMPWORKSPACE));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Head, "Head", "Remember Head"),
remember, win, Remember::REM_HEAD));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Dimensions, "Dimensions", "Remember Dimensions - with width and height"),
2004-06-07 11:46:05 +00:00
remember, win, Remember::REM_DIMENSIONS));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Position, "Position", "Remember position - window co-ordinates"),
2004-06-07 11:46:05 +00:00
remember, win, Remember::REM_POSITION));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Sticky, "Sticky", "Remember Sticky"),
2004-06-07 11:46:05 +00:00
remember, win, Remember::REM_STUCKSTATE));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Decorations, "Decorations", "Remember window decorations"),
remember, win, Remember::REM_DECOSTATE));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Shaded, "Shaded", "Remember shaded"),
remember, win, Remember::REM_SHADEDSTATE));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Layer, "Layer", "Remember Layer"),
remember, win, Remember::REM_LAYER));
menu->insert(new RememberMenuItem(_FBTEXT(Remember, SaveOnClose, "Save on close", "Save remembered attributes on close"),
remember, win, Remember::REM_SAVEONCLOSE));
2003-04-26 07:57:00 +00:00
menu->updateMenu();
2003-04-26 07:57:00 +00:00
return menu;
};
2003-07-10 13:23:09 +00:00
// offset is the offset in the string that we start looking from
// return true if all ok, false on error
2003-08-18 09:32:15 +00:00
bool handleStartupItem(const string &line, int offset) {
2003-07-10 13:23:09 +00:00
int next = 0;
string str;
int screen = 0;
// accept some options, for now only "screen=NN"
// these option are given in parentheses before the command
next = FbTk::StringUtil::getStringBetween(str,
line.c_str() + offset,
2003-07-10 13:23:09 +00:00
'(', ')');
if (next > 0) {
// there are some options
string option;
int pos = str.find('=');
bool error = false;
if (pos > 0) {
option = str.substr(0, pos);
if (option == "screen") {
2003-11-17 00:20:54 +00:00
FB_istringstream iss(str.c_str() + pos + 1);
2003-07-10 13:23:09 +00:00
iss >> screen;
} else {
error = true;
}
} else {
error = true;
}
if (error) {
cerr<<"Error parsing startup options."<<endl;
return false;
}
} else {
next = 0;
}
next = FbTk::StringUtil::getStringBetween(str,
line.c_str() + offset + next,
2003-07-10 13:23:09 +00:00
'{', '}');
if (next <= 0) {
cerr<<"Error parsing [startup] at column "<<offset<<" - expecting {command}."<<endl;
return false;
} else {
FbCommands::ExecuteCmd *tmp_exec_cmd = new FbCommands::ExecuteCmd(str, screen);
#ifdef DEBUG
cerr<<"Executing startup command '"<<str<<"' on screen "<<screen<<endl;
#endif // DEBUG
tmp_exec_cmd->execute();
delete tmp_exec_cmd;
return true;
}
};
}; // end anonymous namespace
2003-04-26 12:46:18 +00:00
2003-07-10 13:23:09 +00:00
Application::Application(bool grouped)
: is_grouped(grouped),
group(0)
{
decostate_remember =
2004-06-07 21:16:13 +00:00
dimensions_remember =
focushiddenstate_remember =
2004-06-07 21:16:13 +00:00
iconhiddenstate_remember =
jumpworkspace_remember =
layer_remember =
2004-06-07 21:16:13 +00:00
position_remember =
shadedstate_remember =
stuckstate_remember =
2004-06-07 21:16:13 +00:00
tabstate_remember =
workspace_remember =
head_remember =
2004-06-07 21:16:13 +00:00
save_on_close_remember = false;
2003-04-26 12:46:18 +00:00
}
/********************************************************
* Remember *
************/
2003-04-26 12:46:18 +00:00
Remember::Remember() {
enableUpdate();
2003-04-26 12:46:18 +00:00
load();
}
Remember::~Remember() {
// free our resources
// 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
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;
}
2003-04-26 12:46:18 +00:00
}
2003-04-26 07:57:00 +00:00
Application* Remember::find(WinClient &winclient) {
// if it is already associated with a application, return that one
// otherwise, check it against every pattern that we've got
Clients::iterator wc_it = m_clients.find(&winclient);
if (wc_it != m_clients.end())
return wc_it->second;
else {
Patterns::iterator it = m_pats.begin();
for (; it != m_pats.end(); it++)
if (it->first->match(winclient)) {
it->first->addMatch();
m_clients[&winclient] = it->second;
return it->second;
}
}
// oh well, no matches
return 0;
2003-04-26 07:57:00 +00:00
}
Application * Remember::add(WinClient &winclient) {
ClientPattern *p = new ClientPattern();
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;
p->addMatch();
m_pats.push_back(make_pair(p, app));
return app;
2003-04-26 07:57:00 +00:00
}
int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
2003-04-26 12:01:55 +00:00
string line;
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2003-04-26 07:57:00 +00:00
int row = 0;
while (! file.eof()) {
if (first_line || getline(file, line)) {
if (first_line) {
line = *first_line;
first_line = 0;
}
2003-04-26 07:57:00 +00:00
row++;
FbTk::StringUtil::removeFirstWhitespace(line);
FbTk::StringUtil::removeTrailingWhitespace(line);
if (line.size() == 0 || line[0] == '#')
continue; //the line is commented or blank
2003-07-04 14:06:20 +00:00
int parse_pos = 0, err = 0;
string str_key, str_option, str_label;
err = FbTk::StringUtil::getStringBetween(str_key,
line.c_str(),
2003-07-04 14:06:20 +00:00
'[', ']');
if (err > 0) {
int tmp;
tmp= FbTk::StringUtil::getStringBetween(str_option,
line.c_str() + err,
'(', ')');
if (tmp>0)
err += tmp;
}
2003-07-04 14:06:20 +00:00
if (err > 0 ) {
parse_pos += err;
err = FbTk::StringUtil::getStringBetween(str_label,
line.c_str() + parse_pos,
2003-07-04 14:06:20 +00:00
'{', '}');
if (err>0) {
2003-04-26 07:57:00 +00:00
parse_pos += err;
2003-07-04 14:06:20 +00:00
}
} else
continue; //read next line
if (!str_key.size())
continue; //read next line
if (str_key == "Workspace") {
unsigned int w;
2003-11-17 00:20:54 +00:00
FB_istringstream iss(str_label.c_str());
2003-07-04 14:06:20 +00:00
iss >> w;
app.rememberWorkspace(w);
} else if (str_key == "Head") {
int h = atoi(str_label.c_str());
app.rememberHead(h);
2003-07-04 14:06:20 +00:00
} else if (str_key == "Layer") {
unsigned int l;
if (str_label == "DESKTOP") {
l = Fluxbox::instance()->getDesktopLayer();
} else if (str_label == "BOTTOM") {
l = Fluxbox::instance()->getBottomLayer();
} else if (str_label == "NORMAL") {
l = Fluxbox::instance()->getNormalLayer();
} else if (str_label == "TOP") {
l = Fluxbox::instance()->getTopLayer();
} else if (str_label == "DOCK") {
l = Fluxbox::instance()->getDockLayer();
} else if (str_label == "ABOVEDOCK") {
l = Fluxbox::instance()->getAboveDockLayer();
} else if (str_label == "MENU") {
l = Fluxbox::instance()->getMenuLayer();
} else {
FB_istringstream iss(str_label.c_str());
iss >> l;
}
2003-07-04 14:06:20 +00:00
app.rememberLayer(l);
} else if (str_key == "Dimensions") {
unsigned int h,w;
2003-11-17 00:20:54 +00:00
FB_istringstream iss(str_label.c_str());
2003-07-04 14:06:20 +00:00
iss >> w >> h;
app.rememberDimensions(w,h);
} else if (str_key == "Position") {
FB_istringstream iss;
unsigned int r= 0;
unsigned int x= 0;
unsigned int y= 0;
// more info about the parameter
// in ::rememberPosition
if ( str_option.length() )
{
if ( str_option == "UPPERLEFT" ) r= POS_UPPERLEFT;
else if ( str_option == "UPPERRIGHT" ) r= POS_UPPERRIGHT;
else if ( str_option == "LOWERLEFT" ) r= POS_LOWERLEFT;
else if ( str_option == "LOWERRIGHT" ) r= POS_LOWERRIGHT;
else if ( str_option == "CENTER" ) r= POS_CENTER;
else if ( str_option == "WINCENTER" ) r= POS_WINCENTER;
else {
iss.str(str_option);
iss >> r;
}
}
iss.str(str_label.c_str());
2003-07-04 14:06:20 +00:00
iss >> x >> y;
app.rememberPosition(x, y, r);
2003-07-04 14:06:20 +00:00
} else if (str_key == "Shaded") {
app.rememberShadedstate((str_label=="yes"));
} else if (str_key == "Tab") {
app.rememberTabstate((str_label=="yes"));
} else if (str_key == "FocusHidden") {
app.rememberFocusHiddenstate((str_label=="yes"));
} else if (str_key == "IconHidden") {
app.rememberIconHiddenstate((str_label=="yes"));
} else if (str_key == "Hidden") {
app.rememberIconHiddenstate((str_label=="yes"));
app.rememberFocusHiddenstate((str_label=="yes"));
2003-07-04 14:06:20 +00:00
} else if (str_key == "Deco") {
if (str_label == "NONE") {
app.rememberDecostate((unsigned int) 0);
} else if (str_label == "NORMAL") {
app.rememberDecostate((unsigned int) 0xfffffff);
} else if (str_label == "TINY") {
app.rememberDecostate((unsigned int)
FluxboxWindow::DECORM_TITLEBAR
2003-07-04 14:06:20 +00:00
| FluxboxWindow::DECORM_ICONIFY
| FluxboxWindow::DECORM_MENU
);
2003-07-04 14:06:20 +00:00
} else if (str_label == "TOOL") {
app.rememberDecostate((unsigned int)
FluxboxWindow::DECORM_TITLEBAR
| FluxboxWindow::DECORM_MENU
);
2003-07-04 14:06:20 +00:00
} else if (str_label == "BORDER") {
app.rememberDecostate((unsigned int)
FluxboxWindow::DECORM_BORDER
| FluxboxWindow::DECORM_MENU
);
2003-04-26 07:57:00 +00:00
} else {
2003-07-04 14:06:20 +00:00
unsigned int mask;
const char * str = str_label.c_str();
// it'll have at least one char and \0, so this is safe
2003-11-17 00:20:54 +00:00
FB_istringstream iss(str);
2003-07-04 14:06:20 +00:00
// check for hex
if (str[0] == '0' && str[1] == 'x') {
iss.seekg(2);
iss >> hex;
}
iss >> mask ;
app.rememberDecostate(mask);
2003-04-26 07:57:00 +00:00
}
2003-07-04 14:06:20 +00:00
} else if (str_key == "Sticky") {
app.rememberStuckstate((str_label=="yes"));
} else if (str_key == "Jump") {
app.rememberJumpworkspace((str_label=="yes"));
} else if (str_key == "Close") {
app.rememberSaveOnClose((str_label=="yes"));
} else if (str_key == "end") {
return row;
} else {
2004-06-07 11:46:05 +00:00
cerr << _FBTEXT(Remember, Unknown, "Unknown apps key", "apps entry type not known")<<" = " << str_key << endl;
2003-04-26 07:57:00 +00:00
}
}
}
return row;
}
void Remember::load() {
2003-04-26 12:46:18 +00:00
string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename());
2003-05-27 11:55:23 +00:00
2003-04-26 07:57:00 +00:00
#ifdef DEBUG
2003-04-26 12:46:18 +00:00
cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl;
2003-04-26 07:57:00 +00:00
#endif // DEBUG
2003-04-26 12:01:55 +00:00
ifstream apps_file(apps_string.c_str());
2003-04-26 12:46:18 +00:00
2003-04-26 07:57:00 +00:00
if (!apps_file.fail()) {
if (!apps_file.eof()) {
2003-04-26 12:01:55 +00:00
string line;
2003-04-26 07:57:00 +00:00
int row = 0;
bool in_group = false;
std::list<ClientPattern *> grouped_pats;
2003-04-26 07:57:00 +00:00
while (getline(apps_file, line) && ! apps_file.eof()) {
row++;
2004-09-04 04:54:38 +00:00
FbTk::StringUtil::removeFirstWhitespace(line);
FbTk::StringUtil::removeTrailingWhitespace(line);
if (line.size() == 0 || line[0] == '#')
2003-04-26 07:57:00 +00:00
continue;
2003-04-26 12:01:55 +00:00
string key;
int err=0;
int pos = FbTk::StringUtil::getStringBetween(key,
line.c_str(),
2003-04-26 18:58:30 +00:00
'[', ']');
2003-04-26 07:57:00 +00:00
if (pos > 0 && key == "app") {
ClientPattern *pat = new ClientPattern(line.c_str() + pos);
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 {
grouped_pats.push_back(pat);
}
2003-07-10 13:23:09 +00:00
} else if (pos > 0 && key == "startup") {
if (!handleStartupItem(line, pos)) {
cerr<<"Error reading apps file at line "<<row<<"."<<endl;
}
// save the item even if it was bad (aren't we nice)
m_startups.push_back(line.substr(pos));
} 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;
2003-04-26 07:57:00 +00:00
} else
cerr<<"Error in apps file on line "<<row<<"."<<endl;
2003-04-26 07:57:00 +00:00
}
} else {
#ifdef DEBUG
2003-04-26 12:46:18 +00:00
cerr<<__FILE__<<"("<<__FUNCTION__<< ") Empty apps file" << endl;
2003-04-26 07:57:00 +00:00
#endif
}
} else {
cerr << "apps file failure" << endl;
}
}
void Remember::save() {
#ifdef DEBUG
2003-04-26 12:46:18 +00:00
cerr<<__FILE__<<"("<<__FUNCTION__<<"): Saving apps file..."<<endl;
2003-04-26 07:57:00 +00:00
#endif // DEBUG
2003-05-27 11:55:23 +00:00
string apps_string;
Fluxbox::instance()->getDefaultDataFilename("apps", apps_string);
2003-04-26 12:01:55 +00:00
ofstream apps_file(apps_string.c_str());
2003-07-10 13:23:09 +00:00
// first of all we output all the startup commands
Startups::iterator sit = m_startups.begin();
Startups::iterator sit_end = m_startups.end();
for (; sit != sit_end; ++sit) {
apps_file<<"[startup] "<<(*sit)<<endl;
}
Patterns::iterator it = m_pats.begin();
Patterns::iterator it_end = m_pats.end();
std::set<Application *> grouped_apps; // no duplicates
2003-04-26 07:57:00 +00:00
for (; it != it_end; ++it) {
Application &a = *it->second;
if (a.is_grouped) {
// if already processed
if (grouped_apps.find(&a) != grouped_apps.end())
continue;
2003-07-10 13:23:09 +00:00
grouped_apps.insert(&a);
// 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++) {
2003-07-10 13:23:09 +00:00
if (git->second == &a) {
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;
2003-04-26 07:57:00 +00:00
}
if (a.head_remember) {
apps_file << " [Head]\t{" << a.head << "}" << endl;
}
if (a.dimensions_remember) {
apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl;
2003-04-26 07:57:00 +00:00
}
if (a.position_remember) {
apps_file << " [Position]\t{" << a.x << " " << a.y << "}" << endl;
2003-04-26 07:57:00 +00:00
}
if (a.shadedstate_remember) {
apps_file << " [Shaded]\t{" << ((a.shadedstate)?"yes":"no") << "}" << endl;
2003-04-26 07:57:00 +00:00
}
if (a.tabstate_remember) {
apps_file << " [Tab]\t\t{" << ((a.tabstate)?"yes":"no") << "}" << endl;
2003-04-26 07:57:00 +00:00
}
if (a.decostate_remember) {
switch (a.decostate) {
2003-04-26 07:57:00 +00:00
case (0) :
apps_file << " [Deco]\t{NONE}" << endl;
2003-04-26 07:57:00 +00:00
break;
case (0xffffffff):
case (FluxboxWindow::DECORM_LAST - 1):
apps_file << " [Deco]\t{NORMAL}" << endl;
break;
case (FluxboxWindow::DECORM_TITLEBAR
2003-04-26 07:57:00 +00:00
| FluxboxWindow::DECORM_ICONIFY
| FluxboxWindow::DECORM_MENU):
apps_file << " [Deco]\t{TOOL}" << endl;
break;
case (FluxboxWindow::DECORM_TITLEBAR
2003-04-26 07:57:00 +00:00
| FluxboxWindow::DECORM_MENU):
apps_file << " [Deco]\t{TINY}" << endl;
break;
case (FluxboxWindow::DECORM_BORDER
| FluxboxWindow::DECORM_MENU):
apps_file << " [Deco]\t{BORDER}" << endl;
break;
2003-04-26 07:57:00 +00:00
default:
apps_file << " [Deco]\t{0x"<<hex<<a.decostate<<dec<<"}"<<endl;
2003-04-26 07:57:00 +00:00
break;
}
}
if (a.focushiddenstate_remember || a.iconhiddenstate_remember) {
if (a.focushiddenstate_remember && a.iconhiddenstate_remember &&
a.focushiddenstate && a.iconhiddenstate)
apps_file << " [Hidden]\t{" << ((a.focushiddenstate)?"yes":"no") << "}" << endl;
else if (a.focushiddenstate_remember) {
apps_file << " [FocusHidden]\t{" << ((a.focushiddenstate)?"yes":"no") << "}" << endl;
} else if (a.iconhiddenstate_remember) {
apps_file << " [IconHidden]\t{" << ((a.iconhiddenstate)?"yes":"no") << "}" << endl;
}
}
if (a.stuckstate_remember) {
apps_file << " [Sticky]\t{" << ((a.stuckstate)?"yes":"no") << "}" << endl;
2003-04-26 07:57:00 +00:00
}
if (a.jumpworkspace_remember) {
apps_file << " [Jump]\t{" << ((a.jumpworkspace)?"yes":"no") << "}" << endl;
2003-04-26 07:57:00 +00:00
}
if (a.layer_remember) {
apps_file << " [Layer]\t{" << a.layer << "}" << endl;
2003-04-26 13:47:53 +00:00
}
if (a.save_on_close_remember) {
apps_file << " [Close]\t{" << ((a.save_on_close)?"yes":"no") << "}" << endl;
2003-04-26 07:57:00 +00:00
}
apps_file << "[end]" << endl;
}
}
bool Remember::isRemembered(WinClient &winclient, Attribute attrib) {
Application *app = find(winclient);
if (!app) return false;
switch (attrib) {
case REM_WORKSPACE:
return app->workspace_remember;
break;
case REM_HEAD:
return app->head_remember;
break;
2003-04-26 07:57:00 +00:00
case REM_DIMENSIONS:
return app->dimensions_remember;
break;
case REM_POSITION:
return app->position_remember;
break;
case REM_FOCUSHIDDENSTATE:
return app->focushiddenstate_remember;
break;
case REM_ICONHIDDENSTATE:
return app->iconhiddenstate_remember;
break;
2003-04-26 07:57:00 +00:00
case REM_STUCKSTATE:
return app->stuckstate_remember;
break;
case REM_DECOSTATE:
return app->decostate_remember;
break;
case REM_SHADEDSTATE:
return app->shadedstate_remember;
break;
2003-04-26 12:46:18 +00:00
// case REM_TABSTATE:
// return app->tabstate_remember;
// break;
2003-04-26 07:57:00 +00:00
case REM_JUMPWORKSPACE:
return app->jumpworkspace_remember;
break;
2003-04-26 13:47:53 +00:00
case REM_LAYER:
return app->layer_remember;
break;
2003-04-26 07:57:00 +00:00
case REM_SAVEONCLOSE:
return app->save_on_close_remember;
break;
case REM_LASTATTRIB:
default:
return false; // should never get here
}
}
void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) {
FluxboxWindow *win = winclient.fbwindow();
if (!win) return;
Application *app = find(winclient);
if (!app) {
app = add(winclient);
if (!app) return;
}
switch (attrib) {
case REM_WORKSPACE:
2003-05-15 11:17:29 +00:00
app->rememberWorkspace(win->workspaceNumber());
2003-04-26 07:57:00 +00:00
break;
case REM_HEAD:
app->rememberHead(win->screen().getHead(win->fbWindow()));
break;
2003-04-26 07:57:00 +00:00
case REM_DIMENSIONS:
2003-05-11 13:36:12 +00:00
app->rememberDimensions(win->width(), win->height());
2003-04-26 07:57:00 +00:00
break;
case REM_POSITION:
2003-05-15 11:17:29 +00:00
app->rememberPosition(win->x(), win->y());
2003-04-26 07:57:00 +00:00
break;
case REM_FOCUSHIDDENSTATE:
app->rememberFocusHiddenstate(win->isFocusHidden());
break;
case REM_ICONHIDDENSTATE:
app->rememberIconHiddenstate(win->isIconHidden());
break;
case REM_SHADEDSTATE:
2003-04-26 07:57:00 +00:00
app->rememberShadedstate(win->isShaded());
break;
case REM_DECOSTATE:
2003-05-15 11:17:29 +00:00
app->rememberDecostate(win->decorationMask());
2003-04-26 07:57:00 +00:00
break;
case REM_STUCKSTATE:
2003-04-26 07:57:00 +00:00
app->rememberStuckstate(win->isStuck());
break;
2003-04-26 12:46:18 +00:00
// case REM_TABSTATE:
// break;
2003-04-26 07:57:00 +00:00
case REM_JUMPWORKSPACE:
app->rememberJumpworkspace(true);
break;
2003-04-26 13:47:53 +00:00
case REM_LAYER:
2003-05-15 11:17:29 +00:00
app->rememberLayer(win->layerNum());
2003-04-26 13:47:53 +00:00
break;
2003-04-26 07:57:00 +00:00
case REM_SAVEONCLOSE:
app->rememberSaveOnClose(true);
break;
case REM_LASTATTRIB:
default:
// nothing
break;
}
}
void Remember::forgetAttrib(WinClient &winclient, Attribute attrib) {
FluxboxWindow *win = winclient.fbwindow();
if (!win) return;
Application *app = find(winclient);
if (!app) {
app = add(winclient);
if (!app) return;
}
switch (attrib) {
case REM_WORKSPACE:
app->forgetWorkspace();
break;
case REM_HEAD:
app->forgetHead();
break;
2003-04-26 07:57:00 +00:00
case REM_DIMENSIONS:
app->forgetDimensions();
break;
case REM_POSITION:
app->forgetPosition();
break;
case REM_FOCUSHIDDENSTATE:
app->forgetFocusHiddenstate();
break;
case REM_ICONHIDDENSTATE:
app->forgetIconHiddenstate();
break;
2003-04-26 07:57:00 +00:00
case REM_STUCKSTATE:
app->forgetStuckstate();
break;
case REM_DECOSTATE:
app->forgetDecostate();
break;
case REM_SHADEDSTATE:
app->forgetShadedstate();
break;
// case REM_TABSTATE:
// break;
case REM_JUMPWORKSPACE:
app->forgetJumpworkspace();
break;
2003-04-26 13:47:53 +00:00
case REM_LAYER:
app->forgetLayer();
break;
2003-04-26 07:57:00 +00:00
case REM_SAVEONCLOSE:
app->forgetSaveOnClose();
break;
case REM_LASTATTRIB:
default:
// nothing
break;
}
}
void Remember::setupFrame(FluxboxWindow &win) {
2003-04-26 07:57:00 +00:00
WinClient &winclient = win.winClient();
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
// we don't touch the window if it is a transient
// of something else
// All windows get the remember menu.
2004-06-07 11:46:05 +00:00
win.addExtraMenu(_FBTEXT(Remember, MenuItemName, "Remember...", "Remember item in menu"),
createRememberMenu(*this, win, (winclient.transientFor() == 0)));
if (winclient.transientFor())
return;
2003-04-26 07:57:00 +00:00
Application *app = find(winclient);
if (app == 0)
2003-05-10 22:47:55 +00:00
return; // nothing to do
2003-04-26 07:57:00 +00:00
if (app->is_grouped && app->group == 0)
app->group = &win;
BScreen &screen = winclient.screen();
2003-04-26 07:57:00 +00:00
if (app->workspace_remember) {
// TODO: fix placement to initialise properly
screen.reassociateWindow(&win, app->workspace, true);
2003-04-26 07:57:00 +00:00
if (app->jumpworkspace_remember)
screen.changeWorkspaceID(app->workspace);
}
if (app->head_remember) {
win.screen().setOnHead<FluxboxWindow>(win, app->head);
}
if (app->decostate_remember)
win.setDecorationMask(app->decostate);
2003-04-26 07:57:00 +00:00
if (app->dimensions_remember)
win.resize(app->w, app->h);
int head = screen.getHead(win.fbWindow());
if (app->position_remember) {
switch (app->refc) {
default:
case POS_UPPERLEFT: // upperleft corner
win.move(screen.getHeadX(head) + app->x,
screen.getHeadY(head) + app->y);
break;
case POS_UPPERRIGHT: // upperright corner
win.move(screen.getHeadX(head) + screen.getHeadWidth(head) - win.width() - app->x,
screen.getHeadY(head) + app->y);
break;
case POS_LOWERLEFT: // lowerleft corner
win.move(screen.getHeadX(head) + app->x,
screen.getHeadHeight(head) - win.height() - app->y);
break;
case POS_LOWERRIGHT: // lowerright corner
win.move(screen.getHeadWidth(head) - win.width() - app->x,
screen.getHeadHeight(head) - win.height() - app->y);
break;
case POS_CENTER: // center of the screen, windows topleft corner is on the center
win.move((screen.getHeadWidth(head) / 2) + app->x,
(screen.getHeadHeight(head) / 2) + app->y);
break;
case POS_WINCENTER: // the window is centered REALLY upon the center
win.move((screen.getHeadWidth(head) / 2) - ( win.width() / 2 ) + app->x,
(screen.getHeadHeight(head) / 2) - ( win.height() / 2 ) + app->y);
break;
};
}
2003-04-26 07:57:00 +00:00
if (app->shadedstate_remember)
// if inconsistent...
if (win.isShaded() && !app->shadedstate ||
!win.isShaded() && app->shadedstate)
win.shade(); // toggles
// external tabs aren't available atm...
//if (app->tabstate_remember) ...
if (app->stuckstate_remember)
// if inconsistent...
if (win.isStuck() && !app->stuckstate ||
!win.isStuck() && app->stuckstate)
win.stick(); // toggles
if (app->focushiddenstate_remember)
win.setFocusHidden(true);
if (app->iconhiddenstate_remember)
win.setIconHidden(true);
2003-04-26 07:57:00 +00:00
2003-04-26 13:47:53 +00:00
if (app->layer_remember)
win.moveToLayer(app->layer);
2003-04-26 07:57:00 +00:00
}
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);
}
}
2003-07-04 14:06:20 +00:00
void Remember::updateClientClose(WinClient &winclient) {
Application *app = find(winclient);
if (app && (app->save_on_close_remember && app->save_on_close)) {
2003-07-04 14:06:20 +00:00
for (int attrib = 0; attrib <= REM_LASTATTRIB; attrib++) {
if (isRemembered(winclient, (Attribute) attrib)) {
rememberAttrib(winclient, (Attribute) attrib);
}
}
2003-07-04 14:06:20 +00:00
save();
}
2003-04-26 07:57:00 +00:00
2003-07-04 14:06:20 +00:00
// we need to get rid of references to this client
Clients::iterator wc_it = m_clients.find(&winclient);
2003-07-04 14:06:20 +00:00
if (wc_it != m_clients.end()) {
m_clients.erase(wc_it);
2003-07-04 14:06:20 +00:00
}
2003-04-26 07:57:00 +00:00
2003-07-04 14:06:20 +00:00
}
2003-04-26 07:57:00 +00:00
2003-07-04 14:06:20 +00:00
void Remember::updateFrameClose(FluxboxWindow &win) {
// scan all applications and remove this fbw if it is a recorded group
Patterns::iterator it = m_pats.begin();
while (it != m_pats.end()) {
if (&win == it->second->group)
it->second->group = 0;
++it;
2003-04-26 07:57:00 +00:00
}
}