00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 # include "../config.h"
00005 #endif
00006
00007 #include "openbox.hh"
00008 #include "client.hh"
00009 #include "screen.hh"
00010 #include "actions.hh"
00011 #include "bindings.hh"
00012 #include "python.hh"
00013 #include "otk/property.hh"
00014 #include "otk/assassin.hh"
00015 #include "otk/property.hh"
00016 #include "otk/util.hh"
00017 #include "otk/rendercolor.hh"
00018
00019 extern "C" {
00020 #include <X11/cursorfont.h>
00021
00022 #ifdef HAVE_STDIO_H
00023 # include <stdio.h>
00024 #endif // HAVE_STDIO_H
00025
00026 #ifdef HAVE_STDLIB_H
00027 # include <stdlib.h>
00028 #endif // HAVE_STDLIB_H
00029
00030 #ifdef HAVE_SIGNAL_H
00031 # include <signal.h>
00032 #endif // HAVE_SIGNAL_H
00033
00034 #ifdef HAVE_FCNTL_H
00035 # include <fcntl.h>
00036 #endif // HAVE_FCNTL_H
00037
00038 #ifdef HAVE_SYS_WAIT_H
00039 # include <sys/wait.h>
00040 #endif // HAVE_SYS_WAIT_H
00041
00042 #include "gettext.h"
00043 #define _(str) gettext(str)
00044 }
00045
00046 #include <algorithm>
00047
00048 namespace ob {
00049
00050 Openbox *openbox = (Openbox *) 0;
00051
00052
00053 void Openbox::signalHandler(int signal)
00054 {
00055 switch (signal) {
00056 case SIGUSR1:
00057 printf("Caught SIGUSR1 signal. Restarting.\n");
00058 openbox->restart();
00059 break;
00060
00061 case SIGCHLD:
00062 wait(NULL);
00063 break;
00064
00065 case SIGHUP:
00066 case SIGINT:
00067 case SIGTERM:
00068 case SIGPIPE:
00069 printf("Caught signal %d. Exiting.\n", signal);
00070 openbox->shutdown();
00071 break;
00072
00073 case SIGFPE:
00074 case SIGSEGV:
00075 printf("Caught signal %d. Aborting and dumping core.\n", signal);
00076 abort();
00077 }
00078 }
00079
00080
00081 Openbox::Openbox(int argc, char **argv)
00082 : otk::EventDispatcher(),
00083 otk::EventHandler(),
00084 _display()
00085 {
00086 struct sigaction action;
00087
00088 _state = State_Starting;
00089
00090 openbox = this;
00091
00092 _displayreq = (char*) 0;
00093 _argv = argv;
00094 _shutdown = false;
00095 _restart = false;
00096 _rcfilepath = otk::expandTilde("~/.openbox/rc3");
00097 _scriptfilepath = otk::expandTilde("~/.openbox/user.py");
00098 _focused_client = 0;
00099 _sync = false;
00100 _single = false;
00101
00102 parseCommandLine(argc, argv);
00103
00104 XSynchronize(**otk::display, _sync);
00105
00106
00107 action.sa_handler = Openbox::signalHandler;
00108 action.sa_mask = sigset_t();
00109 action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
00110 sigaction(SIGUSR1, &action, (struct sigaction *) 0);
00111 sigaction(SIGPIPE, &action, (struct sigaction *) 0);
00112 sigaction(SIGSEGV, &action, (struct sigaction *) 0);
00113 sigaction(SIGFPE, &action, (struct sigaction *) 0);
00114 sigaction(SIGTERM, &action, (struct sigaction *) 0);
00115 sigaction(SIGINT, &action, (struct sigaction *) 0);
00116 sigaction(SIGHUP, &action, (struct sigaction *) 0);
00117 sigaction(SIGCHLD, &action, (struct sigaction *) 0);
00118
00119
00120 while (waitpid(-1, NULL, WNOHANG) > 0);
00121
00122 otk::RenderColor::initialize();
00123 otk::Timer::initialize();
00124 otk::Property::initialize();
00125 _actions = new Actions();
00126 _bindings = new Bindings();
00127
00128 setMasterHandler(_actions);
00129
00130
00131 _cursors.session = XCreateFontCursor(**otk::display, XC_left_ptr);
00132 _cursors.move = XCreateFontCursor(**otk::display, XC_fleur);
00133 _cursors.ll_angle = XCreateFontCursor(**otk::display, XC_ll_angle);
00134 _cursors.lr_angle = XCreateFontCursor(**otk::display, XC_lr_angle);
00135 _cursors.ul_angle = XCreateFontCursor(**otk::display, XC_ul_angle);
00136 _cursors.ur_angle = XCreateFontCursor(**otk::display, XC_ur_angle);
00137
00138
00139 python_init(argv[0]);
00140
00141
00142
00143
00144
00145
00146
00147 if (!python_exec(_scriptfilepath.c_str()))
00148 python_exec(SCRIPTDIR"/defaults.py");
00149
00150
00151 _focused_screen = 0;
00152
00153 for (int i = 0, max = ScreenCount(**otk::display); i < max; ++i) {
00154 Screen *screen;
00155
00156 if (_single && i != DefaultScreen(**otk::display)) {
00157 _screens.push_back(0);
00158 continue;
00159 }
00160
00161 screen = new Screen(i);
00162 if (screen->managed()) {
00163 _screens.push_back(screen);
00164 if (!_focused_screen)
00165 _focused_screen = screen;
00166 } else {
00167 delete screen;
00168 _screens.push_back(0);
00169 }
00170 }
00171
00172 assert(_focused_screen);
00173
00174 if (_screens.empty()) {
00175 printf(_("No screens were found without a window manager. Exiting.\n"));
00176 ::exit(1);
00177 }
00178
00179 ScreenList::iterator it, end = _screens.end();
00180 for (it = _screens.begin(); it != end; ++it) {
00181 (*it)->manageExisting();
00182 }
00183
00184
00185 _bindings->grabKeys(true);
00186
00187
00188 setFocusedClient(0);
00189
00190 _state = State_Normal;
00191 }
00192
00193
00194 Openbox::~Openbox()
00195 {
00196 _state = State_Exiting;
00197
00198 std::for_each(_screens.begin(), _screens.end(), otk::PointerAssassin());
00199
00200 delete _bindings;
00201 delete _actions;
00202
00203 python_destroy();
00204
00205 XSetInputFocus(**otk::display, PointerRoot, RevertToNone,
00206 CurrentTime);
00207 XSync(**otk::display, false);
00208
00209
00210
00211
00212
00213
00214 otk::Timer::destroy();
00215 otk::RenderColor::destroy();
00216 }
00217
00218
00219 void Openbox::parseCommandLine(int argc, char **argv)
00220 {
00221 bool err = false;
00222
00223 for (int i = 1; i < argc; ++i) {
00224 std::string arg(argv[i]);
00225
00226 if (arg == "-display") {
00227 if (++i >= argc)
00228 err = true;
00229 else
00230 _displayreq = argv[i];
00231 } else if (arg == "-rc") {
00232 if (++i >= argc)
00233 err = true;
00234 else
00235 _rcfilepath = argv[i];
00236 } else if (arg == "-menu") {
00237 if (++i >= argc)
00238 err = true;
00239 else
00240 _menufilepath = argv[i];
00241 } else if (arg == "-script") {
00242 if (++i >= argc)
00243 err = true;
00244 else
00245 _scriptfilepath = argv[i];
00246 } else if (arg == "-sync") {
00247 _sync = true;
00248 } else if (arg == "-single") {
00249 _single = true;
00250 } else if (arg == "-version") {
00251 showVersion();
00252 ::exit(0);
00253 } else if (arg == "-help") {
00254 showHelp();
00255 ::exit(0);
00256 } else
00257 err = true;
00258
00259 if (err) {
00260 showHelp();
00261 exit(1);
00262 }
00263 }
00264 }
00265
00266
00267 void Openbox::showVersion()
00268 {
00269 printf(_("Openbox - version %s\n"), VERSION);
00270 printf(" (c) 2002 - 2002 Ben Jansens\n\n");
00271 }
00272
00273
00274 void Openbox::showHelp()
00275 {
00276 showVersion();
00277
00278
00279 printf(_("Usage: %s [OPTIONS...]\n\
00280 Options:\n\
00281 -display <string> use display connection.\n\
00282 -single run on a single screen (default is to run every one).\n\
00283 -rc <string> use alternate resource file.\n\
00284 -menu <string> use alternate menu file.\n\
00285 -script <string> use alternate startup script file.\n\
00286 -sync run in synchronous mode (for debugging X errors).\n\
00287 -version display version and exit.\n\
00288 -help display this help text and exit.\n\n"), _argv[0]);
00289
00290 printf(_("Compile time options:\n\
00291 Debugging: %s\n\
00292 Shape: %s\n\
00293 Xinerama: %s\n\
00294 Xkb: %s\n"),
00295 #ifdef DEBUG
00296 _("yes"),
00297 #else
00298 _("no"),
00299 #endif
00300
00301 #ifdef SHAPE
00302 _("yes"),
00303 #else
00304 _("no"),
00305 #endif
00306
00307 #ifdef XINERAMA
00308 _("yes"),
00309 #else
00310 _("no"),
00311 #endif
00312
00313 #ifdef XKB
00314 _("yes")
00315 #else
00316 _("no")
00317 #endif
00318 );
00319 }
00320
00321
00322 void Openbox::eventLoop()
00323 {
00324 while (true) {
00325 dispatchEvents();
00326 XFlush(**otk::display);
00327
00328 if (_shutdown) break;
00329 otk::Timer::dispatchTimers(!_sync);
00330 }
00331 }
00332
00333
00334 void Openbox::addClient(Window window, Client *client)
00335 {
00336 _clients[window] = client;
00337 }
00338
00339
00340 void Openbox::removeClient(Window window)
00341 {
00342 _clients.erase(window);
00343 }
00344
00345
00346 Client *Openbox::findClient(Window window)
00347 {
00348
00349
00350
00351
00352
00353 ClientMap::iterator it = _clients.find(window);
00354 if (it != _clients.end())
00355 return it->second;
00356 else
00357 return (Client*) 0;
00358 }
00359
00360
00361 void Openbox::setFocusedClient(Client *c)
00362 {
00363
00364
00365
00366
00367 assert(_focused_screen);
00368
00369
00370 if (_focused_client)
00371 _focused_client->installColormap(false);
00372 else
00373 _focused_screen->installColormap(false);
00374
00375 _focused_client = c;
00376 if (c) {
00377 _focused_screen = _screens[c->screen()];
00378
00379
00380 c->installColormap(true);
00381 } else {
00382 XSetInputFocus(**otk::display, _focused_screen->focuswindow(),
00383 RevertToNone, CurrentTime);
00384
00385
00386 _focused_screen->installColormap(true);
00387 }
00388
00389 ScreenList::iterator it, end = _screens.end();
00390 for (it = _screens.begin(); it != end; ++it) {
00391 int num = (*it)->number();
00392 Window root = otk::display->screenInfo(num)->rootWindow();
00393 otk::Property::set(root, otk::Property::atoms.net_active_window,
00394 otk::Property::atoms.window,
00395 (c && _focused_screen == *it) ? c->window() : None);
00396 }
00397
00398
00399 EventData data(_focused_screen->number(), c, EventAction::Focus, 0);
00400 _bindings->fireEvent(&data);
00401 }
00402
00403 }
00404