epist now based on the BaseDisplay.

has the ability to be multiscreen!
This commit is contained in:
Dana Jansens 2002-07-12 16:29:59 +00:00
parent 89d09297f0
commit 24a1e215d1
10 changed files with 558 additions and 350 deletions

View file

@ -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 @@ distclean-local:
# 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

View file

@ -30,10 +30,6 @@ extern "C" {
# 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 @@ extern "C" {
# 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) {
_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);
}
}
#ifdef HAVE_SIGACTION
static void signalhandler(int sig)
#else // HAVE_SIGACTION
static RETSIGTYPE signalhandler(int sig)
#endif // HAVE_SIGACTION
{
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);
}
_shutdown = true;
return false; // this should be unreachable
#ifndef HAVE_SIGACTION
// assume broken, braindead sysv signal semantics
signal(sig, (RETSIGTYPE (*)(int)) signalhandler);
#endif // HAVE_SIGACTION
case SIGTERM:
case SIGINT:
case SIGPIPE:
shutdown();
return true;
}
return false;
}
void parseCommandLine(int argc, char **argv) {
_argv = argv;
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()");
}
}
}
}
void epist::process_event(XEvent *e) {
Window root;
if (e->xany.type == KeyPress)
root = e->xkey.root;
else
root = e->xany.window;
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;
}
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);
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);
ScreenList::const_iterator it, end = _screens.end();
for (it = _screens.begin(); it != end; ++it) {
if ((*it)->rootWindow() == root) {
(*it)->processEvent(*e);
return;
}
}
XSelectInput(_display, _root, None);
delete _xatom;
XCloseDisplay(_display);
// wasnt a root window, try for client windows
XWindow *w = findWindow(e->xany.window);
if (w) w->processEvent(*e);
}
void epist::addWindow(XWindow *window) {
_windows.insert(WindowLookupPair(window->window(), window));
}
void epist::removeWindow(XWindow *window) {
_windows.erase(window->window());
}
XWindow *epist::findWindow(Window window) const {
WindowLookup::const_iterator it = _windows.find(window);
if (it != _windows.end())
return it->second;
return 0;
}

View file

@ -27,11 +27,40 @@ extern "C" {
#include <X11/Xlib.h>
}
class XAtom;
#include <string>
#include <map>
extern bool _shutdown;
extern Display *_display;
extern Window _root;
extern XAtom *_xatom;
#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; }
void addWindow(XWindow *window);
void removeWindow(XWindow *window);
XWindow *findWindow(Window window) const;
};
#endif // __epist_hh

82
util/epist/main.cc Normal file
View file

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

View file

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

View file

@ -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

240
util/epist/screen.cc Normal file
View file

@ -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()");
}
*/

68
util/epist/screen.hh Normal file
View file

@ -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

View file

@ -24,10 +24,6 @@
# 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 @@ void XWindow::updateClass() {
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;
}
}

View file

@ -30,12 +30,16 @@ extern "C" {
#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;
@ -51,8 +55,13 @@ private:
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 @@ public:
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; }