bin_PROGRAMS = epist
-epist_SOURCES = epist.cc process.cc window.cc
-epist_LDADD = ../../src/XAtom.o
+epist_SOURCES = epist.cc process.cc window.cc screen.cc main.cc
+epist_LDADD = ../../src/XAtom.o ../../src/BaseDisplay.o \
+ ../../src/Util.o ../../src/i18n.o \
+ ../../src/GCCache.o ../../src/Color.o ../../src/Texture.o \
+ ../../src/Timer.o ../../src/Image.o ../../src/ImageControl.o
MAINTAINERCLEANFILES = Makefile.in
# local dependencies
-epist.o: epist.cc epist.hh process.hh
-process.o: process.cc process.hh /usr/include/X11/Xlib.h epist.hh
+epist.o: epist.cc epist.hh ../../src/BaseDisplay.hh ../../src/Timer.hh \
+ ../../src/Util.hh process.hh screen.hh window.hh ../../src/XAtom.hh
+main.o: main.cc epist.hh ../../src/BaseDisplay.hh ../../src/Timer.hh \
+ ../../src/Util.hh ../../src/i18n.hh ../../nls/blackbox-nls.hh
+process.o: process.cc
+screen.o: screen.cc ../../src/XAtom.hh screen.hh window.hh epist.hh \
+ ../../src/BaseDisplay.hh ../../src/Timer.hh ../../src/Util.hh
+window.o: window.cc window.hh epist.hh ../../src/BaseDisplay.hh \
+ ../../src/Timer.hh ../../src/Util.hh ../../src/XAtom.hh
# include <unistd.h>
#endif // HAVE_UNISTD_H
-#ifdef HAVE_STDIO_H
-# include <stdio.h>
-#endif // HAVE_STDIO_H
-
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif // HAVE_STDLIB_H
# include <signal.h>
#endif // HAVE_SIGNAL_H
-#ifdef HAVE_LIBGEN_H
+/*#ifdef HAVE_LIBGEN_H
# include <libgen.h>
-#endif // HAVE_LIBGEN_H
+#endif // HAVE_LIBGEN_H*/
}
#include <iostream>
#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) {
+
+ _argv = argv;
+
+ if (rc_file)
+ _rc_file = rc_file;
+ else
+ _rc_file = expandTilde("~/.openbox/epistrc");
+
+ _xatom = new XAtom(getXDisplay());
+
+ screen *s = new screen(this, DefaultScreen(getXDisplay()));
+ if (s->managed())
+ _screens.push_back(s);
+ if (_screens.empty()) {
+ cout << "No compatible window manager found on any screens. Aborting.\n";
+ ::exit(1);
+ }
+}
+
+
+epist::~epist() {
+ delete _xatom;
+}
-#ifdef HAVE_SIGACTION
-static void signalhandler(int sig)
-#else // HAVE_SIGACTION
-static RETSIGTYPE signalhandler(int sig)
-#endif // HAVE_SIGACTION
-{
+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;
- XSelectInput(_display, _root, None);
- delete _xatom;
- XCloseDisplay(_display);
return 0;
}
#include <X11/Xlib.h>
}
+#include <string>
+#include <map>
+
+#include "../../src/BaseDisplay.hh"
+
class XAtom;
+class screen;
+class XWindow;
+
+class epist : public BaseDisplay {
+private:
+ std::string _rc_file;
+ XAtom *_xatom;
+ char **_argv;
+
+ typedef std::vector<screen *> ScreenList;
+ ScreenList _screens;
+
+ typedef std::map<Window, XWindow*> WindowLookup;
+ typedef WindowLookup::value_type WindowLookupPair;
+ WindowLookup _windows;
+
+ virtual void process_event(XEvent *e);
+ virtual bool handleSignal(int sig);
+
+public:
+ epist(char **argv, char *display_name, char *rc_file);
+ virtual ~epist();
+
+ inline XAtom *xatom() { return _xatom; }
-extern bool _shutdown;
-extern Display *_display;
-extern Window _root;
-extern XAtom *_xatom;
+ void addWindow(XWindow *window);
+ void removeWindow(XWindow *window);
+ XWindow *findWindow(Window window) const;
+};
#endif // __epist_hh
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// main.cc for Epistory - 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
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef HAVE_CONFIG_H
+# include "../../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h>
+# include <unistd.h>
+#endif // HAVE_UNISTD_H
+
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif // HAVE_STDIO_H
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif // HAVE_STDLIB_H
+}
+
+#include <iostream>
+#include <string>
+
+using std::cout;
+using std::endl;
+using std::string;
+
+#include "epist.hh"
+#include "../../src/i18n.hh"
+
+I18n i18n;
+
+int main(int argc, char **argv) {
+ i18n.openCatalog("openbox.cat");
+
+ // parse the command line
+ char *display_name = 0;
+ char *rc_file = 0;
+
+ for (int i = 1; i < argc; ++i) {
+ if (string(argv[i]) == "-display") {
+ if (++i >= argc) {
+ fprintf(stderr, i18n(mainSet, mainDISPLAYRequiresArg,
+ "error: '-display' requires an argument\n"));
+ exit(1);
+ }
+ display_name = argv[i];
+ } else if (string(argv[i]) == "-rc") {
+ if (++i >= argc) {
+ fprintf(stderr, i18n(mainSet, mainRCRequiresArg,
+ "error: '-rc' requires an argument\n"));
+ exit(1);
+ }
+ rc_file = argv[i];
+ }
+ }
+
+ epist ep(argv, display_name, rc_file);
+ ep.eventLoop();
+ return 0;
+}
-// -*- mode: C++; indent-tabs-mode: nil; -*-
-// process.cc for Epistory - 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
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#include "process.hh"
-#include "epist.hh"
-#include "window.hh"
-
-#ifdef HAVE_CONFIG_H
-# include "../../config.h"
-#endif // HAVE_CONFIG_H
-
-#include <iostream>
-
-using std::cout;
-using std::endl;
-using std::hex;
-using std::dec;
-
-#include "../../src/XAtom.hh"
-
-WindowList _clients;
-WindowList::iterator _active = _clients.end();
-
-
-XWindow *findWindow(const XEvent &e) {
- WindowList::iterator it, end = _clients.end();
- for (it = _clients.begin(); it != end; ++it)
- if (**it == e.xany.window)
- break;
- if(it == end)
- return 0;
- return *it;
-}
-
-
-void processEvent(const XEvent &e) {
- XWindow *window = 0;
- if (e.xany.window != _root) {
- window = findWindow(e); // find the window
- assert(window); // we caught an event for a window we don't know about!?
- }
-
- switch (e.type) {
- case PropertyNotify:
- if (e.xany.window == _root) {
- // root window
- if (e.xproperty.atom == _xatom->getAtom(XAtom::net_active_window))
- updateActiveWindow();
- if (e.xproperty.atom == _xatom->getAtom(XAtom::net_client_list)) {
- // catch any window unmaps first
- XEvent ev;
- if (XCheckTypedWindowEvent(_display, e.xany.window,
- DestroyNotify, &ev) ||
- XCheckTypedWindowEvent(_display, e.xany.window,
- UnmapNotify, &ev)) {
- processEvent(ev);
- }
-
- updateClientList();
- }
- } else {
- // a client window
- if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state))
- window->updateState();
- else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop))
- window->updateDesktop();
- else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_name) ||
- e.xproperty.atom == _xatom->getAtom(XAtom::wm_name))
- window->updateTitle();
- else if (e.xproperty.atom == _xatom->getAtom(XAtom::wm_class))
- window->updateClass();
- }
- break;
- case DestroyNotify:
- case UnmapNotify:
- window->setUnmapped(true);
- break;
- }
-}
-
-
-// do we want to add this window to our list?
-bool doAddWindow(Window window) {
- Atom type;
- if (! _xatom->getValue(window, XAtom::net_wm_window_type, XAtom::atom,
- type))
- return True;
-
- if (type == _xatom->getAtom(XAtom::net_wm_window_type_dock) ||
- type == _xatom->getAtom(XAtom::net_wm_window_type_menu))
- return False;
-
- return True;
-}
-
-
-void updateClientList() {
- WindowList::iterator insert_point = _active;
- if (insert_point != _clients.end())
- ++insert_point; // get to the item client the focused client
-
- // get the client list from the root window
- Window *rootclients = 0;
- unsigned long num = (unsigned) -1;
- if (! _xatom->getValue(_root, XAtom::net_client_list, XAtom::window, num,
- &rootclients)) {
- while (! _clients.empty()) {
- delete _clients.front();
- _clients.erase(_clients.begin());
- }
- if (rootclients) delete [] rootclients;
- return;
- }
-
- WindowList::iterator it, end = _clients.end();
- unsigned long i;
-
- // insert new clients after the active window
- for (i = 0; i < num; ++i) {
- for (it = _clients.begin(); it != end; ++it)
- if (**it == rootclients[i])
- break;
- if (it == end) { // didn't already exist
- if (doAddWindow(rootclients[i])) {
- cout << "Added window: 0x" << hex << rootclients[i] << dec << endl;
- _clients.insert(insert_point, new XWindow(rootclients[i]));
- }
- }
- }
-
- // remove clients that no longer exist
- for (it = _clients.begin(); it != end;) {
- WindowList::iterator it2 = it++;
- for (i = 0; i < num; ++i)
- if (**it2 == rootclients[i])
- break;
- if (i == num) { // no longer exists
- cout << "Removed window: 0x" << hex << (*it2)->window() << dec << endl;
- delete *it2;
- _clients.erase(it2);
- }
- }
-
- if (rootclients) delete [] rootclients;
-}
-
-
-void updateActiveWindow() {
- Window a = None;
- _xatom->getValue(_root, XAtom::net_active_window, XAtom::window, a);
-
- WindowList::iterator it, end = _clients.end();
- for (it = _clients.begin(); it != end; ++it) {
- if (**it == a)
- break;
- }
- _active = it;
-
- cout << "Active window is now: ";
- if (_active == _clients.end()) cout << "None\n";
- else cout << "0x" << hex << (*_active)->window() << dec << endl;
-}
-// -*- mode: C++; indent-tabs-mode: nil; -*-
-// process.hh for Epistory - 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
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef __process_hh
-#define __process_hh
-
-extern "C" {
-#include "X11/Xlib.h"
-}
-
-void processEvent(const XEvent &e);
-void updateClientList();
-void updateActiveWindow();
-
-#endif // __process_hh
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// screen.cc for Epistory - 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
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef HAVE_CONFIG_H
+# include "../../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h>
+# include <unistd.h>
+#endif // HAVE_UNISTD_H
+}
+
+#include <iostream>
+#include <string>
+
+using std::cout;
+using std::endl;
+using std::hex;
+using std::dec;
+using std::string;
+
+#include "../../src/XAtom.hh"
+#include "screen.hh"
+#include "epist.hh"
+
+
+screen::screen(epist *epist, int number) {
+ _epist = epist;
+ _xatom = _epist->xatom();
+ _number = number;
+ _active = _clients.end();
+ _root = RootWindow(_epist->getXDisplay(), _number);
+
+ // find a window manager supporting NETWM, waiting for it to load if we must
+ int count = 20; // try for 20 seconds
+ _managed = false;
+ while (! (_epist->doShutdown() || _managed || count <= 0)) {
+ if (! (_managed = findSupportingWM()))
+ usleep(1000);
+ --count;
+ }
+ if (_managed)
+ cout << "Found compatible window manager '" << _wm_name << "' for screen "
+ << _number << ".\n";
+ else {
+ cout << "Unable to find a compatible window manager for screen " <<
+ _number << ".\n";
+ return;
+ }
+
+ XSelectInput(_epist->getXDisplay(), _root, PropertyChangeMask);
+
+ updateClientList();
+ updateActiveWindow();
+}
+
+
+screen::~screen() {
+ if (_managed)
+ XSelectInput(_epist->getXDisplay(), _root, None);
+}
+
+
+bool screen::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);
+ _wm_name = title;
+ return true;
+}
+
+
+XWindow *screen::findWindow(const XEvent &e) const {
+ assert(_managed);
+
+ WindowList::const_iterator it, end = _clients.end();
+ for (it = _clients.begin(); it != end; ++it)
+ if (**it == e.xany.window)
+ break;
+ if(it == end)
+ return 0;
+ return *it;
+}
+
+
+void screen::processEvent(const XEvent &e) {
+ assert(_managed);
+ assert(e.xany.window == _root);
+
+ XWindow *window = 0;
+ if (e.xany.window != _root) {
+ window = findWindow(e); // find the window
+ assert(window); // we caught an event for a window we don't know about!?
+ }
+
+ switch (e.type) {
+ case PropertyNotify:
+ // root window
+ if (e.xproperty.atom == _xatom->getAtom(XAtom::net_active_window))
+ updateActiveWindow();
+ if (e.xproperty.atom == _xatom->getAtom(XAtom::net_client_list)) {
+ // catch any window unmaps first
+ XEvent ev;
+ if (XCheckTypedWindowEvent(_epist->getXDisplay(), e.xany.window,
+ DestroyNotify, &ev) ||
+ XCheckTypedWindowEvent(_epist->getXDisplay(), e.xany.window,
+ UnmapNotify, &ev)) {
+ processEvent(ev);
+ }
+
+ updateClientList();
+ }
+ break;
+ case KeyPress:
+ break;
+ }
+}
+
+
+// do we want to add this window to our list?
+bool screen::doAddWindow(Window window) const {
+ assert(_managed);
+
+ Atom type;
+ if (! _xatom->getValue(window, XAtom::net_wm_window_type, XAtom::atom,
+ type))
+ return True;
+
+ if (type == _xatom->getAtom(XAtom::net_wm_window_type_dock) ||
+ type == _xatom->getAtom(XAtom::net_wm_window_type_menu))
+ return False;
+
+ return True;
+}
+
+
+void screen::updateClientList() {
+ assert(_managed);
+
+ WindowList::iterator insert_point = _active;
+ if (insert_point != _clients.end())
+ ++insert_point; // get to the item client the focused client
+
+ // get the client list from the root window
+ Window *rootclients = 0;
+ unsigned long num = (unsigned) -1;
+ if (! _xatom->getValue(_root, XAtom::net_client_list, XAtom::window, num,
+ &rootclients)) {
+ while (! _clients.empty()) {
+ delete _clients.front();
+ _clients.erase(_clients.begin());
+ }
+ if (rootclients) delete [] rootclients;
+ return;
+ }
+
+ WindowList::iterator it, end = _clients.end();
+ unsigned long i;
+
+ // insert new clients after the active window
+ for (i = 0; i < num; ++i) {
+ for (it = _clients.begin(); it != end; ++it)
+ if (**it == rootclients[i])
+ break;
+ if (it == end) { // didn't already exist
+ if (doAddWindow(rootclients[i])) {
+ cout << "Added window: 0x" << hex << rootclients[i] << dec << endl;
+ _clients.insert(insert_point, new XWindow(_epist, rootclients[i]));
+ }
+ }
+ }
+
+ // remove clients that no longer exist
+ for (it = _clients.begin(); it != end;) {
+ WindowList::iterator it2 = it++;
+ for (i = 0; i < num; ++i)
+ if (**it2 == rootclients[i])
+ break;
+ if (i == num) { // no longer exists
+ cout << "Removed window: 0x" << hex << (*it2)->window() << dec << endl;
+ delete *it2;
+ _clients.erase(it2);
+ }
+ }
+
+ if (rootclients) delete [] rootclients;
+}
+
+
+void screen::updateActiveWindow() {
+ assert(_managed);
+
+ Window a = None;
+ _xatom->getValue(_root, XAtom::net_active_window, XAtom::window, a);
+
+ WindowList::iterator it, end = _clients.end();
+ for (it = _clients.begin(); it != end; ++it) {
+ if (**it == a)
+ break;
+ }
+ _active = it;
+
+ cout << "Active window is now: ";
+ if (_active == _clients.end()) cout << "None\n";
+ else cout << "0x" << hex << (*_active)->window() << dec << endl;
+}
+
+/*
+ * use this when execing a command to have it on the right screen
+ 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()");
+ }
+ */
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// screen.hh for Epistory - 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
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef __screen_hh
+#define __screen_hh
+
+extern "C" {
+#include "X11/Xlib.h"
+}
+
+#include <vector>
+
+#include "window.hh"
+
+class epist;
+class screen;
+class XAtom;
+
+class screen {
+ epist *_epist;
+ XAtom *_xatom;
+ int _number;
+ Window _root;
+
+ std::string _wm_name;
+
+ WindowList _clients;
+ WindowList::iterator _active;
+
+ bool _managed;
+
+ XWindow *findWindow(const XEvent &e) const;
+ void updateClientList();
+ void updateActiveWindow();
+ bool doAddWindow(Window window) const;
+ bool findSupportingWM();
+
+public:
+ screen(epist *epist, int number);
+ virtual ~screen();
+
+ inline Window rootWindow() const { return _root; }
+ inline bool managed() const { return _managed; }
+
+ void processEvent(const XEvent &e);
+};
+
+#endif // __screen_hh
+
# include "../../config.h"
#endif // HAVE_CONFIG_H
-#include "window.hh"
-#include "epist.hh"
-#include "../../src/XAtom.hh"
-
#include <iostream>
using std::cout;
using std::hex;
using std::dec;
-XWindow::XWindow(Window window) : _window(window) {
+#include "window.hh"
+#include "epist.hh"
+#include "../../src/XAtom.hh"
+
+XWindow::XWindow(epist *epist, Window window)
+ : _epist(epist), _xatom(epist->xatom()), _window(window) {
+
_unmapped = false;
- XSelectInput(_display, _window, PropertyChangeMask | StructureNotifyMask);
+ XSelectInput(_epist->getXDisplay(), _window,
+ PropertyChangeMask | StructureNotifyMask);
updateState();
updateDesktop();
updateTitle();
updateClass();
+
+ _epist->addWindow(this);
}
XWindow::~XWindow() {
if (! _unmapped)
- XSelectInput(_display, _window, None);
+ XSelectInput(_epist->getXDisplay(), _window, None);
+ _epist->removeWindow(this);
}
if (num > 0) _app_name = v[0];
if (num > 1) _app_class = v[1];
}
+
+
+void XWindow::processEvent(const XEvent &e) {
+ assert(e.xany.window == _window);
+
+ switch (e.type) {
+ case PropertyNotify:
+ // a client window
+ if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state))
+ updateState();
+ else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop))
+ updateDesktop();
+ else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_name) ||
+ e.xproperty.atom == _xatom->getAtom(XAtom::wm_name))
+ updateTitle();
+ else if (e.xproperty.atom == _xatom->getAtom(XAtom::wm_class))
+ updateClass();
+ break;
+ case DestroyNotify:
+ case UnmapNotify:
+ _unmapped = true;
+ break;
+ }
+}
#include <list>
#include <string>
+class epist;
class XWindow;
+class XAtom;
typedef std::list<XWindow *> WindowList;
class XWindow {
private:
+ epist *_epist;
+ XAtom *_xatom;
Window _window;
unsigned int _desktop;
bool _unmapped;
+ void updateState();
+ void updateDesktop();
+ void updateTitle();
+ void updateClass();
+
public:
- XWindow(Window window);
+ XWindow(epist *epist, Window window);
virtual ~XWindow();
inline Window window() const { return _window; }
inline bool maxVert() const { return _max_vert; }
inline bool maxHorz() const { return _max_horz; }
- inline void setUnmapped(bool u) { _unmapped = u; }
-
- void updateState();
- void updateDesktop();
- void updateTitle();
- void updateClass();
+ void processEvent(const XEvent &e);
bool operator == (const XWindow &w) const { return w._window == _window; }
bool operator == (const Window &w) const { return w == _window; }