// -*- mode: C++; indent-tabs-mode: nil; -*-
-// epist.cc for Epistory - a key handler for NETWM/EWMH window managers.
+// epist.cc for Epistophy - a key handler for NETWM/EWMH window managers.
// Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a
using std::string;
#include "epist.hh"
-#include "process.hh"
+#include "screen.hh"
+#include "window.hh"
#include "../../src/XAtom.hh"
-bool _shutdown = false;
-char **_argv;
-char *_display_name = 0;
-Display *_display = 0;
-Window _root = None;
-XAtom *_xatom;
+epist::epist(char **argv, char *dpy_name, char *rc_file)
+ : BaseDisplay(argv[0], dpy_name) {
-#ifdef HAVE_SIGACTION
-static void signalhandler(int sig)
-#else // HAVE_SIGACTION
-static RETSIGTYPE signalhandler(int sig)
-#endif // HAVE_SIGACTION
-{
+ _argv = argv;
+
+ if (rc_file)
+ _rc_file = rc_file;
+ else
+ _rc_file = expandTilde("~/.openbox/epistrc");
+
+ _xatom = new XAtom(getXDisplay());
+
+ for (unsigned int i = 0; i < getNumberOfScreens(); ++i) {
+ screen *s = new screen(this, i);
+ if (s->managed())
+ _screens.push_back(s);
+ }
+ if (_screens.empty()) {
+ cout << "No compatible window manager found on any screens. Aborting.\n";
+ ::exit(1);
+ }
+
+ _actions.push_back(Action(Action::nextWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Tab")),
+ ControlMask));
+ _actions.push_back(Action(Action::prevWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Tab")),
+ ControlMask | ShiftMask));
+ _actions.push_back(Action(Action::toggleshade,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("F5")),
+ Mod1Mask));
+ _actions.push_back(Action(Action::close,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("F4")),
+ Mod1Mask));
+ _actions.push_back(Action(Action::nextWindow,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Tab")),
+ Mod1Mask));
+ _actions.push_back(Action(Action::prevWindow,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Tab")),
+ Mod1Mask | ShiftMask));
+ _actions.push_back(Action(Action::nextWindowOnAllWorkspaces,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Tab")),
+ Mod1Mask | ControlMask));
+ _actions.push_back(Action(Action::prevWindowOnAllWorkspaces,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Tab")),
+ Mod1Mask | ShiftMask | ControlMask));
+ _actions.push_back(Action(Action::raise,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Up")),
+ Mod1Mask));
+ _actions.push_back(Action(Action::lower,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Down")),
+ Mod1Mask));
+ _actions.push_back(Action(Action::moveWindowUp,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Up")),
+ Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::moveWindowDown,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Down")),
+ Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::moveWindowLeft,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Left")),
+ Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::moveWindowRight,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Right")),
+ Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::resizeWindowHeight,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Up")),
+ ShiftMask | Mod1Mask | ControlMask, -1));
+ _actions.push_back(Action(Action::resizeWindowHeight,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Down")),
+ ShiftMask | Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::resizeWindowWidth,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Left")),
+ ShiftMask | Mod1Mask | ControlMask, -1));
+ _actions.push_back(Action(Action::resizeWindowWidth,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("Right")),
+ ShiftMask | Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::iconify,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("I")),
+ Mod1Mask | ControlMask));
+ _actions.push_back(Action(Action::toggleomnipresent,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("O")),
+ Mod1Mask | ControlMask));
+ _actions.push_back(Action(Action::toggleMaximizeHorizontal,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("X")),
+ ShiftMask | Mod1Mask));
+ _actions.push_back(Action(Action::toggleMaximizeVertical,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("X")),
+ ShiftMask | ControlMask));
+ _actions.push_back(Action(Action::toggleMaximizeFull,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("X")),
+ Mod1Mask | ControlMask));
+ _actions.push_back(Action(Action::changeWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("1")),
+ Mod1Mask | ControlMask, 0));
+ _actions.push_back(Action(Action::changeWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("2")),
+ Mod1Mask | ControlMask, 1));
+ _actions.push_back(Action(Action::changeWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("3")),
+ Mod1Mask | ControlMask, 2));
+ _actions.push_back(Action(Action::changeWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("4")),
+ Mod1Mask | ControlMask, 3));
+ _actions.push_back(Action(Action::sendToWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("1")),
+ Mod1Mask | ControlMask | ShiftMask, 0));
+ _actions.push_back(Action(Action::sendToWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("2")),
+ Mod1Mask | ControlMask | ShiftMask, 1));
+ _actions.push_back(Action(Action::sendToWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("3")),
+ Mod1Mask | ControlMask | ShiftMask, 2));
+ _actions.push_back(Action(Action::sendToWorkspace,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("4")),
+ Mod1Mask | ControlMask | ShiftMask, 3));
+ _actions.push_back(Action(Action::execute,
+ XKeysymToKeycode(getXDisplay(),
+ XStringToKeysym("space")),
+ Mod1Mask, "rxvt"));
+ activateGrabs();
+}
+
+
+epist::~epist() {
+ delete _xatom;
+}
+
+void epist::activateGrabs() {
+
+ ScreenList::const_iterator scrit, scrend = _screens.end();
+
+ for (scrit = _screens.begin(); scrit != scrend; ++scrit) {
+ ActionList::const_iterator ait, end = _actions.end();
+
+ for(ait = _actions.begin(); ait != end; ++ait) {
+ XGrabKey(getXDisplay(), ait->keycode(), ait->modifierMask(),
+ (*scrit)->rootWindow(), False, GrabModeAsync, GrabModeAsync);
+ }
+ }
+}
+
+
+bool epist::handleSignal(int sig) {
switch (sig) {
- case SIGSEGV:
- cout << "epist: Segmentation fault. Aborting and dumping core.\n";
- abort();
case SIGHUP:
cout << "epist: Restarting on request.\n";
execvp(_argv[0], _argv);
execvp(basename(_argv[0]), _argv);
+ return false; // this should be unreachable
+
+ case SIGTERM:
+ case SIGINT:
+ case SIGPIPE:
+ shutdown();
+ return true;
}
- _shutdown = true;
-#ifndef HAVE_SIGACTION
- // assume broken, braindead sysv signal semantics
- signal(sig, (RETSIGTYPE (*)(int)) signalhandler);
-#endif // HAVE_SIGACTION
+ return false;
}
-void parseCommandLine(int argc, char **argv) {
- _argv = argv;
+void epist::process_event(XEvent *e) {
+ Window root;
- for (int i = 1; i < argc; ++i) {
- if (string(argv[i]) == "-display") {
- if (++i >= argc) {
- cout << "error:: '-display' requires an argument\n";
- exit(1);
- }
- _display_name = argv[i];
-
- string dtmp = (string)"DISPLAY=" + _display_name;
- if (putenv(const_cast<char*>(dtmp.c_str()))) {
- cout << "warning: couldn't set environment variable 'DISPLAY'\n";
- perror("putenv()");
- }
+ if (e->xany.type == KeyPress)
+ root = e->xkey.root;
+ else
+ root = e->xany.window;
+
+ ScreenList::const_iterator it, end = _screens.end();
+ for (it = _screens.begin(); it != end; ++it) {
+ if ((*it)->rootWindow() == root) {
+ (*it)->processEvent(*e);
+ return;
}
}
-}
+ // wasnt a root window, try for client windows
+ XWindow *w = findWindow(e->xany.window);
+ if (w) w->processEvent(*e);
+}
-bool findSupportingWM() {
- Window support_win;
- if (! _xatom->getValue(_root, XAtom::net_supporting_wm_check, XAtom::window,
- support_win) || support_win == None)
- return false;
-
- string title;
- _xatom->getValue(support_win, XAtom::net_wm_name, XAtom::utf8, title);
- cout << "Found compatible window manager: " << title << endl;
- return true;
+
+void epist::addWindow(XWindow *window) {
+ _windows.insert(WindowLookupPair(window->window(), window));
}
-int main(int argc, char **argv) {
-#ifdef HAVE_SIGACTION
- struct sigaction action;
-
- action.sa_handler = signalhandler;
- action.sa_mask = sigset_t();
- action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
-
- sigaction(SIGPIPE, &action, NULL);
- sigaction(SIGSEGV, &action, NULL);
- sigaction(SIGFPE, &action, NULL);
- sigaction(SIGTERM, &action, NULL);
- sigaction(SIGINT, &action, NULL);
- sigaction(SIGHUP, &action, NULL);
-#else // !HAVE_SIGACTION
- signal(SIGPIPE, (RETSIGTYPE (*)(int)) signalhandler);
- signal(SIGSEGV, (RETSIGTYPE (*)(int)) signalhandler);
- signal(SIGFPE, (RETSIGTYPE (*)(int)) signalhandler);
- signal(SIGTERM, (RETSIGTYPE (*)(int)) signalhandler);
- signal(SIGINT, (RETSIGTYPE (*)(int)) signalhandler);
- signal(SIGHUP, (RETSIGTYPE (*)(int)) signalhandler);
-#endif // HAVE_SIGACTION
-
- parseCommandLine(argc, argv);
-
- _display = XOpenDisplay(_display_name);
- if (! _display) {
- cout << "Connection to X server '" << _display_name << "' failed.\n";
- return 1;
- }
- _root = RootWindow(_display, DefaultScreen(_display));
- _xatom = new XAtom(_display);
+void epist::removeWindow(XWindow *window) {
+ _windows.erase(window->window());
+}
- XSelectInput(_display, _root, PropertyChangeMask);
- // find a window manager supporting NETWM, waiting for it to load if we must
- while (! (_shutdown || findSupportingWM()));
-
- if (! _shutdown) {
- updateClientList();
- updateActiveWindow();
- }
-
- while (! _shutdown) {
- if (XPending(_display)) {
- XEvent e;
- XNextEvent(_display, &e);
- processEvent(e);
- } else {
- usleep(300);
- }
- }
+XWindow *epist::findWindow(Window window) const {
+ WindowLookup::const_iterator it = _windows.find(window);
+ if (it != _windows.end())
+ return it->second;
- delete _xatom;
- XCloseDisplay(_display);
return 0;
}