all repos — openbox @ 24a1e215d1f8d2ff1674847278a15336d4b671b6

openbox fork - make it a bit more like ryudo

epist now based on the BaseDisplay.
has the ability to be multiscreen!
Dana Jansens danakj@orodu.net
commit

24a1e215d1f8d2ff1674847278a15336d4b671b6

parent

89d09297f0ef3d2db648a756f62a57bf2be317df

M util/epist/Makefile.amutil/epist/Makefile.am

@@ -4,8 +4,11 @@ CPPFLAGS= @CPPFLAGS@ @DEBUG@

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

@@ -14,5 +17,12 @@ rm -f *\~ .\#*

# 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
M util/epist/epist.ccutil/epist/epist.cc

@@ -30,10 +30,6 @@ # 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

@@ -42,9 +38,9 @@ #ifdef HAVE_SIGNAL_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>

@@ -56,129 +52,93 @@ 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()); + + 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; +} + + +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 +void epist::removeWindow(XWindow *window) { + _windows.erase(window->window()); +} - 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); - - 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; }
M util/epist/epist.hhutil/epist/epist.hh

@@ -27,11 +27,40 @@ extern "C" {

#include <X11/Xlib.h> } +#include <string> +#include <map> + +#include "../../src/BaseDisplay.hh" + class XAtom; +class screen; +class XWindow; -extern bool _shutdown; -extern Display *_display; -extern Window _root; -extern XAtom *_xatom; +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; } + + void addWindow(XWindow *window); + void removeWindow(XWindow *window); + XWindow *findWindow(Window window) const; +}; #endif // __epist_hh
A util/epist/main.cc

@@ -0,0 +1,82 @@

+// -*- 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; +}
M util/epist/process.ccutil/epist/process.cc

@@ -1,181 +0,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; -}
M util/epist/process.hhutil/epist/process.hh

@@ -1,34 +0,0 @@

-// -*- 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
A util/epist/screen.cc

@@ -0,0 +1,240 @@

+// -*- 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()"); + } + */
A util/epist/screen.hh

@@ -0,0 +1,68 @@

+// -*- 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 +
M util/epist/window.ccutil/epist/window.cc

@@ -24,10 +24,6 @@ #ifdef HAVE_CONFIG_H

# include "../../config.h" #endif // HAVE_CONFIG_H -#include "window.hh" -#include "epist.hh" -#include "../../src/XAtom.hh" - #include <iostream> using std::cout;

@@ -35,20 +31,30 @@ using std::endl;

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); }

@@ -110,3 +116,27 @@

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; + } +}
M util/epist/window.hhutil/epist/window.hh

@@ -30,12 +30,16 @@

#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;

@@ -50,9 +54,14 @@ bool _max_vert;

bool _max_horz; 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; }

@@ -67,12 +76,7 @@ inline bool iconic() const { return _iconic; }

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; }