00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "Remember.hh"
00027 #include "ClientPattern.hh"
00028 #include "Screen.hh"
00029 #include "Window.hh"
00030 #include "WinClient.hh"
00031 #include "FbMenu.hh"
00032 #include "FbCommands.hh"
00033 #include "fluxbox.hh"
00034
00035 #include "FbTk/StringUtil.hh"
00036 #include "FbTk/MenuItem.hh"
00037 #include "FbTk/App.hh"
00038
00039
00040 #include <X11/Xlib.h>
00041
00042
00043 #ifndef _GNU_SOURCE
00044 #define _GNU_SOURCE
00045 #endif // _GNU_SOURCE
00046
00047
00048 #include <iostream>
00049 #include <fstream>
00050 #include <string>
00051 #include <memory>
00052 #include <set>
00053
00054 #ifdef HAVE_CONFIG_H
00055 #include "config.h"
00056 #endif // HAVE_CONFIG_H
00057
00058 #ifdef HAVE_SSTREAM
00059 #include <sstream>
00060 #define FB_istringstream istringstream
00061 #elif HAVE_STRSTREAM
00062 #include <strstream>
00063 #define FB_istringstream istrstream
00064 #else
00065 #error "You dont have sstream or strstream headers!"
00066 #endif // HAVE_STRSTREAM
00067
00068 using namespace std;
00069
00070 #ifndef MAXPATHLEN
00071 #define MAXPATHLEN 255
00072 #endif // MAXPATHLEN
00073
00074 namespace {
00075
00076 class RememberMenuItem : public FbTk::MenuItem {
00077 public:
00078 RememberMenuItem(const char *label, Remember &remember,
00079 FluxboxWindow &fbwin,
00080 Remember::Attribute attrib) :
00081 FbTk::MenuItem(label), m_remember(remember),
00082 m_win(fbwin), m_attrib(attrib) {}
00083
00084 bool isSelected() const {
00085 return m_remember.isRemembered(m_win.winClient(), m_attrib);
00086 }
00087
00088 bool isEnabled() const {
00089 if (m_attrib != Remember::REM_JUMPWORKSPACE)
00090 return true;
00091 else
00092 return (m_remember.isRemembered(m_win.winClient(), Remember::REM_WORKSPACE));
00093 }
00094
00095 void click(int button, int time) {
00096 if (isSelected()) {
00097 m_remember.forgetAttrib(m_win.winClient(), m_attrib);
00098 } else {
00099 m_remember.rememberAttrib(m_win.winClient(), m_attrib);
00100 }
00101 m_remember.save();
00102 FbTk::MenuItem::click(button, time);
00103 }
00104
00105 private:
00106
00107 Remember &m_remember;
00108 FluxboxWindow &m_win;
00109 Remember::Attribute m_attrib;
00110 };
00111
00112 FbTk::Menu *createRememberMenu(Remember &remember, FluxboxWindow &win, bool enabled) {
00113
00114
00115 FbTk::Menu *menu = win.screen().createMenu("");
00116
00117
00118 if (!enabled) {
00119 FbTk::MenuItem *item = new FbTk::MenuItem("unavailable");
00120 item->setEnabled(false);
00121 menu->insert(item);
00122 menu->update();
00123 return menu;
00124 }
00125
00126
00127 menu->insert(new RememberMenuItem("Workspace", remember, win,
00128 Remember::REM_WORKSPACE));
00129 menu->insert(new RememberMenuItem("Jump to workspace", remember, win,
00130 Remember::REM_JUMPWORKSPACE));
00131 menu->insert(new RememberMenuItem("Dimensions", remember, win,
00132 Remember::REM_DIMENSIONS));
00133 menu->insert(new RememberMenuItem("Position", remember, win,
00134 Remember::REM_POSITION));
00135 menu->insert(new RememberMenuItem("Sticky", remember, win,
00136 Remember::REM_STUCKSTATE));
00137 menu->insert(new RememberMenuItem("Decorations", remember, win,
00138 Remember::REM_DECOSTATE));
00139 menu->insert(new RememberMenuItem("Shaded", remember, win,
00140 Remember::REM_SHADEDSTATE));
00141 menu->insert(new RememberMenuItem("Layer", remember, win,
00142 Remember::REM_LAYER));
00143 menu->insert(new RememberMenuItem("Save on close", remember, win,
00144 Remember::REM_SAVEONCLOSE));
00145
00146 menu->update();
00147 return menu;
00148 };
00149
00150
00151
00152 bool handleStartupItem(const string &line, int offset) {
00153 int next = 0;
00154 string str;
00155 int screen = 0;
00156
00157
00158
00159 next = FbTk::StringUtil::getStringBetween(str,
00160 line.c_str() + offset,
00161 '(', ')');
00162 if (next > 0) {
00163
00164 string option;
00165 int pos = str.find('=');
00166 bool error = false;
00167 if (pos > 0) {
00168 option = str.substr(0, pos);
00169 if (option == "screen") {
00170 FB_istringstream iss(str.c_str() + pos + 1);
00171 iss >> screen;
00172 } else {
00173 error = true;
00174 }
00175 } else {
00176 error = true;
00177 }
00178 if (error) {
00179 cerr<<"Error parsing startup options."<<endl;
00180 return false;
00181 }
00182 } else {
00183 next = 0;
00184 }
00185
00186 next = FbTk::StringUtil::getStringBetween(str,
00187 line.c_str() + offset + next,
00188 '{', '}');
00189
00190 if (next <= 0) {
00191 cerr<<"Error parsing [startup] at column "<<offset<<" - expecting {command}."<<endl;
00192 return false;
00193 } else {
00194 FbCommands::ExecuteCmd *tmp_exec_cmd = new FbCommands::ExecuteCmd(str, screen);
00195 #ifdef DEBUG
00196 cerr<<"Executing startup command '"<<str<<"' on screen "<<screen<<endl;
00197 #endif // DEBUG
00198 tmp_exec_cmd->execute();
00199 delete tmp_exec_cmd;
00200 return true;
00201 }
00202 };
00203
00204 };
00205
00206
00207 Application::Application(bool grouped)
00208 : is_grouped(grouped),
00209 group(0)
00210 {
00211 workspace_remember =
00212 dimensions_remember =
00213 position_remember =
00214 stuckstate_remember =
00215 decostate_remember =
00216 shadedstate_remember =
00217 tabstate_remember =
00218 jumpworkspace_remember =
00219 layer_remember =
00220 save_on_close_remember = false;
00221 }
00222
00223
00224
00225
00226
00227 Remember::Remember() {
00228 enableUpdate();
00229 load();
00230 }
00231
00232 Remember::~Remember() {
00233
00234
00235
00236
00237 Patterns::iterator it;
00238 std::set<Application *> all_apps;
00239 while (!m_pats.empty()) {
00240 it = m_pats.begin();
00241 delete it->first;
00242 all_apps.insert(it->second);
00243 m_pats.erase(it);
00244 }
00245
00246 std::set<Application *>::iterator ait = all_apps.begin();
00247 while (ait != all_apps.end()) {
00248 delete (*ait);
00249 ++ait;
00250 }
00251 }
00252
00253 Application* Remember::find(WinClient &winclient) {
00254
00255
00256 Clients::iterator wc_it = m_clients.find(&winclient);
00257 if (wc_it != m_clients.end())
00258 return wc_it->second;
00259 else {
00260 Patterns::iterator it = m_pats.begin();
00261 for (; it != m_pats.end(); it++)
00262 if (it->first->match(winclient)) {
00263 it->first->addMatch();
00264 m_clients[&winclient] = it->second;
00265 return it->second;
00266 }
00267 }
00268
00269 return 0;
00270 }
00271
00272 Application * Remember::add(WinClient &winclient) {
00273 ClientPattern *p = new ClientPattern();
00274 Application *app = new Application(false);
00275
00276 p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
00277 m_clients[&winclient] = app;
00278 p->addMatch();
00279 m_pats.push_back(make_pair(p, app));
00280 return app;
00281 }
00282
00283 int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
00284 string line;
00285 int row = 0;
00286 while (! file.eof()) {
00287 if (first_line || getline(file, line)) {
00288 if (first_line) {
00289 line = *first_line;
00290 first_line = 0;
00291 }
00292
00293 row++;
00294 if (line[0] == '#')
00295 continue;
00296 int parse_pos = 0, err = 0;
00297 string str_key, str_option, str_label;
00298 err = FbTk::StringUtil::getStringBetween(str_key,
00299 line.c_str(),
00300 '[', ']');
00301 if (err > 0) {
00302 int tmp;
00303 tmp= FbTk::StringUtil::getStringBetween(str_option,
00304 line.c_str() + err,
00305 '(', ')');
00306 if (tmp>0)
00307 err += tmp;
00308 }
00309 if (err > 0 ) {
00310 parse_pos += err;
00311 err = FbTk::StringUtil::getStringBetween(str_label,
00312 line.c_str() + parse_pos,
00313 '{', '}');
00314 if (err>0) {
00315 parse_pos += err;
00316 }
00317 } else
00318 continue;
00319
00320 if (!str_key.size())
00321 continue;
00322 if (str_key == "Workspace") {
00323 unsigned int w;
00324 FB_istringstream iss(str_label.c_str());
00325 iss >> w;
00326 app.rememberWorkspace(w);
00327 } else if (str_key == "Layer") {
00328 unsigned int l;
00329 FB_istringstream iss(str_label.c_str());
00330 iss >> l;
00331 app.rememberLayer(l);
00332 } else if (str_key == "Dimensions") {
00333 unsigned int h,w;
00334 FB_istringstream iss(str_label.c_str());
00335 iss >> w >> h;
00336 app.rememberDimensions(w,h);
00337 } else if (str_key == "Position") {
00338 FB_istringstream iss;
00339 unsigned int r= 0;
00340 unsigned int x= 0;
00341 unsigned int y= 0;
00342
00343
00344
00345 if ( str_option.length() )
00346 {
00347 if ( str_option == "UPPERLEFT" ) r= POS_UPPERLEFT;
00348 else if ( str_option == "UPPERRIGHT" ) r= POS_UPPERRIGHT;
00349 else if ( str_option == "LOWERLEFT" ) r= POS_LOWERLEFT;
00350 else if ( str_option == "LOWERRIGHT" ) r= POS_LOWERRIGHT;
00351 else if ( str_option == "CENTER" ) r= POS_CENTER;
00352 else if ( str_option == "WINCENTER" ) r= POS_WINCENTER;
00353 else {
00354 iss.str(str_option);
00355 iss >> r;
00356 }
00357 }
00358
00359 iss.str(str_label.c_str());
00360 iss >> x >> y;
00361 app.rememberPosition(x, y, r);
00362 } else if (str_key == "Shaded") {
00363 app.rememberShadedstate((str_label=="yes"));
00364 } else if (str_key == "Tab") {
00365 app.rememberTabstate((str_label=="yes"));
00366 } else if (str_key == "Deco") {
00367 if (str_label == "NONE") {
00368 app.rememberDecostate((unsigned int) 0);
00369 } else if (str_label == "NORMAL") {
00370 app.rememberDecostate((unsigned int) 0xfffffff);
00371 } else if (str_label == "TINY") {
00372 app.rememberDecostate((unsigned int)
00373 FluxboxWindow::DECORM_TITLEBAR
00374 | FluxboxWindow::DECORM_ICONIFY
00375 | FluxboxWindow::DECORM_MENU
00376 );
00377 } else if (str_label == "TOOL") {
00378 app.rememberDecostate((unsigned int)
00379 FluxboxWindow::DECORM_TITLEBAR
00380 | FluxboxWindow::DECORM_MENU
00381 );
00382 } else if (str_label == "BORDER") {
00383 app.rememberDecostate((unsigned int)
00384 FluxboxWindow::DECORM_BORDER
00385 | FluxboxWindow::DECORM_MENU
00386 );
00387 } else {
00388 unsigned int mask;
00389 const char * str = str_label.c_str();
00390
00391 FB_istringstream iss(str);
00392
00393 if (str[0] == '0' && str[1] == 'x') {
00394 iss.seekg(2);
00395 iss >> hex;
00396 }
00397 iss >> mask ;
00398 app.rememberDecostate(mask);
00399 }
00400 } else if (str_key == "Sticky") {
00401 app.rememberStuckstate((str_label=="yes"));
00402 } else if (str_key == "Jump") {
00403 app.rememberJumpworkspace((str_label=="yes"));
00404 } else if (str_key == "Close") {
00405 app.rememberSaveOnClose((str_label=="yes"));
00406 } else if (str_key == "end") {
00407 return row;
00408 } else {
00409 cerr << "Unsupported apps key = " << str_key << endl;
00410 }
00411 }
00412 }
00413 return row;
00414 }
00415
00416 void Remember::load() {
00417
00418 string apps_string;
00419 Fluxbox::instance()->getDefaultDataFilename("apps", apps_string);
00420
00421 #ifdef DEBUG
00422 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl;
00423 #endif // DEBUG
00424 ifstream apps_file(apps_string.c_str());
00425
00426 if (!apps_file.fail()) {
00427 if (!apps_file.eof()) {
00428 string line;
00429 int row = 0;
00430 bool in_group = false;
00431 std::list<ClientPattern *> grouped_pats;
00432 while (getline(apps_file, line) && ! apps_file.eof()) {
00433 row++;
00434 if (line[0] == '#')
00435 continue;
00436 string key;
00437 int err=0;
00438 int pos = FbTk::StringUtil::getStringBetween(key,
00439 line.c_str(),
00440 '[', ']');
00441
00442 if (pos > 0 && key == "app") {
00443 ClientPattern *pat = new ClientPattern(line.c_str() + pos);
00444 if (!in_group) {
00445 if ((err = pat->error()) == 0) {
00446 Application *app = new Application(false);
00447 m_pats.push_back(make_pair(pat, app));
00448 row += parseApp(apps_file, *app);
00449 } else {
00450 cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
00451 delete pat;
00452 }
00453 } else {
00454 grouped_pats.push_back(pat);
00455 }
00456 } else if (pos > 0 && key == "startup") {
00457 if (!handleStartupItem(line, pos)) {
00458 cerr<<"Error reading apps file at line "<<row<<"."<<endl;
00459 }
00460
00461 m_startups.push_back(line.substr(pos));
00462 } else if (pos > 0 && key == "group") {
00463 in_group = true;
00464 } else if (in_group) {
00465
00466 Application *app = new Application(true);
00467 while (!grouped_pats.empty()) {
00468
00469 m_pats.push_back(make_pair(grouped_pats.front(), app));
00470 grouped_pats.pop_front();
00471 }
00472
00473
00474
00475
00476 if (!(pos>0 && key == "end")) {
00477 row += parseApp(apps_file, *app, &line);
00478 }
00479 in_group = false;
00480 } else
00481 cerr<<"Error in apps file on line "<<row<<"."<<endl;
00482
00483 }
00484 } else {
00485 #ifdef DEBUG
00486 cerr<<__FILE__<<"("<<__FUNCTION__<< ") Empty apps file" << endl;
00487 #endif
00488 }
00489 } else {
00490 cerr << "apps file failure" << endl;
00491 }
00492 }
00493
00494 void Remember::save() {
00495 #ifdef DEBUG
00496 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Saving apps file..."<<endl;
00497 #endif // DEBUG
00498 string apps_string;
00499 Fluxbox::instance()->getDefaultDataFilename("apps", apps_string);
00500 ofstream apps_file(apps_string.c_str());
00501
00502
00503 Startups::iterator sit = m_startups.begin();
00504 Startups::iterator sit_end = m_startups.end();
00505 for (; sit != sit_end; ++sit) {
00506 apps_file<<"[startup] "<<(*sit)<<endl;
00507 }
00508
00509 Patterns::iterator it = m_pats.begin();
00510 Patterns::iterator it_end = m_pats.end();
00511
00512 std::set<Application *> grouped_apps;
00513
00514 for (; it != it_end; ++it) {
00515 Application &a = *it->second;
00516 if (a.is_grouped) {
00517
00518 if (grouped_apps.find(&a) != grouped_apps.end())
00519 continue;
00520 grouped_apps.insert(&a);
00521
00522 apps_file << "[group]" << endl;
00523 Patterns::iterator git = m_pats.begin();
00524 Patterns::iterator git_end = m_pats.end();
00525 for (; git != git_end; git++) {
00526 if (git->second == &a) {
00527 apps_file << " [app]"<<git->first->toString()<<endl;
00528 }
00529 }
00530 } else {
00531 apps_file << "[app]"<<it->first->toString()<<endl;
00532 }
00533 if (a.workspace_remember) {
00534 apps_file << " [Workspace]\t{" << a.workspace << "}" << endl;
00535 }
00536 if (a.dimensions_remember) {
00537 apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl;
00538 }
00539 if (a.position_remember) {
00540 apps_file << " [Position]\t{" << a.x << " " << a.y << "}" << endl;
00541 }
00542 if (a.shadedstate_remember) {
00543 apps_file << " [Shaded]\t{" << ((a.shadedstate)?"yes":"no") << "}" << endl;
00544 }
00545 if (a.tabstate_remember) {
00546 apps_file << " [Tab]\t\t{" << ((a.tabstate)?"yes":"no") << "}" << endl;
00547 }
00548 if (a.decostate_remember) {
00549 switch (a.decostate) {
00550 case (0) :
00551 apps_file << " [Deco]\t{NONE}" << endl;
00552 break;
00553 case (0xffffffff):
00554 case (FluxboxWindow::DECORM_LAST - 1):
00555 apps_file << " [Deco]\t{NORMAL}" << endl;
00556 break;
00557 case (FluxboxWindow::DECORM_TITLEBAR
00558 | FluxboxWindow::DECORM_ICONIFY
00559 | FluxboxWindow::DECORM_MENU):
00560 apps_file << " [Deco]\t{TOOL}" << endl;
00561 break;
00562 case (FluxboxWindow::DECORM_TITLEBAR
00563 | FluxboxWindow::DECORM_MENU):
00564 apps_file << " [Deco]\t{TINY}" << endl;
00565 break;
00566 case (FluxboxWindow::DECORM_BORDER
00567 | FluxboxWindow::DECORM_MENU):
00568 apps_file << " [Deco]\t{BORDER}" << endl;
00569 break;
00570 default:
00571 apps_file << " [Deco]\t{0x"<<hex<<a.decostate<<dec<<"}"<<endl;
00572 break;
00573 }
00574 }
00575 if (a.stuckstate_remember) {
00576 apps_file << " [Sticky]\t{" << ((a.stuckstate)?"yes":"no") << "}" << endl;
00577 }
00578 if (a.jumpworkspace_remember) {
00579 apps_file << " [Jump]\t{" << ((a.jumpworkspace)?"yes":"no") << "}" << endl;
00580 }
00581 if (a.layer_remember) {
00582 apps_file << " [Layer]\t{" << a.layer << "}" << endl;
00583 }
00584 if (a.save_on_close_remember) {
00585 apps_file << " [Close]\t{" << ((a.save_on_close)?"yes":"no") << "}" << endl;
00586 }
00587 apps_file << "[end]" << endl;
00588 }
00589 }
00590
00591 bool Remember::isRemembered(WinClient &winclient, Attribute attrib) {
00592 Application *app = find(winclient);
00593 if (!app) return false;
00594 switch (attrib) {
00595 case REM_WORKSPACE:
00596 return app->workspace_remember;
00597 break;
00598 case REM_DIMENSIONS:
00599 return app->dimensions_remember;
00600 break;
00601 case REM_POSITION:
00602 return app->position_remember;
00603 break;
00604 case REM_STUCKSTATE:
00605 return app->stuckstate_remember;
00606 break;
00607 case REM_DECOSTATE:
00608 return app->decostate_remember;
00609 break;
00610 case REM_SHADEDSTATE:
00611 return app->shadedstate_remember;
00612 break;
00613
00614
00615
00616 case REM_JUMPWORKSPACE:
00617 return app->jumpworkspace_remember;
00618 break;
00619 case REM_LAYER:
00620 return app->layer_remember;
00621 break;
00622 case REM_SAVEONCLOSE:
00623 return app->save_on_close_remember;
00624 break;
00625 case REM_LASTATTRIB:
00626 default:
00627 return false;
00628 }
00629 }
00630
00631 void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) {
00632 FluxboxWindow *win = winclient.fbwindow();
00633 if (!win) return;
00634 Application *app = find(winclient);
00635 if (!app) {
00636 app = add(winclient);
00637 if (!app) return;
00638 }
00639 switch (attrib) {
00640 case REM_WORKSPACE:
00641 app->rememberWorkspace(win->workspaceNumber());
00642 break;
00643 case REM_DIMENSIONS:
00644 app->rememberDimensions(win->width(), win->height());
00645 break;
00646 case REM_POSITION:
00647 app->rememberPosition(win->x(), win->y());
00648 break;
00649 case REM_SHADEDSTATE:
00650 app->rememberShadedstate(win->isShaded());
00651 break;
00652 case REM_DECOSTATE:
00653 app->rememberDecostate(win->decorationMask());
00654 break;
00655 case REM_STUCKSTATE:
00656 app->rememberStuckstate(win->isStuck());
00657 break;
00658
00659
00660 case REM_JUMPWORKSPACE:
00661 app->rememberJumpworkspace(true);
00662 break;
00663 case REM_LAYER:
00664 app->rememberLayer(win->layerNum());
00665 break;
00666 case REM_SAVEONCLOSE:
00667 app->rememberSaveOnClose(true);
00668 break;
00669 case REM_LASTATTRIB:
00670 default:
00671
00672 break;
00673 }
00674 }
00675
00676 void Remember::forgetAttrib(WinClient &winclient, Attribute attrib) {
00677 FluxboxWindow *win = winclient.fbwindow();
00678 if (!win) return;
00679 Application *app = find(winclient);
00680 if (!app) {
00681 app = add(winclient);
00682 if (!app) return;
00683 }
00684 switch (attrib) {
00685 case REM_WORKSPACE:
00686 app->forgetWorkspace();
00687 break;
00688 case REM_DIMENSIONS:
00689 app->forgetDimensions();
00690 break;
00691 case REM_POSITION:
00692 app->forgetPosition();
00693 break;
00694 case REM_STUCKSTATE:
00695 app->forgetStuckstate();
00696 break;
00697 case REM_DECOSTATE:
00698 app->forgetDecostate();
00699 break;
00700 case REM_SHADEDSTATE:
00701 app->forgetShadedstate();
00702 break;
00703
00704
00705 case REM_JUMPWORKSPACE:
00706 app->forgetJumpworkspace();
00707 break;
00708 case REM_LAYER:
00709 app->forgetLayer();
00710 break;
00711 case REM_SAVEONCLOSE:
00712 app->forgetSaveOnClose();
00713 break;
00714 case REM_LASTATTRIB:
00715 default:
00716
00717 break;
00718 }
00719 }
00720
00721 void Remember::setupFrame(FluxboxWindow &win) {
00722 WinClient &winclient = win.winClient();
00723
00724
00725
00726
00727
00728
00729 win.addExtraMenu("Remember...", createRememberMenu(*this, win, (winclient.transientFor() == 0)));
00730
00731 if (winclient.transientFor())
00732 return;
00733
00734 Application *app = find(winclient);
00735 if (app == 0)
00736 return;
00737
00738 if (app->is_grouped && app->group == 0)
00739 app->group = &win;
00740
00741 BScreen &screen = winclient.screen();
00742
00743 if (app->workspace_remember) {
00744
00745 screen.reassociateWindow(&win, app->workspace, true);
00746 if (app->jumpworkspace_remember)
00747 screen.changeWorkspaceID(app->workspace);
00748 }
00749
00750 if (app->dimensions_remember)
00751 win.resize(app->w, app->h);
00752
00753 if (app->position_remember) {
00754 switch (app->refc) {
00755 default:
00756 case POS_UPPERLEFT:
00757 win.move(app->x, app->y);
00758 break;
00759 case POS_UPPERRIGHT:
00760 win.move(screen.width() - win.width() - app->x, app->y);
00761 break;
00762 case POS_LOWERLEFT:
00763 win.move(app->x, screen.height() - win.height() - app->y);
00764 break;
00765 case POS_LOWERRIGHT:
00766 win.move(screen.width() - win.width() - app->x,
00767 screen.height() - win.height() - app->y);
00768 break;
00769 case POS_CENTER:
00770 win.move((screen.width() / 2) + app->x,
00771 (screen.height() / 2) + app->y);
00772 break;
00773 case POS_WINCENTER:
00774 win.move((screen.width() / 2) - ( win.width() / 2 ) + app->x,
00775 (screen.height() / 2) - ( win.height() / 2 ) + app->y);
00776 break;
00777 };
00778 }
00779
00780 if (app->shadedstate_remember)
00781
00782 if (win.isShaded() && !app->shadedstate ||
00783 !win.isShaded() && app->shadedstate)
00784 win.shade();
00785
00786
00787
00788
00789 if (app->decostate_remember)
00790 win.setDecorationMask(app->decostate);
00791
00792 if (app->stuckstate_remember)
00793
00794 if (win.isStuck() && !app->stuckstate ||
00795 !win.isStuck() && app->stuckstate)
00796 win.stick();
00797
00798 if (app->layer_remember)
00799 win.moveToLayer(app->layer);
00800
00801 }
00802
00803 void Remember::setupClient(WinClient &winclient) {
00804
00805 Application *app = find(winclient);
00806 if (app == 0)
00807 return;
00808
00809 if (winclient.fbwindow() == 0 && app->is_grouped && app->group) {
00810 app->group->attachClient(winclient);
00811 }
00812 }
00813
00814 void Remember::updateClientClose(WinClient &winclient) {
00815 Application *app = find(winclient);
00816
00817 if (app && (app->save_on_close_remember && app->save_on_close)) {
00818
00819 for (int attrib = 0; attrib <= REM_LASTATTRIB; attrib++) {
00820 if (isRemembered(winclient, (Attribute) attrib)) {
00821 rememberAttrib(winclient, (Attribute) attrib);
00822 }
00823 }
00824
00825 save();
00826 }
00827
00828
00829 Clients::iterator wc_it = m_clients.find(&winclient);
00830
00831 if (wc_it != m_clients.end()) {
00832 m_clients.erase(wc_it);
00833 }
00834
00835 }
00836
00837 void Remember::updateFrameClose(FluxboxWindow &win) {
00838
00839 Patterns::iterator it = m_pats.begin();
00840 while (it != m_pats.end()) {
00841 if (&win == it->second->group)
00842 it->second->group = 0;
00843 ++it;
00844 }
00845 }