epist now based on the BaseDisplay.
has the ability to be multiscreen!
This commit is contained in:
parent
89d09297f0
commit
24a1e215d1
10 changed files with 558 additions and 350 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
82
util/epist/main.cc
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
240
util/epist/screen.cc
Normal 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
68
util/epist/screen.hh
Normal 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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in a new issue