1
// Remember.cc for Fluxbox Window Manager
2
// Copyright (c) 2003 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
3
// and Simon Bowden (rathnor at users.sourceforge.net)
4
// Copyright (c) 2002 Xavier Brouckaert
6
// Permission is hereby granted, free of charge, to any person obtaining a
7
// copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the
11
// Software is furnished to do so, subject to the following conditions:
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
// DEALINGS IN THE SOFTWARE.
24
// $Id: Remember.cc 4066 2005-06-23 09:22:11Z mathias $
26
#include "Remember.hh"
27
#include "ClientPattern.hh"
30
#include "WinClient.hh"
32
#include "FbCommands.hh"
34
#include "WindowCmd.hh"
36
#include "FbTk/I18n.hh"
37
#include "FbTk/StringUtil.hh"
38
#include "FbTk/MenuItem.hh"
39
#include "FbTk/App.hh"
40
#include "FbTk/stringstream.hh"
62
class RememberMenuItem : public FbTk::MenuItem {
64
RememberMenuItem(const char *label,
65
Remember::Attribute attrib) :
66
FbTk::MenuItem(label),
71
bool isSelected() const {
72
if (WindowCmd<void>::window() == 0)
75
if (WindowCmd<void>::window()->numClients()) // ensure it HAS clients
76
return Remember::instance().isRemembered(WindowCmd<void>::window()->winClient(), m_attrib);
81
bool isEnabled() const {
82
if (WindowCmd<void>::window() == 0)
85
if (m_attrib != Remember::REM_JUMPWORKSPACE)
87
else if (WindowCmd<void>::window()->numClients())
88
return (Remember::instance().isRemembered(WindowCmd<void>::window()->winClient(), Remember::REM_WORKSPACE));
93
void click(int button, int time) {
94
if (WindowCmd<void>::window() != 0) {
96
Remember::instance().forgetAttrib(WindowCmd<void>::window()->winClient(), m_attrib);
98
Remember::instance().rememberAttrib(WindowCmd<void>::window()->winClient(), m_attrib);
101
Remember::instance().save();
102
FbTk::MenuItem::click(button, time);
106
Remember::Attribute m_attrib;
109
FbTk::Menu *createRememberMenu(BScreen &screen) {
110
// each fluxboxwindow has its own windowmenu
111
// so we also create a remember menu just for it...
112
FbTk::Menu *menu = screen.createMenu("");
114
// if enabled, then we want this to be a unavailable menu
117
FbTk::MenuItem *item = new FbTk::MenuItem("unavailable");
118
item->setEnabled(false);
125
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Workspace, "Workspace", "Remember Workspace"),
126
Remember::REM_WORKSPACE));
127
menu->insert(new RememberMenuItem(_FBTEXT(Remember, JumpToWorkspace, "Jump to workspace", "Change active workspace to remembered one on open"),
128
Remember::REM_JUMPWORKSPACE));
129
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Head, "Head", "Remember Head"),
130
Remember::REM_HEAD));
131
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Dimensions, "Dimensions", "Remember Dimensions - with width and height"),
132
Remember::REM_DIMENSIONS));
133
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Position, "Position", "Remember position - window co-ordinates"),
134
Remember::REM_POSITION));
135
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Sticky, "Sticky", "Remember Sticky"),
136
Remember::REM_STUCKSTATE));
137
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Decorations, "Decorations", "Remember window decorations"),
138
Remember::REM_DECOSTATE));
139
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Shaded, "Shaded", "Remember shaded"),
140
Remember::REM_SHADEDSTATE));
141
menu->insert(new RememberMenuItem(_FBTEXT(Remember, Layer, "Layer", "Remember Layer"),
142
Remember::REM_LAYER));
143
menu->insert(new RememberMenuItem(_FBTEXT(Remember, SaveOnClose, "Save on close", "Save remembered attributes on close"),
144
Remember::REM_SAVEONCLOSE));
150
// offset is the offset in the string that we start looking from
151
// return true if all ok, false on error
152
bool handleStartupItem(const string &line, int offset) {
157
// accept some options, for now only "screen=NN"
158
// these option are given in parentheses before the command
159
next = FbTk::StringUtil::getStringBetween(str,
160
line.c_str() + offset,
163
// there are some options
165
int pos = str.find('=');
168
option = str.substr(0, pos);
169
if (option == "screen") {
170
FbTk_istringstream iss(str.c_str() + pos + 1);
179
cerr<<"Error parsing startup options."<<endl;
186
next = FbTk::StringUtil::getStringBetween(str,
187
line.c_str() + offset + next,
191
cerr<<"Error parsing [startup] at column "<<offset<<" - expecting {command}."<<endl;
194
FbCommands::ExecuteCmd *tmp_exec_cmd = new FbCommands::ExecuteCmd(str, screen);
196
cerr<<"Executing startup command '"<<str<<"' on screen "<<screen<<endl;
198
tmp_exec_cmd->execute();
204
}; // end anonymous namespace
207
Application::Application(bool grouped)
208
: is_grouped(grouped),
212
dimensions_remember =
213
focushiddenstate_remember =
214
iconhiddenstate_remember =
215
jumpworkspace_remember =
218
shadedstate_remember =
219
stuckstate_remember =
223
save_on_close_remember = false;
230
Remember *Remember::s_instance = 0;
232
Remember::Remember() {
234
throw string("Can not create more than one instance of Remember");
241
Remember::~Remember() {
243
// free our resources
245
// the patterns free the "Application"s
246
// the client mapping shouldn't need cleaning
247
Patterns::iterator it;
248
std::set<Application *> all_apps; // no duplicates
249
while (!m_pats.empty()) {
251
delete it->first; // ClientPattern
252
all_apps.insert(it->second); // Application, not necessarily unique
256
std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates
257
while (ait != all_apps.end()) {
265
Application* Remember::find(WinClient &winclient) {
266
// if it is already associated with a application, return that one
267
// otherwise, check it against every pattern that we've got
268
Clients::iterator wc_it = m_clients.find(&winclient);
269
if (wc_it != m_clients.end())
270
return wc_it->second;
272
Patterns::iterator it = m_pats.begin();
273
for (; it != m_pats.end(); it++)
274
if (it->first->match(winclient)) {
275
it->first->addMatch();
276
m_clients[&winclient] = it->second;
280
// oh well, no matches
284
Application * Remember::add(WinClient &winclient) {
285
ClientPattern *p = new ClientPattern();
286
Application *app = new Application(false);
287
// by default, we match against the WMClass of a window.
288
p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
289
m_clients[&winclient] = app;
291
m_pats.push_back(make_pair(p, app));
295
int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
299
while (! file.eof()) {
300
if (first_line || getline(file, line)) {
307
FbTk::StringUtil::removeFirstWhitespace(line);
308
FbTk::StringUtil::removeTrailingWhitespace(line);
309
if (line.size() == 0 || line[0] == '#')
310
continue; //the line is commented or blank
311
int parse_pos = 0, err = 0;
312
string str_key, str_option, str_label;
313
err = FbTk::StringUtil::getStringBetween(str_key,
318
tmp= FbTk::StringUtil::getStringBetween(str_option,
326
err = FbTk::StringUtil::getStringBetween(str_label,
327
line.c_str() + parse_pos,
333
continue; //read next line
336
continue; //read next line
337
if (str_key == "Workspace") {
339
FbTk_istringstream iss(str_label.c_str());
341
app.rememberWorkspace(w);
342
} else if (str_key == "Head") {
343
int h = atoi(str_label.c_str());
345
} else if (str_key == "Layer") {
347
if (str_label == "DESKTOP") {
348
l = Fluxbox::instance()->getDesktopLayer();
349
} else if (str_label == "BOTTOM") {
350
l = Fluxbox::instance()->getBottomLayer();
351
} else if (str_label == "NORMAL") {
352
l = Fluxbox::instance()->getNormalLayer();
353
} else if (str_label == "TOP") {
354
l = Fluxbox::instance()->getTopLayer();
355
} else if (str_label == "DOCK") {
356
l = Fluxbox::instance()->getDockLayer();
357
} else if (str_label == "ABOVEDOCK") {
358
l = Fluxbox::instance()->getAboveDockLayer();
359
} else if (str_label == "MENU") {
360
l = Fluxbox::instance()->getMenuLayer();
362
FbTk_istringstream iss(str_label.c_str());
365
app.rememberLayer(l);
366
} else if (str_key == "Dimensions") {
368
FbTk_istringstream iss(str_label.c_str());
370
app.rememberDimensions(w,h);
371
} else if (str_key == "Position") {
375
// more info about the parameter
376
// in ::rememberPosition
378
if ( str_option.length() )
380
if ( str_option == "UPPERLEFT" ) r= POS_UPPERLEFT;
381
else if ( str_option == "UPPERRIGHT" ) r= POS_UPPERRIGHT;
382
else if ( str_option == "LOWERLEFT" ) r= POS_LOWERLEFT;
383
else if ( str_option == "LOWERRIGHT" ) r= POS_LOWERRIGHT;
384
else if ( str_option == "CENTER" ) r= POS_CENTER;
385
else if ( str_option == "WINCENTER" ) r= POS_WINCENTER;
387
FbTk_istringstream iss_r(str_option.c_str());
392
FbTk_istringstream iss_xy(str_label.c_str());
394
app.rememberPosition(x, y, r);
395
} else if (str_key == "Shaded") {
396
app.rememberShadedstate((str_label=="yes"));
397
} else if (str_key == "Tab") {
398
app.rememberTabstate((str_label=="yes"));
399
} else if (str_key == "FocusHidden") {
400
app.rememberFocusHiddenstate((str_label=="yes"));
401
} else if (str_key == "IconHidden") {
402
app.rememberIconHiddenstate((str_label=="yes"));
403
} else if (str_key == "Hidden") {
404
app.rememberIconHiddenstate((str_label=="yes"));
405
app.rememberFocusHiddenstate((str_label=="yes"));
406
} else if (str_key == "Deco") {
407
if (str_label == "NONE") {
408
app.rememberDecostate((unsigned int) 0);
409
} else if (str_label == "NORMAL") {
410
app.rememberDecostate((unsigned int) 0xfffffff);
411
} else if (str_label == "TINY") {
412
app.rememberDecostate((unsigned int)
413
FluxboxWindow::DECORM_TITLEBAR
414
| FluxboxWindow::DECORM_ICONIFY
415
| FluxboxWindow::DECORM_MENU
417
} else if (str_label == "TOOL") {
418
app.rememberDecostate((unsigned int)
419
FluxboxWindow::DECORM_TITLEBAR
420
| FluxboxWindow::DECORM_MENU
422
} else if (str_label == "BORDER") {
423
app.rememberDecostate((unsigned int)
424
FluxboxWindow::DECORM_BORDER
425
| FluxboxWindow::DECORM_MENU
429
const char * str = str_label.c_str();
430
// it'll have at least one char and \0, so this is safe
431
FbTk_istringstream iss(str);
433
if (str[0] == '0' && str[1] == 'x') {
438
app.rememberDecostate(mask);
440
} else if (str_key == "Sticky") {
441
app.rememberStuckstate((str_label=="yes"));
442
} else if (str_key == "Jump") {
443
app.rememberJumpworkspace((str_label=="yes"));
444
} else if (str_key == "Close") {
445
app.rememberSaveOnClose((str_label=="yes"));
446
} else if (str_key == "end") {
449
cerr << _FBTEXT(Remember, Unknown, "Unknown apps key", "apps entry type not known")<<" = " << str_key << endl;
456
void Remember::load() {
458
string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename());
461
cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl;
463
ifstream apps_file(apps_string.c_str());
465
if (!apps_file.fail()) {
466
if (!apps_file.eof()) {
469
bool in_group = false;
470
std::list<ClientPattern *> grouped_pats;
471
while (getline(apps_file, line) && ! apps_file.eof()) {
473
FbTk::StringUtil::removeFirstWhitespace(line);
474
FbTk::StringUtil::removeTrailingWhitespace(line);
475
if (line.size() == 0 || line[0] == '#')
479
int pos = FbTk::StringUtil::getStringBetween(key,
483
if (pos > 0 && key == "app") {
484
ClientPattern *pat = new ClientPattern(line.c_str() + pos);
486
if ((err = pat->error()) == 0) {
487
Application *app = new Application(false);
488
m_pats.push_back(make_pair(pat, app));
489
row += parseApp(apps_file, *app);
491
cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
492
delete pat; // since it didn't work
495
grouped_pats.push_back(pat);
497
} else if (pos > 0 && key == "startup") {
498
if (!handleStartupItem(line, pos)) {
499
cerr<<"Error reading apps file at line "<<row<<"."<<endl;
501
// save the item even if it was bad (aren't we nice)
502
m_startups.push_back(line.substr(pos));
503
} else if (pos > 0 && key == "group") {
505
} else if (in_group) {
506
// otherwise assume that it is the start of the attributes
507
Application *app = new Application(true);
508
while (!grouped_pats.empty()) {
509
// associate all the patterns with this app
510
m_pats.push_back(make_pair(grouped_pats.front(), app));
511
grouped_pats.pop_front();
514
// we hit end... probably don't have attribs for the group
515
// so finish it off with an empty application
516
// otherwise parse the app
517
if (!(pos>0 && key == "end")) {
518
row += parseApp(apps_file, *app, &line);
522
cerr<<"Error in apps file on line "<<row<<"."<<endl;
527
cerr<<__FILE__<<"("<<__FUNCTION__<< ") Empty apps file" << endl;
531
cerr << "apps file failure" << endl;
535
void Remember::save() {
537
cerr<<__FILE__<<"("<<__FUNCTION__<<"): Saving apps file..."<<endl;
540
Fluxbox::instance()->getDefaultDataFilename("apps", apps_string);
541
ofstream apps_file(apps_string.c_str());
543
// first of all we output all the startup commands
544
Startups::iterator sit = m_startups.begin();
545
Startups::iterator sit_end = m_startups.end();
546
for (; sit != sit_end; ++sit) {
547
apps_file<<"[startup] "<<(*sit)<<endl;
550
Patterns::iterator it = m_pats.begin();
551
Patterns::iterator it_end = m_pats.end();
553
std::set<Application *> grouped_apps; // no duplicates
555
for (; it != it_end; ++it) {
556
Application &a = *it->second;
558
// if already processed
559
if (grouped_apps.find(&a) != grouped_apps.end())
561
grouped_apps.insert(&a);
562
// otherwise output this whole group
563
apps_file << "[group]" << endl;
564
Patterns::iterator git = m_pats.begin();
565
Patterns::iterator git_end = m_pats.end();
566
for (; git != git_end; git++) {
567
if (git->second == &a) {
568
apps_file << " [app]"<<git->first->toString()<<endl;
572
apps_file << "[app]"<<it->first->toString()<<endl;
574
if (a.workspace_remember) {
575
apps_file << " [Workspace]\t{" << a.workspace << "}" << endl;
577
if (a.head_remember) {
578
apps_file << " [Head]\t{" << a.head << "}" << endl;
580
if (a.dimensions_remember) {
581
apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl;
583
if (a.position_remember) {
584
apps_file << " [Position]\t(";
587
apps_file << "WINCENTER";
590
apps_file << "CENTER";
593
apps_file << "LOWERLEFT";
596
apps_file << "LOWERRIGHT";
599
apps_file << "UPPERRIGHT";
602
apps_file << "UPPERLEFT";
604
apps_file << ")\t{" << a.x << " " << a.y << "}" << endl;
606
if (a.shadedstate_remember) {
607
apps_file << " [Shaded]\t{" << ((a.shadedstate)?"yes":"no") << "}" << endl;
609
if (a.tabstate_remember) {
610
apps_file << " [Tab]\t\t{" << ((a.tabstate)?"yes":"no") << "}" << endl;
612
if (a.decostate_remember) {
613
switch (a.decostate) {
615
apps_file << " [Deco]\t{NONE}" << endl;
618
case (FluxboxWindow::DECORM_LAST - 1):
619
apps_file << " [Deco]\t{NORMAL}" << endl;
621
case (FluxboxWindow::DECORM_TITLEBAR
622
| FluxboxWindow::DECORM_ICONIFY
623
| FluxboxWindow::DECORM_MENU):
624
apps_file << " [Deco]\t{TOOL}" << endl;
626
case (FluxboxWindow::DECORM_TITLEBAR
627
| FluxboxWindow::DECORM_MENU):
628
apps_file << " [Deco]\t{TINY}" << endl;
630
case (FluxboxWindow::DECORM_BORDER
631
| FluxboxWindow::DECORM_MENU):
632
apps_file << " [Deco]\t{BORDER}" << endl;
635
apps_file << " [Deco]\t{0x"<<hex<<a.decostate<<dec<<"}"<<endl;
640
if (a.focushiddenstate_remember || a.iconhiddenstate_remember) {
641
if (a.focushiddenstate_remember && a.iconhiddenstate_remember &&
642
a.focushiddenstate && a.iconhiddenstate)
643
apps_file << " [Hidden]\t{" << ((a.focushiddenstate)?"yes":"no") << "}" << endl;
644
else if (a.focushiddenstate_remember) {
645
apps_file << " [FocusHidden]\t{" << ((a.focushiddenstate)?"yes":"no") << "}" << endl;
646
} else if (a.iconhiddenstate_remember) {
647
apps_file << " [IconHidden]\t{" << ((a.iconhiddenstate)?"yes":"no") << "}" << endl;
650
if (a.stuckstate_remember) {
651
apps_file << " [Sticky]\t{" << ((a.stuckstate)?"yes":"no") << "}" << endl;
653
if (a.jumpworkspace_remember) {
654
apps_file << " [Jump]\t{" << ((a.jumpworkspace)?"yes":"no") << "}" << endl;
656
if (a.layer_remember) {
657
apps_file << " [Layer]\t{" << a.layer << "}" << endl;
659
if (a.save_on_close_remember) {
660
apps_file << " [Close]\t{" << ((a.save_on_close)?"yes":"no") << "}" << endl;
662
apps_file << "[end]" << endl;
666
bool Remember::isRemembered(WinClient &winclient, Attribute attrib) {
667
Application *app = find(winclient);
668
if (!app) return false;
671
return app->workspace_remember;
674
return app->head_remember;
677
return app->dimensions_remember;
680
return app->position_remember;
682
case REM_FOCUSHIDDENSTATE:
683
return app->focushiddenstate_remember;
685
case REM_ICONHIDDENSTATE:
686
return app->iconhiddenstate_remember;
689
return app->stuckstate_remember;
692
return app->decostate_remember;
694
case REM_SHADEDSTATE:
695
return app->shadedstate_remember;
697
// case REM_TABSTATE:
698
// return app->tabstate_remember;
700
case REM_JUMPWORKSPACE:
701
return app->jumpworkspace_remember;
704
return app->layer_remember;
706
case REM_SAVEONCLOSE:
707
return app->save_on_close_remember;
711
return false; // should never get here
715
void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) {
716
FluxboxWindow *win = winclient.fbwindow();
718
Application *app = find(winclient);
720
app = add(winclient);
725
app->rememberWorkspace(win->workspaceNumber());
728
app->rememberHead(win->screen().getHead(win->fbWindow()));
731
app->rememberDimensions(win->width(), win->height());
734
app->rememberPosition(win->x(), win->y());
736
case REM_FOCUSHIDDENSTATE:
737
app->rememberFocusHiddenstate(win->isFocusHidden());
739
case REM_ICONHIDDENSTATE:
740
app->rememberIconHiddenstate(win->isIconHidden());
742
case REM_SHADEDSTATE:
743
app->rememberShadedstate(win->isShaded());
746
app->rememberDecostate(win->decorationMask());
749
app->rememberStuckstate(win->isStuck());
751
// case REM_TABSTATE:
753
case REM_JUMPWORKSPACE:
754
app->rememberJumpworkspace(true);
757
app->rememberLayer(win->layerNum());
759
case REM_SAVEONCLOSE:
760
app->rememberSaveOnClose(true);
769
void Remember::forgetAttrib(WinClient &winclient, Attribute attrib) {
770
FluxboxWindow *win = winclient.fbwindow();
772
Application *app = find(winclient);
774
app = add(winclient);
779
app->forgetWorkspace();
785
app->forgetDimensions();
788
app->forgetPosition();
790
case REM_FOCUSHIDDENSTATE:
791
app->forgetFocusHiddenstate();
793
case REM_ICONHIDDENSTATE:
794
app->forgetIconHiddenstate();
797
app->forgetStuckstate();
800
app->forgetDecostate();
802
case REM_SHADEDSTATE:
803
app->forgetShadedstate();
805
// case REM_TABSTATE:
807
case REM_JUMPWORKSPACE:
808
app->forgetJumpworkspace();
813
case REM_SAVEONCLOSE:
814
app->forgetSaveOnClose();
823
void Remember::setupFrame(FluxboxWindow &win) {
824
WinClient &winclient = win.winClient();
826
// we don't touch the window if it is a transient
830
if (winclient.transientFor())
833
Application *app = find(winclient);
835
return; // nothing to do
837
if (app->is_grouped && app->group == 0)
840
BScreen &screen = winclient.screen();
842
if (app->workspace_remember) {
843
// we use setWorkspace and not reassoc because we're still initialising
844
win.setWorkspace(app->workspace);
845
if (app->jumpworkspace_remember)
846
screen.changeWorkspaceID(app->workspace);
849
if (app->head_remember) {
850
win.screen().setOnHead<FluxboxWindow>(win, app->head);
853
if (app->decostate_remember)
854
win.setDecorationMask(app->decostate);
857
if (app->dimensions_remember)
858
win.resize(app->w, app->h);
860
int head = screen.getHead(win.fbWindow());
862
if (app->position_remember) {
866
case POS_UPPERLEFT: // upperleft corner
867
win.move(screen.getHeadX(head) + app->x,
868
screen.getHeadY(head) + app->y);
870
case POS_UPPERRIGHT: // upperright corner
871
win.move(screen.getHeadX(head) + screen.getHeadWidth(head) - win.width() - app->x,
872
screen.getHeadY(head) + app->y);
874
case POS_LOWERLEFT: // lowerleft corner
875
win.move(screen.getHeadX(head) + app->x,
876
screen.getHeadHeight(head) - win.height() - app->y);
878
case POS_LOWERRIGHT: // lowerright corner
879
win.move(screen.getHeadWidth(head) - win.width() - app->x,
880
screen.getHeadHeight(head) - win.height() - app->y);
882
case POS_CENTER: // center of the screen, windows topleft corner is on the center
883
win.move((screen.getHeadWidth(head) / 2) + app->x,
884
(screen.getHeadHeight(head) / 2) + app->y);
886
case POS_WINCENTER: // the window is centered REALLY upon the center
887
win.move((screen.getHeadWidth(head) / 2) - ( win.width() / 2 ) + app->x,
888
(screen.getHeadHeight(head) / 2) - ( win.height() / 2 ) + app->y);
893
if (app->shadedstate_remember)
894
// if inconsistent...
895
if (win.isShaded() && !app->shadedstate ||
896
!win.isShaded() && app->shadedstate)
897
win.shade(); // toggles
899
// external tabs aren't available atm...
900
//if (app->tabstate_remember) ...
902
if (app->stuckstate_remember)
903
// if inconsistent...
904
if (win.isStuck() && !app->stuckstate ||
905
!win.isStuck() && app->stuckstate)
906
win.stick(); // toggles
907
if (app->focushiddenstate_remember)
908
win.setFocusHidden(true);
909
if (app->iconhiddenstate_remember)
910
win.setIconHidden(true);
912
if (app->layer_remember)
913
win.moveToLayer(app->layer);
917
void Remember::setupClient(WinClient &winclient) {
919
Application *app = find(winclient);
921
return; // nothing to do
923
if (winclient.fbwindow() == 0 && app->is_grouped && app->group) {
924
app->group->attachClient(winclient);
928
void Remember::updateClientClose(WinClient &winclient) {
929
Application *app = find(winclient);
931
if (app && (app->save_on_close_remember && app->save_on_close)) {
933
for (int attrib = 0; attrib <= REM_LASTATTRIB; attrib++) {
934
if (isRemembered(winclient, (Attribute) attrib)) {
935
rememberAttrib(winclient, (Attribute) attrib);
942
// we need to get rid of references to this client
943
Clients::iterator wc_it = m_clients.find(&winclient);
945
if (wc_it != m_clients.end()) {
946
m_clients.erase(wc_it);
951
void Remember::initForScreen(BScreen &screen) {
952
// All windows get the remember menu.
954
screen.addExtraWindowMenu(_FBTEXT(Remember, MenuItemName, "Remember...", "Remember item in menu"),
955
createRememberMenu(screen));
959
void Remember::updateFrameClose(FluxboxWindow &win) {
960
// scan all applications and remove this fbw if it is a recorded group
961
Patterns::iterator it = m_pats.begin();
962
while (it != m_pats.end()) {
963
if (&win == it->second->group)
964
it->second->group = 0;