diff options
Diffstat (limited to 'src/fluxbox.cc')
-rw-r--r-- | src/fluxbox.cc | 162 |
1 files changed, 68 insertions, 94 deletions
diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 015bb62..3658e50 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc | |||
@@ -168,11 +168,38 @@ int handleXErrors(Display *d, XErrorEvent *e) { | |||
168 | // kill(0, 2); | 168 | // kill(0, 2); |
169 | } | 169 | } |
170 | #endif // !DEBUG | 170 | #endif // !DEBUG |
171 | |||
172 | return False; | 171 | return False; |
173 | } | 172 | } |
174 | 173 | ||
175 | 174 | ||
175 | int handleXIOErrors(Display* d) { | ||
176 | cerr << "Fluxbox: XIOError: lost connection to display.\n"; | ||
177 | exit(1); | ||
178 | } | ||
179 | |||
180 | |||
181 | |||
182 | class KeyReloadHelper { | ||
183 | public: | ||
184 | void reload() { | ||
185 | Fluxbox* f = Fluxbox::instance(); | ||
186 | Keys* k = (f ? f->keys() : 0); | ||
187 | if (k) { | ||
188 | XRefreshKeyboardMapping(&(this->xmapping)); | ||
189 | FbTk::KeyUtil::instance().init(); | ||
190 | k->regrab(); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | XMappingEvent xmapping; | ||
195 | }; | ||
196 | |||
197 | KeyReloadHelper s_key_reloader; | ||
198 | |||
199 | typedef FbTk::SimpleCommand<KeyReloadHelper> KeyReloadHelperCmd; | ||
200 | typedef FbTk::SimpleCommand<Fluxbox> FluxboxCmd; | ||
201 | |||
202 | |||
176 | 203 | ||
177 | /* functor to call a memberfunction with by a reference argument | 204 | /* functor to call a memberfunction with by a reference argument |
178 | other places needs this helper as well it should be moved | 205 | other places needs this helper as well it should be moved |
@@ -281,21 +308,8 @@ Fluxbox::Fluxbox(int argc, char **argv, | |||
281 | s_kwm2_dockwindow = XInternAtom(disp, | 308 | s_kwm2_dockwindow = XInternAtom(disp, |
282 | "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False); | 309 | "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False); |
283 | // setup X error handler | 310 | // setup X error handler |
284 | XSetErrorHandler((XErrorHandler) handleXErrors); | 311 | XSetErrorHandler(handleXErrors); |
285 | 312 | XSetIOErrorHandler(handleXIOErrors); | |
286 | //catch system signals | ||
287 | SignalHandler &sigh = SignalHandler::instance(); | ||
288 | sigh.registerHandler(SIGSEGV, this); | ||
289 | sigh.registerHandler(SIGFPE, this); | ||
290 | sigh.registerHandler(SIGTERM, this); | ||
291 | sigh.registerHandler(SIGINT, this); | ||
292 | #ifndef _WIN32 | ||
293 | sigh.registerHandler(SIGPIPE, this); // e.g. output sent to grep | ||
294 | sigh.registerHandler(SIGCHLD, this); | ||
295 | sigh.registerHandler(SIGHUP, this); | ||
296 | sigh.registerHandler(SIGUSR1, this); | ||
297 | sigh.registerHandler(SIGUSR2, this); | ||
298 | #endif | ||
299 | 313 | ||
300 | // | 314 | // |
301 | // setup timer | 315 | // setup timer |
@@ -303,11 +317,21 @@ Fluxbox::Fluxbox(int argc, char **argv, | |||
303 | // Because when the command is executed we shouldn't do reconfig directly | 317 | // Because when the command is executed we shouldn't do reconfig directly |
304 | // because it could affect ongoing menu stuff so we need to reconfig in | 318 | // because it could affect ongoing menu stuff so we need to reconfig in |
305 | // the next event "round". | 319 | // the next event "round". |
306 | FbTk::RefCount<FbTk::Command<void> > reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure)); | 320 | FluxboxCmd* reconfig_cmd = new FluxboxCmd(*this, &Fluxbox::timed_reconfigure); |
307 | m_reconfig_timer.setTimeout(1); | 321 | m_reconfig_timer.setTimeout(1); |
308 | m_reconfig_timer.setCommand(reconfig_cmd); | 322 | m_reconfig_timer.setCommand(FbTk::RefCount<FbTk::Command<void> >(reconfig_cmd)); |
309 | m_reconfig_timer.fireOnce(true); | 323 | m_reconfig_timer.fireOnce(true); |
310 | 324 | ||
325 | // xmodmap and other tools send a lot of MappingNotify events under some | ||
326 | // circumstances ("keysym comma = comma semicolon" creates 4 or 5). | ||
327 | // reloading the keys-file for every one of them is unclever. we postpone | ||
328 | // the reload() via a timer. | ||
329 | KeyReloadHelperCmd* rh_cmd = | ||
330 | new KeyReloadHelperCmd(s_key_reloader, &KeyReloadHelper::reload); | ||
331 | m_key_reload_timer.setTimeout(250 * FbTk::FbTime::IN_MILLISECONDS); | ||
332 | m_key_reload_timer.setCommand(FbTk::RefCount<FbTk::Command<void> >(rh_cmd)); | ||
333 | m_key_reload_timer.fireOnce(true); | ||
334 | |||
311 | if (xsync) | 335 | if (xsync) |
312 | XSynchronize(disp, True); | 336 | XSynchronize(disp, True); |
313 | 337 | ||
@@ -638,20 +662,12 @@ void Fluxbox::handleEvent(XEvent * const e) { | |||
638 | 662 | ||
639 | if (! winclient) { | 663 | if (! winclient) { |
640 | BScreen *screen = 0; | 664 | BScreen *screen = 0; |
641 | int screen_num; | ||
642 | XWindowAttributes attr; | 665 | XWindowAttributes attr; |
643 | // find screen | 666 | // find screen |
644 | if (XGetWindowAttributes(display(), | 667 | if (XGetWindowAttributes(display(), |
645 | e->xmaprequest.window, | 668 | e->xmaprequest.window, |
646 | &attr) && attr.screen != 0) { | 669 | &attr) && attr.screen != 0) { |
647 | screen_num = XScreenNumberOfScreen(attr.screen); | 670 | screen = findScreen(XScreenNumberOfScreen(attr.screen)); |
648 | |||
649 | // find screen | ||
650 | ScreenList::iterator screen_it = find_if(m_screen_list.begin(), | ||
651 | m_screen_list.end(), | ||
652 | FbTk::CompareEqual<BScreen>(&BScreen::screenNumber, screen_num)); | ||
653 | if (screen_it != m_screen_list.end()) | ||
654 | screen = *screen_it; | ||
655 | } | 671 | } |
656 | // try with parent if we failed to find screen num | 672 | // try with parent if we failed to find screen num |
657 | if (screen == 0) | 673 | if (screen == 0) |
@@ -675,21 +691,18 @@ void Fluxbox::handleEvent(XEvent * const e) { | |||
675 | break; | 691 | break; |
676 | case UnmapNotify: | 692 | case UnmapNotify: |
677 | handleUnmapNotify(e->xunmap); | 693 | handleUnmapNotify(e->xunmap); |
678 | break; | 694 | break; |
679 | case MappingNotify: | 695 | case MappingNotify: // Update stored modifier mapping |
680 | // Update stored modifier mapping | ||
681 | fbdbg<<"MappingNotify"<<endl; | ||
682 | 696 | ||
683 | if (e->xmapping.request == MappingKeyboard | 697 | if (e->xmapping.request == MappingKeyboard |
684 | || e->xmapping.request == MappingModifier) { | 698 | || e->xmapping.request == MappingModifier) { |
685 | XRefreshKeyboardMapping(&e->xmapping); | 699 | |
686 | FbTk::KeyUtil::instance().init(); // reinitialise the key utils | 700 | s_key_reloader.xmapping = e->xmapping; |
687 | // reconfigure keys (if the mapping changes, they don't otherwise update | 701 | m_key_reload_timer.start(); |
688 | m_key->regrab(); | ||
689 | } | 702 | } |
690 | break; | 703 | break; |
691 | case CreateNotify: | 704 | case CreateNotify: |
692 | break; | 705 | break; |
693 | case DestroyNotify: { | 706 | case DestroyNotify: { |
694 | WinClient *winclient = searchWindow(e->xdestroywindow.window); | 707 | WinClient *winclient = searchWindow(e->xdestroywindow.window); |
695 | if (winclient != 0) { | 708 | if (winclient != 0) { |
@@ -887,58 +900,6 @@ void Fluxbox::handleClientMessage(XClientMessageEvent &ce) { | |||
887 | } | 900 | } |
888 | } | 901 | } |
889 | 902 | ||
890 | /// handle system signals | ||
891 | void Fluxbox::handleSignal(int signum) { | ||
892 | _FB_USES_NLS; | ||
893 | |||
894 | static int re_enter = 0; | ||
895 | |||
896 | switch (signum) { | ||
897 | #ifndef _WIN32 | ||
898 | case SIGCHLD: // we don't want the child process to kill us | ||
899 | // more than one process may have terminated | ||
900 | while (waitpid(-1, 0, WNOHANG | WUNTRACED) > 0); | ||
901 | break; | ||
902 | case SIGHUP: | ||
903 | restart(); | ||
904 | break; | ||
905 | case SIGUSR1: | ||
906 | load_rc(); | ||
907 | break; | ||
908 | case SIGUSR2: | ||
909 | reconfigure(); | ||
910 | break; | ||
911 | #endif | ||
912 | case SIGSEGV: | ||
913 | abort(); | ||
914 | break; | ||
915 | case SIGFPE: | ||
916 | case SIGINT: | ||
917 | #ifndef _WIN32 | ||
918 | case SIGPIPE: | ||
919 | #endif | ||
920 | case SIGTERM: | ||
921 | shutdown(); | ||
922 | break; | ||
923 | default: | ||
924 | fprintf(stderr, | ||
925 | _FB_CONSOLETEXT(BaseDisplay, SignalCaught, "%s: signal %d caught\n", "signal catch debug message. Include %s for Command<void> and %d for signal number").c_str(), | ||
926 | m_argv[0], signum); | ||
927 | |||
928 | if (! m_starting && ! re_enter) { | ||
929 | re_enter = 1; | ||
930 | cerr<<_FB_CONSOLETEXT(BaseDisplay, ShuttingDown, "Shutting Down\n", "Quitting because of signal, end with newline"); | ||
931 | shutdown(); | ||
932 | } | ||
933 | |||
934 | |||
935 | cerr<<_FB_CONSOLETEXT(BaseDisplay, Aborting, "Aborting... dumping core\n", "Aboring and dumping core, end with newline"); | ||
936 | abort(); | ||
937 | break; | ||
938 | } | ||
939 | } | ||
940 | |||
941 | |||
942 | void Fluxbox::windowDied(Focusable &focusable) { | 903 | void Fluxbox::windowDied(Focusable &focusable) { |
943 | FluxboxWindow *fbwin = focusable.fbwindow(); | 904 | FluxboxWindow *fbwin = focusable.fbwindow(); |
944 | 905 | ||
@@ -1113,18 +1074,30 @@ void Fluxbox::restart(const char *prog) { | |||
1113 | } | 1074 | } |
1114 | } | 1075 | } |
1115 | 1076 | ||
1116 | /// prepares fluxbox for a shutdown | 1077 | // prepares fluxbox for a shutdown. when x_wants_down is != 0 we assume that |
1117 | void Fluxbox::shutdown() { | 1078 | // the xserver is about to shutdown or is in the midst of shutting down |
1079 | // already. trying to cleanup over a shaky xserver connection is pointless and | ||
1080 | // might lead to hangups. | ||
1081 | void Fluxbox::shutdown(int x_wants_down) { | ||
1118 | if (m_shutdown) | 1082 | if (m_shutdown) |
1119 | return; | 1083 | return; |
1120 | 1084 | ||
1085 | Display *dpy = FbTk::App::instance()->display(); | ||
1121 | m_shutdown = true; | 1086 | m_shutdown = true; |
1122 | 1087 | ||
1123 | XSetInputFocus(FbTk::App::instance()->display(), PointerRoot, None, CurrentTime); | 1088 | #ifdef HAVE_ALARM |
1089 | // give ourself 2 seconds (randomly picked randon number) to shutdown | ||
1090 | // and then try to reenter signal handling. a bad race condition might | ||
1091 | // lead to an inifite loop and this is some kind of last resort | ||
1092 | alarm(2); | ||
1093 | #endif | ||
1124 | 1094 | ||
1125 | STLUtil::forAll(m_screen_list, mem_fun(&BScreen::shutdown)); | 1095 | XSetInputFocus(dpy, PointerRoot, None, CurrentTime); |
1126 | 1096 | ||
1127 | sync(false); | 1097 | if (x_wants_down == 0) { |
1098 | STLUtil::forAll(m_screen_list, mem_fun(&BScreen::shutdown)); | ||
1099 | sync(false); | ||
1100 | } | ||
1128 | } | 1101 | } |
1129 | 1102 | ||
1130 | /// saves resources | 1103 | /// saves resources |
@@ -1279,6 +1252,7 @@ void Fluxbox::load_rc(BScreen &screen) { | |||
1279 | } | 1252 | } |
1280 | 1253 | ||
1281 | void Fluxbox::reconfigure() { | 1254 | void Fluxbox::reconfigure() { |
1255 | m_key_reload_timer.stop(); | ||
1282 | load_rc(); | 1256 | load_rc(); |
1283 | m_reconfigure_wait = true; | 1257 | m_reconfigure_wait = true; |
1284 | m_reconfig_timer.start(); | 1258 | m_reconfig_timer.start(); |
@@ -1350,7 +1324,7 @@ bool Fluxbox::validateClient(const WinClient *client) const { | |||
1350 | WinClientMap::const_iterator it = | 1324 | WinClientMap::const_iterator it = |
1351 | find_if(m_window_search.begin(), | 1325 | find_if(m_window_search.begin(), |
1352 | m_window_search.end(), | 1326 | m_window_search.end(), |
1353 | Compose(bind2nd(equal_to<WinClient *>(), client), | 1327 | Compose(bind2nd(equal_to<const WinClient *>(), client), |
1354 | Select2nd<WinClientMap::value_type>())); | 1328 | Select2nd<WinClientMap::value_type>())); |
1355 | return it != m_window_search.end(); | 1329 | return it != m_window_search.end(); |
1356 | } | 1330 | } |