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
00027 #include "fluxbox.hh"
00028
00029 #include "I18n.hh"
00030 #include "Screen.hh"
00031 #include "Window.hh"
00032 #include "Workspace.hh"
00033 #include "AtomHandler.hh"
00034 #include "FbCommands.hh"
00035 #include "WinClient.hh"
00036 #include "Keys.hh"
00037 #include "FbAtoms.hh"
00038 #include "defaults.hh"
00039
00040 #include "FbTk/Image.hh"
00041 #include "FbTk/KeyUtil.hh"
00042 #include "FbTk/ImageControl.hh"
00043 #include "FbTk/EventManager.hh"
00044 #include "FbTk/StringUtil.hh"
00045 #include "FbTk/Resource.hh"
00046 #include "FbTk/SimpleCommand.hh"
00047 #include "FbTk/XrmDatabaseHelper.hh"
00048 #include "FbTk/Command.hh"
00049 #include "FbTk/RefCount.hh"
00050 #include "FbTk/SimpleCommand.hh"
00051
00052
00053 #ifndef _GNU_SOURCE
00054 #define _GNU_SOURCE
00055 #endif // _GNU_SOURCE
00056
00057 #ifdef HAVE_CONFIG_H
00058 #include "config.h"
00059 #endif // HAVE_CONFIG_H
00060
00061 #ifdef SLIT
00062 #include "Slit.hh"
00063 #endif // SLIT
00064 #ifdef USE_GNOME
00065 #include "Gnome.hh"
00066 #endif // USE_GNOME
00067 #ifdef USE_NEWWMSPEC
00068 #include "Ewmh.hh"
00069 #endif // USE_NEWWMSPEC
00070 #ifdef REMEMBER
00071 #include "Remember.hh"
00072 #endif // REMEMBER
00073 #ifdef USE_TOOLBAR
00074 #include "Toolbar.hh"
00075 #else
00076 class Toolbar { };
00077 #endif // USE_TOOLBAR
00078
00079
00080 #include <X11/Xlib.h>
00081 #include <X11/Xutil.h>
00082 #include <X11/Xresource.h>
00083 #include <X11/Xatom.h>
00084 #include <X11/keysym.h>
00085
00086
00087 #ifdef SHAPE
00088 #include <X11/extensions/shape.h>
00089 #endif // SHAPE
00090 #ifdef HAVE_RANDR
00091 #include <X11/extensions/Xrandr.h>
00092 #endif // HAVE_RANDR
00093
00094
00095
00096 #include <cstdio>
00097 #include <cstdlib>
00098 #include <cstring>
00099
00100 #ifdef HAVE_UNISTD_H
00101 #include <sys/types.h>
00102 #include <unistd.h>
00103 #endif // HAVE_UNISTD_H
00104
00105 #ifdef HAVE_SYS_PARAM_H
00106 #include <sys/param.h>
00107 #endif // HAVE_SYS_PARAM_H
00108
00109 #ifdef HAVE_SYS_SELECT_H
00110 #include <sys/select.h>
00111 #endif // HAVE_SYS_SELECT_H
00112
00113 #ifdef HAVE_SYS_STAT_H
00114 #include <sys/types.h>
00115 #include <sys/stat.h>
00116 #endif // HAVE_SYS_STAT_H
00117
00118 #ifdef TIME_WITH_SYS_TIME
00119 #include <sys/time.h>
00120 #include <time.h>
00121 #else // !TIME_WITH_SYS_TIME
00122 #ifdef HAVE_SYS_TIME_H
00123 #include <sys/time.h>
00124 #else // !HAVE_SYS_TIME_H
00125 #include <time.h>
00126 #endif // HAVE_SYS_TIME_H
00127 #endif // TIME_WITH_SYS_TIME
00128
00129 #include <sys/wait.h>
00130
00131 #include <iostream>
00132 #include <string>
00133 #include <memory>
00134 #include <algorithm>
00135 #include <typeinfo>
00136
00137 using namespace std;
00138 using namespace FbTk;
00139
00140
00141
00142
00143
00144 template<>
00145 void FbTk::Resource<int>::
00146 setFromString(const char* strval) {
00147 int val;
00148 if (sscanf(strval, "%d", &val)==1)
00149 *this = val;
00150 }
00151
00152 template<>
00153 void FbTk::Resource<std::string>::
00154 setFromString(const char *strval) {
00155 *this = strval;
00156 }
00157
00158 template<>
00159 void FbTk::Resource<bool>::
00160 setFromString(char const *strval) {
00161 if (strcasecmp(strval, "true")==0)
00162 *this = true;
00163 else
00164 *this = false;
00165 }
00166
00167
00168
00169 template<>
00170 void FbTk::Resource<Fluxbox::TitlebarList>::
00171 setFromString(char const *strval) {
00172 vector<std::string> val;
00173 StringUtil::stringtok(val, strval);
00174 int size=val.size();
00175
00176 m_value.clear();
00177
00178 for (int i=0; i<size; i++) {
00179 if (strcasecmp(val[i].c_str(), "Maximize")==0)
00180 m_value.push_back(Fluxbox::MAXIMIZE);
00181 else if (strcasecmp(val[i].c_str(), "Minimize")==0)
00182 m_value.push_back(Fluxbox::MINIMIZE);
00183 else if (strcasecmp(val[i].c_str(), "Shade")==0)
00184 m_value.push_back(Fluxbox::SHADE);
00185 else if (strcasecmp(val[i].c_str(), "Stick")==0)
00186 m_value.push_back(Fluxbox::STICK);
00187 else if (strcasecmp(val[i].c_str(), "Menu")==0)
00188 m_value.push_back(Fluxbox::MENU);
00189 else if (strcasecmp(val[i].c_str(), "Close")==0)
00190 m_value.push_back(Fluxbox::CLOSE);
00191 }
00192 }
00193
00194 template<>
00195 void FbTk::Resource<unsigned int>::
00196 setFromString(const char *strval) {
00197 if (sscanf(strval, "%ul", &m_value) != 1)
00198 setDefaultValue();
00199 }
00200
00201
00202
00203
00204 template<>
00205 std::string FbTk::Resource<bool>::
00206 getString() {
00207 return std::string(**this == true ? "true" : "false");
00208 }
00209
00210 template<>
00211 std::string FbTk::Resource<int>::
00212 getString() {
00213 char strval[256];
00214 sprintf(strval, "%d", **this);
00215 return std::string(strval);
00216 }
00217
00218 template<>
00219 std::string FbTk::Resource<std::string>::
00220 getString() { return **this; }
00221
00222
00223 template<>
00224 std::string FbTk::Resource<Fluxbox::TitlebarList>::
00225 getString() {
00226 string retval;
00227 int size=m_value.size();
00228 for (int i=0; i<size; i++) {
00229 switch (m_value[i]) {
00230 case Fluxbox::SHADE:
00231 retval.append("Shade");
00232 break;
00233 case Fluxbox::MINIMIZE:
00234 retval.append("Minimize");
00235 break;
00236 case Fluxbox::MAXIMIZE:
00237 retval.append("Maximize");
00238 break;
00239 case Fluxbox::CLOSE:
00240 retval.append("Close");
00241 break;
00242 case Fluxbox::STICK:
00243 retval.append("Stick");
00244 break;
00245 case Fluxbox::MENU:
00246 retval.append("Menu");
00247 break;
00248 default:
00249 break;
00250 }
00251 retval.append(" ");
00252 }
00253
00254 return retval;
00255 }
00256
00257 template<>
00258 string FbTk::Resource<unsigned int>::
00259 getString() {
00260 char tmpstr[128];
00261 sprintf(tmpstr, "%ul", m_value);
00262 return string(tmpstr);
00263 }
00264
00265 template<>
00266 void FbTk::Resource<Fluxbox::Layer>::
00267 setFromString(const char *strval) {
00268 int tempnum = 0;
00269 if (sscanf(strval, "%d", &tempnum) == 1)
00270 m_value = tempnum;
00271 else if (strcasecmp(strval, "Menu") == 0)
00272 m_value = Fluxbox::instance()->getMenuLayer();
00273 else if (strcasecmp(strval, "AboveDock") == 0)
00274 m_value = Fluxbox::instance()->getAboveDockLayer();
00275 else if (strcasecmp(strval, "Dock") == 0)
00276 m_value = Fluxbox::instance()->getDockLayer();
00277 else if (strcasecmp(strval, "Top") == 0)
00278 m_value = Fluxbox::instance()->getTopLayer();
00279 else if (strcasecmp(strval, "Normal") == 0)
00280 m_value = Fluxbox::instance()->getNormalLayer();
00281 else if (strcasecmp(strval, "Bottom") == 0)
00282 m_value = Fluxbox::instance()->getBottomLayer();
00283 else if (strcasecmp(strval, "Desktop") == 0)
00284 m_value = Fluxbox::instance()->getDesktopLayer();
00285 else
00286 setDefaultValue();
00287 }
00288
00289
00290 template<>
00291 string FbTk::Resource<Fluxbox::Layer>::
00292 getString() {
00293
00294 if (m_value.getNum() == Fluxbox::instance()->getMenuLayer())
00295 return string("Menu");
00296 else if (m_value.getNum() == Fluxbox::instance()->getAboveDockLayer())
00297 return string("AboveDock");
00298 else if (m_value.getNum() == Fluxbox::instance()->getDockLayer())
00299 return string("Dock");
00300 else if (m_value.getNum() == Fluxbox::instance()->getTopLayer())
00301 return string("Top");
00302 else if (m_value.getNum() == Fluxbox::instance()->getNormalLayer())
00303 return string("Normal");
00304 else if (m_value.getNum() == Fluxbox::instance()->getBottomLayer())
00305 return string("Bottom");
00306 else if (m_value.getNum() == Fluxbox::instance()->getDesktopLayer())
00307 return string("Desktop");
00308 else {
00309 char tmpstr[128];
00310 sprintf(tmpstr, "%d", m_value.getNum());
00311 return string(tmpstr);
00312 }
00313 }
00314 template<>
00315 void FbTk::Resource<long>::
00316 setFromString(const char *strval) {
00317 if (sscanf(strval, "%ld", &m_value) != 1)
00318 setDefaultValue();
00319 }
00320
00321
00322 string FbTk::Resource<long>::
00323 getString() {
00324 char tmpstr[128];
00325 sprintf(tmpstr, "%ld", m_value);
00326 return string(tmpstr);
00327 }
00328
00329 static Window last_bad_window = None;
00330 namespace {
00331 void copyFile(const std::string &from, const std::string &to) {
00332 ifstream from_file(from.c_str());
00333 ofstream to_file(to.c_str());
00334
00335 if (! to_file.good()) {
00336 cerr<<"Can't write file: "<<to<<endl;
00337 } else if (from_file.good()) {
00338 to_file<<from_file.rdbuf();
00339 } else {
00340 cerr<<"Can't copy from "<<from<<" to "<<to<<endl;
00341 }
00342 }
00343
00344 }
00345
00346 static int handleXErrors(Display *d, XErrorEvent *e) {
00347 #ifdef DEBUG
00348
00349
00350
00351
00352
00353
00354
00355 #endif // !DEBUG
00356
00357 if (e->error_code == BadWindow)
00358 last_bad_window = e->resourceid;
00359
00360 return False;
00361 }
00362
00363
00364
00365 Fluxbox *Fluxbox::s_singleton=0;
00366
00367
00368
00369 Fluxbox::Titlebar Fluxbox::s_titlebar_left[] = {STICK};
00370 Fluxbox::Titlebar Fluxbox::s_titlebar_right[] = {MINIMIZE, MAXIMIZE, CLOSE};
00371
00372 Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfilename)
00373 : FbTk::App(dpy_name),
00374 m_fbatoms(new FbAtoms()),
00375 m_resourcemanager(rcfilename, true),
00376
00377 m_screen_rm(m_resourcemanager),
00378 m_rc_tabs(m_resourcemanager, true, "session.tabs", "Session.Tabs"),
00379 m_rc_ignoreborder(m_resourcemanager, false, "session.ignoreBorder", "Session.IgnoreBorder"),
00380 m_rc_colors_per_channel(m_resourcemanager, 4,
00381 "session.colorsPerChannel", "Session.ColorsPerChannel"),
00382 m_rc_numlayers(m_resourcemanager, 13, "session.numLayers", "Session.NumLayers"),
00383 m_rc_double_click_interval(m_resourcemanager, 250, "session.doubleClickInterval", "Session.DoubleClickInterval"),
00384 m_rc_update_delay_time(m_resourcemanager, 0, "session.updateDelayTime", "Session.UpdateDelayTime"),
00385 m_rc_stylefile(m_resourcemanager, "", "session.styleFile", "Session.StyleFile"),
00386 m_rc_menufile(m_resourcemanager, DEFAULTMENU, "session.menuFile", "Session.MenuFile"),
00387 m_rc_keyfile(m_resourcemanager, DEFAULTKEYSFILE, "session.keyFile", "Session.KeyFile"),
00388 m_rc_slitlistfile(m_resourcemanager, "", "session.slitlistFile", "Session.SlitlistFile"),
00389 m_rc_groupfile(m_resourcemanager, "", "session.groupFile", "Session.GroupFile"),
00390 m_rc_titlebar_left(m_resourcemanager,
00391 TitlebarList(&s_titlebar_left[0], &s_titlebar_left[1]),
00392 "session.titlebar.left", "Session.Titlebar.Left"),
00393 m_rc_titlebar_right(m_resourcemanager,
00394 TitlebarList(&s_titlebar_right[0], &s_titlebar_right[3]),
00395 "session.titlebar.right", "Session.Titlebar.Right"),
00396 m_rc_cache_life(m_resourcemanager, 5, "session.cacheLife", "Session.CacheLife"),
00397 m_rc_cache_max(m_resourcemanager, 200, "session.cacheMax", "Session.CacheMax"),
00398 m_rc_auto_raise_delay(m_resourcemanager, 250, "session.autoRaiseDelay", "Session.AutoRaiseDelay"),
00399 m_rc_use_mod1(m_resourcemanager, true, "session.useMod1", "Session.UseMod1"),
00400 m_focused_window(0), m_masked_window(0),
00401 m_mousescreen(0),
00402 m_keyscreen(0),
00403 m_watching_screen(0), m_watch_keyrelease(0),
00404 m_last_time(0),
00405 m_masked(0),
00406 m_rc_file(rcfilename ? rcfilename : ""),
00407 m_argv(argv), m_argc(argc),
00408 m_starting(true),
00409 m_shutdown(false),
00410 m_server_grabs(0),
00411 m_randr_event_type(0),
00412 m_RC_PATH("fluxbox"),
00413 m_RC_INIT_FILE("init") {
00414
00415
00416 if (s_singleton != 0)
00417 throw string("Fatal! There can only one instance of fluxbox class.");
00418
00419 if (display() == 0) {
00421 throw string("Can not connect to X server.\n"
00422 "Make sure you started X before you start Fluxbox.");
00423 }
00424
00425
00426 m_kwm1_dockwindow = XInternAtom(FbTk::App::instance()->display(),
00427 "KWM_DOCKWINDOW", False);
00428
00429 m_kwm2_dockwindow = XInternAtom(FbTk::App::instance()->display(),
00430 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
00431
00432 XSetErrorHandler((XErrorHandler) handleXErrors);
00433
00434
00435 SignalHandler &sigh = SignalHandler::instance();
00436 sigh.registerHandler(SIGSEGV, this);
00437 sigh.registerHandler(SIGFPE, this);
00438 sigh.registerHandler(SIGTERM, this);
00439 sigh.registerHandler(SIGINT, this);
00440 sigh.registerHandler(SIGCHLD, this);
00441 sigh.registerHandler(SIGHUP, this);
00442 sigh.registerHandler(SIGUSR1, this);
00443 sigh.registerHandler(SIGUSR2, this);
00444
00445
00446
00447
00448
00449
00450 FbTk::RefCount<FbTk::Command> reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure));
00451 timeval to;
00452 to.tv_sec = 0;
00453 to.tv_usec = 1;
00454 m_reconfig_timer.setTimeout(to);
00455 m_reconfig_timer.setCommand(reconfig_cmd);
00456 m_reconfig_timer.fireOnce(true);
00457
00458 Display *disp = FbTk::App::instance()->display();
00459
00460 s_singleton = this;
00461 m_have_shape = false;
00462 m_shape_eventbase = 0;
00463 #ifdef SHAPE
00464 int shape_err;
00465 m_have_shape = XShapeQueryExtension(disp, &m_shape_eventbase, &shape_err);
00466 #endif // SHAPE
00467
00468 #ifdef HAVE_RANDR
00469
00470 int randr_error_base;
00471 XRRQueryExtension(disp, &m_randr_event_type, &randr_error_base);
00472 #endif // HAVE_RANDR
00473
00474 load_rc();
00475
00476 FbTk::ThemeManager::instance().load(getStyleFilename());
00477
00478
00479 #ifdef USE_GNOME
00480 addAtomHandler(new Gnome());
00481 #endif //USE_GNOME
00482
00483 #ifdef USE_NEWWMSPEC
00484 addAtomHandler(new Ewmh());
00485 #endif // USE_NEWWMSPEC
00486
00487 #ifdef REMEMBER
00488 addAtomHandler(new Remember());
00489 #endif // REMEMBER
00490
00491 grab();
00492
00493 setupConfigFiles();
00494
00495 if (! XSupportsLocale())
00496 cerr<<"Warning: X server does not support locale"<<endl;
00497
00498 if (XSetLocaleModifiers("") == 0)
00499 cerr<<"Warning: cannot set locale modifiers"<<endl;
00500
00501
00502 #ifdef HAVE_GETPID
00503 m_fluxbox_pid = XInternAtom(disp, "_BLACKBOX_PID", False);
00504 #endif // HAVE_GETPID
00505
00506
00507 for (int i = 0; i < ScreenCount(display()); i++) {
00508 char scrname[128], altscrname[128];
00509 sprintf(scrname, "session.screen%d", i);
00510 sprintf(altscrname, "session.Screen%d", i);
00511 BScreen *screen = new BScreen(m_screen_rm.lock(),
00512
00513 scrname, altscrname,
00514 i, getNumberOfLayers());
00515 if (! screen->isScreenManaged()) {
00516 delete screen;
00517 continue;
00518 }
00519
00520 #ifdef HAVE_GETPID
00521 pid_t bpid = getpid();
00522
00523 screen->rootWindow().changeProperty(getFluxboxPidAtom(), XA_CARDINAL,
00524 sizeof(pid_t) * 8, PropModeReplace,
00525 (unsigned char *) &bpid, 1);
00526 #endif // HAVE_GETPID
00527
00528 #ifdef HAVE_RANDR
00529
00530
00531 #ifdef X_RRScreenChangeSelectInput
00532
00533 XRRScreenChangeSelectInput(disp, screen->rootWindow().window(), True);
00534 #else
00535 XRRSelectInput(disp, screen->rootWindow().window(),
00536 RRScreenChangeNotifyMask);
00537 #endif // X_RRScreenChangeSelectInput
00538
00539 #endif // HAVE_RANDR
00540
00541 m_screen_list.push_back(screen);
00542 #ifdef USE_TOOLBAR
00543 m_toolbars.push_back(new Toolbar(*screen,
00544 *screen->layerManager().getLayer(Fluxbox::instance()->getNormalLayer())));
00545 #endif // USE_TOOLBAR
00546
00547
00548 screen->currentWorkspaceSig().attach(this);
00549 screen->workspaceCountSig().attach(this);
00550 screen->workspaceNamesSig().attach(this);
00551 screen->clientListSig().attach(this);
00552
00553
00554 for (size_t atomh=0; atomh<m_atomhandler.size(); ++atomh) {
00555 m_atomhandler[atomh]->initForScreen(*screen);
00556 }
00557
00558 revertFocus(*screen);
00559
00560 }
00561
00562
00563 m_keyscreen = m_mousescreen = m_screen_list.front();
00564
00565 if (m_screen_list.size() == 0) {
00567 throw string("Couldn't find screens to manage.\n"
00568 "Make sure you don't have another window manager running.");
00569 }
00570
00571
00572 FbTk::ThemeManager::instance().load(getStyleFilename());
00573
00574 XSynchronize(disp, False);
00575 sync(false);
00576
00577 m_reconfigure_wait = m_reread_menu_wait = false;
00578
00579
00580 m_key.reset(new Keys(StringUtil::expandFilename(*m_rc_keyfile).c_str()));
00581
00582 m_resourcemanager.unlock();
00583 ungrab();
00584
00585 #ifdef DEBUG
00586 if (m_resourcemanager.lockDepth() != 0)
00587 cerr<<"--- resource manager lockdepth = "<<m_resourcemanager.lockDepth()<<endl;
00588 #endif //DEBUG
00589 m_starting = false;
00590
00591
00592
00593
00594
00595 }
00596
00597
00598 Fluxbox::~Fluxbox() {
00599
00600 while (!m_toolbars.empty()) {
00601 delete m_toolbars.back();
00602 m_toolbars.pop_back();
00603 }
00604
00605
00606 while (!m_atomhandler.empty()) {
00607 delete m_atomhandler.back();
00608 m_atomhandler.pop_back();
00609 }
00610
00611 while (!m_screen_list.empty()) {
00612 delete m_screen_list.back();
00613 m_screen_list.pop_back();
00614 }
00615
00616 clearMenuFilenames();
00617 }
00618
00619 void Fluxbox::eventLoop() {
00620 Display *disp = display();
00621 while (!m_shutdown) {
00622 if (XPending(disp)) {
00623 XEvent e;
00624 XNextEvent(disp, &e);
00625
00626 if (last_bad_window != None && e.xany.window == last_bad_window &&
00627 e.type != DestroyNotify) {
00628 #ifdef DEBUG
00629 cerr<<"Fluxbox::eventLoop(): removing bad window from event queue"<<endl;
00630 #endif // DEBUG
00631 } else {
00632 last_bad_window = None;
00633 handleEvent(&e);
00634 }
00635 } else {
00636 FbTk::Timer::updateTimers(ConnectionNumber(disp));
00637 }
00638 }
00639 }
00640
00641 bool Fluxbox::validateWindow(Window window) const {
00642 XEvent event;
00643 if (XCheckTypedWindowEvent(display(), window, DestroyNotify, &event)) {
00644 XPutBackEvent(display(), &event);
00645 return false;
00646 }
00647
00648 return true;
00649 }
00650
00651 void Fluxbox::grab() {
00652 if (! m_server_grabs++)
00653 XGrabServer(display());
00654 }
00655
00656 void Fluxbox::ungrab() {
00657 if (! --m_server_grabs)
00658 XUngrabServer(display());
00659 if (m_server_grabs < 0)
00660 m_server_grabs = 0;
00661 }
00662
00667 void Fluxbox::setupConfigFiles() {
00668
00669 bool create_init = false, create_keys = false, create_menu = false;
00670
00671 string dirname = getenv("HOME") + string("/.") + string(m_RC_PATH) + "/";
00672 string init_file, keys_file, menu_file, slitlist_file;
00673 init_file = dirname + m_RC_INIT_FILE;
00674 keys_file = dirname + "keys";
00675 menu_file = dirname + "menu";
00676
00677 struct stat buf;
00678
00679
00680 if (! stat(dirname.c_str(), &buf)) {
00681
00682
00683 if (stat(init_file.c_str(), &buf))
00684 create_init = true;
00685 if (stat(keys_file.c_str(), &buf))
00686 create_keys = true;
00687 if (stat(menu_file.c_str(), &buf))
00688 create_menu = true;
00689
00690 } else {
00691 #ifdef DEBUG
00692 cerr <<__FILE__<<"("<<__LINE__<<"): Creating dir: " << dirname.c_str() << endl;
00693 #endif // DEBUG
00694
00695
00696 if (mkdir(dirname.c_str(), 0700)) {
00697 cerr << "Can't create " << dirname << " directory!" << endl;
00698 return;
00699 }
00700
00701
00702 create_init = create_keys = create_menu = true;
00703 }
00704
00705
00706
00707 if (create_keys)
00708 copyFile(DEFAULTKEYSFILE, keys_file);
00709
00710
00711 if (create_menu)
00712 copyFile(DEFAULTMENU, menu_file);
00713
00714
00715 if (create_init)
00716 copyFile(DEFAULT_INITFILE, init_file);
00717
00718 }
00719
00720 void Fluxbox::handleEvent(XEvent * const e) {
00721 m_last_event = *e;
00722
00723
00724
00725 if ((m_masked == e->xany.window) && m_masked_window) {
00726 if (e->type == MotionNotify) {
00727 m_last_time = e->xmotion.time;
00728 m_masked_window->motionNotifyEvent(e->xmotion);
00729 return;
00730 } else if (e->type == ButtonRelease) {
00731 e->xbutton.window = m_masked_window->fbWindow().window();
00732 }
00733
00734 }
00735
00736
00737 if (e->type == KeyPress ||
00738 e->type == KeyRelease) {
00739 m_keyscreen = searchScreen(e->xkey.root);
00740 } else if (e->type == ButtonPress ||
00741 e->type == ButtonRelease ||
00742 e->type == MotionNotify ) {
00743 if (e->type == MotionNotify)
00744 m_last_time = e->xmotion.time;
00745 else
00746 m_last_time = e->xbutton.time;
00747
00748 m_mousescreen = searchScreen(e->xbutton.root);
00749 } else if (e->type == EnterNotify ||
00750 e->type == LeaveNotify) {
00751 m_last_time = e->xcrossing.time;
00752 m_mousescreen = searchScreen(e->xcrossing.root);
00753 } else if (e->type == PropertyNotify)
00754 m_last_time = e->xproperty.time;
00755
00756
00757
00758 FbTk::EventManager::instance()->handleEvent(*e);
00759
00760 switch (e->type) {
00761 case ButtonRelease:
00762 case ButtonPress:
00763 handleButtonEvent(e->xbutton);
00764 break;
00765 case ConfigureRequest: {
00766 WinClient *winclient = (WinClient *) 0;
00767
00768 if ((winclient = searchWindow(e->xconfigurerequest.window))) {
00769
00770 } else {
00771 grab();
00772
00773 if (validateWindow(e->xconfigurerequest.window)) {
00774 XWindowChanges xwc;
00775
00776 xwc.x = e->xconfigurerequest.x;
00777 xwc.y = e->xconfigurerequest.y;
00778 xwc.width = e->xconfigurerequest.width;
00779 xwc.height = e->xconfigurerequest.height;
00780 xwc.border_width = e->xconfigurerequest.border_width;
00781 xwc.sibling = e->xconfigurerequest.above;
00782 xwc.stack_mode = e->xconfigurerequest.detail;
00783
00784 XConfigureWindow(FbTk::App::instance()->display(),
00785 e->xconfigurerequest.window,
00786 e->xconfigurerequest.value_mask, &xwc);
00787 }
00788
00789 ungrab();
00790 }
00791
00792 }
00793 break;
00794 case MapRequest: {
00795
00796 #ifdef DEBUG
00797 cerr<<"MapRequest for 0x"<<hex<<e->xmaprequest.window<<dec<<endl;
00798 #endif // DEBUG
00799
00800 WinClient *winclient = searchWindow(e->xmaprequest.window);
00801 FluxboxWindow *win = 0;
00802
00803 if (! winclient) {
00805 BScreen *scr = searchScreen(e->xmaprequest.parent);
00806 if (scr != 0)
00807 win = scr->createWindow(e->xmaprequest.window);
00808 else
00809 cerr<<"Fluxbox Warning! Could not find screen to map window on!"<<endl;
00810
00811 } else {
00812 win = winclient->fbwindow();
00813 }
00814
00815
00816 if (win)
00817 win->mapRequestEvent(e->xmaprequest);
00818 }
00819 break;
00820 case MapNotify: {
00821
00822 } break;
00823 case UnmapNotify:
00824 handleUnmapNotify(e->xunmap);
00825 break;
00826 case MappingNotify:
00827
00828 #ifdef DEBUG
00829 cerr<<__FILE__<<"("<<__FUNCTION__<<"): MappingNotify"<<endl;
00830 #endif // DEBUG
00831
00832 FbTk::KeyUtil::instance().init();
00833
00834 break;
00835 case CreateNotify:
00836 break;
00837 case DestroyNotify: {
00838 WinClient *winclient = searchWindow(e->xdestroywindow.window);
00839 if (winclient != 0) {
00840 FluxboxWindow *win = winclient->fbwindow();
00841 if (win)
00842 win->destroyNotifyEvent(e->xdestroywindow);
00843
00844 delete winclient;
00845
00846 if (win && win->numClients() == 0)
00847 delete win;
00848 }
00849
00850 }
00851 break;
00852 case MotionNotify:
00853 m_last_time = e->xmotion.time;
00854 break;
00855 case PropertyNotify: {
00856 m_last_time = e->xproperty.time;
00857 WinClient *winclient = searchWindow(e->xproperty.window);
00858 if (winclient == 0)
00859 break;
00860
00861
00862 for (size_t i=0; i<m_atomhandler.size(); ++i) {
00863 if (m_atomhandler[i]->propertyNotify(*winclient, e->xproperty.atom))
00864 break;
00865 }
00866 } break;
00867 case EnterNotify: {
00868 m_last_time = e->xcrossing.time;
00869 BScreen *screen = 0;
00870
00871 if (e->xcrossing.mode == NotifyGrab)
00872 break;
00873
00874 if ((e->xcrossing.window == e->xcrossing.root) &&
00875 (screen = searchScreen(e->xcrossing.window))) {
00876 screen->imageControl().installRootColormap();
00877
00878 }
00879
00880 } break;
00881 case LeaveNotify:
00882 m_last_time = e->xcrossing.time;
00883 break;
00884 case Expose:
00885 break;
00886 case KeyRelease:
00887 case KeyPress:
00888 handleKeyEvent(e->xkey);
00889 break;
00890 case ColormapNotify: {
00891 BScreen *screen = searchScreen(e->xcolormap.window);
00892
00893 if (screen != 0) {
00894 screen->setRootColormapInstalled((e->xcolormap.state ==
00895 ColormapInstalled) ? true : false);
00896 }
00897 } break;
00898 case FocusIn: {
00899
00900
00901
00902 if (e->xfocus.mode == NotifyGrab ||
00903 e->xfocus.detail == NotifyPointer ||
00904 e->xfocus.detail == NotifyInferior)
00905 break;
00906
00907 WinClient *winclient = searchWindow(e->xfocus.window);
00908 if (winclient && m_focused_window != winclient)
00909 setFocusedWindow(winclient);
00910
00911 } break;
00912 case FocusOut:{
00913
00914
00915 if (e->xfocus.mode == NotifyGrab ||
00916 e->xfocus.detail == NotifyPointer ||
00917 e->xfocus.detail == NotifyInferior)
00918 break;
00919
00920 WinClient *winclient = searchWindow(e->xfocus.window);
00921 if (winclient == 0 && FbTk::Menu::focused() == 0) {
00922 #ifdef DEBUG
00923 cerr<<__FILE__<<"("<<__FUNCTION__<<") Focus out is not a FluxboxWindow !!"<<endl;
00924 #endif // DEBUG
00925 } else if (winclient && winclient == m_focused_window)
00926 setFocusedWindow(0);
00927 }
00928 break;
00929 case ClientMessage:
00930 handleClientMessage(e->xclient);
00931 break;
00932 default: {
00933 #ifdef HAVE_RANDR
00934 if (e->type == m_randr_event_type) {
00935
00936 BScreen *scr = searchScreen(e->xany.window);
00937 if (scr != 0)
00938 scr->updateSize();
00939 }
00940 #endif // HAVE_RANDR
00941
00942 }
00943
00944 }
00945 }
00946
00947 void Fluxbox::handleButtonEvent(XButtonEvent &be) {
00948
00949 switch (be.type) {
00950 case ButtonPress: {
00951 m_last_time = be.time;
00952
00953 BScreen *screen = searchScreen(be.window);
00954 if (screen == 0)
00955 break;
00956
00957 screen->hideMenus();
00958
00959
00960
00961
00962
00963 if (FbTk::KeyUtil::instance().cleanMods(be.state) != 0)
00964 return;
00965
00966 if (be.button == 1) {
00967 if (! screen->isRootColormapInstalled())
00968 screen->imageControl().installRootColormap();
00969
00970 if (screen->getWorkspacemenu().isVisible())
00971 screen->getWorkspacemenu().hide();
00972 if (screen->getRootmenu().isVisible())
00973 screen->getRootmenu().hide();
00974
00975 } else if (be.button == 2) {
00976 int mx = be.x_root -
00977 (screen->getWorkspacemenu().width() / 2);
00978 int my = be.y_root -
00979 (screen->getWorkspacemenu().titleHeight() / 2);
00980
00981 if (mx < 0) mx = 0;
00982 if (my < 0) my = 0;
00983
00984 if (mx + screen->getWorkspacemenu().width() >
00985 screen->width()) {
00986 mx = screen->width()-1 -
00987 screen->getWorkspacemenu().width() -
00988 2*screen->getWorkspacemenu().fbwindow().borderWidth();
00989 }
00990
00991 if (my + screen->getWorkspacemenu().height() >
00992 screen->height()) {
00993 my = screen->height()-1 -
00994 screen->getWorkspacemenu().height() -
00995 2*screen->getWorkspacemenu().fbwindow().borderWidth();
00996 }
00997 screen->getWorkspacemenu().move(mx, my);
00998
00999 if (! screen->getWorkspacemenu().isVisible()) {
01000 screen->getWorkspacemenu().removeParent();
01001 screen->getWorkspacemenu().show();
01002 }
01003 } else if (be.button == 3) {
01004
01005
01006 int mx = be.x_root -
01007 (screen->getRootmenu().width() / 2);
01008 int my = be.y_root -
01009 (screen->getRootmenu().titleHeight() / 2);
01010 int borderw = screen->getRootmenu().fbwindow().borderWidth();
01011
01012 if (mx < 0) mx = 0;
01013 if (my < 0) my = 0;
01014
01015 if (mx + screen->getRootmenu().width() + 2*borderw > screen->width()) {
01016 mx = screen->width() -
01017 screen->getRootmenu().width() -
01018 2*borderw;
01019 }
01020
01021 if (my + screen->getRootmenu().height() + 2*borderw >
01022 screen->height()) {
01023 my = screen->height() -
01024 screen->getRootmenu().height() -
01025 2*borderw;
01026 }
01027 screen->getRootmenu().move(mx, my);
01028
01029 if (! screen->getRootmenu().isVisible()) {
01030 checkMenu();
01031 screen->getRootmenu().show();
01032 }
01033 } else if (screen->isDesktopWheeling() && be.button == 4) {
01034 screen->nextWorkspace(1);
01035 } else if (screen->isDesktopWheeling() && be.button == 5) {
01036 screen->prevWorkspace(1);
01037 }
01038
01039 } break;
01040 case ButtonRelease:
01041 m_last_time = be.time;
01042 break;
01043 default:
01044 break;
01045 }
01046 }
01047
01048 void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) {
01049
01050
01051 WinClient *winclient = 0;
01052
01053 BScreen *screen = searchScreen(ue.event);
01054
01055 if ( ue.event != ue.window && (screen != 0 || !ue.send_event))
01056 return;
01057
01058 if ((winclient = searchWindow(ue.window)) != 0) {
01059
01060 if (winclient != 0) {
01061 FluxboxWindow *win = winclient->fbwindow();
01062
01063 if (!win) {
01064 delete winclient;
01065 return;
01066 }
01067
01068
01069 win->unmapNotifyEvent(ue);
01070
01071 winclient = 0;
01072
01073
01074 if (win->numClients() == 0) {
01075 delete win;
01076 win = 0;
01077 }
01078 }
01079 }
01080
01081 }
01082
01086 void Fluxbox::handleClientMessage(XClientMessageEvent &ce) {
01087 #ifdef DEBUG
01088 char * atom = 0;
01089 if (ce.message_type)
01090 atom = XGetAtomName(FbTk::App::instance()->display(), ce.message_type);
01091
01092 cerr<<__FILE__<<"("<<__LINE__<<"): ClientMessage. data.l[0]=0x"<<hex<<ce.data.l[0]<<
01093 " message_type=0x"<<ce.message_type<<dec<<" = \""<<atom<<"\""<<endl;
01094
01095 if (ce.message_type && atom) XFree((char *) atom);
01096
01097 #endif // DEBUG
01098
01099 if (ce.format != 32)
01100 return;
01101
01102 if (ce.message_type == m_fbatoms->getWMChangeStateAtom()) {
01103 WinClient *winclient = searchWindow(ce.window);
01104 if (! winclient || !winclient->fbwindow() || ! winclient->validateClient())
01105 return;
01106
01107 if (ce.data.l[0] == IconicState)
01108 winclient->fbwindow()->iconify();
01109 if (ce.data.l[0] == NormalState)
01110 winclient->fbwindow()->deiconify();
01111 } else if (ce.message_type == m_fbatoms->getFluxboxChangeWorkspaceAtom()) {
01112 BScreen *screen = searchScreen(ce.window);
01113
01114 if (screen && ce.data.l[0] >= 0 &&
01115 ce.data.l[0] < (signed)screen->getCount())
01116 screen->changeWorkspaceID(ce.data.l[0]);
01117
01118 } else if (ce.message_type == m_fbatoms->getFluxboxChangeWindowFocusAtom()) {
01119 WinClient *winclient = searchWindow(ce.window);
01120 if (winclient) {
01121 FluxboxWindow *win = winclient->fbwindow();
01122 if (win && win->isVisible())
01123 win->setCurrentClient(*winclient, true);
01124 }
01125 } else if (ce.message_type == m_fbatoms->getFluxboxCycleWindowFocusAtom()) {
01126 BScreen *screen = searchScreen(ce.window);
01127
01128 if (screen) {
01129 if (! ce.data.l[0])
01130 screen->prevFocus();
01131 else
01132 screen->nextFocus();
01133 }
01134 } else if (ce.message_type == m_fbatoms->getFluxboxChangeAttributesAtom()) {
01135 WinClient *winclient = searchWindow(ce.window);
01136 FluxboxWindow *win = 0;
01137 if (winclient && (win = winclient->fbwindow()) && winclient->validateClient()) {
01138 FluxboxWindow::BlackboxHints net;
01139 net.flags = ce.data.l[0];
01140 net.attrib = ce.data.l[1];
01141 net.workspace = ce.data.l[2];
01142 net.stack = ce.data.l[3];
01143 net.decoration = static_cast<int>(ce.data.l[4]);
01144 win->changeBlackboxHints(net);
01145 }
01146 } else {
01147 WinClient *winclient = searchWindow(ce.window);
01148 BScreen *screen = searchScreen(ce.window);
01149
01150
01151 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01152 m_atomhandler[i]->checkClientMessage(ce, screen, winclient);
01153 }
01154
01155 }
01156 }
01157
01161 void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
01162
01163 if (keyScreen() == 0 || mouseScreen() == 0)
01164 return;
01165
01166
01167 switch (ke.type) {
01168 case KeyPress:
01169 m_key->doAction(ke);
01170 break;
01171 case KeyRelease: {
01172
01173
01174
01175
01176 if (m_watching_screen && m_watch_keyrelease) {
01177
01178
01179 ke.state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode);
01180
01181 if ((m_watch_keyrelease & ke.state) == 0) {
01182
01183 m_watching_screen->notifyReleasedKeys(ke);
01184 XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
01185
01186
01187 m_watching_screen = 0;
01188 m_watch_keyrelease = 0;
01189 }
01190 }
01191
01192 break;
01193 }
01194 default:
01195 break;
01196 }
01197
01198
01199 }
01200
01202 void Fluxbox::handleSignal(int signum) {
01203 I18n *i18n = I18n::instance();
01204 static int re_enter = 0;
01205
01206 switch (signum) {
01207 case SIGCHLD:
01208 waitpid(-1, 0, WNOHANG | WUNTRACED);
01209 break;
01210 case SIGHUP:
01211 load_rc();
01212 break;
01213 case SIGUSR1:
01214 reload_rc();
01215 break;
01216 case SIGUSR2:
01217 rereadMenu();
01218 break;
01219 case SIGSEGV:
01220 abort();
01221 break;
01222 case SIGFPE:
01223 case SIGINT:
01224 case SIGTERM:
01225 shutdown();
01226 break;
01227 default:
01228 fprintf(stderr,
01229 i18n->getMessage(
01230 FBNLS::BaseDisplaySet, FBNLS::BaseDisplaySignalCaught,
01231 "%s: signal %d caught\n"),
01232 m_argv[0], signum);
01233
01234 if (! m_starting && ! re_enter) {
01235 re_enter = 1;
01236 fprintf(stderr,
01237 i18n->getMessage(
01238 FBNLS::BaseDisplaySet, FBNLS::BaseDisplayShuttingDown,
01239 "shutting down\n"));
01240 shutdown();
01241 }
01242
01243
01244 fprintf(stderr,
01245 i18n->getMessage(
01246 FBNLS::BaseDisplaySet, FBNLS::BaseDisplayAborting,
01247 "aborting... dumping core\n"));
01248 abort();
01249 break;
01250 }
01251 }
01252
01253
01254 void Fluxbox::update(FbTk::Subject *changedsub) {
01255
01256 if (typeid(*changedsub) == typeid(FluxboxWindow::WinSubject)) {
01257 FluxboxWindow::WinSubject *winsub = dynamic_cast<FluxboxWindow::WinSubject *>(changedsub);
01258 FluxboxWindow &win = winsub->win();
01259 if ((&(win.hintSig())) == changedsub) {
01260 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01261 if (m_atomhandler[i]->update())
01262 m_atomhandler[i]->updateHints(win);
01263 }
01264 } else if ((&(win.stateSig())) == changedsub) {
01265 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01266 if (m_atomhandler[i]->update())
01267 m_atomhandler[i]->updateState(win);
01268 }
01269
01270
01271 if (win.isIconic()) {
01272 Workspace *space = win.screen().getWorkspace(win.workspaceNumber());
01273 if (space != 0)
01274 space->removeWindow(&win);
01275 win.screen().addIcon(&win);
01276 }
01277
01278 if (win.isStuck()) {
01279
01280
01281 BScreen &scr = win.screen();
01282 if (scr.currentWorkspaceID() != win.workspaceNumber()) {
01283 scr.reassociateWindow(&win,
01284 scr.currentWorkspaceID(),
01285 true);
01286 }
01287 }
01288 } else if ((&(win.layerSig())) == changedsub) {
01289
01290 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01291 if (m_atomhandler[i]->update())
01292 m_atomhandler[i]->updateLayer(win);
01293 }
01294 } else if ((&(win.dieSig())) == changedsub) {
01295 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01296 if (m_atomhandler[i]->update())
01297 m_atomhandler[i]->updateFrameClose(win);
01298 }
01299
01300 BScreen &scr = win.screen();
01301 scr.removeWindow(&win);
01302 if (m_focused_window == &win.winClient())
01303 m_focused_window = 0;
01304
01305 } else if ((&(win.workspaceSig())) == changedsub) {
01306 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01307 if (m_atomhandler[i]->update())
01308 m_atomhandler[i]->updateWorkspace(win);
01309 }
01310 } else {
01311 #ifdef DEBUG
01312 cerr<<__FILE__<<"("<<__LINE__<<"): WINDOW uncought signal from "<<&win<<endl;
01313 #endif // DEBUG
01314 }
01315
01316 } else if (typeid(*changedsub) == typeid(BScreen::ScreenSubject)) {
01317 BScreen::ScreenSubject *subj = dynamic_cast<BScreen::ScreenSubject *>(changedsub);
01318 BScreen &screen = subj->screen();
01319 if ((&(screen.workspaceCountSig())) == changedsub) {
01320 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01321 if (m_atomhandler[i]->update())
01322 m_atomhandler[i]->updateWorkspaceCount(screen);
01323 }
01324 } else if ((&(screen.workspaceNamesSig())) == changedsub) {
01325 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01326 if (m_atomhandler[i]->update())
01327 m_atomhandler[i]->updateWorkspaceNames(screen);
01328 }
01329 } else if ((&(screen.currentWorkspaceSig())) == changedsub) {
01330 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01331 if (m_atomhandler[i]->update())
01332 m_atomhandler[i]->updateCurrentWorkspace(screen);
01333 }
01334 } else if ((&(screen.clientListSig())) == changedsub) {
01335 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01336 if (m_atomhandler[i]->update())
01337 m_atomhandler[i]->updateClientList(screen);
01338 }
01339 }
01340 } else if (typeid(*changedsub) == typeid(WinClient::WinClientSubj)) {
01341
01342 WinClient::WinClientSubj *subj = dynamic_cast<WinClient::WinClientSubj *>(changedsub);
01343 WinClient &client = subj->winClient();
01344
01345
01346 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01347 if (m_atomhandler[i]->update())
01348 m_atomhandler[i]->updateClientClose(client);
01349 }
01350
01351 BScreen &screen = client.screen();
01352
01353 screen.removeClient(client);
01354
01355 screen.updateNetizenWindowDel(client.window());
01356
01357 if (m_focused_window == &client)
01358 revertFocus(screen);
01359
01360
01361 if (m_focused_window == &client)
01362 m_focused_window = 0;
01363 }
01364 }
01365
01366 void Fluxbox::attachSignals(FluxboxWindow &win) {
01367 win.hintSig().attach(this);
01368 win.stateSig().attach(this);
01369 win.workspaceSig().attach(this);
01370 win.layerSig().attach(this);
01371 win.dieSig().attach(this);
01372 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01373 m_atomhandler[i]->setupFrame(win);
01374 }
01375 }
01376
01377 void Fluxbox::attachSignals(WinClient &winclient) {
01378 winclient.dieSig().attach(this);
01379
01380 for (size_t i=0; i<m_atomhandler.size(); ++i) {
01381 m_atomhandler[i]->setupClient(winclient);
01382 }
01383 }
01384
01385 BScreen *Fluxbox::searchScreen(Window window) {
01386 ScreenList::iterator it = m_screen_list.begin();
01387 ScreenList::iterator it_end = m_screen_list.end();
01388 for (; it != it_end; ++it) {
01389 if (*it && (*it)->rootWindow() == window)
01390 return (*it);
01391 }
01392
01393 return 0;
01394 }
01395
01396 void Fluxbox::addAtomHandler(AtomHandler *atomh) {
01397 for (unsigned int handler = 0; handler < m_atomhandler.size(); handler++) {
01398 if (m_atomhandler[handler] == atomh)
01399 return;
01400 }
01401 m_atomhandler.push_back(atomh);
01402 }
01403
01404 void Fluxbox::removeAtomHandler(AtomHandler *atomh) {
01405 std::vector<AtomHandler *>::iterator it = m_atomhandler.begin();
01406 for (; it != m_atomhandler.end(); ++it) {
01407 if (*it == atomh) {
01408 m_atomhandler.erase(it);
01409 return;
01410 }
01411 }
01412 }
01413
01414 WinClient *Fluxbox::searchWindow(Window window) {
01415 std::map<Window, WinClient *>::iterator it = m_window_search.find(window);
01416 if (it != m_window_search.end())
01417 return it->second;
01418
01419 std::map<Window, FluxboxWindow *>::iterator git = m_window_search_group.find(window);
01420 return git == m_window_search_group.end() ? 0 : &git->second->winClient();
01421 }
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433 void Fluxbox::saveWindowSearch(Window window, WinClient *data) {
01434 m_window_search[window] = data;
01435 }
01436
01437
01438 void Fluxbox::saveWindowSearchGroup(Window window, FluxboxWindow *data) {
01439 m_window_search_group[window] = data;
01440 }
01441
01442 void Fluxbox::saveGroupSearch(Window window, WinClient *data) {
01443 m_group_search.insert(pair<Window, WinClient *>(window, data));
01444 }
01445
01446
01447 void Fluxbox::removeWindowSearch(Window window) {
01448 m_window_search.erase(window);
01449 }
01450
01451 void Fluxbox::removeWindowSearchGroup(Window window) {
01452 m_window_search_group.erase(window);
01453 }
01454
01455 void Fluxbox::removeGroupSearch(Window window) {
01456 m_group_search.erase(window);
01457 }
01458
01460 void Fluxbox::restart(const char *prog) {
01461 shutdown();
01462
01463 if (prog) {
01464 execlp(prog, prog, 0);
01465 perror(prog);
01466 }
01467
01468
01469 execvp(m_argv[0], m_argv);
01470 execvp(StringUtil::basename(m_argv[0]).c_str(), m_argv);
01471 }
01472
01474 void Fluxbox::shutdown() {
01475
01476 XSetInputFocus(FbTk::App::instance()->display(), PointerRoot, None, CurrentTime);
01477
01478
01479 for_each(m_screen_list.begin(), m_screen_list.end(), mem_fun(&BScreen::shutdown));
01480
01481 m_shutdown = true;
01482 sync(false);
01483
01484 }
01485
01487 void Fluxbox::save_rc() {
01488
01489 XrmDatabase new_blackboxrc = 0;
01490
01491 char rc_string[1024];
01492
01493 string dbfile(getRcFilename());
01494
01495 if (dbfile.size() != 0) {
01496 m_resourcemanager.save(dbfile.c_str(), dbfile.c_str());
01497 m_screen_rm.save(dbfile.c_str(), dbfile.c_str());
01498 } else
01499 cerr<<"database filename is invalid!"<<endl;
01500
01501 ScreenList::iterator it = m_screen_list.begin();
01502 ScreenList::iterator it_end = m_screen_list.end();
01503
01504
01505
01506 for (; it != it_end; ++it) {
01507 BScreen *screen = *it;
01508 int screen_number = screen->screenNumber();
01509
01510
01511
01512
01513
01514
01515
01516 sprintf(rc_string, "session.screen%d.workspaceNames: ", screen_number);
01517 string workspaces_string(rc_string);
01518
01519 for (unsigned int workspace=0; workspace < screen->getCount(); workspace++) {
01520 if (screen->getWorkspace(workspace)->name().size()!=0)
01521 workspaces_string.append(screen->getWorkspace(workspace)->name());
01522 else
01523 workspaces_string.append("Null");
01524 workspaces_string.append(",");
01525 }
01526
01527 XrmPutLineResource(&new_blackboxrc, workspaces_string.c_str());
01528
01529 }
01530
01531 XrmDatabase old_blackboxrc = XrmGetFileDatabase(dbfile.c_str());
01532
01533 XrmMergeDatabases(new_blackboxrc, &old_blackboxrc);
01534 XrmPutFileDatabase(old_blackboxrc, dbfile.c_str());
01535 XrmDestroyDatabase(old_blackboxrc);
01536 #ifdef DEBUG
01537 cerr<<__FILE__<<"("<<__LINE__<<"): ------------ SAVING DONE"<<endl;
01538 #endif // DEBUG
01539 }
01540
01542 string Fluxbox::getRcFilename() {
01543
01544 if (m_rc_file.size() == 0) {
01545 string defaultfile(getenv("HOME") + string("/.") + m_RC_PATH + string("/") + m_RC_INIT_FILE);
01546 return defaultfile;
01547 }
01548
01549 return m_rc_file;
01550 }
01551
01553 void Fluxbox::getDefaultDataFilename(char *name, string &filename) {
01554 filename = string(getenv("HOME") + string("/.") + m_RC_PATH + string("/") + name);
01555 }
01556
01558 void Fluxbox::load_rc() {
01559
01560
01561 string dbfile(getRcFilename());
01562
01563 if (dbfile.size() != 0) {
01564 if (!m_resourcemanager.load(dbfile.c_str())) {
01565 cerr<<"Failed to load database:"<<dbfile<<endl;
01566 cerr<<"Trying with: "<<DEFAULT_INITFILE<<endl;
01567 if (!m_resourcemanager.load(DEFAULT_INITFILE))
01568 cerr<<"Failed to load database: "<<DEFAULT_INITFILE<<endl;
01569 }
01570 } else {
01571 if (!m_resourcemanager.load(DEFAULT_INITFILE))
01572 cerr<<"Failed to load database: "<<DEFAULT_INITFILE<<endl;
01573 }
01574
01575 if (m_rc_menufile->size() == 0)
01576 m_rc_menufile.setDefaultValue();
01577
01578 if (m_rc_slitlistfile->size() != 0) {
01579 *m_rc_slitlistfile = StringUtil::expandFilename(*m_rc_slitlistfile);
01580 } else {
01581 string filename;
01582 getDefaultDataFilename("slitlist", filename);
01583 m_rc_slitlistfile.setFromString(filename.c_str());
01584 }
01585
01586 if (*m_rc_colors_per_channel < 2)
01587 *m_rc_colors_per_channel = 2;
01588 else if (*m_rc_colors_per_channel > 6)
01589 *m_rc_colors_per_channel = 6;
01590
01591 if (m_rc_stylefile->size() == 0)
01592 *m_rc_stylefile = DEFAULTSTYLE;
01593 else
01594 *m_rc_stylefile = StringUtil::expandFilename(*m_rc_stylefile);
01595
01596
01597
01598 *m_rc_groupfile = StringUtil::expandFilename(*m_rc_groupfile);
01599
01600 #ifdef DEBUG
01601 cerr<<__FILE__<<": Loading groups ("<<*m_rc_groupfile<<")"<<endl;
01602 #endif // DEBUG
01603 if (!Workspace::loadGroups(*m_rc_groupfile)) {
01604 cerr<<"Failed to load groupfile: "<<*m_rc_groupfile<<endl;
01605 }
01606 }
01607
01608 void Fluxbox::load_rc(BScreen &screen) {
01609
01610 string dbfile(getRcFilename());
01611
01612 XrmDatabaseHelper database;
01613
01614 database = XrmGetFileDatabase(dbfile.c_str());
01615 if (database==0)
01616 database = XrmGetFileDatabase(DEFAULT_INITFILE);
01617
01618 XrmValue value;
01619 char *value_type, name_lookup[1024], class_lookup[1024];
01620 int screen_number = screen.screenNumber();
01621
01622
01623 screen.removeWorkspaceNames();
01624
01625 sprintf(name_lookup, "session.screen%d.workspaceNames", screen_number);
01626 sprintf(class_lookup, "Session.Screen%d.WorkspaceNames", screen_number);
01627 if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
01628 &value)) {
01629 #ifdef DEBUG
01630 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Workspaces="<<
01631 screen.getNumberOfWorkspaces()<<endl;
01632 #endif // DEBUG
01633 char *search = StringUtil::strdup(value.addr);
01634
01635 int i;
01636 for (i = 0; i < screen.getNumberOfWorkspaces(); i++) {
01637 char *nn;
01638
01639 if (! i) nn = strtok(search, ",");
01640 else nn = strtok(0, ",");
01641
01642 if (nn)
01643 screen.addWorkspaceName(nn);
01644 else break;
01645
01646 }
01647
01648 delete [] search;
01649 }
01650
01651 FbTk::Image::removeAllSearchPaths();
01652 sprintf(name_lookup, "session.screen%d.imageSearchPath", screen_number);
01653 sprintf(class_lookup, "Session.Screen%d.imageSearchPath", screen_number);
01654 if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
01655 &value) && value.addr) {
01656 std::vector<std::string> paths;
01657 StringUtil::stringtok(paths, value.addr, ", ");
01658 for (unsigned int i=0; i<paths.size(); ++i)
01659 FbTk::Image::addSearchPath(paths[i]);
01660 }
01661
01662 if (dbfile.size() != 0) {
01663 if (!m_screen_rm.load(dbfile.c_str())) {
01664 cerr<<"Failed to load database:"<<dbfile<<endl;
01665 cerr<<"Trying with: "<<DEFAULT_INITFILE<<endl;
01666 if (!m_screen_rm.load(DEFAULT_INITFILE))
01667 cerr<<"Failed to load database: "<<DEFAULT_INITFILE<<endl;
01668 }
01669 } else {
01670 if (!m_screen_rm.load(DEFAULT_INITFILE))
01671 cerr<<"Failed to load database: "<<DEFAULT_INITFILE<<endl;
01672 }
01673
01674 }
01675
01676 void Fluxbox::loadRootCommand(BScreen &screen) {
01677
01678 string dbfile(getRcFilename());
01679
01680 XrmDatabaseHelper database(dbfile.c_str());
01681 if (!*database)
01682 database = XrmGetFileDatabase(DEFAULT_INITFILE);
01683
01684 XrmValue value;
01685 char *value_type, name_lookup[1024], class_lookup[1024];
01686 sprintf(name_lookup, "session.screen%d.rootCommand", screen.screenNumber());
01687 sprintf(class_lookup, "Session.Screen%d.RootCommand", screen.screenNumber());
01688 if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
01689 &value)) {
01690 screen.saveRootCommand(value.addr==0 ?